Infinitely scrolling grid

This commit is contained in:
Synthasmagoria 2026-08-27 19:55:19 +02:00
commit ebd0ef76d3
3 changed files with 35 additions and 8 deletions

View file

@ -1,3 +1,6 @@
- Grid line changing
- Zoom sensitivity
- Playback slider
- Save grid and animation data to file - Save grid and animation data to file
- Load project - Load project
- Fix focus on submenu - Fix focus on submenu

View file

@ -10,7 +10,27 @@ Grid :: struct {
} }
grid_get_zoom :: proc(zoom: v2) -> v2 { grid_get_zoom :: proc(zoom: v2) -> v2 {
return linalg.pow(v2{2.0, 2.0}, zoom) - 1.0 return linalg.pow(v2(2.0), zoom)
}
grid_get_line_separation :: proc(zoom: v2, min_line_distance: f32) -> v2 {
zoom_factor := grid_get_zoom(zoom)
sep := linalg.pow(v2(10.0), linalg.floor(linalg.log10(min_line_distance * zoom_factor)))
for {
if sep.x / zoom_factor.x >= min_line_distance {
break
}
if sep.x * 2.5 / zoom_factor.x >= min_line_distance {
sep *= 2.5
break
}
if sep.x * 5.0 / zoom_factor.x >= min_line_distance {
sep *= 5.0
break
}
sep *= 10.0
}
return sep
} }
grid_world_to_grid_matrix :: proc(zoom, offset: v2) -> mat3 { grid_world_to_grid_matrix :: proc(zoom, offset: v2) -> mat3 {
@ -24,17 +44,20 @@ grid_world_to_grid_matrix :: proc(zoom, offset: v2) -> mat3 {
linalg.matrix3_scale(v3{**zoom_amount, 1.0})) linalg.matrix3_scale(v3{**zoom_amount, 1.0}))
} }
import "core:fmt"
draw_grid :: proc(grid: Grid, text_draw, text_clip: rect2) { draw_grid :: proc(grid: Grid, text_draw, text_clip: rect2) {
world_to_grid_matrix := grid_world_to_grid_matrix(grid.zoom, grid.offset) world_to_grid_matrix := grid_world_to_grid_matrix(grid.zoom, grid.offset)
grid_to_world_matrix := linalg.inverse(world_to_grid_matrix) grid_to_world_matrix := linalg.inverse(world_to_grid_matrix)
grid_world_br := grid.world_position + grid.world_size grid_world_br := grid.world_position + grid.world_size
grid_color := rl.Color{64, 64, 64, 255} grid_color := rl.Color{64, 64, 64, 255}
grid_tl := (v3{**grid.world_position, 1.0} * world_to_grid_matrix).xy sep := grid_get_line_separation(grid.zoom, 32.0)
grid_tl = linalg.floor(grid_tl / grid.cell_size) * grid.cell_size tl := (v3{**grid.world_position, 1.0} * world_to_grid_matrix).xy
grid_br := (v3{**grid_world_br, 1.0} * world_to_grid_matrix).xy tl = linalg.floor(tl / sep) * sep
br := (v3{**grid_world_br, 1.0} * world_to_grid_matrix).xy
for x: f32 = grid_tl.x; x < grid_br.x; x += grid.cell_size.x { for x: f32 = tl.x; x < br.x; x += sep.x {
world_position_x := (v3{x, 0.0, 1.0} * grid_to_world_matrix).x world_position_x := (v3{x, 0.0, 1.0} * grid_to_world_matrix).x
p1 := v2{world_position_x, grid.world_position.y} p1 := v2{world_position_x, grid.world_position.y}
p2 := v2{world_position_x, grid_world_br.y} p2 := v2{world_position_x, grid_world_br.y}
@ -44,7 +67,7 @@ draw_grid :: proc(grid: Grid, text_draw, text_clip: rect2) {
} }
} }
for y: f32 = grid_tl.y; y < grid_br.y; y += grid.cell_size.y { for y: f32 = tl.y; y < br.y; y += sep.y {
world_position_y := (v3{0.0, y, 1.0} * grid_to_world_matrix).y world_position_y := (v3{0.0, y, 1.0} * grid_to_world_matrix).y
p1 := v2{grid.world_position.x, world_position_y} p1 := v2{grid.world_position.x, world_position_y}
p2 := v2{grid_world_br.x, world_position_y} p2 := v2{grid_world_br.x, world_position_y}

View file

@ -229,6 +229,7 @@ Program :: struct {
grid: Grid, grid: Grid,
grid_zoom_x_only: bool, grid_zoom_x_only: bool,
grid_zoom_y_only: bool, grid_zoom_y_only: bool,
grid_zoom_speed: f32,
font_style: FontStyle, font_style: FontStyle,
state: ProgramState, state: ProgramState,
message_type: ProgramMessageType, message_type: ProgramMessageType,
@ -301,6 +302,7 @@ program_init :: proc(allocator := context.allocator) {
world_position = 0.0, world_position = 0.0,
world_size = program_screen_size() world_size = program_screen_size()
} }
program.grid_zoom_speed = 1.0
program.mouse_draggable_radius = 6.0 program.mouse_draggable_radius = 6.0
ui.init(&program.ui_context, 4000, ui_measure_text, &program.font_style, allocator) ui.init(&program.ui_context, 4000, ui_measure_text, &program.font_style, allocator)
@ -429,7 +431,6 @@ program_update :: proc() {
top_bar_container_br := rect_get_br(rect2(top_bar_container.area)) top_bar_container_br := rect_get_br(rect2(top_bar_container.area))
matrix_container_br := rect_get_br(rect2(matrix_container.area)) matrix_container_br := rect_get_br(rect2(matrix_container.area))
program.grid.world_size = program_screen_size() program.grid.world_size = program_screen_size()
grid_text_clip := rect_from_area(v2{matrix_container_br.x, top_bar_container_br.y}, program_screen_size()) grid_text_clip := rect_from_area(v2{matrix_container_br.x, top_bar_container_br.y}, program_screen_size())
draw_grid(program.grid, rect_grow(grid_text_clip, -4.0), rect_grow(grid_text_clip, -32.0)) draw_grid(program.grid, rect_grow(grid_text_clip, -4.0), rect_grow(grid_text_clip, -32.0))
@ -710,7 +711,7 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
} }
program.grid.zoom_previous = program.grid.zoom program.grid.zoom_previous = program.grid.zoom
grid_zoom_dimension_lock := v2{1.0 - f32(int(program.grid_zoom_y_only)), 1.0 - f32(int(program.grid_zoom_x_only))} grid_zoom_dimension_lock := v2{1.0 - f32(int(program.grid_zoom_y_only)), 1.0 - f32(int(program.grid_zoom_x_only))}
program.grid.zoom += grid_zoom_dimension_lock * mouse_wheel.y * 0.01 program.grid.zoom += grid_zoom_dimension_lock * mouse_wheel.y * 0.2 * program.grid_zoom_speed
case .DraggingDraggable: case .DraggingDraggable:
if !rl.IsMouseButtonDown(.LEFT) { if !rl.IsMouseButtonDown(.LEFT) {
mouse_state = .Hover mouse_state = .Hover