UI fixes and new layout features

This commit is contained in:
2024-12-30 01:42:27 +01:00
parent 6ed67e8fcb
commit 6cf19a6f9b
5 changed files with 144 additions and 228 deletions

View File

@@ -33,15 +33,17 @@ pick_scene_view_at :: (camera: Camera, coordinates: Vector2) {
editor_ui :: () {
// Scene picking
if key_down(.MOUSE_LEFT) {
if engine.current_scene != null {
coords := engine.input.normalized_viewport_mouse_position;
pick_scene_view_at(engine.editor.camera, .{coords.x, 1.0-coords.y});
if !ui_mouse_over_window() {
if key_down(.MOUSE_LEFT) {
if engine.current_scene != null {
coords := engine.input.normalized_viewport_mouse_position;
pick_scene_view_at(engine.editor.camera, .{coords.x, 1.0-coords.y});
}
}
}
{
ui_window_begin("Create", 100, 5, 200, 200);
ui_window_begin("Create", cast(s32)engine.renderer.render_target_width - 200, 5, 200, 200);
new_entity := editor_ui_entity_creation();
if new_entity != null {
set_position(*new_entity.transform, engine.editor.camera.position + engine.editor.camera.forward * 20.0);
@@ -83,208 +85,63 @@ editor_ui :: () {
}
ui_window_end();
ui_full_size_background();
ui_push_parent(ui_state.last_box, alignment=.LEFT, axis=.VERTICAL);
ui_window_begin("Settings", 0, cast(s32)engine.renderer.render_target_height-80, 300, 80);
{
ui_set_next_padding(1);
ui_toolbar();
ui_push_parent(ui_state.last_box, alignment=.LEFT, axis=.HORIZONTAL);
{
if ui_toolbar_button("File") {
if engine.editor.transform_gizmo.snap_to_grid {
if ui_toolbar_button("Snap to grid enabled", .{0.0, 0.4, 0.0, 1.0}) {
engine.editor.transform_gizmo.snap_to_grid = false;
}
//ui_space(15, 10);
if ui_toolbar_button("Edit") {
}
//ui_space(15, 10);
//if ui_toolbar_button("View") {
//}
ui_space(20, 0);
if engine.mode == {
case .PLAYING; {
ui_set_next_background_color(.{0,0.6,0,1});
if ui_button_with_texture(engine.editor.icons.stop) {
switch_engine_mode(.EDITING);
}
ui_label(tprint("Playing '%'", engine.current_scene.name), .{0,0.7,0,1});
}
case .EDITING; {
ui_set_next_background_color(.{0.6,0,0,1});
if ui_button_with_texture(engine.editor.icons.play) {
switch_engine_mode(.PLAYING);
}
ui_label(tprint("Editing '%'", engine.current_scene.name), .{1,1,1,1});
}
} else {
if ui_toolbar_button("Snap to grid disabled", .{0.4, 0.0, 0.0, 1.0}) {
engine.editor.transform_gizmo.snap_to_grid = true;
}
}
ui_pop_parent();
ui_set_next_size_x(.PCT, 1.0);
ui_set_next_size_y(.PCT, 0.965);
ui_set_next_background_color(.{0,0,0,1});
background := ui_box(.NONE);
ui_push_parent(ui_state.last_box, alignment=.LEFT, axis=.HORIZONTAL);
{
ui_set_next_size_x(.PCT, 0.1);
ui_set_next_size_y(.PCT, 1.0);
ui_set_next_padding(1);
first_panel := ui_box(.NONE);
ui_push_parent(first_panel, alignment=.LEFT, axis=.VERTICAL);
{
ui_set_next_size_x(.PCT, 1.0);
ui_set_next_size_y(.PCT, 1.0);
ui_set_next_background_color(.{0.04, 0.04, 0.04, 1.0});
background := ui_box(.DRAW_BACKGROUND|.DRAW_BORDER);
ui_push_parent(background, alignment=.LEFT, axis=.VERTICAL);
{
ui_set_next_size_x(.PCT, 1.0);
ui_tab_title_bar("ENTITIES");
//if engine.current_scene != null {
// for engine.current_scene.entities {
// if it.flags & .DELETED continue;
// ui_set_next_padding(20);
// clicked := false;
// selected := array_find(engine.editor.selected_entities, it);
// if it.name.count == 0 {
// clicked = ui_clickable_label(tprint("%", it.type), selected, it.id);
// } else {
// clicked = ui_clickable_label(it.name, selected, it.id);
// }
// if clicked {
// if !key_pressed(.CTRL) {
// engine.editor.selected_entities.count = 0;
// array_add(*engine.editor.selected_entities, it);
// } else {
// if selected {
// array_unordered_remove_by_value(*engine.editor.selected_entities, it);
// } else {
// array_add(*engine.editor.selected_entities, it);
// }
// }
// }
// //ui_space(0, 5);
// }
//}
}
ui_pop_parent();
if engine.editor.transform_gizmo.space == .LOCAL {
if ui_toolbar_button("LOCAL", .{0.0, 0.3, 0.0, 1.0}) {
engine.editor.transform_gizmo.space = .WORLD;
}
ui_pop_parent();
// Scene
ui_set_next_size_x(.PCT, 0.7);
ui_set_next_size_y(.PCT, 1.0);
ui_set_next_padding(1);
viewport_layer := ui_box(.NONE);
ui_push_parent(viewport_layer, alignment=.LEFT, axis=.VERTICAL);
{
ui_set_next_size_x(.PCT, 1.0);
ui_tab_title_bar("SCENE");
ui_set_next_size_x(.PCT, 1.0);
ui_set_next_size_y(.PCT, 0.1);
ui_toolbar();
ui_push_parent(ui_state.last_box, alignment=.LEFT, axis=.HORIZONTAL);
{
if engine.editor.transform_gizmo.snap_to_grid {
if ui_toolbar_button("Snap to grid enabled", .{0.0, 0.4, 0.0, 1.0}) {
engine.editor.transform_gizmo.snap_to_grid = false;
}
} else {
if ui_toolbar_button("Snap to grid disabled", .{0.4, 0.0, 0.0, 1.0}) {
engine.editor.transform_gizmo.snap_to_grid = true;
}
}
if engine.editor.transform_gizmo.space == .LOCAL {
if ui_toolbar_button("LOCAL", .{0.0, 0.3, 0.0, 1.0}) {
engine.editor.transform_gizmo.space = .WORLD;
}
} else {
if ui_toolbar_button("WORLD", .{0.0, 0.0, 0.3, 1.0}) {
engine.editor.transform_gizmo.space = .LOCAL;
}
}
//ui_space(15, 10)
ui_space(20, 0);
}
ui_pop_parent();
//ui_set_next_size_x(.PCT, 1.0);
//ui_set_next_size_y(.PCT, 0.65);
//state := ui_interactable_texture(get_texture_from_pass("UI Blend Pass"));
//engine.input.viewport_mouse_position = state.local_mouse_coordinates;
//engine.input.normalized_viewport_mouse_position = state.normalized_local_mouse_coordinates;
//engine.editor.mouse_viewport_state = state;
//ui_set_next_size_x(.PCT, 1.0);
//ui_set_next_size_y(.PCT, 0.25);
//ui_tab_title_bar("Create entities");
//{
// new_entity := editor_ui_entity_creation();
// if new_entity != null {
// set_position(*new_entity.transform, engine.editor.camera.position + engine.editor.camera.forward * 20.0);
// engine.editor.selected_entities.count = 0;
// array_add(*engine.editor.selected_entities, new_entity);
// }
//}
} else {
if ui_toolbar_button("WORLD", .{0.0, 0.0, 0.3, 1.0}) {
engine.editor.transform_gizmo.space = .LOCAL;
}
ui_pop_parent();
// Properties
ui_set_next_size_x(.PCT, 0.2);
ui_set_next_size_y(.PCT, 1.0);
ui_set_next_background_color(.{0.04, 0.04, 0.04, 1.0});
ui_set_next_padding(1);
inspector := ui_box(.DRAW_BACKGROUND | .DRAW_BORDER);
ui_push_parent(inspector, alignment=.LEFT, axis=.VERTICAL);
{
ui_set_next_size_x(.PCT, 1.0);
ui_tab_title_bar("PROPERTIES");
if engine.editor.selected_entities.count == 1 {
entity := engine.editor.selected_entities[0];
//ui_slider(*slider_value, 0.0, 1.0);
ui_textfield("Name", *entity.name);
ui_label(tprint("Id: %", entity.id));
updated := ui_vector_field("Position", *entity.transform.position);
euler_rotation := quaternion_to_euler_v3(entity.transform.orientation);
euler_rotation *= RADIANS_TO_DEGREES;
updated |= ui_vector_field("Rotation", *euler_rotation);
euler_rotation *= DEGREES_TO_RADIANS;
entity.transform.orientation = euler_to_quaternion(euler_rotation);
updated |= ui_vector_field("Scale", *entity.transform.scale);
if updated {
update_matrix(*entity.transform);
}
entity_ui(entity);
}
}
ui_pop_parent();
}
ui_pop_parent();
//ui_space(15, 10)
ui_space(20, 0);
}
ui_window_end();
// Properties
{
if engine.editor.selected_entities.count == 1 {
ui_window_begin("Properties", 200, 200, 400, 500);
if engine.editor.selected_entities.count == 1 {
entity := engine.editor.selected_entities[0];
//ui_slider(*slider_value, 0.0, 1.0);
ui_textfield("Name", *entity.name);
ui_label(tprint("Id: %", entity.id));
updated := ui_vector_field("Position", *entity.transform.position);
euler_rotation := quaternion_to_euler_v3(entity.transform.orientation);
euler_rotation *= RADIANS_TO_DEGREES;
updated |= ui_vector_field("Rotation", *euler_rotation);
euler_rotation *= DEGREES_TO_RADIANS;
entity.transform.orientation = euler_to_quaternion(euler_rotation);
updated |= ui_vector_field("Scale", *entity.transform.scale);
if updated {
update_matrix(*entity.transform);
}
entity_ui(entity);
}
ui_window_end();
}
}
ui_pop_parent();
}
text_fun : string;
@@ -310,8 +167,10 @@ base_editor_update :: () {
//coordinates := Vector2.{engine.editor.mouse_viewport_state.normalized_local_mouse_coordinates.x, 1.0 - engine.editor.mouse_viewport_state.normalized_local_mouse_coordinates.y};
ray := normalized_screen_to_ray_v2(engine.editor.camera, coordinates);
if update_transform_gizmo(ray, coordinates) {
engine.editor.should_check_entities = false;
if !ui_mouse_over_window() {
if update_transform_gizmo(ray, coordinates) {
engine.editor.should_check_entities = false;
}
}
}

View File

@@ -123,10 +123,12 @@ generate_member_ui :: (type: *Type_Info_Struct, builder: *String_Builder, path:
for type.members {
if should_make_ui(type, it) && should_serialize(type, it) {
new_path : string;
if path.count == 0 {
new_path = it.name;
} else {
new_path = tprint("%1.%2", path, it.name);
if it.name != "entity" {
if path.count == 0 {
new_path = it.name;
} else {
new_path = tprint("%1.%2", path, it.name);
}
}
type : Type_Info_Tag;

View File

@@ -108,7 +108,7 @@ coven_run :: (game_update_proc: (float), game_editor_update_proc: (float), game_
dt = now - time;
time = now;
engine.time = time;
engine.dt = dt;
engine.dt = min(dt, 0.4);
update_fps_counter(dt);

View File

@@ -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;
}

View File

@@ -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();