From 9b94f02a2729dacb3990b347b4aff08473b2b31f Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 30 Dec 2025 02:38:57 -0600 Subject: [PATCH] floating position anchors --- src/base/base.cgh | 3 + src/base/base_inc.h | 2 +- src/base/base_math.h | 66 +++---- src/pp/pp_vis/pp_vis_core.c | 69 ++++--- src/pp/pp_vis/pp_vis_core.h | 4 +- src/ui/ui_core.c | 373 ++++++++++++++++++++---------------- src/ui/ui_core.h | 58 +++--- src/ui/ui_extras.c | 2 +- 8 files changed, 315 insertions(+), 262 deletions(-) diff --git a/src/base/base.cgh b/src/base/base.cgh index f7b1ba60..c64b765a 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -406,6 +406,9 @@ #define AlignedStruct(name, n) typedef struct name name; struct alignas(n) name #define AlignedBlock(n) struct alignas(n) +//- Union +#define Union(name) typedef union name name; union name + //- Enum #if IsLanguageC #define Enum(name) typedef enum name name; enum name diff --git a/src/base/base_inc.h b/src/base/base_inc.h index 01634877..644baf48 100644 --- a/src/base/base_inc.h +++ b/src/base/base_inc.h @@ -5,7 +5,6 @@ //- Api #include "base.cgh" #if IsLanguageC - #include "base_tweak.h" #include "base_intrinsics.h" #include "base_memory.h" #include "base_arena.h" @@ -27,6 +26,7 @@ #include "base_resource.h" #include "base_controller.h" #include "base_async.h" + #include "base_tweak.h" #include "base_state.h" #elif IsLanguageG #include "base_shader.gh" diff --git a/src/base/base_math.h b/src/base/base_math.h index 0ee4db1e..d74425a7 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -22,12 +22,12 @@ Enum(Axis) //- Vec2 -Struct(Vec2) { f32 x, y; }; -Struct(Vec2F64) { f64 x, y; }; -Struct(Vec2I32) { i32 x, y; }; -Struct(Vec2I64) { i64 x, y; }; -Struct(Vec2U32) { i32 x, y; }; -Struct(Vec2U64) { u64 x, y; }; +Union(Vec2) { struct { f32 x, y; }; f32 v[2]; }; +Union(Vec2F64) { struct { f64 x, y; }; f64 v[2]; }; +Union(Vec2I32) { struct { i32 x, y; }; i32 v[2]; }; +Union(Vec2I64) { struct { i64 x, y; }; i64 v[2]; }; +Union(Vec2U32) { struct { u32 x, y; }; u32 v[2]; }; +Union(Vec2U64) { struct { u64 x, y; }; u64 v[2]; }; Struct(Vec2Array) { Vec2 *points; u64 count; }; @@ -47,12 +47,12 @@ Struct(Vec2Array) { Vec2 *points; u64 count; }; //- Vec3 -Struct(Vec3) { f32 x, y, z; }; -Struct(Vec3F64) { f64 x, y, z; }; -Struct(Vec3I32) { i32 x, y, z; }; -Struct(Vec3I64) { i64 x, y, z; }; -Struct(Vec3U32) { i32 x, y, z; }; -Struct(Vec3U64) { u64 x, y, z; }; +Union(Vec3) { struct { f32 x, y, z; }; f32 v[3]; }; +Union(Vec3F64) { struct { f64 x, y, z; }; f64 v[3]; }; +Union(Vec3I32) { struct { i32 x, y, z; }; i32 v[3]; }; +Union(Vec3I64) { struct { i64 x, y, z; }; i64 v[3]; }; +Union(Vec3U32) { struct { u32 x, y, z; }; u32 v[3]; }; +Union(Vec3U64) { struct { u64 x, y, z; }; u64 v[3]; }; Struct(Vec3Array) { Vec3 *points; u64 count; }; @@ -72,12 +72,12 @@ Struct(Vec3Array) { Vec3 *points; u64 count; }; //- Vec4 -Struct(Vec4) { f32 x, y, z, w; }; -Struct(Vec4F64) { f64 x, y, z, w; }; -Struct(Vec4I32) { i32 x, y, z, w; }; -Struct(Vec4I64) { i64 x, y, z, w; }; -Struct(Vec4U32) { i32 x, y, z, w; }; -Struct(Vec4U64) { u64 x, y, z, w; }; +Union(Vec4) { struct { f32 x, y, z, w; }; f32 v[4]; }; +Union(Vec4F64) { struct { f64 x, y, z, w; }; f64 v[4]; }; +Union(Vec4I32) { struct { i32 x, y, z, w; }; i32 v[4]; }; +Union(Vec4I64) { struct { i64 x, y, z, w; }; i64 v[4]; }; +Union(Vec4U32) { struct { u32 x, y, z, w; }; u32 v[4]; }; +Union(Vec4U64) { struct { u64 x, y, z, w; }; u64 v[4]; }; Struct(Vec4Array) { Vec4 *points; u64 count; }; @@ -100,11 +100,11 @@ Struct(Vec4Array) { Vec4 *points; u64 count; }; //- Rng1 -Struct(Rng) { f32 min; f32 max; }; -Struct(RngI32) { i32 min; i32 max; }; -Struct(RngI64) { i64 min; i64 max; }; -Struct(RngU32) { u32 min; u32 max; }; -Struct(RngU64) { u64 min; u64 max; }; +Struct(Rng) { f32 min, max; }; +Struct(RngI32) { i32 min, max; }; +Struct(RngI64) { i64 min, max; }; +Struct(RngU32) { u32 min, max; }; +Struct(RngU64) { u64 min, max; }; #define RNG(min, max) (Rng) { (min), (max) } #define RNGI32(min, max) (RngI32) { (min), (max) } @@ -114,11 +114,11 @@ Struct(RngU64) { u64 min; u64 max; }; //- Rng2 -Struct(Rng2) { Vec2 p0; Vec2 p1; }; -Struct(Rng2I32) { Vec2I32 p0; Vec2I32 p1; }; -Struct(Rng2I64) { Vec2I64 p0; Vec2I64 p1; }; -Struct(Rng2U32) { Vec2U32 p0; Vec2U32 p1; }; -Struct(Rng2U64) { Vec2U64 p0; Vec2U64 p1; }; +Struct(Rng2) { Vec2 p0, p1; }; +Struct(Rng2I32) { Vec2I32 p0, p1; }; +Struct(Rng2I64) { Vec2I64 p0, p1; }; +Struct(Rng2U32) { Vec2U32 p0, p1; }; +Struct(Rng2U64) { Vec2U64 p0, p1; }; #define RNG2(p0, p1) (Rng2) { (p0), (p1) } #define RNG2I32(p0, p1) (Rng2I32) { (p0), (p1) } @@ -128,11 +128,11 @@ Struct(Rng2U64) { Vec2U64 p0; Vec2U64 p1; }; //- Rng3 -Struct(Rng3) { Vec3 p0; Vec3 p1; }; -Struct(Rng3I32) { Vec3I32 p0; Vec3I32 p1; }; -Struct(Rng3I64) { Vec3I64 p0; Vec3I64 p1; }; -Struct(Rng3U32) { Vec3U32 p0; Vec3U32 p1; }; -Struct(Rng3U64) { Vec3U64 p0; Vec3U64 p1; }; +Struct(Rng3) { Vec3 p0, p1; }; +Struct(Rng3I32) { Vec3I32 p0, p1; }; +Struct(Rng3I64) { Vec3I64 p0, p1; }; +Struct(Rng3U32) { Vec3U32 p0, p1; }; +Struct(Rng3U64) { Vec3U64 p0, p1; }; #define RNG3(p0, p1) (Rng3) { (p0), (p1) } #define RNG3I32(p0, p1) (Rng3I32) { (p0), (p1) } diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 64446451..950a7292 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -239,7 +239,6 @@ void V_TickForever(WaveLaneCtx *lane) frame->palette = last_frame->palette; frame->is_editing = last_frame->is_editing; frame->ui_debug = last_frame->ui_debug; - frame->show_palette = last_frame->show_palette; frame->show_console = last_frame->show_console; frame->look = last_frame->look; frame->edit_mode = last_frame->edit_mode; @@ -810,14 +809,9 @@ void V_TickForever(WaveLaneCtx *lane) UI_Report divider_rep = UI_ReportFromKey(resize_panel->divider_key); f32 child_pref_size = 0; - if (panel->axis == Axis_X) - { - child_pref_size = frame->ui_cursor.x - child_rep.screen_rect.p0.x - divider_rep.last_mouse_down_cursor_offset.x; - } - else - { - child_pref_size = frame->ui_cursor.y - child_rep.screen_rect.p0.y - divider_rep.last_mouse_down_cursor_offset.y; - } + child_pref_size += frame->ui_cursor.v[panel->axis]; + child_pref_size -= child_rep.screen_anchor.v[panel->axis]; + child_pref_size -= divider_rep.last_cursor_down_anchor_offset.v[panel->axis]; f32 ratio_diff = (child_pref_size / panel_size) - resize_panel->pref_ratio; f32 min_ratio = 0.05; @@ -988,7 +982,7 @@ void V_TickForever(WaveLaneCtx *lane) f32 drag_threshold = 20; if (tab_rep.m1.held) { - Vec2 drag_start = AddVec2(tab_rep.screen_rect.p0, tab_rep.last_mouse_down_cursor_offset); + Vec2 drag_start = AddVec2(tab_rep.screen_anchor, tab_rep.last_cursor_down_anchor_offset); if (Vec2Len(SubVec2(frame->ui_cursor, drag_start)) > drag_threshold) { V.dragging_window = window; @@ -1034,14 +1028,14 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Border, 1); UI_SetNext(Width, UI_SHRINK(0, 0)); UI_SetNext(Height, UI_SHRINK(0, 0)); - UI_SetNext(ChildAlignment, UI_Alignment_Left); + UI_SetNext(ChildAlignment, UI_Region_Left); UI_SetNext(Flags, UI_BoxFlag_Interactable | (UI_BoxFlag_Selected * (active_window == window))); UI_SetNext(Text, tab_name); UI_PushCP(UI_BuildRowEx(tab->key)); { // Build tab title { - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(Flags, UI_BoxFlag_DrawText); UI_SetNext(Text, tab_name); UI_SetNext(Width, UI_SHRINK(6, 0)); @@ -1062,7 +1056,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(BackgroundColor, close_color); UI_SetNext(BorderColor, close_border_color); UI_SetNext(Border, 2); - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); UI_SetNext(Text, Lit("x")); UI_SetNext(Width, UI_SHRINK(6, 0)); @@ -1099,7 +1093,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Border, 2); UI_SetNext(Width, UI_PIX(30, 0)); UI_SetNext(Height, UI_GROW(1, 0)); - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); // UI_SetNext(FontSize, theme.font_size * 1.5); UI_PushCP(UI_BuildRowEx(tab->key)); { @@ -1126,7 +1120,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Border, 2); UI_SetNext(Width, UI_SHRINK(10, 0)); UI_SetNext(Height, UI_SHRINK(2, 0)); - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); // UI_SetNext(FontSize, theme.font_size * 1.5); UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); UI_SetNext(Text, Lit("+")); @@ -1190,7 +1184,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Flags, UI_BoxFlag_Interactable | (UI_BoxFlag_Selected * is_selected)); UI_PushCP(UI_BuildRowEx(key)); { - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(Text, name); UI_SetNext(Flags, UI_BoxFlag_DrawText); UI_SetNext(Width, UI_SHRINK(4, 0)); @@ -1285,6 +1279,8 @@ void V_TickForever(WaveLaneCtx *lane) //- Build command palette V_Palette *palette = &frame->palette; + palette->show = LerpF32(palette->show, palette->pref_show, 30.0 * frame->dt); + if (palette->show > 0.001) { palette->key = UI_KeyF("command palette"); UI_Checkpoint palette_cp = UI_PushCP(UI_NilKey); @@ -1292,27 +1288,21 @@ void V_TickForever(WaveLaneCtx *lane) UI_Push(Tag, palette->key.hash); UI_Key titlebar_key = UI_KeyF("title bar"); UI_Report titlebar_rep = UI_ReportFromKey(titlebar_key); - UI_Report widget_rep = UI_ReportFromKey(palette->key); - Vec2 widget_half_dims = MulVec2(DimsFromRng2(widget_rep.screen_rect), 0.5); + UI_Report palette_rep = UI_ReportFromKey(palette->key); Vec4 window_background_color = theme.window_background_color; - // Vec4 window_background_color = VEC4(0, 0, 0, 0); Vec4 window_border_color = theme.window_border_color; Vec4 titlebar_color = Zi; Vec4 titlebar_border_color = Zi; Vec4 divider_color = theme.divider_color; if (titlebar_rep.m1.held) { - palette->pos = AddVec2(SubVec2(frame->ui_cursor, titlebar_rep.last_mouse_down_cursor_offset), widget_half_dims); + palette->pos = SubVec2(frame->ui_cursor, palette_rep.last_cursor_down_anchor_offset); } window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot); - UI_Push(Scale, LerpF32(0.75, 1, widget_rep.selected)); - UI_Push(Tint, VEC4(1, 1, 1, widget_rep.selected)); - if (widget_rep.selected < 0.25) - { - UI_Push(OmitFlags, UI_UseTop(OmitFlags) | UI_BoxFlag_Interactable); - } + UI_Push(Scale, LerpF32(0.75, 1, palette->show)); + UI_Push(Tint, VEC4(1, 1, 1, palette->show)); UI_Push(BackgroundColor, window_background_color); UI_Push(BorderColor, window_border_color); @@ -1321,8 +1311,9 @@ void V_TickForever(WaveLaneCtx *lane) UI_Push(Width, UI_PIX(theme.window_width, 0)); UI_Push(Height, UI_SHRINK(0, 0)); UI_Push(ChildLayoutAxis, Axis_Y); - UI_Push(FloatingPos, SubVec2(palette->pos, widget_half_dims)); - UI_SetNext(Flags, UI_BoxFlag_Floating | (UI_BoxFlag_Selected * frame->show_palette)); + UI_Push(FloatingPos, palette->pos); + UI_SetNext(FloatingPosAnchor, UI_Region_Center); + UI_SetNext(Flags, UI_BoxFlag_Floating); UI_PushCP(UI_BuildBoxEx(palette->key)); { // Title bar @@ -1345,7 +1336,7 @@ void V_TickForever(WaveLaneCtx *lane) // Title box UI_SetNext(FontSize, theme.window_title_font_size); - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(Width, UI_SHRINK(0, 1)); UI_SetNext(Text, Lit("Command Palette")); UI_SetNext(Flags, UI_BoxFlag_DrawText); @@ -1460,8 +1451,12 @@ void V_TickForever(WaveLaneCtx *lane) Vec4 item_color = theme.window_background_color; item_color = LerpSrgb(item_color, theme.button_hot_color, item_rep.hot); - item_color = LerpSrgb(item_color, theme.button_active_color, item_rep.active); - Vec4 item_border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, item_rep.hot); + Vec4 item_border_color = Zi; + if (item->flags & PaletteItemFlag_IsCmd) + { + item_color = LerpSrgb(item_color, theme.button_active_color, item_rep.active); + item_border_color = LerpSrgb(item_border_color, theme.button_active_color, item_rep.hot); + } UI_SetNext(BorderColor, 0); UI_SetNext(Rounding, UI_RPIX(0)); @@ -1472,7 +1467,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Rounding, UI_RPIX(5)); UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Height, UI_FNT(1.5, 1)); - UI_SetNext(ChildAlignment, UI_Alignment_Left); + UI_SetNext(ChildAlignment, UI_Region_Left); UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); UI_PushCP(UI_BuildRowEx(item->key)); { @@ -1482,7 +1477,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_BuildSpacer(UI_PIX(20, 1), Axis_X); // Command label - UI_SetNext(ChildAlignment, UI_Alignment_Left); + UI_SetNext(ChildAlignment, UI_Region_Left); UI_BuildLabel(item->display_name); // Middle spacer @@ -1568,7 +1563,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Height, UI_GROW(1, 0)); UI_SetNext(Rounding, UI_RPIX(5)); UI_SetNext(Border, 1); - UI_SetNext(ChildAlignment, UI_Alignment_Center); + UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); UI_PushCP(UI_BuildRowEx(hotkey_key)); { @@ -1618,7 +1613,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_PushCP(UI_BuildColumn()); { // UI_BuildSpacer(UI_PIX(10, 1), Axis_X); - // UI_Push(ChildAlignment, UI_Alignment_Center); + // UI_Push(ChildAlignment, UI_Region_Center); // UI_SetNext(Width, UI_SHRINK(0, 1)); // UI_SetNext(Height, UI_SHRINK(0, 1)); UI_SetNext(Width, UI_SHRINK(0, 1)); @@ -1790,7 +1785,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_Push(BorderColor, Rgb(0.25, 0.25, 0.25)); UI_Push(Rounding, UI_RPIX(0)); UI_Push(Border, 1); - UI_Push(ChildAlignment, UI_Alignment_Left); + UI_Push(ChildAlignment, UI_Region_Left); UI_PushCP(UI_BuildRow()); { // UI_SetNext(Height, UI_PIX(100, 0)); @@ -1839,7 +1834,7 @@ void V_TickForever(WaveLaneCtx *lane) case V_CmdKind_toggle_palette: { - frame->show_palette = !frame->show_palette; + frame->palette.pref_show = !frame->palette.pref_show; } break; case V_CmdKind_zoom_in: diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index 90454f70..b1772fcf 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -120,6 +120,9 @@ Struct(V_Palette) // Persistent state Vec2 pos; UI_Key key; + + f32 pref_show; + f32 show; }; //////////////////////////////////////////////////////////// @@ -197,7 +200,6 @@ Struct(V_Frame) // Modes b32 is_editing; b32 ui_debug; - b32 show_palette; b32 show_console; // Editor state diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 39e18475..31879b7e 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -76,6 +76,97 @@ UI_Box *UI_BoxFromKey(UI_Key key) return box; } +//////////////////////////////////////////////////////////// +//~ Anchor helpers + +UI_Region UI_RegionFromPair(UI_RegionPair pair) +{ + UI_Region result = 0; + switch(pair.y) + { + case UI_AxisRegion_Start: + { + switch(pair.x) + { + case UI_AxisRegion_Start: { result = UI_Region_TopLeft; } break; + case UI_AxisRegion_Center: { result = UI_Region_Top; } break; + case UI_AxisRegion_End: { result = UI_Region_TopRight; } break; + } + } break; + case UI_AxisRegion_Center: + { + switch(pair.x) + { + case UI_AxisRegion_Start: { result = UI_Region_Left; } break; + case UI_AxisRegion_Center: { result = UI_Region_Center; } break; + case UI_AxisRegion_End: { result = UI_Region_Right; } break; + } + } break; + case UI_AxisRegion_End: + { + switch(pair.x) + { + case UI_AxisRegion_Start: { result = UI_Region_BottomLeft; } break; + case UI_AxisRegion_Center: { result = UI_Region_Bottom; } break; + case UI_AxisRegion_End: { result = UI_Region_BottomRight; } break; + } + } break; + } + return result; +} + +UI_RegionPair UI_PairFromRegion(UI_Region region) +{ + UI_RegionPair result = Zi; + // Horizontal + switch(region) + { + default: break; + case UI_Region_TopLeft: + case UI_Region_Left: + case UI_Region_BottomLeft: + { + result.x = UI_AxisRegion_Start; + } break; + case UI_Region_Top: + case UI_Region_Center: + case UI_Region_Bottom: + { + result.x = UI_AxisRegion_Center; + } break; + case UI_Region_TopRight: + case UI_Region_Right: + case UI_Region_BottomRight: + { + result.x = UI_AxisRegion_End; + } break; + } + // Vertical + switch(region) + { + default: break; + case UI_Region_TopLeft: + case UI_Region_Top: + case UI_Region_TopRight: + { + result.y = UI_AxisRegion_Start; + } break; + case UI_Region_Left: + case UI_Region_Center: + case UI_Region_Right: + { + result.y = UI_AxisRegion_Center; + } break; + case UI_Region_BottomLeft: + case UI_Region_Bottom: + case UI_Region_BottomRight: + { + result.y = UI_AxisRegion_End; + } break; + } + return result; +} + //////////////////////////////////////////////////////////// //~ Iteration helpers @@ -295,57 +386,6 @@ void UI_PushStyle(UI_StyleDesc desc) UI_PushCopy(Height, desc, desc.style.AxisSize); } } break; - - case UI_StyleKind_ChildAlignment: - { - UI_Alignment alignment = desc.style.ChildAlignment; - // Alignment -> horizontal alignment - switch(alignment) - { - default: break; - case UI_Alignment_TopLeft: - case UI_Alignment_Left: - case UI_Alignment_BottomLeft: - { - UI_PushCopy(ChildAlignmentX, desc, UI_AxisAlignment_Start); - } break; - case UI_Alignment_Top: - case UI_Alignment_Center: - case UI_Alignment_Bottom: - { - UI_PushCopy(ChildAlignmentX, desc, UI_AxisAlignment_Center); - } break; - case UI_Alignment_TopRight: - case UI_Alignment_Right: - case UI_Alignment_BottomRight: - { - UI_PushCopy(ChildAlignmentX, desc, UI_AxisAlignment_End); - } break; - } - // Alignment -> vertical alignment - switch(alignment) - { - default: break; - case UI_Alignment_TopLeft: - case UI_Alignment_Top: - case UI_Alignment_TopRight: - { - UI_PushCopy(ChildAlignmentY, desc, UI_AxisAlignment_Start); - } break; - case UI_Alignment_Left: - case UI_Alignment_Center: - case UI_Alignment_Right: - { - UI_PushCopy(ChildAlignmentY, desc, UI_AxisAlignment_Center); - } break; - case UI_Alignment_BottomLeft: - case UI_Alignment_Bottom: - case UI_Alignment_BottomRight: - { - UI_PushCopy(ChildAlignmentY, desc, UI_AxisAlignment_End); - } break; - } - } break; } } else @@ -415,7 +455,6 @@ UI_Style UI_PopStyle(UI_StyleDesc desc) switch(kind) { default: break; - case UI_StyleKind_AxisSize: { if (desc.axis == Axis_X) @@ -429,46 +468,6 @@ UI_Style UI_PopStyle(UI_StyleDesc desc) result = UI_PopStyle(desc); } }; - - case UI_StyleKind_ChildAlignment: - { - UI_StyleDesc x_desc = desc; - UI_StyleDesc y_desc = desc; - x_desc.style.kind = UI_StyleKind_ChildAlignmentX; - y_desc.style.kind = UI_StyleKind_ChildAlignmentY; - UI_AxisAlignment x_alignment = UI_PopStyle(x_desc).ChildAlignmentX; - UI_AxisAlignment y_alignment = UI_PopStyle(y_desc).ChildAlignmentY; - switch(y_alignment) - { - case UI_AxisAlignment_Start: - { - switch(x_alignment) - { - case UI_AxisAlignment_Start: { result.ChildAlignment = UI_Alignment_TopLeft; } break; - case UI_AxisAlignment_Center: { result.ChildAlignment = UI_Alignment_Top; } break; - case UI_AxisAlignment_End: { result.ChildAlignment = UI_Alignment_TopRight; } break; - } - } break; - case UI_AxisAlignment_Center: - { - switch(x_alignment) - { - case UI_AxisAlignment_Start: { result.ChildAlignment = UI_Alignment_Left; } break; - case UI_AxisAlignment_Center: { result.ChildAlignment = UI_Alignment_Center; } break; - case UI_AxisAlignment_End: { result.ChildAlignment = UI_Alignment_Right; } break; - } - } break; - case UI_AxisAlignment_End: - { - switch(x_alignment) - { - case UI_AxisAlignment_Start: { result.ChildAlignment = UI_Alignment_BottomLeft; } break; - case UI_AxisAlignment_Center: { result.ChildAlignment = UI_Alignment_Bottom; } break; - case UI_AxisAlignment_End: { result.ChildAlignment = UI_Alignment_BottomRight; } break; - } - } break; - } - } break; } } else @@ -509,8 +508,7 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.pref_semantic_dims[Axis_X] = UI_UseTop(Width); n->cmd.box.pref_semantic_dims[Axis_Y] = UI_UseTop(Height); n->cmd.box.scale = UI_UseTop(Scale); - n->cmd.box.child_alignment[Axis_X] = UI_UseTop(ChildAlignmentX); - n->cmd.box.child_alignment[Axis_Y] = UI_UseTop(ChildAlignmentY); + n->cmd.box.child_alignment = UI_UseTop(ChildAlignment); n->cmd.box.child_layout_axis = UI_UseTop(ChildLayoutAxis); n->cmd.box.background_color = UI_UseTop(BackgroundColor); n->cmd.box.border_color = UI_UseTop(BorderColor); @@ -522,6 +520,7 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.font_size = UI_UseTop(FontSize); n->cmd.box.rounding = UI_UseTop(Rounding); n->cmd.box.text = UI_UseTop(Text); + n->cmd.box.floating_pos_anchor = UI_UseTop(FloatingPosAnchor); n->cmd.box.floating_pos = UI_UseTop(FloatingPos); } ++frame->cmds_count; @@ -635,12 +634,12 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) ////////////////////////////// //- Process controller events + frame->cursor_pos = last_frame->cursor_pos; + if (last_frame->boxes_pre != 0) { ControllerEventsArray controller_events = frame->window_frame.controller_events; - frame->cursor_pos = last_frame->cursor_pos; - // Locate boxes UI_Box *top_hovered_box = 0; UI_Box *active_box = UI_BoxFromKey(last_frame->active_box); @@ -662,8 +661,8 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) b32 is_cursor_in_box = 0; { // TODO: More efficient test. This logic is just copied from the renderer's SDF function for now. - Vec2 p0 = box->rect.p0; - Vec2 p1 = box->rect.p1; + Vec2 p0 = box->screen_rect.p0; + Vec2 p1 = box->screen_rect.p1; Vec2 point = frame->cursor_pos; b32 is_corner = 0; f32 non_corner_edge_dist = MinF32(MinF32(point.x - p0.x, p1.x - point.x), MinF32(point.y - p0.y, p1.y - point.y)); @@ -702,6 +701,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) } // Update state from controller events + i32 mouse_downs = 0; for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index) { ControllerEvent cev = controller_events.events[cev_index]; @@ -713,9 +713,9 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { if (cev.button == Button_M1 || cev.button == Button_M2 || cev.button == Button_M3) { + mouse_downs += 1; if (top_hovered_box && active_box == 0) { - top_hovered_box->report.last_mouse_down_cursor_offset = SubVec2(frame->cursor_pos, top_hovered_box->rect.p0); if (cev.button == Button_M1) { ++top_hovered_box->report.m1.downs; @@ -823,7 +823,13 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) report->active = LerpF32(report->active, target_active, active_blend_rate); report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate); report->selected = LerpF32(report->selected, target_selected, selected_blend_rate); - report->screen_rect = box->rect; + report->screen_rect = box->screen_rect; + report->screen_anchor = box->screen_anchor; + + if (mouse_downs > 0) + { + report->last_cursor_down_anchor_offset = SubVec2(frame->cursor_pos, box->screen_anchor); + } } frame->top_hovered_box = top_hovered_box ? top_hovered_box->key : UI_NilKey; @@ -1075,7 +1081,7 @@ void UI_EndFrame(UI_Frame *frame) // Reset layout data box->cursor = 0; ZeroStructs(box->final_children_size_accum, countof(box->final_children_size_accum)); - ZeroStructs(box->solved_dims, countof(box->solved_dims)); + box->solved_dims = VEC2(0, 0); } else { @@ -1097,7 +1103,7 @@ void UI_EndFrame(UI_Frame *frame) UI_Size sem_dims = box->desc.pref_semantic_dims[axis]; if (sem_dims.kind == UI_SizeKind_Pixel) { - box->solved_dims[axis] = RoundF32(sem_dims.v * box->desc.scale); + box->solved_dims.v[axis] = RoundF32(sem_dims.v * box->desc.scale); } else if (sem_dims.kind == UI_SizeKind_Shrink && AnyBit(box->desc.flags, UI_BoxFlag_DrawText)) { @@ -1111,7 +1117,7 @@ void UI_EndFrame(UI_Frame *frame) { text_size = box->glyph_run.font_ascent + box->glyph_run.font_descent; } - box->solved_dims[axis] = RoundF32(text_size + (sem_dims.v * 2 * box->desc.scale)); + box->solved_dims.v[axis] = RoundF32(text_size + (sem_dims.v * 2 * box->desc.scale)); } } } @@ -1134,11 +1140,11 @@ void UI_EndFrame(UI_Frame *frame) if (ancestor_size.kind == UI_SizeKind_Pixel || (ancestor_size.kind == UI_SizeKind_Shrink && AnyBit(box->desc.flags, UI_BoxFlag_DrawText))) { // Match independent ancestor - match_size = ancestor->solved_dims[axis]; + match_size = ancestor->solved_dims.v[axis]; found_match = 1; } } - box->solved_dims[axis] = RoundF32(match_size * sem_dims.v); + box->solved_dims.v[axis] = RoundF32(match_size * sem_dims.v); } } } @@ -1159,15 +1165,15 @@ void UI_EndFrame(UI_Frame *frame) { if (axis == box->desc.child_layout_axis) { - accum += child->solved_dims[axis]; + accum += child->solved_dims.v[axis]; } else { - accum = MaxF32(child->solved_dims[axis], accum); + accum = MaxF32(child->solved_dims.v[axis], accum); } } } - box->solved_dims[axis] = CeilF32(accum + (sem_dims.v * 2)); + box->solved_dims.v[axis] = CeilF32(accum + (sem_dims.v * 2)); } } } @@ -1182,7 +1188,7 @@ void UI_EndFrame(UI_Frame *frame) UI_Size sem_dims = box->desc.pref_semantic_dims[axis]; if (sem_dims.kind == UI_SizeKind_Grow) { - box->solved_dims[axis] = RoundF32(box->parent->solved_dims[axis] * sem_dims.v); + box->solved_dims.v[axis] = RoundF32(box->parent->solved_dims.v[axis] * sem_dims.v); } } } @@ -1193,7 +1199,7 @@ void UI_EndFrame(UI_Frame *frame) UI_Box *box = boxes_pre[pre_index]; for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) { - f32 box_size = box->solved_dims[axis]; + f32 box_size = box->solved_dims.v[axis]; // Solve non-floating violations { f32 size_accum = 0; @@ -1202,7 +1208,7 @@ void UI_EndFrame(UI_Frame *frame) { if (!AnyBit(child->desc.flags, UI_BoxFlag_Floating)) { - f32 size = child->solved_dims[axis]; + f32 size = child->solved_dims.v[axis]; f32 strictness = child->desc.pref_semantic_dims[axis].strictness; f32 flex = size * (1.0 - strictness); if (axis == box->desc.child_layout_axis) @@ -1225,7 +1231,7 @@ void UI_EndFrame(UI_Frame *frame) { if (!AnyBit(child->desc.flags, UI_BoxFlag_Floating)) { - f32 size = child->solved_dims[axis]; + f32 size = child->solved_dims.v[axis]; f32 strictness = child->desc.pref_semantic_dims[axis].strictness; f32 flex = size * (1.0 - strictness); f32 new_size = size; @@ -1242,7 +1248,7 @@ void UI_EndFrame(UI_Frame *frame) } } adjusted_size_accum += new_size; - child->solved_dims[axis] = RoundF32(new_size); + child->solved_dims.v[axis] = RoundF32(new_size); } } size_accum = adjusted_size_accum; @@ -1254,12 +1260,12 @@ void UI_EndFrame(UI_Frame *frame) { if (AnyBit(child->desc.flags, UI_BoxFlag_Floating) && !AnyBit(child->desc.flags, UI_BoxFlag_NoFloatingClamp)) { - f32 size = child->solved_dims[axis]; + f32 size = child->solved_dims.v[axis]; if (size > box_size) { f32 strictness = child->desc.pref_semantic_dims[axis].strictness; f32 flex = size * (1.0 - strictness); - child->solved_dims[axis] = RoundF32(MaxF32(size - flex, box_size)); + child->solved_dims.v[axis] = RoundF32(MaxF32(size - flex, box_size)); } } } @@ -1272,20 +1278,31 @@ void UI_EndFrame(UI_Frame *frame) UI_Box *box = boxes_pre[pre_index]; UI_Box *parent = box->parent; + UI_RegionPair child_alignment = UI_PairFromRegion(box->desc.child_alignment); + UI_RegionPair alignment_in_parent = Zi; + if (parent) + { + alignment_in_parent = UI_PairFromRegion(parent->desc.child_alignment); + } + else + { + alignment_in_parent = UI_PairFromRegion(UI_Region_TopLeft); + } + // Initialize layout cursor based on alignment { Axis axis = box->desc.child_layout_axis; - UI_AxisAlignment alignment = box->desc.child_alignment[axis]; - f32 box_size = box->solved_dims[axis]; + UI_AxisRegion alignment = child_alignment.v[axis]; + f32 box_size = box->solved_dims.v[axis]; f32 size_accum = box->final_children_size_accum[axis]; switch(alignment) { default: break; - case UI_AxisAlignment_Center: + case UI_AxisRegion_Center: { box->cursor = box_size / 2 - size_accum / 2; } break; - case UI_AxisAlignment_End: + case UI_AxisRegion_End: { box->cursor = box_size - size_accum; } break; @@ -1294,24 +1311,43 @@ void UI_EndFrame(UI_Frame *frame) // Position { - f32 *dims_arr = box->solved_dims; - Vec2 dims_vec = VEC2(dims_arr[0], dims_arr[1]); Vec2 final_pos = Zi; + Vec2 offset = Zi; + Vec2 anchor_offset = Zi; // Floating box position if (AnyBit(box->desc.flags, UI_BoxFlag_Floating)) { - Vec2 offset = box->desc.floating_pos; - final_pos = AddVec2(parent->rect.p0, offset); + UI_RegionPair floating_anchor = UI_PairFromRegion(box->desc.floating_pos_anchor); + + for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) + { + UI_AxisRegion anchor = floating_anchor.v[axis]; + switch (anchor) + { + default: break; + case UI_AxisRegion_Center: + { + anchor_offset.v[axis] = box->solved_dims.v[axis] * 0.5; + } break; + case UI_AxisRegion_End: + { + anchor_offset.v[axis] = box->solved_dims.v[axis]; + } break; + } + } + offset = SubVec2(box->desc.floating_pos, anchor_offset); + + final_pos = AddVec2(parent->screen_rect.p0, offset); if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp)) { { - f32 overshoot = MaxF32(0, (final_pos.x + dims_vec.x) - parent->rect.p1.x); - final_pos.x = MaxF32(parent->rect.p0.x, final_pos.x - overshoot); + f32 overshoot = MaxF32(0, (final_pos.x + box->solved_dims.x) - parent->screen_rect.p1.x); + final_pos.x = MaxF32(parent->screen_rect.p0.x, final_pos.x - overshoot); } { - f32 overshoot = MaxF32((final_pos.y + dims_vec.y) - parent->rect.p1.y, 0); - final_pos.y = MaxF32(parent->rect.p0.y, final_pos.y - overshoot); + f32 overshoot = MaxF32((final_pos.y + box->solved_dims.y) - parent->screen_rect.p1.y, 0); + final_pos.y = MaxF32(parent->screen_rect.p0.y, final_pos.y - overshoot); } } } @@ -1319,48 +1355,49 @@ void UI_EndFrame(UI_Frame *frame) else if (parent) { f32 layout_cursor = parent->cursor; - f32 offset[2] = Zi; // Compute offset in layout direction { Axis axis = parent->desc.child_layout_axis; - offset[axis] = layout_cursor; + offset.v[axis] = layout_cursor; } // Compute offset in non-layout direction (based on alignment) { Axis axis = !parent->desc.child_layout_axis; - UI_AxisAlignment alignment = parent->desc.child_alignment[axis]; + UI_AxisRegion alignment = alignment_in_parent.v[axis]; switch(alignment) { default: break; - case UI_AxisAlignment_Center: + case UI_AxisRegion_Center: { - f32 parent_size = parent->solved_dims[axis]; - f32 box_size = dims_arr[axis]; - offset[axis] = parent_size / 2 - box_size / 2; + f32 parent_size = parent->solved_dims.v[axis]; + f32 box_size = box->solved_dims.v[axis]; + offset.v[axis] = parent_size / 2 - box_size / 2; } break; - case UI_AxisAlignment_End: + case UI_AxisRegion_End: { - f32 parent_size = parent->solved_dims[axis]; - f32 box_size = dims_arr[axis]; - offset[axis] = parent_size - box_size; + f32 parent_size = parent->solved_dims.v[axis]; + f32 box_size = box->solved_dims.v[axis]; + offset.v[axis] = parent_size - box_size; } break; } } - final_pos.x = parent->rect.p0.x + offset[0]; - final_pos.y = parent->rect.p0.y + offset[1]; - parent->cursor += dims_arr[parent->desc.child_layout_axis]; + final_pos.x = parent->screen_rect.p0.x + offset.x; + final_pos.y = parent->screen_rect.p0.y + offset.y; + parent->cursor += box->solved_dims.v[parent->desc.child_layout_axis]; } // Submit position Vec2 rounded_final_pos = FloorVec2(final_pos); - box->rect.p0 = rounded_final_pos; - box->rect.p1 = AddVec2(rounded_final_pos, dims_vec); + box->screen_rect.p0 = rounded_final_pos; + box->screen_rect.p1 = AddVec2(rounded_final_pos, box->solved_dims); + + box->screen_anchor = AddVec2(box->screen_rect.p0, anchor_offset); } // Rounding { UI_Round rounding = box->desc.rounding; - Vec2 half_dims = MulVec2(SubVec2(box->rect.p1, box->rect.p0), 0.5); + Vec2 half_dims = MulVec2(SubVec2(box->screen_rect.p1, box->screen_rect.p0), 0.5); f32 min_half_dims = MinF32(half_dims.x, half_dims.y); f32 final_rounding_tl = 0; f32 final_rounding_tr = 0; @@ -1388,10 +1425,10 @@ void UI_EndFrame(UI_Frame *frame) if (parent && !AllBits(box->desc.flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClamp)) { - Vec2 vtl = SubVec2(VEC2(parent->rect.p0.x, parent->rect.p0.y), VEC2(box->rect.p0.x, box->rect.p0.y)); - Vec2 vtr = SubVec2(VEC2(parent->rect.p1.x, parent->rect.p0.y), VEC2(box->rect.p1.x, box->rect.p0.y)); - Vec2 vbr = SubVec2(VEC2(parent->rect.p1.x, parent->rect.p1.y), VEC2(box->rect.p1.x, box->rect.p1.y)); - Vec2 vbl = SubVec2(VEC2(parent->rect.p0.x, parent->rect.p1.y), VEC2(box->rect.p0.x, box->rect.p1.y)); + Vec2 vtl = SubVec2(VEC2(parent->screen_rect.p0.x, parent->screen_rect.p0.y), VEC2(box->screen_rect.p0.x, box->screen_rect.p0.y)); + Vec2 vtr = SubVec2(VEC2(parent->screen_rect.p1.x, parent->screen_rect.p0.y), VEC2(box->screen_rect.p1.x, box->screen_rect.p0.y)); + Vec2 vbr = SubVec2(VEC2(parent->screen_rect.p1.x, parent->screen_rect.p1.y), VEC2(box->screen_rect.p1.x, box->screen_rect.p1.y)); + Vec2 vbl = SubVec2(VEC2(parent->screen_rect.p0.x, parent->screen_rect.p1.y), VEC2(box->screen_rect.p0.x, box->screen_rect.p1.y)); final_rounding_tl = MaxF32(final_rounding_tl, parent->rounding_tl - Vec2Len(vtl)); final_rounding_tr = MaxF32(final_rounding_tr, parent->rounding_tr - Vec2Len(vtr)); final_rounding_br = MaxF32(final_rounding_br, parent->rounding_br - Vec2Len(vbr)); @@ -1420,10 +1457,12 @@ void UI_EndFrame(UI_Frame *frame) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) { UI_Box *box = boxes_pre[pre_index]; + UI_RegionPair child_alignment = UI_PairFromRegion(box->desc.child_alignment); + b32 is_visible = 1; is_visible = is_visible && (box->desc.tint.w >= 0.001); - is_visible = is_visible && (box->rect.p1.x - box->rect.p0.x >= 1); - is_visible = is_visible && (box->rect.p1.y - box->rect.p0.y >= 1); + is_visible = is_visible && (box->screen_rect.p1.x - box->screen_rect.p0.x >= 1); + is_visible = is_visible && (box->screen_rect.p1.y - box->screen_rect.p0.y >= 1); if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) { Vec4 debug_lin = is_visible ? LinearFromSrgb(box->desc.debug_color) : LinearFromSrgb(box->desc.invisible_debug_color); @@ -1431,7 +1470,7 @@ void UI_EndFrame(UI_Frame *frame) // Box rect { UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); - rect->bounds = box->rect; + rect->bounds = box->screen_rect; rect->background_lin = LinearFromSrgb(box->desc.background_color); rect->border_lin = LinearFromSrgb(box->desc.border_color); rect->debug_lin = debug_lin; @@ -1449,7 +1488,7 @@ void UI_EndFrame(UI_Frame *frame) GC_Run raw_run = box->glyph_run; if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run.ready) { - f32 max_baseline = DimsFromRng2(box->rect).x; + f32 max_baseline = DimsFromRng2(box->screen_rect).x; b32 should_truncate = raw_run.baseline_length > max_baseline && !AnyBit(box->desc.flags, UI_BoxFlag_NoTextTruncation); // Truncate run @@ -1497,48 +1536,48 @@ void UI_EndFrame(UI_Frame *frame) final_baseline_length = raw_run.baseline_length; } - UI_AxisAlignment x_alignment = box->desc.child_alignment[Axis_X]; - UI_AxisAlignment y_alignment = box->desc.child_alignment[Axis_Y]; + UI_AxisRegion x_alignment = child_alignment.v[Axis_X]; + UI_AxisRegion y_alignment = child_alignment.v[Axis_Y]; // Compute baseline f32 ascent = raw_run.font_ascent; f32 font_descent = raw_run.font_descent; f32 cap = raw_run.font_cap; f32 baseline_height = ascent + font_descent; - Vec2 box_dims = DimsFromRng2(box->rect); + Vec2 box_dims = DimsFromRng2(box->screen_rect); Vec2 baseline = Zi; switch (x_alignment) { - case UI_AxisAlignment_Start: + case UI_AxisRegion_Start: { - baseline.x = box->rect.p0.x; + baseline.x = box->screen_rect.p0.x; } break; - case UI_AxisAlignment_End: + case UI_AxisRegion_End: { - baseline.x = box->rect.p1.x; + baseline.x = box->screen_rect.p1.x; baseline.x -= final_baseline_length; } break; - case UI_AxisAlignment_Center: + case UI_AxisRegion_Center: { - baseline.x = box->rect.p0.x; + baseline.x = box->screen_rect.p0.x; baseline.x += (box_dims.x - final_baseline_length) / 2; } break; } switch (y_alignment) { - case UI_AxisAlignment_Start: + case UI_AxisRegion_Start: { - baseline.y = box->rect.p0.y; + baseline.y = box->screen_rect.p0.y; baseline.y += ascent; } break; - case UI_AxisAlignment_End: + case UI_AxisRegion_End: { - baseline.y = box->rect.p1.y; + baseline.y = box->screen_rect.p1.y; baseline.y -= font_descent; } break; - case UI_AxisAlignment_Center: + case UI_AxisRegion_Center: { - baseline.y = box->rect.p0.y; + baseline.y = box->screen_rect.p0.y; baseline.y += box_dims.y / 2; baseline.y += cap / 2; } break; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 91596a3f..cd2f1a06 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -42,28 +42,34 @@ Struct(UI_Round) }; //////////////////////////////////////////////////////////// -//~ Alignment types +//~ Region types -Enum(UI_Alignment) +Enum(UI_Region) { - UI_Alignment_TopLeft, - UI_Alignment_Top, - UI_Alignment_TopRight, + UI_Region_TopLeft, + UI_Region_Top, + UI_Region_TopRight, - UI_Alignment_Left, - UI_Alignment_Center, - UI_Alignment_Right, + UI_Region_Left, + UI_Region_Center, + UI_Region_Right, - UI_Alignment_BottomLeft, - UI_Alignment_Bottom, - UI_Alignment_BottomRight, + UI_Region_BottomLeft, + UI_Region_Bottom, + UI_Region_BottomRight, }; -Enum(UI_AxisAlignment) +Enum(UI_AxisRegion) { - UI_AxisAlignment_Start, - UI_AxisAlignment_Center, - UI_AxisAlignment_End, + UI_AxisRegion_Start, + UI_AxisRegion_Center, + UI_AxisRegion_End, +}; + +Union(UI_RegionPair) +{ + struct { UI_AxisRegion x, y; }; + UI_AxisRegion v[2]; }; //////////////////////////////////////////////////////////// @@ -98,8 +104,7 @@ Enum(UI_BoxFlag) X(Parent, UI_Key) \ X(Tag, u64) \ X(ChildLayoutAxis, Axis) \ - X(ChildAlignmentX, UI_AxisAlignment) \ - X(ChildAlignmentY, UI_AxisAlignment) \ + X(ChildAlignment, UI_Region) \ X(Width, UI_Size) \ X(Height, UI_Size) \ X(Scale, f32) \ @@ -109,6 +114,7 @@ Enum(UI_BoxFlag) X(InvisibleDebugColor, Vec4) \ X(Tint, Vec4) \ X(Border, f32) \ + X(FloatingPosAnchor, UI_Region) \ X(FloatingPos, Vec2) \ X(Rounding, UI_Round) \ X(Font, GC_FontKey) \ @@ -121,7 +127,6 @@ Enum(UI_BoxFlag) /* --------------------------------------------- */ \ X(BeginVirtualStyles_, i8) \ /* --------------------------------------------- */ \ - X(ChildAlignment, UI_Alignment) \ X(AxisSize, UI_Size) \ /* ------------------------------------------------- */ @@ -199,13 +204,14 @@ Struct(UI_Report) f32 selected; // Mouse button info - Vec2 last_mouse_down_cursor_offset; + Vec2 last_cursor_down_anchor_offset; UI_MouseReport m1; UI_MouseReport m2; UI_MouseReport m3; // Where was this box last rendered in screen coordinates Rng2 screen_rect; + Vec2 screen_anchor; }; //////////////////////////////////////////////////////////// @@ -241,7 +247,8 @@ Struct(UI_BoxDesc) GC_FontKey font; f32 font_size; Axis child_layout_axis; - UI_AxisAlignment child_alignment[Axis_COUNTXY]; + UI_Region child_alignment; + UI_Region floating_pos_anchor; }; Struct(UI_Cmd) @@ -302,10 +309,11 @@ Struct(UI_Box) //- Layout data f32 cursor; f32 final_children_size_accum[Axis_COUNTXY]; - f32 solved_dims[Axis_COUNTXY]; + Vec2 solved_dims; //- Layout results - Rng2 rect; + Rng2 screen_rect; + Vec2 screen_anchor; f32 rounding_tl; f32 rounding_tr; f32 rounding_br; @@ -426,6 +434,12 @@ UI_Key UI_KeyF_(String fmt, ...); UI_Key UI_RandKey(void); UI_Box *UI_BoxFromKey(UI_Key key); +//////////////////////////////////////////////////////////// +//~ Region helpers + +UI_Region UI_RegionFromPair(UI_RegionPair pair); +UI_RegionPair UI_PairFromRegion(UI_Region region); + //////////////////////////////////////////////////////////// //~ Iteration helpers diff --git a/src/ui/ui_extras.c b/src/ui/ui_extras.c index e0b71488..bbd09327 100644 --- a/src/ui/ui_extras.c +++ b/src/ui/ui_extras.c @@ -8,7 +8,7 @@ UI_Key UI_BuildLabel(String text) f32 font_size = UI_UseTop(FontSize); f32 scale = UI_UseTop(Scale); Vec4 tint = UI_UseTop(Tint); - UI_Alignment alignment = UI_UseTop(ChildAlignment); + UI_Region alignment = UI_UseTop(ChildAlignment); UI_Key key = Zi; UI_PushCP(UI_NilKey);