From 83f6378656396fb4d85d94c3713cb95c01cd2099 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 4 Mar 2022 12:26:03 -0600 Subject: [PATCH] better textbox support --- src/entity/editor.onyx | 83 +++++++++++++++++------------------------- src/gfx/ui.onyx | 34 ++++++++++++++++- src/main.onyx | 2 +- 3 files changed, 67 insertions(+), 52 deletions(-) diff --git a/src/entity/editor.onyx b/src/entity/editor.onyx index 288f0c2..9058033 100644 --- a/src/entity/editor.onyx +++ b/src/entity/editor.onyx @@ -379,7 +379,7 @@ editor_draw :: () { #local prepare_field_editor :: (v: any) { array.ensure_capacity(^field_buffer, 256); field_buffer.count = 256; - s := conv.format_va(field_buffer, "{}", .[v]); + s := conv.format_va(field_buffer, "{\"d}", .[v]); field_buffer.count = s.count; } @@ -393,64 +393,47 @@ editor_draw :: () { y += 32; font_print(editor_font, x, y, field_name); - switch v.type { - type_is(i32) { - font_print(editor_font, x, y + 32, "INT: {}\n", value); - if draw_textbox(.{ x, y + 64, w, 48 }, ^field_buffer) { - conv.parse_any(v.data, v.type, field_buffer); + info := type_info.get_type_info(v.type); + + switch info.kind { + case .Enum { + enum_info := cast(^type_info.Type_Info_Enum) info; + value: u64; + switch enum_info.backing_type { + case i8, u8 do value = cast(u64) *(cast(^u8) v.data); + case i16, u16 do value = cast(u64) *(cast(^u16) v.data); + case i32, u32 do value = cast(u64) *(cast(^u32) v.data); + case i64, u64 do value = cast(u64) *(cast(^u64) v.data); + case #default do assert(false, "Bad enum backing type"); } - } - type_is(f32) { - font_print(editor_font, x, y + 32, "FLOAT: {}\n", value); - if draw_textbox(.{ x, y + 64, w, 48 }, ^field_buffer) { - conv.parse_any(v.data, v.type, field_buffer); - } - } - - case #default { - info := type_info.get_type_info(v.type); - - if info.kind == .Enum { - enum_info := cast(^type_info.Type_Info_Enum) info; - value: u64; - switch enum_info.backing_type { - case i8, u8 do value = cast(u64) *(cast(^u8) v.data); - case i16, u16 do value = cast(u64) *(cast(^u16) v.data); - case i32, u32 do value = cast(u64) *(cast(^u32) v.data); - case i64, u64 do value = cast(u64) *(cast(^u64) v.data); - case #default do assert(false, "Bad enum backing type"); - } + if enum_info.is_flags { + for^ enum_info.members { + y += 20; + checkbox_value := (value & it.value) != 0; + if draw_checkbox(.{x, y, w, 20}, ^checkbox_value, it.name, increment=~~y) { + switch enum_info.backing_type { + case i8, u8 do set_value(u8); + case i16, u16 do set_value(u16); + case i32, u32 do set_value(u32); + case i64, u64 do set_value(u64); + } - if enum_info.is_flags { - for^ enum_info.members { - y += 20; - checkbox_value := (value & it.value) != 0; - if draw_checkbox(.{x, y, w, 20}, ^checkbox_value, it.name, increment=~~y) { - switch enum_info.backing_type { - case i8, u8 do set_value(u8); - case i16, u16 do set_value(u16); - case i32, u32 do set_value(u32); - case i64, u64 do set_value(u64); - } - - set_value :: macro (T: type_expr) { - if !checkbox_value do *cast(^T) v.data = ~~(value & ~it.value); - else do *cast(^T) v.data = ~~(value | it.value); - } + set_value :: macro (T: type_expr) { + if !checkbox_value do *cast(^T) v.data = ~~(value & ~it.value); + else do *cast(^T) v.data = ~~(value | it.value); } } - } else { - @TODO // Add radio buttons for enum type. } + } else { + @TODO // Add radio buttons for enum type. } } - } - type_is :: macro (T: type_expr, body: Code) { - case T { - value := *cast(^T) v.data; - #insert body; + case #default { + if draw_textbox(.{ x, y + 64, w, 48 }, ^field_buffer) { + conv.parse_any(v.data, v.type, field_buffer); + } } } } diff --git a/src/gfx/ui.onyx b/src/gfx/ui.onyx index 20f9dc8..839b198 100644 --- a/src/gfx/ui.onyx +++ b/src/gfx/ui.onyx @@ -189,12 +189,17 @@ draw_textbox :: (use r: Rect, text_buffer: ^[..] u8, placeholder := null_str, th if is_button_down(GLFW_MOUSE_BUTTON_LEFT) && contains { textbox_editing_state.cursor_animation = 1.0f; - // textbox_editing_state.cursor_position = get_cursor_position(text_buffer, text_x, text_y, theme.font_size, ~~mx, ~~my); + textbox_editing_state.cursor_position = screen_to_cursor(^font, text_x, text_y, text, ~~mx, ~~my); } keys := input_get_keys_this_frame(); for key: iter.as_iterator(^keys) { switch key.key { + case GLFW_KEY_ESCAPE { + set_active_item(0); + input_release_keys(); + } + case GLFW_KEY_LEFT do textbox_editing_state.cursor_position -= 1; case GLFW_KEY_RIGHT do textbox_editing_state.cursor_position += 1; case GLFW_KEY_END do textbox_editing_state.cursor_position = text_buffer.count; @@ -258,6 +263,11 @@ draw_textbox :: (use r: Rect, text_buffer: ^[..] u8, placeholder := null_str, th // Draw the cursor on textboxes if is_active_item(hash) { cursor := cursor_to_screen(^font, x + border_width, y + border_width, text, textbox_editing_state.cursor_position); + right_edge := x + w - border_width * 2; + if cursor.x > right_edge { + text_x -= cursor.x - right_edge; + cursor.x = right_edge - 2; + } immediate_set_color(.{0,0,0}); immediate_rectangle(cursor.x, cursor.y + 2, 2, h - border_width * 2 - 4); } @@ -285,6 +295,28 @@ draw_textbox :: (use r: Rect, text_buffer: ^[..] u8, placeholder := null_str, th return .{ cx, cy }; } + + screen_to_cursor :: (font: ^Font, x, y: f32, text: str, mouse_x, mouse_y: f32) -> i32 { + mx := mouse_x - x; + my := mouse_y - y; + + cx := 0.0f; + cy := 0.0f; + for pos: text.count { + if text[pos] == #char "\n" { + cx = 0; + cy += font.em + 2; + } else { + cx += font_get_char_width(*font, text[pos]); + } + + if cy >= my && cx >= mx { + return pos; + } + } + + return text.count; + } } diff --git a/src/main.onyx b/src/main.onyx index c3c6c20..882d3a2 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -46,7 +46,7 @@ deinit :: () { update :: (dt: f32) { input_update(); - if is_key_down(GLFW_KEY_ESCAPE) { + if is_key_just_up(GLFW_KEY_ESCAPE) { glfwSetWindowShouldClose(window, true); return; } -- 2.25.1