Blending queues now working
This commit is contained in:
@@ -7,13 +7,12 @@
|
||||
#include "../Core/System.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "Rendering/Model.h"
|
||||
#include "Rendering/EAnimationComplete.h"
|
||||
#include "Rendering/Skeleton.h"
|
||||
#include "Rendering/BlendTree.h"
|
||||
#include "Rendering/EAnimationBlend.h"
|
||||
#include "Rendering/EAutoAnimationBlend.h"
|
||||
#include "../Input/EInputCommand.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
#include "Rendering/AutoBlendQueue.h"
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
@@ -27,10 +26,7 @@ private:
|
||||
void CreateBlendTrees();
|
||||
void UpdateAnimations(double dt);
|
||||
void UpdateWeights(double dt);
|
||||
void AnimationComplete(EntityWrapper animationEntity);
|
||||
|
||||
EventRelay<AnimationSystem, Events::AnimationBlend> m_EAnimationBlend;
|
||||
bool OnAnimationBlend(Events::AnimationBlend& e);
|
||||
EventRelay<AnimationSystem, Events::AutoAnimationBlend> m_EAutoAnimationBlend;
|
||||
bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e);
|
||||
|
||||
@@ -38,40 +34,7 @@ private:
|
||||
EventRelay<AnimationSystem, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
|
||||
struct BlendJob
|
||||
{
|
||||
EntityWrapper BlendEntity = EntityWrapper::Invalid;
|
||||
double StartWeight;
|
||||
double GoalWeight;
|
||||
double Duration;
|
||||
double CurrentTime = 0.0;
|
||||
};
|
||||
|
||||
struct QueuedBlendJob : BlendJob
|
||||
{
|
||||
EntityWrapper AnimationEntity = EntityWrapper::Invalid;
|
||||
};
|
||||
|
||||
struct AutoBlendJob
|
||||
{
|
||||
EntityWrapper RootNode = EntityWrapper::Invalid;
|
||||
double Duration;
|
||||
double CurrentTime = 0.0;
|
||||
double Delay = 0.0;
|
||||
BlendTree::AutoBlendInfo BlendInfo;
|
||||
};
|
||||
|
||||
|
||||
std::list<AutoBlendJob> m_AutoBlendJobs;
|
||||
std::unordered_map<EntityWrapper, AutoBlendJob> m_QueuedAutoBlendJobs;
|
||||
std::list<BlendJob> m_BlendJobs;
|
||||
std::list<QueuedBlendJob> m_QueuedBlendJobs;
|
||||
|
||||
char m_AnimationName1[20] = "Run";
|
||||
float m_BlendTime1 = 0.5f;
|
||||
|
||||
char m_AnimationName2[20] = "Jump";
|
||||
float m_BlendTime2 = 0.5f;
|
||||
std::unordered_map<EntityWrapper, AutoBlendQueue> m_AutoBlendQueues;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Skeleton.h"
|
||||
#include "Model.h"
|
||||
#include "BlendTree.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
|
||||
class AutoBlendQueue
|
||||
{
|
||||
@@ -15,11 +16,29 @@ public:
|
||||
double Duration;
|
||||
double CurrentTime = 0.0;
|
||||
double Delay = 0.0;
|
||||
EntityWrapper AnimationEntity = EntityWrapper::Invalid;
|
||||
BlendTree::AutoBlendInfo BlendInfo;
|
||||
};
|
||||
|
||||
struct AutoblendNode
|
||||
{
|
||||
AutoBlendJob BlendJob;
|
||||
double StartTime;
|
||||
double EndTime;
|
||||
};
|
||||
|
||||
AutoBlendQueue() { };
|
||||
|
||||
void Insert(AutoBlendJob autoBlendJob);
|
||||
void UpdateTime(double dt);
|
||||
|
||||
void PrintQueue();
|
||||
bool HasActiveBlendJob();
|
||||
std::shared_ptr<BlendTree> GetBlendTree();
|
||||
|
||||
AutoBlendQueue::AutoBlendJob& GetActiveBlendJob();
|
||||
private:
|
||||
std::map<double, AutoBlendJob> m_BlendQueue;
|
||||
std::list<AutoblendNode> m_BlendQueue;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -60,8 +60,7 @@ public:
|
||||
{
|
||||
std::string NodeName;
|
||||
double progress;
|
||||
bool Restart;
|
||||
double AnimationSpeed;
|
||||
bool Start;
|
||||
std::unordered_map<EntityWrapper, double> StartWeights;
|
||||
};
|
||||
|
||||
@@ -78,6 +77,11 @@ public:
|
||||
void PrintTree();
|
||||
BlendTree::AutoBlendInfo AutoBlendStep(AutoBlendInfo blendInfo);
|
||||
|
||||
BlendTree::Node* GetCommonParent(std::string NodeName1, std::string NodeName2);
|
||||
BlendTree::Node* FirstCommonParent(Node* node1, Node* node2);
|
||||
|
||||
EntityWrapper GetSubTreeRoot(std::string nodeName);
|
||||
|
||||
private:
|
||||
Skeleton* m_Skeleton = nullptr;
|
||||
Node* m_Root = nullptr;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef Events_AnimationBlend_h__
|
||||
#define Events_AnimationBlend_h__
|
||||
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct AnimationBlend : Event
|
||||
{
|
||||
EntityWrapper BlendEntity = EntityWrapper::Invalid;
|
||||
double GoalWeight;
|
||||
double Duration;
|
||||
|
||||
EntityWrapper AnimationEntity = EntityWrapper::Invalid;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,9 +13,9 @@ struct AutoAnimationBlend : Event
|
||||
std::string NodeName;
|
||||
double Duration = 0.0;
|
||||
double Delay = 0.0;
|
||||
|
||||
|
||||
double AnimationSpeed = 1.0;
|
||||
|
||||
bool Start = false;
|
||||
bool Reverse = false;
|
||||
bool Restart = false;
|
||||
|
||||
EntityWrapper AnimationEntity = EntityWrapper::Invalid;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<Animation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Animation.xsd">
|
||||
<AnimationName></AnimationName>
|
||||
<Time>0</Time>
|
||||
<Play>false</Play>
|
||||
<Reverse>false</Reverse>
|
||||
<Speed>0</Speed>
|
||||
<Loop>true</Loop>
|
||||
<Additive>false</Additive>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<xs:element name="AnimationName" type="t:string" minOccurs="0"/>
|
||||
<xs:element name="Time" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Speed" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Play" type="t:bool" minOccurs="0"/>
|
||||
<xs:element name="Reverse" type="t:bool" minOccurs="0"/>
|
||||
<xs:element name="Loop" type="t:bool" minOccurs="0"/>
|
||||
<xs:element name="Additive" type="t:bool" minOccurs="0"/>
|
||||
</xs:all>
|
||||
|
||||
@@ -68,9 +68,9 @@
|
||||
<Resource>Models/Weapons/Blue/AssaultWeaponBlue.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0.153846264" Y="1.07432497" Z="-0.209223658"/>
|
||||
<Position X="0.165889457" Y="1.06815922" Z="-0.204587683"/>
|
||||
<Orientation X="-0.0241590273" Y="-0.118801616" Z="0.15191035"/>
|
||||
<Scale X="1.00000012" Y="1" Z="1.00000012"/>
|
||||
<Orientation X="-0.033799246" Y="-0.120032266" Z="0.188354403"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
@@ -85,11 +85,11 @@
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity name="AimPrimary">
|
||||
<Entity name="AimSecondary">
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<AnimationName>AimRifleA</AnimationName>
|
||||
<Time>0.49999979138374329</Time>
|
||||
<AnimationName>AimSecWepA</AnimationName>
|
||||
<Time>0.5</Time>
|
||||
<Loop>false</Loop>
|
||||
<Additive>true</Additive>
|
||||
</c:Animation>
|
||||
@@ -97,11 +97,11 @@
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity name="AimSecondary">
|
||||
<Entity name="AimPrimary">
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<AnimationName>AimSecWepA</AnimationName>
|
||||
<Time>0.5</Time>
|
||||
<AnimationName>AimRifleA</AnimationName>
|
||||
<Time>0.49999979138374329</Time>
|
||||
<Loop>false</Loop>
|
||||
<Additive>true</Additive>
|
||||
</c:Animation>
|
||||
@@ -125,7 +125,7 @@
|
||||
<c:Blend>
|
||||
<Pose1>StandCrouchBlend</Pose1>
|
||||
<Pose2>JumpDashBlend</Pose2>
|
||||
<Weight>0</Weight>
|
||||
<Weight>0.00067602147306955462</Weight>
|
||||
</c:Blend>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -183,8 +183,9 @@
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<AnimationName>RunF</AnimationName>
|
||||
<Time>0.032768287014830921</Time>
|
||||
<Time>0.44556648193146309</Time>
|
||||
<Speed>1</Speed>
|
||||
<Play>true</Play>
|
||||
</c:Animation>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -317,7 +318,7 @@
|
||||
<c:Blend>
|
||||
<Pose1>Jump</Pose1>
|
||||
<Pose2>DashBlend</Pose2>
|
||||
<Weight>1</Weight>
|
||||
<Weight>0.01016461050458084</Weight>
|
||||
</c:Blend>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -327,6 +328,8 @@
|
||||
<c:Animation>
|
||||
<AnimationName>JumpF</AnimationName>
|
||||
<Time>0.5</Time>
|
||||
<Speed>1</Speed>
|
||||
<Loop>false</Loop>
|
||||
</c:Animation>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -337,7 +340,7 @@
|
||||
<c:Blend>
|
||||
<Pose1>DashFBBlend</Pose1>
|
||||
<Pose2>DashLRBlend</Pose2>
|
||||
<Weight>0</Weight>
|
||||
<Weight>0.99999999999984523</Weight>
|
||||
</c:Blend>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -347,7 +350,7 @@
|
||||
<c:Blend>
|
||||
<Pose1>DashForward</Pose1>
|
||||
<Pose2>DashBackward</Pose2>
|
||||
<Weight>1</Weight>
|
||||
<Weight>0.98238059685988577</Weight>
|
||||
</c:Blend>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -356,6 +359,8 @@
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<AnimationName>DashForwardF</AnimationName>
|
||||
<Time>1</Time>
|
||||
<Speed>1</Speed>
|
||||
<Loop>false</Loop>
|
||||
</c:Animation>
|
||||
<c:Transform/>
|
||||
@@ -367,6 +372,7 @@
|
||||
<c:Animation>
|
||||
<AnimationName>DashBackwardF</AnimationName>
|
||||
<Time>1</Time>
|
||||
<Speed>1</Speed>
|
||||
<Loop>false</Loop>
|
||||
</c:Animation>
|
||||
<c:Transform/>
|
||||
@@ -380,7 +386,7 @@
|
||||
<c:Blend>
|
||||
<Pose1>DashLeft</Pose1>
|
||||
<Pose2>DashRight</Pose2>
|
||||
<Weight>0</Weight>
|
||||
<Weight>0.96547196574235861</Weight>
|
||||
</c:Blend>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -390,6 +396,7 @@
|
||||
<c:Animation>
|
||||
<AnimationName>DashLeftF</AnimationName>
|
||||
<Time>1</Time>
|
||||
<Speed>1</Speed>
|
||||
<Loop>false</Loop>
|
||||
</c:Animation>
|
||||
<c:Transform/>
|
||||
@@ -400,6 +407,8 @@
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<AnimationName>DashRightF</AnimationName>
|
||||
<Time>1</Time>
|
||||
<Speed>1</Speed>
|
||||
<Loop>false</Loop>
|
||||
</c:Animation>
|
||||
<c:Transform/>
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
AnimationSystem::AnimationSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EAnimationBlend, &AnimationSystem::OnAnimationBlend);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &AnimationSystem::OnInputCommand);
|
||||
}
|
||||
|
||||
void AnimationSystem::Update(double dt)
|
||||
{
|
||||
ImGui::InputText("AnimationName1", &m_AnimationName1[0], sizeof(m_AnimationName1));
|
||||
ImGui::SliderFloat("Blendtime1", &m_BlendTime1, 0.f, 10.f);
|
||||
ImGui::InputText("AnimationName2", &m_AnimationName2[0], sizeof(m_AnimationName2));
|
||||
ImGui::SliderFloat("Blendtime2", &m_BlendTime2, 0.f, 10.f);
|
||||
|
||||
UpdateAnimations(dt);
|
||||
CreateBlendTrees();
|
||||
UpdateWeights(dt);
|
||||
|
||||
|
||||
for(auto& autoBlendQueue : m_AutoBlendQueues) {
|
||||
autoBlendQueue.second.UpdateTime(dt);
|
||||
// autoBlendQueue.second.PrintQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationSystem::CreateBlendTrees()
|
||||
@@ -91,66 +91,29 @@ void AnimationSystem::UpdateAnimations(double dt)
|
||||
|
||||
double animationSpeed = (double)animationC["Speed"];
|
||||
|
||||
if (animationSpeed != 0.0) {
|
||||
if((bool)animationC["Reverse"]) {
|
||||
animationSpeed *= -1;
|
||||
}
|
||||
|
||||
|
||||
if ((bool)animationC["Play"]) {
|
||||
|
||||
double nextTime = (double)animationC["Time"] + animationSpeed * dt;
|
||||
|
||||
|
||||
//Pre animation end blend
|
||||
if (m_QueuedAutoBlendJobs.find(entity) != m_QueuedAutoBlendJobs.end()) {
|
||||
if (glm::sign(m_QueuedAutoBlendJobs.at(entity).Delay) < 0) {
|
||||
if (!(bool)animationC["Loop"]) {
|
||||
if (nextTime > animation->Duration + m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) > 0) {
|
||||
AnimationComplete(entity);
|
||||
} else if (nextTime < 0 - m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) < 0) {
|
||||
AnimationComplete(entity);
|
||||
}
|
||||
} else {
|
||||
if (nextTime > animation->Duration + m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) > 0) {
|
||||
AnimationComplete(entity);
|
||||
} else if (nextTime < 0 - m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) < 0) {
|
||||
AnimationComplete(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(bool)animationC["Loop"]) {
|
||||
if (nextTime > animation->Duration) {
|
||||
nextTime = animation->Duration;
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationC["AnimationName"];
|
||||
m_EventBroker->Publish(e);
|
||||
AnimationComplete(entity);
|
||||
(double&)animationC["Speed"] = 0.0;
|
||||
(bool&)animationC["Play"] = false;
|
||||
} else if (nextTime < 0) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationC["AnimationName"];
|
||||
m_EventBroker->Publish(e);
|
||||
AnimationComplete(entity);
|
||||
nextTime = 0;
|
||||
(double&)animationC["Speed"] = 0.0;
|
||||
(bool&)animationC["Play"] = false;
|
||||
}
|
||||
} else {
|
||||
if (nextTime > animation->Duration) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationC["AnimationName"];
|
||||
m_EventBroker->Publish(e);
|
||||
AnimationComplete(entity);
|
||||
|
||||
while (nextTime > animation->Duration) {
|
||||
nextTime -= animation->Duration;
|
||||
}
|
||||
} else if (nextTime < 0) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationC["AnimationName"];
|
||||
m_EventBroker->Publish(e);
|
||||
AnimationComplete(entity);
|
||||
while (nextTime < 0) {
|
||||
nextTime += animation->Duration;
|
||||
}
|
||||
@@ -164,154 +127,27 @@ void AnimationSystem::UpdateAnimations(double dt)
|
||||
|
||||
void AnimationSystem::UpdateWeights(double dt)
|
||||
{
|
||||
for (auto it = m_BlendJobs.begin(); it != m_BlendJobs.end();) {
|
||||
if (!it->BlendEntity.Valid()) {
|
||||
it = m_BlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
for (auto& autoBlendQueue : m_AutoBlendQueues) {
|
||||
|
||||
if (it->BlendEntity.HasComponent("Blend")) {
|
||||
it->CurrentTime += dt;
|
||||
double progress = it->CurrentTime / it->Duration;
|
||||
progress = glm::clamp(progress, 0.0, 1.0);
|
||||
if(autoBlendQueue.second.HasActiveBlendJob()) {
|
||||
AutoBlendQueue::AutoBlendJob& blendJob = autoBlendQueue.second.GetActiveBlendJob();
|
||||
|
||||
double weight = ((it->GoalWeight - it->StartWeight) * progress) + it->StartWeight;
|
||||
(double&)it->BlendEntity["Blend"]["Weight"] = weight;
|
||||
std::shared_ptr<BlendTree> blendTree = autoBlendQueue.second.GetBlendTree();
|
||||
|
||||
if(weight == it->GoalWeight) {
|
||||
it = m_BlendJobs.erase(it);
|
||||
if (blendTree != nullptr) {
|
||||
blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0);
|
||||
LOG_INFO("Progress: %f, %s", blendJob.BlendInfo.progress, blendJob.BlendInfo.NodeName.c_str());
|
||||
blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
|
||||
for (auto it = m_AutoBlendJobs.begin(); it != m_AutoBlendJobs.end();) {
|
||||
it->CurrentTime += dt;
|
||||
|
||||
if (!it->RootNode.Valid()) {
|
||||
it = m_AutoBlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!it->RootNode.HasComponent("Model")) {
|
||||
it = m_AutoBlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(it->RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<BlendTree> blendTree;
|
||||
if(skeleton->BlendTrees.find(it->RootNode) != skeleton->BlendTrees.end()) {
|
||||
blendTree = skeleton->BlendTrees.at(it->RootNode);
|
||||
} else {
|
||||
it = m_AutoBlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
it->BlendInfo.progress = glm::clamp(it->CurrentTime / it->Duration, 0.0, 1.0);
|
||||
it->BlendInfo = blendTree->AutoBlendStep(it->BlendInfo);
|
||||
|
||||
|
||||
if (it->CurrentTime >= it->Duration) {
|
||||
it = m_AutoBlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::AnimationComplete(EntityWrapper animationEntity)
|
||||
{
|
||||
for (auto it = m_QueuedBlendJobs.begin(); it != m_QueuedBlendJobs.end();) {
|
||||
if (!it->BlendEntity.Valid() || !it->AnimationEntity.Valid()) {
|
||||
it = m_QueuedBlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(animationEntity == it->AnimationEntity) {
|
||||
BlendJob bj;
|
||||
bj.BlendEntity = it->BlendEntity;
|
||||
bj.StartWeight = it->StartWeight;
|
||||
bj.GoalWeight = it->GoalWeight;
|
||||
bj.Duration = it->Duration;
|
||||
bj.CurrentTime = 0.0;
|
||||
m_BlendJobs.push_back(bj);
|
||||
it = m_QueuedBlendJobs.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
|
||||
if (m_QueuedAutoBlendJobs.find(animationEntity) != m_QueuedAutoBlendJobs.end()) {
|
||||
AutoBlendJob abj = m_QueuedAutoBlendJobs.at(animationEntity);
|
||||
|
||||
if (!abj.RootNode.Valid() || !animationEntity.Valid()) {
|
||||
m_QueuedAutoBlendJobs.erase(animationEntity);
|
||||
} else {
|
||||
m_AutoBlendJobs.push_back(abj);
|
||||
m_QueuedAutoBlendJobs.erase(animationEntity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool AnimationSystem::OnAnimationBlend(Events::AnimationBlend& e)
|
||||
{
|
||||
if(!e.BlendEntity.Valid()) {
|
||||
return false;
|
||||
}
|
||||
if(!e.BlendEntity.HasComponent("Blend")){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.AnimationEntity.Valid()) {
|
||||
if (e.AnimationEntity.HasComponent("Animation")) {
|
||||
QueuedBlendJob qbj;
|
||||
qbj.BlendEntity = e.BlendEntity;
|
||||
qbj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"];
|
||||
qbj.GoalWeight = e.GoalWeight;
|
||||
qbj.Duration = e.Duration;
|
||||
qbj.CurrentTime = 0.0;
|
||||
qbj.AnimationEntity = e.AnimationEntity;
|
||||
m_QueuedBlendJobs.push_back(qbj);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
BlendJob bj;
|
||||
bj.BlendEntity = e.BlendEntity;
|
||||
bj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"];
|
||||
bj.GoalWeight = e.GoalWeight;
|
||||
bj.Duration = e.Duration;
|
||||
bj.CurrentTime = 0.0;
|
||||
m_BlendJobs.push_back(bj);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e)
|
||||
{
|
||||
|
||||
if(!e.RootNode.Valid()) {
|
||||
return false;
|
||||
}
|
||||
@@ -320,108 +156,80 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.AnimationEntity.Valid()) {
|
||||
AutoBlendJob abj;
|
||||
abj.RootNode = e.RootNode;
|
||||
abj.CurrentTime = 0.0;
|
||||
abj.Duration = e.Duration;
|
||||
abj.Delay = e.Delay;
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlendTree::AutoBlendInfo abInfo;
|
||||
abInfo.NodeName = e.NodeName;
|
||||
abInfo.progress = 0.0;
|
||||
abInfo.Restart = e.Restart;
|
||||
abInfo.AnimationSpeed = e.AnimationSpeed;
|
||||
abj.BlendInfo = abInfo;
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_QueuedAutoBlendJobs[e.AnimationEntity] = abj;
|
||||
return true;
|
||||
std::shared_ptr<BlendTree> blendTree;
|
||||
if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) {
|
||||
blendTree = skeleton->BlendTrees.at(e.RootNode);
|
||||
} else {
|
||||
AutoBlendJob abj;
|
||||
abj.RootNode = e.RootNode;
|
||||
abj.CurrentTime = 0.0;
|
||||
abj.Duration = e.Duration;
|
||||
|
||||
BlendTree::AutoBlendInfo abInfo;
|
||||
abInfo.NodeName = e.NodeName;
|
||||
abInfo.progress = 0.0;
|
||||
abInfo.Restart = e.Restart;
|
||||
abInfo.AnimationSpeed = e.AnimationSpeed;
|
||||
|
||||
abj.BlendInfo = abInfo;
|
||||
|
||||
m_AutoBlendJobs.push_back(abj);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EntityWrapper subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName);
|
||||
|
||||
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;
|
||||
|
||||
if (e.Restart) {
|
||||
EntityWrapper nodeEntity = subTreeRoot.FirstChildByName(e.NodeName);
|
||||
if (nodeEntity.Valid()) {
|
||||
if (nodeEntity.HasComponent("Animation")) {
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(nodeEntity["Animation"]["AnimationName"]);
|
||||
|
||||
if (animation != nullptr) {
|
||||
if (e.Restart) {
|
||||
(bool&)nodeEntity["Animation"]["Reverse"] = e.Reverse;
|
||||
if (e.Reverse) {
|
||||
(double&)nodeEntity["Animation"]["Time"] = animation->Duration;
|
||||
} else {
|
||||
(double&)nodeEntity["Animation"]["Time"] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOG_INFO("Inserting %s blendJob into %s subtree", e.NodeName.c_str(), subTreeRoot.Name().c_str());
|
||||
m_AutoBlendQueues[subTreeRoot].Insert(abj);
|
||||
|
||||
LOG_INFO("\n");
|
||||
m_AutoBlendQueues.at(subTreeRoot).PrintQueue();
|
||||
LOG_INFO("\n");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
{
|
||||
|
||||
if (e.Value == 1.f) {
|
||||
if (e.Command == "BlendTest0") {
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
if (blendComponents == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (auto& bc : *blendComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
|
||||
|
||||
if (entity.Name() == "Assault") {
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = m_BlendTime1;
|
||||
aeb.NodeName = m_AnimationName1;
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
|
||||
m_EventBroker->Publish(aeb);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else if (e.Command == "BlendTest1") {
|
||||
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
if (blendComponents == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (auto& bc : *blendComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
|
||||
|
||||
if (entity.Name() == "Assault") {
|
||||
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = m_BlendTime2;
|
||||
aeb.NodeName = m_AnimationName2;
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = m_BlendTime2;
|
||||
aeb.NodeName = "Run";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("DashLeft");
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(e.Command == "DashForward") {
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
@@ -434,19 +242,21 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
if (entity.Name() == "Assault") {
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.1;
|
||||
aeb.Duration = 0.2;
|
||||
aeb.NodeName = "DashForward";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Start = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.3;
|
||||
aeb.NodeName = "Run";
|
||||
aeb.NodeName = "StandCrouchBlend";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Delay = 0;
|
||||
aeb.Delay = -0.3;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("DashForward");
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
@@ -469,14 +279,16 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
aeb.NodeName = "DashBackward";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Start = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.3;
|
||||
aeb.NodeName = "Run";
|
||||
aeb.NodeName = "StandCrouchBlend";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.Delay = -0.3;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("DashBackward");
|
||||
m_EventBroker->Publish(aeb);
|
||||
@@ -499,15 +311,17 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
aeb.NodeName = "DashLeft";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Start = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.3;
|
||||
aeb.NodeName = "Run";
|
||||
aeb.NodeName = "StandCrouchBlend";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Delay = -0.3;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("DashLeft");
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
@@ -529,14 +343,16 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
aeb.NodeName = "DashRight";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Start = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.3;
|
||||
aeb.NodeName = "Run";
|
||||
aeb.NodeName = "StandCrouchBlend";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Restart = true;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("DashRight");
|
||||
aeb.Delay = -0.3;
|
||||
m_EventBroker->Publish(aeb);
|
||||
@@ -558,20 +374,128 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
aeb.Duration = 0.35;
|
||||
aeb.NodeName = "Jump";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.35;
|
||||
aeb.NodeName = "Run";
|
||||
aeb.Duration = 0.6;
|
||||
aeb.NodeName = "StandCrouchBlend";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("Jump");
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (e.Command == "Reload") {
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
if (blendComponents == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (auto& bc : *blendComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
|
||||
|
||||
if (entity.Name() == "Assault") {
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.2;
|
||||
aeb.NodeName = "ReloadSwitch";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.2;
|
||||
aeb.NodeName = "IdlePrimary";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Delay = -0.1;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("ReloadSwitch");
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (e.Command == "Crouch") {
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
if (blendComponents == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (auto& bc : *blendComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
|
||||
|
||||
if (entity.Name() == "Assault") {
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.3;
|
||||
aeb.NodeName = "CrouchMovement";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (e.Command == "Stand") {
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
if (blendComponents == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (auto& bc : *blendComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
|
||||
|
||||
if (entity.Name() == "Assault") {
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.3;
|
||||
aeb.NodeName = "StandMovement";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (e.Command == "Shoot") {
|
||||
auto blendComponents = m_World->GetComponents("BlendAdditive");
|
||||
|
||||
if (blendComponents == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (auto& bc : *blendComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
|
||||
|
||||
if (entity.Name() == "Assault") {
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.1;
|
||||
aeb.NodeName = "ShootPrimary";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = true;
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
{
|
||||
Events::AutoAnimationBlend aeb;
|
||||
aeb.Duration = 0.1;
|
||||
aeb.NodeName = "IdlePrimary";
|
||||
aeb.RootNode = entity;
|
||||
aeb.Delay = 0.0;
|
||||
aeb.Start = true;
|
||||
aeb.Restart = false;
|
||||
aeb.AnimationEntity = entity.FirstChildByName("ShootPrimary");
|
||||
m_EventBroker->Publish(aeb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
#include "Rendering/AutoBlendQueue.h"
|
||||
|
||||
void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob)
|
||||
{
|
||||
if(!autoBlendJob.RootNode.HasComponent("Model")) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoblendNode blendNode;
|
||||
blendNode.BlendJob = autoBlendJob;
|
||||
blendNode.StartTime = autoBlendJob.Delay;
|
||||
blendNode.EndTime = autoBlendJob.Delay + autoBlendJob.Duration;
|
||||
|
||||
|
||||
|
||||
if (autoBlendJob.AnimationEntity.Valid()) {
|
||||
if (autoBlendJob.AnimationEntity.HasComponent("Animation")) {
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>((std::string)autoBlendJob.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation((std::string)autoBlendJob.AnimationEntity["Animation"]["AnimationName"]);
|
||||
|
||||
if (animation == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
double AnimationDuration = 0.0;
|
||||
|
||||
double animationSpeed = (double)autoBlendJob.AnimationEntity["Animation"]["Speed"];
|
||||
double animationTime = (double)autoBlendJob.AnimationEntity["Animation"]["Time"];
|
||||
|
||||
|
||||
if ((bool)autoBlendJob.AnimationEntity["Animation"]["Reverse"]) {
|
||||
AnimationDuration = (animation->Duration * animationSpeed) - (animation->Duration - animationTime);
|
||||
} else {
|
||||
AnimationDuration = (animation->Duration * animationSpeed) - animationTime;
|
||||
}
|
||||
|
||||
LOG_INFO("Animation Duration %f", AnimationDuration);
|
||||
blendNode.StartTime += AnimationDuration;
|
||||
blendNode.EndTime += AnimationDuration;
|
||||
if (m_BlendQueue.size() == 0) {
|
||||
m_BlendQueue.push_back(blendNode);
|
||||
} else {
|
||||
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if (next != m_BlendQueue.end()) {
|
||||
if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) {
|
||||
LOG_INFO("Inserted %s between %s and %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str(), next->BlendJob.BlendInfo.NodeName.c_str());
|
||||
m_BlendQueue.insert(next, blendNode);
|
||||
return;
|
||||
}
|
||||
} else if(it->StartTime > blendNode.StartTime){
|
||||
LOG_INFO("Inserted %s after %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str());
|
||||
m_BlendQueue.push_front(blendNode);
|
||||
return;
|
||||
} else if (it->StartTime <= blendNode.StartTime) {
|
||||
LOG_INFO("Inserted %s after %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str());
|
||||
m_BlendQueue.push_back(blendNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOG_INFO("Cleared BlendQueue and inserted %s", blendNode.BlendJob.BlendInfo.NodeName.c_str());
|
||||
m_BlendQueue.clear();
|
||||
m_BlendQueue.push_back(blendNode);
|
||||
}
|
||||
|
||||
void AutoBlendQueue::UpdateTime(double dt)
|
||||
{
|
||||
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) {
|
||||
it->EndTime -= dt;
|
||||
it->StartTime -= dt;
|
||||
if (it->EndTime < 0) {
|
||||
it = m_BlendQueue.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AutoBlendQueue::PrintQueue()
|
||||
{
|
||||
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) {
|
||||
LOG_INFO("Start: %f End: %f \t %s", it->StartTime, it->EndTime, it->BlendJob.BlendInfo.NodeName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AutoBlendQueue::HasActiveBlendJob()
|
||||
{
|
||||
if(m_BlendQueue.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
AutoblendNode blendNode = m_BlendQueue.front();
|
||||
if (blendNode.StartTime <= 0) {
|
||||
AutoBlendJob blendJob = blendNode.BlendJob;
|
||||
|
||||
if (!blendJob.RootNode.Valid()) {
|
||||
m_BlendQueue.pop_front();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!blendJob.RootNode.HasComponent("Model")) {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
|
||||
if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) {
|
||||
return true;
|
||||
} else {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<BlendTree> AutoBlendQueue::GetBlendTree()
|
||||
{
|
||||
AutoblendNode blendNode = m_BlendQueue.front();
|
||||
AutoBlendJob blendJob = blendNode.BlendJob;
|
||||
|
||||
if (!blendJob.RootNode.Valid()) {
|
||||
m_BlendQueue.pop_front();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!blendJob.RootNode.HasComponent("Model")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) {
|
||||
return skeleton->BlendTrees.at(blendJob.RootNode);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
AutoBlendQueue::AutoBlendJob& AutoBlendQueue::GetActiveBlendJob()
|
||||
{
|
||||
AutoblendNode& blendNode = m_BlendQueue.front();
|
||||
blendNode.BlendJob.CurrentTime = -blendNode.StartTime;
|
||||
return blendNode.BlendJob;
|
||||
}
|
||||
|
||||
@@ -51,8 +51,6 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
|
||||
}
|
||||
|
||||
m_FinalPose = AccumulateFinalPose();
|
||||
|
||||
|
||||
// PrintTree();
|
||||
}
|
||||
|
||||
@@ -207,18 +205,16 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
|
||||
{
|
||||
std::vector<Node*> goalNodes = FindNodesByName(blendInfo.NodeName);
|
||||
|
||||
if (blendInfo.Restart) {
|
||||
if (blendInfo.Start) {
|
||||
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
|
||||
EntityWrapper entity = (*it)->Entity;
|
||||
|
||||
if (entity.Valid()) {
|
||||
if (entity.HasComponent("Animation")) {
|
||||
(double&)entity["Animation"]["Time"] = 0.0;
|
||||
(double&)entity["Animation"]["Speed"] = blendInfo.AnimationSpeed;
|
||||
(bool&)entity["Animation"]["Play"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
blendInfo.Restart = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,8 +226,6 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
|
||||
|
||||
while (currentNode != nullptr)
|
||||
{
|
||||
|
||||
|
||||
if(!currentNode->Entity.HasComponent("Blend")) {
|
||||
return blendInfo;
|
||||
}
|
||||
@@ -267,6 +261,91 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
|
||||
return blendInfo;
|
||||
}
|
||||
|
||||
|
||||
BlendTree::Node* BlendTree::GetCommonParent(std::string NodeName1, std::string NodeName2)
|
||||
{
|
||||
std::vector<Node*> nodes1 = FindNodesByName(NodeName1);
|
||||
std::vector<Node*> nodes2 = FindNodesByName(NodeName2);
|
||||
|
||||
for (auto it = nodes1.begin(); it != nodes1.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if(next != nodes1.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
(*next) = commonParent;
|
||||
nodes1.erase(it);
|
||||
it = nodes1.begin();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = nodes2.begin(); it != nodes2.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if (next != nodes2.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
(*next) = commonParent;
|
||||
nodes2.erase(it);
|
||||
it = nodes2.begin();
|
||||
}
|
||||
}
|
||||
|
||||
return FirstCommonParent(nodes1.front(), nodes2.front());;
|
||||
}
|
||||
|
||||
|
||||
BlendTree::Node* BlendTree::FirstCommonParent(Node* node1, Node* node2)
|
||||
{
|
||||
std::list<Node*> node1Parents;
|
||||
|
||||
Node* currentNode = node1;
|
||||
while (currentNode != nullptr) {
|
||||
node1Parents.push_back(currentNode);
|
||||
currentNode = currentNode->Parent;
|
||||
}
|
||||
|
||||
currentNode = node2;
|
||||
while (currentNode != nullptr) {
|
||||
for (auto it = node1Parents.begin(); it != node1Parents.end(); it++) {
|
||||
if (currentNode == (*it)) {
|
||||
return currentNode;
|
||||
}
|
||||
}
|
||||
currentNode = currentNode->Parent;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName)
|
||||
{
|
||||
std::vector<Node*> nodes = FindNodesByName(nodeName);
|
||||
|
||||
std::vector<Node*> subTreeRoots;
|
||||
|
||||
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||
Node* currentNode = (*it);
|
||||
while (currentNode->Parent->Type == NodeType::Blend) {
|
||||
currentNode = currentNode->Parent;
|
||||
}
|
||||
subTreeRoots.push_back(currentNode);
|
||||
}
|
||||
|
||||
|
||||
for (auto it = subTreeRoots.begin(); it != subTreeRoots.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if (next != subTreeRoots.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
(*next) = commonParent;
|
||||
subTreeRoots.erase(it);
|
||||
it = subTreeRoots.begin();
|
||||
}
|
||||
}
|
||||
|
||||
return subTreeRoots.front()->Entity;
|
||||
}
|
||||
|
||||
void BlendTree::Blend(std::map<int, Skeleton::PoseData>& pose)
|
||||
{
|
||||
Node* currentNode;
|
||||
|
||||
Reference in New Issue
Block a user