Added rudimentary layers to the animation system.

This commit is contained in:
Peter Slattery 2020-03-07 16:06:10 -08:00
parent 3a20883a49
commit de1a9474f0
7 changed files with 176 additions and 173 deletions

View File

@ -298,7 +298,7 @@ int main(int ArgCount, char* Args[])
string_builder PanelCodeGen = {0}; string_builder PanelCodeGen = {0};
GeneratePanelMetaInfo(Meta, &PanelCodeGen); GeneratePanelMetaInfo(Meta, &PanelCodeGen);
string TypeInfoHFilePath = AllocAndConcatStrings(GeneratedFilesDirectory, MakeStringLiteral("gs_meta_genreated_typeinfo.h")); string TypeInfoHFilePath = AllocAndConcatStrings(GeneratedFilesDirectory, MakeStringLiteral("gs_meta_generated_typeinfo.h"));
FILE* TypeInfoH = fopen(TypeInfoHFilePath.Memory, "w"); FILE* TypeInfoH = fopen(TypeInfoHFilePath.Memory, "w");
if (TypeInfoH) if (TypeInfoH)
{ {
@ -315,7 +315,7 @@ int main(int ArgCount, char* Args[])
} }
string NodeInfoHFilePath = AllocAndConcatStrings(GeneratedFilesDirectory, MakeStringLiteral("foldhaus_nodes_generated.h")); string NodeInfoHFilePath = AllocAndConcatStrings(GeneratedFilesDirectory, MakeStringLiteral("foldhaus_nodes_generated.h"));
FILE* NodeInfoH = fopen(TypeInfoHFilePath.Memory, "w"); FILE* NodeInfoH = fopen(NodeInfoHFilePath.Memory, "w");
if (NodeInfoH) if (NodeInfoH)
{ {
WriteStringBuilderToFile(*NodeTypeGen.Builder, NodeInfoH); WriteStringBuilderToFile(*NodeTypeGen.Builder, NodeInfoH);

View File

@ -10,8 +10,8 @@ typedef ANIMATION_PROC(animation_proc);
struct frame_range struct frame_range
{ {
u32 Min; s32 Min;
u32 Max; s32 Max;
}; };
struct animation_block struct animation_block
@ -21,19 +21,28 @@ struct animation_block
u32 Layer; u32 Layer;
}; };
struct anim_layer
{
string Name;
};
#define ANIMATION_SYSTEM_LAYERS_MAX 128 #define ANIMATION_SYSTEM_LAYERS_MAX 128
#define ANIMATION_SYSTEM_BLOCKS_MAX 128 #define ANIMATION_SYSTEM_BLOCKS_MAX 128
struct animation_system struct animation_system
{ {
memory_arena Storage;
gs_list<animation_block> Blocks; gs_list<animation_block> Blocks;
anim_layer* Layers;
u32 LayersCount;
u32 LayersMax;
// NOTE(Peter): The frame currently being displayed/processed. you // NOTE(Peter): The frame currently being displayed/processed. you
// can see which frame you're on by looking at the time slider on the timeline // can see which frame you're on by looking at the time slider on the timeline
// panel // panel
u32 CurrentFrame; s32 CurrentFrame;
u32 LastUpdatedFrame; s32 LastUpdatedFrame;
r32 SecondsPerFrame; r32 SecondsPerFrame;
b32 TimelineShouldAdvance; b32 TimelineShouldAdvance;
// Timeline // Timeline
@ -48,7 +57,7 @@ SecondsToFrames(r32 Seconds, animation_system System)
} }
inline b32 inline b32
FrameIsInRange(u32 Frame, frame_range Range) FrameIsInRange(s32 Frame, frame_range Range)
{ {
b32 Result = (Frame >= Range.Min) && (Frame <= Range.Max); b32 Result = (Frame >= Range.Min) && (Frame <= Range.Max);
return Result; return Result;
@ -57,7 +66,7 @@ FrameIsInRange(u32 Frame, frame_range Range)
internal u32 internal u32
GetFrameCount(frame_range Range) GetFrameCount(frame_range Range)
{ {
u32 Result = Range.Max - Range.Min; u32 Result = (u32)GSMax(0, Range.Max - Range.Min);
return Result; return Result;
} }
@ -69,17 +78,17 @@ FrameToPercentRange(s32 Frame, frame_range Range)
return Result; return Result;
} }
internal u32 internal s32
PercentToFrameInRange(r32 Percent, frame_range Range) PercentToFrameInRange(r32 Percent, frame_range Range)
{ {
u32 Result = Range.Min + (u32)(Percent * GetFrameCount(Range)); s32 Result = Range.Min + (s32)(Percent * GetFrameCount(Range));
return Result; return Result;
} }
internal u32 internal s32
ClampFrameToRange(u32 Frame, frame_range Range) ClampFrameToRange(s32 Frame, frame_range Range)
{ {
u32 Result = Frame; s32 Result = Frame;
if (Result < Range.Min) if (Result < Range.Min)
{ {
Result = Range.Min; Result = Range.Min;
@ -91,5 +100,69 @@ ClampFrameToRange(u32 Frame, frame_range Range)
return Result; return Result;
} }
// Blocks
internal gs_list_handle
AddAnimationBlock(u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 Layer, animation_system* AnimationSystem)
{
gs_list_handle Result = {0};
animation_block NewBlock = {0};
NewBlock.Range.Min = StartFrame;
NewBlock.Range.Max = EndFrame;
NewBlock.AnimationProcHandle = AnimationProcHandle;
NewBlock.Layer = Layer;
Result = AnimationSystem->Blocks.PushElementOnList(NewBlock);
return Result;
}
internal void
RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* AnimationSystem)
{
Assert(ListHandleIsValid(AnimationBlockHandle));
AnimationSystem->Blocks.FreeElementWithHandle(AnimationBlockHandle);
}
// Layers
internal u32
AddLayer (string Name, animation_system* AnimationSystem)
{
// TODO(Peter): If this assert fires its time to make the layer buffer system
// resizable.
Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax);
u32 Result = 0;
Result = AnimationSystem->LayersCount++;
anim_layer* NewLayer = AnimationSystem->Layers + Result;
*NewLayer = {0};
NewLayer->Name = MakeString(PushArray(&AnimationSystem->Storage, char, Name.Length), Name.Length);
CopyStringTo(Name, &NewLayer->Name);
return Result;
}
internal void
RemoveLayer (u32 LayerIndex, animation_system* AnimationSystem)
{
Assert(LayerIndex < AnimationSystem->LayersMax);
Assert(LayerIndex < AnimationSystem->LayersCount);
for (u32 i = LayerIndex; i < AnimationSystem->LayersCount - 1; i++)
{
AnimationSystem->Layers[i] = AnimationSystem->Layers[i + 1];
}
for (u32 i = AnimationSystem->Blocks.Used -= 1; i >= 0; i--)
{
gs_list_entry<animation_block>* Entry = AnimationSystem->Blocks.GetEntryAtIndex(i);
if (EntryIsFree(Entry)) { continue; }
animation_block* Block = &Entry->Value;
if (Block->Layer > LayerIndex)
{
Block->Layer -= 1;
}
else if (Block->Layer == LayerIndex)
{
AnimationSystem->Blocks.FreeElementAtIndex(i);
}
}
AnimationSystem->LayersCount -= 1;
}
#define FOLDHAUS_ANIMATION #define FOLDHAUS_ANIMATION
#endif // FOLDHAUS_ANIMATION #endif // FOLDHAUS_ANIMATION

