correct cursor position
This commit is contained in:
parent
89727b9bc1
commit
e4df2e1551
@ -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.
12
src/main.jai
12
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;
|
||||
|
||||
@ -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
|
||||
|
||||
16
src/text.jai
16
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);
|
||||
|
||||
75
src/ui.jai
75
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;
|
||||
|
||||
42
ui.rad
42
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
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user