From 361db162e0a445da76f09a3ecefbe902440c3162 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Mon, 27 Jan 2025 20:24:11 +0100 Subject: [PATCH] Add grid snap option --- armorcore/sources/iron_ui_nodes.c | 28 ++++++++++++++++++++++++++++ armorcore/sources/iron_ui_nodes.h | 1 + armorcore/sources/ts/ui.ts | 1 + base/sources/base.ts | 1 + base/sources/box_preferences.ts | 8 ++++++-- base/sources/config.ts | 2 ++ base/sources/ui_nodes.ts | 1 + 7 files changed, 40 insertions(+), 2 deletions(-) diff --git a/armorcore/sources/iron_ui_nodes.c b/armorcore/sources/iron_ui_nodes.c index 781132488..5562a2b7f 100644 --- a/armorcore/sources/iron_ui_nodes.c +++ b/armorcore/sources/iron_ui_nodes.c @@ -33,6 +33,8 @@ ui_canvas_control_t *(*ui_nodes_on_canvas_control)(void) = NULL; void (*ui_nodes_on_canvas_released)(void) = NULL; void (*ui_nodes_on_socket_released)(int) = NULL; void (*ui_nodes_on_link_drag)(int, bool) = NULL; +bool ui_nodes_grid_snap = true; +int ui_nodes_grid_snap_w = 40; int ui_popup_x = 0; int ui_popup_y = 0; @@ -365,6 +367,12 @@ void ui_nodes_rgba_popup(ui_handle_t *nhandle, float *val, int x, int y) { ui_popup(x, y, 140.0 * current_nodes->scale_factor, current->ops->theme->ELEMENT_H * 10.0, &rgba_popup_commands, nhandle, val); } +static float ui_nodes_snap(float f) { + float w = ui_nodes_grid_snap_w * UI_NODES_SCALE(); + f = f * UI_NODES_SCALE(); + return roundf(f / w) * w; +} + static char_ptr_array_t enum_ar; static char enum_label[64]; static char enum_texts_data[64][64]; @@ -402,6 +410,19 @@ void ui_draw_node(ui_node_t *node, ui_node_canvas_t *canvas) { } } + // Grid snap preview + if (ui_nodes_grid_snap && ui_is_selected(node) && current_nodes->nodes_drag) { + kinc_g2_set_color(current->ops->theme->BUTTON_COL); + ui_draw_rect(false, + ui_nodes_snap(node->x) + UI_NODES_PAN_X(), + ui_nodes_snap(node->y) + UI_NODES_PAN_Y(), + w + 2, + h + 2 + ); + // nx = ui_nodes_snap(node->x) + UI_NODES_PAN_X(); + // ny = ui_nodes_snap(node->y) + UI_NODES_PAN_Y(); + } + // Shadow ui_draw_shadow(nx, ny, w, h); @@ -1005,8 +1026,15 @@ void ui_node_canvas(ui_nodes_t *nodes, ui_node_canvas_t *canvas) { current_nodes->dragged = true; node->x += current->input_dx / UI_NODES_SCALE(); node->y += current->input_dy / UI_NODES_SCALE(); + // Absolute + // node->x = (current->input_x - current->_window_x - UI_NODES_PAN_X()) / UI_NODES_SCALE(); + // node->y = (current->input_y - current->_window_y - UI_NODES_PAN_Y()) / UI_NODES_SCALE(); } } + if (ui_nodes_grid_snap && current->input_released && ui_is_selected(node)) { + node->x = ui_nodes_snap(node->x) / UI_NODES_SCALE(); + node->y = ui_nodes_snap(node->y) / UI_NODES_SCALE(); + } ui_draw_node(node, canvas); } diff --git a/armorcore/sources/iron_ui_nodes.h b/armorcore/sources/iron_ui_nodes.h index fadcb0f6b..ce0558338 100644 --- a/armorcore/sources/iron_ui_nodes.h +++ b/armorcore/sources/iron_ui_nodes.h @@ -129,6 +129,7 @@ extern ui_canvas_control_t *(*ui_nodes_on_canvas_control)(void); extern void (*ui_nodes_on_canvas_released)(void); extern void (*ui_nodes_on_socket_released)(int); extern void (*ui_nodes_on_link_drag)(int, bool); +extern bool ui_nodes_grid_snap; void ui_node_canvas_encode(ui_node_canvas_t *canvas); uint32_t ui_node_canvas_encoded_size(ui_node_canvas_t *canvas); diff --git a/armorcore/sources/ts/ui.ts b/armorcore/sources/ts/ui.ts index 759ee0bf0..72d5bfeb5 100644 --- a/armorcore/sources/ts/ui.ts +++ b/armorcore/sources/ts/ui.ts @@ -264,6 +264,7 @@ declare let ui_is_copy: bool; declare let ui_is_paste: bool; declare let ui_nodes_exclude_remove: string[]; declare let ui_clipboard: string; +declare let ui_nodes_grid_snap: bool; declare function ui_nest(handle: ui_handle_t, pos: i32): ui_handle_t; declare function ui_theme_default(theme: ui_theme_t): void; diff --git a/base/sources/base.ts b/base/sources/base.ts index 2ef6b09f3..573d2db6c 100644 --- a/base/sources/base.ts +++ b/base/sources/base.ts @@ -840,6 +840,7 @@ function base_init_config() { raw.blender = ""; raw.atlas_res = 0; raw.pathtrace_mode = pathtrace_mode_t.FAST; + raw.grid_snap = false; base_ext_init_config(raw); } diff --git a/base/sources/box_preferences.ts b/base/sources/box_preferences.ts index ee088a743..ac15e214b 100644 --- a/base/sources/box_preferences.ts +++ b/base/sources/box_preferences.ts @@ -124,8 +124,12 @@ function box_preferences_show() { } config_raw.splash_screen = ui_check(h_splash_screen, tr("Splash Screen")); - // ui_text("Node Editor"); - // let grid_snap: bool = ui_check(ui_handle("boxpreferences_11", { selected: false }), "Grid Snap"); + let h_grid_snap: ui_handle_t = ui_handle(__ID__); + if (h_grid_snap.init) { + h_grid_snap.selected = config_raw.grid_snap; + } + config_raw.grid_snap = ui_check(h_grid_snap, tr("Grid Snap")); + ui_nodes_grid_snap = config_raw.grid_snap; _ui_end_element(); diff --git a/base/sources/config.ts b/base/sources/config.ts index 1b62cec44..d16ff2afc 100644 --- a/base/sources/config.ts +++ b/base/sources/config.ts @@ -99,6 +99,7 @@ function config_save() { json_encode_string("blender", config_raw.blender); json_encode_i32("atlas_res", config_raw.atlas_res); json_encode_i32("pathtrace_mode", config_raw.pathtrace_mode); + json_encode_bool("grid_snap", config_raw.grid_snap); let config_json: string = json_encode_end(); let buffer: buffer_t = sys_string_to_buffer(config_json); @@ -441,4 +442,5 @@ type config_t = { blender?: string; atlas_res: i32; // Forge pathtrace_mode: i32; + grid_snap: bool; }; diff --git a/base/sources/ui_nodes.ts b/base/sources/ui_nodes.ts index 07c52af37..7fe0bf82b 100644 --- a/base/sources/ui_nodes.ts +++ b/base/sources/ui_nodes.ts @@ -61,6 +61,7 @@ function ui_viewnodes_init() { ui_nodes_on_socket_released = ui_viewnodes_on_socket_released; ui_nodes_on_canvas_released = ui_viewnodes_on_canvas_released; ui_nodes_on_canvas_control = ui_viewnodes_on_canvas_control; + ui_nodes_grid_snap = config_raw.grid_snap; nodes_material_init(); let scale: f32 = config_raw.window_scale;