Improved movement animaitons
Added a SetBlendWeight event that sets the weight for all nodes with a name.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include "../Game/Events/EDashAbility.h"
|
#include "../Game/Events/EDashAbility.h"
|
||||||
#include "InputHandler.h"
|
#include "InputHandler.h"
|
||||||
#include "Rendering/EAutoAnimationBlend.h"
|
#include "Rendering/EAutoAnimationBlend.h"
|
||||||
|
#include "Rendering/ESetBlendWeight.h"
|
||||||
|
|
||||||
template <typename EventContext>
|
template <typename EventContext>
|
||||||
class FirstPersonInputController : public InputController<EventContext>
|
class FirstPersonInputController : public InputController<EventContext>
|
||||||
@@ -45,7 +46,6 @@ protected:
|
|||||||
bool m_Crouching = false;
|
bool m_Crouching = false;
|
||||||
//assault dash membervariables - needed to calculate the doubletap- and dashlogic
|
//assault dash membervariables - needed to calculate the doubletap- and dashlogic
|
||||||
double m_AssaultDashDoubleTapDeltaTime = 0.0;
|
double m_AssaultDashDoubleTapDeltaTime = 0.0;
|
||||||
double m_DashEffectResetTimer = 0.0;
|
|
||||||
//i will let m_AssaultDashDoubleTapSensitivityTimer stay hardcoded, its not really a gamevariable (more an inputvariable),
|
//i will let m_AssaultDashDoubleTapSensitivityTimer stay hardcoded, its not really a gamevariable (more an inputvariable),
|
||||||
//and its very unlikely that someone wants to change that value
|
//and its very unlikely that someone wants to change that value
|
||||||
const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f;
|
const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f;
|
||||||
@@ -137,6 +137,7 @@ bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputComm
|
|||||||
}
|
}
|
||||||
aeb.RootNode = playerModel;
|
aeb.RootNode = playerModel;
|
||||||
aeb.Start = true;
|
aeb.Start = true;
|
||||||
|
aeb.SingleLevelBlend = true;
|
||||||
m_EventBroker->Publish(aeb);
|
m_EventBroker->Publish(aeb);
|
||||||
} else if (val < 0) {
|
} else if (val < 0) {
|
||||||
Events::AutoAnimationBlend aeb;
|
Events::AutoAnimationBlend aeb;
|
||||||
@@ -148,6 +149,7 @@ bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputComm
|
|||||||
}
|
}
|
||||||
aeb.RootNode = playerModel;
|
aeb.RootNode = playerModel;
|
||||||
aeb.Start = true;
|
aeb.Start = true;
|
||||||
|
aeb.SingleLevelBlend = true;
|
||||||
aeb.Reverse = true;
|
aeb.Reverse = true;
|
||||||
m_EventBroker->Publish(aeb);
|
m_EventBroker->Publish(aeb);
|
||||||
} else {
|
} else {
|
||||||
@@ -169,6 +171,7 @@ bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputComm
|
|||||||
aeb.Duration = 0.1;
|
aeb.Duration = 0.1;
|
||||||
aeb.NodeName = "Right";
|
aeb.NodeName = "Right";
|
||||||
aeb.RootNode = playerModel;
|
aeb.RootNode = playerModel;
|
||||||
|
aeb.SingleLevelBlend = true;
|
||||||
aeb.Start = true;
|
aeb.Start = true;
|
||||||
m_EventBroker->Publish(aeb);
|
m_EventBroker->Publish(aeb);
|
||||||
} else if (val < 0) {
|
} else if (val < 0) {
|
||||||
@@ -176,6 +179,7 @@ bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputComm
|
|||||||
aeb.Duration = 0.1;
|
aeb.Duration = 0.1;
|
||||||
aeb.NodeName = "Left";
|
aeb.NodeName = "Left";
|
||||||
aeb.RootNode = playerModel;
|
aeb.RootNode = playerModel;
|
||||||
|
aeb.SingleLevelBlend = true;
|
||||||
aeb.Start = true;
|
aeb.Start = true;
|
||||||
m_EventBroker->Publish(aeb);
|
m_EventBroker->Publish(aeb);
|
||||||
} else {
|
} else {
|
||||||
@@ -186,16 +190,28 @@ bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputComm
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (glm::length2(m_Movement) > 0) {
|
|
||||||
m_Movement = glm::normalize(m_Movement);
|
|
||||||
|
if (glm::length2(m_Movement) < 0.1f) {
|
||||||
|
if (m_PlayerEntity.Valid()) {
|
||||||
|
EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel");
|
||||||
|
|
||||||
|
if (playerModel.Valid()) {
|
||||||
|
Events::AutoAnimationBlend aeb;
|
||||||
|
aeb.Duration = 0.2;
|
||||||
|
aeb.NodeName = "Idle";
|
||||||
|
aeb.RootNode = playerModel;
|
||||||
|
m_EventBroker->Publish(aeb);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (m_PlayerEntity.Valid()) {
|
if (m_PlayerEntity.Valid()) {
|
||||||
EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel");
|
EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel");
|
||||||
|
|
||||||
if (playerModel.Valid()) {
|
if (playerModel.Valid()) {
|
||||||
Events::AutoAnimationBlend aeb;
|
Events::AutoAnimationBlend aeb;
|
||||||
aeb.Duration = 0.1;
|
aeb.Duration = 0.2;
|
||||||
aeb.NodeName = "Idle";
|
aeb.NodeName = "MovementBlend";
|
||||||
aeb.RootNode = playerModel;
|
aeb.RootNode = playerModel;
|
||||||
m_EventBroker->Publish(aeb);
|
m_EventBroker->Publish(aeb);
|
||||||
}
|
}
|
||||||
@@ -203,6 +219,29 @@ bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputComm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (glm::length2(m_Movement) > 0) {
|
||||||
|
m_Movement = glm::normalize(m_Movement);
|
||||||
|
|
||||||
|
if (m_PlayerEntity.Valid()) {
|
||||||
|
EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel");
|
||||||
|
|
||||||
|
if (playerModel.Valid()) {
|
||||||
|
glm::vec2 direction = glm::normalize(glm::vec2(m_Movement.x, m_Movement.z));
|
||||||
|
|
||||||
|
double weight = glm::abs(glm::dot(glm::vec2(1, 0), direction));
|
||||||
|
LOG_INFO("Weight %f", weight);
|
||||||
|
Events::SetBlendWeight sbw;
|
||||||
|
sbw.NodeName = "MovementBlend";
|
||||||
|
sbw.Weight = weight;
|
||||||
|
sbw.RootNode = playerModel;
|
||||||
|
m_EventBroker->Publish(sbw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (e.Command == "Forward" || e.Command == "Right") {
|
if (e.Command == "Forward" || e.Command == "Right") {
|
||||||
if (e.Value != 0) {
|
if (e.Value != 0) {
|
||||||
m_CurrentDirectionVector = e.Command == "Right" ? (e.Value > 0 ? "Right" : "Left") : (e.Value > 0 ? "Forward" : "Backward");
|
m_CurrentDirectionVector = e.Command == "Right" ? (e.Value > 0 ? "Right" : "Left") : (e.Value > 0 ? "Forward" : "Backward");
|
||||||
@@ -288,17 +327,10 @@ bool FirstPersonInputController<EventContext>::OnLockMouse(const Events::LockMou
|
|||||||
template <typename EventContext>
|
template <typename EventContext>
|
||||||
void FirstPersonInputController<EventContext>::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer, EntityID playerID) {
|
void FirstPersonInputController<EventContext>::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer, EntityID playerID) {
|
||||||
m_AssaultDashDoubleTapDeltaTime += dt;
|
m_AssaultDashDoubleTapDeltaTime += dt;
|
||||||
m_DashEffectResetTimer += dt;
|
|
||||||
assaultDashCoolDownTimer -= dt;
|
assaultDashCoolDownTimer -= dt;
|
||||||
//cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work)
|
//cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work)
|
||||||
if (assaultDashCoolDownTimer > (assaultDashCoolDownMaxTimer - 0.25f)) {
|
if (assaultDashCoolDownTimer > (assaultDashCoolDownMaxTimer - 0.25f)) {
|
||||||
m_PlayerIsDashing = true;
|
m_PlayerIsDashing = true;
|
||||||
if (m_DashEffectResetTimer > 0.05) {
|
|
||||||
Events::DashAbility e;
|
|
||||||
e.Player = playerID;
|
|
||||||
m_EventBroker->Publish(e);
|
|
||||||
m_DashEffectResetTimer = 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
m_PlayerIsDashing = false;
|
m_PlayerIsDashing = false;
|
||||||
}
|
}
|
||||||
@@ -310,6 +342,7 @@ void FirstPersonInputController<EventContext>::AssaultDashCheck(double dt, bool
|
|||||||
assaultDashCoolDownTimer = assaultDashCoolDownMaxTimer;
|
assaultDashCoolDownTimer = assaultDashCoolDownMaxTimer;
|
||||||
m_AssaultDashDoubleTapped = true;
|
m_AssaultDashDoubleTapped = true;
|
||||||
m_AssaultDashDoubleTapDeltaTime = 0.f;
|
m_AssaultDashDoubleTapDeltaTime = 0.f;
|
||||||
|
|
||||||
Events::DashAbility e;
|
Events::DashAbility e;
|
||||||
e.Player = playerID;
|
e.Player = playerID;
|
||||||
m_EventBroker->Publish(e);
|
m_EventBroker->Publish(e);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include "../Core/EntityWrapper.h"
|
#include "../Core/EntityWrapper.h"
|
||||||
#include "Rendering/AutoBlendQueue.h"
|
#include "Rendering/AutoBlendQueue.h"
|
||||||
#include "../Input/EInputCommand.h"
|
#include "../Input/EInputCommand.h"
|
||||||
|
#include "../Core/EEntityDeleted.h"
|
||||||
|
#include "Rendering/ESetBlendWeight.h"
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
class AnimationSystem : public ImpureSystem
|
class AnimationSystem : public ImpureSystem
|
||||||
@@ -28,6 +30,13 @@ private:
|
|||||||
|
|
||||||
EventRelay<AnimationSystem, Events::AutoAnimationBlend> m_EAutoAnimationBlend;
|
EventRelay<AnimationSystem, Events::AutoAnimationBlend> m_EAutoAnimationBlend;
|
||||||
bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e);
|
bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e);
|
||||||
|
|
||||||
|
EventRelay<AnimationSystem, Events::EntityDeleted> m_EEntityDeleted;
|
||||||
|
bool OnEntityDeleted(Events::EntityDeleted& e);
|
||||||
|
|
||||||
|
EventRelay<AnimationSystem, Events::SetBlendWeight> m_ESetBlendWeight;
|
||||||
|
bool OnSetBlendWeight(Events::SetBlendWeight& e);
|
||||||
|
|
||||||
std::unordered_map<EntityWrapper, AutoBlendQueue> m_AutoBlendQueues;
|
std::unordered_map<EntityWrapper, AutoBlendQueue> m_AutoBlendQueues;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
std::shared_ptr<BlendTree> GetBlendTree();
|
std::shared_ptr<BlendTree> GetBlendTree();
|
||||||
|
|
||||||
AutoBlendQueue::AutoBlendJob& GetActiveBlendJob();
|
AutoBlendQueue::AutoBlendJob& GetActiveBlendJob();
|
||||||
|
|
||||||
|
bool Empty() { return m_BlendQueue.empty(); }
|
||||||
private:
|
private:
|
||||||
std::list<AutoblendNode> m_BlendQueue;
|
std::list<AutoblendNode> m_BlendQueue;
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ public:
|
|||||||
std::vector<glm::mat4> GetFinalPose() { return m_FinalPose; }
|
std::vector<glm::mat4> GetFinalPose() { return m_FinalPose; }
|
||||||
glm::mat4 GetBoneTransform(int boneID);
|
glm::mat4 GetBoneTransform(int boneID);
|
||||||
bool IsValid() { return (m_Root == nullptr ? false : true); }
|
bool IsValid() { return (m_Root == nullptr ? false : true); }
|
||||||
|
|
||||||
void PrintTree();
|
void PrintTree();
|
||||||
BlendTree::AutoBlendInfo AutoBlendStep(AutoBlendInfo blendInfo);
|
BlendTree::AutoBlendInfo AutoBlendStep(AutoBlendInfo blendInfo);
|
||||||
|
|
||||||
@@ -84,16 +83,20 @@ public:
|
|||||||
|
|
||||||
EntityWrapper GetSubTreeRoot(std::string nodeName);
|
EntityWrapper GetSubTreeRoot(std::string nodeName);
|
||||||
|
|
||||||
|
std::vector<EntityWrapper> GetSingleLevelRoots(std::string name);
|
||||||
|
std::vector<EntityWrapper> GetEntitesByName(std::string name);
|
||||||
|
|
||||||
|
void SetWeightByName(std::string name, double weight);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Skeleton* m_Skeleton = nullptr;
|
Skeleton* m_Skeleton = nullptr;
|
||||||
Node* m_Root = nullptr;
|
Node* m_Root = nullptr;
|
||||||
|
|
||||||
std::vector<glm::mat4> m_FinalPose;
|
std::vector<glm::mat4> m_FinalPose;
|
||||||
std::map<int, glm::mat4> m_FinalBoneTransforms;
|
std::map<int, glm::mat4> m_FinalBoneTransforms;
|
||||||
|
std::vector<BlendTree::Node*> FindNodesByName(std::string name);
|
||||||
std::vector<glm::mat4> AccumulateFinalPose();
|
std::vector<glm::mat4> AccumulateFinalPose();
|
||||||
BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity);
|
BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity);
|
||||||
std::vector<BlendTree::Node*> FindNodesByName(std::string name);
|
|
||||||
|
|
||||||
void Blend(std::map<int, Skeleton::PoseData>& pose);
|
void Blend(std::map<int, Skeleton::PoseData>& pose);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ struct AutoAnimationBlend : Event
|
|||||||
bool Reverse = false;
|
bool Reverse = false;
|
||||||
bool Restart = false;
|
bool Restart = false;
|
||||||
bool SingleLevelBlend = false;
|
bool SingleLevelBlend = false;
|
||||||
|
|
||||||
double Weight = -1.0;
|
double Weight = -1.0;
|
||||||
|
|
||||||
EntityWrapper AnimationEntity = EntityWrapper::Invalid;
|
EntityWrapper AnimationEntity = EntityWrapper::Invalid;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef Events_SetBlendWeight_h__
|
||||||
|
#define Events_SetBlendWeight_h__
|
||||||
|
|
||||||
|
#include "../Core/EventBroker.h"
|
||||||
|
#include "../Core/EntityWrapper.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
//Sets the blend weight for all nodes with "NodeName"
|
||||||
|
struct SetBlendWeight : Event
|
||||||
|
{
|
||||||
|
EntityWrapper RootNode = EntityWrapper::Invalid;
|
||||||
|
std::string NodeName;
|
||||||
|
double Weight;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,17 +2,12 @@
|
|||||||
<Entity name="DashEffect" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
<Entity name="DashEffect" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||||
|
|
||||||
<Components>
|
<Components>
|
||||||
<c:Animation/>
|
|
||||||
<c:Lifetime>
|
<c:Lifetime>
|
||||||
<Lifetime>0.5</Lifetime>
|
<Lifetime>0.5</Lifetime>
|
||||||
</c:Lifetime>
|
</c:Lifetime>
|
||||||
<c:ExplosionEffect>
|
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
|
||||||
<TimeSinceDeath>0</TimeSinceDeath>
|
|
||||||
<ExplosionDuration>0.5</ExplosionDuration>
|
|
||||||
<EndColor A="0" B="0" G="0" R="0"/>
|
|
||||||
</c:ExplosionEffect>
|
|
||||||
<c:Model/>
|
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
</Components>
|
</Components>
|
||||||
|
|
||||||
|
<Children/>
|
||||||
|
|
||||||
</Entity>
|
</Entity>
|
||||||
|
|||||||
@@ -875,7 +875,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>RunF</AnimationName>
|
<AnimationName>RunF</AnimationName>
|
||||||
<Time>0.34392228616198395</Time>
|
<Time>0.34392228616198395</Time>
|
||||||
<Speed>1</Speed>
|
<Speed>1.5</Speed>
|
||||||
<Play>true</Play>
|
<Play>true</Play>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
@@ -899,7 +899,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>StrafeRightF</AnimationName>
|
<AnimationName>StrafeRightF</AnimationName>
|
||||||
<Time>0.27701693305173336</Time>
|
<Time>0.27701693305173336</Time>
|
||||||
<Speed>1</Speed>
|
<Speed>2</Speed>
|
||||||
<Play>true</Play>
|
<Play>true</Play>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
@@ -911,7 +911,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>StrafeLeftF</AnimationName>
|
<AnimationName>StrafeLeftF</AnimationName>
|
||||||
<Time>0.25350140317161873</Time>
|
<Time>0.25350140317161873</Time>
|
||||||
<Speed>1</Speed>
|
<Speed>2</Speed>
|
||||||
<Play>true</Play>
|
<Play>true</Play>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
@@ -986,7 +986,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>DashForwardF</AnimationName>
|
<AnimationName>DashForwardF</AnimationName>
|
||||||
<Time>1</Time>
|
<Time>1</Time>
|
||||||
<Speed>2</Speed>
|
<Speed>3</Speed>
|
||||||
<Loop>false</Loop>
|
<Loop>false</Loop>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
@@ -998,7 +998,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>DashBackwardF</AnimationName>
|
<AnimationName>DashBackwardF</AnimationName>
|
||||||
<Time>1</Time>
|
<Time>1</Time>
|
||||||
<Speed>2</Speed>
|
<Speed>3</Speed>
|
||||||
<Loop>false</Loop>
|
<Loop>false</Loop>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
@@ -1022,7 +1022,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>DashLeftF</AnimationName>
|
<AnimationName>DashLeftF</AnimationName>
|
||||||
<Time>1</Time>
|
<Time>1</Time>
|
||||||
<Speed>2</Speed>
|
<Speed>3</Speed>
|
||||||
<Loop>false</Loop>
|
<Loop>false</Loop>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
@@ -1034,7 +1034,7 @@
|
|||||||
<c:Animation>
|
<c:Animation>
|
||||||
<AnimationName>DashRightF</AnimationName>
|
<AnimationName>DashRightF</AnimationName>
|
||||||
<Time>1</Time>
|
<Time>1</Time>
|
||||||
<Speed>2</Speed>
|
<Speed>3</Speed>
|
||||||
<Loop>false</Loop>
|
<Loop>false</Loop>
|
||||||
</c:Animation>
|
</c:Animation>
|
||||||
<c:Transform/>
|
<c:Transform/>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ AnimationSystem::AnimationSystem(SystemParams params)
|
|||||||
: System(params)
|
: System(params)
|
||||||
{
|
{
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend);
|
EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &AnimationSystem::OnEntityDeleted);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_ESetBlendWeight, &AnimationSystem::OnSetBlendWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationSystem::Update(double dt)
|
void AnimationSystem::Update(double dt)
|
||||||
@@ -122,16 +124,13 @@ void AnimationSystem::UpdateAnimations(double dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AnimationSystem::UpdateWeights(double dt)
|
void AnimationSystem::UpdateWeights(double dt)
|
||||||
{
|
{
|
||||||
for (auto& autoBlendQueue : m_AutoBlendQueues) {
|
for (auto it = m_AutoBlendQueues.begin(); it != m_AutoBlendQueues.end(); ) {
|
||||||
|
if(it->second.HasActiveBlendJob()) {
|
||||||
if(autoBlendQueue.second.HasActiveBlendJob()) {
|
AutoBlendQueue::AutoBlendJob& blendJob = it->second.GetActiveBlendJob();
|
||||||
AutoBlendQueue::AutoBlendJob& blendJob = autoBlendQueue.second.GetActiveBlendJob();
|
|
||||||
|
|
||||||
std::shared_ptr<BlendTree> blendTree = autoBlendQueue.second.GetBlendTree();
|
|
||||||
|
|
||||||
|
std::shared_ptr<BlendTree> blendTree = it->second.GetBlendTree();
|
||||||
if (blendTree != nullptr) {
|
if (blendTree != nullptr) {
|
||||||
if (blendJob.Duration != 0.0) {
|
if (blendJob.Duration != 0.0) {
|
||||||
blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0);
|
blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0);
|
||||||
@@ -140,10 +139,17 @@ void AnimationSystem::UpdateWeights(double dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo);
|
blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo);
|
||||||
|
} else {
|
||||||
|
it = m_AutoBlendQueues.erase(it);
|
||||||
|
}
|
||||||
|
it++;
|
||||||
|
} else {
|
||||||
|
if (it->second.Empty()) {
|
||||||
|
it = m_AutoBlendQueues.erase(it);
|
||||||
|
} else {
|
||||||
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,46 +183,163 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityWrapper subTreeRoot;
|
||||||
|
|
||||||
|
|
||||||
EntityWrapper subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName);
|
if (e.SingleLevelBlend) {
|
||||||
|
subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName);
|
||||||
|
|
||||||
if (!subTreeRoot.Valid()) {
|
if (!subTreeRoot.Valid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoBlendQueue::AutoBlendJob abj;
|
AutoBlendQueue::AutoBlendJob abj;
|
||||||
abj.AnimationEntity = e.AnimationEntity;
|
abj.AnimationEntity = e.AnimationEntity;
|
||||||
abj.CurrentTime = 0.0;
|
abj.CurrentTime = 0.0;
|
||||||
abj.Delay = e.Delay;
|
abj.Delay = e.Delay;
|
||||||
abj.Duration = e.Duration;
|
abj.Duration = e.Duration;
|
||||||
abj.RootNode = e.RootNode;
|
abj.RootNode = e.RootNode;
|
||||||
|
|
||||||
abj.BlendInfo.NodeName = e.NodeName;
|
abj.BlendInfo.NodeName = e.NodeName;
|
||||||
abj.BlendInfo.progress = 0.0;
|
abj.BlendInfo.progress = 0.0;
|
||||||
abj.BlendInfo.Start = e.Start;
|
abj.BlendInfo.Start = e.Start;
|
||||||
abj.BlendInfo.SingleBlend = e.SingleLevelBlend;
|
abj.BlendInfo.SingleBlend = e.SingleLevelBlend;
|
||||||
abj.BlendInfo.Weight = e.Weight;
|
abj.BlendInfo.Weight = e.Weight;
|
||||||
|
|
||||||
EntityWrapper nodeEntity = subTreeRoot.FirstChildByName(e.NodeName); // more than one
|
std::vector<EntityWrapper> animationEntities = blendTree->GetEntitesByName(e.NodeName); // more than one
|
||||||
if (nodeEntity.Valid()) {
|
for(auto entity : animationEntities)
|
||||||
if (nodeEntity.HasComponent("Animation")) {
|
if (entity.Valid()) {
|
||||||
const Skeleton::Animation* animation = skeleton->GetAnimation(nodeEntity["Animation"]["AnimationName"]);
|
if (entity.HasComponent("Animation")) {
|
||||||
(bool&)nodeEntity["Animation"]["Reverse"] = e.Reverse;
|
const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]);
|
||||||
|
(bool&)entity["Animation"]["Reverse"] = e.Reverse;
|
||||||
|
|
||||||
if (e.Restart) {
|
if (e.Restart) {
|
||||||
if (animation != nullptr) {
|
if (animation != nullptr) {
|
||||||
if (e.Restart) {
|
if (e.Restart) {
|
||||||
if (e.Reverse) {
|
if (e.Reverse) {
|
||||||
(double&)nodeEntity["Animation"]["Time"] = animation->Duration;
|
(double&)entity["Animation"]["Time"] = animation->Duration;
|
||||||
} else {
|
} else {
|
||||||
(double&)nodeEntity["Animation"]["Time"] = 0.0;
|
(double&)entity["Animation"]["Time"] = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_AutoBlendQueues[subTreeRoot].Insert(abj);
|
||||||
|
} else {
|
||||||
|
std::vector<EntityWrapper> subtreeroots = blendTree->GetSingleLevelRoots(e.NodeName);
|
||||||
|
|
||||||
|
for(auto entity : subtreeroots) {
|
||||||
|
subTreeRoot = entity;
|
||||||
|
|
||||||
|
if (!subTreeRoot.Valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoBlendQueue::AutoBlendJob abj;
|
||||||
|
abj.AnimationEntity = e.AnimationEntity;
|
||||||
|
abj.CurrentTime = 0.0;
|
||||||
|
abj.Delay = e.Delay;
|
||||||
|
abj.Duration = e.Duration;
|
||||||
|
abj.RootNode = e.RootNode;
|
||||||
|
|
||||||
|
abj.BlendInfo.NodeName = e.NodeName;
|
||||||
|
abj.BlendInfo.progress = 0.0;
|
||||||
|
abj.BlendInfo.Start = e.Start;
|
||||||
|
abj.BlendInfo.SingleBlend = e.SingleLevelBlend;
|
||||||
|
abj.BlendInfo.Weight = e.Weight;
|
||||||
|
m_AutoBlendQueues[subTreeRoot].Insert(abj);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<EntityWrapper> animationEntities = blendTree->GetEntitesByName(e.NodeName); // more than one
|
||||||
|
for (auto entity : animationEntities)
|
||||||
|
if (entity.Valid()) {
|
||||||
|
if (entity.HasComponent("Animation")) {
|
||||||
|
const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]);
|
||||||
|
(bool&)entity["Animation"]["Reverse"] = e.Reverse;
|
||||||
|
|
||||||
|
if (e.Restart) {
|
||||||
|
if (animation != nullptr) {
|
||||||
|
if (e.Restart) {
|
||||||
|
if (e.Reverse) {
|
||||||
|
(double&)entity["Animation"]["Time"] = animation->Duration;
|
||||||
|
} else {
|
||||||
|
(double&)entity["Animation"]["Time"] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_AutoBlendQueues[subTreeRoot].Insert(abj);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AnimationSystem::OnEntityDeleted(Events::EntityDeleted& e)
|
||||||
|
{
|
||||||
|
EntityWrapper entity = EntityWrapper(m_World, e.DeletedEntity);
|
||||||
|
|
||||||
|
if (entity.HasComponent("Model")) {
|
||||||
|
Model* model;
|
||||||
|
try {
|
||||||
|
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||||
|
if (skeleton == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skeleton->BlendTrees.find(entity) != skeleton->BlendTrees.end()) {
|
||||||
|
skeleton->BlendTrees.erase(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AnimationSystem::OnSetBlendWeight(Events::SetBlendWeight& e)
|
||||||
|
{
|
||||||
|
if (!e.RootNode.Valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.RootNode.HasComponent("Model")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Model* model;
|
||||||
|
try {
|
||||||
|
model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||||
|
if (skeleton == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlendTree> blendTree;
|
||||||
|
if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) {
|
||||||
|
blendTree = skeleton->BlendTrees.at(e.RootNode);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.Weight >= 0 && e.Weight <= 1) {
|
||||||
|
|
||||||
|
blendTree->SetWeightByName(e.NodeName, e.Weight);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_BlendQueue.clear();
|
m_BlendQueue.clear();
|
||||||
m_BlendQueue.push_back(blendNode);
|
m_BlendQueue.push_back(blendNode);
|
||||||
}
|
}
|
||||||
@@ -124,7 +123,7 @@ bool AutoBlendQueue::HasActiveBlendJob()
|
|||||||
try {
|
try {
|
||||||
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
|
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
m_BlendQueue.pop_front();
|
//m_BlendQueue.pop_front();
|
||||||
return HasActiveBlendJob();
|
return HasActiveBlendJob();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
|
BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
|
||||||
{
|
{
|
||||||
|
|
||||||
m_Skeleton = skeleton;
|
m_Skeleton = skeleton;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ModelEntity.HasComponent("Animation")) {
|
if (ModelEntity.HasComponent("Animation")) {
|
||||||
const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]);
|
const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]);
|
||||||
if (animation == nullptr) {
|
if (animation == nullptr) {
|
||||||
@@ -270,7 +267,7 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
|
|||||||
currentNode = currentNode->Parent;
|
currentNode = currentNode->Parent;
|
||||||
|
|
||||||
if (blendInfo.SingleBlend) {
|
if (blendInfo.SingleBlend) {
|
||||||
break;
|
return blendInfo;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(goalNodes.size() >= 2) {
|
} else if(goalNodes.size() >= 2) {
|
||||||
@@ -331,6 +328,9 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
|
|||||||
|
|
||||||
lastNode = currentNode;
|
lastNode = currentNode;
|
||||||
currentNode = currentNode->Parent;
|
currentNode = currentNode->Parent;
|
||||||
|
if (blendInfo.SingleBlend) {
|
||||||
|
return blendInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,6 +427,55 @@ EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName)
|
|||||||
return subTreeRoots.front()->Entity;
|
return subTreeRoots.front()->Entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<EntityWrapper> BlendTree::GetSingleLevelRoots(std::string name)
|
||||||
|
{
|
||||||
|
std::vector<Node*> nodes = FindNodesByName(name);
|
||||||
|
std::vector<EntityWrapper> entities;
|
||||||
|
|
||||||
|
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||||
|
Node* currentNode = (*it)->Parent;
|
||||||
|
|
||||||
|
if(currentNode->Entity.Valid()) {
|
||||||
|
entities.push_back(currentNode->Entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<EntityWrapper> BlendTree::GetEntitesByName(std::string name)
|
||||||
|
{
|
||||||
|
std::vector<Node*> nodes = FindNodesByName(name);
|
||||||
|
std::vector<EntityWrapper> entities;
|
||||||
|
|
||||||
|
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||||
|
Node* currentNode = (*it);
|
||||||
|
|
||||||
|
if (currentNode->Entity.Valid()) {
|
||||||
|
entities.push_back(currentNode->Entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BlendTree::SetWeightByName(std::string name, double weight)
|
||||||
|
{
|
||||||
|
std::vector<Node*> nodes = FindNodesByName(name);
|
||||||
|
|
||||||
|
for (auto node : nodes) {
|
||||||
|
EntityWrapper entity = node->Entity;
|
||||||
|
|
||||||
|
if(entity.HasComponent("Blend")) {
|
||||||
|
entity["Blend"]["Weight"] = weight;
|
||||||
|
node->Weight = weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BlendTree::Blend(std::map<int, Skeleton::PoseData>& pose)
|
void BlendTree::Blend(std::map<int, Skeleton::PoseData>& pose)
|
||||||
{
|
{
|
||||||
Node* currentNode;
|
Node* currentNode;
|
||||||
|
|||||||
@@ -321,6 +321,8 @@ Skeleton::~Skeleton()
|
|||||||
for (auto &kv : Bones) {
|
for (auto &kv : Bones) {
|
||||||
delete kv.second;
|
delete kv.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlendTrees.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
|
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
|
||||||
|
|||||||
@@ -443,18 +443,34 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* EntityWrapper dashEffectModel;
|
||||||
|
dashEffectModel = playerModel.Clone(dashEffect);
|
||||||
|
player["Transform"].Copy(dashEffectModel["Transform"]);
|
||||||
|
|
||||||
|
|
||||||
|
dashEffectModel.AttachComponent("ExplosionEffect");
|
||||||
|
dashEffectModel["ExplosionEffect"]["EndColor"] = (glm::vec4)playerModel["Model"]["Color"];
|
||||||
|
((glm::vec4&)dashEffectModel["ExplosionEffect"]["EndColor"]).w = 0.f;
|
||||||
|
(double&)dashEffectModel["ExplosionEffect"]["ExplosionDuration"] = dashEffect["Lifetime"]["Lifetime"];
|
||||||
|
(glm::vec3&)dashEffectModel["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 1, 0) + (0.2f * controller->Movement());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auto animationChildren = dashEffectModel.ChildrenWithComponent("Animation");
|
||||||
|
|
||||||
|
for (auto animationEntity : animationChildren) {
|
||||||
|
(bool&)animationEntity["Animation"]["Play"] = false;
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
auto playerEntityAnimation = playerModel["Animation"];
|
|
||||||
|
|
||||||
playerEntityModel.Copy(dashEffect["Model"]);
|
|
||||||
playerEntityAnimation.Copy(dashEffect["Animation"]);
|
|
||||||
dashEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"];
|
|
||||||
((glm::vec4&)dashEffect["ExplosionEffect"]["EndColor"]).w = 0.f;
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user