From 4261f07762c54818cba821088f35e17390f14dbf Mon Sep 17 00:00:00 2001 From: Synthasmagoria Date: Mon, 17 Aug 2026 23:45:21 +0200 Subject: [PATCH] Easier interface use --- animation.odin | 62 +++++++++++++++++++++++++++++++++++--------------- program.odin | 34 ++++++++++++++++++--------- utils.odin | 6 +++++ 3 files changed, 73 insertions(+), 29 deletions(-) diff --git a/animation.odin b/animation.odin index 0063275..fa9d302 100644 --- a/animation.odin +++ b/animation.odin @@ -9,6 +9,36 @@ import "core:fmt" as in 2d. But I'm not sure if that's actually how it works. */ +AnimationInterface :: struct { + data: rawptr, + reset: proc(animation: ^AnimationInterface), + update_last: proc(animation: ^AnimationInterface, master_matrix: mat3), + update: proc(animation: ^AnimationInterface, animation_progress: f32), + next_matrix: proc(animation: ^AnimationInterface, next_matrix: mat3), + draw_idle: proc(animation: AnimationInterface), + draw_active: proc(animation: AnimationInterface), +} + +animation_update_last :: proc(animation: ^AnimationInterface, master_matrix: mat3) { + animation.update_last(animation, master_matrix) +} + +animation_update :: proc(animation: ^AnimationInterface, animation_progress: f32) { + animation.update(animation, animation_progress) +} + +animation_next_matrix :: proc(animation: ^AnimationInterface, next_matrix: mat3) { + animation.next_matrix(animation, next_matrix) +} + +animation_draw_idle :: proc(animation: AnimationInterface) { + animation.draw_idle(animation) +} + +animation_draw_active :: proc(animation: AnimationInterface) { + animation.draw_active(animation) +} + AnimationType :: enum { Rectangle, } @@ -33,17 +63,23 @@ AnimationData_Rectangle :: struct { draw_transformation_rectangle :: proc(rectangle: RectangleCorners, color: rl.Color) { rect := rect_from_corners(rectangle.tl, rectangle.tr, rectangle.br, rectangle.bl) rl.DrawRectangleRec(rect, rl.Color{**color.rgb, color.a / 2}) - points := []v2{rectangle.tl, rectangle.tr, rectangle.br, rectangle.bl} - for i := 0; i < len(points); i += 1 { - rl.DrawLineV(points[i], points[(i + 1) % len(points)], color) - rl.DrawCircleV(points[i], 4.0, rl.RED) - } + rl.DrawRectangleLinesEx(rect, 1.0, color) +} + +draw_transformation_rectangle_with_handles :: proc(rectangle: RectangleCorners, color: rl.Color) { + rect := rect_from_corners(rectangle.tl, rectangle.tr, rectangle.br, rectangle.bl) + rl.DrawRectangleRec(rect, rl.Color{**color.rgb, color.a / 2}) + rl.DrawRectangleLinesEx(rect, 1.0, color) + rl.DrawCircleV(rectangle.tl, 4.0, color) + rl.DrawCircleV(rectangle.tr, 4.0, color) + rl.DrawCircleV(rectangle.br, 4.0, color) + rl.DrawCircleV(rectangle.bl, 4.0, color) } _animation_rectangle_draw_idle :: proc(animation: AnimationInterface) { data := cast(^AnimationData_Rectangle)animation.data draw_transformation_rectangle(data.last, TRANSFORMATION_RECTANGLE_COLOR_LAST) - draw_transformation_rectangle(data.origin, TRANSFORMATION_RECTANGLE_COLOR_ORIGIN) + draw_transformation_rectangle_with_handles(data.origin, TRANSFORMATION_RECTANGLE_COLOR_ORIGIN) } _animation_rectangle_draw_active :: proc(animation: AnimationInterface) { @@ -88,8 +124,8 @@ _animation_rectangle_update :: proc(animation: ^AnimationInterface, animation_pr } } -_animation_rectangle_update_goto_next :: proc(animation: ^AnimationInterface, next_matrix: mat3) { - +animation_reset :: proc(animation: ^AnimationInterface) { + animation.reset(animation) } animation_create_rectangle :: proc(rectangle: ^AnimationData_Rectangle) -> AnimationInterface { @@ -103,13 +139,3 @@ animation_create_rectangle :: proc(rectangle: ^AnimationData_Rectangle) -> Anima draw_active = _animation_rectangle_draw_active, } } - -AnimationInterface :: struct { - data: rawptr, - reset: proc(animation: ^AnimationInterface), - update_last: proc(animation: ^AnimationInterface, master_matrix: mat3), - update: proc(animation: ^AnimationInterface, animation_progress: f32), - next_matrix: proc(animation: ^AnimationInterface, next_matrix: mat3), - draw_idle: proc(animation: AnimationInterface), - draw_active: proc(animation: AnimationInterface), -} diff --git a/program.odin b/program.odin index 0b763bb..14784ca 100644 --- a/program.odin +++ b/program.odin @@ -5,6 +5,7 @@ import ui "libraries/snths_ui" import "core:fmt" import "core:math/linalg" import "core:math/ease" +import "core:math" RAYGUI_ICON_PLAY :: "#131#" RAYGUI_ICON_PAUSE :: "#132#" @@ -256,7 +257,7 @@ program_set_transformation_state :: proc(state: AnimationState) { switch program.animation_state { case .Ready: program.animation_matrix_index = -1 - program.animation.reset(&program.animation) + animation_reset(&program.animation) case .Playing: case .Paused: @@ -264,6 +265,10 @@ program_set_transformation_state :: proc(state: AnimationState) { } } +float_slice_get_mat3 :: proc(floats: []f32, index: int) -> ^mat3 { + return cast(^mat3)(&floats[index * 9]) +} + program_update :: proc() { ui_elements, matrix_container := program_build_workspace_ui(&program.ui_context) ui_overlay_elements: []ui.Element @@ -305,7 +310,7 @@ program_update :: proc() { case .CreateScaleMatrix: program_add_scalar_matrix(vals[0], vals[1], vals[2]) case .CreateRotationMatrix: program_add_rotation_matrix(vals[0]) } - program.animation.update_last(&program.animation, program_get_master_matrix()) + animation_update_last(&program.animation, program_get_master_matrix()) program.state = .Normal } } @@ -317,16 +322,23 @@ program_update :: proc() { if program.animation_state == .Playing { program.animation_matrix_progress += program.animation_speed * delta_time_fraction() if program.animation_matrix_progress >= 1.0 { - program.animation_matrix_progress = 1.0; + if program.animation_matrix_index + 1 < program.matrix_count { + program.animation_matrix_index += 1 + animation_next_matrix(&program.animation, float_slice_get_mat3(program.matrix_float_pool, program.animation_matrix_index)^) + program.animation_matrix_progress = fract(program.animation_matrix_progress) + } else { + program.animation_matrix_progress = 1.0; + program.animation_state = .Finished + } } - program.animation.update(&program.animation, ease.ease(program.animation_ease, program.animation_matrix_progress)) + animation_update(&program.animation, ease.ease(program.animation_ease, program.animation_matrix_progress)) } switch program.animation_state { case .Ready: - program.animation.draw_idle(program.animation) + animation_draw_idle(program.animation) case .Playing, .Paused, .Finished: - program.animation.draw_active(program.animation) + animation_draw_active(program.animation) } ui_element_focus := program.state == .Normal ? program.ui_element_focus : ui.element_id_invalid() @@ -620,18 +632,18 @@ program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: u case .StartTransformation: if program.matrix_count > 0 { program.animation_state = .Playing - program.animation.reset(&program.animation) - program.animation.next_matrix(&program.animation, (cast(^mat3)raw_data(program.matrix_float_pool))^) + animation_reset(&program.animation) + animation_next_matrix(&program.animation, (cast(^mat3)raw_data(program.matrix_float_pool))^) } case .PauseTransformation: program.animation_state = .Paused case .ResumeTransformation: program.animation_state = .Playing case .ResetTransformation: - program.animation.reset(&program.animation) + animation_reset(&program.animation) } if data.type in UiButtonRecalculateFinishGroup { - program.animation.update_last(&program.animation, program_get_master_matrix()) + animation_update_last(&program.animation, program_get_master_matrix()) } } case .Slider: @@ -644,7 +656,7 @@ program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: u focus_element_id = element.id } if value_previous != data.value^ && .UpdateMatrix in data.tag { - program.animation.update_last(&program.animation, program_get_master_matrix()) + animation_update_last(&program.animation, program_get_master_matrix()) } case .Dropdown: assert(element.data != nil, "Element data cannot be nil when creating a dropdown") diff --git a/utils.odin b/utils.odin index 54977c9..5496a5f 100644 --- a/utils.odin +++ b/utils.odin @@ -4,6 +4,7 @@ import rl "libraries/raylib" import "base:intrinsics" import "core:strings" import "core:fmt" +import "core:math" import "core:math/linalg" import "core:mem" @@ -67,6 +68,11 @@ draw_text_aligned :: proc(text: cstring, position: v2, style: FontStyle, halign: draw_text(text, position, style, color) } +/// ### MATH ### /// +fract :: proc(val: f32) -> f32 { + return val - math.trunc(val) +} + /// ### TYPES ### /// v1 :: [1]f32 v2 :: [2]f32