UI fixes and new layout features
This commit is contained in:
77
ui/ui.jai
77
ui/ui.jai
@@ -5,7 +5,7 @@ MAX_WINDOWS :: 128;
|
||||
SCROLL_SPEED :: 5;
|
||||
|
||||
WINDOW_TITLE_BAR_HEIGHT :: 20.0;
|
||||
WINDOW_BORDER_WIDTH :: 3.0;
|
||||
WINDOW_BORDER_WIDTH :: 3;
|
||||
|
||||
UI_Box_Flags :: enum_flags u32 {
|
||||
NONE :: 0;
|
||||
@@ -55,7 +55,8 @@ UI_Box :: struct {
|
||||
hash: u32;
|
||||
last_used_frame_index: u64;
|
||||
|
||||
root_for_window: *UI_Window;
|
||||
window: *UI_Window;
|
||||
root_in_window: bool;
|
||||
parent: *UI_Box;
|
||||
first_child: *UI_Box;
|
||||
last_child: *UI_Box;
|
||||
@@ -165,6 +166,7 @@ UI_State :: struct {
|
||||
|
||||
last_box: *UI_Box;
|
||||
|
||||
mouse_over_window: bool;
|
||||
parent_stack: Stack(*UI_Box);
|
||||
|
||||
allocator: Allocator;
|
||||
@@ -254,7 +256,6 @@ ui_box_make :: (flags: UI_Box_Flags, hash: u32) -> *UI_Box {
|
||||
actual_hash += ui_state.current_window.hash + actual_hash;
|
||||
}
|
||||
|
||||
|
||||
box := get_ui_box_or_create_new(actual_hash);
|
||||
box.last_used_frame_index = ui_state.frame_index;
|
||||
box.first_child = null;
|
||||
@@ -264,13 +265,16 @@ ui_box_make :: (flags: UI_Box_Flags, hash: u32) -> *UI_Box {
|
||||
box.num_children = 0;
|
||||
box.flags = flags;
|
||||
box.parent = null;
|
||||
box.root_for_window = null;
|
||||
box.window = null;
|
||||
box.root_in_window = false;
|
||||
|
||||
if ui_state.current_window && parent == null {
|
||||
array_add(*ui_state.current_window.boxes, box);
|
||||
box.root_for_window = ui_state.current_window;
|
||||
box.root_in_window = true;
|
||||
}
|
||||
|
||||
box.window = ui_state.current_window;
|
||||
|
||||
// Set the links
|
||||
box.parent = parent;
|
||||
if box.parent != null {
|
||||
@@ -345,7 +349,7 @@ ui_init :: () {
|
||||
|
||||
ui_state.sampler = create_sampler(engine.renderer);
|
||||
//ui_state.fonts.regular = create_font(engine.renderer, "../assets/fonts/roboto/Roboto-Regular.ttf", 32);
|
||||
ui_state.fonts.regular = create_font(engine.renderer, "../assets/fonts/Inconsolata-Regular.ttf", 18);
|
||||
ui_state.fonts.regular = create_font(engine.renderer, "../assets/fonts/Inconsolata-Regular.ttf", 14);
|
||||
ui_state.fonts.button = create_font(engine.renderer, "../assets/fonts/roboto/Roboto-Regular.ttf", 14);
|
||||
|
||||
// ui_rect
|
||||
@@ -504,8 +508,8 @@ ui_figure_out_sizes :: () {
|
||||
if box.semantic_size[0].size_kind == .PCT {
|
||||
if box.parent != null {
|
||||
box.size.x = box.parent.size.x * box.semantic_size[0].value - (box.parent.padding_left + box.parent.padding_right);
|
||||
} else if box.root_for_window != null {
|
||||
box.size.x = cast(float)box.root_for_window.size.x * box.semantic_size[0].value - (WINDOW_BORDER_WIDTH);
|
||||
} else if box.root_in_window {
|
||||
box.size.x = cast(float)box.window.size.x * box.semantic_size[0].value - (cast(float)WINDOW_BORDER_WIDTH);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -513,8 +517,8 @@ ui_figure_out_sizes :: () {
|
||||
if box.semantic_size[1].size_kind == .PCT {
|
||||
if box.parent != null {
|
||||
box.size.y = box.parent.size.y * box.semantic_size[1].value - (box.parent.padding_top + box.parent.padding_bottom);
|
||||
} else if box.root_for_window != null {
|
||||
box.size.y = cast(float)box.root_for_window.size.y * box.semantic_size[0].value - (WINDOW_BORDER_WIDTH);
|
||||
} else if box.root_in_window {
|
||||
box.size.y = cast(float)box.window.size.y * box.semantic_size[0].value - (cast(float)WINDOW_BORDER_WIDTH);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -566,10 +570,10 @@ ui_figure_out_sizes :: () {
|
||||
// Find final positions
|
||||
for *box : ui_state.boxes {
|
||||
if box.parent == null {
|
||||
if box.root_for_window {
|
||||
window := box.root_for_window;
|
||||
box.rect.x = xx (window.actual_position.x + window.scroll_offset.x) + WINDOW_BORDER_WIDTH;
|
||||
box.rect.y = xx (window.actual_position.y + window.scroll_offset.y) + WINDOW_BORDER_WIDTH + WINDOW_TITLE_BAR_HEIGHT;
|
||||
if box.root_in_window {
|
||||
window := box.window;
|
||||
box.rect.x = xx (window.actual_position.x + window.scroll_offset.x) + cast(float)WINDOW_BORDER_WIDTH;
|
||||
box.rect.y = xx (window.actual_position.y + window.scroll_offset.y) + cast(float)WINDOW_BORDER_WIDTH + WINDOW_TITLE_BAR_HEIGHT;
|
||||
} else {
|
||||
box.rect.x = 0.0;
|
||||
box.rect.y = 0.0;
|
||||
@@ -762,6 +766,8 @@ get_rect_instance_buffer :: () -> *Instanced_Rects_Data {
|
||||
ui_render :: () {
|
||||
// Draw each window separately
|
||||
for window: ui_state.windows {
|
||||
if window.last_used_frame_index != ui_state.frame_index continue;
|
||||
|
||||
// Draw outer rect + border of window
|
||||
title_bar_buffer_data := get_rect_instance_buffer();
|
||||
inv_w := 1.0 / cast(float)engine.renderer.render_target_width;
|
||||
@@ -814,7 +820,7 @@ ui_render :: () {
|
||||
{
|
||||
if window.title.count > 0 {
|
||||
font_handle := ui_state.fonts.regular;
|
||||
x : float = (xx window.actual_position.x + WINDOW_BORDER_WIDTH + 2);
|
||||
x : float = cast(float)(xx window.actual_position.x + cast(u32)WINDOW_BORDER_WIDTH + 2);
|
||||
y : float = (cast(float)engine.renderer.render_target_height - (window.actual_position.y + WINDOW_BORDER_WIDTH + 2.0));
|
||||
|
||||
text_size := get_text_size(engine.renderer, window.title, font_handle);
|
||||
@@ -830,10 +836,10 @@ ui_render :: () {
|
||||
}
|
||||
|
||||
push_cmd_set_scissor(engine.renderer,
|
||||
xx window.size.x,
|
||||
xx (window.size.y - WINDOW_TITLE_BAR_HEIGHT),
|
||||
xx window.actual_position.x,
|
||||
xx (window.actual_position.y + WINDOW_TITLE_BAR_HEIGHT));
|
||||
xx window.size.x- cast(u32)(WINDOW_BORDER_WIDTH*2),
|
||||
xx (window.size.y - WINDOW_TITLE_BAR_HEIGHT - cast(u32)(WINDOW_BORDER_WIDTH*2)),
|
||||
xx window.actual_position.x + cast(u32)WINDOW_BORDER_WIDTH,
|
||||
xx (window.actual_position.y + WINDOW_TITLE_BAR_HEIGHT + WINDOW_BORDER_WIDTH));
|
||||
|
||||
buffer_data := get_rect_instance_buffer();
|
||||
|
||||
@@ -900,6 +906,10 @@ ui_render :: () {
|
||||
//}
|
||||
}
|
||||
|
||||
ui_mouse_over_window :: () -> bool {
|
||||
return ui_state.mouse_over_window;
|
||||
}
|
||||
|
||||
#scope_file
|
||||
set_properties_to_defaults :: () {
|
||||
background_color = .{1,1,1,1};
|
||||
@@ -1103,7 +1113,7 @@ ui_render_text_recursively :: (box: *UI_Box) {
|
||||
inv_h := 1.0 / cast(float)engine.renderer.render_target_height;
|
||||
|
||||
if box.flags & .DRAW_TEXT {
|
||||
font_handle := ui_state.fonts.regular;
|
||||
font_handle := ui_state.fonts.button;
|
||||
if box.text.count > 0 {
|
||||
text_size := get_text_size(engine.renderer, box.text, font_handle);
|
||||
|
||||
@@ -1150,8 +1160,23 @@ ui_update_input :: () {
|
||||
mouse_x := engine.input.mouse.x;
|
||||
mouse_y := engine.input.mouse.y;
|
||||
|
||||
ui_state.mouse_over_window = false;
|
||||
for *window: ui_state.windows {
|
||||
if window.last_used_frame_index != ui_state.frame_index continue;
|
||||
rect: Rect;
|
||||
rect.x = xx window.actual_position.x;
|
||||
rect.y = xx window.actual_position.y;
|
||||
rect.w = xx window.size.x;
|
||||
rect.h = xx window.size.y;
|
||||
|
||||
if is_mouse_inside(mouse_x, mouse_y, rect) {
|
||||
ui_state.mouse_over_window = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Scrolling
|
||||
for *window: ui_state.windows {
|
||||
if window.last_used_frame_index != ui_state.frame_index continue;
|
||||
rect: Rect;
|
||||
rect.x = xx window.actual_position.x;
|
||||
rect.y = xx (window.actual_position.y+WINDOW_TITLE_BAR_HEIGHT);
|
||||
@@ -1159,12 +1184,14 @@ ui_update_input :: () {
|
||||
rect.h = xx (window.size.y - WINDOW_TITLE_BAR_HEIGHT);
|
||||
|
||||
if is_mouse_inside(mouse_x, mouse_y, rect) {
|
||||
ui_state.mouse_over_window = true;
|
||||
window.scroll_offset.y += cast(s32) engine.input.mouse.wheel * SCROLL_SPEED;
|
||||
}
|
||||
}
|
||||
|
||||
if ui_state.currently_moving_window == null {
|
||||
for *window: ui_state.windows {
|
||||
if window.last_used_frame_index != ui_state.frame_index continue;
|
||||
rect: Rect;
|
||||
rect.x = xx window.actual_position.x;
|
||||
rect.y = xx window.actual_position.y;
|
||||
@@ -1188,6 +1215,7 @@ ui_update_input :: () {
|
||||
}
|
||||
|
||||
for *window: ui_state.windows {
|
||||
if window.last_used_frame_index != ui_state.frame_index continue;
|
||||
window.actual_position = window.position + window.offset;
|
||||
}
|
||||
|
||||
@@ -1212,7 +1240,14 @@ ui_update_input :: () {
|
||||
box.interaction.left_mouse_pressed = false;
|
||||
}
|
||||
} else {
|
||||
if is_mouse_inside(mouse_x, mouse_y, box.rect) && key_pressed(.MOUSE_LEFT) {
|
||||
window := box.window;
|
||||
rect := box.rect;
|
||||
rect.x = clamp(rect.x, cast(float)window.actual_position.x, cast(float)window.actual_position.x + window.size.x);
|
||||
rect.w += rect.x - box.rect.x;
|
||||
rect.y = clamp(rect.y, cast(float)window.actual_position.y, cast(float)window.actual_position.y + window.size.y);
|
||||
rect.h += rect.y - box.rect.y;
|
||||
|
||||
if is_mouse_inside(mouse_x, mouse_y, rect) && key_pressed(.MOUSE_LEFT) {
|
||||
box.interaction.left_mouse_pressed = true;
|
||||
box.interaction.left_mouse_down = true;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,16 @@ ui_label :: (text: string, text_color: Color = .{1,1,1,1}, identifier: s64 = 0,
|
||||
box := ui_box_make(.DRAW_TEXT, get_hash(loc, identifier));
|
||||
}
|
||||
|
||||
ui_label_for_fields :: (text: string, text_color: Color = .{1,1,1,1}, identifier: s64 = 0, loc := #caller_location) {
|
||||
ui_set_next_text(text);
|
||||
ui_set_next_background_color(.{0.0,1.0,1.0,0.0});
|
||||
ui_set_next_text_color(text_color);
|
||||
ui_set_next_size_x(.PCT, 0.5);
|
||||
ui_set_next_size_y(.TEXT_DIM);
|
||||
ui_set_next_padding(5);
|
||||
box := ui_box_make(.DRAW_TEXT, get_hash(loc, identifier));
|
||||
}
|
||||
|
||||
ui_label_fill_parent_x :: (text: string, identifier: s64 = 0, loc := #caller_location) {
|
||||
ui_set_next_text(text);
|
||||
ui_set_next_background_color(.{0.0,1.0,1.0,0.0});
|
||||
@@ -288,7 +298,6 @@ ui_int_field :: (label: string, value: *int, identifier: s64 = 0, loc := #caller
|
||||
ui_float_field :: (label: string, value: *float, identifier: s64 = 0, loc := #caller_location) -> bool {
|
||||
changed := false;
|
||||
ui_container_layout(identifier=identifier, loc=loc);
|
||||
ui_set_next_size_x(.CHILDREN_SUM);
|
||||
ui_push_parent(ui_state.last_box, .LEFT, .HORIZONTAL);
|
||||
{
|
||||
ui_label(label);
|
||||
@@ -425,16 +434,27 @@ ui_float_field :: (value: *float, identifier: s64 = 0, loc := #caller_location)
|
||||
|
||||
ui_vector_field :: (label: string, value: *Vector3, identifier: s64 = 0, loc := #caller_location) -> bool {
|
||||
changed := false;
|
||||
ui_set_next_size_x(.TEXT_DIM);
|
||||
ui_set_next_size_y(.TEXT_DIM);
|
||||
ui_container_layout(identifier=identifier, loc=loc);
|
||||
ui_push_parent(ui_state.last_box, .LEFT, .HORIZONTAL);
|
||||
{
|
||||
ui_label(label);
|
||||
ui_label_for_fields(label);
|
||||
|
||||
//ui_set_next_size_x(.PCT, 0.5);
|
||||
//ui_set_next_size_y(.CHILDREN_SUM);
|
||||
|
||||
//container := ui_box_make(0, get_hash(loc, 123));
|
||||
//ui_push_parent(ui_state.last_box, .LEFT, .HORIZONTAL);
|
||||
|
||||
ui_label("X");
|
||||
changed |= ui_float_field(*value.x);
|
||||
ui_label("Y");
|
||||
changed |= ui_float_field(*value.y);
|
||||
ui_label("Z");
|
||||
changed |= ui_float_field(*value.z);
|
||||
|
||||
//ui_pop_parent();
|
||||
}
|
||||
ui_pop_parent();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user