Implemented adding animation clips to the timeline

This commit is contained in:
Peter Slattery 2019-12-28 16:01:34 -08:00
parent 20636acdce
commit 6a080f3aed
4 changed files with 149 additions and 169 deletions

View File

@ -197,17 +197,8 @@ INITIALIZE_APPLICATION(InitializeApplication)
InitializeAnimationSystem(&State->AnimationSystem); InitializeAnimationSystem(&State->AnimationSystem);
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
animation_block BlockOne = {0}; AddAnimationBlock(0, 8, TestPatternTwo, &State->AnimationSystem);
BlockOne.StartTime = 0; AddAnimationBlock(8, 15, TestPatternThree, &State->AnimationSystem);
BlockOne.EndTime = 8;
BlockOne.Proc = TestPatternTwo;
AddAnimationBlock(BlockOne, &State->AnimationSystem);
animation_block BlockTwo = {0};
BlockTwo.StartTime = 8;
BlockTwo.EndTime = 15;
BlockTwo.Proc = TestPatternThree;
AddAnimationBlock(BlockTwo, &State->AnimationSystem);
State->AnimationSystem.AnimationStart = 0; State->AnimationSystem.AnimationStart = 0;
State->AnimationSystem.AnimationEnd = 15; State->AnimationSystem.AnimationEnd = 15;

View File