View File

@ -190,6 +190,11 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
State->AnimationSystem.PlayableRange.Min = 0; State->AnimationSystem.PlayableRange.Min = 0;
State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
State->AnimationSystem.LayersMax = 32;
State->AnimationSystem.Layers = PushArray(&State->Permanent, anim_layer, State->AnimationSystem.LayersMax);
AddLayer(MakeStringLiteral("Base Layer"), &State->AnimationSystem);
AddLayer(MakeStringLiteral("Color Layer"), &State->AnimationSystem);
AddLayer(MakeStringLiteral("Sparkles"), &State->AnimationSystem);
} // End Animation Playground } // End Animation Playground
@ -330,7 +335,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
} }
} }
u32 CurrentFrame = State->AnimationSystem.CurrentFrame; s32 CurrentFrame = State->AnimationSystem.CurrentFrame;
if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame) if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame)
{ {
State->AnimationSystem.LastUpdatedFrame = CurrentFrame; State->AnimationSystem.LastUpdatedFrame = CurrentFrame;
@ -339,11 +344,10 @@ UPDATE_AND_RENDER(UpdateAndRender)
for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++)
{ {
gs_list_entry<animation_block>* BlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); gs_list_entry<animation_block>* BlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i);
if (!EntryIsFree(BlockEntry)) if (EntryIsFree(BlockEntry)) { continue; }
{
animation_block Block = BlockEntry->Value; animation_block Block = BlockEntry->Value;
if (CurrentFrame >= Block.Range.Min && CurrentFrame <= Block.Range.Max) if (CurrentFrame < Block.Range.Min || CurrentFrame > Block.Range.Max) { continue; }
{
for (u32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++) for (u32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++)
{ {
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j); gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j);
@ -375,8 +379,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
} }
} }
} }
}
}
s32 HeaderSize = State->NetworkProtocolHeaderSize; s32 HeaderSize = State->NetworkProtocolHeaderSize;
dmx_buffer_list* DMXBuffers = 0; dmx_buffer_list* DMXBuffers = 0;

