diff --git a/code/core/core_math.cpp b/code/core/core_math.cpp index 591d999..a99a57f 100644 --- a/code/core/core_math.cpp +++ b/code/core/core_math.cpp @@ -507,6 +507,12 @@ inline r32 DimOfRange(range1_r32 Range) return(Result); } +inline range1_r32 Intersection(range1_r32 A, range1_r32 B) +{ + range1_r32 Result = {Max(A.Min, B.Min), Min(A.Max, B.Max)}; + return(Result); +} + inline range1_s32 Range1S32(s32 Min, s32 Max) { range1_s32 Result = {Min, Max}; @@ -525,6 +531,12 @@ inline s32 DimOfRange(range1_s32 Range) return(Result); } +inline range1_s32 Intersection(range1_s32 A, range1_s32 B) +{ + range1_s32 Result = {Max(A.Min, B.Min), Min(A.Max, B.Max)}; + return(Result); +} + inline range1_s64 Range1S64(s64 Min, s64 Max) { range1_s64 Result = {Min, Max}; @@ -543,6 +555,12 @@ inline s64 DimOfRange(range1_s64 Range) return(Result); } +inline range1_s64 Intersection(range1_s64 A, range1_s64 B) +{ + range1_s64 Result = {Max(A.Min, B.Min), Min(A.Max, B.Max)}; + return(Result); +} + inline range2_r32 Range2R32(v2_r32 Min, v2_r32 Max) { range2_r32 Result = {Min, Max}; @@ -562,6 +580,12 @@ inline v2_r32 DimOfRange(range2_r32 Range) return(Result); } +inline range2_r32 Intersection(range2_r32 A, range2_r32 B) +{ + range2_r32 Result = {Max(A.Min, B.Min), Min(A.Max, B.Max)}; + return(Result); +} + inline range2_s32 Range2S32(v2_s32 Min, v2_s32 Max) { range2_s32 Result = {Min, Max}; @@ -581,6 +605,12 @@ inline v2_s32 DimOfRange(range2_s32 Range) return(Result); } +inline range2_s32 Intersection(range2_s32 A, range2_s32 B) +{ + range2_s32 Result = {Max(A.Min, B.Min), Min(A.Max, B.Max)}; + return(Result); +} + inline range2_s64 Range2S64(v2_s64 Min, v2_s64 Max) { range2_s64 Result = {Min, Max}; @@ -598,4 +628,10 @@ inline v2_s64 DimOfRange(range2_s64 Range) { v2_s64 Result = Range.Max - Range.Min; return(Result); +} + +inline range2_s64 Intersection(range2_s64 A, range2_s64 B) +{ + range2_s64 Result = {Max(A.Min, B.Min), Min(A.Max, B.Max)}; + return(Result); } \ No newline at end of file diff --git a/code/core/core_math.h b/code/core/core_math.h index 3f580fe..3294946 100644 --- a/code/core/core_math.h +++ b/code/core/core_math.h @@ -209,6 +209,12 @@ inline r32 LinearBlend(r32 a, r32 b, r32 x) { r32 Result = a + (b-a)*x; return(R inline r32 Min(r32 A, r32 B) { r32 Result = Minimum(A, B); return(Result); } inline r32 Max(r32 A, r32 B) { r32 Result = Maximum(A, B); return(Result); } +inline s32 Min(s32 A, s32 B) { s32 Result = Minimum(A, B); return(Result); } +inline s32 Max(s32 A, s32 B) { s32 Result = Maximum(A, B); return(Result); } + +inline s64 Min(s64 A, s64 B) { s64 Result = Minimum(A, B); return(Result); } +inline s64 Max(s64 A, s64 B) { s64 Result = Maximum(A, B); return(Result); } + //- sixten: Vector functions inline v2_r32 V2R32(r32 x, r32 y); @@ -322,26 +328,32 @@ inline v4_s64 Max(v4_s64 A, v4_s64 B); inline range1_r32 Range1R32(r32 Min, r32 Max); inline b32 InRange(range1_r32 Range, r32 Value); inline r32 DimOfRange(range1_r32 Range); +inline range1_r32 Intersection(range1_r32 A, range1_r32 B); inline range1_s32 Range1S32(s32 Min, s32 Max); inline b32 InRange(range1_s32 Range, s32 Value); inline s32 DimOfRange(range1_s32 Range); +inline range1_s32 Intersection(range1_s32 A, range1_s32 B); inline range1_s64 Range1S64(s64 Min, s64 Max); inline b32 InRange(range1_s64 Range, s64 Value); inline s64 DimOfRange(range1_s64 Range); +inline range1_s64 Intersection(range1_s64 A, range1_s64 B); inline range2_r32 Range2R32(v2_r32 Min, v2_r32 Max); inline b32 InRange(range2_r32 Range, v2_r32 Value); inline v2_r32 DimOfRange(range2_r32 Range); +inline range2_r32 Intersection(range2_r32 A, range2_r32 B); inline range2_s32 Range2S32(v2_s32 Min, v2_s32 Max); inline b32 InRange(range2_s32 Range, v2_s32 Value); inline v2_s32 DimOfRange(range2_s32 Range); +inline range2_s32 Intersection(range2_s32 A, range2_s32 B); inline range2_s64 Range2S64(v2_s64 Min, v2_s64 Max); inline b32 InRange(range2_s64 Range, v2_s64 Value); inline v2_s64 DimOfRange(range2_s64 Range); +inline range2_s64 Intersection(range2_s64 A, range2_s64 B); //- sixten: Shorthand base types diff --git a/code/core/core_string.cpp b/code/core/core_string.cpp index c7edf34..88349a1 100644 --- a/code/core/core_string.cpp +++ b/code/core/core_string.cpp @@ -262,7 +262,7 @@ static string ConvertS64ToString(memory_arena *Arena, s64 Value) Value = -Value; } - s64 DigitCount = (s64)Floor(Log(Max(Value, 1)) / Log(10)) + 1; + s64 DigitCount = (s64)Floor(Log(Max(Value, 1LL)) / Log(10)) + 1; s64 TotalBufferCount = DigitCount + IsNegative; diff --git a/code/gen.cpp b/code/gen.cpp index efbd7f5..0de6dd2 100644 --- a/code/gen.cpp +++ b/code/gen.cpp @@ -1,4 +1,4 @@ -#include "vn_core.h" +#include "core/core.h" #include #define ArrayCount(Array) (sizeof(Array)/sizeof((Array)[0])) diff --git a/code/gen_ui.cpp b/code/gen_ui.cpp index f37d52c..00daa6f 100644 --- a/code/gen_ui.cpp +++ b/code/gen_ui.cpp @@ -20,6 +20,8 @@ ui_style_stack UIStyleStacks[] = { "CornerRadius", "r32", "CornerRadius" }, { "Font", "font_id", "Font" }, { "FontSize", "r32", "FontSize" }, + { "OffsetX", "r32", "Offset.x" }, + { "OffsetY", "r32", "Offset.y" }, }; static void GenUI(void) diff --git a/code/generated/vn_generated_ui.cpp b/code/generated/vn_generated_ui.cpp index 83ca56b..d275bb9 100644 --- a/code/generated/vn_generated_ui.cpp +++ b/code/generated/vn_generated_ui.cpp @@ -453,6 +453,76 @@ inline r32 UI_TopFontSize(void) #define UI_FontSize(Element) DeferLoop(UI_PushFontSize(Element), UI_PopFontSize()) +inline void UI_PushOffsetX(r32 Element) +{ + ui *UI = UI_GetState(); + Assert(UI->Stacks.OffsetXStackUsed + 1 < ArrayCount(UI->Stacks.OffsetXStack)); + UI->Stacks.OffsetXStack[UI->Stacks.OffsetXStackUsed++] = Element; +} + +inline void UI_PopOffsetX(void) +{ + ui *UI = UI_GetState(); + Assert(UI->Stacks.OffsetXStackUsed > 0); + --UI->Stacks.OffsetXStackUsed; +} + +inline void UI_SetNextOffsetX(r32 Element) +{ + ui *UI = UI_GetState(); + UI_PushOffsetX(Element); + UI->Stacks.AutoPopOffsetX = true; +} + +inline r32 UI_FirstOffsetX(void) +{ + ui *UI = UI_GetState(); + return(UI->Stacks.OffsetXStack[0]); +} + +inline r32 UI_TopOffsetX(void) +{ + ui *UI = UI_GetState(); + return(UI->Stacks.OffsetXStack[UI->Stacks.OffsetXStackUsed - 1]); +} + +#define UI_OffsetX(Element) DeferLoop(UI_PushOffsetX(Element), UI_PopOffsetX()) + +inline void UI_PushOffsetY(r32 Element) +{ + ui *UI = UI_GetState(); + Assert(UI->Stacks.OffsetYStackUsed + 1 < ArrayCount(UI->Stacks.OffsetYStack)); + UI->Stacks.OffsetYStack[UI->Stacks.OffsetYStackUsed++] = Element; +} + +inline void UI_PopOffsetY(void) +{ + ui *UI = UI_GetState(); + Assert(UI->Stacks.OffsetYStackUsed > 0); + --UI->Stacks.OffsetYStackUsed; +} + +inline void UI_SetNextOffsetY(r32 Element) +{ + ui *UI = UI_GetState(); + UI_PushOffsetY(Element); + UI->Stacks.AutoPopOffsetY = true; +} + +inline r32 UI_FirstOffsetY(void) +{ + ui *UI = UI_GetState(); + return(UI->Stacks.OffsetYStack[0]); +} + +inline r32 UI_TopOffsetY(void) +{ + ui *UI = UI_GetState(); + return(UI->Stacks.OffsetYStack[UI->Stacks.OffsetYStackUsed - 1]); +} + +#define UI_OffsetY(Element) DeferLoop(UI_PushOffsetY(Element), UI_PopOffsetY()) + inline void UI_ApplyStyles(ui_box *Box) { @@ -561,4 +631,20 @@ inline void UI_ApplyStyles(ui_box *Box) UI->Stacks.AutoPopFontSize = false; } + Assert(UI->Stacks.OffsetXStackUsed > 0); + Box->Offset.x = UI->Stacks.OffsetXStack[UI->Stacks.OffsetXStackUsed - 1]; + if(UI->Stacks.AutoPopOffsetX) + { + UI_PopOffsetX(); + UI->Stacks.AutoPopOffsetX = false; + } + + Assert(UI->Stacks.OffsetYStackUsed > 0); + Box->Offset.y = UI->Stacks.OffsetYStack[UI->Stacks.OffsetYStackUsed - 1]; + if(UI->Stacks.AutoPopOffsetY) + { + UI_PopOffsetY(); + UI->Stacks.AutoPopOffsetY = false; + } + } diff --git a/code/generated/vn_generated_ui.h b/code/generated/vn_generated_ui.h index a4f025f..44cbece 100644 --- a/code/generated/vn_generated_ui.h +++ b/code/generated/vn_generated_ui.h @@ -39,4 +39,10 @@ struct ui_style_stacks r32 FontSizeStack[64]; s32 FontSizeStackUsed; b32 AutoPopFontSize; + r32 OffsetXStack[64]; + s32 OffsetXStackUsed; + b32 AutoPopOffsetX; + r32 OffsetYStack[64]; + s32 OffsetYStackUsed; + b32 AutoPopOffsetY; }; diff --git a/code/vn.cpp b/code/vn.cpp index be0cd34..fd45005 100644 --- a/code/vn.cpp +++ b/code/vn.cpp @@ -7,6 +7,7 @@ struct debug_settings { b32 RenderUIDebugRects; b32 RenderFPSCounter; + b32 ListHotAndActive; }; per_thread debug_settings *DEBUG_DebugSettings = 0; @@ -18,6 +19,7 @@ per_thread debug_settings *DEBUG_DebugSettings = 0; #include "vn_font.h" #include "vn_text_op.h" #include "vn_ui.h" +#include "vn_ui_utils.h" #include "vn_workspace.h" #include "vn_theme_dark.h" #include "vn_animation_curve.h" @@ -66,6 +68,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) #if VN_INTERNAL Config_BindB32(State->Config, StrLit("Dev/RenderUIDebugRects"), &State->DebugSettings.RenderUIDebugRects, 0); Config_BindB32(State->Config, StrLit("Dev/RenderFPSCounter"), &State->DebugSettings.RenderFPSCounter, 0); + Config_BindB32(State->Config, StrLit("Dev/ListHotAndActive"), &State->DebugSettings.ListHotAndActive, 0); #endif Config_ReadFile(State->Config, StrLit("config.vn")); @@ -79,13 +82,13 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) #endif AnimationCurve_NewFrame(&State->AnimationCurveState, Input->dtForFrame); - UI_NewFrame(&State->UI, Input->EventList, Input->MouseP); + UI_NewFrame(&State->UI, Input->EventList, Input->MouseP, State->GlyphAtlas); UI_BeginBuild(RenderCommands->RenderDim); { Workspace_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas); } - UI_EndBuild(State->GlyphAtlas); + UI_EndBuild(); for(platform_event *Event = Input->EventList->First; @@ -105,4 +108,12 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) PushClear(&Group, V3(0.1, 0.1, 0.1)); UI_RenderFrame(&Group, State->GlyphAtlas); + + if(DEBUG_DebugSettings->ListHotAndActive) + { + PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - 20), 15, Color_Grey, + PushFormat(&State->UI.FrameArena, "Hot: %S:%llu", UI_GetBoxNameByKey(UI_GetHot()), UI_GetHot())); + PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - 40), 15, Color_Grey, + PushFormat(&State->UI.FrameArena, "Active: %S:%llu", UI_GetBoxNameByKey(UI_GetActive()), UI_GetActive())); + } } \ No newline at end of file diff --git a/code/vn_font.cpp b/code/vn_font.cpp index 68d2124..eb8368e 100644 --- a/code/vn_font.cpp +++ b/code/vn_font.cpp @@ -116,6 +116,7 @@ static glyph_atlas *CreateGlyphAtlas(vn_render_commands *RenderCommands, Atlas->Fonts[Font_Regular].Data = Platform_ReadEntireFile(&Atlas->Arena, StrLit("fonts/Roboto-Regular.ttf")); Atlas->Fonts[Font_Bold].Data = Platform_ReadEntireFile(&Atlas->Arena, StrLit("fonts/Roboto-Bold.ttf")); Atlas->Fonts[Font_Monospace].Data = Platform_ReadEntireFile(&Atlas->Arena, StrLit("fonts/Liberation-Mono.ttf")); + Atlas->Fonts[Font_Hand].Data = Platform_ReadEntireFile(&Atlas->Arena, StrLit("fonts/PatrickHand-Regular.ttf")); Atlas->Fonts[Font_Icons].Data = Platform_ReadEntireFile(&Atlas->Arena, StrLit("fonts/icons.ttf")); for(s32 FontIndex = 0; diff --git a/code/vn_font.h b/code/vn_font.h index da4fdca..8d33dbb 100644 --- a/code/vn_font.h +++ b/code/vn_font.h @@ -8,6 +8,7 @@ enum font_id Font_Regular, Font_Bold, Font_Monospace, + Font_Hand, Font_Icons, Font_Count, diff --git a/code/vn_render.cpp b/code/vn_render.cpp index 3b62690..09ab620 100644 --- a/code/vn_render.cpp +++ b/code/vn_render.cpp @@ -127,7 +127,7 @@ inline void PushTexturedQuad(render_group *Group, v2 DestMin = Max(Dest.Min, Clip.Min); v2 DestMax = Min(Dest.Max, Clip.Max); - //if(InRange(Clip, P) || InRange(Clip, P + Dim)) + if(InRange(Clip, P) || InRange(Clip, P + Dim)) { v2 HalfSize = Dim*0.5; diff --git a/code/vn_render.h b/code/vn_render.h index eae4e40..6375b57 100644 --- a/code/vn_render.h +++ b/code/vn_render.h @@ -8,6 +8,9 @@ #define ColorFromHex(Value) V4((((Value) >> 24) & 0xFF) / 255.0, (((Value) >> 16) & 0xFF) / 255.0, (((Value) >> 8) & 0xFF) / 255.0, (((Value) >> 0) & 0xFF) / 255.0) +#define Brighten(Color, Amount) (Color*(Amount)) +#define Darken(Color, Amount) (Color*(1.0/(Amount))) + read_only v4 Color_Black = V4(0, 0, 0, 1); read_only v4 Color_White = V4(1, 1, 1, 1); read_only v4 Color_Grey = V4(0.5, 0.5, 0.5, 1); diff --git a/code/vn_ui.cpp b/code/vn_ui.cpp index aad2251..391bf84 100644 --- a/code/vn_ui.cpp +++ b/code/vn_ui.cpp @@ -30,7 +30,6 @@ inline ui_size UI_ChildrenSum(r32 Value, r32 Strictness) return(Result); } - per_thread ui *ThreadLocal_UI; inline void UI_SetState(ui *UI) @@ -304,26 +303,36 @@ inline void UI_SetNextHot(ui_key Key) } } -inline b32 UI_ChildrenContainsP(ui_box *Box, v2 P) +// sixten(NOTE): ClippingRect = Intersection(TrueClippingRect, Parent->Rect); +static b32 UI_ChildrenContainsP(ui_box *Parent, v2 P, range2_r32 Clip) { b32 Result = false; - if(Box->Flags & UI_BoxFlag_Clickable && InRange(Box->Rect, P)) + for(ui_box *Child = Parent->First; + Child != 0; + Child = Child->Next) { - Result = true; - } - else - { - if(Box->First) - { - Result = UI_ChildrenContainsP(Box->First, P); - } + range2_r32 IntersectionRect = Intersection(Clip, Child->Rect); - if(!Result) + if(Child->Flags & UI_BoxFlag_Clickable && InRange(IntersectionRect, P)) { - if(Box->Next) + Result = true; + break; + } + else + { + if(Child->Flags & UI_BoxFlag_Clip) { - Result = UI_ChildrenContainsP(Box->Next, P); + Result = UI_ChildrenContainsP(Child, P, IntersectionRect); + } + else + { + Result = UI_ChildrenContainsP(Child, P, Clip); + } + + if(Result) + { + break; } } } @@ -337,9 +346,19 @@ static ui_signal UI_SignalFromBox(ui_box *Box) ui_signal Signal = {}; - Signal.Hovering = InRange(Box->Rect, UI->MouseP) && - !(Box->First && UI_ChildrenContainsP(Box->First, UI->MouseP)) && - !(Box->Next && UI_ChildrenContainsP(Box->Next, UI->MouseP)); + // sixten: Gather the clipping rects of all the parents. + range2_r32 ClippedRect = Box->Rect; + for(ui_box *Parent = Box->Parent; + Parent != 0; + Parent = Parent->Parent) + { + if(Parent->Flags & UI_BoxFlag_Clip) + { + ClippedRect = Intersection(ClippedRect, Parent->Rect); + } + } + + Signal.Hovering = InRange(ClippedRect, UI->MouseP) && !UI_ChildrenContainsP(Box, UI->MouseP, ClippedRect); // sixten: Make sure the tooltip is not overlapping. { @@ -356,9 +375,10 @@ static ui_signal UI_SignalFromBox(ui_box *Box) } } - if(!FoundTooltip && UI->TooltipNode->First) + if(!FoundTooltip) { - Signal.Hovering &= ~UI_ChildrenContainsP(UI->TooltipNode->First, UI->MouseP); + Signal.Hovering &= ~UI_ChildrenContainsP(UI->TooltipNode, UI->MouseP, + Range2R32(V2(0, 0), V2(InfinityR32, InfinityR32))); } } @@ -585,7 +605,8 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas if(Box->Flags & UI_BoxFlag_Clip) { - PushClip(Group, Box->Rect); + range2_r32 Rect = Intersection(Group->ClipStack[Group->ClipStackUsed], Box->Rect); + PushClip(Group, Rect); } for(ui_box *Child = Box->First; @@ -622,12 +643,13 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas } } -static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, glyph_atlas *Atlas); +static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis); -static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) +static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis) { r32 Result = 0; + ui *UI = UI_GetState(); ui_box *Parent = Box->Parent; switch(Box->SemanticSize[Axis].Type) @@ -639,6 +661,8 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) case UI_SizeType_TextContent: { + glyph_atlas *Atlas = UI->GlyphAtlas; + Result = ((Axis == Axis2_X) ? CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, Box->String) : CalculateRasterizedTextHeight(Atlas, Box->Font, Box->FontSize, Box->String)) + @@ -661,7 +685,7 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) case UI_SizeType_ChildrenSum: { - Result = UI_CalculateChildrenSum(Box, Axis, Atlas)*Box->SemanticSize[Axis].Value; + Result = UI_CalculateChildrenSum(Box, Axis)*Box->SemanticSize[Axis].Value; } break; InvalidDefaultCase; @@ -670,7 +694,7 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) return(Result); } -static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) +static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis) { r32 Result = 0; @@ -680,7 +704,7 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) Child != 0; Child = Child->Next) { - Result += UI_CalculateBoxSize(Child, Axis, Atlas); + Result += UI_CalculateBoxSize(Child, Axis); } } else @@ -689,31 +713,33 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) Child != 0; Child = Child->Next) { - Result = Max(Result, UI_CalculateBoxSize(Child, Axis, Atlas)); + Result = Max(Result, UI_CalculateBoxSize(Child, Axis)); } } return(Result); } -static void UI_LayoutBox(ui_box *Box, axis2 Axis, glyph_atlas *Atlas) +static void UI_LayoutBox(ui_box *Box) { for(ui_box *Child = Box->First; Child != 0; Child = Child->Next) { - Child->ComputedDim.E[Axis] = UI_CalculateBoxSize(Child, Axis, Atlas); + Child->ComputedDim.E[Axis2_X] = UI_CalculateBoxSize(Child, Axis2_X); + Child->ComputedDim.E[Axis2_Y] = UI_CalculateBoxSize(Child, Axis2_Y); } - UI_SolveSizeViolations(Box, Axis); + UI_SolveSizeViolations(Box, Axis2_X); + UI_SolveSizeViolations(Box, Axis2_Y); for(ui_box *Child = Box->First; - Child; + Child != 0; Child = Child->Next) { - Child->Rect.Min.E[Axis] = Box->Rect.Min.E[Axis] + Child->ComputedRelativeP.E[Axis]; - Child->Rect.Max.E[Axis] = Child->Rect.Min.E[Axis] + Child->ComputedDim.E[Axis]; + Child->Rect.Min = Box->Rect.Min + Child->ComputedRelativeP + Box->Offset; + Child->Rect.Max = Child->Rect.Min + Child->ComputedDim; - UI_LayoutBox(Child, Axis, Atlas); + UI_LayoutBox(Child); } } @@ -734,6 +760,8 @@ static void UI_BeginBuild(v2 ScreenDim) UI_PushCornerRadius(0); UI_PushFont(Font_Regular); UI_PushFontSize(15.0f); + UI_PushOffsetX(0); + UI_PushOffsetY(0); UI->RootNode = UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("UI Root Node")); UI->Stacks.ParentStack[0] = UI->RootNode; @@ -746,7 +774,7 @@ static void UI_BeginBuild(v2 ScreenDim) UI->NextHotSet = false; } -static void UI_EndBuild(glyph_atlas *GlyphAtlas) +static void UI_EndBuild(void) { ui *UI = UI_GetState(); @@ -770,9 +798,10 @@ static void UI_EndBuild(glyph_atlas *GlyphAtlas) UI_PopCornerRadius(); UI_PopFont(); UI_PopFontSize(); + UI_PopOffsetX(); + UI_PopOffsetY(); - UI_LayoutBox(UI->RootNode, Axis2_X, GlyphAtlas); - UI_LayoutBox(UI->RootNode, Axis2_Y, GlyphAtlas); + UI_LayoutBox(UI->RootNode); } static void UI_RenderFrame(render_group *Group, glyph_atlas *GlyphAtlas) @@ -804,7 +833,7 @@ inline void UI_ScanForHotAndActive(ui_box *Box, b32 *FoundHot, b32 *FoundActive) } } -static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP) +static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, glyph_atlas *GlyphAtlas) { UI_SetState(UI); @@ -818,6 +847,8 @@ static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP) UI->EventList = EventList; UI->MouseP = MouseP; + UI->GlyphAtlas = GlyphAtlas; + // sixten: Make sure that the hot and active boxes are valid. if(UI->RootNode) { diff --git a/code/vn_ui.h b/code/vn_ui.h index 0684e91..f029bae 100644 --- a/code/vn_ui.h +++ b/code/vn_ui.h @@ -3,6 +3,7 @@ #ifndef VN_UI_H #define VN_UI_H +//- sixten: Keying struct ui_key { u64 Value; @@ -14,23 +15,7 @@ inline b32 AreEqual(ui_key A, ui_key B) 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; - +//- sixten: Semantic sizing enum ui_size_type { UI_SizeType_Pixels, @@ -52,6 +37,24 @@ inline ui_size UI_TextContent(r32 Value, r32 Strictness); inline ui_size UI_Percent(r32 Value, r32 Strictness); inline ui_size UI_ChildrenSum(r32 Value, r32 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), +}; +typedef u32 ui_box_flags; + typedef void ui_draw_callback(render_group *Group, glyph_atlas *Atlas, struct ui_box *Box, void *Data); struct ui_box @@ -81,6 +84,7 @@ struct ui_box r32 CornerRadius; font_id Font; r32 FontSize; + v2 Offset; ui_draw_callback *DrawCallback; void *DrawCallbackData; @@ -136,13 +140,15 @@ struct ui ui_key NextHot; b32 NextHotSet; - platform_event_list *EventList; - v2 MouseP; - u64 DragData[8]; v2 DragStartP; ui_style_stacks Stacks; + + platform_event_list *EventList; + v2 MouseP; + + glyph_atlas *GlyphAtlas; }; //- sixten: State management @@ -166,20 +172,23 @@ 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 ui_key UI_EmptyKey(void); +static ui_key UI_SeedKey(ui_key Key, ui_key Seed); +static ui_key UI_GenerateKeyFromString(string String); static string UI_GetBoxNameByKey(ui_key Key); -inline ui_box *UI_GetBoxByKey(ui *UI, ui_key Key); +static 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, ...); +static ui_box *UI_MakeBox(ui_box_flags Flags, string String); +static ui_box *UI_MakeBoxF(ui_box_flags Flags, char *Format, ...); + +//- sixten: User interaction +static ui_signal UI_SignalFromBox(ui_box *Box); //- 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); +static void UI_EndBuild(void); +static void UI_RenderFrame(render_group *RenderGroup); +static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, glyph_atlas *GlyphAtlas); #endif //VN_UI_H diff --git a/code/vn_ui_utils.cpp b/code/vn_ui_utils.cpp index 620de29..fdd88d3 100644 --- a/code/vn_ui_utils.cpp +++ b/code/vn_ui_utils.cpp @@ -1,8 +1,8 @@ -// sixten: Rows and columns. -inline void UI_RowBegin(void) +//- sixten: Rows and columns. +inline void UI_RowBegin(u32 Flags, string Name) { UI_SetNextLayoutAxis(Axis2_X); - ui_box *Box = UI_MakeBox(0, StrLit("")); + ui_box *Box = UI_MakeBox(Flags, Name); UI_PushParent(Box); } @@ -11,10 +11,10 @@ inline void UI_RowEnd(void) UI_PopParent(); } -inline void UI_ColumnBegin(void) +inline void UI_ColumnBegin(u32 Flags, string Name) { UI_SetNextLayoutAxis(Axis2_Y); - ui_box *Box = UI_MakeBox(0, StrLit("")); + ui_box *Box = UI_MakeBox(Flags, Name); UI_PushParent(Box); } @@ -23,10 +23,7 @@ inline void UI_ColumnEnd(void) UI_PopParent(); } -#define UI_Row DeferLoop(UI_RowBegin(), UI_RowEnd()) -#define UI_Column DeferLoop(UI_ColumnBegin(), UI_ColumnEnd()) - -// sixten: Compositions +//- sixten: Compositions inline void UI_PushAxisSize(axis2 Axis, ui_size Size) { if(Axis == Axis2_X) @@ -63,17 +60,7 @@ inline void UI_SetNextAxisSize(axis2 Axis, ui_size Size) } } -#define UI_AxisSize(Axis, Size) DeferLoop(UI_PushAxisSize(Axis, Size), UI_PopAxisSize(Axis)) - -#define UI_Size(Width, Height) UI_Width(Width) UI_Height(Height) -#define UI_PushSize(Width, Height) UI_PushWidth(Width); UI_PushHeight(Height) -#define UI_PopSize() UI_PopWidth(); UI_PopHeight() -#define UI_SetNextSize(Width, Height) UI_SetNextWidth(Width); UI_SetNextHeight(Height) - -#define UI_FixedP(Value) UI_FixedX(Value.x) UI_FixedY(Value.y) -#define UI_SetNextFixedP(Value) UI_SetNextFixedX(Value.x); UI_SetNextFixedY(Value.y) - -// sixten: Spacing +//- sixten: Spacing static ui_box *UI_NamedSpacer(ui_size Size, string String) { ui_box *Parent = UI_TopParent(); @@ -104,9 +91,10 @@ static void UI_Spacer(ui_size Size) UI_NamedSpacer(Size, StrLit("")); } -#define UI_Padding(Size) DeferLoop(UI_Spacer(Size), UI_Spacer(Size)) +//- sixten: Scrollable regions -// sixten: Common widgets + +//- sixten: Common widgets static ui_box *UI_Label(string String) { ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawText, String); @@ -165,7 +153,7 @@ static ui_signal UI_ButtonF(char *Format, ...) return(Signal); } -static ui_signal UI_Checkbox(string String, b32 *Checked) +static ui_signal UI_Checkbox(b32 *Checked, string String) { UI_SetNextSize(UI_ChildrenSum(1, 1), UI_ChildrenSum(1, 1)); UI_SetNextLayoutAxis(Axis2_X); @@ -196,4 +184,174 @@ static ui_signal UI_Checkbox(string String, b32 *Checked) } return(Signal); +} + +//- sixten: Scrollable regions +static ui_signal UI_Scrollbar(axis2 Axis, string Name, r32 Size, r32 Offset) +{ + ui_signal Signal; + + UI_SetNextAxisSize(Axis, UI_Percent(1, 0)); + UI_SetNextAxisSize(Opposite(Axis), UI_Em(1, 1)); + UI_SetNextBackgroundColor(Darken(UI_TopBackgroundColor(), 2)); + UI_SetNextLayoutAxis(Axis); + UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, Name)) + { + UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1)); + UI_SetNextFont(Font_Icons); + UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", Axis?FontIcon_UpDir:FontIcon_LeftDir); + + UI_Spacer(UI_Pixels(Offset, 1)); + + UI_SetNextAxisSize(Axis, UI_Pixels(Size, 1)); + UI_SetNextAxisSize(Opposite(Axis), UI_Percent(1, 1)); + + Signal = UI_SignalFromBox(UI_MakeBox(UI_BoxFlag_DrawBorder | + UI_BoxFlag_DrawBackground | + UI_BoxFlag_Clickable | + UI_BoxFlag_HotAnimation | + UI_BoxFlag_ActiveAnimation, + StrLit("Slider"))); + + UI_Spacer(UI_Percent(1, 0)); + + UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1)); + UI_SetNextFont(Font_Icons); + UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", Axis?FontIcon_DownDir:FontIcon_RightDir); + } + + return(Signal); +} + +/* + +Goal for next week: Be able to make basic dialog trees. +Goal for tomorrow: Scrollable regions and basic text editing (with line wrapping). + +*/ + +static void UI_ScrollBegin(r32 *X, r32 *Y, string Name) +{ + u32 Flags = 0; + + b32 AllowOnX = (X != 0); + b32 AllowOnY = (Y != 0); + + UI_RowBegin(UI_BoxFlag_Clip|UI_BoxFlag_DrawBorder, Name); + { + UI_SetNextSize(UI_Percent(1, 0), UI_Percent(1, 0)); + UI_ColumnBegin(); + { + if(AllowOnX) + { + Flags |= UI_BoxFlag_OverflowX; + UI_SetNextOffsetX(-(*X)); + } + + if(AllowOnY) + { + Flags |= UI_BoxFlag_OverflowY; + UI_SetNextOffsetY(-(*Y)); + } + + UI_SetNextSize(AllowOnX?UI_ChildrenSum(1, 1):UI_Percent(1, 0), + AllowOnY?UI_ChildrenSum(1, 1):UI_Percent(1, 0)); + + ui_box *ScrollableBox = UI_MakeBox(Flags, StrLit("Scrollable Box")); + + UI_PushParent(ScrollableBox); + } + } +} + +static void UI_ScrollEnd(r32 *X, r32 *Y) +{ + b32 AllowOnX = (X != 0); + b32 AllowOnY = (Y != 0); + + ui_box *ScrollableBox = UI_TopParent(); + { + { + UI_PopParent(); + + if(AllowOnX) + { + r32 TotalWidth = UI_CalculateBoxSize(ScrollableBox, Axis2_X); + r32 ViewWidth = UI_CalculateBoxSize(ScrollableBox->Parent->Parent, Axis2_X); + + if(ViewWidth / TotalWidth < 1) + { + r32 TotalScrollWidth = ViewWidth - ScrollableBox->FontSize*2; + r32 ScrollScale = TotalScrollWidth / TotalWidth; + + // sixten(TODO): Add a max of 1 em, and figure out the associated algebra. + r32 ScrollWidth = ViewWidth*ScrollScale; + r32 ScrollOffset = (*X)*ScrollScale; + + ui_signal Signal = UI_Scrollbar(Axis2_X, StrLit("Scroll X"), ScrollWidth, ScrollOffset); + { + if(Signal.Dragging) + { + if(Signal.Pressed) + { + UI_StoreDragR32(*X); + } + + r32 StartOffset = UI_GetDragR32(); + r32 EndOffset = StartOffset + Signal.DragDelta.x/ScrollScale; + + AnimationCurve_AnimateValueDirect(EndOffset, 0.2, X); + } + } + } + *X = Clamp(*X, 0, Max(0.0, TotalWidth - ViewWidth)); + } + } + UI_ColumnEnd(); + + if(AllowOnY) + { + UI_SetNextSize(UI_ChildrenSum(1, 1), UI_Percent(1, 0)); + UI_Column() + { + r32 TotalHeight = UI_CalculateBoxSize(ScrollableBox, Axis2_Y); + r32 ViewHeight = UI_CalculateBoxSize(ScrollableBox->Parent->Parent, Axis2_Y); + + if(ViewHeight / TotalHeight < 1) + { + r32 TotalScrollHeight = ViewHeight - ScrollableBox->FontSize*2; + r32 ScrollScale = TotalScrollHeight / TotalHeight; + + // sixten(TODO): Add a max of 1 em, and figure out the associated algebra. + r32 ScrollHeight = ViewHeight*ScrollScale; + r32 ScrollOffset = (*Y)*ScrollScale; + + ui_signal Signal = UI_Scrollbar(Axis2_Y, StrLit("Scroll Y"), ScrollHeight, ScrollOffset); + { + if(Signal.Dragging) + { + if(Signal.Pressed) + { + UI_StoreDragR32(*Y); + } + + r32 StartOffset = UI_GetDragR32(); + r32 EndOffset = StartOffset + Signal.DragDelta.y/ScrollScale; + + AnimationCurve_AnimateValueDirect(EndOffset, 0.2, Y); + } + } + } + *Y = Clamp(*Y, 0, Max(0.0, TotalHeight - ViewHeight)); + } + // sixten: Add padding + if(AllowOnX && AllowOnY) + { + UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1)); + UI_SetNextBackgroundColor(Darken(UI_TopBackgroundColor(), 2)); + UI_MakeBox(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, StrLit("Padding")); + } + } + } + UI_RowEnd(); } \ No newline at end of file diff --git a/code/vn_ui_utils.h b/code/vn_ui_utils.h new file mode 100644 index 0000000..4915f37 --- /dev/null +++ b/code/vn_ui_utils.h @@ -0,0 +1,56 @@ +/* date = June 24th 2023 9:43 pm */ + +#ifndef VN_UI_UTILS_H +#define VN_UI_UTILS_H + +//- sixten: Rows and columns. +inline void UI_RowBegin(u32 Flags = 0, string Name = StrLit("")); +inline void UI_RowEnd(void); +inline void UI_ColumnBegin(u32 Flags = 0, string Name = StrLit("")); +inline void UI_ColumnEnd(void); + +#define UI_Row(...) DeferLoop(UI_RowBegin(__VA_ARGS__), UI_RowEnd()) +#define UI_Column(...) DeferLoop(UI_ColumnBegin(__VA_ARGS__), UI_ColumnEnd()) + +//- sixten: Compositions +inline void UI_PushAxisSize(axis2 Axis, ui_size Size); +inline void UI_PopAxisSize(axis2 Axis); +inline void UI_SetNextAxisSize(axis2 Axis, ui_size Size); + +#define UI_AxisSize(Axis, Size) DeferLoop(UI_PushAxisSize(Axis, Size), UI_PopAxisSize(Axis)) + +#define UI_Size(Width, Height) UI_Width(Width) UI_Height(Height) +#define UI_PushSize(Width, Height) UI_PushWidth(Width); UI_PushHeight(Height) +#define UI_PopSize() UI_PopWidth(); UI_PopHeight() +#define UI_SetNextSize(Width, Height) UI_SetNextWidth(Width); UI_SetNextHeight(Height) + +#define UI_Offset(x, y) UI_OffsetX(x) UI_OffsetY(y) +#define UI_PushOffset(x, y) UI_PushOffsetX(x); UI_PushOffsetY(y) +#define UI_PopOffset() UI_PopOffsetX(); UI_PopOffsetY() +#define UI_SetNextOffset(x, y) UI_SetNextOffsetX(x); UI_SetNextOffsetY(y) + +#define UI_FixedP(Value) UI_FixedX(Value.x) UI_FixedY(Value.y) +#define UI_SetNextFixedP(Value) UI_SetNextFixedX(Value.x); UI_SetNextFixedY(Value.y) + +//- sixten: Spacing +static ui_box *UI_NamedSpacer(ui_size Size, string String); +static ui_box *UI_NamedSpacerF(ui_size Size, char *Format, ...); + +#define UI_Padding(Size) DeferLoop(UI_Spacer(Size), UI_Spacer(Size)) + +//- sixten: Scrollable regions +static void UI_ScrollBegin(r32 *X, r32 *Y, string Name = StrLit("Scrollable Region Container")); +static void UI_ScrollEnd(r32 *X, r32 *Y, string Name); + +#define UI_Scroll(...) DeferLoop(UI_ScrollBegin(__VA_ARGS__), UI_ScrollEnd(__VA_ARGS__)) + +//- sixten: Common widgets +static ui_box *UI_Label(string String); +static ui_box *UI_LabelF(char *Format, ...); + +static ui_signal UI_Button(string String); +static ui_signal UI_ButtonF(char *Format, ...); + +static ui_signal UI_Checkbox(b32 *Checked, string String); + +#endif //VN_UI_UTILS_H diff --git a/code/vn_workspace.cpp b/code/vn_workspace.cpp index c0057e8..18327b4 100644 --- a/code/vn_workspace.cpp +++ b/code/vn_workspace.cpp @@ -205,6 +205,12 @@ static void Workspace_BuildToolbar(workspace *Workspace, r32 dtForFrame) Workspace->Menu = ToolbarMenu_None; } + if(Workspace_BuildMenuItem(FontIcon_None, "Command Palette", "").Clicked) + { + Workspace_CreateNewView(Workspace_View_CommandPalette, CurrentPanel); + + Workspace->Menu = ToolbarMenu_None; + } if(Workspace_BuildMenuItem(FontIcon_Wrench, "Settings", "").Clicked) { Workspace_CreateNewView(Workspace_View_Settings, CurrentPanel); @@ -419,6 +425,8 @@ static void Workspace_BuildPanelHeader(workspace *Workspace, workspace_panel *Pa Workspace_BuildTabItem(Workspace, Panel, View); } + UI_Spacer(UI_Percent(1, 0)); + // sixten: Panel Close Button if(Panel != Workspace->RootPanel) { @@ -500,8 +508,8 @@ static void Workspace_BuildPanel(workspace *Workspace, workspace_panel *Panel) } else { - UI_Column UI_Padding(UI_Percent(1, 0)) - UI_Height(UI_ChildrenSum(1, 1)) UI_Row UI_Padding(UI_Percent(1, 0)) + UI_Column() UI_Padding(UI_Percent(1, 0)) + UI_Height(UI_ChildrenSum(1, 1)) UI_Row() UI_Padding(UI_Percent(1, 0)) { UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1)) { diff --git a/code/vn_workspace_view.cpp b/code/vn_workspace_view.cpp index f6852a0..03479d0 100644 --- a/code/vn_workspace_view.cpp +++ b/code/vn_workspace_view.cpp @@ -146,7 +146,7 @@ static void Workspace_BuildViewTypeLister(workspace *Workspace, workspace_view * ui_box *InputTextBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Workspace View Lister")); InputTextBox->String = MakeString(CommandPalette->ListerInput, CommandPalette->ListerInputUsed); InputTextBox->DrawCallback = Workspace_ViewListerInputCallback; - InputTextBox->DrawCallbackData = View; + InputTextBox->DrawCallbackData = CommandPalette; } UI_Spacer(UI_Pixels(4, 1)); @@ -338,8 +338,8 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View) workspace_view_settings *Settings = (workspace_view_settings *)View->Data; UI_Height(UI_ChildrenSum(1, 1)) - UI_Column UI_Padding(UI_Pixels(50, 0)) - UI_Row UI_Padding(UI_Pixels(50, 0)) + UI_Column() UI_Padding(UI_Pixels(50, 0)) + UI_Row() UI_Padding(UI_Pixels(50, 0)) { UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1)) UI_Font(Font_Bold) UI_FontSize(36) @@ -353,8 +353,8 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View) UI_Width(UI_Pixels(300, 1)) UI_Parent(UI_MakeBoxF(0, "Navigation")) { - UI_Row UI_Padding(UI_Pixels(50, 1)) - UI_Width(UI_Percent(1, 0)) UI_Column UI_Padding(UI_Percent(1, 0)) + UI_Row() UI_Padding(UI_Pixels(50, 1)) + UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Percent(1, 0)) UI_Height(UI_ChildrenSum(1, 1)) UI_LayoutAxis(Axis2_Y) UI_Parent(UI_MakeBoxF(0, "")) { Workspace_BuildSettingsTabButton(Settings, "All", Workspace_Settings_All); @@ -391,12 +391,11 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View) s32 DropdownSelected; FindIndexOfElement(DropdownSelected, AlternativeMapping, 0, Workspace->Input->RefreshRate); - persist b32 DropdownOpen = false; - - if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives), &DropdownOpen, &DropdownSelected)) + if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives), + &Settings->GeneralDropdownOpen, &DropdownSelected)) { Workspace->Input->RefreshRate = AlternativeMapping[DropdownSelected]; - DropdownOpen = false; + Settings->GeneralDropdownOpen = false; } UI_Spacer(UI_Pixels(50, 1)); @@ -406,19 +405,25 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View) { UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Theme"); - UI_SetNextSize(UI_Percent(1, 1), UI_ChildrenSum(1, 1)); - UI_SetNextCornerRadius(3); + UI_SetNextSize(UI_Percent(1, 1), UI_Em(13, 1)); - UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBorder, "Theme Lister")) - UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) + UI_Scroll(0, &Settings->ThemeScroll) { - UI_ButtonF("Hello"); - UI_ButtonF("Line"); - UI_ButtonF("Paint"); - UI_ButtonF("Color"); - UI_ButtonF("Design"); - UI_ButtonF("Address"); - UI_ButtonF("Brightness"); + UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) + { + for(s32 Index = 0; + Index < 2; + ++Index) + { + UI_ButtonF("Hello#%i", Index); + UI_ButtonF("Line#%i", Index); + UI_ButtonF("Paint#%i", Index); + UI_ButtonF("Color#%i", Index); + UI_ButtonF("Design#%i", Index); + UI_ButtonF("Address#%i", Index); + UI_ButtonF("Brightness#%i", Index); + } + } } UI_Spacer(UI_Pixels(50, 1)); @@ -427,9 +432,11 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View) if(!Category || (Category == Workspace_Settings_Developer)) { UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Developer"); - UI_Checkbox(StrLit("Render UI Debug Rects"), &DEBUG_DebugSettings->RenderUIDebugRects); + UI_Checkbox(&DEBUG_DebugSettings->RenderUIDebugRects, StrLit("Render UI Debug Rects")); UI_Spacer(UI_Pixels(5, 1)); - UI_Checkbox(StrLit("Render FPS Counter"), &DEBUG_DebugSettings->RenderFPSCounter); + UI_Checkbox(&DEBUG_DebugSettings->RenderFPSCounter, StrLit("Render FPS Counter")); + UI_Spacer(UI_Pixels(5, 1)); + UI_Checkbox(&DEBUG_DebugSettings->ListHotAndActive, StrLit("List Hot & Active")); UI_Spacer(UI_Pixels(50, 1)); } @@ -459,8 +466,8 @@ static void Workspace_BuildView(workspace *Workspace, workspace_view *View) { if(View->Type == Workspace_View_Startup) { - UI_Row UI_Padding(UI_Pixels(50, 0)) - UI_Width(UI_ChildrenSum(1, 1)) UI_Column UI_Padding(UI_Pixels(50, 0)) + UI_Row() UI_Padding(UI_Pixels(50, 0)) + UI_Width(UI_ChildrenSum(1, 1)) UI_Column() UI_Padding(UI_Pixels(50, 0)) { UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1)) { diff --git a/code/vn_workspace_view.h b/code/vn_workspace_view.h index d0c031b..a90eef0 100644 --- a/code/vn_workspace_view.h +++ b/code/vn_workspace_view.h @@ -53,6 +53,12 @@ enum workspace_settings_category struct workspace_view_settings { workspace_settings_category Category; + + // sixten: General + b32 GeneralDropdownOpen; + + // sixten: Theme + r32 ThemeScroll; }; //- sixten: Views diff --git a/config.vn b/config.vn index f749c5c..f6daacd 100644 --- a/config.vn +++ b/config.vn @@ -7,4 +7,5 @@ Dev { RenderUIDebugRects = false; RenderFPSCounter = false; + ListHotAndActive = true; } \ No newline at end of file diff --git a/fonts/PatrickHand-Regular.ttf b/fonts/PatrickHand-Regular.ttf new file mode 100644 index 0000000..a1b90ba Binary files /dev/null and b/fonts/PatrickHand-Regular.ttf differ diff --git a/todo.txt b/todo.txt index 28efaf3..cbf17de 100644 --- a/todo.txt +++ b/todo.txt @@ -1,9 +1,12 @@ This is a list of things that needs doing in a SUGGESTED order. * UI - - Settings / Preferences view. (Including saving and loading of these settings/preferences) + - Incorrect behaviour when closing panels in a certain order, most likely some things are not being copied over properly. * Rendering - Fix texture clipping - Control over each corner when rounding +Completed +* UI + - Settings / Preferences view. (Including saving and loading of these settings/preferences) \ No newline at end of file