/* date = April 29th 2023 8:22 pm */ #ifndef VN_UI_H #define VN_UI_H struct ui_key { u64 Value; }; inline b32 AreEqual(ui_key A, ui_key B) { b32 Result = (A.Value == B.Value); return(Result); } enum { UI_BoxFlag_Clickable = (1 << 0), UI_BoxFlag_DrawText = (1 << 1), UI_BoxFlag_DrawBorder = (1 << 2), UI_BoxFlag_DrawBackground = (1 << 3), UI_BoxFlag_DrawDropShadow = (1 << 4), UI_BoxFlag_Clip = (1 << 5), UI_BoxFlag_HotAnimation = (1 << 6), UI_BoxFlag_ActiveAnimation = (1 << 7), UI_BoxFlag_OverflowX = (1 << 8), UI_BoxFlag_OverflowY = (1 << 9), UI_BoxFlag_FloatingX = (1 << 10), UI_BoxFlag_FloatingY = (1 << 11), }; typedef u32 ui_box_flags; enum ui_size_type { UI_SizeType_Pixels, UI_SizeType_TextContent, UI_SizeType_PercentOfParent, UI_SizeType_ChildrenSum, }; struct ui_size { ui_size_type Type; r32 Value; r32 Strictness; }; inline ui_size UI_Pixels(r32 Value, r32 Strictness) { ui_size Result = {UI_SizeType_Pixels, Value, Strictness}; return(Result); } inline ui_size UI_TextContent(r32 Value, r32 Strictness) { ui_size Result = {UI_SizeType_TextContent, Value, Strictness}; return(Result); } inline ui_size UI_Percent(r32 Value, r32 Strictness) { ui_size Result = {UI_SizeType_PercentOfParent, Value, Strictness}; return(Result); } inline ui_size UI_ChildrenSum(r32 Value, r32 Strictness) { ui_size Result = {UI_SizeType_ChildrenSum, Value, Strictness}; return(Result); } typedef void ui_draw_callback(render_group *Group, glyph_atlas *Atlas, struct ui_box *Box, void *Data); struct ui_box { ui_box *First; ui_box *Last; ui_box *Next; ui_box *Prev; ui_box *Parent; ui_box *HashNext; ui_box *HashPrev; ui_key Key; ui_key Seed; u64 LastFrameTouched; ui_box_flags Flags; string String; ui_size SemanticSize[Axis2_Count]; v2 FixedP; v4 TextColor; v4 BackgroundColor; v4 BorderColor; r32 BorderThickness; axis2 LayoutAxis; r32 CornerRadius; font_id Font; r32 FontSize; ui_draw_callback *DrawCallback; void *DrawCallbackData; v2 ComputedRelativeP; v2 ComputedDim; range2_r32 Rect; r32 HotTransition; r32 ActiveTransition; }; struct ui_box_bucket { ui_box *First; ui_box *Last; }; struct ui_signal { ui_box *Box; v2 MouseP; v2 DragDelta; b8 Clicked; b8 Pressed; b8 PressedRight; b8 Released; b8 Hovering; b8 Dragging; }; #include "generated/vn_generated_ui.h" struct ui { memory_arena Arena; memory_arena FrameArena; temporary_memory FrameMemory; ui_box *FirstFreeBox; ui_box *LastFreeBox; ui_box_bucket BoxBuckets[256]; ui_box *RootNode; ui_box *TooltipNode; ui_box *ContainerNode; u64 CurrentFrame; ui_key Hot; ui_key Active; ui_key NextHot; b32 NextHotSet; platform_event_list *EventList; v2 MouseP; u64 DragData[8]; v2 DragStartP; ui_style_stacks Stacks; }; //- sixten: State management inline void UI_SetState(ui *UI); inline ui *UI_GetState(void); inline ui_key UI_GetHot(void); inline ui_key UI_GetActive(void); //- sixten: Drag helpers inline void UI_SetDragStartP(v2 P); inline void UI_UpdateDragStartP(void); inline v2 UI_GetDragStartP(void); inline void UI_StoreDragV2(v2 DragData); inline v2 UI_GetDragV2(void); inline void UI_StoreDragR32(r32 DragData); inline r32 UI_GetDragR32(void); inline void UI_StoreDragPayload(void *Data); // sixten(NOTE): Payload MUST be 64-bytes. inline void UI_GetDragDataPayload(void *Data); inline void UI_StoreDragPointer(void *Data); inline void *UI_GetDragDataPointer(void); //- sixten: Key functions inline ui_key UI_EmptyKey(void); inline ui_key UI_SeedKey(ui_key Key, ui_key Seed); inline ui_key UI_GenerateKeyFromString(string String); static string UI_GetBoxNameByKey(ui_key Key); inline ui_box *UI_GetBoxByKey(ui *UI, ui_key Key); //- sixten: Box creation inline ui_box *UI_MakeBox(ui_box_flags Flags, string String); inline ui_box *UI_MakeBoxF(ui_box_flags Flags, char *Format, ...); //- sixten: Building and rendering static void UI_BeginBuild(ui *UI, v2 ScreenDim); static void UI_EndBuild(glyph_atlas *GlyphAtlas); static void UI_RenderFrame(render_group *RenderGroup, glyph_atlas *GlyphAtlas); static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP); #endif //VN_UI_H