diff --git a/example/main.odin b/example/main.odin index 9268b0b..2a5568f 100644 --- a/example/main.odin +++ b/example/main.odin @@ -39,8 +39,14 @@ UiElementData_FloatInput :: struct { value_string: cstring, } -ui_measure_text :: proc(str: cstring) -> ui.v2 { - return rl.MeasureTextEx(rl.GetFontDefault(), str, 18.0, 1.0) +TextStyle :: struct { + font: rl.Font, + size, spacing: f32, +} + +ui_measure_text :: proc(str: cstring, font_data: rawptr) -> ui.v2 { + style := cast(^TextStyle)font_data + return rl.MeasureTextEx(style.font, str, style.size, style.spacing) } main :: proc() { @@ -52,8 +58,9 @@ main :: proc() { defer rl.CloseWindow() rl.SetTargetFPS(WINDOW_FRAMERATE) + text_style := TextStyle {font = rl.GetFontDefault(), size = 18.0, spacing = 1.0} ctx: ui.Context - ui.init(&ctx, 4000, ui_measure_text) + ui.init(&ctx, 4000, ui_measure_text, &text_style) 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)) @@ -67,6 +74,7 @@ main :: proc() { element_focus_id := ui.element_id_invalid() debug_element_focus_id := ui.element_id_invalid() + for !rl.WindowShouldClose() { ui.start(&ctx, origin = {0, 0}, size = {WINDOW_WIDTH, WINDOW_HEIGHT}) for i in 0..<7 { @@ -112,7 +120,7 @@ main :: proc() { defer rl.EndDrawing() rl.ClearBackground(rl.BLACK) - render_ui_elements(&ctx, &element_focus_id, elements) + render_ui_elements(&ctx, &element_focus_id, text_style, 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)} @@ -124,6 +132,9 @@ main :: proc() { 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.element(.Label, {ui.SIZE_AUTO, ui.SIZE_AUTO}, {margin = V2_ONE * 4, label = "Text", color = {255, 255, 255, 255}}) + ui.element(.Label, {ui.SIZE_AUTO, ui.SIZE_AUTO}, {margin = V2_ONE * 4, label = "Ahhahahahahhahah", color = {255, 255, 255, 255}}) + ui.element(.Label, {ui.SIZE_AUTO, ui.SIZE_AUTO}, {margin = V2_ONE * 4, label = "Joker ui moment", color = {255, 255, 255, 255}}) ui.container_end() debug_elements := ui.end() @@ -131,7 +142,7 @@ main :: proc() { debug_element_focus_id = ui.focus_next_element(debug_element_focus_id, debug_elements, {.InputFloat}) } - render_ui_elements(&ctx, &debug_element_focus_id, debug_elements) + render_ui_elements(&ctx, &debug_element_focus_id, text_style, debug_elements) } } @@ -166,9 +177,10 @@ ui_input_float_2d :: proc(width, height: ui.Size_Percentage, config: ui.ElementC return container } -render_ui_elements :: proc(ctx: ^ui.Context, focus_element_id: ^ui.ElementId, elements: []ui.Element) { +render_ui_elements :: proc(ctx: ^ui.Context, focus_element_id: ^ui.ElementId, text_style: TextStyle, elements: []ui.Element) { for element in elements { area := rl.Rectangle(element.area) + color := rl.Color(element.color) #partial switch element.type { case .Container: dim := rl.Color {0, 0, 0, 192} @@ -204,6 +216,8 @@ render_ui_elements :: proc(ctx: ^ui.Context, focus_element_id: ^ui.ElementId, el if rl.GuiValueBoxFloat(area, element.label, data.value_string, data.value, element.id == focus_element_id^) == 1 { focus_element_id^ = element.id } + case .Label: + rl.DrawTextEx(text_style.font, element.label, ui.rect_get_tl(ui.rect2(area)), text_style.size, text_style.spacing, color) } } } diff --git a/ui.odin b/ui.odin index 5ee2bc4..24b87ea 100644 --- a/ui.odin +++ b/ui.odin @@ -16,7 +16,7 @@ rect_grow :: #force_inline proc(rect: rect2, amount: v2) -> rect2 {return {rect. ctx: ^Context -MeasureTextProc :: proc(cstring) -> v2 +MeasureTextProc :: proc(text: cstring, data: rawptr) -> v2 Context :: struct { origin: v2, @@ -25,7 +25,8 @@ Context :: struct { container_last_element: [dynamic]int, elements: [dynamic]Element, same_line: bool, - measure_text: MeasureTextProc, + measure_text_callback: MeasureTextProc, + measure_text_callback_data: rawptr, } CONTAINER_STACK_SIZE :: 16 @@ -42,7 +43,6 @@ Element :: struct { data: rawptr, type: ElementType, dimensions: Dimensions, - is_text: bool, } element_id_invalid :: proc() -> ElementId { @@ -94,11 +94,12 @@ Dimensions :: struct { Axis :: enum {X, Y} -init :: proc(ctx: ^Context, element_capacity: int, measure_text_callback: MeasureTextProc, allocator := context.allocator) { +init :: proc(ctx: ^Context, element_capacity: int, measure_text_callback: MeasureTextProc, measure_text_callback_data: rawptr, allocator := context.allocator) { ctx.containers = make(type_of(ctx.containers), 0, CONTAINER_STACK_SIZE, allocator) ctx.container_last_element = make(type_of(ctx.container_last_element), 0, CONTAINER_STACK_SIZE, allocator) ctx.elements = make(type_of(ctx.elements), 0, element_capacity, allocator) - ctx.measure_text = measure_text_callback + ctx.measure_text_callback = measure_text_callback + ctx.measure_text_callback_data = measure_text_callback_data } start :: proc(ui_context: ^Context, origin: v2, size: v2) { @@ -141,7 +142,7 @@ focus_next_element :: proc(id: ElementId, elements: []Element, allowed_focus: bi container_begin :: proc(dimensions: Dimensions, config: ElementConfiguration, data: rawptr = nil) -> ^Element { element := Element{config = config, type = .Container, dimensions = dimensions, data = data} - element.area = _resolve_element_area(element) + element.area = _resolve_element_area(element, is_text = false) ctx.container_count += 1 element_ref := _append_element(element) container_index := len(ctx.elements) - 1 @@ -189,8 +190,7 @@ element :: proc(element_type: ElementType, dimensions: Dimensions, config: Eleme assert(element_type != .Container) assert_auto_with_pixels(dimensions) element := Element{config = config, type = element_type, dimensions = dimensions, data = data} - element.is_text = element.type == .Label - element.area = _resolve_element_area(element) + element.area = _resolve_element_area(element, is_text = (element.type == .Label)) return _append_element(element) } @@ -211,14 +211,14 @@ _append_element :: proc(element: Element) -> ^Element { return element } -_resolve_element_area :: proc(element: Element) -> rect2 { +_resolve_element_area :: proc(element: Element, is_text: bool) -> rect2 { outer_position := _resolve_element_outer_position() - if !element.is_text { + if !is_text { outer_size := _resolve_element_outer_size(element.dimensions) return rect_grow(rect2{**outer_position, **outer_size}, -element.margin * 2.0) } - inner_position := ctx.measure_text(element.label) - return {**outer_position, **(inner_position + element.margin * 2.0)} + inner_position := ctx.measure_text_callback(element.label, ctx.measure_text_callback_data) + return {**(outer_position + element.margin), **(inner_position + element.margin)} } _resolve_element_outer_position :: proc() -> v2 {