View File

@ -82,6 +82,7 @@ struct app_state
animation_system AnimationSystem; animation_system AnimationSystem;
gs_list_handle SelectedAnimationBlockHandle; gs_list_handle SelectedAnimationBlockHandle;
u32 SelectedAnimationLayer;
panel_system PanelSystem; panel_system PanelSystem;
panel* HotPanel; panel* HotPanel;

View File

@ -1,16 +0,0 @@
enum node_type
{
NodeType_Count,
};
node_specification NodeSpecifications[] = {
};
s32 NodeSpecificationsCount = 0;
internal void CallNodeProc(u32 SpecificationIndex, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)
{
node_specification Spec = NodeSpecifications[SpecificationIndex];
switch (Spec.Type)
{
}
}

View File

@ -1,32 +0,0 @@
enum node_type
{
NodeType_RevolvingDiscs,
NodeType_SolidColorProc,
NodeType_VerticalColorFadeProc,
NodeType_Count,
};
static node_specification_ NodeSpecifications[] = {
{ NodeType_RevolvingDiscs, {"RevolvingDiscs", 14}, gsm_StructType_revolving_discs_data },
{ NodeType_SolidColorProc, {"SolidColorProc", 14}, gsm_StructType_solid_color_data },
{ NodeType_VerticalColorFadeProc, {"VerticalColorFadeProc", 21}, gsm_StructType_vertical_color_fade_data },
};
void CallNodeProc(node_type Type, u8* NodeData)
{
switch(Type) {
case NodeType_RevolvingDiscs:
{
RevolvingDiscs((revolving_discs_data*)NodeData);
} break;
case NodeType_SolidColorProc:
{
SolidColorProc((solid_color_data*)NodeData);
} break;
case NodeType_VerticalColorFadeProc:
{
VerticalColorFadeProc((vertical_color_fade_data*)NodeData);
} break;
}
}

View File

