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;
|
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) {
|
void Graphics::Circle(int x, int y, int radius, int paletteIndex) {
|
||||||
Ellipse(x, y, radius, radius, paletteIndex);
|
Ellipse(x, y, radius, radius, paletteIndex);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,7 @@ public:
|
|||||||
|
|
||||||
void Clear(int paletteIndex);
|
void Clear(int paletteIndex);
|
||||||
void Pixel(int x, int y, 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 Circle(int x, int y, int radius, int paletteIndex);
|
||||||
void Ellipse(int x, int y, int width, int height, 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);
|
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->updateVMVars(m_vm);
|
||||||
m_graphics->draw(this->m_stateManager);
|
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 ChangeState(StateManager::StateType state);
|
||||||
|
|
||||||
|
void OnKeyPressed(int key);
|
||||||
|
void OnCharPressed(char c);
|
||||||
|
|
||||||
void RequestLoadGame();
|
void RequestLoadGame();
|
||||||
void RequestRunGame();
|
void RequestRunGame();
|
||||||
void RequestStopGame();
|
void RequestStopGame();
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "EditorState.h"
|
#include "EditorState.h"
|
||||||
#include "../../Graphics/PycronImage.h"
|
#include "../../Graphics/PycronImage.h"
|
||||||
#include "../../Pycron.h"
|
#include "../../Pycron.h"
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
|
|
||||||
EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphics(graphics){
|
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");
|
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_baseBackgroundColor = 56;
|
||||||
m_baseTextColor = 63;
|
m_shadowColor = 28;
|
||||||
|
m_baseTextColor = 42;
|
||||||
m_lineNumberBackgroundColor = 57;
|
m_lineNumberBackgroundColor = 57;
|
||||||
m_lineNumberTextColor = 6;
|
m_lineNumberTextColor = 6;
|
||||||
m_unknownTextColor = 4;
|
m_unknownTextColor = 4;
|
||||||
m_identifierTextColor = 43;
|
m_identifierTextColor = 63;
|
||||||
m_keywordTextColor = 31;
|
m_keywordTextColor = 31;
|
||||||
m_builtinTextColor = 23;
|
m_builtinTextColor = 23;
|
||||||
m_numericalLiteralTextColor = 32;
|
m_numericalLiteralTextColor = 32;
|
||||||
@ -31,23 +33,30 @@ EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphic
|
|||||||
m_operatorTextColor = 45;
|
m_operatorTextColor = 45;
|
||||||
m_commentTextColor = 60;
|
m_commentTextColor = 60;
|
||||||
|
|
||||||
|
|
||||||
m_topLetterSpacing = 0;
|
m_topLetterSpacing = 0;
|
||||||
m_bottomLetterSpacing = 1;
|
m_bottomLetterSpacing = 1;
|
||||||
m_leftLetterSpacing = 0;
|
m_leftLetterSpacing = 0;
|
||||||
m_rightLetterSpacing = 1;
|
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_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_charHeight = m_topLetterSpacing + m_graphics->GetCurrentFontHeight() + m_bottomLetterSpacing;
|
||||||
|
|
||||||
m_textWidth = (int)(m_graphics->m_screenWidth / m_charWidth);
|
m_width = (int)(m_graphics->m_screenWidth / m_charWidth);
|
||||||
m_textHeight = (int)(m_graphics->m_screenHeight / m_charHeight);
|
m_height = (int)(m_graphics->m_screenHeight / m_charHeight);
|
||||||
|
|
||||||
m_characterBuffer = std::vector<char>(m_textWidth * m_textHeight);
|
m_characterBuffer = std::vector<char>(m_width * m_height);
|
||||||
m_foregroundIndexBuffer = std::vector<uint8_t>(m_textWidth * m_textHeight);
|
m_foregroundIndexBuffer = std::vector<uint8_t>(m_width * m_height);
|
||||||
m_backgroundIndexBuffer = std::vector<uint8_t>(m_textWidth * m_textHeight);
|
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();
|
Clear();
|
||||||
|
|
||||||
@ -62,28 +71,20 @@ EditorState::~EditorState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorState::Draw() {
|
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){
|
if(m_dirty){
|
||||||
Clear();
|
Clear();
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
for (int i = 0; i < m_text.size(); ++i) {
|
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)
|
// 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);
|
std::string lineNumber = std::to_string(i);
|
||||||
int size = 2;
|
int size = 2;
|
||||||
int diff = size - (int)lineNumber.size();
|
int diff = size - (int)lineNumber.size();
|
||||||
if(diff > 0) lineNumber = std::string(diff, ' ') + lineNumber;
|
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
|
// Text handling
|
||||||
auto tokens = m_pythonTokenizer->tokenizeLine(m_text[i]);
|
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() {
|
void EditorState::OnEnter() {
|
||||||
@ -128,11 +160,33 @@ void EditorState::OnExit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorState::OnKeyPressed(int key) {
|
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() {
|
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_characterBuffer[i] = ' ';
|
||||||
m_foregroundIndexBuffer[i] = m_baseTextColor;
|
m_foregroundIndexBuffer[i] = m_baseTextColor;
|
||||||
m_backgroundIndexBuffer[i] = m_baseBackgroundColor;
|
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) {
|
for (int i = 0; i < text.size(); ++i) {
|
||||||
int charX = x + i;
|
int charX = x + i;
|
||||||
int charY = y;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
char c = text[i];
|
char c = text[i];
|
||||||
int index = y * m_textWidth + (x + i);
|
int index = y * m_width + (x + i);
|
||||||
m_characterBuffer[index] = c;
|
m_characterBuffer[index] = c;
|
||||||
m_backgroundIndexBuffer[index] = bg;
|
m_backgroundIndexBuffer[index] = bg;
|
||||||
m_foregroundIndexBuffer[index] = fg;
|
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) {
|
void EditorState::LoadStringToBuffer(const std::string &text) {
|
||||||
m_text.clear();
|
m_text.clear();
|
||||||
|
|||||||
@ -24,8 +24,12 @@ private:
|
|||||||
Graphics* m_graphics;
|
Graphics* m_graphics;
|
||||||
PythonTokenizer* m_pythonTokenizer;
|
PythonTokenizer* m_pythonTokenizer;
|
||||||
|
|
||||||
|
// Size of the character in pixels
|
||||||
uint8_t m_charWidth, m_charHeight;
|
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;
|
uint8_t m_topLetterSpacing, m_bottomLetterSpacing, m_leftLetterSpacing, m_rightLetterSpacing;
|
||||||
// Text Buffer
|
// Text Buffer
|
||||||
std::vector<char> m_characterBuffer;
|
std::vector<char> m_characterBuffer;
|
||||||
@ -38,6 +42,7 @@ private:
|
|||||||
|
|
||||||
// Theming
|
// Theming
|
||||||
uint8_t m_baseBackgroundColor;
|
uint8_t m_baseBackgroundColor;
|
||||||
|
uint8_t m_shadowColor;
|
||||||
uint8_t m_baseTextColor;
|
uint8_t m_baseTextColor;
|
||||||
uint8_t m_lineNumberBackgroundColor;
|
uint8_t m_lineNumberBackgroundColor;
|
||||||
uint8_t m_lineNumberTextColor;
|
uint8_t m_lineNumberTextColor;
|
||||||
@ -51,9 +56,16 @@ private:
|
|||||||
uint8_t m_operatorTextColor;
|
uint8_t m_operatorTextColor;
|
||||||
uint8_t m_commentTextColor;
|
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_dirty;
|
||||||
|
|
||||||
|
bool m_drawShadows;
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void Text(const std::string &text, int x, int y, int fg = 0, int bg = 63);
|
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) {
|
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) {
|
std::string PythonTokenizer::readNumericLiteral(const std::string &line) {
|
||||||
@ -165,8 +165,6 @@ std::string PythonTokenizer::readStringLiteral(const std::string &line) {
|
|||||||
m_currentPos++;
|
m_currentPos++;
|
||||||
while (m_currentPos < line.length() && line[m_currentPos] != '"') {
|
while (m_currentPos < line.length() && line[m_currentPos] != '"') {
|
||||||
m_currentPos++;
|
m_currentPos++;
|
||||||
std::cout << m_currentPos;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(line[m_currentPos] == '"') m_currentPos++;
|
if(line[m_currentPos] == '"') m_currentPos++;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user