#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;
}
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);
+ }
}
}
}
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;
// 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);
}
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;
+ }
}