floating position anchors
This commit is contained in:
parent
bed51e195e
commit
9b94f02a27
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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) }
|
||||
|
||||
@ -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);
|
||||
Vec4 item_border_color = Zi;
|
||||
if (item->flags & PaletteItemFlag_IsCmd)
|
||||
{
|
||||
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);
|
||||
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:
|
||||
|
||||
@ -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
|
||||
|
||||
373
src/ui/ui_core.c
373
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;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user