From 8eb3044422bf393addd70eb531dd5181b20c13e1 Mon Sep 17 00:00:00 2001 From: PS Date: Sun, 18 Oct 2020 13:57:04 -0700 Subject: [PATCH] implemented an animation handle system for identifying animation blocks --- .../foldhaus_panel_animation_timeline.h | 60 +++++----- src/app/engine/animation/foldhaus_animation.h | 104 ++++++++++++++---- src/app/foldhaus_app.cpp | 6 +- src/app/foldhaus_app.h | 2 +- src/app/foldhaus_platform.h | 19 ++-- 5 files changed, 127 insertions(+), 64 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 5e8bddb..e242a12 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -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* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); 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* 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; diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 7650ce0..45037af 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -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 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 diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 8c028a9..744e4f1 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -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; diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index a368bf7..689f4d0 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -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 }; diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 96a7ec7..e5db04c 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -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;