Added rudimentary layers to the animation system.
This commit is contained in:
parent
3a20883a49
commit
de1a9474f0
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
@ -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,40 +344,37 @@ 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;
|
||||||
|
if (CurrentFrame < Block.Range.Min || CurrentFrame > Block.Range.Max) { continue; }
|
||||||
|
|
||||||
|
for (u32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++)
|
||||||
{
|
{
|
||||||
animation_block Block = BlockEntry->Value;
|
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j);
|
||||||
if (CurrentFrame >= Block.Range.Min && CurrentFrame <= Block.Range.Max)
|
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
||||||
|
|
||||||
|
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
||||||
|
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
||||||
|
// TODO(Peter): Temporary
|
||||||
|
switch(Block.AnimationProcHandle)
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++)
|
case 1:
|
||||||
{
|
{
|
||||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j);
|
TestPatternOne(Assembly, SecondsIntoBlock);
|
||||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
}break;
|
||||||
|
|
||||||
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
case 2:
|
||||||
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
{
|
||||||
// TODO(Peter): Temporary
|
TestPatternTwo(Assembly, SecondsIntoBlock);
|
||||||
switch(Block.AnimationProcHandle)
|
}break;
|
||||||
{
|
|
||||||
case 1:
|
case 3:
|
||||||
{
|
{
|
||||||
TestPatternOne(Assembly, SecondsIntoBlock);
|
TestPatternThree(Assembly, SecondsIntoBlock);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case 2:
|
// NOTE(Peter): Zero is invalid
|
||||||
{
|
InvalidDefaultCase;
|
||||||
TestPatternTwo(Assembly, SecondsIntoBlock);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
TestPatternThree(Assembly, SecondsIntoBlock);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
// NOTE(Peter): Zero is invalid
|
|
||||||
InvalidDefaultCase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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,13 +379,13 @@ 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))
|
||||||
{
|
{
|
||||||
TimelineState->VisibleRange = Result;
|
TimelineState->VisibleRange = Result;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue