power_play/src/ui/ui_core.h
2025-11-04 11:15:05 -06:00

411 lines
9.9 KiB
C

////////////////////////////////////////////////////////////
//~ Key types
#define UI_NilKey ((UI_Key) { 0 })
#define UI_RootKey ((UI_Key) { 0xa3deb3749ef35a7aUll })
Struct(UI_Key)
{
u64 hash;
};
////////////////////////////////////////////////////////////
//~ Size types
Enum(UI_SizeKind)
{
UI_SizeKind_Pixel, /* Exact size */
UI_SizeKind_Fill, /* Size as percent of parent size */
UI_SizeKind_Fit, /* Size to contents */
};
Struct(UI_Size)
{
UI_SizeKind kind;
f32 v;
f32 strictness;
};
////////////////////////////////////////////////////////////
//~ Rounding types
Enum(UI_RoundKind)
{
UI_RoundKind_Pixel, /* Exact radius */
UI_RoundKind_Fill, /* Radius as percent of size */
};
Struct(UI_Round)
{
UI_RoundKind kind;
f32 v;
};
////////////////////////////////////////////////////////////
//~ Alignment types
Enum(UI_Alignment)
{
UI_Alignment_Center,
UI_Alignment_Left,
UI_Alignment_Right,
};
////////////////////////////////////////////////////////////
//~ Padding types
Struct(UI_Pad)
{
UI_Size top;
UI_Size bottom;
UI_Size left;
UI_Size right;
};
////////////////////////////////////////////////////////////
//~ Checkpoint types
Struct(UI_Checkpoint)
{
UI_Checkpoint *next;
u64 v;
};
////////////////////////////////////////////////////////////
//~ Box flags
Enum(UI_BoxFlag)
{
UI_BoxFlag_None = 0,
UI_BoxFlag_DrawText = (1 << 0),
UI_BoxFlag_NoTextTruncation = (1 << 1),
UI_BoxFlag_Floating = (1 << 2),
UI_BoxFlag_NoFloatingClamp = (1 << 3),
};
////////////////////////////////////////////////////////////
//~ Style types
#define UI_StyleKindsXMacro(x) \
x(Flags, UI_BoxFlag) \
x(Parent, struct UI_Box *) \
x(Tag, UI_Tag) \
x(LayoutAxis, Axis) \
x(Width, UI_Size) \
x(Height, UI_Size) \
x(Size, UI_Size) \
x(BackgroundColor, u32) \
x(BorderColor, u32) \
x(Tint, u32) \
x(Border, f32) \
x(FloatingPos, Vec2) \
x(Rounding, UI_Round) \
x(Font, ResourceKey) \
x(FontSize, u32) \
x(Text, String) \
x(TextAlignment, UI_Alignment) \
x(LeftPadding, UI_Size) \
x(RightPadding, UI_Size) \
x(TopPadding, UI_Size) \
x(BottomPadding, UI_Size) \
/* ----------------------------------- */ \
/* --------- Virtual styles --------- */ \
/* ----------------------------------- */ \
x(BeginVirtualStyles_, i8) \
x(Padding, UI_Pad) \
x(AxisSize, UI_AxisSize) \
/* ------------------------------------------- */
Struct(UI_Tag)
{
String name;
u64 hash;
};
Struct(UI_AxisSize)
{
Axis axis;
UI_Size size;
};
Enum(UI_StyleKind)
{
#define X(name, type) UI_StyleKind_##name,
UI_StyleKind_None,
UI_StyleKindsXMacro(X)
UI_StyleKind_Count,
#undef X
};
Struct(UI_Style)
{
UI_StyleKind kind;
b32 pop_when_used;
b32 forced;
/* Union of all style fields */
union
{
#define X(name, type) type name;
UI_StyleKindsXMacro(X)
#undef X
};
};
Struct(UI_StyleNode)
{
UI_StyleNode *next;
u64 checkpoint;
UI_Style style;
};
Struct(UI_Stack)
{
UI_Stack *next;
UI_Checkpoint *top_checkpoint;
UI_StyleNode *style_tops[UI_StyleKind_Count];
};
////////////////////////////////////////////////////////////
//~ Report types
Enum(UI_ReportFlag)
{
UI_ReportFlag_None = 0,
UI_ReportFlag_Active = (1 << 0),
UI_ReportFlag_Hovered = (1 << 1),
};
Struct(UI_Report)
{
UI_ReportFlag flags;
Vec2 activation_offset;
Vec2 screen_p0;
Vec2 screen_p1;
};
////////////////////////////////////////////////////////////
//~ Box types
Struct(UI_Box)
{
//- Hash list
UI_Box *next_in_bin;
UI_Box *prev_in_bin;
//- Tree
UI_Box *parent;
UI_Box *first;
UI_Box *last;
UI_Box *next;
UI_Box *prev;
u64 count;
//- Persistent data
UI_Key key;
UI_Report report;
//- Per-build data
UI_BoxFlag flags;
GPU_Resource *background_texture;
Vec2 background_texture_uv0;
Vec2 background_texture_uv1;
UI_Size pref_size[Axis_CountXY];
UI_Round rounding;
u32 background_color;
u32 border_color;
u32 text_color;
u32 tint;
f32 border;
Vec2 floating_pos;
String text;
UI_Alignment text_alignment;
ResourceKey font_resource;
f32 font_size;
Axis layout_axis;
//- Pre-layout data
u64 pre_index;
u64 post_index;
//- Layout data
F_Run glyph_run;
F_Font *font;
f32 solved_dims[Axis_CountXY];
f32 layout_cursor;
//- Post-layout data
Vec2 p0;
Vec2 p1;
f32 rounding_tl;
f32 rounding_tr;
f32 rounding_br;
f32 rounding_bl;
};
Struct(UI_BoxBin)
{
UI_Box *first;
UI_Box *last;
};
////////////////////////////////////////////////////////////
//~ Frame types
Enum(UI_FrameFlag)
{
UI_FrameFlag_None = 0,
UI_FrameFlag_Debug = (1 << 0),
};
Struct(UI_Frame)
{
WND_Frame window_frame;
};
////////////////////////////////////////////////////////////
//~ State types
#define UI_NumBoxLookupBins 16384
Struct(UI_SharedState)
{
//- Control state
Vec2 cursor_pos;
//- Build state
Arena *build_arena;
Arena *back_build_arena;
UI_FrameFlag frame_flags;
UI_FrameFlag back_frame_flags;
UI_BoxBin *box_bins;
UI_BoxBin *back_box_bins;
UI_Box *root_box;
UI_Box *back_root_box;
u64 boxes_count;
u64 back_boxes_count;
UI_Stack *top_stack;
UI_Stack *first_free_stack;
UI_Checkpoint *first_free_checkpoint;
UI_StyleNode *first_free_style_node;
//- Layout state
UI_Box **boxes_pre;
UI_Box **boxes_post;
UI_Box **back_boxes_pre;
UI_Box **back_boxes_post;
//- Render state
GPU_Resource *render_target;
GPU_Swapchain *swapchain;
i64 gpu_submit_fence_target;
GPU_TransientBuffer draw_rects_tbuff;
Arena *draw_rects_arena;
} extern UI_shared_state;
////////////////////////////////////////////////////////////
//~ Startup
void UI_Startup(void);
////////////////////////////////////////////////////////////
//~ Font helpers
ResourceKey UI_GetDefaultFontResource(void);
////////////////////////////////////////////////////////////
//~ Key helpers
UI_Box *UI_BackBoxFromKey(UI_Key key);
UI_Box *UI_FrontBoxFromKey(UI_Key key);
////////////////////////////////////////////////////////////
//~ Checkpoint helpers
void UI_PushCP(UI_Box *parent);
void UI_PopCP(void);
////////////////////////////////////////////////////////////
//~ Style stack helpers
void UI_PushStack(void);
void UI_PopStack(void);
void UI_PushStyle(UI_Style desc);
UI_Style UI_PopStyle(UI_StyleKind kind);
UI_Style UI_FetchStyle(UI_StyleKind kind, b32 use);
#define UI_SetNext(name, ...) UI_PushStyle((UI_Style) { .kind = UI_StyleKind_##name, .name = __VA_ARGS__, .pop_when_used = 1 })
#define UI_Push(name, ...) UI_PushStyle((UI_Style) { .kind = UI_StyleKind_##name, .name = __VA_ARGS__ })
#define UI_ForceNext(name, ...) UI_PushStyle((UI_Style) { .kind = UI_StyleKind_##name, .name = __VA_ARGS__, .pop_when_used = 1, .forced = 1 })
#define UI_ForcePush(name, ...) UI_PushStyle((UI_Style) { .kind = UI_StyleKind_##name, .name = __VA_ARGS__, .forced = 1 })
#define UI_Pop(name) UI_PopStyle(UI_StyleKind_##name).name
#define UI_FetchTop(name, use) UI_FetchStyle(UI_StyleKind_##name, use).name
#define UI_PeekTop(name) UI_FetchTop(name, 0)
#define UI_UseTop(name) UI_FetchTop(name, 1)
#define UI_PushCopy(name, src, ...) do { \
UI_Style _new = src; \
_new.kind = UI_StyleKind_##name; \
_new.name = __VA_ARGS__; \
UI_PushStyle(_new); \
} while (0)
////////////////////////////////////////////////////////////
//~ Size helpers
#define UI_SIZE(_kind, _v, _s) (UI_Size) { .kind = (_kind), .v = (_v), .strictness = (_s) }
#define UI_AXSIZE(_axis, _size) (UI_AxisSize) { .axis = (_axis), .size = (_size) }
#define UI_PIX(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (_v), (_s))
#define UI_FIT(_s) UI_SIZE(UI_SizeKind_Fit, 0, (_s))
#define UI_FILL(_v, _s) UI_SIZE(UI_SizeKind_Fill, (_v), (_s))
#define UI_FNT(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (f32)UI_PeekTop(FontSize) * (_v), (_s))
////////////////////////////////////////////////////////////
//~ Rounding helpers
#define UI_ROUND(_kind, _v) (UI_Round) { .kind = (_kind), .v = (_v)}
#define UI_RPIX(_v) UI_ROUND(UI_RoundKind_Pixel, (_v))
#define UI_RFILL(_v) UI_ROUND(UI_RoundKind_Fill, (_v))
////////////////////////////////////////////////////////////
//~ Padding helpers
#define UI_PAD(...) ((UI_Pad) { __VA_ARGS__ })
#define UI_PADALL(size) ((UI_Pad) { .top = size, .bottom = size, .left = size, .right = size })
////////////////////////////////////////////////////////////
//~ Box
UI_Box *UI_BuildBox(String seed);
void UI_SetBackgroundTexture(UI_Box *box, GPU_Resource *texture, Vec2 uv0, Vec2 uv1);
b32 UI_IsPointInBox(UI_Box *box, Vec2 point);
////////////////////////////////////////////////////////////
//~ Report
UI_Report UI_ReportFromKey(UI_Key key);
////////////////////////////////////////////////////////////
//~ Begin frame
UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags);
////////////////////////////////////////////////////////////
//~ End build
GPU_ResourceDesc UI_GetRenderTargetDesc(Vec2I32 size);
i64 UI_EndFrame(UI_Frame frame);