/* date = April 29th 2023 8:22 pm */ #ifndef VN_UI_H #define VN_UI_H //- sixten: Keying struct ui_key { u64 Value; }; inline b32 AreEqual(ui_key A, ui_key B) { b32 Result = (A.Value == B.Value); return(Result); } //- sixten: Semantic sizing enum ui_size_kind { UI_SizeKind_Pixels, UI_SizeKind_TextContent, UI_SizeKind_PercentOfParent, UI_SizeKind_ChildrenSum, }; struct ui_size { ui_size_kind Kind; r32 Value; r32 Strictness; }; static ui_size UI_MakeSize(ui_size_kind Kind, r32 Value, r32 Strictness); #define UI_Pixels(Value, Strictness) UI_MakeSize(UI_SizeKind_Pixels, Value, Strictness) #define UI_Em(Value, Strictness) UI_MakeSize(UI_SizeKind_Pixels, (Value)*UI_TopFontSize(), Strictness) #define UI_TextContent(Value, Strictness) UI_MakeSize(UI_SizeKind_TextContent, Value, Strictness) #define UI_Percent(Value, Strictness) UI_MakeSize(UI_SizeKind_PercentOfParent, Value, Strictness) #define UI_ChildrenSum(Value, Strictness) UI_MakeSize(UI_SizeKind_ChildrenSum, Value, Strictness) //- sixten: UI core 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), UI_BoxFlag_Scrollable = (1 << 12), UI_BoxFlag_AnimatePosition = (1 << 13), }; typedef u32 ui_box_flags; #define UI_CUSTOM_DRAW_CALLBACK(name) void name(render_group *Group, glyph_atlas *Atlas, struct ui_box *Box, void *Data) typedef UI_CUSTOM_DRAW_CALLBACK(ui_custom_draw_callback); struct ui_box { // sixten: building ui_box *First; ui_box *Last; ui_box *Next; ui_box *Prev; ui_box *Parent; // sixten: hashing ui_box *HashNext; ui_box *HashPrev; ui_key Key; ui_key Seed; u64 LastFrameTouched; // sixten: per-frame data 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; v2 Offset; platform_cursor HoverCursor; ui_custom_draw_callback *DrawCallback; void *DrawCallbackData; v2 ComputedRelativeP; v2 ComputedDim; // sixten: retained data range2_r32 Rect; r32 HotTransition; r32 ActiveTransition; v2 ApproachingRelativeP; }; struct ui_box_bucket { ui_box *First; ui_box *Last; }; struct ui_signal { ui_box *Box; v2 MouseP; v2 dMouseP; v2 DragDelta; v2 Scroll; b8 Clicked; b8 Pressed; b8 PressedRight; b8 Released; b8 Hovering; b8 Dragging; }; #include "generated/vn_ui.meta.h" struct ui { arena *Arena; arena *FrameArena; 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; r64 Time; ui_key NextHot; b32 NextHotSet; u64 DragData[8]; v2 DragStartP; ui_style_stacks Stacks; platform_event_list *EventList; v2 dMouseP; v2 MouseP; glyph_atlas *GlyphAtlas; }; //- sixten: State management inline void UI_SetState(ui *UI); inline ui *UI_GetState(void); inline ui_key UI_HotKey(void); inline ui_key UI_ActiveKey(void); inline platform_event_list *UI_EventList(void); inline arena *UI_FrameArena(void); inline v2 UI_MouseP(void); inline glyph_atlas *UI_GlyphAtlas(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: Helpers static r64 UI_Time(void); //- sixten: Key functions static ui_key UI_EmptyKey(void); static ui_key UI_SeedKey(ui_key Key, ui_key Seed); static ui_key UI_KeyFromString(string String); static string UI_BoxStringFromKey(ui_key Key); static ui_box *UI_BoxFromKey(ui *UI, ui_key Key); //- sixten: Box creation static ui_box *UI_MakeBox(ui_box_flags Flags, string String); static ui_box *UI_MakeBoxF(ui_box_flags Flags, char *Format, ...); static void UI_EquipBoxText(ui_box *Box, string String); static void UI_EquipBoxCustomDrawCallback(ui_box *Box, ui_custom_draw_callback *DrawCallback, void *Data); //- sixten: User interaction static ui_signal UI_SignalFromBox(ui_box *Box); //- sixten: Building and rendering static void UI_Init(ui *UI); static void UI_BeginBuild(ui *UI, v2 ScreenDim); static void UI_EndBuild(void); static void UI_RenderFrame(render_group *RenderGroup); static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas); #endif //VN_UI_H