implemented an animation handle system for identifying animation blocks

This commit is contained in:
PS 2020-10-18 13:57:04 -07:00
parent 121e9efa93
commit 8eb3044422
5 changed files with 127 additions and 64 deletions

View File

@ -33,18 +33,18 @@ GetXPositionFromFrameInAnimationPanel (u32 Frame, rect2 PanelBounds, frame_range
return XPositionAtFrame; return XPositionAtFrame;
} }
internal gs_list_handle internal handle
AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 LayerHandle, animation_system* System) AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 LayerHandle, animation_system* System)
{ {
u32 NewBlockStart = System->CurrentFrame; u32 NewBlockStart = System->CurrentFrame;
u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System); u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System);
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System); animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
gs_list_handle Result = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle); handle AnimHandle = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle);
return Result; return AnimHandle;
} }
internal void internal void
SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State) SelectAnimationBlock(handle BlockHandle, app_state* State)
{ {
State->SelectedAnimationBlockHandle = BlockHandle; State->SelectedAnimationBlockHandle = BlockHandle;
} }
@ -57,11 +57,16 @@ DeselectCurrentAnimationBlock(app_state* State)
FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand)
{ {
if(ListHandleIsValid(State->SelectedAnimationBlockHandle)) handle SelectedAnimHandle = State->SelectedAnimationBlockHandle;
{
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem);
if(SelectedAnimHandle.Index < ActiveAnim->Blocks_.Count &&
ActiveAnim->Blocks_.Generations[SelectedAnimHandle.Index] == SelectedAnimHandle.Generation)
{
Animation_RemoveBlock(ActiveAnim, State->SelectedAnimationBlockHandle); Animation_RemoveBlock(ActiveAnim, State->SelectedAnimationBlockHandle);
State->SelectedAnimationBlockHandle = {0}; State->SelectedAnimationBlockHandle = {0};
// TODO(pjs): Introduce an animation_block_selection in this file
// it should have a handle to the animation, block, and a HasSelection flag
// as it is now, you kind of always have the first block selected
} }
} }
@ -153,7 +158,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip)
u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->VisibleRange); u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->VisibleRange);
s32 FrameOffset = (s32)FrameAtMouseX - (s32)FrameAtMouseDownX; s32 FrameOffset = (s32)FrameAtMouseX - (s32)FrameAtMouseDownX;
animation_block* AnimationBlock = ActiveAnim->Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle); animation_block* AnimationBlock = Animation_GetBlockFromHandle(ActiveAnim, State->SelectedAnimationBlockHandle);
if (!AnimationBlock) if (!AnimationBlock)
{ {
EndCurrentOperationMode(State, {}, Mouse, Context); EndCurrentOperationMode(State, {}, Mouse, Context);
@ -243,7 +248,7 @@ input_command DragAnimationClipCommands [] = {
}; };
internal void internal void
SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range VisibleRange, rect2 TimelineBounds, app_state* State) SelectAndBeginDragAnimationBlock(handle BlockHandle, frame_range VisibleRange, rect2 TimelineBounds, app_state* State)
{ {
SelectAnimationBlock(BlockHandle, State); SelectAnimationBlock(BlockHandle, State);
@ -256,7 +261,7 @@ SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range Visible
OpState->TimelineBounds = TimelineBounds; OpState->TimelineBounds = TimelineBounds;
OpState->VisibleRange = VisibleRange; OpState->VisibleRange = VisibleRange;
animation_block* SelectedBlock = ActiveAnim->Blocks.GetElementWithHandle(BlockHandle); animation_block* SelectedBlock = Animation_GetBlockFromHandle(ActiveAnim, BlockHandle);
OpState->ClipRange = SelectedBlock->Range; OpState->ClipRange = SelectedBlock->Range;
} }
// ------------------- // -------------------
@ -269,7 +274,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand)
frame_range Range = ActiveAnim->PlayableRange; frame_range Range = ActiveAnim->PlayableRange;
u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range); u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range);
gs_list_handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer); handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer);
SelectAnimationBlock(NewBlockHandle, State); SelectAnimationBlock(NewBlockHandle, State);
} }
@ -488,11 +493,11 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V
return BlockBounds; return BlockBounds;
} }
internal gs_list_handle internal handle
DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, handle SelectedBlockHandle, ui_interface* Interface, app_state* State)
{ {
gs_string Tempgs_string = PushString(State->Transient, 256); gs_string Tempgs_string = PushString(State->Transient, 256);
gs_list_handle Result = SelectedBlockHandle; handle Result = SelectedBlockHandle;
// TODO(pjs): Animation Selection // TODO(pjs): Animation Selection
animation CurrAnimation = AnimationSystem->Animations.Values[0]; animation CurrAnimation = AnimationSystem->Animations.Values[0];
@ -517,38 +522,35 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta
// Animation Blocks // Animation Blocks
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState); b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState);
gs_list_handle DragBlockHandle = {0}; handle DragBlockHandle = {0};
for (u32 i = 0; i < CurrAnimation.Blocks.Used; i++) for (u32 i = 0; i < CurrAnimation.Blocks_.Count; i++)
{ {
gs_list_entry<animation_block>* AnimationBlockEntry = CurrAnimation.Blocks.GetEntryAtIndex(i); animation_block* AnimationBlockAt = CurrAnimation.Blocks_.Values + i;
if (EntryIsFree(AnimationBlockEntry)) { continue; }
gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle;
animation_block AnimationBlockAt = AnimationBlockEntry->Value;
// If either end is in the range, we should draw it // If either end is in the range, we should draw it
b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Min) || b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt->Range.Min) ||
FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Max)); FrameIsInRange(AdjustedViewRange, AnimationBlockAt->Range.Max));
// If neither end is in the range, but the ends surround the visible range, // If neither end is in the range, but the ends surround the visible range,
// we should still draw it. // we should still draw it.
RangeIsVisible |= (AnimationBlockAt.Range.Min <= AdjustedViewRange.Min && RangeIsVisible |= (AnimationBlockAt->Range.Min <= AdjustedViewRange.Min &&
AnimationBlockAt.Range.Max>= AdjustedViewRange.Max); AnimationBlockAt->Range.Max>= AdjustedViewRange.Max);
if (RangeIsVisible) if (RangeIsVisible)
{ {
v4 BlockColor = BlackV4; v4 BlockColor = BlackV4;
if (GSListHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) if (SelectedBlockHandle.Index == i && SelectedBlockHandle.Generation == CurrAnimation.Blocks_.Generations[i])
{ {
BlockColor = PinkV4; BlockColor = PinkV4;
} }
rect2 BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); rect2 BlockBounds = DrawAnimationBlock(*AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer);
if (PointIsInRect(BlockBounds, Interface->Mouse.Pos)) if (PointIsInRect(BlockBounds, Interface->Mouse.Pos))
{ {
DragBlockHandle = CurrentBlockHandle; DragBlockHandle.Index = i;
DragBlockHandle.Generation = CurrAnimation.Blocks_.Generations[i];
} }
} }
} }
if (MouseDownAndNotHandled && ListHandleIsValid(DragBlockHandle)) if (MouseDownAndNotHandled && Handle_IsValid(DragBlockHandle))
{ {
MouseDownAndNotHandled = false; MouseDownAndNotHandled = false;
SelectAndBeginDragAnimationBlock(DragBlockHandle, AdjustedViewRange, TimelineBounds, State); SelectAndBeginDragAnimationBlock(DragBlockHandle, AdjustedViewRange, TimelineBounds, State);
@ -601,7 +603,7 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer*
animation_timeline_state* TimelineState = Panel_GetCurrentTypeStateMemory(Panel, animation_timeline_state); animation_timeline_state* TimelineState = Panel_GetCurrentTypeStateMemory(Panel, animation_timeline_state);
// TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state // TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state
// unless its used elsewhere. Audit later // unless its used elsewhere. Audit later
gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
ui_interface* Interface = &State->Interface; ui_interface* Interface = &State->Interface;
animation_system* AnimationSystem = &State->AnimationSystem; animation_system* AnimationSystem = &State->AnimationSystem;

View File

@ -21,6 +21,14 @@ struct animation_block
u32 Layer; u32 Layer;
}; };
struct animation_block_array
{
u32* Generations;
animation_block* Values;
u32 Count;
u32 CountMax;
};
enum blend_mode enum blend_mode
{ {
BlendMode_Overwrite, BlendMode_Overwrite,
@ -55,6 +63,7 @@ struct animation
anim_layer_array Layers; anim_layer_array Layers;
gs_list<animation_block> Blocks; gs_list<animation_block> Blocks;
animation_block_array Blocks_;
frame_range PlayableRange; frame_range PlayableRange;
}; };
@ -154,6 +163,42 @@ global gs_const_string AnimationFieldStrings[] = {
ConstString("animation_name"),// AnimField_BlockAnimName ConstString("animation_name"),// AnimField_BlockAnimName
}; };
//////////////////////////
//
// Anim Block Array
internal animation_block_array
AnimBlockArray_Create(gs_memory_arena* Storage, u32 CountMax)
{
animation_block_array Result = {0};
Result.CountMax = CountMax;
Result.Values = PushArray(Storage, animation_block, Result.CountMax);
Result.Generations = PushArray(Storage, u32, Result.CountMax);
return Result;
}
internal handle
AnimBlockArray_Push(animation_block_array* Array, animation_block Value)
{
Assert(Array->Count < Array->CountMax);
handle Result = {0};
Result.Index = Array->Count++;
// NOTE(pjs): pre-increment so that generation 0 is always invalid
Result.Generation = ++Array->Generations[Result.Index];
Array->Values[Result.Index] = Value;
return Result;
}
internal void
AnimBlockArray_Remove(animation_block_array* Array, handle Handle)
{
Assert(Handle.Index < Array->Count);
Assert(Handle_IsValid(Handle));
Array->Generations[Handle.Index]++;
}
////////////////////////// //////////////////////////
// //
// Anim Layers Array // Anim Layers Array
@ -176,7 +221,7 @@ AnimLayerArray_Push(anim_layer_array* Array, anim_layer Value)
return Index; return Index;
} }
internal u32 internal void
AnimLayerArray_Remove(anim_layer_array* Array, u32 Index) AnimLayerArray_Remove(anim_layer_array* Array, u32 Index)
{ {
Assert(Index < Array->Count); Assert(Index < Array->Count);
@ -249,6 +294,41 @@ Animation_RemoveLayer (animation* Animation, u32 LayerIndex)
} }
} }
internal handle
Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex)
{
Assert(LayerIndex < Animation->Layers.Count);
animation_block NewBlock = {0};
NewBlock.Range.Min = StartFrame;
NewBlock.Range.Max = EndFrame;
NewBlock.AnimationProcHandle = AnimationProcHandle;
NewBlock.Layer = LayerIndex;
handle Handle = AnimBlockArray_Push(&Animation->Blocks_, NewBlock);
return Handle;
}
internal void
Animation_RemoveBlock(animation* Animation, handle AnimHandle)
{
AnimBlockArray_Remove(&Animation->Blocks_, AnimHandle);
}
internal animation_block*
Animation_GetBlockFromHandle(animation* Animation, handle AnimHandle)
{
animation_block* Result = 0;
if (AnimHandle.Generation != 0 &&
Animation->Blocks_.Generations[AnimHandle.Index] == AnimHandle.Generation)
{
Result = Animation->Blocks_.Values + AnimHandle.Index;
}
return Result;
}
////////////////////////// //////////////////////////
// //
// //
@ -306,28 +386,6 @@ ClampFrameToRange(s32 Frame, frame_range Range)
// Blocks // Blocks
internal gs_list_handle
Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex)
{
Assert(LayerIndex < Animation->Layers.Count);
animation_block NewBlock = {0};
NewBlock.Range.Min = StartFrame;
NewBlock.Range.Max = EndFrame;
NewBlock.AnimationProcHandle = AnimationProcHandle;
NewBlock.Layer = LayerIndex;
gs_list_handle Result = Animation->Blocks.PushElementOnList(NewBlock);
return Result;
}
internal void
Animation_RemoveBlock(animation* Animation, gs_list_handle AnimationBlockHandle)
{
Assert(ListHandleIsValid(AnimationBlockHandle));
Animation->Blocks.FreeElementWithHandle(AnimationBlockHandle);
}
// Layers // Layers
// System // System

