Skip to content

Commit

Permalink
Added Enum define and worked on animation graph
Browse files Browse the repository at this point in the history
  • Loading branch information
Cooltomten committed Sep 28, 2023
1 parent 061fc5f commit 0f96224
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 106 deletions.
79 changes: 50 additions & 29 deletions Volt/GraphKey/src/GraphKey/Nodes/Animation/StateMachineNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,36 @@ namespace GraphKey
{
VT_SERIALIZE_PROPERTY(name, state->name, out);
VT_SERIALIZE_PROPERTY(editorState, state->editorState, out);
VT_SERIALIZE_PROPERTY(stateType, static_cast<uint8_t>(state->stateType), out);
VT_SERIALIZE_PROPERTY(stateType, ToString(state->stateType), out);

VT_SERIALIZE_PROPERTY(id, state->id, out);
VT_SERIALIZE_PROPERTY(pinId, state->topPinId, out);
VT_SERIALIZE_PROPERTY(pinId2, state->bottomPinId, out);
VT_SERIALIZE_PROPERTY(topPinId, state->topPinId, out);
VT_SERIALIZE_PROPERTY(bottomPinId, state->bottomPinId, out);

out << YAML::Key << "Transitions" << YAML::BeginSeq;
for (const auto& transition : state->transitions)
{
out << transition;
}
out << YAML::EndSeq;

if (state->stateGraph)
if (state->stateType == Volt::StateMachineStateType::AnimationState)
{
auto animState = Volt::AnimationStateMachine::AsAnimationState(state);
if (animState->stateGraph)
{
VT_SERIALIZE_PROPERTY(skeletonHandle, animState->stateGraph->GetSkeletonHandle(), out);
Graph::Serialize(animState->stateGraph, out);
}
}
else if (state->stateType == Volt::StateMachineStateType::AliasState)
{
VT_SERIALIZE_PROPERTY(skeletonHandle, state->stateGraph->GetSkeletonHandle(), out);
Graph::Serialize(state->stateGraph, out);
auto aliasState = std::reinterpret_pointer_cast<Volt::AliasState>(state);
out << YAML::Key << "TransitionFromStates" << YAML::BeginSeq;
for (const auto& transition : aliasState->transitionFromStates)
{
out << transition;
}
out << YAML::EndSeq;
}
}
out << YAML::EndMap;
Expand Down Expand Up @@ -133,30 +146,45 @@ namespace GraphKey
std::string stateName;
bool stateIsEntry;
Volt::UUID stateId = Volt::UUID(0);
std::string stateTypeString;

VT_DESERIALIZE_PROPERTY(name, stateName, stateNode, std::string("Null"));
VT_DESERIALIZE_PROPERTY(isEntry, stateIsEntry, stateNode, false);
VT_DESERIALIZE_PROPERTY(id, stateId, stateNode, Volt::UUID(0));
VT_DESERIALIZE_PROPERTY(stateType, stateTypeString, stateNode, std::string("Null"));

Volt::StateMachineStateType stateType = ToEnum<Volt::StateMachineStateType>(stateTypeString);

auto newState = myStateMachine->CreateState(stateName, stateIsEntry, stateId);
auto newState = myStateMachine->AddState(stateName, stateType, stateId);

VT_DESERIALIZE_PROPERTY(editorState, newState->editorState, stateNode, std::string(""));
VT_DESERIALIZE_PROPERTY(pinId, newState->topPinId, stateNode, Volt::UUID(0));
VT_DESERIALIZE_PROPERTY(pinId2, newState->bottomPinId, stateNode, Volt::UUID(0));
VT_DESERIALIZE_PROPERTY(isAny, newState->isAny, stateNode, false);
VT_DESERIALIZE_PROPERTY(topPinId, newState->topPinId, stateNode, Volt::UUID(0));
VT_DESERIALIZE_PROPERTY(bottomPinId, newState->bottomPinId, stateNode, Volt::UUID(0));

for (const auto& transitionNode : stateNode["Transitions"])
{
newState->transitions.emplace_back(transitionNode.as<Volt::UUID>());
}