@ -10,7 +10,7 @@ DrawCharacter_ (render_quad_batch_constructor* BatchConstructor, r32 MinX, r32 M
{ {
s32 AlignedMinX = (s32)(MinX); s32 AlignedMinX = (s32)(MinX);
s32 AlignedMinY = (s32)(MinY); s32 AlignedMinY = (s32)(MinY);
s32 AlignedMaxX = AlignedMinX + (CodepointInfo.Width); s32 AlignedMaxX = AlignedMinX + (CodepointInfo.Width);
s32 AlignedMaxY = AlignedMinY + (CodepointInfo.Height); s32 AlignedMaxY = AlignedMinY + (CodepointInfo.Height);
PushQuad2DOnBatch(BatchConstructor, PushQuad2DOnBatch(BatchConstructor,
@ -434,140 +434,54 @@ enum selection_state
Selection_Deselected, Selection_Deselected,
}; };
struct scroll_list_result struct interface_list
{ {
s32 IndexSelected; rect ListBounds;
s32 StartIndex;
selection_state Selection; v2 ListElementDimensions;
v2 ElementLabelIndent;
v4 TextColor;
v4* LineBGColors;
s32 LineBGColorsCount;
v4 LineBGHoverColor;
s32 ListElementsCount;
}; };
internal scroll_list_result internal rect
DrawOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max, DrawListElementBackground(interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer)
string* Options, s32 OptionsCount,
s32 Start, interface_config Config, mouse_state Mouse)
{ {
scroll_list_result Result = {}; rect LineBounds = {};
Result.IndexSelected = -1; LineBounds.Min = v2{
Result.StartIndex = Start; List->ListBounds.Min.x,
Result.Selection = Selection_None; List->ListBounds.Max.y - (List->ListElementDimensions.y * (List->ListElementsCount + 1))
};
LineBounds.Max = LineBounds.Min + List->ListElementDimensions;
r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y); v4 Color = List->LineBGColors[List->ListElementsCount % List->LineBGColorsCount];
r32 OptionOffset = OptionHeight + Config.Margin.y; if (PointIsInRange(Mouse.Pos, LineBounds.Min, LineBounds.Max))
s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2;
OptionsToDisplay = GSMin(OptionsToDisplay, (OptionsCount - Start));
v2 ButtonMin = v2{Min.x, Max.y - OptionHeight};
v2 ButtonMax = v2{Max.x, Max.y};
string* OptionCursor = Options + Start;
for (s32 i = 0; i < OptionsToDisplay; i++)
{ {
button_result Button = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax, Color = List->LineBGHoverColor;
*OptionCursor,
Config, Mouse);
if (Button.Pressed)
{
Result.IndexSelected = Start + i;
Result.Selection = Selection_Selected;
}
OptionCursor++;
ButtonMin.y -= OptionOffset;
ButtonMax.y -= OptionOffset;
} }
r32 HalfWidthWithMargin = ((Max.x - Min.x) / 2.0f) - Config.Margin.x; PushRenderQuad2D(RenderBuffer, LineBounds.Min, LineBounds.Max, Color);
string DownArrowString = MakeStringLiteral(" v "); return LineBounds;
string UpArrowString = MakeStringLiteral(" ^ ");
button_result Down = EvaluateButton(RenderBuffer, Min, v2{Min.x + HalfWidthWithMargin, Min.y + OptionHeight},
DownArrowString, Config, Mouse);
button_result Up = EvaluateButton(RenderBuffer, v2{Min.x + HalfWidthWithMargin + Config.Margin.x, Min.y},
v2{Max.x, Min.y + OptionHeight},
UpArrowString, Config, Mouse);
if (Down.Pressed)
{
Result.StartIndex += 1;
}
if (Up.Pressed)
{
Result.StartIndex -= 1;
}
Result.StartIndex = GSClamp(0, Result.StartIndex, OptionsCount);
return Result;
} }
internal scroll_list_result internal rect
DrawSelectableOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max, DrawListElement(string Label, interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer, interface_config Interface)
string* Options, s32 OptionsCount,
s32 Start, s32 Selected, interface_config Config, mouse_state Mouse)
{ {
scroll_list_result Result = {}; rect Bounds = DrawListElementBackground(List, Mouse, RenderBuffer);
Result.IndexSelected = Selected;
Result.StartIndex = Start;
Result.Selection = Selection_None;
r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y); v2 LabelPosition = Bounds.Min + List->ElementLabelIndent;
r32 OptionOffset = OptionHeight + Config.Margin.y; DrawString(RenderBuffer, Label, Interface.Font, LabelPosition, List->TextColor);
s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2; List->ListElementsCount++;
OptionsToDisplay = GSMin(OptionsToDisplay, (OptionsCount - Start)); return Bounds;
string* OptionCursor = 0;
OptionCursor = Options + Start;
v2 ButtonMin = v2{Min.x, Max.y - OptionHeight};
v2 ButtonMax = v2{Max.x, Max.y};
for (s32 i = 0; i < OptionsToDisplay; i++)
{
button_result Button = EvaluateSelectableButton(RenderBuffer, ButtonMin, ButtonMax,
*OptionCursor,
Config, Mouse, (Selected == Start + i));
if (Button.Pressed)
{
s32 SelectedIndex = Start + i;
if (SelectedIndex == Result.IndexSelected)
{
Result.Selection = Selection_Deselected;
Result.IndexSelected = -1;
}
else
{
Result.Selection = Selection_Selected;
Result.IndexSelected = Start + i;
}
}
OptionCursor++;
ButtonMin.y -= OptionOffset;
ButtonMax.y -= OptionOffset;
}
r32 HalfWidthWithMargin = ((Max.x - Min.x) / 2.0f) - Config.Margin.x;
string DownArrowString = MakeStringLiteral(" v ");
string UpArrowString = MakeStringLiteral(" ^ ");
button_result Down = EvaluateButton(RenderBuffer, Min, v2{Min.x + HalfWidthWithMargin, Min.y + OptionHeight},
DownArrowString, Config, Mouse);
button_result Up = EvaluateButton(RenderBuffer, v2{Min.x + HalfWidthWithMargin + Config.Margin.x, Min.y},
v2{Max.x, Min.y + OptionHeight},
UpArrowString, Config, Mouse);
if (Down.Pressed)
{
Result.StartIndex += 1;
}
if (Up.Pressed)
{
Result.StartIndex -= 1;
}
Result.StartIndex = GSClamp(0, Result.StartIndex, OptionsCount);
return Result;
} }
internal r32 internal r32
EvaluateColorChannelSlider (render_command_buffer* RenderBuffer, v4 ChannelMask, v2 Min, v2 Max, r32 Current, mouse_state Mouse) EvaluateColorChannelSlider (render_command_buffer* RenderBuffer, v4 ChannelMask, v2 Min, v2 Max, r32 Current, mouse_state Mouse)
{ {

View File

@ -32,6 +32,24 @@ GetXPositionFromTimeInAnimationPanel (r32 Time, rect PanelBounds, s32 StartFrame
return XPositionAtTime; return XPositionAtTime;
} }
internal void
AddAnimationBlock(r32 StartTime, r32 EndTime, animation_proc* Proc, animation_system* AnimationSystem)
{
animation_block NewBlock = {0};
NewBlock.StartTime = StartTime;
NewBlock.EndTime = EndTime;
NewBlock.Proc = Proc;
AddAnimationBlock(NewBlock, AnimationSystem);
}
#define NEW_ANIMATION_BLOCK_DURATION 3
internal void
AddAnimationBlockAtCurrentTime (animation_proc* Proc, animation_system* System)
{
r32 CurrentTime = System->Time;
AddAnimationBlock(CurrentTime, CurrentTime + NEW_ANIMATION_BLOCK_DURATION, Proc, System);
}
internal void internal void
DeleteAnimationBlock(animation_block_handle AnimationBlockHandle, app_state* State) DeleteAnimationBlock(animation_block_handle AnimationBlockHandle, app_state* State)
{ {
@ -109,6 +127,7 @@ StartDragTimeMarker(rect TimelineBounds, s32 PanelStartFrame, s32 PanelEndFrame,
OPERATION_STATE_DEF(drag_animation_clip_state) OPERATION_STATE_DEF(drag_animation_clip_state)
{ {
rect TimelineBounds;
r32 AnimationPanel_StartFrame; r32 AnimationPanel_StartFrame;
r32 AnimationPanel_EndFrame; r32 AnimationPanel_EndFrame;
r32 SelectedClip_InitialStartTime; r32 SelectedClip_InitialStartTime;
@ -119,14 +138,11 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
{ {
drag_animation_clip_state* OpState = (drag_animation_clip_state*)Operation.OpStateMemory; drag_animation_clip_state* OpState = (drag_animation_clip_state*)Operation.OpStateMemory;
panel_and_bounds AnimationPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); s32 ClipInitialStartTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialStartTime, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
Assert(AnimationPanel.Panel); s32 ClipInitialEndTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialEndTime, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
s32 ClipInitialStartTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialStartTime, AnimationPanel.Bounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame); r32 TimeAtMouseDownX = GetTimeFromPointInAnimationPanel(Mouse.DownPos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
s32 ClipInitialEndTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialEndTime, AnimationPanel.Bounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame); r32 TimeAtMouseX = GetTimeFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
r32 TimeAtMouseDownX = GetTimeFromPointInAnimationPanel(Mouse.DownPos, AnimationPanel.Bounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
r32 TimeAtMouseX = GetTimeFromPointInAnimationPanel(Mouse.Pos, AnimationPanel.Bounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
r32 TimeOffset = TimeAtMouseX - TimeAtMouseDownX; r32 TimeOffset = TimeAtMouseX - TimeAtMouseDownX;
animation_block* AnimationBlock = GetAnimationBlockWithHandle(State->SelectedAnimationBlockHandle, &State->AnimationSystem); animation_block* AnimationBlock = GetAnimationBlockWithHandle(State->SelectedAnimationBlockHandle, &State->AnimationSystem);
@ -156,7 +172,7 @@ input_command DragAnimationClipCommands [] = {
}; };
internal void internal void
SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelStartFrame, s32 PanelEndFrame, app_state* State) SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelStartFrame, s32 PanelEndFrame, rect TimelineBounds, app_state* State)
{ {
SelectAnimationBlock(BlockHandle, State); SelectAnimationBlock(BlockHandle, State);
@ -165,6 +181,7 @@ SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelSt
drag_animation_clip_state* OpState = CreateOperationState(DragAnimationClipMode, drag_animation_clip_state* OpState = CreateOperationState(DragAnimationClipMode,
&State->Modes, &State->Modes,
drag_animation_clip_state); drag_animation_clip_state);
OpState->TimelineBounds = TimelineBounds;
OpState->AnimationPanel_StartFrame = PanelStartFrame; OpState->AnimationPanel_StartFrame = PanelStartFrame;
OpState->AnimationPanel_EndFrame = PanelEndFrame ; OpState->AnimationPanel_EndFrame = PanelEndFrame ;
@ -248,11 +265,11 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu
} }
internal rect internal rect
DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPerFrame, s32 FrameCount, s32 StartFrame, v2 TimelineMin, v2 TimelineMax, render_command_buffer* RenderBuffer) DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPerFrame, s32 FrameCount, s32 StartFrame, rect TimelineBounds, render_command_buffer* RenderBuffer)
{ {
rect BlockBounds = {}; rect BlockBounds = {};
r32 TimelineWidth = TimelineMax.x - TimelineMin.x; r32 TimelineWidth = Width(TimelineBounds);
s32 BlockStartFrame = AnimationBlock.StartTime / SecondsPerFrame; s32 BlockStartFrame = AnimationBlock.StartTime / SecondsPerFrame;
r32 StartFramePercent = (r32)(BlockStartFrame - StartFrame) / (r32)FrameCount; r32 StartFramePercent = (r32)(BlockStartFrame - StartFrame) / (r32)FrameCount;
@ -262,8 +279,8 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPe
r32 EndFramePercent = (r32)(BlockEndFrame - StartFrame) / (r32)FrameCount; r32 EndFramePercent = (r32)(BlockEndFrame - StartFrame) / (r32)FrameCount;
r32 EndPosition = TimelineWidth * EndFramePercent; r32 EndPosition = TimelineWidth * EndFramePercent;
BlockBounds.Min = TimelineMin + v2{StartPosition, 25}; BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, 25};
BlockBounds.Max = TimelineMin + v2{EndPosition, 75}; BlockBounds.Max = TimelineBounds.Min + v2{EndPosition, 75};
PushRenderQuad2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, BlockColor); PushRenderQuad2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, BlockColor);
PushRenderBoundingBox2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, 1, WhiteV4); PushRenderBoundingBox2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, 1, WhiteV4);
@ -299,8 +316,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
r32 FrameBarBottom = DrawFrameBar(AnimationSystem, RenderBuffer, StartFrame, EndFrame, PanelBounds, Mouse, State); r32 FrameBarBottom = DrawFrameBar(AnimationSystem, RenderBuffer, StartFrame, EndFrame, PanelBounds, Mouse, State);
// Animation Blocks // Animation Blocks
v2 TimelineMin = PanelBounds.Min; rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} };
v2 TimelineMax = v2{PanelBounds.Max.x, FrameBarBottom};
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState);
for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) for (u32 i = 0; i < AnimationSystem->BlocksCount; i++)
{ {
@ -319,13 +335,13 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
BlockColor = PinkV4; BlockColor = PinkV4;
} }
rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AnimationSystem->SecondsPerFrame, FrameCount, StartFrame, TimelineMin, TimelineMax, RenderBuffer); rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AnimationSystem->SecondsPerFrame, FrameCount, StartFrame, TimelineBounds, RenderBuffer);
if (PointIsInRange(Mouse.Pos, BlockBounds.Min, BlockBounds.Max) if (PointIsInRange(Mouse.Pos, BlockBounds.Min, BlockBounds.Max)
&& MouseButtonTransitionedDown(Mouse.LeftButtonState)) && MouseButtonTransitionedDown(Mouse.LeftButtonState))
{ {
MouseDownAndNotHandled = false; MouseDownAndNotHandled = false;
SelectAndBeginDragAnimationBlock(CurrentBlockHandle, StartFrame, EndFrame, State); SelectAndBeginDragAnimationBlock(CurrentBlockHandle, StartFrame, EndFrame, TimelineBounds, State);
} }
} }
@ -347,24 +363,83 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
PrintF(&TempString, "%d", SliderFrame); PrintF(&TempString, "%d", SliderFrame);
DrawString(RenderBuffer, TempString, State->Interface.Font, HeadMin + v2{4, 4}, WhiteV4); DrawString(RenderBuffer, TempString, State->Interface.Font, HeadMin + v2{4, 4}, WhiteV4);
if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, TimelineMin, TimelineMax)) if (MouseDownAndNotHandled && PointIsInRect(Mouse.Pos, TimelineBounds))
{ {
DeselectCurrentAnimationBlock(State); DeselectCurrentAnimationBlock(State);
} }
return Result; return Result;
} }
struct animation_clip
{
char* Name;
s32 NameLength;
animation_proc* Proc;
};
s32 GlobalAnimationClipsCount = 3;
animation_clip GlobalAnimationClips[] = {
{ "Test Pattern One", 16, TestPatternOne },
{ "Test Pattern Two", 16, TestPatternTwo },
{ "Test Pattern Three", 18, TestPatternThree },
};
internal void
DrawAnimationClipsList(rect PanelBounds, mouse_state Mouse, render_command_buffer* RenderBuffer, app_state* State)
{
v4 LineBGColors[] = {
{ .16f, .16f, .16f, 1.f },
{ .18f, .18f, .18f, 1.f },
};
interface_list List = {};
List.LineBGColors = LineBGColors;
List.LineBGColorsCount = sizeof(LineBGColors) / sizeof(LineBGColors[0]);
List.LineBGHoverColor = v4{ .22f, .22f, .22f, 1.f };
List.TextColor = WhiteV4;
List.ListBounds = PanelBounds;
List.ListElementDimensions = v2{
Width(PanelBounds),
(r32)(State->Interface.Font->PixelHeight + 8),
};
List.ElementLabelIndent = v2{10, 4};
string TitleString = MakeStringLiteral("Animation Clips");
DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface);
for (s32 i = 0; i < GlobalAnimationClipsCount; i++)
{
animation_clip Clip = GlobalAnimationClips[i];
string ClipName = MakeString(Clip.Name, Clip.NameLength);
rect ElementBounds = DrawListElement(ClipName, &List, Mouse, RenderBuffer, State->Interface);
if (MouseButtonTransitionedDown(Mouse.LeftButtonState)
&& PointIsInRect(Mouse.DownPos, ElementBounds))
{
AddAnimationBlockAtCurrentTime(Clip.Proc, &State->AnimationSystem);
}
}
}
PANEL_RENDER_PROC(AnimationTimeline_Render) PANEL_RENDER_PROC(AnimationTimeline_Render)
{ {
animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
r32 OptionsRowHeight = 25; r32 OptionsRowHeight = 25;
rect TimelineBounds = rect{ rect AnimationClipListBounds = rect{
PanelBounds.Min, PanelBounds.Min,
v2{PanelBounds.Max.x, PanelBounds.Max.y - OptionsRowHeight} v2{PanelBounds.Min.x + 300, PanelBounds.Max.y - OptionsRowHeight},
};
rect TimelineBounds = rect{
v2{AnimationClipListBounds.Max.x, PanelBounds.Min.y},
v2{PanelBounds.Max.x, PanelBounds.Max.y - OptionsRowHeight},
}; };
if (Height(TimelineBounds) > 0) if (Height(TimelineBounds) > 0)
{ {
DrawAnimationClipsList(AnimationClipListBounds, Mouse, RenderBuffer, State);
s32 FrameStart = (s32)(State->AnimationSystem.AnimationStart / State->AnimationSystem.SecondsPerFrame); s32 FrameStart = (s32)(State->AnimationSystem.AnimationStart / State->AnimationSystem.SecondsPerFrame);
s32 FrameEnd = (s32)(State->AnimationSystem.AnimationEnd / State->AnimationSystem.SecondsPerFrame); s32 FrameEnd = (s32)(State->AnimationSystem.AnimationEnd / State->AnimationSystem.SecondsPerFrame);
SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem, SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem,

View File

@ -13,43 +13,44 @@ PANEL_RENDER_PROC(HierarchyView_Render)
r32 PanelWidth = PanelBounds.Max.x - PanelBounds.Min.x; r32 PanelWidth = PanelBounds.Max.x - PanelBounds.Min.x;
r32 PanelHeight = PanelBounds.Max.y - PanelBounds.Min.y; r32 PanelHeight = PanelBounds.Max.y - PanelBounds.Min.y;
s32 LineBGColorsCount = 2;
v4 LineBGColors[] = { v4 LineBGColors[] = {
{ .16f, .16f, .16f, 1.f }, { .16f, .16f, .16f, 1.f },
{ .18f, .18f, .18f, 1.f }, { .18f, .18f, .18f, 1.f },
}; };
v4 LineBGHoverColor = { .22f, .22f, .22f, 1.f };
r32 LineHeight = State->Interface.Font->PixelHeight + 8; interface_list List = {};
v2 LineMin = v2{PanelBounds.Min.x, PanelBounds.Max.y - LineHeight}; List.LineBGColors = LineBGColors;
v2 LineMax = LineMin + v2{PanelWidth, LineHeight}; List.LineBGColorsCount = sizeof(LineBGColors) / sizeof(LineBGColors[0]);
List.LineBGHoverColor = v4{ .22f, .22f, .22f, 1.f };
List.ListBounds = PanelBounds;
List.ListElementDimensions = v2{
Width(PanelBounds),
(r32)(State->Interface.Font->PixelHeight + 8),
};
v2 TextOffset = v2{10, 4}; v2 TextOffset = v2{10, 4};
string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); string TempString = MakeString(PushArray(&State->Transient, char, 256), 256);
s32 LineCount = (s32)(PanelHeight / LineHeight) + 1; s32 LineCount = (s32)(PanelHeight / List.ListElementDimensions.y) + 1;
for (s32 i = 0; i < LineCount; i++) for (s32 i = 0; i < LineCount; i++)
{ {
v4 Color = LineBGColors[i % LineBGColorsCount]; rect ElementBounds = DrawListElementBackground(&List, Mouse, RenderBuffer);
if (PointIsInRange(Mouse.Pos, LineMin, LineMax))
{
Color = LineBGHoverColor;
}
PushRenderQuad2D(RenderBuffer, LineMin, LineMax, Color);
if (i < State->ActiveAssemblyIndecies.Used) if (i < State->ActiveAssemblyIndecies.Used)
{ {
array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList);
PrintF(&TempString, "%S", Assembly.Name); PrintF(&TempString, "%S", Assembly.Name);
DrawString(RenderBuffer, TempString, State->Interface.Font, LineMin + TextOffset, WhiteV4); DrawString(RenderBuffer, TempString, State->Interface.Font, ElementBounds.Min + TextOffset, WhiteV4);
PrintF(&TempString, "X"); PrintF(&TempString, "X");
v2 XLowerRight = v2{LineMax.x - 25, LineMin.y + TextOffset.y}; v2 XLowerRight = v2{ElementBounds.Max.x - 25, ElementBounds.Min.y + TextOffset.y};
v2 XLowerLeft = DrawString(RenderBuffer, TempString, State->Interface.Font, XLowerRight, WhiteV4, Align_Right); v2 XLowerLeft = DrawString(RenderBuffer, TempString, State->Interface.Font, XLowerRight, WhiteV4, Align_Right);
if (MouseButtonTransitionedUp(Mouse.LeftButtonState) if (MouseButtonTransitionedUp(Mouse.LeftButtonState)
&& PointIsInRange(Mouse.Pos, XLowerLeft, LineMax)) && PointIsInRange(Mouse.Pos, XLowerLeft, ElementBounds.Max))
{ {
UnloadAssembly(AssemblyHandle.Index, State, Context); UnloadAssembly(AssemblyHandle.Index, State, Context);
} }
@ -57,11 +58,11 @@ PANEL_RENDER_PROC(HierarchyView_Render)
else if (i == State->ActiveAssemblyIndecies.Used) else if (i == State->ActiveAssemblyIndecies.Used)
{ {
PrintF(&TempString, "+ Add Assembly"); PrintF(&TempString, "+ Add Assembly");
v2 TextMinX = LineMin + TextOffset; v2 TextMinX = ElementBounds.Min + TextOffset;
DrawString(RenderBuffer, TempString, State->Interface.Font, TextMinX, WhiteV4); DrawString(RenderBuffer, TempString, State->Interface.Font, TextMinX, WhiteV4);
if (MouseButtonTransitionedUp(Mouse.LeftButtonState) if (MouseButtonTransitionedUp(Mouse.LeftButtonState)
&& PointIsInRange(Mouse.Pos, LineMin, LineMax)) && PointIsInRange(Mouse.Pos, ElementBounds.Min, ElementBounds.Max))
{ {
char FilePath[256]; char FilePath[256];
b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0"); b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0");
@ -72,7 +73,6 @@ PANEL_RENDER_PROC(HierarchyView_Render)
} }
} }
LineMin.y = GSMax(PanelBounds.Min.y, LineMin.y - LineHeight); List.ListElementsCount++;
LineMax.y = GSMax(PanelBounds.Min.y, LineMax.y - LineHeight);
} }
} }