Input matrix fields

This commit is contained in:
Synthasmagoria 2026-08-16 12:49:32 +02:00
commit c739f34581

View file

@ -4,6 +4,7 @@ import rl "libraries/raylib"
import ui "libraries/snths_ui"
import "core:fmt"
import "core:math/linalg"
import "core:strconv"
UiContainerType :: enum {
Normal,
@ -63,18 +64,6 @@ MatrixTypes :: enum {
.Rotation = rl.KeyboardKey.R,
}
matrix_add_hotkey_proc_identity :: proc() {program_add_identity_matrix()}
matrix_add_hotkey_proc_translation :: proc() {program_show_dialog(&program, .CreateTranslationMatrix)}
matrix_add_hotkey_proc_scale :: proc() {program_show_dialog(&program, .CreateScaleMatrix)}
matrix_add_hotkey_proc_rotation :: proc() {program_show_dialog(&program, .CreateRotationMatrix)}
@rodata matrix_add_procs := [MatrixTypes](proc()) {
.Identity = matrix_add_hotkey_proc_identity,
.Translation = matrix_add_hotkey_proc_translation,
.Scale = matrix_add_hotkey_proc_scale,
.Rotation = matrix_add_hotkey_proc_rotation,
}
FontStyle :: struct {
font: rl.Font,
size, spacing: f32
@ -161,6 +150,16 @@ matrix_pool_get_mat3 :: proc() -> ^mat3 {
return mat
}
matrix_pool_get_mat3_2 :: proc() -> []InputFloatField {
assert(program.matrix_count + 1 < matrix_pool_max(), "Max matrix count exceeded")
value_strings := program.matrix_value_string_pool[program.matrix_count * 9 : program.matrix_count * 9 + 9]
for &str in value_strings {
str[0] = '0'
}
program.matrix_count += 1
return value_strings
}
program_show_dialog :: proc(program: ^Program, dialog_type: ProgramDialogType) {
program.dialog_data = {}
program.ui_overlay_queue_focus_first = true
@ -198,22 +197,29 @@ program_update :: proc() {
ui_elements, matrix_container := program_build_workspace_ui(&program.ui_context)
ui_overlay_elements: []ui.Element
for hotkey, i in matrix_add_hotkeys {
if rl.IsKeyPressed(hotkey) {
matrix_add_procs[i]()
}
}
switch program.state {
case .Normal:
program.mouse_state = program_handle_mouse_workspace(program.mouse_state, matrix_container)
if rl.IsKeyPressed(.TAB) {
program.ui_element_focus = ui.focus_next_element(program.ui_element_focus, ui_elements, UI_ALLOWED_FOCUS)
}
for hotkey, index in matrix_add_hotkeys {
if rl.IsKeyPressed(hotkey) {
switch index {
case .Identity: program_add_identity_matrix()
case .Translation: program_show_dialog(&program, .CreateTranslationMatrix)
case .Scale: program_show_dialog(&program, .CreateScaleMatrix)
case .Rotation: program_show_dialog(&program, .CreateRotationMatrix)
}
}
}
case .Message:
case .Dialog:
ui_overlay_elements = program_build_dialog_ui(&program.ui_overlay_context, program.dialog_type)
if rl.IsKeyPressed(.TAB) {
program.ui_overlay_element_focus = ui.focus_next_element(program.ui_overlay_element_focus, ui_overlay_elements, UI_ALLOWED_FOCUS)
}
if rl.IsKeyDown(.ENTER) {
vals := program.dialog_data.input_values
switch program.dialog_type {
@ -234,7 +240,9 @@ program_update :: proc() {
grid_inner_position := rect_get_tl(grid.inner_area)
draw_grid(grid.area, {32.0, 32.0}, rl.GRAY)
program.ui_element_focus = program_render_ui_and_handle_focus(&program.ui_context, program.ui_element_focus, program.font_style, ui_elements)
ui_element_focus := program.state == .Normal ? program.ui_element_focus : ui.element_id_invalid()
program.ui_element_focus = program_render_ui_and_handle_focus(&program.ui_context, ui_element_focus, program.font_style, ui_elements)
if len(ui_overlay_elements) > 0 {
rl.DrawRectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, {0, 0, 0, 192})
program.ui_overlay_element_focus = program_render_ui_and_handle_focus(
@ -246,40 +254,43 @@ program_update :: proc() {
}
program_add_identity_matrix :: proc() {
mat := matrix_pool_get_mat3()
mat^ = {
1, 0, 0,
0, 1, 0,
0, 0, 1,
}
value_strings := matrix_pool_get_mat3_2()
value_strings[0][0] = '1'
value_strings[4][0] = '1'
value_strings[8][0] = '1'
}
program_add_translation_matrix :: proc(x, y, z: f32) {
mat := matrix_pool_get_mat3()
mat^ = {
1, 0, x,
0, 1, y,
0, 0, z,
}
value_strings := matrix_pool_get_mat3_2()
fmt.bprint(value_strings[2][:], x)
fmt.bprint(value_strings[5][:], y)
fmt.bprint(value_strings[8][:], z)
}
program_add_scalar_matrix :: proc(x, y, z: f32) {
mat := matrix_pool_get_mat3()
mat^ = {
x, 0, 0,
0, y, 0,
0, 0, z,
}
value_strings := matrix_pool_get_mat3_2()
fmt.bprint(value_strings[0][:], x)
fmt.bprint(value_strings[4][:], y)
fmt.bprint(value_strings[8][:], z)
}
program_add_rotation_matrix :: proc(angle: f32) {
mat := matrix_pool_get_mat3()
value_strings := matrix_pool_get_mat3_2()
rotmat := linalg.matrix2_rotate_f32(angle)
mat^ = {
rotmat[0, 0], rotmat[0, 1], 0,
rotmat[1, 0], rotmat[1, 1], 0,
0, 0, 1,
}
fmt.bprint(value_strings[0][:], rotmat[0, 0])
fmt.bprint(value_strings[1][:], rotmat[0, 1])
fmt.bprint(value_strings[3][:], rotmat[1, 0])
fmt.bprint(value_strings[4][:], rotmat[1, 1])
}
ui_labeled_input_float_element :: proc(label: cstring, margin: f32, value: ^f32, value_string: ^InputFloatField, allocator := context.temp_allocator) -> ^ui.Element {
label := fmt.ctprintf("%s: ", label)
label_element := ui.element(.Label, {}, {label = label, color = ui.col(rl.WHITE), margin = margin})
dimensions := ui.Dimensions{ui.Size_Pixels(64.0), ui.dimensions_pixels(ui.rect_get_size(ui.get_element_outer_area(label_element^))).height}
ui.same_line()
input_data := new(UiElementData_FloatInput, context.temp_allocator)
input_data^ = {value = value, value_string = cstring(&value_string[0])}
return ui.element(.InputFloat, dimensions, {margin = margin}, input_data)
}
program_build_dialog_ui :: proc(ctx: ^ui.Context, dialog_type: ProgramDialogType) -> []ui.Element {
@ -297,11 +308,17 @@ program_build_dialog_ui :: proc(ctx: ^ui.Context, dialog_type: ProgramDialogType
ui.start(ctx, V2_ZERO, {WINDOW_WIDTH, WINDOW_HEIGHT})
ui.container_begin(ui.dimensions_auto(), {margin = container_margin, padding = 8.0})
ui.element(.Label, {}, {label = program_dialog_messages[program.dialog_type], color = ui.col(rl.WHITE), margin = element_margin})
ui_labeled_input_float_element("X", 4.0, &dialog_data.input_values[0], &dialog_data.input_value_strings[0])
ui_labeled_input_float_element("Y", 4.0, &dialog_data.input_values[1], &dialog_data.input_value_strings[1])
ui_labeled_input_float_element("Z", 4.0, &dialog_data.input_values[2], &dialog_data.input_value_strings[2])
switch dialog_type {
case .CreateTranslationMatrix, .CreateScaleMatrix:
ui.element(.Label, {}, {label = program_dialog_messages[program.dialog_type], color = ui.col(rl.WHITE), margin = element_margin})
ui_labeled_input_float_element("X", 4.0, &dialog_data.input_values[0], &dialog_data.input_value_strings[0])
ui_labeled_input_float_element("Y", 4.0, &dialog_data.input_values[1], &dialog_data.input_value_strings[1])
ui_labeled_input_float_element("Z", 4.0, &dialog_data.input_values[2], &dialog_data.input_value_strings[2])
case .CreateRotationMatrix:
ui.element(.Label, {}, {label = program_dialog_messages[program.dialog_type], color = ui.col(rl.WHITE), margin = element_margin})
ui_labeled_input_float_element("Angle", 4.0, &dialog_data.input_values[0], &dialog_data.input_value_strings[0])
}
button_data: ^UiElementData_Button
button_data = new(UiElementData_Button, context.temp_allocator)
button_data^ = {type = button_type}
@ -315,39 +332,6 @@ program_build_dialog_ui :: proc(ctx: ^ui.Context, dialog_type: ProgramDialogType
return ui.end()
}
ui_labeled_input_float_element :: proc(label: cstring, margin: f32, value: ^f32, value_string: ^InputFloatField, allocator := context.temp_allocator) -> ^ui.Element {
label := fmt.ctprintf("%s: ", label)
label_element := ui.element(.Label, {}, {label = label, color = ui.col(rl.WHITE), margin = margin})
dimensions := ui.Dimensions{ui.Size_Pixels(64.0), ui.dimensions_pixels(ui.rect_get_size(ui.get_element_outer_area(label_element^))).height}
ui.same_line()
input_data := new(UiElementData_FloatInput, context.temp_allocator)
input_data^ = {value = value, value_string = cstring(&value_string[0])}
return ui.element(.InputFloat, dimensions, {margin = margin}, input_data)
}
program_handle_mouse_workspace :: proc(mouse_state: MouseState, matrix_container: ^ui.Element) -> MouseState {
mouse := rl.GetMousePosition()
switch mouse_state {
case .Hover:
if rl.IsMouseButtonPressed(.LEFT) {
return .DraggingGrid
} else if rect_has_point(rect2(matrix_container.area), mouse) {
return .HoverMatrices
}
case .DraggingGrid:
program.grid.inner_area = rect_translate(program.grid.inner_area, rl.GetMouseDelta())
if !rl.IsMouseButtonDown(.LEFT) {
return .Hover
}
case .HoverMatrices:
program.matrix_scroll = max(0, program.matrix_scroll - rl.GetMouseWheelMove() * program.matrix_scroll_speed)
if !rect_has_point(rect2(matrix_container.area), mouse) {
return .Hover
}
}
return mouse_state
}
program_build_workspace_ui :: proc(ctx: ^ui.Context) -> (elements: []ui.Element, matrix_container: ^ui.Element) {
ui.start(ctx, {0, 0}, {WINDOW_WIDTH, WINDOW_HEIGHT})
top_bar_container_config := ui.ElementConfiguration {margin = 4.0}
@ -404,6 +388,29 @@ program_build_workspace_ui :: proc(ctx: ^ui.Context) -> (elements: []ui.Element,
return
}
program_handle_mouse_workspace :: proc(mouse_state: MouseState, matrix_container: ^ui.Element) -> MouseState {
mouse := rl.GetMousePosition()
switch mouse_state {
case .Hover:
if rl.IsMouseButtonPressed(.LEFT) {
return .DraggingGrid
} else if rect_has_point(rect2(matrix_container.area), mouse) {
return .HoverMatrices
}
case .DraggingGrid:
program.grid.inner_area = rect_translate(program.grid.inner_area, rl.GetMouseDelta())
if !rl.IsMouseButtonDown(.LEFT) {
return .Hover
}
case .HoverMatrices:
program.matrix_scroll = max(0, program.matrix_scroll - rl.GetMouseWheelMove() * program.matrix_scroll_speed)
if !rect_has_point(rect2(matrix_container.area), mouse) {
return .Hover
}
}
return mouse_state
}
program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: ui.ElementId, font_style: FontStyle, elements: []ui.Element) -> (focus: ui.ElementId) {
scissor_container: ^ui.Element
render_above: ui.Element