//////////////////////////////////////////////////////////// //~ 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_Children, UI_SizeKind_Ratio, UI_SizeKind_Pixel, UI_SizeKind_Text, }; Struct(UI_Size) { UI_SizeKind kind; f32 v; f32 strictness; }; //////////////////////////////////////////////////////////// //~ Box types /* NOTE: UI flags are located here since they are shared between application & shader code */ Enum(UI_BoxFlag) { UI_BoxFlag_None = 0, UI_BoxFlag_DrawText = (1 << 0), UI_BoxFlag_DrawImage = (1 << 1), }; 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; //- Per-build data UI_BoxFlag flags; String display_text; GPU_Resource *display_image; Axis layout_axis; UI_Size pref_size[Axis_CountXY]; u32 background_color; u32 border_color; f32 border; f32 text_padding; Resource font_resource; f32 font_size; //- Layout data F_Run glyph_run; F_Font *font; f32 solved_dims[Axis_CountXY]; f32 layout_cursor; //- Post-solve data Vec2 p0; Vec2 p1; }; Struct(UI_BoxBin) { UI_Box *first; UI_Box *last; }; //////////////////////////////////////////////////////////// //~ Style types #define UI_StyleKindsXMacro(x) \ x(Tag, u64) \ x(Parent, UI_Box *) \ x(LayoutAxis, Axis) \ x(Width, UI_Size) \ x(Height, UI_Size) \ x(BackgroundColor, u32) \ x(BorderColor, u32) \ x(Border, f32) \ x(Font, Resource) \ x(FontSize, u32) \ x(TextPadding, f32) \ /* ----------------------------------- */ 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; /* Union of all style fields */ union { #define X(name, type) type name; UI_StyleKindsXMacro(X) #undef X }; }; Struct(UI_StyleNode) { UI_StyleNode *next; b32 pop_when_used; u64 checkpoint; UI_Style style; }; //////////////////////////////////////////////////////////// //~ Checkpoint types Struct(UI_Checkpoint) { UI_Checkpoint *next; u64 v; }; //////////////////////////////////////////////////////////// //~ State types #define UI_NumBoxLookupBins 16384 Struct(UI_SharedState) { //- Build state Arena *build_arena; Arena *back_build_arena; 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_Checkpoint *top_checkpoint; UI_Checkpoint *first_free_checkpoint; UI_StyleNode *style_tops[UI_StyleKind_Count]; UI_StyleNode *first_free_style_node; //- Render state GPU_Resource *render_target; i64 render_fence_target; GPU_TransientBuffer draw_rects_tbuff; Arena *draw_rects_arena; } extern UI_shared_state; //////////////////////////////////////////////////////////// //~ Startup void UI_Startup(void); //////////////////////////////////////////////////////////// //~ Font helpers Resource UI_GetDefaultFontResource(void); //////////////////////////////////////////////////////////// //~ Key helpers u64 UI_HashFromTop(void); u64 UI_HashFromString(u64 seed, String str); UI_Key UI_KeyFromString(u64 seed, String str); //////////////////////////////////////////////////////////// //~ Checkpoint helpers void UI_PushCheckpoint(void); void UI_PopCheckpoint(void); //////////////////////////////////////////////////////////// //~ Style stack helpers UI_StyleNode *UI_PushStyleNode(UI_StyleKind kind, b32 pop_when_used, UI_Style desc); UI_Style UI_PopStyleNode(UI_StyleKind kind); UI_StyleNode *UI_PeekTopStyleNode(UI_StyleKind kind); UI_Style UI_StyleFromTopNode(UI_StyleKind kind, b32 use); #define UI_SetNext(name, v) UI_PushStyleNode(UI_StyleKind_##name, 1, (UI_Style) { .name = v }) #define UI_Push(name, v) UI_PushStyleNode(UI_StyleKind_##name, 0, (UI_Style) { .name = v }) #define UI_Pop(name, v) UI_PopStyleNode(UI_StyleKind_##name).name #define UI_UseTop(name) UI_StyleFromTopNode(UI_StyleKind_##name, 1).name #define UI_PeekTop(name) UI_StyleFromTopNode(UI_StyleKind_##name, 0).name //////////////////////////////////////////////////////////// //~ Size helpers #define UI_ChildrenSize(_strictness) ((UI_Size) { .kind = UI_SizeKind_Children, .strictness = strictness_ }) #define UI_RatioSize(_ratio, _strictness) ((UI_Size) { .kind = UI_SizeKind_Ratio, .v = _ratio, .strictness = _strictness }) #define UI_PixelSize(_pixels, _strictness) ((UI_Size) { .kind = UI_SizeKind_Pixel, .v = _pixels, .strictness = _strictness }) #define UI_TextSize(_strictness) ((UI_Size) { .kind = UI_SizeKind_Text, .strictness = _strictness }) //////////////////////////////////////////////////////////// //~ Box UI_Box *UI_BuildBox(UI_BoxFlag flags, UI_Key key); void UI_SetDisplayText(UI_Box *box, String str); void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img); //////////////////////////////////////////////////////////// //~ Image void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img); //////////////////////////////////////////////////////////// //~ Begin build void UI_BeginBuild(void); //////////////////////////////////////////////////////////// //~ End build GPU_Resource *UI_EndBuild(Rect render_viewport);