text editing

This commit is contained in:
Vicente Ferrari Smith 2025-07-25 08:21:52 +02:00
parent 3520906f28
commit 89727b9bc1
14 changed files with 139 additions and 422 deletions

View File

@ -6,7 +6,7 @@
NAME :: "mexplore"; NAME :: "mexplore";
VERSION :: "0.1"; VERSION :: "0.1";
JAI_VERSION :: "beta 0.2.014, built on 24 May 2025"; JAI_VERSION :: "beta 0.2.014, built on 24 May 2025";
RELEASE_DATE :: "16 July 2025, 20:47:28"; RELEASE_DATE :: "19 July 2025, 16:47:42";
GIT_BRANCH :: "main"; GIT_BRANCH :: "main";
GIT_REVISION :: "68096796dc50c0bfe4e9d687ce4e9563e0bbf4bb"; GIT_REVISION :: "3520906f2803cf5baf5d52dcb05daf94d8edadd1";
DEBUG :: true; 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.

Binary file not shown.

View File

@ -77,9 +77,15 @@ main :: () {
running = false; running = false;
case SDL_EVENT_KEY_DOWN; case SDL_EVENT_KEY_DOWN;
if event.key.key == SDLK_ESCAPE if event.key.key == {
case SDLK_ESCAPE;
running = false; running = false;
case SDLK_RETURN;
log("pressing enter");
input_state.last_char = STB_TEXTEDIT_NEWLINE;
}
case SDL_EVENT_MOUSE_MOTION; case SDL_EVENT_MOUSE_MOTION;
transition.motion_delta = .{event.motion.xrel, event.motion.yrel}; transition.motion_delta = .{event.motion.xrel, event.motion.yrel};
@ -152,7 +158,7 @@ main :: () {
ui_context.sizing_x = .FIT; ui_context.sizing_x = .FIT;
ui_context.sizing_y = .FIT; ui_context.sizing_y = .FIT;
//ui_label("Hello, World! How's it going?"); //ui_label("Hello, World! How's it going?");
ui_label("Hello, World!"); //ui_label("Hello, World!");
ui_text_input("Name"); ui_text_input("Name");
// ui_begin_container("Picture-Name-Settings"); // ui_begin_container("Picture-Name-Settings");
// { // {

View File

@ -283,7 +283,7 @@ STB_TEXTEDIT_STRINGLEN :: (obj: *STB_TEXTEDIT_STRING) -> s32 {
} }
STB_TEXTEDIT_KEYTOTEXT :: (k: STB_TEXTEDIT_KEYTYPE) -> s32 #expand { STB_TEXTEDIT_KEYTOTEXT :: (k: STB_TEXTEDIT_KEYTYPE) -> s32 #expand {
return ifx k >= 32 then k else -1; return ifx k >= 0 then k else -1;
} }
STB_TEXTEDIT_DELETECHARS :: (obj: *STB_TEXTEDIT_STRING, i: s32, n: s32) { STB_TEXTEDIT_DELETECHARS :: (obj: *STB_TEXTEDIT_STRING, i: s32, n: s32) {
@ -321,33 +321,31 @@ STB_TEXTEDIT_INSERTCHARS :: (obj: *STB_TEXTEDIT_STRING, i: s32, c: *STB_TEXTEDIT
} }
STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s32) { STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s32) {
// text : *u8 = obj.text.data;
// line_start : *u8 = text + n;
// len := obj.text.count - (line_start - text);
// text_utf32 : [..]u32;
// defer array_free(text_utf32);
// StringAt : u64;
// while StringAt < xx len {
// Decode : kbts_decode = kbts_DecodeUtf8(line_start, xx len - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if Decode.Valid {
// array_add(*text_utf32, Decode.Codepoint);
// }
// }
//size, max_descent, read := SegmentText(obj.font, text_utf32.data, xx text_utf32.count);
idx : s32; idx : s32;
while word := n + idx < obj.text.count && row.x1 < obj.max_size.x { if n + idx < obj.text.count && row.x1 < obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
size, max_descent, read := next_word_size(obj.font, obj.text, n + idx, obj.max_size.x); size, max_descent, read := next_line_size(obj.font, obj.text, n + idx, obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding));
if row.x1 + size.x > obj.max_size.x { if row.x1 + size.x > obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
while word := n + idx < obj.text.count && row.x1 < obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
size, max_descent, read := next_word_size(obj.font, obj.text, n + idx, obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding));
if row.x1 + size.x > obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
while grapheme := idx < obj.text.count { while grapheme := idx < obj.text.count {
size, max_descent, read := next_grapheme_size(obj.font, obj.text, n + idx, obj.max_size.x); size, max_descent, read := next_grapheme_size(obj.font, obj.text, n + idx, obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding));
if row.x1 + size.x > obj.max_size.x { if row.x1 + size.x > obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
break word; //break word;
return;
}
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;
idx += read;
}
} }
row.x1 += size.x; row.x1 += size.x;
@ -368,153 +366,6 @@ STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s
} }
row.x0 = 0.0; row.x0 = 0.0;
// words := split(.{len, line_start}, " ");
// for *word : words {
// if word.* != "" && word.data - line_start + word.count < len {
// if text[word.data - line_start + len] == " " {
// word.count += 1;
// }
// }
// }
//total_size : Vector2;
//lines : [..]Line;
// if !text {
// //return .{}, 0.0, 0.0, lines;
// }
// if words.count == 0 {
// return .{}, 0.0, 0.0, lines;
// }
//line : Line;
// for word : words {
// started_a_line : bool;
// if line.text.count == 0 {
// line.text.data = word.data;
// line.text.count = word.count;
// started_a_line = true;
// }
// buf : *hb_buffer_t = hb_buffer_create();
// hb_buffer_add_utf8(buf, word.data, xx word.count, 0, -1);
// hb_buffer_set_direction(buf, hb_direction_t.LTR);
// hb_buffer_set_script(buf, hb_script_t.HB_SCRIPT_LATIN);
// hb_buffer_set_language(buf, hb_language_from_string("en", -1));
// features : [1]hb_feature_t;
// features[0].tag = HB_TAG(#char "c", #char "a", #char "l", #char "t");
// features[0].value = 1;
// features[0].start = HB_FEATURE_GLOBAL_START;
// features[0].end = HB_FEATURE_GLOBAL_END;
// hb_shape(obj.font.hb, buf, features.data, features.count);
// glyph_count_u : u32;
// glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count_u);
// glyph_pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count_u);
// glyph_count : s32 = xx glyph_count_u;
// word_size : Vector2;
// for i : 0..glyph_count - 1 {
// glyphid : hb_codepoint_t = glyph_info[i].codepoint;
// x_offset : hb_position_t = glyph_pos[i].x_offset;
// y_offset : hb_position_t = glyph_pos[i].y_offset;
// x_advance : hb_position_t = glyph_pos[i].x_advance;
// y_advance : hb_position_t = glyph_pos[i].y_advance;
// glyph : *Glyph = table_find_pointer(*obj.font.glyphs, glyphid);
// if glyph {
// word_size.y = max(word_size.y, xx (glyph.height + glyph.descent));
// word_size.x += x_advance / 64.0;
// line.max_descent = max(line.max_descent, cast(float) glyph.descent);
// line.max_ascent = max(line.max_ascent, cast(float) glyph.ascent);
// }
// }
// if !started_a_line {
// line.text.count += word.count;
// }
// if obj.max_size.x > 0.0 {
// if line.size.x + word_size.x > obj.max_size.x {
// line.size.x = obj.max_size.x;
// line.size.y = max(line.size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// array_add(*lines, line);
// line = .{};
// } else {
// line.size.y = max(total_size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// line.size.x += word_size.x;
// // } else {
// // line.text.data = word.data;
// // line.text.count = word.count;
// // }
// }
// } else if obj.max_size.x == 0.0 {
// line.size.y = max(total_size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// line.size.x += word_size.x;
// // if include_descent
// // size.y = max_ascent + max_descent;
// }
// hb_buffer_destroy(buf);
// }
// if line.text.count > 0 {
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// array_add(*lines, line);
// line = .{};
// }
// for line : lines {
// total_size.x = max(total_size.x, line.size.x);
// total_size.y += line.size.y;
// }
// // determine how many characters to shape (until newline or wrap)
// // for simplicity, shape a chunk of ~256 characters or to newline
// p := line_start;
// len : s32 = 0;
// while p.* && p.* != #char "\n" && len < 256 {
// p += 1;
// len += 1;
// }
// // shape the text
// buf : *hb_buffer_t = hb_buffer_create();
// hb_buffer_add_utf8(buf, line_start, len, 0, len);
// hb_buffer_guess_segment_properties(buf);
// hb_shape(hb_font, buf, NULL, 0);
// glyph_count : u32;
// glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count);
// pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count);
// // iterate through glyphs, accumulate width
// x : float = 0.0;
// num_chars : s32 = 0;
// for i : 0..glyph_count - 1 {
// x += pos[i].x_advance / 64.0; // HarfBuzz uses 26.6 fixed-point
// num_chars += 1;
// // optional: if you have a max line width, break here
// }
// 4. Use FreeType or your line layout logic for line height
// line_height : float = obj->font->height; // or extract from FT_Size_Metrics
// ymin : float = -obj->font->ascent;
// ymax : float = obj->font->descent;
//hb_buffer_destroy(buf);
} }
STB_TEXTEDIT_GETWIDTH :: (obj: *STB_TEXTEDIT_STRING, n: s32, i: s32) -> float { STB_TEXTEDIT_GETWIDTH :: (obj: *STB_TEXTEDIT_STRING, n: s32, i: s32) -> float {

View File

@ -85,7 +85,6 @@ init_font :: (using font: *Font, filename: string, size: s32) {
charcode = FT_Get_First_Char(face, *gindex); charcode = FT_Get_First_Char(face, *gindex);
while gindex != 0 { while gindex != 0 {
log("Reading index: % - Charcode: %", gindex, charcode);
error = FT_Load_Glyph(face, gindex, FT_LOAD_RENDER); error = FT_Load_Glyph(face, gindex, FT_LOAD_RENDER);
if error if error
log("%", to_string(FT_Error_String(error))); log("%", to_string(FT_Error_String(error)));
@ -280,9 +279,9 @@ render_text :: (font: *Font, text: []u32, pos: Vector2, size: Vector2, window_sp
glyph : *Glyph = table_find_pointer(*font.glyphs, kglyph.Id); glyph : *Glyph = table_find_pointer(*font.glyphs, kglyph.Id);
if !glyph { if !glyph {
log("[Error] Panic! Didn't find the glyph!"); //log("[Error] Panic! Didn't find the glyph!");
for font.glyphs GlyphIndex += 1;
log("%", it); continue;
} }
v0 : Vector2; v0 : Vector2;
@ -649,23 +648,6 @@ next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0)
Codepoints : *u32 = textp + n; Codepoints : *u32 = textp + n;
CodepointCount : u64 = xx (text.count - (Codepoints - textp)); CodepointCount : u64 = xx (text.count - (Codepoints - textp));
// text_utf32 : [..]u32;
// defer array_free(text_utf32);
// StringAt : u64;
// while StringAt < xx len {
// Decode : kbts_decode = kbts_DecodeUtf8(line_start + StringAt, xx len - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if Decode.Valid {
// array_add(*text_utf32, Decode.Codepoint);
// }
// }
//size, max_descent, read := SegmentText(font, line_start, len);
//return size, max_descent, read;
Cursor : kbts_cursor; Cursor : kbts_cursor;
Direction : kbts_direction = .NONE; Direction : kbts_direction = .NONE;
Script : kbts_script = .DONT_KNOW; Script : kbts_script = .DONT_KNOW;
@ -673,29 +655,12 @@ next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0)
BreakState : kbts_break_state; BreakState : kbts_break_state;
kbts_BeginBreak(*BreakState, .NONE, .NORMAL); kbts_BeginBreak(*BreakState, .NONE, .NORMAL);
// size : Vector2;
// max_descent : float;
CodepointIndex : u64; CodepointIndex : u64;
while CodepointIndex < xx CodepointCount { while CodepointIndex < xx CodepointCount {
kbts_BreakAddCodepoint(*BreakState, Codepoints[CodepointIndex], 1, xx ((CodepointIndex + 1) == xx CodepointCount)); kbts_BreakAddCodepoint(*BreakState, Codepoints[CodepointIndex], 1, xx ((CodepointIndex + 1) == xx CodepointCount));
Break : kbts_break; Break : kbts_break;
while kbts_Break(*BreakState, *Break) { while kbts_Break(*BreakState, *Break) {
// if (Break.Position > RunStart) && (Break.Flags & (.DIRECTION | .SCRIPT | .LINE_HARD)) {
// RunLength : u64 = Break.Position - RunStart;
// size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
// return size, max_descent, Break.Position;
// }
// if (Break.Position > RunStart) && (Break.Flags & (.DIRECTION | .SCRIPT | .LINE_HARD)) {
// RunLength : u64 = Break.Position - RunStart;
// size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
// return size, max_descent, xx CodepointIndex;
// }
if Break.Flags & .DIRECTION { if Break.Flags & .DIRECTION {
Direction = Break.Direction; Direction = Break.Direction;
if(!Cursor.Direction) Cursor = kbts_Cursor(BreakState.MainDirection); if(!Cursor.Direction) Cursor = kbts_Cursor(BreakState.MainDirection);
@ -709,182 +674,14 @@ next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0)
RunLength : u64 = Break.Position - RunStart; RunLength : u64 = Break.Position - RunStart;
size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script); size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
//if max_width > 0.0 && size.x + word_size.x > max_width {
return size, max_descent, xx Break.Position; return size, max_descent, xx Break.Position;
//}
// size.x += word_size.x;
// size.y = max(word_size.y);
// max_descent = max(max_descent, word_max_descent);
} }
// if (Break.Position > RunStart) && Break.Flags & .LINE_HARD {
// RunLength : u64 = Break.Position - RunStart;
// word_size, word_max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
// return size, max_descent, Break.Position;
// }
} }
CodepointIndex += 1; CodepointIndex += 1;
} }
return .{}, 0, 0; return .{}, 0, 0;
// words := split(text, " ");
// for *word : words {
// if word.* != "" && word.data - text.data + word.count < text.count {
// if text[word.data - text.data + word.count] == " " {
// word.count += 1;
// }
// }
// }
//total_size : Vector2;
// lines : [..]Line;
// if !text {
// return .{}, 0.0, 0.0, lines;
// }
// if words.count == 0 {
// return .{}, 0.0, 0.0, lines;
// }
// text_utf32 : [..]u32;
// defer array_free(text_utf32);
// StringAt : u64;
// while StringAt < text.count {
// Decode : kbts_decode = kbts_DecodeUtf8(text.data, text.count - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if Decode.Valid {
// array_add(*text_utf32, Decode.Codepoint);
// }
// }
// String : *u8 = text_utf32.data;
// Length : u64 = text_utf32.count;
// // Make some glyphs
// kbts_glyph *Glyphs = cast(*kbts_glyph, alloc(size_of(kbts_glyph) * Length));
// GlyphCount : u32 = 0;
// Script : kbts_script = KBTS_SCRIPT_DONT_KNOW;
// Direction : kbts_direction = KBTS_DIRECTION_NONE;
// StringAt : u64;
// while StringAt < Length {
// Decode : kbts_decode = kbts_DecodeUtf8(String, Length - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if(Decode.Valid) {
// Glyph : kbts_glyph = kbts_CodepointToGlyph(*Font, Decode.Codepoint);
// // Easy script inference for simple cases. (This is similar to hb_buffer_guess_segment_properties.)
// // If you have already segmented String with our API, you already have a script!
// // So no need to pass it in that case.
// // Only use this as a shorthand, when you are pretty sure String is a single
// // script.
// kbts_InferScript(*Direction, *Script, Glyph.Script);
// Glyphs[GlyphCount] = Glyph;
// GlyphCount += 1;
// }
// }
// void SegmentText(uint32_t *Codepoints, size_t CodepointCount)
// line : Line;
// for word : words {
// started_a_line : bool;
// if line.text.count == 0 {
// line.text.data = word.data;
// line.text.count = word.count;
// started_a_line = true;
// }
// buf : *hb_buffer_t = hb_buffer_create();
// hb_buffer_add_utf8(buf, word.data, xx word.count, 0, -1);
// hb_buffer_set_direction(buf, hb_direction_t.LTR);
// hb_buffer_set_script(buf, hb_script_t.HB_SCRIPT_LATIN);
// hb_buffer_set_language(buf, hb_language_from_string("en", -1));
// features : [1]hb_feature_t;
// features[0].tag = HB_TAG(#char "c", #char "a", #char "l", #char "t");
// features[0].value = 1;
// features[0].start = HB_FEATURE_GLOBAL_START;
// features[0].end = HB_FEATURE_GLOBAL_END;
// hb_shape(font.hb, buf, features.data, features.count);
// glyph_count_u : u32;
// glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count_u);
// glyph_pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count_u);
// glyph_count : s32 = xx glyph_count_u;
// word_size : Vector2;
// for i : 0..glyph_count - 1 {
// glyphid : hb_codepoint_t = glyph_info[i].codepoint;
// x_offset : hb_position_t = glyph_pos[i].x_offset;
// y_offset : hb_position_t = glyph_pos[i].y_offset;
// x_advance : hb_position_t = glyph_pos[i].x_advance;
// y_advance : hb_position_t = glyph_pos[i].y_advance;
// glyph : *Glyph = table_find_pointer(*font.glyphs, glyphid);
// if glyph {
// word_size.y = max(word_size.y, xx (glyph.height + glyph.descent));
// word_size.x += x_advance / 64.0;
// line.max_descent = max(line.max_descent, cast(float) glyph.descent);
// line.max_ascent = max(line.max_ascent, cast(float) glyph.ascent);
// }
// }
// if !started_a_line {
// line.text.count += word.count;
// }
// if max_width > 0.0 {
// if line.size.x + word_size.x > max_width {
// line.size.x = max_width;
// line.size.y = max(line.size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// array_add(*lines, line);
// line = .{};
// } else {
// line.size.y = max(total_size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// line.size.x += word_size.x;
// // } else {
// // line.text.data = word.data;
// // line.text.count = word.count;
// // }
// }
// } else if max_width == 0.0 {
// line.size.y = max(total_size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// line.size.x += word_size.x;
// // if include_descent
// // size.y = max_ascent + max_descent;
// }
// hb_buffer_destroy(buf);
// }
// if line.text.count > 0 {
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// array_add(*lines, line);
// line = .{};
// }
// for line : lines {
// total_size.x = max(total_size.x, line.size.x);
// total_size.y += line.size.y;
// }
//return total_size, 0, 0;
} }
next_word_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) -> Vector2, float, s32 { next_word_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) -> Vector2, float, s32 {
@ -1065,6 +862,48 @@ next_word_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) ->
//return total_size, 0, 0; //return total_size, 0, 0;
} }
next_line_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) -> Vector2, float, s32 {
textp : *u32 = text.data;
Codepoints : *u32 = textp + n;
CodepointCount : u64 = xx (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);
CodepointIndex : u64;
while CodepointIndex < xx CodepointCount {
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 & .LINE_HARD) {
RunLength : u64 = Break.Position - RunStart;
size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
return size, max_descent, xx Break.Position;
}
}
CodepointIndex += 1;
}
return .{}, 0, 0;
}
make_texture_from_data :: (data: *u8, width: s32, height: s32) -> Texture { make_texture_from_data :: (data: *u8, width: s32, height: s32) -> Texture {
if !data { if !data {
log("[Error] Could not load the texture."); log("[Error] Could not load the texture.");
@ -1102,7 +941,7 @@ PRIMITIVE_TYPE :: enum u8 {
render_batch :: (primitive_type: PRIMITIVE_TYPE, vertices: []$T, shader: *_Shader, texture: *Texture, view: Matrix4, proj: Matrix4) { render_batch :: (primitive_type: PRIMITIVE_TYPE, vertices: []$T, shader: *_Shader, texture: *Texture, view: Matrix4, proj: Matrix4) {
if !vertices { if !vertices {
log("[Error] The batch has no vertices."); //log("[Error] The batch has no vertices.");
return; return;
} }

View File

@ -899,39 +899,50 @@ ui_text_input :: (s: string, font_colour := Vector4.{1, 1, 1, 1}) {
//text_input.frame = get_texture("panel-border-000"); //text_input.frame = get_texture("panel-border-000");
text_input.font = ui_context.font; text_input.font = ui_context.font;
stb_textedit_initialize_state(*text_input.textedit_state, 1); stb_textedit_initialize_state(*text_input.textedit_state, 0);
} }
ui_append_to_parent(text_input); ui_append_to_parent(text_input);
if text_input.active && input_state.last_char > 0 { if text_input.active && input_state.last_char > 0 {
stb_textedit_key(text_input, *text_input.textedit_state, input_state.last_char); stb_textedit_key(text_input, *text_input.textedit_state, input_state.last_char);
log("adding char %", input_state.last_char);
// log("Adding % to builder.", to_string(*input_state.last_char, 1)); // log("Adding % to builder.", to_string(*input_state.last_char, 1));
// append(*text_input.input_buffer, input_state.last_char); // append(*text_input.input_buffer, input_state.last_char);
} }
text_size : Vector2; text_size : Vector2;
text_size.y = xx text_input.font.face.size.metrics.height >> 6; //text_size.y = xx text_input.font.face.size.metrics.height >> 6;
//str := builder_to_string(*text_input.input_buffer, 0, false); //str := builder_to_string(*text_input.input_buffer, 0, false);
// if str.count > 0 { // if str.count > 0 {
// defer free(str); // defer free(str);
// textsize = Vector2.{xx Simp.prepare_text(text_input.font, str), xx text_input.font.character_height}; // textsize = Vector2.{xx Simp.prepare_text(text_input.font, str), xx text_input.font.character_height};
// } // }
max_descent : float; max_descent : float;
idx : s32; // idx : s32;
while idx < text_input.text.count { // while idx < text_input.text.count {
word_size, word_descent, read := next_word_size(text_input.font, text_input.text, idx, 0.0); // word_size, word_descent, read := next_word_size(text_input.font, text_input.text, idx, 0.0);
text_size.x += word_size.x; // text_size.x += word_size.x;
text_size.y = max(text_size.y, word_size.y); // text_size.y = max(text_size.y, word_size.y);
max_descent = max(max_descent, word_descent); // max_descent = max(max_descent, word_descent);
idx += read; // idx += read;
// }
i : s32;
while i < text_input.text.count {
row : StbTexteditRow;
STB_TEXTEDIT_LAYOUTROW(*row, text_input, i);
text_size.x = max(text_size.x, row.x1);
text_size.y += text_input.font.face.size.metrics.height >> 6;
i += xx row.num_chars;
} }
text_input.min_size = v2(2 * text_input.margin + 2 * text_input.border_size + 2 * text_input.padding) + text_size; text_input.min_size = v2(2 * text_input.margin + 2 * text_input.border_size + 2 * text_input.padding) + max(text_size, .{xx text_input.font.face.size.metrics.max_advance >> 6, xx text_input.font.face.size.metrics.height >> 6});
text_input.size = text_input.min_size; text_input.size = text_input.min_size;
text_input.size = max(text_input.size, .{40.0, 20.0});
text_input.max_size = text_input.size; text_input.max_size = text_input.size;
text_input.anchor = ui_context.anchor; text_input.anchor = ui_context.anchor;
@ -984,7 +995,7 @@ ui_draw_text_input :: (using text_input: *TextInput) {
if text_input.text.count > 0 { if text_input.text.count > 0 {
//midline : Vector2 = pos + Vector2.{cast(float, margin + border_size + padding), xx (size.y / 2.0)}; //midline : Vector2 = pos + Vector2.{cast(float, margin + border_size + padding), xx (size.y / 2.0)};
draw_pos : Vector2 = pos + v2(margin); 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; i : s32;

60
ui.rad
View File

@ -1,41 +1,51 @@
// raddbg 0.9.20 project file // raddbg 0.9.20 project file
recent_file: path: "src/text.jai" recent_file: path: "../jai_test/j.jai"
recent_file: path: "src/ui.jai" recent_file: path: "src/ui.jai"
recent_file: path: "src/stb_textedit.jai" recent_file: path: "src/stb_textedit.jai"
recent_file: path: "../../../../jai/modules/runtime_support.jai"
recent_file: path: "modules/kb_text_shape/kb_text_shape.h" 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" recent_file: path: "src/main.jai"
recent_file: path: "../../../../jai/modules/math/module.jai"
recent_file: path: "../../../../jai/modules/basic/array.jai" recent_file: path: "../../../../jai/modules/basic/array.jai"
recent_file: path: "../../../../jai/modules/math/module.jai"
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/basic/module.jai"
recent_file: path: "../../../../jai/modules/default_allocator/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: target:
{ {
executable: "bin/mexplore-debug.exe" executable: "../jai_test/j.exe"
working_directory: bin working_directory: "../jai_test/"
enabled: 1 enabled: 1
} }
breakpoint: breakpoint:
{ {
source_location: "src/ui.jai:1588:1" source_location: "../jai_test/j.jai:44:1"
hit_count: 0 hit_count: 1
enabled: 0
}
breakpoint:
{
source_location: "src/ui.jai:262:1"
hit_count: 0
enabled: 0
}
breakpoint:
{
source_location: "src/stb_textedit.jai:346:1"
hit_count: 0
enabled: 0
}
breakpoint:
{
source_location: "src/text.jai:282:1"
hit_count: 8
} }