Initial cursor implementation
This commit is contained in:
parent
6e19d50a5a
commit
8b1f403c87
@ -247,6 +247,41 @@ void Graphics::Pixel(int x, int y, int paletteIndex) {
|
||||
m_virtualScreenColorBuffer[y * m_screenWidth + x] = paletteIndex;
|
||||
}
|
||||
|
||||
void Graphics::Line(int x0, int y0, int x1, int y1, int paletteIndex) {
|
||||
int dx = x1 - x0; // Change in x
|
||||
int dy = y1 - y0; // Change in y
|
||||
int abs_dx = std::abs(dx);
|
||||
int abs_dy = std::abs(dy);
|
||||
|
||||
int sx = (dx > 0) ? 1 : -1; // Step direction in x
|
||||
int sy = (dy > 0) ? 1 : -1; // Step direction in y
|
||||
|
||||
// Choose the primary axis for iteration
|
||||
if (abs_dx > abs_dy) {
|
||||
int err = abs_dx / 2; // Error value
|
||||
for (int i = 0; i <= abs_dx; i++) {
|
||||
Pixel(x0, y0, paletteIndex); // Plot the pixel
|
||||
err -= abs_dy; // Update error term
|
||||
if (err < 0) {
|
||||
y0 += sy; // Move in y direction
|
||||
err += abs_dx; // Update error term
|
||||
}
|
||||
x0 += sx; // Always move in x direction
|
||||
}
|
||||
} else {
|
||||
int err = abs_dy / 2; // Error value
|
||||
for (int i = 0; i <= abs_dy; i++) {
|
||||
Pixel(x0, y0, paletteIndex); // Plot the pixel
|
||||
err -= abs_dx; // Update error term
|
||||
if (err < 0) {
|
||||
x0 += sx; // Move in x direction
|
||||
err += abs_dy; // Update error term
|
||||
}
|
||||
y0 += sy; // Always move in y direction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::Circle(int x, int y, int radius, int paletteIndex) {
|
||||
Ellipse(x, y, radius, radius, paletteIndex);
|
||||
}
|
||||
|
||||
@ -70,6 +70,7 @@ public:
|
||||
|
||||
void Clear(int paletteIndex);
|
||||
void Pixel(int x, int y, int paletteIndex);
|
||||
void Line(int x0, int y0, int x1, int y1, int paletteIndex);
|
||||
void Circle(int x, int y, int radius, int paletteIndex);
|
||||
void Ellipse(int x, int y, int width, int height, int paletteIndex);
|
||||
void EllipseBorder(int x, int y, int width, int height, int paletteIndex);
|
||||
|
||||
@ -45,6 +45,19 @@ void Pycron::StartGameLoop() {
|
||||
}
|
||||
m_graphics->updateVMVars(m_vm);
|
||||
m_graphics->draw(this->m_stateManager);
|
||||
|
||||
char c = (char)GetCharPressed();
|
||||
|
||||
while(c > 0){
|
||||
m_stateManager->OnCharPressed(c);
|
||||
c = (char)GetCharPressed();
|
||||
}
|
||||
|
||||
for (int key = KeyboardKey::KEY_BACK; key < KeyboardKey::KEY_KP_EQUAL; ++key) {
|
||||
if(IsKeyPressed(key) || IsKeyPressedRepeat(key)){
|
||||
m_stateManager->OnKeyPressed(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -67,3 +67,11 @@ void StateManager::Draw() {
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager::OnKeyPressed(int key) {
|
||||
m_currentState->OnKeyPressed(key);
|
||||
}
|
||||
|
||||
void StateManager::OnCharPressed(char c) {
|
||||
m_currentState->OnCharPressed(c);
|
||||
}
|
||||
|
||||
|
||||
@ -31,6 +31,9 @@ public:
|
||||
|
||||
void ChangeState(StateManager::StateType state);
|
||||
|
||||
void OnKeyPressed(int key);
|
||||
void OnCharPressed(char c);
|
||||
|
||||
void RequestLoadGame();
|
||||
void RequestRunGame();
|
||||
void RequestStopGame();
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "EditorState.h"
|
||||
#include "../../Graphics/PycronImage.h"
|
||||
#include "../../Pycron.h"
|
||||
#include <raylib.h>
|
||||
|
||||
|
||||
EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphics(graphics){
|
||||
@ -15,14 +16,15 @@ EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphic
|
||||
|
||||
Token a(TokenType::Keyword, "Test");
|
||||
|
||||
std::string randomSource = Pycron::loadFileToString("../python/syntaxTest.py");
|
||||
std::string randomSource = Pycron::loadFileToString("../python/main.py");
|
||||
|
||||
m_baseBackgroundColor = 56;
|
||||
m_baseTextColor = 63;
|
||||
m_shadowColor = 28;
|
||||
m_baseTextColor = 42;
|
||||
m_lineNumberBackgroundColor = 57;
|
||||
m_lineNumberTextColor = 6;
|
||||
m_unknownTextColor = 4;
|
||||
m_identifierTextColor = 43;
|
||||
m_identifierTextColor = 63;
|
||||
m_keywordTextColor = 31;
|
||||
m_builtinTextColor = 23;
|
||||
m_numericalLiteralTextColor = 32;
|
||||
@ -31,23 +33,30 @@ EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphic
|
||||
m_operatorTextColor = 45;
|
||||
m_commentTextColor = 60;
|
||||
|
||||
|
||||
m_topLetterSpacing = 0;
|
||||
m_bottomLetterSpacing = 1;
|
||||
m_leftLetterSpacing = 0;
|
||||
m_rightLetterSpacing = 1;
|
||||
|
||||
m_cursorX = 0;
|
||||
m_cursorY = 0;
|
||||
|
||||
m_cursorBlinkTimer = 0;
|
||||
m_cursorBlinkInterval = 0.5;
|
||||
|
||||
m_charWidth = m_leftLetterSpacing + m_graphics->GetCurrentFontWidth() + m_rightLetterSpacing; // Final size of char with spacing. If the literal width of the font is n, the final width is n + spacing.
|
||||
m_charHeight = m_topLetterSpacing + m_graphics->GetCurrentFontHeight() + m_bottomLetterSpacing;
|
||||
|
||||
m_textWidth = (int)(m_graphics->m_screenWidth / m_charWidth);
|
||||
m_textHeight = (int)(m_graphics->m_screenHeight / m_charHeight);
|
||||
m_width = (int)(m_graphics->m_screenWidth / m_charWidth);
|
||||
m_height = (int)(m_graphics->m_screenHeight / m_charHeight);
|
||||
|
||||
m_characterBuffer = std::vector<char>(m_textWidth * m_textHeight);
|
||||
m_foregroundIndexBuffer = std::vector<uint8_t>(m_textWidth * m_textHeight);
|
||||
m_backgroundIndexBuffer = std::vector<uint8_t>(m_textWidth * m_textHeight);
|
||||
m_characterBuffer = std::vector<char>(m_width * m_height);
|
||||
m_foregroundIndexBuffer = std::vector<uint8_t>(m_width * m_height);
|
||||
m_backgroundIndexBuffer = std::vector<uint8_t>(m_width * m_height);
|
||||
|
||||
m_dirtyFlags = std::vector<bool>(m_textHeight);
|
||||
m_dirtyFlags = std::vector<bool>(m_height);
|
||||
|
||||
m_drawShadows = true;
|
||||
|
||||
Clear();
|
||||
|
||||
@ -62,28 +71,20 @@ EditorState::~EditorState() {
|
||||
}
|
||||
|
||||
void EditorState::Draw() {
|
||||
m_graphics->Clear(0);
|
||||
|
||||
int bg = 28;
|
||||
|
||||
for (int i = 0; i < m_characterBuffer.size(); ++i) {
|
||||
int x = (i % m_textWidth) * m_charWidth;
|
||||
int y = (i / m_textWidth) * m_charHeight;
|
||||
m_graphics->Rect(x, y, m_charWidth, m_charHeight, m_backgroundIndexBuffer[i]);
|
||||
m_graphics->Char(m_characterBuffer[i], x + m_leftLetterSpacing + 1, y + m_topLetterSpacing + 1, bg);
|
||||
m_graphics->Char(m_characterBuffer[i], x + m_leftLetterSpacing, y + m_topLetterSpacing, m_foregroundIndexBuffer[i]);
|
||||
}
|
||||
|
||||
// Set text and color buffers if needed
|
||||
if(m_dirty){
|
||||
Clear();
|
||||
m_dirty = false;
|
||||
for (int i = 0; i < m_text.size(); ++i) {
|
||||
// Line numbers TODO: maybe not have this as part of the buffer, instead as a custom bar. (Allows for more custom functionality such as bookmarks)
|
||||
// std::string lineNumber = std::to_string(std::abs(m_cursorY - i));
|
||||
// if(i == m_cursorY) lineNumber = std::to_string(m_cursorY);
|
||||
std::string lineNumber = std::to_string(i);
|
||||
int size = 2;
|
||||
int diff = size - (int)lineNumber.size();
|
||||
if(diff > 0) lineNumber = std::string(diff, ' ') + lineNumber;
|
||||
Text(lineNumber, 0, i, m_lineNumberTextColor, m_lineNumberBackgroundColor);
|
||||
Text(lineNumber, 0, i, i == m_cursorY ? m_lineNumberTextColor : m_commentTextColor, m_lineNumberBackgroundColor);
|
||||
|
||||
// Text handling
|
||||
auto tokens = m_pythonTokenizer->tokenizeLine(m_text[i]);
|
||||
@ -117,6 +118,37 @@ void EditorState::Draw() {
|
||||
}
|
||||
}
|
||||
|
||||
m_graphics->Clear(0);
|
||||
|
||||
// draw text with info from color buffers
|
||||
for (int i = 0; i < m_characterBuffer.size(); ++i) {
|
||||
int x = (i % m_width) * m_charWidth;
|
||||
int y = (i / m_width) * m_charHeight;
|
||||
m_graphics->Rect(x, y, m_charWidth, m_charHeight, m_backgroundIndexBuffer[i]);
|
||||
if(m_drawShadows) m_graphics->Char(m_characterBuffer[i], x + m_leftLetterSpacing + 1, y + m_topLetterSpacing + 1, m_shadowColor);
|
||||
m_graphics->Char(m_characterBuffer[i], x + m_leftLetterSpacing, y + m_topLetterSpacing, m_foregroundIndexBuffer[i]);
|
||||
}
|
||||
|
||||
|
||||
if(m_cursorVisible) {
|
||||
int x = (m_cursorX + 2) * m_charWidth;
|
||||
int y = m_cursorY * m_charHeight;
|
||||
int index = m_cursorY * m_width + (m_cursorX + 2);
|
||||
|
||||
if(m_drawShadows) m_graphics->Rect(x, y, m_charWidth + 1, m_charHeight + 1, m_shadowColor);
|
||||
m_graphics->Rect(x - 1, y - 1, m_charWidth + 1, m_charHeight + 1, m_foregroundIndexBuffer[index]);
|
||||
// m_graphics->Line(x - 1, y, x - 1, y + m_charHeight - 1, 63);
|
||||
std::string s(1, m_characterBuffer[index]);
|
||||
m_graphics->Text(s, x, y, m_backgroundIndexBuffer[index]);
|
||||
}
|
||||
|
||||
// Cursor blink
|
||||
m_cursorBlinkTimer += GetFrameTime();
|
||||
if(m_cursorBlinkTimer > m_cursorBlinkInterval){
|
||||
m_cursorVisible = !m_cursorVisible;
|
||||
m_cursorBlinkTimer = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EditorState::OnEnter() {
|
||||
@ -128,11 +160,33 @@ void EditorState::OnExit() {
|
||||
}
|
||||
|
||||
void EditorState::OnKeyPressed(int key) {
|
||||
std::cout << key << ". \n";
|
||||
if(key == KEY_LEFT && m_cursorX > 0){
|
||||
m_cursorX--;
|
||||
}
|
||||
if(key == KEY_RIGHT && m_cursorX < m_width - 1 - 2){
|
||||
m_cursorX++;
|
||||
}
|
||||
if(key == KEY_UP && m_cursorY > 0){
|
||||
m_cursorY--;
|
||||
}
|
||||
if(key == KEY_DOWN && m_cursorY < m_height - 1){
|
||||
m_cursorY++;
|
||||
}
|
||||
|
||||
m_cursorVisible = true;
|
||||
m_cursorBlinkTimer = 0;
|
||||
|
||||
m_dirty = true;
|
||||
|
||||
if(key == KEY_GRAVE) m_drawShadows = !m_drawShadows;
|
||||
}
|
||||
|
||||
void EditorState::OnCharPressed(char character){
|
||||
|
||||
}
|
||||
|
||||
void EditorState::Clear() {
|
||||
for (int i = 0; i < m_textWidth * m_textHeight; ++i) {
|
||||
for (int i = 0; i < m_width * m_height; ++i) {
|
||||
m_characterBuffer[i] = ' ';
|
||||
m_foregroundIndexBuffer[i] = m_baseTextColor;
|
||||
m_backgroundIndexBuffer[i] = m_baseBackgroundColor;
|
||||
@ -143,11 +197,11 @@ void EditorState::Text(const std::string &text, int x, int y, int fg, int bg) {
|
||||
for (int i = 0; i < text.size(); ++i) {
|
||||
int charX = x + i;
|
||||
int charY = y;
|
||||
if(charX < 0 || charY < 0 || charX >= m_textWidth || charY >= m_textHeight){
|
||||
if(charX < 0 || charY < 0 || charX >= m_width || charY >= m_height){
|
||||
return;
|
||||
}
|
||||
char c = text[i];
|
||||
int index = y * m_textWidth + (x + i);
|
||||
int index = y * m_width + (x + i);
|
||||
m_characterBuffer[index] = c;
|
||||
m_backgroundIndexBuffer[index] = bg;
|
||||
m_foregroundIndexBuffer[index] = fg;
|
||||
@ -156,9 +210,6 @@ void EditorState::Text(const std::string &text, int x, int y, int fg, int bg) {
|
||||
}
|
||||
}
|
||||
|
||||
void EditorState::OnCharPressed(char character) {
|
||||
|
||||
}
|
||||
|
||||
void EditorState::LoadStringToBuffer(const std::string &text) {
|
||||
m_text.clear();
|
||||
|
||||
@ -24,8 +24,12 @@ private:
|
||||
Graphics* m_graphics;
|
||||
PythonTokenizer* m_pythonTokenizer;
|
||||
|
||||
// Size of the character in pixels
|
||||
uint8_t m_charWidth, m_charHeight;
|
||||
uint8_t m_textWidth, m_textHeight;
|
||||
|
||||
// Size of the editor in characters
|
||||
uint8_t m_width, m_height;
|
||||
|
||||
uint8_t m_topLetterSpacing, m_bottomLetterSpacing, m_leftLetterSpacing, m_rightLetterSpacing;
|
||||
// Text Buffer
|
||||
std::vector<char> m_characterBuffer;
|
||||
@ -38,6 +42,7 @@ private:
|
||||
|
||||
// Theming
|
||||
uint8_t m_baseBackgroundColor;
|
||||
uint8_t m_shadowColor;
|
||||
uint8_t m_baseTextColor;
|
||||
uint8_t m_lineNumberBackgroundColor;
|
||||
uint8_t m_lineNumberTextColor;
|
||||
@ -51,9 +56,16 @@ private:
|
||||
uint8_t m_operatorTextColor;
|
||||
uint8_t m_commentTextColor;
|
||||
|
||||
int m_cursorX;
|
||||
int m_cursorY;
|
||||
bool m_cursorVisible;
|
||||
float_t m_cursorBlinkTimer;
|
||||
float_t m_cursorBlinkInterval;
|
||||
|
||||
bool m_dirty;
|
||||
|
||||
bool m_drawShadows;
|
||||
|
||||
void Clear();
|
||||
void Text(const std::string &text, int x, int y, int fg = 0, int bg = 63);
|
||||
|
||||
|
||||
@ -117,7 +117,7 @@ bool PythonTokenizer::isPunctuation(char c) {
|
||||
}
|
||||
|
||||
bool PythonTokenizer::isOperator(char c) {
|
||||
return c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '<' || c == '>' || c == '!';
|
||||
return c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '<' || c == '>' || c == '!' || c == ':';
|
||||
}
|
||||
|
||||
std::string PythonTokenizer::readNumericLiteral(const std::string &line) {
|
||||
@ -165,8 +165,6 @@ std::string PythonTokenizer::readStringLiteral(const std::string &line) {
|
||||
m_currentPos++;
|
||||
while (m_currentPos < line.length() && line[m_currentPos] != '"') {
|
||||
m_currentPos++;
|
||||
std::cout << m_currentPos;
|
||||
|
||||
}
|
||||
|
||||
if(line[m_currentPos] == '"') m_currentPos++;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user