diff --git a/src/basic/math.cpp b/src/basic/math.cpp index cd0ce41..d6d37fb 100644 --- a/src/basic/math.cpp +++ b/src/basic/math.cpp @@ -181,3 +181,8 @@ float SafeDivide(float a, float b) { } return a / b; } + +bool CheckCollisionPointRec(Vec2 point, Rect2 rec) { + bool result = (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); + return result; +} \ No newline at end of file diff --git a/src/basic/math_int.cpp b/src/basic/math_int.cpp index a3946ee..dc7bdee 100644 --- a/src/basic/math_int.cpp +++ b/src/basic/math_int.cpp @@ -141,3 +141,8 @@ Int SafeDivide(Int a, Int b) { } return a / b; } + +bool CheckCollisionPointRec(Vec2I point, Rect2I rec) { + bool result = (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); + return result; +} \ No newline at end of file diff --git a/src/platform/render_opengl.cpp b/src/platform/render_opengl.cpp index 4109c72..fb33dfe 100644 --- a/src/platform/render_opengl.cpp +++ b/src/platform/render_opengl.cpp @@ -76,7 +76,7 @@ void EndFrameRender(Color color) { GLint y = (GLint)rect.min.y; GLsizei w = (GLsizei)(rect.max.x - rect.min.x); GLsizei h = (GLsizei)(rect.max.y - rect.min.y); - glScissor(x, (GLint)WindowSize.y - h, w, h); + glScissor(x, (GLint)WindowSize.y - (GLint)rect.max.y, w, h); glNamedBufferSubData(VBO, 0, it->count * sizeof(Vertex2D), it->vertices); glBindVertexArray(VAO); GLint s_texture = 0; // texture unit that sampler2D will use in GLSL code @@ -229,6 +229,8 @@ void SetScissor(Rect2 rect) { } } +void SetScissor(Rect2I rect) { SetScissor(ToRect2(rect)); } + Vertex2D *AllocVertex2D(Allocator allocator, VertexList2D *list, int count) { VertexNode2D *node = list->last; if (node == 0 || node->count + count > Lengthof(node->vertices)) { @@ -293,6 +295,9 @@ void PushQuad2D(Allocator arena, VertexList2D *list, Rect2 rect, Rect2 tex, Colo void DrawRect(Rect2 rect, Color color) { PushQuad2D(RenderArena, &Vertices, rect, MainFont.white_texture_bounding_box, color); } +void DrawRect(Rect2I rect, Color color) { + PushQuad2D(RenderArena, &Vertices, ToRect2(rect), MainFont.white_texture_bounding_box, color); +} Vec2 DrawString(Font *font, String16 string, Vec2 pos, Color color, bool draw = true) { pos.y += font->ascent - font->descent; @@ -309,6 +314,38 @@ Vec2 DrawString(Font *font, String16 string, Vec2 pos, Color color, bool draw = return result; } +#define PI32 3.14159265359f +void DrawCircle(Vec2 pos, float radius, Color color) { + const int segment_count = 16; + const int vertex_count = segment_count * 3; + Vec2 points[segment_count + 1]; + for (int i = 0; i < Lengthof(points); i += 1) { + float radians = 2.0f * PI32 * float(i) / float(segment_count); + float x = radius * cosf(radians); + float y = radius * sinf(radians); + points[i] = {x, y}; + } + points[segment_count] = points[0]; // wrap around + + Vertex2D *vertices = AllocVertex2D(RenderArena, &Vertices, vertex_count); + int point_i = 0; + int segment_i = 0; + for (; segment_i < vertex_count; segment_i += 3, point_i += 1) { + Rect2 tex = MainFont.white_texture_bounding_box; + Vertex2D *it = vertices + segment_i; + it[0].color = color; + it[1].color = color; + it[2].color = color; + it[0].tex = {tex.min.x, tex.max.y}; + it[1].tex = {tex.max.x, tex.max.y}; + it[2].tex = {tex.min.x, tex.min.y}; + + it[0].pos = {pos + points[point_i]}; + it[1].pos = {pos + points[point_i + 1]}; + it[2].pos = {pos}; + } +} + Vec2 GetStringSize(Font *font, String16 string) { return DrawString(font, string, {}, {}, false); } diff --git a/src/text_editor/commands_window.cpp b/src/text_editor/commands_window.cpp index fcd7c18..7df4304 100644 --- a/src/text_editor/commands_window.cpp +++ b/src/text_editor/commands_window.cpp @@ -625,40 +625,6 @@ void HandleWindowBindings(Window *window) { } } -void ChangeActiveWindowAndScroll(Array &order) { - For(order) { - Window *window = &Windows[it]; - - if (window->invisible_when_inactive) { - if (IsActive(window)) window->visible = true; - else window->visible = false; - } - if (!window->visible) continue; - - View *view = GetActiveView(window); - view->main_caret_on_begin_frame = view->carets[0]; - - // Vec2 mouse = GetMousePosition(); - // bool mouse_in_window = CheckCollisionPointRec(mouse, ToRectangle(window->total_rect)); - // if (mouse_in_window) { - // if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - // Window *active_window = GetWindow(ActiveWindow); - // if (active_window->z <= window->z) { - // SetActiveWindow(window->id); - // } - // } - // if (LastFrameIDWhenScrolled != FrameID) { - // if (IsKeyDown(KEY_F1)) { - // view->scroll.x -= (Int)(GetMouseWheelMove() * 48); - // } else { - // view->scroll.y -= (Int)(GetMouseWheelMove() * 48); - // } - // LastFrameIDWhenScrolled = FrameID; - // } - // } - } -} - void ReplaceInfobarData() { Window *window = GetWindow(InfoBarWindowID); if (IsActive(window)) return; diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp index 530c9e6..1f487e1 100644 --- a/src/text_editor/management.cpp +++ b/src/text_editor/management.cpp @@ -16,7 +16,6 @@ WindowID SearchWindowID = {0}; Array WindowSwitchHistory; // @todo: probably better as a circular buffer WindowID ActiveWindow; // @todo: maybe NextActiveWindow and change at end of frame Int CaretChangeID; -Int LastFrameIDWhenScrolled = -1; Int LastFrameIDWhenSwitchedActiveWindow; inline ViewID AllocViewID() { return {ViewIDs.id++}; } diff --git a/src/text_editor/new_text_editor.cpp b/src/text_editor/new_text_editor.cpp index 6fc846b..7b42830 100644 --- a/src/text_editor/new_text_editor.cpp +++ b/src/text_editor/new_text_editor.cpp @@ -35,8 +35,9 @@ #include "lua.hpp" #include "lua_api.cpp" -bool AppIsRunning = true; -bool WaitForEvents = false; +bool AppIsRunning = true; +bool WaitForEvents = false; +SDL_Cursor *SDL_MouseCursor = NULL; void ProcessSDLEvent(SDL_Event *event) { switch (event->type) { @@ -63,14 +64,77 @@ void ProcessSDLEvent(SDL_Event *event) { } break; case SDL_EVENT_TEXT_INPUT: { + SDL_TextInputEvent &b = event->text; + } break; case SDL_EVENT_MOUSE_MOTION: { + SDL_MouseMotionEvent &b = event->motion; + Vec2I mouse = {(Int)b.x, (Int)b.y}; + + Window *w = GetActiveWindow(); + bool mouse_in_document = CheckCollisionPointRec(mouse, w->document_rect); + bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, w->scrollbar_rect); + bool mouse_in_total = CheckCollisionPointRec(mouse, w->total_rect); + + if (SDL_MouseCursor) SDL_DestroyCursor(SDL_MouseCursor); + + if (w->mouse_selecting || mouse_in_document) { + SDL_MouseCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_TEXT); + SDL_SetCursor(SDL_MouseCursor); + } else if (mouse_in_scrollbar || w->mouse_selecting_scrollbar) { + SDL_MouseCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT); + SDL_SetCursor(SDL_MouseCursor); + } else { + SDL_MouseCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER); + SDL_SetCursor(SDL_MouseCursor); + } } break; case SDL_EVENT_MOUSE_BUTTON_DOWN: { + SDL_MouseButtonEvent &b = event->button; + Vec2I mouse = {(Int)b.x, (Int)b.y}; + Scratch scratch; + Array order = GetWindowZOrder(scratch); + + For(order) { + Window *window = &Windows[it]; + if (!window->visible) continue; + // view->main_caret_on_begin_frame = view->carets[0]; + + // if (window->invisible_when_inactive) { + // if (IsActive(window)) window->visible = true; + // else window->visible = false; + // } + + bool mouse_in_window = CheckCollisionPointRec(mouse, window->total_rect); + if (mouse_in_window) { + Window *active_window = GetWindow(ActiveWindow); + if (active_window->z <= window->z) { + SetActiveWindow(window->id); + } + } + } } break; case SDL_EVENT_MOUSE_BUTTON_UP: { + SDL_MouseButtonEvent &b = event->button; } break; case SDL_EVENT_MOUSE_WHEEL: { + SDL_MouseWheelEvent &b = event->wheel; + Vec2 wheel = {b.x, b.y}; + Vec2I mouse = {(Int)b.mouse_x, (Int)b.mouse_y}; + + Scratch scratch; + Array order = GetWindowZOrder(scratch); + For(IterateInReverse(&order)) { + Window *window = &Windows[it]; + if (!window->visible) continue; + + bool mouse_in_window = CheckCollisionPointRec(mouse, window->total_rect); + if (mouse_in_window) { + View *view = GetView(window->active_view); + view->scroll.y -= (Int)(wheel.y * 48); + break; + } + } } break; } } @@ -158,6 +222,7 @@ int main() while (SDL_PollEvent(&event)) { ProcessSDLEvent(&event); } + ReplaceInfobarData(); Scratch scratch; Array order = GetWindowZOrder(scratch); diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index e06cb09..36d1f92 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -1,19 +1,3 @@ -void SetMouseCursor() { - // Window *w = GetActiveWindow(); - // Vec2 mouse = GetMousePosition(); - - // bool mouse_in_document = CheckCollisionPointRec(mouse, ToRectangle(w->document_rect)); - // bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(w->scrollbar_rect)); - // bool mouse_in_total = CheckCollisionPointRec(mouse, ToRectangle(w->total_rect)); - - // if (w->mouse_selecting || mouse_in_document) { - // SetMouseCursor(MOUSE_CURSOR_IBEAM); - // } else if (mouse_in_scrollbar || w->mouse_selecting_scrollbar) { - // SetMouseCursor(MOUSE_CURSOR_DEFAULT); - // } else { - // SetMouseCursor(MOUSE_CURSOR_POINTING_HAND); - // } -} Array GetWindowZOrder(Allocator allocator) { Array order = {allocator}; @@ -78,7 +62,7 @@ void InitWindows() { AddView(w, v->id); CommandWindowID = w->id; - // Command_EvalLua(v, L"open \"./\""); + Command_EvalLua(v, L"open \"./\""); } { diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/window_draw.cpp index ac7dd72..abf714f 100644 --- a/src/text_editor/window_draw.cpp +++ b/src/text_editor/window_draw.cpp @@ -41,15 +41,15 @@ Scroller ComputeScrollerRect(Window &window) { void DrawVisibleText(Window &window) { ProfileFunction(); Color tint = ColorText; - View &view = *GetActiveView(&window); - Buffer *buffer = GetBuffer(view.active_buffer); + View *view = GetActiveView(&window); + Buffer *buffer = GetBuffer(view->active_buffer); Rect2I visible = GetVisibleCells(window); for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < buffer->line_starts.len; line_index += 1) { String16 line_string = GetLineString(*buffer, line_index); Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing}; - pos -= view.scroll; + pos -= view->scroll; pos += window.document_rect.min; float text_offset_x = 0; @@ -93,10 +93,11 @@ void DrawCaret(Window &window, XY xy, float size, Color color) { void DrawWindow(Window &window) { View &view = *GetActiveView(&window); Buffer *buffer = GetBuffer(view.active_buffer); - DrawRect(ToRect2(window.total_rect), ColorBackground); + SetScissor(GetScreenRectF()); + DrawRect(window.total_rect, ColorBackground); bool is_active = IsActive(&window) || window.id.id == GetLastActiveWindow().id; - SetScissor(ToRect2(window.document_rect)); + SetScissor(window.document_rect); BeginProfileScope(draw_caret_selection); Rect2I visible = GetVisibleCells(window); For(view.carets) { @@ -125,10 +126,13 @@ void DrawWindow(Window &window) { DrawRect(rect, ColorSelection); if (line_string[col] == ' ' || line_string[col] == '\t') { + DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y + (float)FontLineSpacing / 2.f}, MainFont.size / 10.f, ColorWhitespaceDuringSelection); // DrawCircle((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)MainFont.size / 10.f, ColorWhitespaceDuringSelection); } else if (line_string[col] == '\n') { + DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y + (float)FontLineSpacing / 2.f}, MainFont.size / 4.f, ColorWhitespaceDuringSelection); // DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)MainFont.size / 4.f, (float)MainFont.size / 15.f, ColorWhitespaceDuringSelection); } else if (line_string[col] == '\r') { + DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y + (float)FontLineSpacing / 2.f}, MainFont.size / 4.f, ColorWhitespaceDuringSelection); // DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)MainFont.size / 10.f, (float)MainFont.size / 4.f, ColorWhitespaceDuringSelection); } } @@ -149,7 +153,6 @@ void DrawWindow(Window &window) { } } EndProfileScope(); - DrawVisibleText(window); BeginProfileScope(draw_carets); @@ -165,34 +168,33 @@ void DrawWindow(Window &window) { // Draw line numbers if (window.draw_line_numbers) { - Rect2I r = window.line_numbers_rect; - DrawRect(ToRect2(r), ColorBackground); - SetScissor(ToRect2(r)); + SetScissor(window.line_numbers_rect); + DrawRect(window.line_numbers_rect, ColorBackground); Rect2I vlines = GetVisibleCells(window); for (Int line = vlines.min.y; line <= vlines.max.y; line += 1) { Scratch scratch; Vec2I pos = {0, line * FontLineSpacing}; pos.y -= view.scroll.y; - pos += r.min; + pos += window.line_numbers_rect.min; String s = Format(scratch, "%lld", (long long)line); String16 string = ToString16(scratch, s); float x = GetStringSize(&MainFont, string).x; Vec2 p = ToVec2(pos); - float rectx = (float)GetSize(r).x; + float rectx = (float)GetSize(window.line_numbers_rect).x; p.x += (rectx - x) / 2.f; - if (x > rectx) p.x = (float)r.min.x; + if (x > rectx) p.x = (float)window.line_numbers_rect.min.x; DrawString(&MainFont, string, p, ColorTextLineNumbers); } } - SetScissor(GetScreenRectF()); // Draw scrollbar if (window.draw_scrollbar) { + SetScissor(window.scrollbar_rect); // Vec2 mouse = GetMousePosition(); // bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(window.scrollbar_rect)); - DrawRect(ToRect2(window.scrollbar_rect), ColorScrollbarBackground); + DrawRect(window.scrollbar_rect, ColorScrollbarBackground); Scroller scroller = ComputeScrollerRect(window); Rect2 rect = Shrink(scroller.rect, 2); Color color = ColorScrollbarScroller; @@ -203,6 +205,7 @@ void DrawWindow(Window &window) { } if (!is_active) { - DrawRect(ToRect2(window.total_rect), {0, 0, 0, 30}); + SetScissor(GetScreenRectF()); + DrawRect(window.total_rect, {0, 0, 0, 30}); } }