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;
}
internal gs_list_handle
internal handle
AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 LayerHandle, animation_system* System)
{
u32 NewBlockStart = System->CurrentFrame;
u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System);
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
gs_list_handle Result = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle);
return Result;
handle AnimHandle = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle);
return AnimHandle;
}
internal void
SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State)
SelectAnimationBlock(handle BlockHandle, app_state* State)
{
State->SelectedAnimationBlockHandle = BlockHandle;
}
@ -57,11 +57,16 @@ DeselectCurrentAnimationBlock(app_state* State)
FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand)
{
if(ListHandleIsValid(State->SelectedAnimationBlockHandle))
{
handle SelectedAnimHandle = State->SelectedAnimationBlockHandle;
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem);
if(SelectedAnimHandle.Index < ActiveAnim->Blocks_.Count &&
ActiveAnim->Blocks_.Generations[SelectedAnimHandle.Index] == SelectedAnimHandle.Generation)
{
Animation_RemoveBlock(ActiveAnim, State->SelectedAnimationBlockHandle);
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);
s32 FrameOffset = (s32)FrameAtMouseX - (s32)FrameAtMouseDownX;
animation_block* AnimationBlock = ActiveAnim->Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle);
animation_block* AnimationBlock = Animation_GetBlockFromHandle(ActiveAnim, State->SelectedAnimationBlockHandle);
if (!AnimationBlock)
{
EndCurrentOperationMode(State, {}, Mouse, Context);
@ -243,7 +248,7 @@ input_command DragAnimationClipCommands [] = {
};
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);
@ -256,7 +261,7 @@ SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range Visible
OpState->TimelineBounds = TimelineBounds;
OpState->VisibleRange = VisibleRange;
animation_block* SelectedBlock = ActiveAnim->Blocks.GetElementWithHandle(BlockHandle);
animation_block* SelectedBlock = Animation_GetBlockFromHandle(ActiveAnim, BlockHandle);
OpState->ClipRange = SelectedBlock->Range;
}
// -------------------
@ -269,7 +274,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand)
frame_range Range = ActiveAnim->PlayableRange;
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);
}
@ -488,11 +493,11 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V
return BlockBounds;
}
internal gs_list_handle
DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State)
internal handle
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_list_handle Result = SelectedBlockHandle;
handle Result = SelectedBlockHandle;
// TODO(pjs): Animation Selection
animation CurrAnimation = AnimationSystem->Animations.Values[0];
@ -517,38 +522,35 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta
// Animation Blocks
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState);
gs_list_handle DragBlockHandle = {0};
for (u32 i = 0; i < CurrAnimation.Blocks.Used; i++)
handle DragBlockHandle = {0};
for (u32 i = 0; i < CurrAnimation.Blocks_.Count; i++)
{
gs_list_entry<animation_block>* AnimationBlockEntry = CurrAnimation.Blocks.GetEntryAtIndex(i);
if (EntryIsFree(AnimationBlockEntry)) { continue; }
gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle;
animation_block AnimationBlockAt = AnimationBlockEntry->Value;
animation_block* AnimationBlockAt = CurrAnimation.Blocks_.Values + i;
// If either end is in the range, we should draw it
b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Min) ||
FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Max));
b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt->Range.Min) ||
FrameIsInRange(AdjustedViewRange, AnimationBlockAt->Range.Max));
// If neither end is in the range, but the ends surround the visible range,
// we should still draw it.
RangeIsVisible |= (AnimationBlockAt.Range.Min <= AdjustedViewRange.Min &&
AnimationBlockAt.Range.Max>= AdjustedViewRange.Max);
RangeIsVisible |= (AnimationBlockAt->Range.Min <= AdjustedViewRange.Min &&
AnimationBlockAt->Range.Max>= AdjustedViewRange.Max);
if (RangeIsVisible)
{
v4 BlockColor = BlackV4;
if (GSListHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle))
if (SelectedBlockHandle.Index == i && SelectedBlockHandle.Generation == CurrAnimation.Blocks_.Generations[i])
{
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))
{
DragBlockHandle = CurrentBlockHandle;
DragBlockHandle.Index = i;
DragBlockHandle.Generation = CurrAnimation.Blocks_.Generations[i];
}
}
}
if (MouseDownAndNotHandled && ListHandleIsValid(DragBlockHandle))
if (MouseDownAndNotHandled && Handle_IsValid(DragBlockHandle))
{
MouseDownAndNotHandled = false;
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);
// TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state
// unless its used elsewhere. Audit later
gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
ui_interface* Interface = &State->Interface;
animation_system* AnimationSystem = &State->AnimationSystem;

View File

@ -21,6 +21,14 @@ struct animation_block
u32 Layer;
};
struct animation_block_array
{
u32* Generations;
animation_block* Values;
u32 Count;
u32 CountMax;
};
enum blend_mode
{
BlendMode_Overwrite,
@ -55,6 +63,7 @@ struct animation
anim_layer_array Layers;
gs_list<animation_block> Blocks;
animation_block_array Blocks_;
frame_range PlayableRange;
};
@ -154,6 +163,42 @@ global gs_const_string AnimationFieldStrings[] = {
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
@ -176,7 +221,7 @@ AnimLayerArray_Push(anim_layer_array* Array, anim_layer Value)
return Index;
}
internal u32
internal void
AnimLayerArray_Remove(anim_layer_array* Array, u32 Index)
{
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
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
// System

View File

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

View File

@ -64,7 +64,7 @@ struct app_state
camera Camera; // TODO(Peter): move into the sculpture view
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
};

View File

@ -12,21 +12,24 @@
#include "..\gs_libs\gs_types.h"
#include "..\gs_libs\gs_types.cpp"
//#define GS_LANGUAGE_NO_PROFILER_DEFINES
//#include "..\gs_libs\gs_language.h"
struct handle
{
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_bucket.h"
//#define GS_MEMORY_TRACK_ALLOCATIONS
//#include "..\gs_libs\gs_memory_arena.h"
#include "..\gs_libs\gs_string.h"
#include "foldhaus_debug.h"
global debug_services* GlobalDebugServices;