if (stateNode["Graph"])
if (stateType == Volt::StateMachineStateType::AnimationState)
{
auto animState = Volt::AnimationStateMachine::AsAnimationState(newState);
if (stateNode["Graph"])
{
Volt::AssetHandle characterHandle;
VT_DESERIALIZE_PROPERTY(characterHandle, characterHandle, stateNode, Volt::AssetHandle(0));
animState->stateGraph = CreateRef<Volt::AnimationGraphAsset>(characterHandle);
Graph::Deserialize(animState->stateGraph, stateNode["Graph"]);
}
}
else if (stateType == Volt::StateMachineStateType::AliasState)
{
Volt::AssetHandle characterHandle;
VT_DESERIALIZE_PROPERTY(characterHandle, characterHandle, stateNode, Volt::AssetHandle(0));
newState->stateGraph = CreateRef<Volt::AnimationGraphAsset>(characterHandle);
Graph::Deserialize(newState->stateGraph, stateNode["Graph"]);
auto aliasState = std::reinterpret_pointer_cast<Volt::AliasState>(newState);
for (const auto& transitionNode : stateNode["TransitionFromStates"])
{
aliasState->transitionFromStates.emplace_back(transitionNode.as<Volt::UUID>());
}
}

}

for (const auto& transitionNode : rootNode["Transitions"])
Expand All @@ -172,7 +200,7 @@ namespace GraphKey
auto newTransition = myStateMachine->CreateTransition(transitionId);
newTransition->fromState = transitionFromState;
newTransition->toState = transitionToState;

VT_DESERIALIZE_PROPERTY(shouldBlend, newTransition->shouldBlend, transitionNode, false);
VT_DESERIALIZE_PROPERTY(blendTime, newTransition->blendTime, transitionNode, 1.f);

Expand All @@ -181,33 +209,26 @@ namespace GraphKey
newTransition->transitionGraph = CreateRef<Volt::AnimationTransitionGraph>();
newTransition->transitionGraph->SetStateMachine(myStateMachine.get());
newTransition->transitionGraph->SetTransitionID(transitionId);

Graph::Deserialize(std::reinterpret_pointer_cast<Graph>(newTransition->transitionGraph), transitionNode["Graph"]);
}
}

bool hasAnyState = false;
bool hasEntryState = false;

for (const auto& state : myStateMachine->GetStates())
{
hasAnyState |= state->isAny;
hasEntryState |= state->isEntry;
hasEntryState |= state->stateType == Volt::StateMachineStateType::EntryState;

if (hasEntryState && hasAnyState)
if (hasEntryState)
{
break;
}
}

if (!hasAnyState)
{
myStateMachine->AddState("Any", false, true);
}

