diff options
Diffstat (limited to 'Runtime/mecanim/statemachine')
-rw-r--r-- | Runtime/mecanim/statemachine/statemachine.cpp | 967 | ||||
-rw-r--r-- | Runtime/mecanim/statemachine/statemachine.h | 547 |
2 files changed, 1514 insertions, 0 deletions
diff --git a/Runtime/mecanim/statemachine/statemachine.cpp b/Runtime/mecanim/statemachine/statemachine.cpp new file mode 100644 index 0000000..3bd1a25 --- /dev/null +++ b/Runtime/mecanim/statemachine/statemachine.cpp @@ -0,0 +1,967 @@ +#include "UnityPrefix.h" + + +#include "Runtime/Serialize/TransferFunctions/TransferNameConversions.h" + +#include "Runtime/Misc/BuildSettings.h" +#include "Runtime/mecanim/generic/stringtable.h" + +#include "Runtime/mecanim/statemachine/statemachine.h" + +#include "Runtime/Math/Simd/math.h" + +namespace mecanim +{ +namespace statemachine +{ + + int32_t GetStateIndex(StateMachineConstant const* apStateMachineConstant, uint32_t id) + { + for(uint32_t i=0;i<apStateMachineConstant->m_StateConstantCount;++i) + { + if (CompareStateID (apStateMachineConstant->m_StateConstantArray[i].Get(), id)) + return i; + } + return -1; + } + + + + TransitionConstant const* GetTransitionConstant(StateMachineConstant const* apStateMachineConstant, StateConstant const* apStateConstant, uint32_t id) + { + if( id >= s_DynamicTransitionEncodeKey) + return 0; + else if( id >= s_AnyTransitionEncodeKey) + return apStateMachineConstant->m_AnyStateTransitionConstantArray[id-s_AnyTransitionEncodeKey].Get(); + else + return apStateConstant->m_TransitionConstantArray[id].Get(); + } + + + bool IsCurrentTransitionAtomic(StateMachineConstant const* apStateMachineConstant, StateMachineMemory *apStateMachineMemory) + { + TransitionConstant const* transition = GetTransitionConstant(apStateMachineConstant, apStateMachineConstant->m_StateConstantArray[apStateMachineMemory->m_CurrentStateIndex].Get(), apStateMachineMemory->m_TransitionId); + return transition->m_Atomic; + } + + TransitionWorkspace* GetTransitionWorkspace(StateMachineWorkspace const* apStateMachineWorkspace, StateWorkspace const* apStateWorkspace, uint32_t id) + { + if( id > s_AnyTransitionEncodeKey) + return apStateMachineWorkspace->m_AnyStateTransitionWorkspaceArray[id-s_AnyTransitionEncodeKey]; + + else + return apStateWorkspace->m_TransitionWorkspaceArray[id]; + } + + TransitionConstant *CreateTransitionConstant(ConditionConstant** apConditionsConstantArray, uint32_t aConditionConstantCount, + uint32_t aDestinationState,float aTransitionDuration, float aTransitionOffset, bool aAtomic, uint32_t aID, uint32_t aUserID, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(TransitionConstant); + + TransitionConstant * transitionConstant = arAlloc.Construct<TransitionConstant >(); + transitionConstant->m_ConditionConstantArray = arAlloc.ConstructArray< OffsetPtr<ConditionConstant> >(aConditionConstantCount); + transitionConstant->m_ConditionConstantCount = aConditionConstantCount; + + transitionConstant->m_TransitionDuration = aTransitionDuration; + transitionConstant->m_TransitionOffset = aTransitionOffset; + transitionConstant->m_Atomic = aAtomic; + transitionConstant->m_ID = aID; + transitionConstant->m_UserID= aUserID; + + + transitionConstant->m_DestinationState = aDestinationState; + + + uint32_t i; + for(i=0;i<aConditionConstantCount;i++) + transitionConstant->m_ConditionConstantArray[i] = apConditionsConstantArray[i]; + + return transitionConstant; + } + + void DestroyTransitionConstant(TransitionConstant *apTransitionConstant, memory::Allocator& arAlloc) + { + if(apTransitionConstant) + { + arAlloc.Deallocate(apTransitionConstant->m_ConditionConstantArray); + arAlloc.Deallocate(apTransitionConstant); + } + } + + + TransitionWorkspace* CreateTransitionWorkspace(TransitionConstant const* apTransitionConstant, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(TransitionWorkspace); + TransitionWorkspace* transitionWorkspace = arAlloc.Construct<TransitionWorkspace>(); + transitionWorkspace->m_ConditionConstantCount = apTransitionConstant->m_ConditionConstantCount; + + return transitionWorkspace; + } + + void DestroyTransitionWorkspace(TransitionWorkspace* apTransitionWorkspace, memory::Allocator& arAlloc) + { + if(apTransitionWorkspace) + { + arAlloc.Deallocate(apTransitionWorkspace); + } + } + + + ConditionConstant *CreateConditionConstant( uint32_t aConditionMode, uint32_t aEventID, float aEventThreshold, float aExitTime, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(ConditionConstant); + ConditionConstant* conditionConstant = arAlloc.Construct<ConditionConstant>(); + + conditionConstant->m_ConditionMode = aConditionMode; + + if(aConditionMode == kConditionModeIf || aConditionMode == kConditionModeIfNot || aConditionMode == kConditionModeGreater || aConditionMode == kConditionModeLess || aConditionMode == kConditionModeEquals || aConditionMode == kConditionModeNotEqual) + { + conditionConstant->m_EventID = aEventID; + if(aConditionMode == kConditionModeGreater || aConditionMode == kConditionModeLess || aConditionMode == kConditionModeEquals || aConditionMode == kConditionModeNotEqual) + { + conditionConstant->m_EventThreshold = aEventThreshold; + } + } + else if(aConditionMode == kConditionModeExitTime) + { + conditionConstant->m_ExitTime = aExitTime; + } + + return conditionConstant; + } + void DestroyConditionConstant(ConditionConstant *apConditionConstant, memory::Allocator& arAlloc) + { + if(apConditionConstant) + { + arAlloc.Deallocate(apConditionConstant); + } + } + + static int GetBlendTreeIndex(const StateConstant& arStateConstant, mecanim::int32_t aMotionSetIndex) + { + return arStateConstant.m_BlendTreeConstantIndexArray[aMotionSetIndex]; + } + + animation::BlendTreeConstant const* GetBlendTreeConstant(const StateConstant& arStateConstant, mecanim::int32_t aMotionSetIndex) + { + int blendTreeIndex = GetBlendTreeIndex(arStateConstant,aMotionSetIndex); + return blendTreeIndex != -1 ? arStateConstant.m_BlendTreeConstantArray[blendTreeIndex].Get() : 0; + } + + animation::BlendTreeMemory *GetBlendTreeMemory(const StateConstant& arStateConstant,StateMemory& arStateMemory, mecanim::int32_t aMotionSetIndex) + { + int blendTreeIndex = GetBlendTreeIndex(arStateConstant,aMotionSetIndex); + return blendTreeIndex != -1 ? arStateMemory.m_BlendTreeMemoryArray[blendTreeIndex].Get() : 0; + } + + StateConstant* CreateStateConstant(TransitionConstant** apTransitionConstantArray, uint32_t aTransitionConstantCount, + float aSpeed, bool aIKOnFeet, bool aMirror, float aCycleOffset, animation::BlendTreeConstant** apBlendTreeConstantArray, + uint32_t aMotionSetCount, uint32_t nameID, uint32_t pathID, uint32_t aTagID, bool aLoop, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateConstant); + StateConstant* stateConstant = arAlloc.Construct<StateConstant>(); + + stateConstant->m_TransitionConstantCount = aTransitionConstantCount; + stateConstant->m_Speed = aSpeed; + stateConstant->m_IKOnFeet = aIKOnFeet; + stateConstant->m_Mirror = aMirror; + stateConstant->m_CycleOffset = aCycleOffset; + stateConstant->m_PathID = pathID; + stateConstant->m_NameID = nameID; + stateConstant->m_TagID = aTagID; + stateConstant->m_MotionSetCount = aMotionSetCount; + stateConstant->m_BlendTreeCount = 0 ; + stateConstant->m_Loop = aLoop; + + stateConstant->m_BlendTreeConstantIndexArray = arAlloc.ConstructArray<int32_t>(aMotionSetCount); + stateConstant->m_LeafInfoArray = arAlloc.ConstructArray<LeafInfoConstant>(aMotionSetCount); + + stateConstant->m_TransitionConstantArray = arAlloc.ConstructArray< OffsetPtr<TransitionConstant> >(aTransitionConstantCount); + + uint32_t i; + for(i = 0 ; i < aTransitionConstantCount; i++) + stateConstant->m_TransitionConstantArray[i] = apTransitionConstantArray[i]; + + for(i = 0 ; i < aMotionSetCount; i++) + { + if(apBlendTreeConstantArray[i] != 0) + { + stateConstant->m_BlendTreeConstantIndexArray[i] = stateConstant->m_BlendTreeCount ; + stateConstant->m_LeafInfoArray[i].m_Count = animation::GetLeafCount(*apBlendTreeConstantArray[i]); + stateConstant->m_LeafInfoArray[i].m_IDArray = arAlloc.ConstructArray<uint32_t>(stateConstant->m_LeafInfoArray[i].m_Count); + animation::FillLeafIDArray(*apBlendTreeConstantArray[i], stateConstant->m_LeafInfoArray[i].m_IDArray.Get()); + stateConstant->m_BlendTreeCount++; + } + else + { + stateConstant->m_BlendTreeConstantIndexArray[i] = -1; + stateConstant->m_LeafInfoArray[i].m_Count = 0; + stateConstant->m_LeafInfoArray[i].m_IDArray = 0 ; + } + + } + + stateConstant->m_BlendTreeConstantArray = arAlloc.ConstructArray< OffsetPtr<animation::BlendTreeConstant> >(stateConstant->m_BlendTreeCount); + uint32_t currentTreeCount = 0; + for(i = 0 ; i < aMotionSetCount ; i++) + { + if(apBlendTreeConstantArray[i] != 0) + { + stateConstant->m_BlendTreeConstantArray[currentTreeCount] = apBlendTreeConstantArray[i]; + currentTreeCount++; + } + } + + return stateConstant; + } + + void DestroyStateConstant(StateConstant* apStateConstant, memory::Allocator& arAlloc) + { + if(apStateConstant) + { + for(uint32_t i = 0 ; i < apStateConstant->m_MotionSetCount; i++) + { + arAlloc.Deallocate(apStateConstant->m_LeafInfoArray[i].m_IDArray); + } + arAlloc.Deallocate(apStateConstant->m_LeafInfoArray); + arAlloc.Deallocate(apStateConstant->m_BlendTreeConstantArray); + arAlloc.Deallocate(apStateConstant->m_BlendTreeConstantIndexArray); + + arAlloc.Deallocate(apStateConstant->m_TransitionConstantArray); + arAlloc.Deallocate(apStateConstant); + } + } + + StateMemory* CreateStateMemory(StateConstant const* apStateConstant, StateMachineConstant const* apParentStateMachineConstant, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateMemory); + StateMemory *stateMemory = arAlloc.Construct<StateMemory>(); + + stateMemory->m_BlendTreeCount = apStateConstant->m_BlendTreeCount; + stateMemory->m_BlendTreeMemoryArray = arAlloc.ConstructArray< OffsetPtr<animation::BlendTreeMemory> >(stateMemory->m_BlendTreeCount); + + for(int blendTreeIter = 0 ; blendTreeIter < stateMemory->m_BlendTreeCount; blendTreeIter++) + { + stateMemory->m_BlendTreeMemoryArray[blendTreeIter] = animation::CreateBlendTreeMemory(apStateConstant->m_BlendTreeConstantArray[blendTreeIter].Get(), arAlloc); + } + + return stateMemory; + } + + void DestroyStateMemory(StateMemory* apStateMemory, memory::Allocator& arAlloc) + { + if(apStateMemory) + { + for(int i = 0 ; i < apStateMemory->m_BlendTreeCount; i++) + { + arAlloc.Deallocate(apStateMemory->m_BlendTreeMemoryArray[i]); + } + + arAlloc.Deallocate(apStateMemory->m_BlendTreeMemoryArray); + arAlloc.Deallocate(apStateMemory); + } + } + + StateWorkspace* CreateStateWorkspace(StateConstant const* apStateConstant, uint32_t maxBlendedClip, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateWorkspace); + StateWorkspace* stateWorkspace = arAlloc.Construct<StateWorkspace>(); + + stateWorkspace->m_TransitionWorkspaceCount = apStateConstant->m_TransitionConstantCount; + stateWorkspace->m_TransitionWorkspaceArray = arAlloc.ConstructArray<TransitionWorkspace*>(stateWorkspace->m_TransitionWorkspaceCount); + stateWorkspace->m_BlendTreeInputArray = arAlloc.ConstructArray<animation::BlendTreeInput*>(apStateConstant->m_MotionSetCount); + stateWorkspace->m_BlendTreeOutputArray = arAlloc.ConstructArray<animation::BlendTreeOutput*>(apStateConstant->m_MotionSetCount); + stateWorkspace->m_BlendTreeWorkspaceArray = arAlloc.ConstructArray<animation::BlendTreeWorkspace*>(apStateConstant->m_MotionSetCount); + stateWorkspace->m_MotionSetCount = apStateConstant->m_MotionSetCount; + + for(uint32_t i = 0 ; i < stateWorkspace->m_TransitionWorkspaceCount ; i++) + { + stateWorkspace->m_TransitionWorkspaceArray[i] = CreateTransitionWorkspace(apStateConstant->m_TransitionConstantArray[i].Get(), arAlloc); + } + + for(uint32_t i = 0 ; i < stateWorkspace->m_MotionSetCount ; i++) + { + animation::BlendTreeConstant const *blendTreeConstant = statemachine::GetBlendTreeConstant(*apStateConstant,i); + if(blendTreeConstant != 0) + { + stateWorkspace->m_BlendTreeInputArray[i] = animation::CreateBlendTreeInput(blendTreeConstant, arAlloc); + stateWorkspace->m_BlendTreeOutputArray[i] = animation::CreateBlendTreeOutput(blendTreeConstant, maxBlendedClip, arAlloc); + stateWorkspace->m_BlendTreeWorkspaceArray[i] = animation::CreateBlendTreeWorkspace(blendTreeConstant,arAlloc); + } + else + { + stateWorkspace->m_BlendTreeInputArray[i] = 0; + stateWorkspace->m_BlendTreeOutputArray[i] = 0; + stateWorkspace->m_BlendTreeWorkspaceArray[i] = 0; + } + } + + return stateWorkspace; + } + + void DestroyStateWorkspace(StateWorkspace* apStateWorkspace, memory::Allocator& arAlloc) + { + if(apStateWorkspace) + { + + for(uint32_t i = 0 ; i < apStateWorkspace->m_TransitionWorkspaceCount; i++) + { + DestroyTransitionWorkspace(apStateWorkspace->m_TransitionWorkspaceArray[i], arAlloc); + } + for(uint32_t i = 0 ; i < apStateWorkspace->m_MotionSetCount ; i++) + { + animation::DestroyBlendTreeInput(apStateWorkspace->m_BlendTreeInputArray[i], arAlloc); + animation::DestroyBlendTreeOutput(apStateWorkspace->m_BlendTreeOutputArray[i], arAlloc); + animation::DestroyBlendTreeWorkspace(apStateWorkspace->m_BlendTreeWorkspaceArray[i], arAlloc); + } + + arAlloc.Deallocate(apStateWorkspace->m_BlendTreeInputArray); + arAlloc.Deallocate(apStateWorkspace->m_BlendTreeOutputArray); + arAlloc.Deallocate(apStateWorkspace->m_BlendTreeWorkspaceArray); + + arAlloc.Deallocate(apStateWorkspace->m_TransitionWorkspaceArray); + arAlloc.Deallocate(apStateWorkspace); + } + } + + + StateOutput* CreateStateOutput(StateConstant const* apStateConstant, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateOutput); + return arAlloc.Construct<StateOutput>(); + } + + void DestroyStateOutput(StateOutput* apStateOutput, memory::Allocator& arAlloc) + { + if(apStateOutput) + { + arAlloc.Deallocate(apStateOutput); + } + } + + StateMachineConstant* CreateStateMachineConstant(StateConstant** apStateConstantArray, uint32_t aStateConstantCount, uint32_t aDefaultState, + TransitionConstant** apAnyStateTransitionConstantArray, uint32_t aAnyStateTransitionConstantCount, uint32_t aMotionSetCount, + memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateMachineConstant); + StateMachineConstant* stateMachineConstant = arAlloc.Construct<StateMachineConstant>(); + stateMachineConstant->m_StateConstantArray = arAlloc.ConstructArray< OffsetPtr<StateConstant> >(aStateConstantCount); + stateMachineConstant->m_AnyStateTransitionConstantArray = arAlloc.ConstructArray< OffsetPtr<TransitionConstant> >(aAnyStateTransitionConstantCount); + + stateMachineConstant->m_StateConstantCount = aStateConstantCount; + stateMachineConstant->m_DefaultState = aDefaultState; + stateMachineConstant->m_AnyStateTransitionConstantCount = aAnyStateTransitionConstantCount; + stateMachineConstant->m_MotionSetCount = aMotionSetCount; + + uint32_t i; + for(i=0;i<aStateConstantCount;i++) + stateMachineConstant->m_StateConstantArray[i] = apStateConstantArray[i]; + + for(i=0;i<aAnyStateTransitionConstantCount;i++) + stateMachineConstant->m_AnyStateTransitionConstantArray[i] = apAnyStateTransitionConstantArray[i]; + + ///////////////////////////////////////////////////////// + // + uint32_t j; + for(j = 0 ; j < stateMachineConstant->m_MotionSetCount; j++) + { + uint32_t clipOffset = 0 ; + for( i = 0 ; i < aStateConstantCount; i++) + { + stateMachineConstant->m_StateConstantArray[i]->m_LeafInfoArray[j].m_IndexOffset = clipOffset; + clipOffset += stateMachineConstant->m_StateConstantArray[i]->m_LeafInfoArray[j].m_Count; + } + } + + return stateMachineConstant; + } + + void DestroyStateMachineConstant(StateMachineConstant* apStateMachineConstant, memory::Allocator& arAlloc) + { + if(apStateMachineConstant) + { + arAlloc.Deallocate(apStateMachineConstant->m_AnyStateTransitionConstantArray); + arAlloc.Deallocate(apStateMachineConstant->m_StateConstantArray); + + arAlloc.Deallocate(apStateMachineConstant); + } + } + + StateMachineInput* CreateStateMachineInput(StateMachineConstant const* apStateMachineConstant, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateMachineInput); + StateMachineInput* stateMachineInput = arAlloc.Construct<StateMachineInput>(); + return stateMachineInput; + } + + void DestroyStateMachineInput(StateMachineInput* apStateMachineInput, memory::Allocator& arAlloc) + { + if(apStateMachineInput) + { + arAlloc.Deallocate(apStateMachineInput); + } + } + + StateMachineMemory* CreateStateMachineMemory(StateMachineConstant const* apStateMachineConstant, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateMachineMemory); + StateMachineMemory* stateMachineMemory = arAlloc.Construct<StateMachineMemory>(); + stateMachineMemory->m_CurrentStateIndex = apStateMachineConstant->m_DefaultState; + stateMachineMemory->m_StateMemoryCount = apStateMachineConstant->m_StateConstantCount; + stateMachineMemory->m_StateMemoryArray = arAlloc.ConstructArray< OffsetPtr<StateMemory> >(stateMachineMemory->m_StateMemoryCount); + + stateMachineMemory->m_MotionSetAutoWeightArray = arAlloc.ConstructArray<float>(apStateMachineConstant->m_MotionSetCount); + + stateMachineMemory->m_MotionSetCount = apStateMachineConstant->m_MotionSetCount; + + for( uint32_t i = 0 ; i < stateMachineMemory->m_StateMemoryCount; i++) + { + stateMachineMemory->m_StateMemoryArray[i] = CreateStateMemory(apStateMachineConstant->m_StateConstantArray[i].Get(), apStateMachineConstant, arAlloc); + + if(stateMachineMemory->m_StateMemoryArray[i].IsNull()) + { + DestroyStateMachineMemory(stateMachineMemory, arAlloc); + return 0; + } + } + return stateMachineMemory; + } + + void DestroyStateMachineMemory(StateMachineMemory* apStateMachineMemory, memory::Allocator& arAlloc) + { + if(apStateMachineMemory) + { + for(uint32_t i = 0 ; i < apStateMachineMemory->m_StateMemoryCount ; i++) + { + DestroyStateMemory(apStateMachineMemory->m_StateMemoryArray[i].Get(), arAlloc); + } + + arAlloc.Deallocate(apStateMachineMemory->m_MotionSetAutoWeightArray); + arAlloc.Deallocate(apStateMachineMemory->m_StateMemoryArray); + arAlloc.Deallocate(apStateMachineMemory); + } + } + + + StateMachineWorkspace* CreateStateMachineWorkspace(StateMachineConstant const* apStateMachineConstant, uint32_t maxBlendState, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateMachineWorkspace); + StateMachineWorkspace* stateMachineWorkspace = arAlloc.Construct<StateMachineWorkspace>(); + + stateMachineWorkspace->m_StateWorkspaceCount = apStateMachineConstant->m_StateConstantCount; + stateMachineWorkspace->m_StateWorkspaceArray = arAlloc.ConstructArray<StateWorkspace*>(stateMachineWorkspace->m_StateWorkspaceCount); + memset(&stateMachineWorkspace->m_StateWorkspaceArray[0], 0, sizeof(StateWorkspace*)*stateMachineWorkspace->m_StateWorkspaceCount); + + for( uint32_t i = 0 ; i < stateMachineWorkspace->m_StateWorkspaceCount; i++) + { + stateMachineWorkspace->m_StateWorkspaceArray[i] = CreateStateWorkspace(apStateMachineConstant->m_StateConstantArray[i].Get(), maxBlendState, arAlloc); + if(stateMachineWorkspace->m_StateWorkspaceArray[i] == 0) + { + DestroyStateMachineWorkspace(stateMachineWorkspace, arAlloc); + return 0; + } + } + + + stateMachineWorkspace->m_AnyStateTransitionWorkspaceCount = apStateMachineConstant->m_AnyStateTransitionConstantCount; + stateMachineWorkspace->m_AnyStateTransitionWorkspaceArray = arAlloc.ConstructArray<TransitionWorkspace*>(stateMachineWorkspace->m_AnyStateTransitionWorkspaceCount); + for( uint32_t i = 0 ; i < stateMachineWorkspace->m_AnyStateTransitionWorkspaceCount; i++) + { + stateMachineWorkspace->m_AnyStateTransitionWorkspaceArray[i] = CreateTransitionWorkspace(apStateMachineConstant->m_AnyStateTransitionConstantArray[i].Get(), arAlloc); + } + + return stateMachineWorkspace; + + } + + void DestroyStateMachineWorkspace(StateMachineWorkspace* apStateMachineWorkspace, memory::Allocator& arAlloc) + { + if(apStateMachineWorkspace) + { + for(uint32_t i = 0 ; i < apStateMachineWorkspace->m_StateWorkspaceCount; i++) + { + DestroyStateWorkspace(apStateMachineWorkspace->m_StateWorkspaceArray[i], arAlloc); + } + + for(uint32_t i = 0 ; i < apStateMachineWorkspace->m_AnyStateTransitionWorkspaceCount ; i++) + { + DestroyTransitionWorkspace(apStateMachineWorkspace->m_AnyStateTransitionWorkspaceArray[i], arAlloc); + } + + arAlloc.Deallocate(apStateMachineWorkspace->m_StateWorkspaceArray); + arAlloc.Deallocate(apStateMachineWorkspace->m_AnyStateTransitionWorkspaceArray); + arAlloc.Deallocate(apStateMachineWorkspace); + } + } + + StateMachineOutput* CreateStateMachineOutput(StateMachineConstant const* apStateMachineConstant, uint32_t maxBlendedClip, memory::Allocator& arAlloc) + { + SETPROFILERLABEL(StateMachineOutput); + StateMachineOutput* stateMachineOutput = arAlloc.Construct<StateMachineOutput>(); + stateMachineOutput->m_MotionSetCount = apStateMachineConstant->m_MotionSetCount; + stateMachineOutput->m_Left.m_BlendNodeLayer = arAlloc.ConstructArray<BlendNodeLayer>(apStateMachineConstant->m_MotionSetCount); + stateMachineOutput->m_Right.m_BlendNodeLayer = arAlloc.ConstructArray<BlendNodeLayer>(apStateMachineConstant->m_MotionSetCount); + + for(int i=0;i<apStateMachineConstant->m_MotionSetCount;i++) + { + stateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputBlendArray = arAlloc.ConstructArray<float>(maxBlendedClip); + stateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputIndexArray = arAlloc.ConstructArray<uint32_t>(maxBlendedClip); + stateMachineOutput->m_Left.m_BlendNodeLayer[i].m_ReverseArray = arAlloc.ConstructArray<bool>(maxBlendedClip); + stateMachineOutput->m_Left.m_BlendNodeLayer[i].m_MirrorArray = arAlloc.ConstructArray<bool>(maxBlendedClip); + stateMachineOutput->m_Left.m_BlendNodeLayer[i].m_CycleOffsetArray = arAlloc.ConstructArray<float>(maxBlendedClip); + + stateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputBlendArray = arAlloc.ConstructArray<float>(maxBlendedClip); + stateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputIndexArray = arAlloc.ConstructArray<uint32_t>(maxBlendedClip); + stateMachineOutput->m_Right.m_BlendNodeLayer[i].m_ReverseArray = arAlloc.ConstructArray<bool>(maxBlendedClip); + stateMachineOutput->m_Right.m_BlendNodeLayer[i].m_MirrorArray = arAlloc.ConstructArray<bool>(maxBlendedClip); + stateMachineOutput->m_Right.m_BlendNodeLayer[i].m_CycleOffsetArray = arAlloc.ConstructArray<float>(maxBlendedClip); + } + + return stateMachineOutput; + } + + void DestroyStateMachineOutput(StateMachineOutput* apStateMachineOutput, memory::Allocator& arAlloc) + { + if(apStateMachineOutput) + { + for(int i=0;i<apStateMachineOutput->m_MotionSetCount;i++) + { + arAlloc.Deallocate(apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputBlendArray); + arAlloc.Deallocate(apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputIndexArray); + arAlloc.Deallocate(apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_ReverseArray); + arAlloc.Deallocate(apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_MirrorArray); + arAlloc.Deallocate(apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_CycleOffsetArray); + + arAlloc.Deallocate(apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputBlendArray); + arAlloc.Deallocate(apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputIndexArray); + arAlloc.Deallocate(apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_ReverseArray); + arAlloc.Deallocate(apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_MirrorArray); + arAlloc.Deallocate(apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_CycleOffsetArray); + } + + arAlloc.Deallocate(apStateMachineOutput->m_Left.m_BlendNodeLayer); + arAlloc.Deallocate(apStateMachineOutput->m_Right.m_BlendNodeLayer); + arAlloc.Deallocate(apStateMachineOutput); + } + } + + float DoBlendTreeEvaluation( const StateConstant& arStateConstant, StateOutput& arStateOutput, StateMemory& arStateMemory, StateWorkspace& arStateWorkspace, const ValueArrayConstant& arValues, const StateMachineInput& arStateMachineInput, int blendTreeIndex, float weight) + { + float duration = 0 ; + for(uint32_t i = 0 ; i < arStateConstant.m_MotionSetCount ; i++) + { + animation::BlendTreeConstant const* treeConstant = statemachine::GetBlendTreeConstant(arStateConstant, i); + animation::BlendTreeMemory const *treeMemory = statemachine::GetBlendTreeMemory(arStateConstant,arStateMemory, i); + + if(treeConstant) + { + if(!treeConstant->m_BlendEventArrayConstant.IsNull()) + { + for(uint32_t k = 0 ; k < treeConstant->m_BlendEventArrayConstant->m_Count ; k++) + { + float blendValue = 0.0f; + int32_t index = FindValueIndex(&arValues, treeConstant->m_BlendEventArrayConstant->m_ValueArray[k].m_ID); + if(index >=0) + { + arStateMachineInput.m_Values->ReadData(blendValue, arValues.m_ValueArray[index].m_Index); + } + arStateWorkspace.m_BlendTreeInputArray[i]->m_BlendValueArray->WriteData(blendValue, treeConstant->m_BlendEventArrayConstant->m_ValueArray[k].m_Index); + } + } + + animation::EvaluateBlendTree(*treeConstant, *arStateWorkspace.m_BlendTreeInputArray[i], *treeMemory, *arStateWorkspace.m_BlendTreeOutputArray[i], *arStateWorkspace.m_BlendTreeWorkspaceArray[i]); + + uint32_t index = 0 ; + uint32_t leafIndex = 0; + while(index < arStateWorkspace.m_BlendTreeOutputArray[i]->m_MaxBlendedClip && arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_ID != -1) + { + arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputBlendArray[arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount] = weight*arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_BlendValue; + + arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_ReverseArray[arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount] = ( arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_Reverse && arStateConstant.m_Speed >= 0) || + ( !arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_Reverse && arStateConstant.m_Speed < 0); + + arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_MirrorArray[arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount] = ( arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_Mirror || arStateConstant.m_Mirror) && + !(arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_Mirror && arStateConstant.m_Mirror); + + arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_CycleOffsetArray[arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount] = arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_CycleOffset + arStateConstant.m_CycleOffset; + + for( ; leafIndex< arStateConstant.m_LeafInfoArray[i].m_Count ; leafIndex++) + { + /// match leaf ID + if(arStateWorkspace.m_BlendTreeOutputArray[i]->m_OutputBlendArray[index].m_ID == arStateConstant.m_LeafInfoArray[i].m_IDArray[leafIndex]) + { + arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputIndexArray[arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount] = leafIndex + arStateConstant.m_LeafInfoArray[i].m_IndexOffset; + arStateOutput.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount++; + leafIndex++; + break; + } + } + + index++; + } + + // sync layers affect timing + float effectiveDurationWeight = 1 ; + for(int index = arStateConstant.m_MotionSetCount - 1 ; index >= (int)i+1; --index) + { + if(statemachine::GetBlendTreeConstant(arStateConstant, index)) // if has motion + effectiveDurationWeight -= (effectiveDurationWeight*arStateMachineInput.m_MotionSetTimingWeightArray[index]); + } + + duration += arStateWorkspace.m_BlendTreeOutputArray[i]->m_Duration*arStateMachineInput.m_MotionSetTimingWeightArray[i]*effectiveDurationWeight; + + + } + } + + return duration; + } + + void EvaluateState( ValueArrayConstant const* apValues, + StateConstant const *apStateConstant, + StateMachineInput const* apStateMachineInput, + StateMachineMemory* apStateMachineMemory, + StateOutput *apStateOutput, + StateMemory *apStateMemory, + StateWorkspace *apStateWorkspace) + { + for(int i = 0 ; i < apStateConstant->m_MotionSetCount ; i++) + { + apStateOutput->m_BlendNode->m_BlendNodeLayer[i].m_OutputCount = 0; + } + + apStateOutput->m_BlendNode->m_IKOnFeet = apStateConstant->m_IKOnFeet; + + float deltaTime = apStateMachineInput->m_DeltaTime; + + float speed = IS_CONTENT_NEWER_OR_SAME(kUnityVersion4_2_a1) ? math::abs(apStateConstant->m_Speed) : 1.f; + + apStateOutput->m_StateDuration = DoBlendTreeEvaluation( *apStateConstant, *apStateOutput, *apStateMemory, *apStateWorkspace, *apValues, *apStateMachineInput, 0, 1.f) / speed; + + if( apStateOutput->m_StateDuration != 0) + { + deltaTime /= apStateOutput->m_StateDuration; + } + + if(apStateMachineMemory->m_ActiveGotoState && apStateMachineInput->m_GotoStateInfo->m_StateID == 0) + { + apStateOutput->m_BlendNode->m_CurrentTime = apStateMachineInput->m_GotoStateInfo->m_NormalizedTime + (apStateMachineInput->m_GotoStateInfo->m_DenormalizedTimeOffset/apStateOutput->m_StateDuration); + apStateOutput->m_BlendNode->m_PreviousTime = apStateMachineInput->m_GotoStateInfo->m_NormalizedTime - deltaTime; + apStateMachineMemory->m_ActiveGotoState = false; + apStateMachineInput->m_GotoStateInfo->m_DenormalizedTimeOffset = 0.0f; + } + else + { + apStateOutput->m_BlendNode->m_CurrentTime = apStateMemory->m_PreviousTime + deltaTime; + apStateOutput->m_BlendNode->m_PreviousTime = apStateMemory->m_PreviousTime ; + } + + apStateMemory->m_PreviousTime = apStateOutput->m_BlendNode->m_CurrentTime; + apStateMemory->m_Duration = apStateOutput->m_StateDuration; + } + + void EvaluateTransition ( TransitionConstant const* apTransitionConstant, TransitionInput const *apTransitionInput, TransitionOutput * apTransitionOutput, TransitionMemory const* apTransitionMemory, TransitionWorkspace const* apTransitionWorkspace) + { + apTransitionOutput->m_DoTransition = apTransitionConstant->m_ConditionConstantCount > 0; + apTransitionOutput->m_TransitionDuration = apTransitionConstant->m_TransitionDuration; + apTransitionOutput->m_TransitionOffset = apTransitionConstant->m_TransitionOffset; + apTransitionOutput->m_TransitionStartTime = 0.0f; + apTransitionOutput->m_NextStateStartTime = apTransitionConstant->m_TransitionOffset; + + + for( uint32_t conditionIndex = 0 ; apTransitionOutput->m_DoTransition && conditionIndex < apTransitionConstant->m_ConditionConstantCount ; conditionIndex++) + { + apTransitionOutput->m_DoTransition = false; + const ConditionConstant* currentCondition = apTransitionConstant->m_ConditionConstantArray[conditionIndex].Get(); + + if( currentCondition->m_ConditionMode == kConditionModeIf || + currentCondition->m_ConditionMode == kConditionModeIfNot || + currentCondition->m_ConditionMode == kConditionModeGreater || + currentCondition->m_ConditionMode == kConditionModeLess || + currentCondition->m_ConditionMode == kConditionModeEquals || + currentCondition->m_ConditionMode == kConditionModeNotEqual) + { + int32_t index = FindValueIndex(apTransitionMemory->m_ValuesConstant, currentCondition->m_EventID); + + if(index > -1) + { + ValueConstant const& valueConstant = apTransitionMemory->m_ValuesConstant->m_ValueArray[index]; + if(currentCondition->m_ConditionMode == kConditionModeIf || currentCondition->m_ConditionMode == kConditionModeIfNot) + { + bool booleanEvent; + apTransitionInput->m_Values->ReadData(booleanEvent, valueConstant.m_Index); + apTransitionOutput->m_DoTransition = currentCondition->m_ConditionMode == kConditionModeIf ? booleanEvent : !booleanEvent; + } + else if (currentCondition->m_ConditionMode == kConditionModeEquals || currentCondition->m_ConditionMode == kConditionModeNotEqual) + { + mecanim::int32_t intEvent; + apTransitionInput->m_Values->ReadData(intEvent, valueConstant.m_Index); + apTransitionOutput->m_DoTransition = currentCondition->m_ConditionMode == kConditionModeEquals ? intEvent == currentCondition->m_EventThreshold : intEvent != currentCondition->m_EventThreshold; + } + else + { + if(valueConstant.m_Type == mecanim::kFloatType) + { + float floatEvent; + apTransitionInput->m_Values->ReadData(floatEvent, valueConstant.m_Index); + apTransitionOutput->m_DoTransition = currentCondition->m_ConditionMode == kConditionModeGreater ? floatEvent > currentCondition->m_EventThreshold : floatEvent < currentCondition->m_EventThreshold; + } + else if(valueConstant.m_Type == mecanim::kInt32Type) + { + mecanim::int32_t intEvent; + apTransitionInput->m_Values->ReadData(intEvent, valueConstant.m_Index); + apTransitionOutput->m_DoTransition = currentCondition->m_ConditionMode == kConditionModeGreater ? intEvent > currentCondition->m_EventThreshold : intEvent < currentCondition->m_EventThreshold; + } + + } + } + } + else if(currentCondition->m_ConditionMode == kConditionModeExitTime) + { + float relativeTimeError = 0; + if(currentCondition->m_ExitTime <= 1) + { + float previousTimeLow = math::fmod(apTransitionInput->m_PreviousTime,1); + float currentTimeLow = math::fmod(apTransitionInput->m_CurrentTime,1); + + float previousTimeHigh = previousTimeLow; + float currentTimeHigh = currentTimeLow; + + if(previousTimeLow > currentTimeLow) + { + previousTimeLow -= 1; + currentTimeHigh += 1; + } + + if(previousTimeLow < currentCondition->m_ExitTime && currentTimeLow >= currentCondition->m_ExitTime) + { + apTransitionOutput->m_DoTransition = true; + relativeTimeError = (currentTimeLow - currentCondition->m_ExitTime); + } + else if(previousTimeHigh < currentCondition->m_ExitTime && currentTimeHigh >= currentCondition->m_ExitTime) + { + apTransitionOutput->m_DoTransition = true; + relativeTimeError = (currentTimeHigh - currentCondition->m_ExitTime); + } + } + else if ( apTransitionInput->m_PreviousTime < currentCondition->m_ExitTime && apTransitionInput->m_CurrentTime >= currentCondition->m_ExitTime) + { + apTransitionOutput->m_DoTransition = true; + relativeTimeError = (apTransitionInput->m_CurrentTime - currentCondition->m_ExitTime); + } + + if(apTransitionOutput->m_DoTransition) + { + apTransitionOutput->m_TransitionStartTime = apTransitionOutput->m_TransitionDuration == 0 ? 1 : (relativeTimeError / apTransitionOutput->m_TransitionDuration); + apTransitionOutput->m_NextStateStartTime = apTransitionOutput->m_TransitionOffset; + apTransitionOutput->m_NextStateStartInitialDeltaTime = relativeTimeError; // this is in source state normalized time + } + } + } + + } + + void EvaluateStateMachine( StateMachineConstant const* apStateMachineConstant, + StateMachineInput const* apStateMachineInput, + StateMachineOutput * apStateMachineOutput, + StateMachineMemory * apStateMachineMemory, + StateMachineWorkspace * apStateMachineWorkspace) + { + + /// Initialize workspace values + apStateMachineOutput->m_BlendFactor = 0; + for(uint32_t i = 0 ; i < apStateMachineConstant->m_MotionSetCount; i++) + { + apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputCount = 0; + apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputCount = 0; + } + + if(apStateMachineConstant->m_StateConstantCount == 0) + { + for(int i = 0 ; i < apStateMachineConstant->m_MotionSetCount; i++) + apStateMachineMemory->m_MotionSetAutoWeightArray[i] = 0; + return ; + } + + float deltaTime = apStateMachineInput->m_DeltaTime; + + const uint32_t currentStateIndex = apStateMachineMemory->m_CurrentStateIndex; + const StateConstant* currentState = apStateMachineConstant->m_StateConstantArray[currentStateIndex].Get(); + StateMemory* currentStateMemory = apStateMachineMemory->m_StateMemoryArray[currentStateIndex].Get(); + StateWorkspace* currentStateWS = apStateMachineWorkspace->m_StateWorkspaceArray[currentStateIndex]; + + StateOutput outputSrc; + outputSrc.m_BlendNode = &apStateMachineOutput->m_Left; + EvaluateState(apStateMachineWorkspace->m_ValuesConstant, currentState, apStateMachineInput, apStateMachineMemory, &outputSrc, currentStateMemory, currentStateWS); + + TransitionInput transitionInput; + transitionInput.m_Values = apStateMachineInput->m_Values; + transitionInput.m_CurrentStatePreviousTime = currentStateMemory->m_PreviousTime; + transitionInput.m_CurrentStateDuration = outputSrc.m_StateDuration; + transitionInput.m_CurrentTime = outputSrc.m_BlendNode->m_CurrentTime; + transitionInput.m_PreviousTime = outputSrc.m_BlendNode->m_PreviousTime; + + TransitionOutput transitionOutput; + + TransitionMemory transitionMemory; + transitionMemory.m_ValuesConstant = apStateMachineWorkspace->m_ValuesConstant; + + bool startTransition = false; + bool wasInTransition = apStateMachineMemory->m_InTransition ; + + const TransitionConstant* currentTransition = wasInTransition ? GetTransitionConstant(apStateMachineConstant, apStateMachineConstant->m_StateConstantArray[apStateMachineMemory->m_CurrentStateIndex].Get(), apStateMachineMemory->m_TransitionId) : 0; + bool isCurrentTransitionAnyState = apStateMachineMemory->m_TransitionId >= s_AnyTransitionEncodeKey; + + for(int i = 0 ; i < apStateMachineConstant->m_MotionSetCount; i++) + apStateMachineMemory->m_MotionSetAutoWeightArray[i] = outputSrc.m_BlendNode->m_BlendNodeLayer[i].m_OutputCount ? 1 : 0; + + //////////////////////////////////////////////////////// + // Validate if we need to transition + if(apStateMachineMemory->m_ActiveGotoState) + { + int32_t nextState = GetStateIndex(apStateMachineConstant, apStateMachineInput->m_GotoStateInfo->m_StateID); + if(nextState != -1) + { + startTransition = true; + + apStateMachineMemory->m_ActiveGotoState = false; + + apStateMachineMemory->m_InTransition = true; + apStateMachineMemory->m_NextStateIndex = nextState; + apStateMachineMemory->m_TransitionId = s_DynamicTransitionEncodeKey; + apStateMachineMemory->m_TransitionDuration = apStateMachineInput->m_GotoStateInfo->m_TransitionDuration; + apStateMachineMemory->m_TransitionOffset = apStateMachineInput->m_GotoStateInfo->m_NormalizedTime; + apStateMachineMemory->m_TransitionTime = apStateMachineInput->m_GotoStateInfo->m_TransitionTime; + + apStateMachineMemory->m_StateMemoryArray[apStateMachineMemory->m_NextStateIndex]->m_PreviousTime = apStateMachineInput->m_GotoStateInfo->m_NormalizedTime + apStateMachineMemory->m_TransitionTime; + apStateMachineMemory->m_InInterruptedTransition = wasInTransition; + } + } + + // Dynamic transition cannot be interrupted by any transition + for(uint32_t run = 0 ; apStateMachineMemory->m_TransitionId != s_DynamicTransitionEncodeKey && !startTransition && run < 2 ; run++) // run 0 for AnyState, run 1 for transition in current state + { + ///////////////////// + int transitionCount = 0 ; + + if(apStateMachineMemory->m_InTransition) + { + if(!currentTransition->m_Atomic) + { + if ( run == 0 ) + transitionCount = isCurrentTransitionAnyState ? apStateMachineMemory->m_TransitionId - s_AnyTransitionEncodeKey : apStateMachineConstant->m_AnyStateTransitionConstantCount; + else + transitionCount = !isCurrentTransitionAnyState? apStateMachineMemory->m_TransitionId : 0 ; // anyState has higher priority + } + // else -> the transition is atomic, cannot be interrupted, transitionCount = 0 + } + else + { + transitionCount = run == 0 ? apStateMachineConstant->m_AnyStateTransitionConstantCount : currentState->m_TransitionConstantCount; + } + + for(uint32_t i = 0 ; !startTransition && i < transitionCount; i++) + { + const TransitionConstant* transitionConstant = run == 0 ? apStateMachineConstant->m_AnyStateTransitionConstantArray[i].Get() : currentState->m_TransitionConstantArray[i].Get(); + TransitionWorkspace* transitionWorkspace = run == 0 ? apStateMachineWorkspace->m_AnyStateTransitionWorkspaceArray[i] : currentStateWS->m_TransitionWorkspaceArray[i]; + + transitionMemory.m_InTransition = apStateMachineMemory->m_InTransition; + + EvaluateTransition(transitionConstant, &transitionInput, &transitionOutput, &transitionMemory, transitionWorkspace); + + if(transitionOutput.m_DoTransition) + { + startTransition = true; + + apStateMachineMemory->m_InTransition = true; + apStateMachineMemory->m_NextStateIndex = transitionConstant->m_DestinationState; + apStateMachineMemory->m_TransitionId = run == 0 ? (i + s_AnyTransitionEncodeKey) : i; + apStateMachineMemory->m_TransitionDuration = transitionOutput.m_TransitionDuration; + apStateMachineMemory->m_TransitionOffset = transitionOutput.m_TransitionOffset; + apStateMachineMemory->m_TransitionTime = transitionOutput.m_TransitionStartTime; + apStateMachineMemory->m_InInterruptedTransition = wasInTransition; + + apStateMachineMemory->m_ActiveGotoState = true; + apStateMachineInput->m_GotoStateInfo->m_StateID = 0; + apStateMachineInput->m_GotoStateInfo->m_NormalizedTime = transitionOutput.m_NextStateStartTime; + apStateMachineInput->m_GotoStateInfo->m_DenormalizedTimeOffset = transitionOutput.m_NextStateStartInitialDeltaTime * currentStateMemory->m_Duration; // denormalize source state time to denormalizedTime + + } + } + } + + + if(apStateMachineMemory->m_InTransition) + { + const int32_t nextStateIndex = apStateMachineMemory->m_NextStateIndex; + const StateConstant* nextState = apStateMachineConstant->m_StateConstantArray[nextStateIndex].Get(); + StateMemory* nextStateMemory = apStateMachineMemory->m_StateMemoryArray[nextStateIndex].Get(); + StateWorkspace* nextStateWS = apStateMachineWorkspace->m_StateWorkspaceArray[nextStateIndex]; + + if(wasInTransition) // delta already applied in m_TransitionStartTime when transition was just triggered, so dont add twice. + apStateMachineMemory->m_TransitionTime += apStateMachineMemory->m_TransitionDuration == 0 ? 1 : (deltaTime / (apStateMachineMemory->m_TransitionDuration * (outputSrc.m_StateDuration != 0 ? outputSrc.m_StateDuration : 1.0f))); + apStateMachineOutput->m_BlendFactor = math::saturate(apStateMachineMemory->m_TransitionTime); + + + StateOutput outputDst; + outputDst.m_BlendNode = &apStateMachineOutput->m_Right; + EvaluateState(apStateMachineWorkspace->m_ValuesConstant, nextState, apStateMachineInput, apStateMachineMemory, &outputDst, nextStateMemory, nextStateWS); + + for(int i = 0 ; i < apStateMachineConstant->m_MotionSetCount; i++) + { + if(apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputCount == 0 && apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputCount > 0) + apStateMachineMemory->m_MotionSetAutoWeightArray[i] = apStateMachineOutput->m_BlendFactor; + else if(apStateMachineOutput->m_Right.m_BlendNodeLayer[i].m_OutputCount == 0 && apStateMachineOutput->m_Left.m_BlendNodeLayer[i].m_OutputCount > 0) + apStateMachineMemory->m_MotionSetAutoWeightArray[i] = 1 - apStateMachineOutput->m_BlendFactor; + + } + + ///////////////////////////////////////// + // Transition is finished + if(apStateMachineMemory->m_TransitionTime >= 1) + { + for( uint32_t conditionIndex = 0 ; currentTransition != 0 && conditionIndex < currentTransition->m_ConditionConstantCount ; conditionIndex++) + { + const ConditionConstant* currentCondition = currentTransition->m_ConditionConstantArray[conditionIndex].Get(); + + if( currentCondition->m_ConditionMode == kConditionModeIf) + { + int32_t index = FindValueIndex(apStateMachineWorkspace->m_ValuesConstant, currentCondition->m_EventID); + + if(index > -1) + { + ValueConstant const& valueConstant = apStateMachineWorkspace->m_ValuesConstant->m_ValueArray[index]; + if(valueConstant.m_Type == mecanim::kTriggerType) + apStateMachineInput->m_Values->WriteData(false, valueConstant.m_Index); + } + } + } + + apStateMachineMemory->m_InTransition = false; + apStateMachineMemory->m_TransitionTime = 0.f; + apStateMachineMemory->m_TransitionId = 0; + apStateMachineMemory->m_TransitionDuration = 0.f; + apStateMachineMemory->m_TransitionOffset = 0.f; + apStateMachineMemory->m_CurrentStateIndex = apStateMachineMemory->m_NextStateIndex; + apStateMachineMemory->m_InInterruptedTransition = false; + + + BlendNodeLayer *nodeSwap = apStateMachineOutput->m_Left.m_BlendNodeLayer; + apStateMachineOutput->m_Left = apStateMachineOutput->m_Right; + apStateMachineOutput->m_Right.m_BlendNodeLayer = nodeSwap; + apStateMachineOutput->m_BlendFactor = 0.f; + apStateMachineOutput->m_Right.m_BlendNodeLayer[0].m_OutputCount = 0; + + } + } + } + + void StateConstant::InitializeClass() + { + RegisterAllowNameConversion("StateConstant", "m_ID", "m_PathID"); + } + + +}//namespace statemachine + +}//namespace mecanim diff --git a/Runtime/mecanim/statemachine/statemachine.h b/Runtime/mecanim/statemachine/statemachine.h new file mode 100644 index 0000000..6de46a9 --- /dev/null +++ b/Runtime/mecanim/statemachine/statemachine.h @@ -0,0 +1,547 @@ +#pragma once + +#include "Runtime/mecanim/animation/blendtree.h" +#include "Runtime/mecanim/generic/valuearray.h" + +#include "Runtime/Serialize/Blobification/offsetptr.h" +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" +#include "Runtime/Animation/MecanimArraySerialization.h" + +namespace mecanim +{ + +namespace statemachine +{ + static const mecanim::int32_t s_AnyTransitionEncodeKey = 20000; + static const mecanim::int32_t s_DynamicTransitionEncodeKey = 30000; + + enum ConditionMode + { + //kConditionModeGraph = 0, + kConditionModeIf = 1, // backward compat + kConditionModeIfNot, + kConditionModeGreater, + kConditionModeLess, + kConditionModeExitTime, + kConditionModeEquals, + kConditionModeNotEqual, + kConditionModeCount + }; + + struct GotoStateInfo + { + GotoStateInfo():m_StateID(0),m_NormalizedTime(0),m_TransitionDuration(0),m_TransitionTime(0), m_DenormalizedTimeOffset(0){} + + uint32_t m_StateID; + float m_NormalizedTime; + float m_TransitionDuration; + float m_TransitionTime; + float m_DenormalizedTimeOffset; // used to offset by seconds, internally used when transitions are taken + }; + + + struct BlendNodeLayer + { + BlendNodeLayer() : m_OutputCount(0), m_OutputIndexArray(0), m_OutputBlendArray(0), m_ReverseArray(0), m_MirrorArray(0), m_CycleOffsetArray(0) {} + uint32_t m_OutputCount; + uint32_t* m_OutputIndexArray; + float* m_OutputBlendArray; + bool* m_ReverseArray; + bool* m_MirrorArray; + float* m_CycleOffsetArray; + }; + + struct BlendNode + { + BlendNode(): m_BlendNodeLayer(0), m_CurrentTime(0),m_PreviousTime(0), m_IKOnFeet(false){} + + BlendNodeLayer* m_BlendNodeLayer; + + float m_CurrentTime; + float m_PreviousTime; + bool m_IKOnFeet; + }; + + + struct ConditionConstant + { + DEFINE_GET_TYPESTRING(ConditionConstant) + + ConditionConstant() : m_ConditionMode(kConditionModeIf), + m_EventID(0), + m_EventThreshold(0.f), + m_ExitTime(0) + { + } + + uint32_t m_ConditionMode; + uint32_t m_EventID; + + float m_EventThreshold; + float m_ExitTime; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER(m_ConditionMode); + TRANSFER(m_EventID); + TRANSFER(m_EventThreshold); + TRANSFER(m_ExitTime); + } + }; + + struct TransitionConstant + { + DEFINE_GET_TYPESTRING(TransitionConstant) + + TransitionConstant() : m_ConditionConstantCount(0), + m_DestinationState(0), + m_ID(0), + m_UserID(0), + m_TransitionDuration(0), + m_TransitionOffset(0), + m_Atomic(true) + + {} + + + uint32_t m_ConditionConstantCount; + OffsetPtr< OffsetPtr<ConditionConstant> > m_ConditionConstantArray; + + uint32_t m_DestinationState; + uint32_t m_ID; + uint32_t m_UserID; + + float m_TransitionDuration; + float m_TransitionOffset; + + bool m_Atomic; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER_BLOB_ONLY(m_ConditionConstantCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<mecanim::statemachine::ConditionConstant>, m_ConditionConstantArray, m_ConditionConstantCount); + + TRANSFER(m_DestinationState); + TRANSFER(m_ID); + TRANSFER(m_UserID); + + TRANSFER(m_TransitionDuration); + TRANSFER(m_TransitionOffset); + + TRANSFER(m_Atomic); + transfer.Align(); + } + }; + + struct TransitionWorkspace + { + TransitionWorkspace(): m_ConditionConstantCount(0) + { + } + + uint32_t m_ConditionConstantCount; + }; + + + struct TransitionInput + { + TransitionInput(): m_Values(0), + m_CurrentStatePreviousTime(0), + m_CurrentStateDuration(0), + m_CurrentTime(0), + m_PreviousTime() + {} + ValueArray* m_Values; + float m_CurrentStatePreviousTime; + float m_CurrentStateDuration; + float m_CurrentTime; + float m_PreviousTime; + }; + + + struct TransitionOutput + { + TransitionOutput(): m_DoTransition(false), + m_TransitionStartTime(0), + m_NextStateStartTime(0), + m_NextStateStartInitialDeltaTime(0), + m_TransitionDuration(0), + m_TransitionOffset(0) + {} + + bool m_DoTransition; + float m_TransitionStartTime; + float m_NextStateStartTime; + float m_NextStateStartInitialDeltaTime; + float m_TransitionDuration; + float m_TransitionOffset; + + }; + + struct TransitionMemory + { + TransitionMemory(): m_ValuesConstant(0), + m_InTransition(false) + {} + + ValueArrayConstant const* m_ValuesConstant; + bool m_InTransition; + }; + + + struct LeafInfoConstant + { + DEFINE_GET_TYPESTRING(LeafInfoConstant) + + LeafInfoConstant() : m_Count(0), m_IndexOffset(0) + { + + } + + uint32_t m_Count; + OffsetPtr<uint32_t> m_IDArray; + uint32_t m_IndexOffset; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER_BLOB_ONLY(m_Count); + MANUAL_ARRAY_TRANSFER2(mecanim::uint32_t, m_IDArray, m_Count); + TRANSFER(m_IndexOffset); + } + }; + + struct StateConstant + { + DEFINE_GET_TYPESTRING(StateConstant) + + StateConstant() : m_TransitionConstantCount(0), + m_MotionSetCount(0), + m_BlendTreeCount(0), + m_NameID(0), + m_PathID(0), + m_TagID(0), + m_Speed(1), + m_CycleOffset(0), + m_IKOnFeet(true), + m_Loop(false), + m_Mirror(false) + { + } + + uint32_t m_TransitionConstantCount; + OffsetPtr< OffsetPtr<TransitionConstant> > m_TransitionConstantArray; + + uint32_t m_MotionSetCount; + OffsetPtr<int32_t> m_BlendTreeConstantIndexArray; + OffsetPtr<LeafInfoConstant> m_LeafInfoArray; + + uint32_t m_BlendTreeCount; + OffsetPtr< OffsetPtr<animation::BlendTreeConstant> > m_BlendTreeConstantArray; + + uint32_t m_NameID; + uint32_t m_PathID; + uint32_t m_TagID; + + float m_Speed; + float m_CycleOffset; + bool m_IKOnFeet; + bool m_Loop; + bool m_Mirror; + + static void InitializeClass(); + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER_BLOB_ONLY(m_TransitionConstantCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<mecanim::statemachine::TransitionConstant>, m_TransitionConstantArray, m_TransitionConstantCount); + + TRANSFER_BLOB_ONLY(m_MotionSetCount); + MANUAL_ARRAY_TRANSFER2(int32_t, m_BlendTreeConstantIndexArray, m_MotionSetCount); + MANUAL_ARRAY_TRANSFER2(LeafInfoConstant, m_LeafInfoArray, m_MotionSetCount); + + TRANSFER_BLOB_ONLY(m_BlendTreeCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<mecanim::animation::BlendTreeConstant>, m_BlendTreeConstantArray, m_BlendTreeCount); + + TRANSFER(m_NameID); + TRANSFER(m_PathID); + TRANSFER(m_TagID); + + TRANSFER(m_Speed); + TRANSFER(m_CycleOffset); + + TRANSFER(m_IKOnFeet); + TRANSFER(m_Loop); + TRANSFER(m_Mirror); + + transfer.Align(); + } + }; + + struct StateMemory + { + DEFINE_GET_TYPESTRING(StateMemory) + + StateMemory(): m_PreviousTime(0), m_Duration(0) + {} + uint32_t m_BlendTreeCount; + OffsetPtr< OffsetPtr<animation::BlendTreeMemory> > m_BlendTreeMemoryArray; + + float m_PreviousTime; + float m_Duration; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER_BLOB_ONLY(m_BlendTreeCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<mecanim::animation::BlendTreeMemory>, m_BlendTreeMemoryArray, m_BlendTreeCount); + + TRANSFER(m_PreviousTime); + TRANSFER(m_Duration); + + transfer.Align(); + } + + }; + + struct StateWorkspace + { + StateWorkspace():m_TransitionWorkspaceArray(0), + m_BlendTreeInputArray(0), + m_BlendTreeOutputArray(0), + m_BlendTreeWorkspaceArray(0), + m_TransitionWorkspaceCount(0) + {} + + TransitionWorkspace** m_TransitionWorkspaceArray; + + + animation::BlendTreeInput** m_BlendTreeInputArray; + animation::BlendTreeOutput** m_BlendTreeOutputArray; + animation::BlendTreeWorkspace** m_BlendTreeWorkspaceArray; + + uint32_t m_TransitionWorkspaceCount; + uint32_t m_MotionSetCount; + }; + + + + struct StateOutput + { + StateOutput() : m_BlendNode(0), m_StateDuration(0) {} + + float m_StateDuration; + + BlendNode* m_BlendNode; + }; + + + struct StateMachineConstant + { + DEFINE_GET_TYPESTRING(StateMachineConstant) + + StateMachineConstant() : m_StateConstantCount(0), + m_AnyStateTransitionConstantCount(0), + m_DefaultState(0), + m_MotionSetCount(0) + {} + + uint32_t m_StateConstantCount; + OffsetPtr< OffsetPtr<StateConstant> > m_StateConstantArray; + + uint32_t m_AnyStateTransitionConstantCount; + OffsetPtr< OffsetPtr<TransitionConstant> > m_AnyStateTransitionConstantArray; + + uint32_t m_DefaultState; + uint32_t m_MotionSetCount; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER_BLOB_ONLY(m_StateConstantCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<mecanim::statemachine::StateConstant> , m_StateConstantArray, m_StateConstantCount); + + TRANSFER_BLOB_ONLY(m_AnyStateTransitionConstantCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<mecanim::statemachine::TransitionConstant>, m_AnyStateTransitionConstantArray, m_AnyStateTransitionConstantCount); + + TRANSFER(m_DefaultState); + TRANSFER(m_MotionSetCount); + } + }; + + struct StateMachineInput + { + StateMachineInput() : m_Values(0) + {} + + float m_DeltaTime; + ValueArray* m_Values; + + float* m_MotionSetTimingWeightArray; // allocated externally + + GotoStateInfo* m_GotoStateInfo; + }; + + struct StateMachineMemory + { + DEFINE_GET_TYPESTRING(StateMachineMemory) + + StateMachineMemory() : m_MotionSetCount(0), + m_StateMemoryCount(0), + m_CurrentStateIndex(0), + m_NextStateIndex(0), + m_TransitionId(0), + m_TransitionTime(0), + m_TransitionDuration(0), + m_TransitionOffset(0), + m_InInterruptedTransition(false), + m_InTransition(false), + m_ActiveGotoState(false) + {} + + uint32_t m_MotionSetCount; + OffsetPtr<float> m_MotionSetAutoWeightArray; + + uint32_t m_StateMemoryCount; + OffsetPtr<OffsetPtr<StateMemory> > m_StateMemoryArray; + + uint32_t m_CurrentStateIndex; + uint32_t m_NextStateIndex; + uint32_t m_TransitionId; + + float m_TransitionTime; + float m_TransitionDuration; + float m_TransitionOffset; + + bool m_InInterruptedTransition; + bool m_InTransition; + bool m_ActiveGotoState; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER_BLOB_ONLY(m_MotionSetCount); + MANUAL_ARRAY_TRANSFER2( float, m_MotionSetAutoWeightArray, m_MotionSetCount); + + TRANSFER_BLOB_ONLY(m_StateMemoryCount); + MANUAL_ARRAY_TRANSFER2( OffsetPtr<StateMemory>, m_StateMemoryArray, m_StateMemoryCount); + + TRANSFER(m_CurrentStateIndex); + TRANSFER(m_NextStateIndex); + TRANSFER(m_TransitionId); + + TRANSFER(m_TransitionTime); + TRANSFER(m_TransitionDuration); + TRANSFER(m_TransitionOffset); + + TRANSFER(m_InInterruptedTransition); + TRANSFER(m_InTransition); + TRANSFER(m_ActiveGotoState); + transfer.Align(); + } + }; + + struct StateMachineWorkspace + { + StateMachineWorkspace() : m_StateWorkspaceArray(0), + m_StateWorkspaceCount(0), + m_AnyStateTransitionWorkspaceArray(0), + m_AnyStateTransitionWorkspaceCount(0) + {} + + StateWorkspace** m_StateWorkspaceArray; + uint32_t m_StateWorkspaceCount; + + TransitionWorkspace** m_AnyStateTransitionWorkspaceArray; + uint32_t m_AnyStateTransitionWorkspaceCount; + + ValueArrayConstant* m_ValuesConstant; + + }; + + struct StateMachineOutput + { + StateMachineOutput(): m_BlendFactor(0),m_MotionSetCount(0) + {} + + float m_BlendFactor; + + BlendNode m_Left; + BlendNode m_Right; + + uint32_t m_MotionSetCount; + + + }; + + + + TransitionConstant const* GetTransitionConstant(StateMachineConstant const* apStateMachineConstant, StateConstant const* apStateConstant, uint32_t id); + + bool IsCurrentTransitionAtomic(StateMachineConstant const* apStateMachineConstant, StateMachineMemory *apStateMachineMemory); + + ConditionConstant *CreateConditionConstant( uint32_t aConditionMode, uint32_t aEventID, float aEventThreshold, float aExitTime, memory::Allocator& arAlloc); + void DestroyConditionConstant(ConditionConstant *apConditionConstant, memory::Allocator& arAlloc); + + TransitionConstant *CreateTransitionConstant(ConditionConstant** apConditionsConstantArray, uint32_t aConditionConstantCount, uint32_t aDestinationState, + float aTransitionDuration, float aTransitionOffset, bool aAtomic, uint32_t aID, uint32_t aUserID, memory::Allocator& arAlloc); + + void DestroyTransitionConstant(TransitionConstant *apTransitionConstant, memory::Allocator& arAlloc); + + + TransitionWorkspace* CreateTransitionWorkspace(TransitionConstant const* apTransitionConstant, memory::Allocator& arAlloc); + void DestroyTransitionWorkspace(TransitionWorkspace* apTransitionWorkspace, memory::Allocator& arAlloc); + + + StateConstant* CreateStateConstant(TransitionConstant** apTransitionConstantArray, uint32_t aTransitionConstantCount, + float aSpeed, bool aIKOnFeet, bool aMirror, float aCycleOffset, animation::BlendTreeConstant** apBlendTreeConstantArray, + uint32_t aMotionSetCount, uint32_t nameID, uint32_t pathID, uint32_t aTagID, bool aLoop, memory::Allocator& arAlloc); + + void DestroyStateConstant(StateConstant* apStateConstant, memory::Allocator& arAlloc); + + void DestroyStateMemory(StateMemory* apStateMemory, memory::Allocator& arAlloc); + + StateWorkspace* CreateStateWorkspace(StateConstant const* apStateConstant, memory::Allocator& arAlloc); + void DestroyStateWorkspace(StateWorkspace* apStateWorkspace, memory::Allocator& arAlloc); + + StateOutput* CreateStateOutput(StateConstant const* apStateConstant, memory::Allocator& arAlloc); + void DestroyStateOutput(StateOutput* apStateOutput, memory::Allocator& arAlloc); + + StateMachineConstant* CreateStateMachineConstant(StateConstant** apStateConstantArray, uint32_t aStateConstantCount, uint32_t aDefaultState, + TransitionConstant** apAnyStateTransitionConstantArray, uint32_t aAnyStateTransitionConstantCount, uint32_t aMotionSetCount, + memory::Allocator& arAlloc); + void DestroyStateMachineConstant(StateMachineConstant* apStateMachineConstant, memory::Allocator& arAlloc); + + void ClearStateMachineConstant(StateMachineConstant* apStateMachineConstant, memory::Allocator& arAlloc); + + StateMachineInput* CreateStateMachineInput(StateMachineConstant const* apStateMachineConstant, memory::Allocator& arAlloc); + void DestroyStateMachineInput(StateMachineInput* apStateMachineInput, memory::Allocator& arAlloc); + + StateMachineMemory* CreateStateMachineMemory(StateMachineConstant const* apStateMachineConstant, memory::Allocator& arAlloc); + void DestroyStateMachineMemory(StateMachineMemory* apStateMachineMemory, memory::Allocator& arAlloc); + + + StateMachineWorkspace* CreateStateMachineWorkspace(StateMachineConstant const* apStateMachineConstant, uint32_t maxBlendedClip, memory::Allocator& arAlloc); + void DestroyStateMachineWorkspace(StateMachineWorkspace* apStateMachineWorkspace, memory::Allocator& arAlloc); + + StateMachineOutput* CreateStateMachineOutput(StateMachineConstant const* apStateMachineConstant, uint32_t maxBlendedClip, memory::Allocator& arAlloc); + void DestroyStateMachineOutput(StateMachineOutput* apStateMachineOutput, memory::Allocator& arAlloc); + + void EvaluateStateMachine(StateMachineConstant const* apStateMachineConstant, StateMachineInput const* apStateMachineInput, + StateMachineOutput * apStateMachineOutput, StateMachineMemory * apStateMachineMemory, + StateMachineWorkspace * apStateMachineWorkspace); + + animation::BlendTreeConstant const* GetBlendTreeConstant(const StateConstant& arStateConstant, mecanim::int32_t aMotionSetCount); + animation::BlendTreeMemory *GetBlendTreeMemory(const StateConstant& arStateConstant,StateMemory& arStateMemory, mecanim::int32_t aMotionSetIndex); + + int32_t GetStateIndex(StateMachineConstant const* apStateMachineConstant, uint32_t id); + + inline int32_t CompareStateID (StateConstant const* state, uint32_t id) { return state->m_PathID == id || state->m_NameID == id; } + } +} + + + |