correct cursor position

This commit is contained in:
Vicente Ferrari Smith 2025-07-27 19:47:16 +02:00
parent 89727b9bc1
commit e4df2e1551
13 changed files with 153 additions and 41 deletions

View File

@ -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;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;

42
ui.rad
View File

@ -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
}