if (!hasEntryState)
{
myStateMachine->AddState("Entry", true);
myStateMachine->AddState("Entry", Volt::StateMachineStateType::EntryState);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace GraphKey
const auto animTransitionGraph = static_cast<Volt::AnimationTransitionGraph*>(aGraph);
const auto stateMachine = animTransitionGraph->GetStateMachine();
const auto transition = stateMachine->GetTransitionById(animTransitionGraph->GetTransitionID());
const auto fromState = stateMachine->GetStateById(transition->fromState);
const auto fromState = stateMachine->GetAnimationStateById(transition->fromState);

return fromState->stateGraph->GetRelevantAnimationNode();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void AnimationGraphPanel::DrawNodes()
// Node
{
auto id = ed::GetDoubleClickedNode();
auto state = GetLastEntry().stateMachine->GetStateById(id.Get());
auto state = GetLastEntry().stateMachine->GetAnimationStateById(id.Get());

if (state && state->stateGraph)
{
Expand Down Expand Up @@ -420,7 +420,7 @@ void AnimationGraphPanel::DrawNodesPanel()
{
if (ImGui::Button("Add state"))
{
GetLastEntry().stateMachine->AddState("New State", false);
GetLastEntry().stateMachine->AddState("New State", Volt::StateMachineStateType::AnimationState);
}
}
ImGui::End();
Expand Down Expand Up @@ -462,7 +462,7 @@ void AnimationGraphPanel::OnDeleteNode(const Volt::UUID id)
{
auto stateMachine = GetLastEntry().stateMachine;
auto state = stateMachine->GetStateById(id);
if (state && !state->isEntry && !state->isAny)
if (state && state->stateType != Volt::StateMachineStateType::EntryState)
{
stateMachine->RemoveState(id);
}
Expand Down Expand Up @@ -725,11 +725,11 @@ void AnimationGraphPanel::DrawStateMachineNodes()

auto mainColor = IM_COL32(29, 29, 29, 200);

if (state->isEntry)
if (state->stateType == Volt::StateMachineStateType::EntryState)
{
mainColor = IM_COL32(255, 174, 0, 255);
}
else if (state->isAny)
else if (state->stateType == Volt::StateMachineStateType::EntryState)
{
mainColor = IM_COL32(92, 171, 255, 255);
}
Expand Down Expand Up @@ -803,23 +803,25 @@ void AnimationGraphPanel::OnBeginCreateStateMachine()
return false;
});

const bool endIsEntry = endState->stateType == Volt::StateMachineStateType::EntryState;
const bool endIsAlias = endState->stateType == Volt::StateMachineStateType::AliasState;
if (transitionsToEndCount > 1 || sameStateIt != startState->transitions.end())
{
ed::RejectNewItem(ImColor{ 255, 0, 0 }, 2.f);
showLabel("x States are already connected", ImColor{ 255, 0, 0 });
}
else if (endState->isEntry)
else if (endIsEntry)
{
ed::RejectNewItem(ImColor{ 255, 0, 0 }, 2.f);
showLabel("x You cannot go to Entry state!", ImColor{ 255, 0, 0 });
}
else if (endState->isAny)
else if (endIsAlias)
{
ed::RejectNewItem(ImColor{ 255, 0, 0 }, 2.f);
showLabel("x You cannot go to Any state!", ImColor{ 255, 0, 0 });
showLabel("x You cannot go to Alias state!", ImColor{ 255, 0, 0 });
}

if (ed::AcceptNewItem(ImColor{ 1.f, 1.f, 1.f }, 2.f) && sameStateIt == startState->transitions.end() && !endState->isEntry && !endState->isAny)
if (ed::AcceptNewItem(ImColor{ 1.f, 1.f, 1.f }, 2.f) && sameStateIt == startState->transitions.end() && !endIsAlias && !endIsAlias)
{
stateMachine->AddTransition(startState->id, endState->id);
}
Expand Down
42 changes: 33 additions & 9 deletions Volt/Volt/src/Volt/Animation/AnimationStateMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@

#include "Volt/Utility/EnumUtil.h"

CREATE_ENUM(TestEnum, uint32_t,
One,
Two,
Three
);
enum class TestEnum : uint32_t
{
One, Two, Three
}; inline static bool TestEnum_reg = Utils::EnumUtil::RegisterEnum("TestEnum", "One, Two, Three"); inline static std::string ToString(TestEnum aEnumValue)
{
return Utils::EnumUtil::ToString("TestEnum", static_cast<uint64_t>(aEnumValue));
}/*template<TestEnum> inline static TestEnum ToEnum(const std::string& aEnumString)
{
return Utils::EnumUtil::ToEnum<TestEnum>("TestEnum", aEnumString);
};*/

namespace Volt
{
Expand Down Expand Up @@ -187,7 +192,7 @@ namespace Volt
return transition;
}

void AnimationStateMachine::AddState(const std::string& name, StateMachineStateType aStateType, const UUID id)
Ref<StateMachineState> AnimationStateMachine::AddState(const std::string& name, StateMachineStateType aStateType, const UUID id)
{
switch (aStateType)
{
Expand Down Expand Up @@ -221,12 +226,18 @@ namespace Volt

if (!alreadyHasEntry)
{
auto state = CreateRef<AnimationState>("Entry", aStateType);
auto state = CreateRef<StateMachineState>("Entry", aStateType);
myStates.emplace_back(state);
}
break;
}

default:
VT_CORE_ASSERT(false, "State type construction not implemented.");
break;
}

return myStates.back();
}

void AnimationStateMachine::AddTransition(const UUID startStateId, const UUID endStateId)
Expand Down Expand Up @@ -316,6 +327,19 @@ namespace Volt
return nullptr;
}