@ -32,33 +32,14 @@ GetXPositionFromFrameInAnimationPanel (u32 Frame, rect PanelBounds, frame_range
} }
internal gs_list_handle internal gs_list_handle
AddAnimationBlock(u32 StartFrame, u32 EndFrame, u32 AnimationProcHandle, animation_system* AnimationSystem) AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 Layer, animation_system* System)
{
gs_list_handle Result = {0};
animation_block NewBlock = {0};
NewBlock.Range.Min = StartFrame;
NewBlock.Range.Max = EndFrame;
NewBlock.AnimationProcHandle = AnimationProcHandle;
Result = AnimationSystem->Blocks.PushElementOnList(NewBlock);
return Result;
}
internal gs_list_handle
AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, animation_system* System)
{ {
u32 NewBlockStart = System->CurrentFrame; u32 NewBlockStart = System->CurrentFrame;
u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System); u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System);
gs_list_handle Result = AddAnimationBlock(NewBlockStart, NewBlockEnd, AnimationProcHandle, System); gs_list_handle Result = AddAnimationBlock(NewBlockStart, NewBlockEnd, AnimationProcHandle, Layer, System);
return Result; return Result;
} }
internal void
DeleteAnimationBlock(gs_list_handle AnimationBlockHandle, app_state* State)
{
State->AnimationSystem.Blocks.FreeElementWithHandle(AnimationBlockHandle);
State->SelectedAnimationBlockHandle = {0};
}
internal void internal void
SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State) SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State)
{ {
@ -75,7 +56,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand)
{ {
if(ListHandleIsValid(State->SelectedAnimationBlockHandle)) if(ListHandleIsValid(State->SelectedAnimationBlockHandle))
{ {
DeleteAnimationBlock(State->SelectedAnimationBlockHandle, State); RemoveAnimationBlock(State->SelectedAnimationBlockHandle, &State->AnimationSystem);
State->SelectedAnimationBlockHandle = {0};
} }
} }
@ -93,7 +75,7 @@ OPERATION_STATE_DEF(drag_time_marker_operation_state)
OPERATION_RENDER_PROC(UpdateDragTimeMarker) OPERATION_RENDER_PROC(UpdateDragTimeMarker)
{ {
drag_time_marker_operation_state* OpState = (drag_time_marker_operation_state*)Operation.OpStateMemory; drag_time_marker_operation_state* OpState = (drag_time_marker_operation_state*)Operation.OpStateMemory;
frame_range Range = { (u32)OpState->StartFrame, (u32)OpState->EndFrame }; frame_range Range = { OpState->StartFrame, OpState->EndFrame };
u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, Range); u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, Range);
State->AnimationSystem.CurrentFrame = FrameAtMouseX; State->AnimationSystem.CurrentFrame = FrameAtMouseX;
} }
@ -174,13 +156,13 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
if (GSAbs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) if (GSAbs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE)
{ {
u32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; s32 NewStartFrame = OpState->ClipRange.Min + FrameOffset;
if (FrameOffset < 0) if (FrameOffset < 0)
{ {
for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++)
{ {
gs_list_entry<animation_block>* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); gs_list_entry<animation_block>* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i);
if (OtherBlockEntry->Free.NextFreeEntry != 0) { continue; } if (EntryIsFree(OtherBlockEntry)) { continue; }
animation_block OtherBlock = OtherBlockEntry->Value; animation_block OtherBlock = OtherBlockEntry->Value;
NewStartFrame = AttemptToSnapPosition(NewStartFrame, OtherBlock.Range.Max); NewStartFrame = AttemptToSnapPosition(NewStartFrame, OtherBlock.Range.Max);
} }
@ -202,7 +184,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++)
{ {
gs_list_entry<animation_block>* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); gs_list_entry<animation_block>* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i);
if (OtherBlockEntry->Free.NextFreeEntry != 0) { continue; } if (EntryIsFree(OtherBlockEntry)) { continue; }
animation_block OtherBlock = OtherBlockEntry->Value; animation_block OtherBlock = OtherBlockEntry->Value;
NewEndFrame = AttemptToSnapPosition(NewEndFrame, OtherBlock.Range.Min); NewEndFrame = AttemptToSnapPosition(NewEndFrame, OtherBlock.Range.Min);
} }
@ -223,7 +205,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++)
{ {
gs_list_entry<animation_block>* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); gs_list_entry<animation_block>* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i);
if (OtherBlockEntry->Free.NextFreeEntry != 0) { continue; } if (EntryIsFree(OtherBlockEntry)) { continue; }
animation_block OtherBlock = OtherBlockEntry->Value; animation_block OtherBlock = OtherBlockEntry->Value;
u32 SnapFramesAmount = 0; u32 SnapFramesAmount = 0;
@ -277,7 +259,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand)
panel_and_bounds ActivePanel = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, State->WindowBounds); panel_and_bounds ActivePanel = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, State->WindowBounds);
frame_range Range = State->AnimationSystem.PlayableRange; frame_range Range = State->AnimationSystem.PlayableRange;
u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range); u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range);
gs_list_handle NewBlockHandle = AddAnimationBlock(MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, &State->AnimationSystem); gs_list_handle NewBlockHandle = AddAnimationBlock(MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer, &State->AnimationSystem);
SelectAnimationBlock(NewBlockHandle, State); SelectAnimationBlock(NewBlockHandle, State);
} }
@ -370,12 +352,10 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat
v2 SliderBarDim = v2{25, BarHeight}; v2 SliderBarDim = v2{25, BarHeight};
// Convert Frames To Pixels // Convert Frames To Pixels
// TODO(Peter): When the animation system is storing a frame range rather than individual values r32 VisibleMinPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Min, AnimationSystem->PlayableRange);
// come back and use the utility functions here r32 VisibleMaxPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Max, AnimationSystem->PlayableRange);
r32 RangeMinPercentPlayable = FrameToPercentRange(AnimationSystem->PlayableRange.Min, TimelineState->VisibleRange); v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * Width(BarBounds)), BarBounds.Min.y};
r32 RangeMaxPercentPlayable = FrameToPercentRange(AnimationSystem->PlayableRange.Max, TimelineState->VisibleRange); v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * Width(BarBounds)) - 25, BarBounds.Min.y};
v2 RangeMinSliderMin = v2{BarBounds.Min.x + (RangeMinPercentPlayable * Width(BarBounds)), BarBounds.Min.y};
v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (RangeMaxPercentPlayable * Width(BarBounds)) - 25, BarBounds.Min.y};
if (MouseButtonHeldDown(Mouse.LeftButtonState) || if (MouseButtonHeldDown(Mouse.LeftButtonState) ||
MouseButtonTransitionedUp(Mouse.LeftButtonState)) MouseButtonTransitionedUp(Mouse.LeftButtonState))
@ -399,11 +379,11 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat
PushRenderQuad2D(RenderBuffer, RangeMaxSliderMin, RangeMaxSliderMax, v4{.8f, .8f, .8f, 1.f}); PushRenderQuad2D(RenderBuffer, RangeMaxSliderMin, RangeMaxSliderMax, v4{.8f, .8f, .8f, 1.f});
// Convert Pixels Back To Frames and store // Convert Pixels Back To Frames and store
RangeMinPercentPlayable = (RangeMinSliderMin.x - BarBounds.Min.x) / BarWidth; VisibleMinPercentPlayable = (RangeMinSliderMin.x - BarBounds.Min.x) / BarWidth;
RangeMaxPercentPlayable = (RangeMaxSliderMax.x - BarBounds.Min.x) / BarWidth; VisibleMaxPercentPlayable = (RangeMaxSliderMax.x - BarBounds.Min.x) / BarWidth;
u32 VisibleFrameCount = GetFrameCount(AnimationSystem->PlayableRange); u32 VisibleFrameCount = GetFrameCount(AnimationSystem->PlayableRange);
Result.Min = RangeMinPercentPlayable * VisibleFrameCount; Result.Min = VisibleMinPercentPlayable * VisibleFrameCount;
Result.Max = RangeMaxPercentPlayable * VisibleFrameCount; Result.Max = VisibleMaxPercentPlayable * VisibleFrameCount;
if (MouseButtonTransitionedUp(Mouse.LeftButtonState)) if (MouseButtonTransitionedUp(Mouse.LeftButtonState))
{ {
@ -413,6 +393,35 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat
return Result; return Result;
} }
#define LAYER_HEIGHT 52
internal void
DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse)
{
v2 LayerDim = { Width(PanelDim), LAYER_HEIGHT };
v2 LayerListMin = PanelDim.Min + v2{0, 24};
for (u32 LayerIndex = 0; LayerIndex < AnimationSystem->LayersCount; LayerIndex++)
{
anim_layer* Layer = AnimationSystem->Layers + LayerIndex;
rect LayerBounds = {0};
LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * LayerIndex) };
LayerBounds.Max = LayerBounds.Min + LayerDim;
if (MouseButtonTransitionedDown(Mouse.LeftButtonState) &&
PointIsInRect(Mouse.Pos, LayerBounds))
{
State->SelectedAnimationLayer = LayerIndex;
}
v2 LayerTextPos = { LayerBounds.Min.x + 6, LayerBounds.Max.y - 16};
if (State->SelectedAnimationLayer == LayerIndex)
{
PushRenderBoundingBox2D(RenderBuffer, RectExpand(LayerBounds), 1, WhiteV4);
}
DrawString(RenderBuffer, Layer->Name, State->Interface.Font, LayerTextPos, WhiteV4);
}
}
internal rect internal rect
DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect TimelineBounds, render_command_buffer* RenderBuffer) DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect TimelineBounds, render_command_buffer* RenderBuffer)
{ {
@ -428,8 +437,9 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V
r32 EndFramePercent = FrameToPercentRange(ClampedBlockEndFrame, VisibleFrames); r32 EndFramePercent = FrameToPercentRange(ClampedBlockEndFrame, VisibleFrames);
r32 EndPosition = TimelineWidth * EndFramePercent; r32 EndPosition = TimelineWidth * EndFramePercent;
BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, 25}; r32 LayerYOffset = LAYER_HEIGHT * AnimationBlock.Layer;
BlockBounds.Max = TimelineBounds.Min + v2{EndPosition, 75}; BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, LayerYOffset};
BlockBounds.Max = TimelineBounds.Min + v2{EndPosition, LayerYOffset + LAYER_HEIGHT};
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);
@ -437,27 +447,6 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V
return BlockBounds; return BlockBounds;
} }
internal void
DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse)
{
string TempString = MakeString(PushArray(&State->Transient, char, 256), 256);
v2 LayerDim = { Width(PanelDim), 32 };
v2 LayerListMin = PanelDim.Min + v2{0, 32};
for (int i = 0; i < 3; i++)
{
PrintF(&TempString, "Layer %d", i);
rect LayerBounds = {0};
LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * i) };
LayerBounds.Max = LayerBounds.Min + LayerDim;
v2 LayerTextPos = LayerBounds.Min + v2{6, 4};
PushRenderBoundingBox2D(RenderBuffer, RectExpand(LayerBounds), 1, WhiteV4);
DrawString(RenderBuffer, TempString, State->Interface.Font, LayerTextPos, WhiteV4);
}
}
internal gs_list_handle internal gs_list_handle
DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect PanelBounds, gs_list_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect PanelBounds, gs_list_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse)
{ {
@ -499,7 +488,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta
for (u32 i = 0; i < AnimationSystem->Blocks.Used; i++) for (u32 i = 0; i < AnimationSystem->Blocks.Used; i++)
{ {
gs_list_entry<animation_block>* AnimationBlockEntry = AnimationSystem->Blocks.GetEntryAtIndex(i); gs_list_entry<animation_block>* AnimationBlockEntry = AnimationSystem->Blocks.GetEntryAtIndex(i);
if (AnimationBlockEntry->Free.NextFreeEntry != 0) { continue; } if (EntryIsFree(AnimationBlockEntry)) { continue; }
gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle; gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle;
animation_block AnimationBlockAt = AnimationBlockEntry->Value; animation_block AnimationBlockAt = AnimationBlockEntry->Value;
@ -542,25 +531,11 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta
PushRenderBoundingBox2D(RenderBuffer, RectExpand(FrameBarBounds), 1.f, TealV4); PushRenderBoundingBox2D(RenderBuffer, RectExpand(FrameBarBounds), 1.f, TealV4);
PushRenderBoundingBox2D(RenderBuffer, RectExpand(TimelineBounds), 1.f, PinkV4); PushRenderBoundingBox2D(RenderBuffer, RectExpand(TimelineBounds), 1.f, PinkV4);
return Result;
{
r32 FirstPlayablePercentX = FrameToPercentRange(AnimationSystem->PlayableRange.Min, AdjustedViewRange);
r32 LastPlayablePercentX = FrameToPercentRange(AnimationSystem->PlayableRange.Max, AdjustedViewRange);
v2 PlayableMin = v2{(FirstPlayablePercentX * AnimationPanelWidth) + PanelBounds.Min.x, PanelBounds.Min.y };
v2 PlayableMax = v2{(LastPlayablePercentX * AnimationPanelWidth) + PanelBounds.Min.x, PanelBounds.Max.y };
PushRenderQuad2D(RenderBuffer, PlayableMin, PlayableMax, v4{.22f, .22f, .22f, 1.f});
}
if (MouseDownAndNotHandled && PointIsInRect(Mouse.Pos, TimelineBounds)) if (MouseDownAndNotHandled && PointIsInRect(Mouse.Pos, TimelineBounds))
{ {
DeselectCurrentAnimationBlock(State); DeselectCurrentAnimationBlock(State);
} }
return Result; return Result;
} }
@ -611,7 +586,7 @@ DrawAnimationClipsList(rect PanelBounds, mouse_state Mouse, render_command_buffe
if (MouseButtonTransitionedDown(Mouse.LeftButtonState) if (MouseButtonTransitionedDown(Mouse.LeftButtonState)
&& PointIsInRect(Mouse.DownPos, ElementBounds)) && PointIsInRect(Mouse.DownPos, ElementBounds))
{ {
AddAnimationBlockAtCurrentTime(i + 1, &State->AnimationSystem); AddAnimationBlockAtCurrentTime(i + 1, State->SelectedAnimationLayer, &State->AnimationSystem);
} }
} }