Moved everything over to using frames rather than seconds in the animation system.
This commit is contained in:
parent
dc36d44cd2
commit
197b6accc7
|
@ -92,8 +92,8 @@ static void DebugPrint(char* Format, ...);
|
||||||
if((expression)) \
|
if((expression)) \
|
||||||
{ \
|
{ \
|
||||||
}else{ \
|
}else{ \
|
||||||
volatile int* p = 0; \
|
volatile int* p = 0; \
|
||||||
*p = 5; \
|
*p = 5; \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,9 @@ typedef ANIMATION_PROC(animation_proc);
|
||||||
|
|
||||||
struct animation_block
|
struct animation_block
|
||||||
{
|
{
|
||||||
// TODO(Peter): Should we change this to frames??
|
u32 StartFrame;
|
||||||
r32 StartTime;
|
u32 EndFrame;
|
||||||
r32 EndTime;
|
|
||||||
u32 AnimationProcHandle;
|
u32 AnimationProcHandle;
|
||||||
|
|
||||||
u32 Layer;
|
u32 Layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,16 +22,26 @@ struct animation_system
|
||||||
{
|
{
|
||||||
gs_list<animation_block> Blocks;
|
gs_list<animation_block> Blocks;
|
||||||
|
|
||||||
r32 Time;
|
// NOTE(Peter): The frame currently being displayed/processed. you
|
||||||
s32 LastUpdatedFrame;
|
// can see which frame you're on by looking at the time slider on the timeline
|
||||||
|
// panel
|
||||||
|
u32 CurrentFrame;
|
||||||
|
u32 LastUpdatedFrame;
|
||||||
r32 SecondsPerFrame;
|
r32 SecondsPerFrame;
|
||||||
|
|
||||||
b32 TimelineShouldAdvance;
|
b32 TimelineShouldAdvance;
|
||||||
|
|
||||||
// :Temporary
|
// Timeline
|
||||||
r32 AnimationStart;
|
r32 StartFrame;
|
||||||
r32 AnimationEnd;
|
r32 EndFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal u32
|
||||||
|
SecondsToFrames(r32 Seconds, animation_system System)
|
||||||
|
{
|
||||||
|
u32 Result = Seconds * (1.0f / System.SecondsPerFrame);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
#define FOLDHAUS_ANIMATION
|
#define FOLDHAUS_ANIMATION
|
||||||
#endif // FOLDHAUS_ANIMATION
|
#endif // FOLDHAUS_ANIMATION
|
||||||
|
|
|
@ -188,8 +188,8 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
{ // Animation PLAYGROUND
|
{ // Animation PLAYGROUND
|
||||||
State->AnimationSystem = {};
|
State->AnimationSystem = {};
|
||||||
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
|
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
|
||||||
State->AnimationSystem.AnimationStart = 0;
|
State->AnimationSystem.StartFrame = 0;
|
||||||
State->AnimationSystem.AnimationEnd = 15;
|
State->AnimationSystem.EndFrame = SecondsToFrames(15, State->AnimationSystem);
|
||||||
} // End Animation Playground
|
} // End Animation Playground
|
||||||
|
|
||||||
|
|
||||||
|
@ -320,14 +320,17 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
HandleInput(State, State->WindowBounds, InputQueue, Mouse);
|
HandleInput(State, State->WindowBounds, InputQueue, Mouse);
|
||||||
|
|
||||||
if (State->AnimationSystem.TimelineShouldAdvance) {
|
if (State->AnimationSystem.TimelineShouldAdvance) {
|
||||||
State->AnimationSystem.Time += Context.DeltaTime;
|
// TODO(Peter): Revisit this. This implies that the framerate of the animation system
|
||||||
if (State->AnimationSystem.Time > State->AnimationSystem.AnimationEnd)
|
// is tied to the framerate of the simulation. That seems correct to me, but I'm not sure
|
||||||
|
State->AnimationSystem.CurrentFrame += 1;
|
||||||
|
// Loop back to the beginning
|
||||||
|
if (State->AnimationSystem.CurrentFrame > State->AnimationSystem.EndFrame)
|
||||||
{
|
{
|
||||||
State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd;
|
State->AnimationSystem.CurrentFrame = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 CurrentFrame = (s32)(State->AnimationSystem.Time / State->AnimationSystem.SecondsPerFrame);
|
u32 CurrentFrame = State->AnimationSystem.CurrentFrame;
|
||||||
if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame)
|
if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame)
|
||||||
{
|
{
|
||||||
State->AnimationSystem.LastUpdatedFrame = CurrentFrame;
|
State->AnimationSystem.LastUpdatedFrame = CurrentFrame;
|
||||||
|
@ -339,30 +342,31 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
if (!EntryIsFree(BlockEntry))
|
if (!EntryIsFree(BlockEntry))
|
||||||
{
|
{
|
||||||
animation_block Block = BlockEntry->Value;
|
animation_block Block = BlockEntry->Value;
|
||||||
if (State->AnimationSystem.Time >= Block.StartTime
|
if (CurrentFrame >= Block.StartFrame && CurrentFrame <= Block.EndFrame)
|
||||||
&& State->AnimationSystem.Time <= Block.EndTime)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
||||||
|
|
||||||
|
u32 FramesIntoBlock = CurrentFrame - Block.StartFrame;
|
||||||
|
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
||||||
// TODO(Peter): Temporary
|
// TODO(Peter): Temporary
|
||||||
switch(Block.AnimationProcHandle)
|
switch(Block.AnimationProcHandle)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
TestPatternOne(Assembly, FrameTime - Block.StartTime);
|
TestPatternOne(Assembly, SecondsIntoBlock);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
TestPatternTwo(Assembly, FrameTime - Block.StartTime);
|
TestPatternTwo(Assembly, SecondsIntoBlock);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
TestPatternThree(Assembly, FrameTime - Block.StartTime);
|
TestPatternThree(Assembly, SecondsIntoBlock);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
// NOTE(Peter): Zero is invalid
|
// NOTE(Peter): Zero is invalid
|
||||||
|
|
|
@ -5,48 +5,41 @@
|
||||||
//
|
//
|
||||||
#ifndef FOLDHAUS_PANEL_ANIMATION_TIMELINE_H
|
#ifndef FOLDHAUS_PANEL_ANIMATION_TIMELINE_H
|
||||||
|
|
||||||
inline r32
|
inline u32
|
||||||
GetTimeFromPointInAnimationPanel(v2 Point, rect PanelBounds, s32 StartFrame, s32 EndFrame, r32 SecondsPerFrame)
|
GetFrameFromPointInAnimationPanel(v2 Point, rect PanelBounds, u32 StartFrame, u32 EndFrame)
|
||||||
{
|
{
|
||||||
r32 StartFrameTime = (r32)StartFrame * SecondsPerFrame;
|
r32 HorizontalPercentOfBounds = (Point.x - PanelBounds.Min.x) / (PanelBounds.Max.x - PanelBounds.Min.x);
|
||||||
r32 EndFrameTime = (r32)EndFrame * SecondsPerFrame;
|
u32 TimeAtPoint = (u32)(HorizontalPercentOfBounds * (EndFrame - StartFrame)) + StartFrame;
|
||||||
r32 TimeAtPoint = GSRemap(Point.x, PanelBounds.Min.x, PanelBounds.Max.x, StartFrameTime, EndFrameTime);
|
|
||||||
return TimeAtPoint;
|
return TimeAtPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s32
|
inline s32
|
||||||
GetFrameFromPointInAnimationPanel (v2 Point, rect PanelBounds, s32 StartFrame, s32 EndFrame, r32 SecondsPerFrame)
|
GetXPositionFromFrameInAnimationPanel (u32 Frame, rect PanelBounds, s32 StartFrame, s32 EndFrame)
|
||||||
{
|
{
|
||||||
r32 TimeAtPoint = GetTimeFromPointInAnimationPanel(Point, PanelBounds, StartFrame, EndFrame, SecondsPerFrame);
|
r32 PercentOfTimeline = (r32)(Frame - StartFrame) / (r32)(EndFrame - StartFrame);
|
||||||
s32 FrameAtPoint = (s32)(TimeAtPoint * SecondsPerFrame);
|
s32 XPositionAtFrame = (PercentOfTimeline * Width(PanelBounds)) + PanelBounds.Min.x;
|
||||||
return FrameAtPoint;
|
return XPositionAtFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s32
|
internal gs_list_handle
|
||||||
GetXPositionFromTimeInAnimationPanel (r32 Time, rect PanelBounds, s32 StartFrame, s32 EndFrame, r32 SecondsPerFrame)
|
AddAnimationBlock(u32 StartFrame, u32 EndFrame, u32 AnimationProcHandle, animation_system* AnimationSystem)
|
||||||
{
|
|
||||||
r32 StartFrameTime = (r32)StartFrame * SecondsPerFrame;
|
|
||||||
r32 EndFrameTime = (r32)EndFrame * SecondsPerFrame;
|
|
||||||
s32 XPositionAtTime = GSRemap(Time, StartFrameTime, EndFrameTime, PanelBounds.Min.x, PanelBounds.Max.x);
|
|
||||||
return XPositionAtTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
AddAnimationBlock(r32 StartTime, r32 EndTime, u32 AnimationProcHandle, animation_system* AnimationSystem)
|
|
||||||
{
|
{
|
||||||
|
gs_list_handle Result = {0};
|
||||||
animation_block NewBlock = {0};
|
animation_block NewBlock = {0};
|
||||||
NewBlock.StartTime = StartTime;
|
NewBlock.StartFrame = StartFrame;
|
||||||
NewBlock.EndTime = EndTime;
|
NewBlock.EndFrame = EndFrame;
|
||||||
NewBlock.AnimationProcHandle = AnimationProcHandle;
|
NewBlock.AnimationProcHandle = AnimationProcHandle;
|
||||||
AnimationSystem->Blocks.PushElementOnList(NewBlock);
|
Result = AnimationSystem->Blocks.PushElementOnList(NewBlock);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NEW_ANIMATION_BLOCK_DURATION 3
|
internal gs_list_handle
|
||||||
internal void
|
|
||||||
AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, animation_system* System)
|
AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, animation_system* System)
|
||||||
{
|
{
|
||||||
r32 CurrentTime = System->Time;
|
u32 NewBlockStart = System->CurrentFrame;
|
||||||
AddAnimationBlock(CurrentTime, CurrentTime + NEW_ANIMATION_BLOCK_DURATION, AnimationProcHandle, System);
|
u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System);
|
||||||
|
gs_list_handle Result = AddAnimationBlock(NewBlockStart, NewBlockEnd, AnimationProcHandle, System);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -70,7 +63,10 @@ DeselectCurrentAnimationBlock(app_state* State)
|
||||||
|
|
||||||
FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand)
|
FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand)
|
||||||
{
|
{
|
||||||
DeleteAnimationBlock(State->SelectedAnimationBlockHandle, State);
|
if(ListHandleIsValid(State->SelectedAnimationBlockHandle))
|
||||||
|
{
|
||||||
|
DeleteAnimationBlock(State->SelectedAnimationBlockHandle, State);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -87,8 +83,8 @@ 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;
|
||||||
r32 TimeAtMouseX = GetTimeFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->StartFrame, OpState->EndFrame, State->AnimationSystem.SecondsPerFrame);
|
u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->StartFrame, OpState->EndFrame);
|
||||||
State->AnimationSystem.Time = TimeAtMouseX;
|
State->AnimationSystem.CurrentFrame = FrameAtMouseX;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOLDHAUS_INPUT_COMMAND_PROC(EndDragTimeMarker)
|
FOLDHAUS_INPUT_COMMAND_PROC(EndDragTimeMarker)
|
||||||
|
@ -124,20 +120,20 @@ StartDragTimeMarker(rect TimelineBounds, s32 PanelStartFrame, s32 PanelEndFrame,
|
||||||
OPERATION_STATE_DEF(drag_animation_clip_state)
|
OPERATION_STATE_DEF(drag_animation_clip_state)
|
||||||
{
|
{
|
||||||
rect TimelineBounds;
|
rect TimelineBounds;
|
||||||
r32 AnimationPanel_StartFrame;
|
s32 AnimationPanel_StartFrame;
|
||||||
r32 AnimationPanel_EndFrame;
|
s32 AnimationPanel_EndFrame;
|
||||||
r32 SelectedClip_InitialStartTime;
|
s32 SelectedClip_InitialStartFrame;
|
||||||
r32 SelectedClip_InitialEndTime;
|
s32 SelectedClip_InitialEndFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal r32
|
internal u32
|
||||||
AttemptToSnapPosition(r32 Snapping, r32 SnapTo)
|
AttemptToSnapPosition(u32 SnappingFrame, u32 SnapToFrame)
|
||||||
{
|
{
|
||||||
r32 Result = Snapping;
|
u32 Result = SnappingFrame;
|
||||||
r32 SnapDistance = .25f;
|
s32 SnapDistance = 5;
|
||||||
if (GSAbs(Snapping - SnapTo) <= SnapDistance)
|
if (GSAbs((s32)SnappingFrame - (s32)SnapToFrame) <= SnapDistance)
|
||||||
{
|
{
|
||||||
Result = SnapTo;
|
Result = SnapToFrame;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -146,12 +142,13 @@ 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;
|
||||||
|
|
||||||
s32 ClipInitialStartTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialStartTime, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
|
u32 ClipInitialStartFrameXPosition = GetXPositionFromFrameInAnimationPanel(OpState->SelectedClip_InitialStartFrame, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame);
|
||||||
s32 ClipInitialEndTimeXPosition = GetXPositionFromTimeInAnimationPanel(OpState->SelectedClip_InitialEndTime, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
|
u32 ClipInitialEndFrameXPosition = GetXPositionFromFrameInAnimationPanel(OpState->SelectedClip_InitialEndFrame, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame);
|
||||||
|
|
||||||
r32 TimeAtMouseDownX = GetTimeFromPointInAnimationPanel(Mouse.DownPos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
|
u32 FrameAtMouseDownX = GetFrameFromPointInAnimationPanel(Mouse.DownPos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame);
|
||||||
r32 TimeAtMouseX = GetTimeFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
|
|
||||||
r32 TimeOffset = TimeAtMouseX - TimeAtMouseDownX;
|
u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame);
|
||||||
|
s32 FrameOffset = (s32)FrameAtMouseX - (s32)FrameAtMouseDownX;
|
||||||
|
|
||||||
animation_block* AnimationBlock = State->AnimationSystem.Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle);
|
animation_block* AnimationBlock = State->AnimationSystem.Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle);
|
||||||
if (!AnimationBlock)
|
if (!AnimationBlock)
|
||||||
|
@ -160,83 +157,82 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Peter): This should really be in pixels so we can zoom in and out on the timeline
|
if (GSAbs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE)
|
||||||
r32 SnapDistance = .25f;
|
|
||||||
if (GSAbs(Mouse.DownPos.x - ClipInitialStartTimeXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE)
|
|
||||||
{
|
{
|
||||||
r32 NewStartTime = OpState->SelectedClip_InitialStartTime + TimeOffset;
|
u32 NewStartFrame = OpState->SelectedClip_InitialStartFrame + FrameOffset;
|
||||||
if (TimeOffset < 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 (OtherBlockEntry->Free.NextFreeEntry != 0) { continue; }
|
||||||
animation_block OtherBlock = OtherBlockEntry->Value;
|
animation_block OtherBlock = OtherBlockEntry->Value;
|
||||||
NewStartTime = AttemptToSnapPosition(NewStartTime, OtherBlock.EndTime);
|
NewStartFrame = AttemptToSnapPosition(NewStartFrame, OtherBlock.EndFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (NewStartTime >= AnimationBlock->EndTime)
|
if (NewStartFrame >= AnimationBlock->EndFrame)
|
||||||
{
|
{
|
||||||
NewStartTime = AnimationBlock->EndTime - State->AnimationSystem.SecondsPerFrame;
|
NewStartFrame = AnimationBlock->EndFrame - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimationBlock->StartTime = NewStartTime;
|
AnimationBlock->StartFrame = NewStartFrame;
|
||||||
}
|
}
|
||||||
else if (GSAbs(Mouse.DownPos.x - ClipInitialEndTimeXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE)
|
else if (GSAbs(Mouse.DownPos.x - ClipInitialEndFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE)
|
||||||
{
|
{
|
||||||
r32 NewEndTime = OpState->SelectedClip_InitialEndTime + TimeOffset;
|
r32 NewEndFrame = OpState->SelectedClip_InitialEndFrame + FrameOffset;
|
||||||
if (TimeOffset > 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 (OtherBlockEntry->Free.NextFreeEntry != 0) { continue; }
|
||||||
animation_block OtherBlock = OtherBlockEntry->Value;
|
animation_block OtherBlock = OtherBlockEntry->Value;
|
||||||
NewEndTime = AttemptToSnapPosition(NewEndTime, OtherBlock.StartTime);
|
NewEndFrame = AttemptToSnapPosition(NewEndFrame, OtherBlock.StartFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(NewEndTime <= AnimationBlock->StartTime)
|
if(NewEndFrame <= AnimationBlock->StartFrame)
|
||||||
{
|
{
|
||||||
NewEndTime = AnimationBlock->StartTime + State->AnimationSystem.SecondsPerFrame;
|
NewEndFrame = AnimationBlock->StartFrame + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimationBlock->EndTime = NewEndTime;
|
AnimationBlock->EndFrame = NewEndFrame;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r32 NewStartTime = OpState->SelectedClip_InitialStartTime + TimeOffset;
|
u32 NewStartFrame = OpState->SelectedClip_InitialStartFrame + FrameOffset;
|
||||||
r32 NewEndTime = OpState->SelectedClip_InitialEndTime + TimeOffset;
|
u32 NewEndFrame = OpState->SelectedClip_InitialEndFrame + FrameOffset;
|
||||||
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 (OtherBlockEntry->Free.NextFreeEntry != 0) { continue; }
|
||||||
animation_block OtherBlock = OtherBlockEntry->Value;
|
animation_block OtherBlock = OtherBlockEntry->Value;
|
||||||
|
|
||||||
r32 SnapAmount = 0;
|
u32 SnapFramesAmount = 0;
|
||||||
if (TimeOffset > 0)
|
if (FrameOffset > 0)
|
||||||
{
|
{
|
||||||
r32 FinalEndTime = AttemptToSnapPosition(NewEndTime, OtherBlock.StartTime);
|
u32 FinalEndFrame = AttemptToSnapPosition(NewEndFrame, OtherBlock.StartFrame);
|
||||||
SnapAmount = FinalEndTime - NewEndTime;
|
SnapFramesAmount = FinalEndFrame - NewEndFrame;
|
||||||
}
|
}
|
||||||
else if (TimeOffset < 0)
|
else if (FrameOffset < 0)
|
||||||
{
|
{
|
||||||
r32 FinalStartTime = AttemptToSnapPosition(NewStartTime, OtherBlock.EndTime);
|
u32 FinalStartFrame = AttemptToSnapPosition(NewStartFrame, OtherBlock.EndFrame);
|
||||||
SnapAmount = FinalStartTime - NewStartTime;
|
SnapFramesAmount = FinalStartFrame - NewStartFrame;
|
||||||
}
|
}
|
||||||
NewEndTime += SnapAmount;
|
NewEndFrame += SnapFramesAmount;
|
||||||
NewStartTime += SnapAmount;
|
NewStartFrame += SnapFramesAmount;
|
||||||
}
|
}
|
||||||
AnimationBlock->StartTime = NewStartTime;
|
AnimationBlock->StartFrame = NewStartFrame;
|
||||||
AnimationBlock->EndTime = NewEndTime;
|
AnimationBlock->EndFrame = NewEndFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
r32 TimelineEndTime = OpState->AnimationPanel_EndFrame * State->AnimationSystem.SecondsPerFrame;
|
s32 VisibleStartFrame = OpState->AnimationPanel_StartFrame;
|
||||||
AnimationBlock->StartTime = GSClamp(0.f, AnimationBlock->StartTime, TimelineEndTime);
|
s32 VisibleEndFrame = OpState->AnimationPanel_EndFrame;
|
||||||
AnimationBlock->EndTime = GSClamp(0.f, AnimationBlock->EndTime, TimelineEndTime);
|
AnimationBlock->StartFrame = (u32)GSClamp(VisibleStartFrame, (s32)AnimationBlock->StartFrame, VisibleEndFrame);
|
||||||
|
AnimationBlock->EndFrame = (u32)GSClamp(VisibleStartFrame, (s32)AnimationBlock->EndFrame, VisibleEndFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_command DragAnimationClipCommands [] = {
|
input_command DragAnimationClipCommands [] = {
|
||||||
|
@ -258,25 +254,16 @@ SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, s32 PanelStartFrame
|
||||||
OpState->AnimationPanel_EndFrame = PanelEndFrame ;
|
OpState->AnimationPanel_EndFrame = PanelEndFrame ;
|
||||||
|
|
||||||
animation_block* SelectedBlock = State->AnimationSystem.Blocks.GetElementWithHandle(BlockHandle);
|
animation_block* SelectedBlock = State->AnimationSystem.Blocks.GetElementWithHandle(BlockHandle);
|
||||||
OpState->SelectedClip_InitialStartTime = SelectedBlock->StartTime;
|
OpState->SelectedClip_InitialStartFrame = SelectedBlock->StartFrame;
|
||||||
OpState->SelectedClip_InitialEndTime = SelectedBlock->EndTime;
|
OpState->SelectedClip_InitialEndFrame = SelectedBlock->EndFrame;
|
||||||
}
|
}
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand)
|
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);
|
||||||
r32 MouseDownPositionPercent = (Mouse.Pos.x - ActivePanel.Bounds.Min.x) / Width(ActivePanel.Bounds);
|
u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, State->AnimationSystem.StartFrame, State->AnimationSystem.EndFrame);
|
||||||
r32 NewBlockTimeStart = MouseDownPositionPercent * State->AnimationSystem.AnimationEnd;
|
gs_list_handle NewBlockHandle = AddAnimationBlock(MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, &State->AnimationSystem);
|
||||||
#define NEW_BLOCK_DURATION 1
|
|
||||||
r32 NewBlockTimeEnd = NewBlockTimeStart + NEW_BLOCK_DURATION;
|
|
||||||
|
|
||||||
animation_block Block = {0};
|
|
||||||
Block.StartTime = NewBlockTimeStart;
|
|
||||||
Block.EndTime = NewBlockTimeEnd;
|
|
||||||
Block.AnimationProcHandle = 4;
|
|
||||||
|
|
||||||
gs_list_handle NewBlockHandle = State->AnimationSystem.Blocks.PushElementOnList(Block);
|
|
||||||
SelectAnimationBlock(NewBlockHandle, State);
|
SelectAnimationBlock(NewBlockHandle, State);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,18 +330,16 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu
|
||||||
}
|
}
|
||||||
|
|
||||||
internal rect
|
internal rect
|
||||||
DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPerFrame, s32 FrameCount, s32 StartFrame, rect TimelineBounds, render_command_buffer* RenderBuffer)
|
DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, s32 FrameCount, s32 StartFrame, rect TimelineBounds, render_command_buffer* RenderBuffer)
|
||||||
{
|
{
|
||||||
rect BlockBounds = {};
|
rect BlockBounds = {};
|
||||||
|
|
||||||
r32 TimelineWidth = Width(TimelineBounds);
|
r32 TimelineWidth = Width(TimelineBounds);
|
||||||
|
|
||||||
s32 BlockStartFrame = AnimationBlock.StartTime / SecondsPerFrame;
|
r32 StartFramePercent = (r32)(AnimationBlock.StartFrame - StartFrame) / (r32)FrameCount;
|
||||||
r32 StartFramePercent = (r32)(BlockStartFrame - StartFrame) / (r32)FrameCount;
|
|
||||||
r32 StartPosition = TimelineWidth * StartFramePercent;
|
r32 StartPosition = TimelineWidth * StartFramePercent;
|
||||||
|
|
||||||
s32 BlockEndFrame = AnimationBlock.EndTime / SecondsPerFrame;
|
r32 EndFramePercent = (r32)(AnimationBlock.EndFrame - StartFrame) / (r32)FrameCount;
|
||||||
r32 EndFramePercent = (r32)(BlockEndFrame - StartFrame) / (r32)FrameCount;
|
|
||||||
r32 EndPosition = TimelineWidth * EndFramePercent;
|
r32 EndPosition = TimelineWidth * EndFramePercent;
|
||||||
|
|
||||||
BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, 25};
|
BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, 25};
|
||||||
|
@ -367,10 +352,10 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPe
|
||||||
}
|
}
|
||||||
|
|
||||||
internal gs_list_handle
|
internal gs_list_handle
|
||||||
DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 EndFrame, rect PanelBounds, gs_list_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse)
|
DrawAnimationTimeline (animation_system* AnimationSystem, s32 VisibleStartFrame, s32 VisibleEndFrame, rect PanelBounds, gs_list_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse)
|
||||||
{
|
{
|
||||||
string TempString = MakeString(PushArray(&State->Transient, char, 256), 256);
|
string TempString = MakeString(PushArray(&State->Transient, char, 256), 256);
|
||||||
s32 FrameCount = EndFrame - StartFrame;
|
s32 VisibleFrameCount = VisibleEndFrame - VisibleStartFrame;
|
||||||
|
|
||||||
gs_list_handle Result = SelectedBlockHandle;
|
gs_list_handle Result = SelectedBlockHandle;
|
||||||
|
|
||||||
|
@ -378,11 +363,8 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
|
||||||
r32 AnimationPanelWidth = PanelBounds.Max.x - PanelBounds.Min.x;
|
r32 AnimationPanelWidth = PanelBounds.Max.x - PanelBounds.Min.x;
|
||||||
|
|
||||||
{
|
{
|
||||||
s32 FirstPlayableFrame = (AnimationSystem->AnimationStart / AnimationSystem->SecondsPerFrame);
|
r32 FirstPlayablePercentX = ((r32)(AnimationSystem->StartFrame - VisibleStartFrame) / (r32)VisibleFrameCount);
|
||||||
s32 LastPlayableFrame = (AnimationSystem->AnimationEnd / AnimationSystem->SecondsPerFrame);
|
r32 LastPlayablePercentX = ((r32)(AnimationSystem->EndFrame - VisibleStartFrame) / (r32)VisibleFrameCount);
|
||||||
|
|
||||||
r32 FirstPlayablePercentX = ((r32)(FirstPlayableFrame - StartFrame) / (r32)FrameCount);
|
|
||||||
r32 LastPlayablePercentX = ((r32)(LastPlayableFrame - StartFrame) / (r32)FrameCount);
|
|
||||||
|
|
||||||
v2 PlayableMin = v2{(FirstPlayablePercentX * AnimationPanelWidth) + PanelBounds.Min.x, PanelBounds.Min.y };
|
v2 PlayableMin = v2{(FirstPlayablePercentX * AnimationPanelWidth) + PanelBounds.Min.x, PanelBounds.Min.y };
|
||||||
v2 PlayableMax = v2{(LastPlayablePercentX * AnimationPanelWidth) + PanelBounds.Min.x, PanelBounds.Max.y };
|
v2 PlayableMax = v2{(LastPlayablePercentX * AnimationPanelWidth) + PanelBounds.Min.x, PanelBounds.Max.y };
|
||||||
|
@ -391,7 +373,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
|
||||||
PushRenderQuad2D(RenderBuffer, PlayableMin, PlayableMax, v4{.22f, .22f, .22f, 1.f});
|
PushRenderQuad2D(RenderBuffer, PlayableMin, PlayableMax, v4{.22f, .22f, .22f, 1.f});
|
||||||
}
|
}
|
||||||
|
|
||||||
r32 FrameBarBottom = DrawFrameBar(AnimationSystem, RenderBuffer, StartFrame, EndFrame, PanelBounds, Mouse, State);
|
r32 FrameBarBottom = DrawFrameBar(AnimationSystem, RenderBuffer, VisibleStartFrame, VisibleEndFrame, PanelBounds, Mouse, State);
|
||||||
|
|
||||||
// Animation Blocks
|
// Animation Blocks
|
||||||
rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} };
|
rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} };
|
||||||
|
@ -410,19 +392,18 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
|
||||||
BlockColor = PinkV4;
|
BlockColor = PinkV4;
|
||||||
}
|
}
|
||||||
|
|
||||||
rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AnimationSystem->SecondsPerFrame, FrameCount, StartFrame, TimelineBounds, RenderBuffer);
|
rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, VisibleFrameCount, VisibleStartFrame, 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, TimelineBounds, State);
|
SelectAndBeginDragAnimationBlock(CurrentBlockHandle, VisibleStartFrame, VisibleEndFrame, TimelineBounds, State);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time Slider
|
// Time Slider
|
||||||
s32 SliderFrame = AnimationSystem->Time / AnimationSystem->SecondsPerFrame;
|
r32 TimePercent = (r32)(AnimationSystem->CurrentFrame - VisibleStartFrame) / (r32)VisibleFrameCount;
|
||||||
r32 TimePercent = (r32)(SliderFrame - StartFrame) / (r32)FrameCount;
|
|
||||||
r32 SliderX = PanelBounds.Min.x + (AnimationPanelWidth * TimePercent);
|
r32 SliderX = PanelBounds.Min.x + (AnimationPanelWidth * TimePercent);
|
||||||
v2 SliderMin = v2{SliderX, PanelBounds.Min.y};
|
v2 SliderMin = v2{SliderX, PanelBounds.Min.y};
|
||||||
v2 SliderMax = v2{SliderX + 1, PanelBounds.Max.y - 25};
|
v2 SliderMax = v2{SliderX + 1, PanelBounds.Max.y - 25};
|
||||||
|
@ -435,7 +416,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
|
||||||
v2 HeadMax = v2{SliderX + SliderHalfWidth, PanelBounds.Max.y};
|
v2 HeadMax = v2{SliderX + SliderHalfWidth, PanelBounds.Max.y};
|
||||||
PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor);
|
PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor);
|
||||||
|
|
||||||
PrintF(&TempString, "%d", SliderFrame);
|
PrintF(&TempString, "%d", AnimationSystem->CurrentFrame);
|
||||||
DrawString(RenderBuffer, TempString, State->Interface.Font, HeadMin + v2{4, 4}, WhiteV4);
|
DrawString(RenderBuffer, TempString, State->Interface.Font, HeadMin + v2{4, 4}, WhiteV4);
|
||||||
|
|
||||||
if (MouseDownAndNotHandled && PointIsInRect(Mouse.Pos, TimelineBounds))
|
if (MouseDownAndNotHandled && PointIsInRect(Mouse.Pos, TimelineBounds))
|
||||||
|
@ -518,10 +499,9 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R
|
||||||
{
|
{
|
||||||
DrawAnimationClipsList(AnimationClipListBounds, Mouse, RenderBuffer, State);
|
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,
|
SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem,
|
||||||
FrameStart - 20, FrameEnd + 20,
|
State->AnimationSystem.StartFrame - 20,
|
||||||
|
State->AnimationSystem.EndFrame + 20,
|
||||||
TimelineBounds,
|
TimelineBounds,
|
||||||
SelectedBlockHandle,
|
SelectedBlockHandle,
|
||||||
RenderBuffer, State, Mouse);
|
RenderBuffer, State, Mouse);
|
||||||
|
@ -564,7 +544,7 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R
|
||||||
if (StopResult.Pressed)
|
if (StopResult.Pressed)
|
||||||
{
|
{
|
||||||
State->AnimationSystem.TimelineShouldAdvance = false;
|
State->AnimationSystem.TimelineShouldAdvance = false;
|
||||||
State->AnimationSystem.Time = 0;
|
State->AnimationSystem.CurrentFrame = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue