From 5b01ad22f472a271858c37fa9c93a220528b6e2d Mon Sep 17 00:00:00 2001 From: Synthasmagoria Date: Tue, 15 Sep 2026 15:00:11 +0200 Subject: [PATCH] grid snap --- TODO.MD | 4 +- default | Bin 166 -> 166 bytes src/animation.odin | 4 -- src/libraries/snths_ui/ui.odin | 1 + src/main.odin | 2 +- src/program.odin | 68 ++++++++++++++++++++++++++++++--- 6 files changed, 66 insertions(+), 13 deletions(-) diff --git a/TODO.MD b/TODO.MD index 56e62e9..c2a817a 100644 --- a/TODO.MD +++ b/TODO.MD @@ -2,12 +2,12 @@ - Web read/write - Ship with default setup - Fix -vet errors -- Snap to grid option - Set grid -- Set animation value DONE: - When there is no matrix it should still draw the rectangle - Always show coordinates - Web build - Escape closes dialogue if on dialogue. Otherwise stops program if on desktop, but not without an unsaved changes warning. +- Set animation value +- Snap to grid option diff --git a/default b/default index f8ea14d8435ea8c1eae1bb62aa56bc7db75370bd..a628ad7eee40e075dc01f8f143b11ae1b2c7b8a2 100755 GIT binary patch delta 55 ncmZ3+xQuZ^nZf@vXKX=u>lUjcEtfhDGcb4@f?_8m8qNj)p}G@= delta 55 xcmZ3+xQuZ^nZbgYlJ+1R;A(b+L-q9G^^?1uf7ZJ?J0DSk)5g;GoIv6r8US}b7R3Mn diff --git a/src/animation.odin b/src/animation.odin index f3a462a..4202a3c 100644 --- a/src/animation.odin +++ b/src/animation.odin @@ -72,10 +72,6 @@ rectangle_corners_move_corner :: proc "contextless" (corners: RectangleCorners, return corners } -rectangle_corners_transform_mat2 :: proc "contextless" (corners: RectangleCorners, transform: mat2) -> RectangleCorners { - return {corners.tl * transform, corners.tr * transform, corners.br * transform, corners.bl * transform} -} - draw_animation_rectangle_corners :: proc(corners: RectangleCorners, color: rl.Color) { triangles := rectangle_corners_get_triangles(corners) draw_triangle(triangles[0], {**color.rgb, color.a >> 1}) diff --git a/src/libraries/snths_ui/ui.odin b/src/libraries/snths_ui/ui.odin index d09343b..cf4e4bf 100644 --- a/src/libraries/snths_ui/ui.odin +++ b/src/libraries/snths_ui/ui.odin @@ -66,6 +66,7 @@ ElementType :: enum { ToggleGroup, Label, Divider, + Toggle, Custom0, Custom1, Custom2, Custom3, Custom4, Custom5, Custom6, Custom7, Custom8, Custom9, } diff --git a/src/main.odin b/src/main.odin index eee01c2..23a5e7b 100644 --- a/src/main.odin +++ b/src/main.odin @@ -10,7 +10,7 @@ WINDOW_CAPTION :: "Transformation Visualizer" init :: proc() { rl.SetTraceLogLevel(.WARNING) - rl.SetConfigFlags({.VSYNC_HINT}) + rl.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE}) rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION) rl.SetTargetFPS(WINDOW_FRAMERATE) rl.SetExitKey(.KEY_NULL) diff --git a/src/program.odin b/src/program.odin index fddc874..fc3150c 100644 --- a/src/program.odin +++ b/src/program.odin @@ -50,6 +50,7 @@ RAYGUI_ICON_RESET :: "#211#" RAYGUI_ICON_TRASH :: "#143#" RAYGUI_ICON_DOWN :: "#120#" RAYGUI_ICON_UP :: "#121#" +RAYGUI_ICON_SNAP :: "#136#" TRANSFORMATION_RECTANGLE_COLOR_ORIGIN :: rl.RED TRANSFORMATION_RECTANGLE_COLOR_MIDDLE :: rl.MAGENTA @@ -87,6 +88,10 @@ UiElementData_TextInput :: struct { str: cstring, } +UiElementData_Toggle :: struct { + value: ^bool, +} + UiElementData_ToggleGroup :: struct { value: ^i32, } @@ -290,6 +295,7 @@ Program :: struct { grid_zoom_x_only: bool, grid_zoom_y_only: bool, grid_zoom_speed: f32, + grid_snap: bool, font_style: FontStyle, state: ProgramState, message_type: ProgramMessageType, @@ -300,6 +306,7 @@ Program :: struct { animation_state: ProgramAnimationState, animation_speed: f32, animation_mode: AnimationMode, + animation_progress_string: [DIALOG_STATE_TEXT_INPUT_FIELD_COUNT]byte, window_should_close: bool, } @@ -609,6 +616,7 @@ program_update :: proc() { animation := &program.animation if program.animation_state == .Playing { + write_float_to_buffer(program.animation_progress_string[:], animation.matrix_index) animation.matrix_index += 0.01 } @@ -934,18 +942,43 @@ program_build_workspace_ui :: proc(ctx: ^ui.Context) -> (elements: []ui.Element, ui.same_line() ui.element(.Slider, slider_dimensions, slider_config, slider_data) + float_config: ui.ElementConfiguration + float_data: ^UiElementData_FloatInput + float_dimensions := ui.Dimensions{top_bar_button_width * 2.0, ui.Size_Percentage(1.0)} + float_config = {margin = top_bar_element_margin * 2} + float_data = new(UiElementData_FloatInput, context.temp_allocator) + float_data^ = { + value = &program.animation.matrix_index, + value_string = transmute(cstring)&program.animation_progress_string, + } + ui.same_line() + ui.element(.InputFloat, float_dimensions, float_config, float_data) + toggle_group_config: ui.ElementConfiguration toggle_group_dimensions := ui.Dimensions{top_bar_button_width * 3.0, ui.Size_Percentage(1.0)} toggle_group_data: ^UiElementData_ToggleGroup toggle_group_config = { - margin = button_margin, + margin = top_bar_element_margin * 2, label = enum_to_raygui_options_string(AnimationMode, context.temp_allocator), tooltip = "Play animation\nstep by step;Play animation using the\nfull transformation matrix"} toggle_group_data = new(UiElementData_ToggleGroup, context.temp_allocator) toggle_group_data^ = {value = cast(^i32)&program.animation_mode} ui.same_line() ui.element(.ToggleGroup, toggle_group_dimensions, toggle_group_config, toggle_group_data) + + ui.same_line() + ui.element(.Divider, divider_dimensions, divider_config) + + toggle_config: ui.ElementConfiguration + toggle_dimensions := ui.Dimensions{top_bar_button_width, ui.Size_Percentage(1.0)} + toggle_data: ^UiElementData_Toggle + + toggle_config = {margin = top_bar_element_margin, label = RAYGUI_ICON_SNAP, tooltip = "Snap to grid"} + toggle_data = new(UiElementData_Toggle, context.temp_allocator) + toggle_data^ = {value = &program.grid_snap} + ui.same_line() + ui.element(.Toggle, toggle_dimensions, toggle_config, toggle_data) } ui.container_end() @@ -1021,16 +1054,31 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_ break state_label } draggable := program.mouse_current_draggable + position := matrix3_transform_xy(world_to_grid_matrix, mouse) + drag_to_position := matrix3_transform_xy(world_to_grid_matrix, mouse) + if program.grid_snap { + grid_line_sep := grid_get_line_separation(program.grid.zoom, program.grid.cell_size_px) + drag_to_position = linalg.floor(drag_to_position / grid_line_sep) * grid_line_sep + } + switch draggable in draggable { case MouseDraggable_Point: - draggable.ref^ = matrix3_transform_xy(world_to_grid_matrix, mouse) + draggable.ref^ = drag_to_position case MouseDraggable_RectangleCornerData: - position := matrix3_transform_xy(world_to_grid_matrix, mouse) - corners := rectangle_corners_move_corner(draggable.corners_ref^, position, draggable.corner) + corners := rectangle_corners_move_corner(draggable.corners_ref^, drag_to_position, draggable.corner) draggable.corners_ref^ = corners case MouseDraggable_RectangleData: - mouse_delta_grid := rl.GetMouseDelta() * grid_get_zoom(program.grid.zoom) - draggable.corners^ = rectangle_corners_add(draggable.corners^, mouse_delta_grid) + if program.grid_snap { + + prev_tl := draggable.corners.tl + draggable.corners.tl = drag_to_position + draggable.corners.tr += draggable.corners.tl - prev_tl + draggable.corners.br += draggable.corners.tl - prev_tl + draggable.corners.bl += draggable.corners.tl - prev_tl + } else { + mouse_delta_grid := rl.GetMouseDelta() * grid_get_zoom(program.grid.zoom) + draggable.corners^ = rectangle_corners_add(draggable.corners^, mouse_delta_grid) + } } case .DraggingGrid: program.grid.offset -= rl.GetMouseDelta() * grid_get_zoom(program.grid.zoom) @@ -1244,6 +1292,14 @@ program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: u tooltip_text = strings.clone_to_cstring(tooltips_split[tooltip_index], context.temp_allocator) tooltip_position = mouse } + case .Toggle: + data := cast(^UiElementData_Toggle)element.data + rl.GuiToggle(area, element.label, data.value) + mouse := rl.GetMousePosition() + if rect_has_point(area, mouse) { + tooltip_text = element.tooltip + tooltip_position = mouse + } case: rl.DrawRectangleRec(area, rl.MAGENTA) }