package main import rl "raylib" import ui ".." import "core:fmt" WINDOW_WIDTH :: 1280 WINDOW_HEIGHT :: 720 WINDOW_CAPTION :: "Immediate mode GUI" WINDOW_FRAMERATE :: 60 INPUT_FLOAT_CHARACTERS :: 32 v2 :: [2]f32 V2_ONE :: v2{1.0, 1.0} main :: proc() { rl.SetTraceLogLevel(.WARNING) rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION) defer rl.CloseWindow() rl.SetTargetFPS(WINDOW_FRAMERATE) ctx: ui.Context ui.init(&ctx, 4000) outer_container_config := ui.ElementConfiguration {margin = {4.0, 8.0}, padding = {12.0, 24.0}, color = ui.col(rl.RED), label = ""} outer_container_margin_value_string_x := cstring(make([^]u8, INPUT_FLOAT_CHARACTERS)) outer_container_margin_value_string_y := cstring(make([^]u8, INPUT_FLOAT_CHARACTERS)) inner_container_config := ui.ElementConfiguration {color = cast(ui.col)rl.GREEN, label = "", margin = {4.0, 4.0}} inner_container_margin_value_string_x := cstring(make([^]u8, INPUT_FLOAT_CHARACTERS)) inner_container_margin_value_string_y := cstring(make([^]u8, INPUT_FLOAT_CHARACTERS)) button_config := ui.ElementConfiguration {margin = {4.0, 4.0}} button_margin_value_string_x := cstring(make([^]u8, INPUT_FLOAT_CHARACTERS)) button_margin_value_string_y := cstring(make([^]u8, INPUT_FLOAT_CHARACTERS)) for !rl.WindowShouldClose() { ui.start(&ctx, origin = {0, 0}, size = {WINDOW_WIDTH, WINDOW_HEIGHT}) for i in 0..<7 { ui.container_begin(dimensions = {ui.SIZE_AUTO, ui.Size_Percentage(0.1)}, config = inner_container_config) for j in 0..<10 { config := button_config config.label = fmt.ctprintf("%d", i * 10 + j) ui.button(dimensions = {ui.Size_Pixels(64.0), ui.Size_Percentage(1.0)}, config = config) ui.same_line() } ui.container_end() } ui.container_begin(dimensions = {ui.SIZE_AUTO, ui.Size_Percentage(0.2)}, config = inner_container_config) for j in 0..<10 { config := button_config config.label = fmt.ctprintf("%d", 70 + j) ui.button(dimensions = {ui.Size_Pixels(64.0), ui.Size_Percentage(0.5)}, config = config) ui.same_line() } ctx.same_line = false for j in 0..<10 { config := button_config config.label = fmt.ctprintf("%d", 80 + j) ui.button(dimensions = {ui.Size_Pixels(64.0), ui.Size_Percentage(0.5)}, config = config) ui.same_line() } ui.container_end() ui.container_begin(dimensions = {ui.Size_Percentage(1.0), ui.Size_PercentageRemainder(1.0)}, config = inner_container_config) for j in 0..<10 { config := button_config config.label = fmt.ctprintf("%d", 90 + j) ui.button(dimensions = {ui.Size_Percentage(0.1), ui.Size_Percentage(1.0)}, config = config) ui.same_line() } ui.container_end() elements := ui.end() rl.BeginDrawing() defer rl.EndDrawing() rl.ClearBackground(rl.BLACK) render_ui_elements(&ctx, elements) ui.start(&ctx, {0, 0}, {WINDOW_WIDTH, WINDOW_HEIGHT}) config := ui.ElementConfiguration{margin = V2_ONE * 4, padding = V2_ONE * 4, color = ui.col(rl.MAGENTA)} ui.container_begin({ui.Size_Percentage(0.3), ui.Size_Percentage(0.3)}, config) slider_config := config slider_config.label = "Outer container margin" ui_input_float_2d(1.0, 0.2, slider_config, &outer_container_config.margin, outer_container_margin_value_string_x, outer_container_margin_value_string_y) slider_config.label = "Inner container margin" ui_input_float_2d(1.0, 0.2, slider_config, &inner_container_config.margin, inner_container_margin_value_string_x, inner_container_margin_value_string_y) slider_config.label = "Button margin" ui_input_float_2d(1.0, 0.2, slider_config, &button_config.margin, button_margin_value_string_x, button_margin_value_string_y) ui.container_end() debug_elements := ui.end() if rl.IsKeyPressed(.TAB) { ui.focus_next_element(&ctx, {.InputFloat}) } render_ui_elements(&ctx, debug_elements) } } ElementData_Slider :: struct { min, max: f32, value: ^f32, } ElementData_FloatInput :: struct { value: ^f32, value_string: cstring, } ui_slider_2d :: proc(width, height: ui.Size_Percentage, config: ui.ElementConfiguration, value: ^v2, min: f32, max: f32, allocator := context.temp_allocator) -> ^ui.Element { container := ui.container_begin(dimensions = {width, height}, config = config) dimensions := ui.Dimensions {ui.Size_Percentage(0.5), ui.Size_Percentage(1.0)} data: ^ElementData_Slider data = new(ElementData_Slider, allocator) data^ = {value = &value.x, min = min, max = max} ui.slider(dimensions, {margin = config.margin}, data) ui.same_line() data = new(ElementData_Slider, allocator) data^ = {value = &value.y, min = min, max = max} ui.slider(dimensions, {margin = config.margin}, data) ui.container_end() return container } ui_input_float_2d :: proc(width, height: ui.Size_Percentage, config: ui.ElementConfiguration, value: ^v2, value_string_x, value_string_y: cstring, allocator := context.temp_allocator) -> ^ui.Element { container := ui.container_begin(dimensions = {width, height}, config = config) dimensions := ui.Dimensions {ui.Size_Percentage(0.5), ui.Size_Percentage(1.0)} data: ^ElementData_FloatInput data = new(ElementData_FloatInput, allocator) data^ = {value_string = value_string_x, value = &value.x} ui.input_float(dimensions, {margin = config.margin}, data) ui.same_line() data = new(ElementData_FloatInput, allocator) data^ = {value_string = value_string_x, value = &value.x} ui.input_float(dimensions, {margin = config.margin}, data) ui.container_end() return container } render_ui_elements :: proc(ctx: ^ui.Context, elements: []ui.Element) { for element in elements { area := rl.Rectangle(element.area) switch element.type { case .Container: rl.DrawRectangleRounded(area, 0.1, 4.0, {0, 0, 0, 192}) rl.GuiGroupBox(area, element.label) case .Button: rl.GuiButton(area, element.label) case .Slider: data := cast(^ElementData_Slider)element.data rl.GuiSlider(area, "", "", data.value, data.min, data.max) case .InputFloat: data := cast(^ElementData_FloatInput)element.data if rl.GuiValueBoxFloat(area, element.label, data.value_string, data.value, ui.is_element_focused(ctx, element)) == 1 { ui.focus_element(ctx, element) } } } }