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);
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
animation_block BlockOne = {0};
BlockOne.StartTime = 0;
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);
AddAnimationBlock(0, 8, TestPatternTwo, &State->AnimationSystem);
AddAnimationBlock(8, 15, TestPatternThree, &State->AnimationSystem);
State->AnimationSystem.AnimationStart = 0;
State->AnimationSystem.AnimationEnd = 15;

View File

@ -434,139 +434,53 @@ enum selection_state
Selection_Deselected,
};
struct scroll_list_result
struct interface_list
{
s32 IndexSelected;
s32 StartIndex;
selection_state Selection;
rect ListBounds;
v2 ListElementDimensions;
v2 ElementLabelIndent;
v4 TextColor;
v4* LineBGColors;
s32 LineBGColorsCount;
v4 LineBGHoverColor;
s32 ListElementsCount;
};
internal scroll_list_result
DrawOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max,
string* Options, s32 OptionsCount,
s32 Start, interface_config Config, mouse_state Mouse)
internal rect
DrawListElementBackground(interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer)
{
scroll_list_result Result = {};
Result.IndexSelected = -1;
Result.StartIndex = Start;
Result.Selection = Selection_None;
rect LineBounds = {};
LineBounds.Min = v2{
List->ListBounds.Min.x,
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);
r32 OptionOffset = OptionHeight + Config.Margin.y;
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++)
v4 Color = List->LineBGColors[List->ListElementsCount % List->LineBGColorsCount];
if (PointIsInRange(Mouse.Pos, LineBounds.Min, LineBounds.Max))
{
button_result Button = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
*OptionCursor,
Config, Mouse);
if (Button.Pressed)
{
Result.IndexSelected = Start + i;
Result.Selection = Selection_Selected;
}
OptionCursor++;
ButtonMin.y -= OptionOffset;
ButtonMax.y -= OptionOffset;
Color = List->LineBGHoverColor;
}
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)
PushRenderQuad2D(RenderBuffer, LineBounds.Min, LineBounds.Max, Color);
return LineBounds;
}
internal rect
DrawListElement(string Label, interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer, interface_config Interface)
{
Result.StartIndex += 1;
}
if (Up.Pressed)
{
Result.StartIndex -= 1;
rect Bounds = DrawListElementBackground(List, Mouse, RenderBuffer);
v2 LabelPosition = Bounds.Min + List->ElementLabelIndent;
DrawString(RenderBuffer, Label, Interface.Font, LabelPosition, List->TextColor);
List->ListElementsCount++;
return Bounds;
}
Result.StartIndex = GSClamp(0, Result.StartIndex, OptionsCount);
return Result;
}
internal scroll_list_result
DrawSelectableOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max,
string* Options, s32 OptionsCount,
s32 Start, s32 Selected, interface_config Config, mouse_state Mouse)
{
scroll_list_result Result = {};
Result.IndexSelected = Selected;
Result.StartIndex = Start;
Result.Selection = Selection_None;
r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y);
r32 OptionOffset = OptionHeight + Config.Margin.y;
s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2;
OptionsToDisplay = GSMin(OptionsToDisplay, (OptionsCount - Start));
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
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;
}
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
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)
{
rect TimelineBounds;
r32 AnimationPanel_StartFrame;
r32 AnimationPanel_EndFrame;
r32 SelectedClip_InitialStartTime;
@ -119,14 +138,11 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
{
drag_animation_clip_state* OpState = (drag_animation_clip_state*)Operation.OpStateMemory;
panel_and_bounds AnimationPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds);
Assert(AnimationPanel.Panel);
s32 ClipInitialStartTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialStartTime, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
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);
s32 ClipInitialEndTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialEndTime, AnimationPanel.Bounds, 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 TimeAtMouseDownX = GetTimeFromPointInAnimationPanel(Mouse.DownPos, OpState->TimelineBounds, 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 TimeOffset = TimeAtMouseX - TimeAtMouseDownX;
animation_block* AnimationBlock = GetAnimationBlockWithHandle(State->SelectedAnimationBlockHandle, &State->AnimationSystem);
@ -156,7 +172,7 @@ input_command DragAnimationClipCommands [] = {
};
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);
@ -165,6 +181,7 @@ SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelSt
drag_animation_clip_state* OpState = CreateOperationState(DragAnimationClipMode,
&State->Modes,
drag_animation_clip_state);
OpState->TimelineBounds = TimelineBounds;
OpState->AnimationPanel_StartFrame = PanelStartFrame;
OpState->AnimationPanel_EndFrame = PanelEndFrame ;
@ -248,11 +265,11 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu
}
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 = {};
r32 TimelineWidth = TimelineMax.x - TimelineMin.x;
r32 TimelineWidth = Width(TimelineBounds);
s32 BlockStartFrame = AnimationBlock.StartTime / SecondsPerFrame;
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 EndPosition = TimelineWidth * EndFramePercent;
BlockBounds.Min = TimelineMin + v2{StartPosition, 25};
BlockBounds.Max = TimelineMin + v2{EndPosition, 75};
BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, 25};
BlockBounds.Max = TimelineBounds.Min + v2{EndPosition, 75};
PushRenderQuad2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, BlockColor);
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);
// Animation Blocks
v2 TimelineMin = PanelBounds.Min;
v2 TimelineMax = v2{PanelBounds.Max.x, FrameBarBottom};
rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} };
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState);
for (u32 i = 0; i < AnimationSystem->BlocksCount; i++)
{
@ -319,13 +335,13 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
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)
&& MouseButtonTransitionedDown(Mouse.LeftButtonState))
{
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);
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);
}
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)
{
animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
r32 OptionsRowHeight = 25;
rect TimelineBounds = rect{
rect AnimationClipListBounds = rect{
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)
{
DrawAnimationClipsList(AnimationClipListBounds, Mouse, RenderBuffer, State);
s32 FrameStart = (s32)(State->AnimationSystem.AnimationStart / State->AnimationSystem.SecondsPerFrame);
s32 FrameEnd = (s32)(State->AnimationSystem.AnimationEnd / State->AnimationSystem.SecondsPerFrame);
SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem,

View File

@ -13,43 +13,44 @@ PANEL_RENDER_PROC(HierarchyView_Render)
r32 PanelWidth = PanelBounds.Max.x - PanelBounds.Min.x;
r32 PanelHeight = PanelBounds.Max.y - PanelBounds.Min.y;
s32 LineBGColorsCount = 2;
v4 LineBGColors[] = {
{ .16f, .16f, .16f, 1.f },
{ .18f, .18f, .18f, 1.f },
};
v4 LineBGHoverColor = { .22f, .22f, .22f, 1.f };
r32 LineHeight = State->Interface.Font->PixelHeight + 8;
v2 LineMin = v2{PanelBounds.Min.x, PanelBounds.Max.y - LineHeight};
v2 LineMax = LineMin + v2{PanelWidth, LineHeight};
interface_list List = {};
List.LineBGColors = LineBGColors;
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};
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++)
{
v4 Color = LineBGColors[i % LineBGColorsCount];
if (PointIsInRange(Mouse.Pos, LineMin, LineMax))
{
Color = LineBGHoverColor;
}
PushRenderQuad2D(RenderBuffer, LineMin, LineMax, Color);
rect ElementBounds = DrawListElementBackground(&List, Mouse, RenderBuffer);
if (i < State->ActiveAssemblyIndecies.Used)
{
array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList);
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");
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);
if (MouseButtonTransitionedUp(Mouse.LeftButtonState)
&& PointIsInRange(Mouse.Pos, XLowerLeft, LineMax))
&& PointIsInRange(Mouse.Pos, XLowerLeft, ElementBounds.Max))
{
UnloadAssembly(AssemblyHandle.Index, State, Context);
}
@ -57,11 +58,11 @@ PANEL_RENDER_PROC(HierarchyView_Render)
else if (i == State->ActiveAssemblyIndecies.Used)
{
PrintF(&TempString, "+ Add Assembly");
v2 TextMinX = LineMin + TextOffset;
v2 TextMinX = ElementBounds.Min + TextOffset;
DrawString(RenderBuffer, TempString, State->Interface.Font, TextMinX, WhiteV4);
if (MouseButtonTransitionedUp(Mouse.LeftButtonState)
&& PointIsInRange(Mouse.Pos, LineMin, LineMax))
&& PointIsInRange(Mouse.Pos, ElementBounds.Min, ElementBounds.Max))
{
char FilePath[256];
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);
LineMax.y = GSMax(PanelBounds.Min.y, LineMax.y - LineHeight);
List.ListElementsCount++;
}
}