AnimationState* AnimationStateMachine::GetAnimationStateById(const UUID stateId) const
{
auto it = std::find_if(myStates.begin(), myStates.end(), [stateId](const auto& lhs) { return lhs->id == stateId; });
if (it != myStates.end())
{
if (it->get()->stateType == StateMachineStateType::AnimationState)
{
return std::reinterpret_pointer_cast<AnimationState>(*it).get();
}
}
return nullptr;
}

AnimationTransition* AnimationStateMachine::GetTransitionById(const UUID transitionId) const
{
auto it = std::find_if(myTransitions.begin(), myTransitions.end(), [transitionId](const auto& lhs) { return lhs->id == transitionId; });
Expand Down Expand Up @@ -363,7 +387,7 @@ namespace Volt
Ref<StateMachineState> newState;
if (state->stateType == StateMachineStateType::AnimationState)
{
newState = CreateRef<AnimationState>(state->name, state->stateType);
newState = CreateRef<AnimationState>(state->name);
auto newAnimState = std::reinterpret_pointer_cast<AnimationState>(newState);
auto oldAnimState = std::reinterpret_pointer_cast<AnimationState>(state);
if (oldAnimState->stateGraph)
Expand All @@ -377,7 +401,7 @@ namespace Volt
newState = CreateRef<AliasState>(state->name);
auto newAliasState = std::reinterpret_pointer_cast<AliasState>(newState);
auto oldAliasState = std::reinterpret_pointer_cast<AliasState>(state);

newAliasState->transitionFromStates = oldAliasState->transitionFromStates;
}
else
Expand Down
17 changes: 9 additions & 8 deletions Volt/Volt/src/Volt/Animation/AnimationStateMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <any>

#include "Volt/Utility/EnumUtil.h"

namespace GraphKey
{
class Graph;
Expand All @@ -31,12 +33,10 @@ namespace Volt
Ref<AnimationTransitionGraph> transitionGraph;
};

enum class StateMachineStateType : uint8_t
{
CREATE_ENUM_TYPED(StateMachineStateType, uint8_t,
AnimationState,
AliasState,
EntryState
};
EntryState);

struct StateMachineState
{
Expand Down Expand Up @@ -68,7 +68,6 @@ namespace Volt
Ref<AnimationGraphAsset> stateGraph;

float startTime = 0.f;
float speed = 1.f;
};

struct AliasState : public StateMachineState
Expand All @@ -90,7 +89,7 @@ namespace Volt
void Update(float deltaTime);
const GraphKey::AnimationOutputData Sample(Ref<Skeleton> skeleton);

void AddState(const std::string& name, StateMachineStateType aStateType, const UUID id = 0);
Ref<StateMachineState> AddState(const std::string& name, StateMachineStateType aStateType, const UUID id = 0);
void AddTransition(const UUID startState, const UUID endState);

Ref<AnimationTransition> CreateTransition(Volt::UUID id);
Expand All @@ -101,6 +100,7 @@ namespace Volt
void SetStartState(const UUID stateId);

StateMachineState* GetStateById(const UUID stateId) const;
AnimationState* GetAnimationStateById(const UUID stateId) const;
AnimationTransition* GetTransitionById(const UUID transitionId) const;

StateMachineState* GetStateFromPin(const UUID outputId) const;
Expand All @@ -116,20 +116,21 @@ namespace Volt
inline const AssetHandle GetSkeletonHandle() const { return mySkeletonHandle; }

inline const std::string& GetName() const { return myName; }
inline void SetEditorState(const std::string& state) { myState = state; }
inline
void SetEditorState(const std::string& state) { myState = state; }
inline void SetName(const std::string& name) { myName = name; }

void SetSkeletonHandle(AssetHandle aSkeletonHandle);

void Clear();
static Ref<AnimationState> AsAnimationState(Ref<StateMachineState> aState);

private:
const bool ShouldTransition(const UUID transitionId, const UUID currentStateId) const;
const GraphKey::AnimationOutputData CrossfadeTransition();
const GraphKey::AnimationOutputData SampleState(int32_t stateIndex);

Ref<AnimationState> GetAnimationState(uint32_t aIndex);
Ref<AnimationState> AsAnimationState(Ref<StateMachineState> aState);

void SetNextState(const UUID targetStateId, const UUID transitionId);

Expand Down
Loading

0 comments on commit 0f96224

Please sign in to comment.