diff --git a/.build/.added_strings_w3.jai b/.build/.added_strings_w3.jai index 03e7ad2..166fb84 100644 --- a/.build/.added_strings_w3.jai +++ b/.build/.added_strings_w3.jai @@ -5,8 +5,8 @@ // NAME :: "mexplore"; VERSION :: "0.1"; - JAI_VERSION :: "beta 0.2.014, built on 24 May 2025"; - RELEASE_DATE :: "19 July 2025, 16:47:42"; + JAI_VERSION :: "beta 0.2.016, built on 19 July 2025"; + RELEASE_DATE :: "26 July 2025, 17:47:40"; GIT_BRANCH :: "main"; - GIT_REVISION :: "3520906f2803cf5baf5d52dcb05daf94d8edadd1"; + GIT_REVISION :: "89727b9bc176c098f703cbc731593120989767ed"; DEBUG :: true; diff --git a/.build/mexplore-debug_0_w3.obj b/.build/mexplore-debug_0_w3.obj index 9bdb7fd..f6fc585 100644 Binary files a/.build/mexplore-debug_0_w3.obj and b/.build/mexplore-debug_0_w3.obj differ diff --git a/.build/mexplore-debug_1_w3.obj b/.build/mexplore-debug_1_w3.obj index 8f20d5d..8b03293 100644 Binary files a/.build/mexplore-debug_1_w3.obj and b/.build/mexplore-debug_1_w3.obj differ diff --git a/.build/mexplore-debug_2_w3.obj b/.build/mexplore-debug_2_w3.obj index 734ef4d..bc3d8bf 100644 Binary files a/.build/mexplore-debug_2_w3.obj and b/.build/mexplore-debug_2_w3.obj differ diff --git a/.build/mexplore-debug_3_w3.obj b/.build/mexplore-debug_3_w3.obj index 4207122..46b9a64 100644 Binary files a/.build/mexplore-debug_3_w3.obj and b/.build/mexplore-debug_3_w3.obj differ diff --git a/bin/mexplore-debug.exe b/bin/mexplore-debug.exe index 4d5fc8e..0dddf11 100644 Binary files a/bin/mexplore-debug.exe and b/bin/mexplore-debug.exe differ diff --git a/bin/mexplore-debug.pdb b/bin/mexplore-debug.pdb index df7bf4f..ff4f1c3 100644 Binary files a/bin/mexplore-debug.pdb and b/bin/mexplore-debug.pdb differ diff --git a/bin/mexplore-debug.rdi b/bin/mexplore-debug.rdi index ca009d6..606f9b5 100644 Binary files a/bin/mexplore-debug.rdi and b/bin/mexplore-debug.rdi differ diff --git a/src/main.jai b/src/main.jai index e29e9bd..6d66573 100644 --- a/src/main.jai +++ b/src/main.jai @@ -30,8 +30,11 @@ window : *SDL_Window; gl_context : SDL_GLContext; running : bool = true; +dt : float; frame : u64; +counter_frequency : u64; + ui_font_very_small : Font; ui_font_small : Font; ui_font_normal : Font; @@ -64,7 +67,16 @@ main :: () { SDL_StartTextInput(window); + counter_frequency = SDL_GetPerformanceFrequency(); + + last_counter : u64 = SDL_GetPerformanceCounter(); + while (running) { + new_counter : u64 = SDL_GetPerformanceCounter(); + dt = cast(float, new_counter - last_counter) / cast(float, counter_frequency); + last_counter = new_counter; + log("%", dt); + input_state.last_char = 0; event : SDL_Event; diff --git a/src/stb_textedit.jai b/src/stb_textedit.jai index 4263eeb..421ef26 100644 --- a/src/stb_textedit.jai +++ b/src/stb_textedit.jai @@ -369,7 +369,48 @@ STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s } STB_TEXTEDIT_GETWIDTH :: (obj: *STB_TEXTEDIT_STRING, n: s32, i: s32) -> float { - return 10.0; + assert(i >= n, "n is where the line starts, and i the character we want to size. So i must be >= n"); + + textp : *u32 = obj.text.data; + Codepoints : *u32 = textp + n; + CodepointCount : u64 = xx (obj.text.count - (Codepoints - textp)); + + Cursor : kbts_cursor; + Direction : kbts_direction = .NONE; + Script : kbts_script = .DONT_KNOW; + RunStart : u64 = 0; + BreakState : kbts_break_state; + kbts_BeginBreak(*BreakState, .NONE, .NORMAL); + + width : float; + + CodepointIndex : u64; + while CodepointIndex < xx i { + kbts_BreakAddCodepoint(*BreakState, Codepoints[CodepointIndex], 1, xx ((CodepointIndex + 1) == xx CodepointCount)); + Break : kbts_break; + while kbts_Break(*BreakState, *Break) { + + if Break.Flags & .DIRECTION { + Direction = Break.Direction; + if(!Cursor.Direction) Cursor = kbts_Cursor(BreakState.MainDirection); + } + + if Break.Flags & .SCRIPT { + Script = Break.Script; + } + + if (Break.Position > RunStart) && (Break.Flags & .GRAPHEME) { + RunLength : u64 = Break.Position - RunStart; + size, max_descent := ShapeText(obj.font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script); + + width = size.x; + } + } + + CodepointIndex += 1; + } + + return width; } STB_TEXTEDIT_K_LEFT :: 0x200000; // keyboard input to move cursor left diff --git a/src/text.jai b/src/text.jai index e713dc6..80e87e0 100644 --- a/src/text.jai +++ b/src/text.jai @@ -261,6 +261,9 @@ render_text :: (font: *Font, text: []u32, pos: Vector2, size: Vector2, window_sp GlyphCapacity = State.RequiredGlyphCapacity; } + x_offset : float; + y_offset : float; + GlyphIndex : u64; while GlyphIndex < GlyphCount { kglyph : *kbts_glyph = *Glyphs[GlyphIndex]; @@ -273,9 +276,6 @@ render_text :: (font: *Font, text: []u32, pos: Vector2, size: Vector2, window_sp // x_advance : hb_position_t = glyph_pos[i].x_advance; // y_advance : hb_position_t = glyph_pos[i].y_advance; - x_offset : float = xx FT_MulFix(X, font.face.size.metrics.x_scale) >> 6; - y_offset : float = xx FT_MulFix(Y, font.face.size.metrics.y_scale) >> 6; - glyph : *Glyph = table_find_pointer(*font.glyphs, kglyph.Id); if !glyph { @@ -287,14 +287,16 @@ render_text :: (font: *Font, text: []u32, pos: Vector2, size: Vector2, window_sp v0 : Vector2; v1 : Vector2; if count_descent { - v0 = render_pos + .{cast(float) x_offset + glyph.bearing_x, + v0 = render_pos + .{cast(float) x_offset,// + glyph.bearing_x, cast(float) y_offset - glyph.bearing_y + size.y /*- max_descent*/}; } else { - v0 = render_pos + .{cast(float) x_offset + glyph.bearing_x, + v0 = render_pos + .{cast(float) x_offset,// + glyph.bearing_x, cast(float) y_offset - (xx glyph.height - glyph.bearing_y)/* - glyph.height + draw_size.y*/}; } v1 = v0 + Vector2.{cast(float) glyph.width, cast(float) glyph.height}; + x_offset += xx (FT_MulFix(Cursor.X - X, font.face.size.metrics.x_scale) >> 6); + y_offset += xx (FT_MulFix(Cursor.Y - Y, font.face.size.metrics.y_scale) >> 6); // #if Y_IS_UP { // t0 := Vector2.{cast(float, glyph.x) / cast(float, ATLAS_SIZE), cast(float, glyph.y) / cast(float, ATLAS_SIZE)}; @@ -306,6 +308,8 @@ render_text :: (font: *Font, text: []u32, pos: Vector2, size: Vector2, window_sp // t1 := t0 + .{cast(float, glyph.width / ATLAS_SIZE), cast(float, glyph.height / ATLAS_SIZE)}; // } + log("adding vertex %, %, with size %", v0, v1, v1 - v0); + array_add(*vertices, .{v0, t0, colour}); array_add(*vertices, .{.{v0.x, v1.y}, .{t0.x, t1.y}, colour}); array_add(*vertices, .{.{v1.x, v0.y}, .{t1.x, t0.y}, colour}); @@ -484,7 +488,7 @@ ShapeText :: (font: *Font, Cursor: *kbts_cursor, Codepoints: *u32, CodepointCoun glyph : *Glyph = table_find_pointer(*font.glyphs, kglyph.Id); if glyph { size.y = max(size.y, xx glyph.height); - size.x += xx FT_MulFix(Cursor.X - X, font.face.size.metrics.x_scale) >> 6; + size.x += xx (FT_MulFix(kglyph.AdvanceX, font.face.size.metrics.x_scale) >> 6); max_descent = max(max_descent, xx glyph.descent); //line.max_descent = max(line.max_descent, cast(float) glyph.descent); //line.max_ascent = max(line.max_ascent, cast(float) glyph.ascent); diff --git a/src/ui.jai b/src/ui.jai index 2c22696..3edf4c8 100644 --- a/src/ui.jai +++ b/src/ui.jai @@ -203,6 +203,7 @@ TextInput :: struct { max_width : float; max_descent : float; textedit_state : STB_TexteditState; + cursor_time : float; } Container :: struct { @@ -904,6 +905,8 @@ ui_text_input :: (s: string, font_colour := Vector4.{1, 1, 1, 1}) { ui_append_to_parent(text_input); + log("%", text_input.textedit_state.cursor); + if text_input.active && input_state.last_char > 0 { stb_textedit_key(text_input, *text_input.textedit_state, input_state.last_char); log("adding char %", input_state.last_char); @@ -992,10 +995,12 @@ ui_draw_text_input :: (using text_input: *TextInput) { // Restore modified GL state // restore_opengl_state(*opengl_state); + cursor_pos : Vector2 = pos + .{0.0, size.y - font.face.size.metrics.height >> 6 - 2 *(margin + border_size + padding)}; + if text_input.text.count > 0 { //midline : Vector2 = pos + Vector2.{cast(float, margin + border_size + padding), xx (size.y / 2.0)}; - draw_pos : Vector2 = pos + .{0.0, size.y - font.face.size.metrics.height >> 6 - (margin + border_size + padding)} + v2(margin) + v2(border_size) + v2(padding); + draw_pos : Vector2 = pos + .{0.0, size.y - font.face.size.metrics.height >> 6 - (margin + border_size + padding)} + v2(margin) + v2(border_size) + v2(padding); i : s32; @@ -1003,6 +1008,23 @@ ui_draw_text_input :: (using text_input: *TextInput) { row : StbTexteditRow; STB_TEXTEDIT_LAYOUTROW(*row, text_input, i); + if i + xx row.num_chars >= textedit_state.cursor { + j : s32; + while grapheme := i + j < textedit_state.cursor { + size, max_descent, read := next_grapheme_size(font, text, i + j, 0.0); + + cursor_pos.x += size.x; + // row.x1 += size.x; + // row.baseline_y_delta = max(row.baseline_y_delta, size.y); + // row.ymin = max(row.ymin, max_descent); + // row.ymax = max(row.ymax, size.y - row.ymin); + // row.num_chars += read; + j += read; + } + } else { + cursor_pos.y -= font.face.size.metrics.height >> 6; + } + render_text(font, .{row.num_chars, text_input.text.data + i}, .{draw_pos.x, draw_pos.y + row.ymin /*+ line.max_descent*/}, text_input.size, colour = font_colour); @@ -1017,6 +1039,15 @@ ui_draw_text_input :: (using text_input: *TextInput) { // draw_pos.y -= line.size.y; } + + if cursor_time < 0.5 { + log("rendering cursor at %", cursor_pos); + render_filled_rectangle(cursor_pos + v2(margin) + v2(border_size) + v2(padding), .{5.0, xx font.face.size.metrics.height >> 6}); + } else if cursor_time > 1.0 { + cursor_time = 0.0; + } + + cursor_time += dt; } ui_begin_container :: (s: string, gradient := false, colour_left := Vector4.{}, colour_right := Vector4.{}, max_x: s32 = -1, max_y: s32 = -1, flags: ContainerFlags = 0) -> bool { @@ -2296,5 +2327,47 @@ render_rectangle :: (pos: Vector2, size: Vector2, window_space: bool = true) { glDeleteVertexArrays(1, *vao); } +render_filled_rectangle :: (pos: Vector2, size: Vector2, window_space: bool = true) { + + positions: [4]Vector2 = Vector2.[ + .{pos.x + size.x, pos.y}, + .{pos.x, pos.y}, + .{pos.x + size.x, pos.y + size.y}, + .{pos.x, pos.y + size.y}, + ]; + + vao : GLuint; + glGenVertexArrays(1, *vao); + glBindVertexArray(vao); + + vbo : GLuint; + glGenBuffers(1, *vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, size_of(type_of(positions)), positions.data, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, size_of(Vector2), null); + + model : Matrix4 = identity_of(Matrix4); + view : Matrix4 = identity_of(Matrix4); + proj : Matrix4 = orthographic_gl(0.0, xx window_width, 0.0, xx window_height, -1.0, 1.0); + + use(*line_shader); + glBindVertexArray(vao); + + glUniformMatrix4fv(glGetUniformLocation(line_shader.id, "uni_model"), 1, GL_TRUE, cast(*float) *model); + glUniformMatrix4fv(glGetUniformLocation(line_shader.id, "uni_view"), 1, GL_TRUE, cast(*float) *view); + glUniformMatrix4fv(glGetUniformLocation(line_shader.id, "uni_proj"), 1, GL_TRUE, cast(*float) *proj); + + glUniform4f(glGetUniformLocation(line_shader.id, "uni_colour"), 1, 1, 1, 1); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, xx positions.count); + + glBindVertexArray(0); + + glDeleteBuffers(1, *vbo); + glDeleteVertexArrays(1, *vao); +} + #scope_file _frame : u64; diff --git a/ui.rad b/ui.rad index 72806a8..c387193 100644 --- a/ui.rad +++ b/ui.rad @@ -1,10 +1,9 @@ // raddbg 0.9.20 project file -recent_file: path: "../jai_test/j.jai" +recent_file: path: "src/text.jai" recent_file: path: "src/ui.jai" recent_file: path: "src/stb_textedit.jai" recent_file: path: "modules/kb_text_shape/kb_text_shape.h" -recent_file: path: "src/text.jai" recent_file: path: "modules/SDL3/src/SDL-release-3.2.16/src/events/sdl_keyboard.c" recent_file: path: "modules/SDL3/src/SDL-release-3.2.16/src/video/windows/SDL_windowsevents.c" recent_file: path: "src/main.jai" @@ -14,38 +13,21 @@ recent_file: path: "src/math/math.jai" recent_file: path: "../../../../jai/modules/runtime_support.jai" recent_file: path: "../../../../jai/modules/basic/module.jai" recent_file: path: "../../../../jai/modules/default_allocator/module.jai" -breakpoint: -{ - source_location: "src/text.jai:516:1" - hit_count: 0 - enabled: 0 -} -breakpoint: -{ - source_location: "src/ui.jai:935:1" - hit_count: 0 - enabled: 0 -} -breakpoint: -{ - source_location: "src/text.jai:944:1" - hit_count: 0 - enabled: 0 -} -breakpoint: -{ - source_location: "src/ui.jai:908:1" - hit_count: 0 - enabled: 0 -} target: { - executable: "../jai_test/j.exe" - working_directory: "../jai_test/" + executable: "bin/mexplore-debug.exe" + working_directory: bin enabled: 1 } breakpoint: { - source_location: "../jai_test/j.jai:44:1" - hit_count: 1 + source_location: "src/ui.jai:1014:1" + hit_count: 0 + enabled: 0 +} +breakpoint: +{ + source_location: "src/text.jai:281:1" + hit_count: 0 + enabled: 0 }