View File

@ -145,8 +145,8 @@ INITIALIZE_APPLICATION(InitializeApplication)
animation Anim = {0}; animation Anim = {0};
Anim.Name = PushStringF(&State->Permanent, 256, "test_anim_one"); Anim.Name = PushStringF(&State->Permanent, 256, "test_anim_one");
Anim.Layers.CountMax = 8; Anim.Layers = AnimLayerArray_Create(State->AnimationSystem.Storage, 8);
Anim.Layers.Values = PushArray(State->AnimationSystem.Storage, anim_layer, Anim.Layers.CountMax); Anim.Blocks_ = AnimBlockArray_Create(State->AnimationSystem.Storage, 8);
Anim.PlayableRange.Min = 0; Anim.PlayableRange.Min = 0;
Anim.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); Anim.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
Animation_AddLayer(&Anim, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem); Animation_AddLayer(&Anim, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
@ -258,7 +258,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
} }
s32 CurrentFrame = State->AnimationSystem.CurrentFrame; s32 CurrentFrame = State->AnimationSystem.CurrentFrame;
if (true || CurrentFrame != State->AnimationSystem.LastUpdatedFrame) if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame)
{ {
State->AnimationSystem.LastUpdatedFrame = CurrentFrame; State->AnimationSystem.LastUpdatedFrame = CurrentFrame;
r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame;

View File

@ -64,7 +64,7 @@ struct app_state
camera Camera; // TODO(Peter): move into the sculpture view camera Camera; // TODO(Peter): move into the sculpture view
r32 PixelsToWorldScale; r32 PixelsToWorldScale;
gs_list_handle SelectedAnimationBlockHandle; // TODO(Peter): move into animation panel handle SelectedAnimationBlockHandle; // TODO(Peter): move into animation panel
u32 SelectedAnimationLayer; // TODO(Peter): move into animation panel u32 SelectedAnimationLayer; // TODO(Peter): move into animation panel
}; };

View File

@ -12,21 +12,24 @@
#include "..\gs_libs\gs_types.h" #include "..\gs_libs\gs_types.h"
#include "..\gs_libs\gs_types.cpp" #include "..\gs_libs\gs_types.cpp"
//#define GS_LANGUAGE_NO_PROFILER_DEFINES struct handle
//#include "..\gs_libs\gs_language.h" {
u32 Generation;
u32 Index;
};
inline bool
Handle_IsValid(handle Handle)
{
bool Result = (Handle.Generation != 0);
return Result;
}
//#include "..\gs_libs\gs_radix_sort.h"
#include "..\gs_libs\gs_list.h" #include "..\gs_libs\gs_list.h"
#include "..\gs_libs\gs_bucket.h" #include "..\gs_libs\gs_bucket.h"
//#define GS_MEMORY_TRACK_ALLOCATIONS
//#include "..\gs_libs\gs_memory_arena.h"
#include "..\gs_libs\gs_string.h" #include "..\gs_libs\gs_string.h"
#include "foldhaus_debug.h" #include "foldhaus_debug.h"
global debug_services* GlobalDebugServices; global debug_services* GlobalDebugServices;