grid snap

This commit is contained in:
Synthasmagoria 2026-09-15 15:00:11 +02:00
commit 5b01ad22f4
6 changed files with 66 additions and 13 deletions

View file

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

View file

@ -66,6 +66,7 @@ ElementType :: enum {
ToggleGroup,
Label,
Divider,
Toggle,
Custom0, Custom1, Custom2, Custom3, Custom4, Custom5, Custom6, Custom7, Custom8, Custom9,
}

View file

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

View file

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