diff --git a/program.odin b/program.odin index 453f4f0..3a74cb6 100644 --- a/program.odin +++ b/program.odin @@ -9,38 +9,67 @@ WINDOW_HEIGHT :: 720 WINDOW_FRAMERATE :: 30 WINDOW_CAPTION :: "Transformation Visualizer" -value: i32 -ui_style := UiStyle{margin = 4.0, padding = 4.0} -ui_state: UiState +program: Program + +Program :: struct { + ui_state: UiState, + matrices: [dynamic; 1024]f32, + matrix_type: MatrixType, +} + +MatrixType :: enum { + Mat2, + Mat3, + Mat4, +} + +@rodata matrix_type_table := [MatrixType]typeid { + .Mat2 = mat2, + .Mat3 = mat3, + .Mat4 = mat4, +} init :: proc() { rl.SetTraceLogLevel(.WARNING) rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT}) rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION) rl.SetTargetFPS(WINDOW_FRAMERATE) - ui_init(&ui_state, ui_style, {0, 0}, context.temp_allocator) + + ui_style := UiStyle{ + margin = 4.0, + padding = 4.0, + font = rl.GetFontDefault(), + font_size = 16.0, + font_sep = 1.0 + } + ui_init(&program.ui_state, ui_style, {0, 0}, context.temp_allocator) } update :: proc() { if rl.IsMouseButtonPressed(.LEFT) { - ui_element_focus_reset(&ui_state) + ui_element_focus_reset(&program.ui_state) } rl.BeginDrawing() defer rl.EndDrawing() rl.ClearBackground(rl.BLACK) - ui_start(&ui_state) + ui_button_size_top_bar := v2{32.0, 32.0} + ui_start(&program.ui_state) ui_container_begin({label = ""}) - ui_button_size := v2{192.0, 32.0} - ui_button(ui_button_size, {label = "Hi"}) + ui_button(ui_button_size_top_bar, {label = "#10#"}) ui_same_line() - ui_button(ui_button_size, {label = "Hi"}) + ui_button(ui_button_size_top_bar, {label = "#11#"}) ui_same_line() - ui_button(ui_button_size, {label = "Hi"}) - ui_input(ui_button_size, {label = "", value = &value, min = 0, max = 10}) + ui_button(ui_button_size_top_bar, {label = "#12#"}) + ui_container_end() + ui_container_begin({label = "Matrices"}) + if len(program.matrices) == 0 { + ui_text({text = "Add matrices", color = rl.WHITE}) + } else { + + } ui_container_end() - ui_button(ui_button_size, {label = "notheunoehunh"}) ui_elements := ui_end() for element in ui_elements { @@ -50,9 +79,9 @@ update :: proc() { rl.GuiButton(element.area, data.label) case .Input: data := element.data.(UiElementData_Input) - edit_mode := ui_element_is_editing(ui_state, element.id) + edit_mode := ui_element_is_editing(program.ui_state, element.id) if (rl.GuiValueBox(element.area, "", data.value, data.min, data.max, edit_mode) == 1) { - ui_element_focus(&ui_state, element.id) + ui_element_focus(&program.ui_state, element.id) } case .Container: data := element.data.(UiElementData_Container) @@ -61,6 +90,10 @@ update :: proc() { } else { rl.GuiGroupBox(element.area, data.label) } + case .Text: + data := element.data.(UiElementData_Text) + style := program.ui_state.style + rl.DrawTextEx(style.font, data.text, rect_get_tl(element.area), style.font_size, style.font_sep, data.color) } } diff --git a/ui.odin b/ui.odin index 3967707..b85430e 100644 --- a/ui.odin +++ b/ui.odin @@ -3,6 +3,7 @@ package main import "core:math/linalg" import "core:fmt" import "core:mem" +import rl "libraries/raylib" @(private="file") state_current: ^UiState @@ -10,12 +11,14 @@ UiElementType :: enum { Input, Button, Container, + Text, } UiElementData :: union { UiElementData_Button, UiElementData_Input, UiElementData_Container, + UiElementData_Text, } UiElement :: struct { @@ -42,7 +45,9 @@ UiState :: struct { } UiStyle :: struct { - margin, padding: f32, + margin, padding: f32, + font_size, font_sep: f32, + font: rl.Font, } ui_init :: proc(state: ^UiState, style: UiStyle, origin: v2, allocator: mem.Allocator) { @@ -118,6 +123,19 @@ ui_input :: proc(size: v2, data: UiElementData_Input) { append(&state.elements, UiElement{id = state.id_current, area = area, type = .Input, data = data}) } +UiElementData_Text :: struct { + text: cstring, + color: rl.Color, +} + +ui_text :: proc(data: UiElementData_Text) { + state := state_current + size := rl.MeasureTextEx(state.style.font, data.text, state.style.font_size, state.style.font_sep) + area := _ui_advance_element(state, size) + state.id_current.element_index += 1 + append(&state.elements, UiElement{id = state.id_current, area = area, type = .Text, data = data}) +} + ui_same_line :: proc() { state_current.same_line = true } diff --git a/utility.odin b/utility.odin deleted file mode 100644 index 825e7c3..0000000 --- a/utility.odin +++ /dev/null @@ -1,115 +0,0 @@ -package main - -import rl "libraries/raylib" -import "core:math/linalg" - -v1 :: [1]f32 -v2 :: [2]f32 -v3 :: [3]f32 -v4 :: [4]f32 -iv2 :: [2]i32 -iv3 :: [3]i32 -iv4 :: [4]i32 -mat2 :: matrix[2, 2]f32 -mat3 :: matrix[3, 3]f32 -mat4 :: matrix[4, 4]f32 -rect2 :: rl.Rectangle -irect2 :: struct {x, y, width, height: i32} -tri2 :: [3]v2 -Bezier :: [3]v2 - -/// ### GEOMETRY ### /// -rect_from :: proc { - rect2_from_v2, - irect2_from_iv2, -} - -@(private="file") rect2_from_v2 :: proc "contextless" (position, size: v2) -> rect2 { - return {position.x, position.y, size.x, size.y} -} - -@(private="file") irect2_from_iv2 :: proc "contextless" (position, size: iv2) -> irect2 { - return {position.x, position.y, size.x, size.y} -} - -rect_scale :: proc{ - rect2_scale, - irect2_scale, -} - -@(private="file") rect2_scale :: proc "contextless" (rect: rect2, scalar: f32) -> rect2 { - return {rect.x * scalar, rect.y * scalar, rect.width * scalar, rect.height * scalar} -} - -@(private="file") irect2_scale :: proc "contextless" (rect: irect2, scalar: i32) -> irect2 { - return {rect.x * scalar, rect.y * scalar, rect.width * scalar, rect.height * scalar} -} - -rect_grow :: proc { - rect2_grow, - rect2_grow_v2, - irect2_grow, - rect2_grow_iv2, -} - -@(private="file") rect2_grow :: proc "contextless" (rect: rect2, grow: f32) -> rect2 { - return {rect.x - grow, rect.y - grow, rect.width + grow * 2.0, rect.height + grow * 2.0} -} - -@(private="file") rect2_grow_v2 :: proc "contextless" (rect: rect2, grow: v2) -> rect2 { - return {rect.x - grow.x, rect.y - grow.y, rect.width + grow.x * 2.0, rect.height + grow.y * 2.0} -} - -@(private="file") irect2_grow :: proc "contextless" (rect: irect2, grow: i32) -> irect2 { - return {rect.x - grow, rect.y - grow, rect.width + grow * 2, rect.height + grow * 2} -} - -@(private="file") rect2_grow_iv2 :: proc "contextless" (rect: irect2, grow: iv2) -> irect2 { - return {rect.x - grow.x, rect.y - grow.y, rect.width + grow.x * 2.0, rect.height + grow.y * 2.0} -} - - -rect_from_area :: proc { - rect_from_area_v2, - rect_from_area_iv2, -} - -@(private="file") rect_from_area_v2 :: proc "contextless" (start, end: v2) -> rect2 { - tl := linalg.min(start, end) - return {**tl, **(linalg.max(start, end) - tl)} -} - -@(private="file") rect_from_area_iv2 :: proc "contextless" (start, end: iv2) -> irect2 { - tl := linalg.min(start, end) - return {**tl, **(linalg.max(start, end) - tl)} -} - -rect_from_corners :: proc { - rect2_from_corners, - irect2_from_corners, -} - -@(private="file") rect2_from_corners :: proc "contextless" (tl, tr, br, bl: v2) -> rect2 { - top_left := linalg.min(linalg.min(tl, tr, br), bl) - bottom_right := linalg.max(linalg.max(tl, tr, br), bl) - return {**top_left, **(bottom_right - top_left)} -} - -@(private="file") irect2_from_corners :: proc "contextless" (tl, tr, br, bl: iv2) -> irect2 { - top_left := linalg.min(linalg.min(tl, tr, br), bl) - bottom_right := linalg.max(linalg.max(tl, tr, br), bl) - return {**top_left, **(bottom_right - top_left)} -} - -rect_get_br :: proc { - rect2_get_br, - irect2_get_br, -} - -@(private="file") rect2_get_br :: proc(rect: rect2) -> v2 { - return {rect.x + rect.width, rect.y + rect.height} -} - -@(private="file") irect2_get_br :: proc(rect: irect2) -> iv2 { - return {rect.x + rect.width, rect.y + rect.height} -} diff --git a/utils.odin b/utils.odin index 77cba13..f1cee0c 100644 --- a/utils.odin +++ b/utils.odin @@ -1,7 +1,9 @@ -// Wraps os.read_entire_file and os.write_entire_file, but they also work with emscripten. - package main +import rl "libraries/raylib" +import "core:math/linalg" + +// Wraps os.read_entire_file and os.write_entire_file, but they also work with emscripten. @(require_results) read_entire_file :: proc(name: string, allocator := context.allocator, loc := #caller_location) -> (data: []byte, success: bool) { return _read_entire_file(name, allocator, loc) @@ -10,3 +12,127 @@ read_entire_file :: proc(name: string, allocator := context.allocator, loc := #c write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (success: bool) { return _write_entire_file(name, data, truncate) } + +v1 :: [1]f32 +v2 :: [2]f32 +v3 :: [3]f32 +v4 :: [4]f32 +iv2 :: [2]i32 +iv3 :: [3]i32 +iv4 :: [4]i32 +mat2 :: matrix[2, 2]f32 +mat3 :: matrix[3, 3]f32 +mat4 :: matrix[4, 4]f32 +rect2 :: rl.Rectangle +irect2 :: struct {x, y, width, height: i32} +tri2 :: [3]v2 +Bezier :: [3]v2 + +/// ### RECTANGLES ### /// +rect_from :: proc { + rect2_from_v2, + irect2_from_iv2, +} + +@(private="file") rect2_from_v2 :: proc "contextless" (position, size: v2) -> rect2 { + return {position.x, position.y, size.x, size.y} +} + +@(private="file") irect2_from_iv2 :: proc "contextless" (position, size: iv2) -> irect2 { + return {position.x, position.y, size.x, size.y} +} + +rect_scale :: proc{ + rect2_scale, + irect2_scale, +} + +@(private="file") rect2_scale :: proc "contextless" (rect: rect2, scalar: f32) -> rect2 { + return {rect.x * scalar, rect.y * scalar, rect.width * scalar, rect.height * scalar} +} + +@(private="file") irect2_scale :: proc "contextless" (rect: irect2, scalar: i32) -> irect2 { + return {rect.x * scalar, rect.y * scalar, rect.width * scalar, rect.height * scalar} +} + +rect_grow :: proc { + rect2_grow, + rect2_grow_v2, + irect2_grow, + rect2_grow_iv2, +} + +@(private="file") rect2_grow :: proc "contextless" (rect: rect2, grow: f32) -> rect2 { + return {rect.x - grow, rect.y - grow, rect.width + grow * 2.0, rect.height + grow * 2.0} +} + +@(private="file") rect2_grow_v2 :: proc "contextless" (rect: rect2, grow: v2) -> rect2 { + return {rect.x - grow.x, rect.y - grow.y, rect.width + grow.x * 2.0, rect.height + grow.y * 2.0} +} + +@(private="file") irect2_grow :: proc "contextless" (rect: irect2, grow: i32) -> irect2 { + return {rect.x - grow, rect.y - grow, rect.width + grow * 2, rect.height + grow * 2} +} + +@(private="file") rect2_grow_iv2 :: proc "contextless" (rect: irect2, grow: iv2) -> irect2 { + return {rect.x - grow.x, rect.y - grow.y, rect.width + grow.x * 2.0, rect.height + grow.y * 2.0} +} + + +rect_from_area :: proc { + rect_from_area_v2, + rect_from_area_iv2, +} + +@(private="file") rect_from_area_v2 :: proc "contextless" (start, end: v2) -> rect2 { + tl := linalg.min(start, end) + return {**tl, **(linalg.max(start, end) - tl)} +} + +@(private="file") rect_from_area_iv2 :: proc "contextless" (start, end: iv2) -> irect2 { + tl := linalg.min(start, end) + return {**tl, **(linalg.max(start, end) - tl)} +} + +rect_from_corners :: proc { + rect2_from_corners, + irect2_from_corners, +} + +@(private="file") rect2_from_corners :: proc "contextless" (tl, tr, br, bl: v2) -> rect2 { + top_left := linalg.min(linalg.min(tl, tr, br), bl) + bottom_right := linalg.max(linalg.max(tl, tr, br), bl) + return {**top_left, **(bottom_right - top_left)} +} + +@(private="file") irect2_from_corners :: proc "contextless" (tl, tr, br, bl: iv2) -> irect2 { + top_left := linalg.min(linalg.min(tl, tr, br), bl) + bottom_right := linalg.max(linalg.max(tl, tr, br), bl) + return {**top_left, **(bottom_right - top_left)} +} + +rect_get_tl :: proc { + rect2_get_tl, + irect2_get_tl, +} + +@(private="file") rect2_get_tl :: proc(rect: rect2) -> v2 { + return {rect.x, rect.y} +} + +@(private="file") irect2_get_tl :: proc(rect: irect2) -> iv2 { + return {rect.x, rect.y} +} + +rect_get_br :: proc { + rect2_get_br, + irect2_get_br, +} + +@(private="file") rect2_get_br :: proc(rect: rect2) -> v2 { + return {rect.x + rect.width, rect.y + rect.height} +} + +@(private="file") irect2_get_br :: proc(rect: irect2) -> iv2 { + return {rect.x + rect.width, rect.y + rect.height} +}