From 27b322bf259f45695dd08b172ce2b514f09dcec8 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 26 Jul 2024 17:08:05 +0200 Subject: [PATCH] Transitioning text editor to SDL --- build_file.cpp | 10 +- src/basic/math.cpp | 1 + src/basic/math_int.cpp | 7 + src/new_platform/font.cpp | 149 --------------- src/new_platform/new_platform.cpp | 140 -------------- src/new_platform/render_opengl.cpp | 285 ----------------------------- src/text_editor/new_basic.cpp | 43 ----- src/text_editor/text_editor.cpp | 25 +-- src/text_editor/text_editor.h | 10 +- src/text_editor/window.cpp | 24 +-- src/text_editor/window_draw.cpp | 68 +++---- 11 files changed, 67 insertions(+), 695 deletions(-) delete mode 100644 src/new_platform/font.cpp delete mode 100644 src/new_platform/new_platform.cpp delete mode 100644 src/new_platform/render_opengl.cpp delete mode 100644 src/text_editor/new_basic.cpp diff --git a/build_file.cpp b/build_file.cpp index 43b98a0..24914fc 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -116,8 +116,9 @@ int CompileTextEditor() { int result = 0; Array libs = {}; - libs.add(PrepareRaylib()); + libs.add(PrepareSDLDynamic()); libs.add(PrepareLua()); + libs.add(PrepareGlad()); Array cmd = {}; cmd.add("cl.exe"); @@ -127,7 +128,7 @@ int CompileTextEditor() { AddCommonFlags(&cmd); For2(lib, libs) For(lib.defines) cmd.add(it); - cmd.add("../src/text_editor/text_editor.cpp"); + cmd.add("../src/text_editor/new_text_editor.cpp"); cmd.add("../src/basic/win32.cpp"); For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it))); @@ -135,7 +136,8 @@ int CompileTextEditor() { cmd.add("/link"); cmd.add("/incremental:no"); // cmd.add("/SUBSYSTEM:WINDOWS"); - cmd.add("opengl32.lib gdi32.lib winmm.lib shell32.lib user32.lib msvcrt.lib /NODEFAULTLIB:LIBCMT"); + // cmd.add("opengl32.lib gdi32.lib winmm.lib shell32.lib user32.lib msvcrt.lib /NODEFAULTLIB:LIBCMT"); + For2(lib, libs) For(lib.link) cmd.add(it); For(libs) For2(o, it.objects) cmd.add(o); OS_DeleteFile("te.pdb"); @@ -161,7 +163,7 @@ int CompileNewPlatform() { AddCommonFlags(&cmd); For2(lib, libs) For(lib.defines) cmd.add(it); - cmd.add("../src/new_platform/new_platform.cpp"); + cmd.add("../src/platform/platform.cpp"); cmd.add("../src/basic/win32.cpp"); For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it))); diff --git a/src/basic/math.cpp b/src/basic/math.cpp index e582f8f..dd1540c 100644 --- a/src/basic/math.cpp +++ b/src/basic/math.cpp @@ -49,6 +49,7 @@ Vec2 GetSizeF(Rect2I r) { Vec2 ToVec2(Vec2I v) { return {(float)v.x, (float)v.y}; } Vec2I ToVec2I(Vec2 v) { return {(Int)v.x, (Int)v.y}; } Rect2I ToRect2I(Rect2 r) { return {ToVec2I(r.min), ToVec2I(r.max)}; } +Rect2 ToRect2(Rect2I r) { return {ToVec2(r.min), ToVec2(r.max)}; } // clang-format off Rect2 operator-(Rect2 r, Rect2 value) { return { r.min.x - value.min.x, r.min.y - value.min.y, r.max.x - value.max.x, r.max.y - value.max.y }; } diff --git a/src/basic/math_int.cpp b/src/basic/math_int.cpp index 9cd2a61..a3946ee 100644 --- a/src/basic/math_int.cpp +++ b/src/basic/math_int.cpp @@ -8,6 +8,13 @@ struct Rect2I { Vec2I max; }; +struct Color { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +}; + Vec2I GetSize(Rect2I r) { Vec2I result = {r.max.x - r.min.x, r.max.y - r.min.y}; return result; diff --git a/src/new_platform/font.cpp b/src/new_platform/font.cpp deleted file mode 100644 index 4000c74..0000000 --- a/src/new_platform/font.cpp +++ /dev/null @@ -1,149 +0,0 @@ -struct Glyph { - Vec2 size; - Vec2 offset; - float xadvance; - float left_side_bearing; - Rect2 atlas_bounding_box; -}; - -struct Font { - Array glyphs; - uint32_t first_char, last_char; - uint32_t texture_id; - - float size; - float descent; - float ascent; - float line_gap; - - Rect2 white_texture_bounding_box; -}; - -struct Atlas { - uint8_t *bitmap; - Vec2I size; - Vec2 inverse_size; - int xcursor; - int ycursor; - - int32_t biggest_height; - Rect2 white_texture_bounding_box; - uint32_t texture_id; -}; - -Atlas CreateAtlas(Allocator allocator, Vec2I size) { - Atlas result = {}; - result.size = size; - result.inverse_size.x = 1.f / (float)result.size.x; - result.inverse_size.y = 1.f / (float)result.size.y; - result.bitmap = AllocArray(allocator, uint8_t, size.x * size.y); - - // Add a whitebox first for rectangle rendering - for (int y = 0; y < 16; y++) { - for (int x = 0; x < 16; x++) { - uint8_t *dst = result.bitmap + x + y * result.size.x; - *dst = 0xff; - } - } - - result.white_texture_bounding_box = {2.f * result.inverse_size.x, 2.f / (float)result.size.y, 14.f * result.inverse_size.x, 14.f / (float)result.size.y}; - result.xcursor += 16; - result.biggest_height += 16; - return result; -} - -Rect2 PackBitmap(Atlas *atlas, uint8_t *bitmap, int width, int height) { - // Packing into a texture atlas - // @Inefficient The algorithm is a simplest thing I had in mind, first we advance - // through the atlas in X packing consecutive glyphs. After we get to the end of the row - // we advance to the next row by the Y size of the biggest packed glyph. If we get to the - // end of atlas and fail to pack everything the app panics. - - int spacing = 4; - if (atlas->xcursor + width > atlas->size.x) { - if (atlas->ycursor + height < atlas->size.y) { - atlas->xcursor = 0; - atlas->ycursor += atlas->biggest_height + spacing; - } else { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Font loading error!", "Error while packing a font into atlas. Atlas size for this font scale is a bit too small", NULL); - } - } - - uint8_t *src = bitmap; - for (int y = atlas->ycursor; y < atlas->ycursor + height; y += 1) { - for (int x = atlas->xcursor; x < atlas->xcursor + width; x += 1) { - uint8_t *dst = atlas->bitmap + x + y * atlas->size.x; - *dst = *src++; - } - } - - Vec2 size = {(float)width * atlas->inverse_size.x, (float)height * atlas->inverse_size.y}; - Vec2 pos = {(float)atlas->xcursor * atlas->inverse_size.x, (float)atlas->ycursor * atlas->inverse_size.y}; - Rect2 result = {pos.x, pos.y, pos.x + size.x, pos.y + size.y}; - - atlas->xcursor += width + spacing; - if (height > atlas->biggest_height) { - atlas->biggest_height = height; - } - - return result; -} - -Font CreateFont(Atlas *atlas, int32_t size, String path) { - Scratch scratch; - Font result = {}; - - String file = ReadFile(scratch, path); - if (file.len == 0) { - return result; - } - - stbtt_fontinfo stb_font; - int success = stbtt_InitFont(&stb_font, (const unsigned char *)file.data, 0); - if (!success) { - return result; - } - - float scale = stbtt_ScaleForPixelHeight(&stb_font, (float)size); - float em_scale = stbtt_ScaleForMappingEmToPixels(&stb_font, (float)size); - - int ascent, descent, line_gap; - stbtt_GetFontVMetrics(&stb_font, &ascent, &descent, &line_gap); - result.ascent = (float)ascent * scale; - result.descent = (float)descent * scale; - result.line_gap = (float)line_gap * scale; - result.size = (float)size; - result.first_char = ' '; - result.last_char = '~'; - result.white_texture_bounding_box = atlas->white_texture_bounding_box; - - for (uint32_t ascii_symbol = result.first_char; ascii_symbol <= result.last_char; ascii_symbol++) { - int width, height, xoff, yoff; - uint8_t *bitmap = (uint8_t *)stbtt_GetCodepointBitmap(&stb_font, 0, scale, ascii_symbol, &width, &height, &xoff, &yoff); - defer { stbtt_FreeBitmap(bitmap, 0); }; - - int xadvance, left_side_bearing; - stbtt_GetCodepointHMetrics(&stb_font, ascii_symbol, &xadvance, &left_side_bearing); - - Glyph glyph = {}; - glyph.atlas_bounding_box = PackBitmap(atlas, bitmap, width, height); - glyph.size = {(float)width, (float)height}; - glyph.offset = {(float)xoff, (float)yoff}; - glyph.xadvance = (float)xadvance * scale; - glyph.left_side_bearing = (float)left_side_bearing * scale; - Add(&result.glyphs, glyph); - } - - return result; -} - -Glyph *GetGlyph(Font *font, uint32_t codepoint) { - bool is_in_range = codepoint >= font->first_char && codepoint <= font->last_char; - if (is_in_range) { - uint32_t index = codepoint - font->first_char; - return &font->glyphs[index]; - } else { - uint32_t index = '?' - font->first_char; - return &font->glyphs[index]; - } -} \ No newline at end of file diff --git a/src/new_platform/new_platform.cpp b/src/new_platform/new_platform.cpp deleted file mode 100644 index 67f13a4..0000000 --- a/src/new_platform/new_platform.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#define BASIC_IMPL -#include "basic/basic.h" -#include "basic/filesystem.h" - -#include "SDL3/SDL.h" -#include "external/glad/glad.h" -#include "external/stb_truetype.h" -#include "external/stb_truetype.c" - -#include "basic/math_int.cpp" -#include "basic/math.cpp" -#include "font.cpp" -#include "render_opengl.cpp" - -bool AppIsRunning = true; - -void ProcessSDLEvent(SDL_Event *event) { - switch (event->type) { - case SDL_EVENT_QUIT: AppIsRunning = false; return; - case SDL_EVENT_KEY_DOWN: { - SDL_KeyboardEvent &key = event->key; - bool shift = key.mod & SDL_KMOD_SHIFT; - bool ctrl = key.mod & SDL_KMOD_CTRL; - bool alt = key.mod & SDL_KMOD_ALT; - bool super = key.mod & SDL_KMOD_GUI; - - if (key.key == SDLK_F5) { - AppIsRunning = false; - return; - } - - } break; - case SDL_EVENT_KEY_UP: { - SDL_KeyboardEvent &key = event->key; - bool shift = key.mod & SDL_KMOD_SHIFT; - bool ctrl = key.mod & SDL_KMOD_CTRL; - bool alt = key.mod & SDL_KMOD_ALT; - bool super = key.mod & SDL_KMOD_GUI; - - } break; - case SDL_EVENT_TEXT_INPUT: { - } break; - case SDL_EVENT_MOUSE_MOTION: { - } break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: { - } break; - case SDL_EVENT_MOUSE_BUTTON_UP: { - } break; - case SDL_EVENT_MOUSE_WHEEL: { - } break; - } -} - -void GLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *user) { - printf("%s", message); - if (severity == GL_DEBUG_SEVERITY_HIGH || severity == GL_DEBUG_SEVERITY_MEDIUM) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "OpenGL error", message, NULL); - } -} - -#if _WIN32 -int WinMain(void *hInstance, void *hPrevInstance, const char *lpCmdLine, int nShowCmd) -#else -int main() -#endif -{ - InitScratch(); - if (SDL_Init(SDL_INIT_VIDEO) == -1) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL); - return 1; - } - - const char *glsl_version = "#version 450"; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); - - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; - SDL_Window *window = SDL_CreateWindow("Text editor", 640, 480, window_flags); - if (window == NULL) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window!", SDL_GetError(), NULL); - return 1; - } - - SDL_GLContext gl_context = SDL_GL_CreateContext(window); - SDL_GL_MakeCurrent(window, gl_context); - SDL_GL_SetSwapInterval(1); // Enable vsync - SDL_ShowWindow(window); - - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load opengl!", SDL_GetError(), NULL); - return 1; - } - - SDL_GL_SetSwapInterval(1); // vsync - glDebugMessageCallback(&GLDebugCallback, NULL); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - - { - Scratch scratch; - Atlas atlas = CreateAtlas(scratch, {1024, 1024}); - MainFont = CreateFont(&atlas, 16, "C:\\Windows\\Fonts\\consola.ttf"); - { - glCreateTextures(GL_TEXTURE_2D, 1, &atlas.texture_id); - glTextureParameteri(atlas.texture_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTextureParameteri(atlas.texture_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTextureParameteri(atlas.texture_id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTextureParameteri(atlas.texture_id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTextureStorage2D(atlas.texture_id, 1, GL_R8, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y); - glTextureSubImage2D(atlas.texture_id, 0, 0, 0, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y, GL_RED, GL_UNSIGNED_BYTE, atlas.bitmap); - } - MainFont.texture_id = atlas.texture_id; - } - - InitRender(); - - while (AppIsRunning) { - int window_x, window_y; - SDL_GetWindowSize(window, &window_x, &window_y); - Vec2 window_size = {(float)window_x, (float)window_y}; - - SDL_Event event; - SDL_WaitEvent(&event); - ProcessSDLEvent(&event); - - BeginFrameRender(window_size); - DrawString(&MainFont, L"Testing", {0, 0}, {255, 0, 0, 255}); - EndFrameRender({0, 0, 0, 1}); - SDL_GL_SwapWindow(window); - } - - SDL_DestroyWindow(window); - SDL_Quit(); - - return 0; -} \ No newline at end of file diff --git a/src/new_platform/render_opengl.cpp b/src/new_platform/render_opengl.cpp deleted file mode 100644 index 6e05e0b..0000000 --- a/src/new_platform/render_opengl.cpp +++ /dev/null @@ -1,285 +0,0 @@ -struct Shader { - uint32_t pipeline; - uint32_t fshader; - uint32_t vshader; -}; -Shader CreateShader(char *glsl_vshader, char *glsl_fshader); - -struct Color { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; -}; - -struct Vertex2D { - Vec2 pos; - Vec2 tex; - Color color; -}; - -struct VertexNode2D { - VertexNode2D *next; - int count; - Vertex2D vertices[1024 * 64]; -}; - -struct VertexList2D { - VertexNode2D *first; - VertexNode2D *last; -}; - -VertexList2D Vertices; -int64_t TotalVertexCount; - -unsigned VBO, VAO; -Shader Shader2D; -Arena RenderArena; -Font MainFont; -Vec2 WindowSize; - -void BeginFrameRender(Vec2 window_size) { - Clear(&RenderArena); - TotalVertexCount = 0; - Vertices.first = NULL; - Vertices.last = NULL; - WindowSize = window_size; -} - -void EndFrameRender(Vec4 color) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - glViewport(0, 0, (GLsizei)WindowSize.x, (GLsizei)WindowSize.y); - glClearColor(color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a * 255.f); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - // Default draw using the font texture - glBindProgramPipeline(Shader2D.pipeline); - float xinverse = 1.f / (WindowSize.x / 2.f); - float yinverse = 1.f / (WindowSize.y / 2.f); - glProgramUniform2f(Shader2D.vshader, 0, xinverse, yinverse); - for (VertexNode2D *it = Vertices.first; it; it = it->next) { - glNamedBufferSubData(VBO, 0, it->count * sizeof(Vertex2D), it->vertices); - glBindVertexArray(VAO); - GLint s_texture = 0; // texture unit that sampler2D will use in GLSL code - glBindTextureUnit(s_texture, MainFont.texture_id); - glDrawArrays(GL_TRIANGLES, 0, it->count); - } -} - -void InitRender() { - InitArena(&RenderArena); - - glCreateBuffers(1, &VBO); - glNamedBufferStorage(VBO, Lengthof(VertexNode2D::vertices) * sizeof(Vertex2D), 0, GL_DYNAMIC_STORAGE_BIT); - - glCreateVertexArrays(1, &VAO); - - GLint vbuf_index = 0; - glVertexArrayVertexBuffer(VAO, vbuf_index, VBO, 0, sizeof(struct Vertex2D)); - - GLint a_pos = 0; - glVertexArrayAttribFormat(VAO, a_pos, 2, GL_FLOAT, GL_FALSE, offsetof(struct Vertex2D, pos)); - glVertexArrayAttribBinding(VAO, a_pos, vbuf_index); - glEnableVertexArrayAttrib(VAO, a_pos); - - GLint a_tex = 1; - glVertexArrayAttribFormat(VAO, a_tex, 2, GL_FLOAT, GL_FALSE, offsetof(struct Vertex2D, tex)); - glVertexArrayAttribBinding(VAO, a_tex, vbuf_index); - glEnableVertexArrayAttrib(VAO, a_tex); - - GLint a_color = 2; - glVertexArrayAttribFormat(VAO, a_color, 4, GL_UNSIGNED_BYTE, GL_FALSE, offsetof(struct Vertex2D, color)); - glVertexArrayAttribBinding(VAO, a_color, vbuf_index); - glEnableVertexArrayAttrib(VAO, a_color); - - char *glsl_vshader = R"==( - #version 450 core - - layout(location=0) uniform vec2 U_InvHalfScreenSize; - layout(location=0) in vec2 VPos; - layout(location=1) in vec2 VTex; - layout(location=2) in vec4 VColor; - - out gl_PerVertex { vec4 gl_Position; }; // required because of ARB_separate_shader_objects - out vec2 FUV; - out vec4 FColor; - - void main() { - vec2 pos = VPos * U_InvHalfScreenSize; - pos.y = 2 - pos.y; // invert y axis - pos -= vec2(1, 1); // convert to 0,1 range - - gl_Position = vec4(pos, 0, 1); - FUV = VTex; - - FColor = VColor / 255.0; - } - )=="; - - char *glsl_fshader = R"==( - #version 450 core - - in vec2 FUV; - in vec4 FColor; - - layout (binding=0) uniform sampler2D S_Texture; - layout (location=0) out vec4 OutColor; - - void main() { - vec4 c = FColor; - c.a *= texture(S_Texture, FUV).r; - OutColor = c; - } - )=="; - - Shader2D = CreateShader(glsl_vshader, glsl_fshader); -} - -Shader CreateShader(char *glsl_vshader, char *glsl_fshader) { - Shader result = {}; - result.vshader = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vshader); - result.fshader = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fshader); - - GLint linked; - glGetProgramiv(result.vshader, GL_LINK_STATUS, &linked); - if (!linked) { - char message[1024]; - glGetProgramInfoLog(result.vshader, sizeof(message), NULL, message); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to create vertex shader!", message, NULL); - } - - glGetProgramiv(result.fshader, GL_LINK_STATUS, &linked); - if (!linked) { - char message[1024]; - glGetProgramInfoLog(result.fshader, sizeof(message), NULL, message); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to create fragment shader!", message, NULL); - } - - glGenProgramPipelines(1, &result.pipeline); - glUseProgramStages(result.pipeline, GL_VERTEX_SHADER_BIT, result.vshader); - glUseProgramStages(result.pipeline, GL_FRAGMENT_SHADER_BIT, result.fshader); - return result; -} - -#define SLL_QUEUE_ADD_MOD(f, l, n, next) \ - do { \ - (n)->next = 0; \ - if ((f) == 0) { \ - (f) = (l) = (n); \ - } else { \ - (l) = (l)->next = (n); \ - } \ - } while (0) -#define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next) - -Vertex2D *AllocVertex2D(Allocator allocator, VertexList2D *list, int count) { - VertexNode2D *node = list->last; - if (node == 0 || node->count + count > Lengthof(node->vertices)) { - node = AllocType(allocator, VertexNode2D); - SLL_QUEUE_ADD(list->first, list->last, node); - } - - TotalVertexCount += count; - Vertex2D *result = node->vertices + node->count; - node->count += count; - return result; -} - -void PushVertex2D(Allocator allocator, VertexList2D *list, Vertex2D *vertices, int count) { - Vertex2D *result = AllocVertex2D(allocator, list, count); - for (int i = 0; i < count; i += 1) result[i] = vertices[i]; -} - -void PushQuad2D(Allocator arena, VertexList2D *list, Rect2 rect, Rect2 tex, Color color, float rotation = 0.f, Vec2 rotation_point = {}) { - Vertex2D *v = AllocVertex2D(arena, list, 6); - v[0] = { - {rect.min.x, rect.max.y}, - { tex.min.x, tex.max.y}, - color - }; - v[1] = { - {rect.max.x, rect.max.y}, - { tex.max.x, tex.max.y}, - color - }; - v[2] = { - {rect.min.x, rect.min.y}, - { tex.min.x, tex.min.y}, - color - }; - v[3] = { - {rect.min.x, rect.min.y}, - { tex.min.x, tex.min.y}, - color - }; - v[4] = { - {rect.max.x, rect.max.y}, - { tex.max.x, tex.max.y}, - color - }; - v[5] = { - {rect.max.x, rect.min.y}, - { tex.max.x, tex.min.y}, - color - }; - if (rotation != 0.f) { - float s = sinf(rotation); - float c = cosf(rotation); - for (int i = 0; i < 6; i += 1) { - v[i].pos -= rotation_point; - v[i].pos = {v[i].pos.x * c + v[i].pos.y * (-s), v[i].pos.x * s + v[i].pos.y * c}; - v[i].pos += rotation_point; - } - } -} - -void DrawRect(Rect2 rect, Color color) { - PushQuad2D(RenderArena, &Vertices, rect, MainFont.white_texture_bounding_box, color); -} - -Vec2 DrawString(Font *font, String16 string, Vec2 pos, Color color, bool draw = true) { - pos.y += font->ascent; - Vec2 original_pos = pos; - For(string) { - Glyph *g = GetGlyph(font, it); - Rect2 rect = Rect2FromSize(pos + g->offset, g->size); - if (draw && it != '\n' && it != ' ' && it != '\t') { - PushQuad2D(RenderArena, &Vertices, rect, g->atlas_bounding_box, color); - } - pos.x += g->xadvance; - } - Vec2 result = {pos.x - original_pos.x, font->size}; - return result; -} - -Vec2 GetStringSize(Font *font, String16 string, Vec2 pos, Color color) { - return DrawString(font, string, pos, color, false); -} - -Int GetCharSpacing(Font *font) { - Glyph *g = GetGlyph(font, '_'); - if (g->xadvance) return (Int)g->xadvance; - return (Int)g->size.x; -} - -void BeginScissor(Rect2 rect) { - glScissor((GLint)rect.min.x, (GLint)rect.min.y, (GLsizei)(rect.max.x - rect.min.x), (GLsizei)(rect.max.y - rect.min.y)); -} - -void EndScissor() { - glScissor(0, 0, (GLsizei)WindowSize.x, (GLsizei)WindowSize.y); -} - -Rect2 GetScreenRectF() { - Rect2 result = {0, 0, WindowSize.x, WindowSize.y}; - return result; -} - -Rect2I GetScreenRectI() { - Rect2I result = {0, 0, (Int)WindowSize.x, (Int)WindowSize.y}; - return result; -} \ No newline at end of file diff --git a/src/text_editor/new_basic.cpp b/src/text_editor/new_basic.cpp deleted file mode 100644 index 28d236c..0000000 --- a/src/text_editor/new_basic.cpp +++ /dev/null @@ -1,43 +0,0 @@ -void Test() { - { - Array array = {}; - for (int i = 0; i < 64; i += 1) { - Add(&array, i); - } - Assert(array.len == 64); - int i = 0; - For(array) { - Assert(it == i++); - } - Assert(Contains(array, 5)); - Assert(!Contains(array, 70)); - - int a[] = {64, 65, 66, 67}; - InsertArray(&array, a, 4, 62); - Assert(array.len == 68); - Assert(array[61] == 61); - Assert(array[62] == 64); - Assert(array[63] == 65); - Assert(array[64] == 66); - Assert(array[65] == 67); - Assert(array[66] == 62); - - Assert(Get(array, 90, 0) == 0); - Assert(Get(array, 4, 0) == 4); - } - - { - Array arr = {}; - for (int i = 0; i < 32; i += 1) { - Add(&arr, i); - } - - int i = 31; - For(IterateInReverse(&arr)) { - Assert(i == it); - i -= 1; - } - Assert(i == -1); - GetSlice(arr, 4, 7); - } -} diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 1d21295..4900ff8 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -1,16 +1,17 @@ +#include + #define BASIC_IMPL #include "basic/basic.h" #include "basic/filesystem.h" #include "basic/string16.cpp" #include "basic/math_int.cpp" #include "basic/math.cpp" -#include "profiler/profiler.cpp" -#include "new_basic.cpp" -#include + #include "raylib.h" #include "colors.cpp" #include "raylib_utils.cpp" +#include "profiler/profiler.cpp" #include "text_editor.h" #include "buffer_helpers.cpp" @@ -30,26 +31,8 @@ #include "lua.hpp" #include "lua_api.cpp" -/* -- Save file (utf16->utf8) -- resize windows -- file dock on left side - - We can actually combine this with command window and lua, it's just going to be a buffer of - - open "asd/asd/asd/asd" -- Ctrl + F - -- word completion -- Colored strings - -- move off raylib - - Adjust text position a little bit down? - - proper double click that works on laptop - - font cache and on demand unicode loads -*/ - int main(void) { InitScratch(); - Test(); BeginProfiler(); BeginProfileScope("main"); diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 8b4a063..bc293c0 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -86,17 +86,9 @@ struct Scroller { Int line_count; }; -float MenuFontSize; -Font MenuFont; - -Font MainFont; -Int FontSize; -Int FontSpacing; -Int FontLineSpacing; -Int FontCharSpacing; - Int FrameID; String WorkingDir; +Arena Perm; String16 EvalString(Allocator allocator, String16 string16); Rect2I GetVisibleCells(Window &window); diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index dfc95b7..c9425fe 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -1,18 +1,18 @@ void SetMouseCursor() { - Window *w = GetActiveWindow(); - Vec2 mouse = GetMousePosition(); + // 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)); + // 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); - } + // 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) { diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/window_draw.cpp index bf55b6a..8d606e4 100644 --- a/src/text_editor/window_draw.cpp +++ b/src/text_editor/window_draw.cpp @@ -51,23 +51,27 @@ void DrawVisibleText(Window &window) { Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing}; pos -= view.scroll; pos += window.document_rect.min; - // pos.y += (Int)(0.3 * (double)FontSize); // @todo: descent float text_offset_x = 0; for (Int col_index = visible.min.x; col_index < visible.max.x && col_index >= 0 && col_index < line_string.len; col_index += 1) { - int codepoint = line_string[col_index]; - int index = GetGlyphIndex(MainFont, codepoint); + int codepoint = line_string[col_index]; + Glyph *g = GetGlyph(&MainFont, codepoint); + Vec2 p = ToVec2(pos); + p.y += MainFont.ascent; + p.x += text_offset_x; + Rect2 rect = Rect2FromSize(p + g->offset, g->size); if (codepoint == '\n' || codepoint == '\r') { // DrawCircle((int)pos.x + (int)text_offset_x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, tint); } else if (codepoint == ' ') { // DrawCircle((int)pos.x + (int)text_offset_x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, space_color); } else if (codepoint != '\t') { - DrawTextCodepoint(MainFont, codepoint, {(float)pos.x + text_offset_x, (float)pos.y}, (float)FontSize, tint); + PushQuad2D(RenderArena, &Vertices, rect, g->atlas_bounding_box, tint); + // DrawTextCodepoint(MainFont, codepoint, {(float)pos.x + text_offset_x, (float)pos.y}, (float)FontSize, tint); } - if (MainFont.glyphs[index].advanceX == 0) text_offset_x += ((float)MainFont.recs[index].width + FontSpacing); - else text_offset_x += ((float)MainFont.glyphs[index].advanceX + FontSpacing); + if (g->xadvance == 0) text_offset_x += g->size.x; + else text_offset_x += g->xadvance; } } } @@ -88,16 +92,16 @@ void DrawCaret(Window &window, XY xy, float size, Color color) { Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing)); rect -= view.scroll; rect += window.document_rect.min; - DrawRectangleRec(ToRectangle(rect), color); + DrawRect(ToRect2(rect), color); } void DrawWindow(Window &window) { View &view = *GetActiveView(&window); Buffer *buffer = GetBuffer(view.active_buffer); - DrawRectangleRec(ToRectangle(window.total_rect), ColorBackground); + DrawRect(ToRect2(window.total_rect), ColorBackground); bool is_active = IsActive(&window) || window.id.id == GetLastActiveWindow().id; - BeginScissorMode((int)window.document_rect.min.x, (int)window.document_rect.min.y, (int)window.document_rect.max.x - (int)window.document_rect.min.x, (int)window.document_rect.max.y - (int)window.document_rect.min.y); + BeginScissor(window.document_rect); BeginProfileScope(draw_caret_selection); Rect2I visible = GetVisibleCells(window); For(view.carets) { @@ -122,15 +126,15 @@ void DrawWindow(Window &window) { Vec2I pos = {col * FontCharSpacing, line * FontLineSpacing}; pos -= view.scroll; pos += window.document_rect.min; - Rectangle rectangle = {(float)pos.x, (float)pos.y, (float)FontCharSpacing, (float)FontLineSpacing}; - DrawRectangleRec(rectangle, ColorSelection); + Rect2 rect = Rect2FromSize({(float)pos.x, (float)pos.y}, {(float)FontCharSpacing, (float)FontLineSpacing}); + DrawRect(rect, ColorSelection); if (line_string[col] == ' ' || line_string[col] == '\t') { - DrawCircle((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 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') { - DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 4.f, (float)FontSize / 15.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') { - DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, (float)FontSize / 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); } } } @@ -142,11 +146,11 @@ void DrawWindow(Window &window) { Vec2I w = XYToWorldPos(view, XYLine(fxy.line)); w -= view.scroll; w += window.document_rect.min; - Rect2I rect = { - { 0, w.y}, - {GetRenderWidth(), w.y + FontLineSpacing} + Rect2 rect = { + { 0.f, (float)w.y}, + {WindowSize.x, (float)w.y + (float)FontLineSpacing} }; - DrawRectangleRec(ToRectangle(rect), ColorLineHighlight); + DrawRect(rect, ColorLineHighlight); } } EndProfileScope(); @@ -163,28 +167,28 @@ void DrawWindow(Window &window) { } } EndProfileScope(); - EndScissorMode(); + EndScissor(); // Draw scrollbar if (window.draw_scrollbar) { - Vec2 mouse = GetMousePosition(); - bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(window.scrollbar_rect)); + // Vec2 mouse = GetMousePosition(); + // bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(window.scrollbar_rect)); - DrawRectangleRec(ToRectangle(window.scrollbar_rect), ColorScrollbarBackground); + DrawRect(ToRect2(window.scrollbar_rect), ColorScrollbarBackground); Scroller scroller = ComputeScrollerRect(window); Rect2 rect = Shrink(scroller.rect, 2); Color color = ColorScrollbarScroller; - if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) { - if (is_active) color = ColorScrollbarScrollerSelected; - } - DrawRectangleRec(ToRectangle(rect), color); + // if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) { + // if (is_active) color = ColorScrollbarScrollerSelected; + // } + DrawRect(rect, color); } // Draw line numbers if (window.draw_line_numbers) { Rect2I r = window.line_numbers_rect; - DrawRectangleRec(ToRectangle(r), ColorBackground); - BeginScissorMode((int)r.min.x, (int)r.min.y, (int)r.max.x - (int)r.min.x, (int)r.max.y - (int)r.min.y); + DrawRect(ToRect2(r), ColorBackground); + BeginScissor(r); Rect2I vlines = GetVisibleCells(window); for (Int line = vlines.min.y; line <= vlines.max.y; line += 1) { @@ -194,18 +198,18 @@ void DrawWindow(Window &window) { pos += r.min; String s = Format(scratch, "%lld", (long long)line); String16 string = ToString16(scratch, s); - float x = MeasureTextEx(MainFont, s.data, (float)FontSize, (float)FontSpacing).x; + float x = GetStringSize(&MainFont, string).x; Vec2 p = ToVec2(pos); float rectx = (float)GetSize(r).x; p.x += (rectx - x) / 2.f; if (x > rectx) p.x = (float)r.min.x; - DrawString(MainFont, string, p, (float)FontSize, (float)FontSpacing, ColorTextLineNumbers); + DrawString(&MainFont, string, p, ColorTextLineNumbers); } - EndScissorMode(); + EndScissor(); } if (!is_active) { - DrawRectangleRec(ToRectangle(window.total_rect), {0, 0, 0, 30}); + DrawRect(ToRect2(window.total_rect), {0, 0, 0, 30}); } }