Support proper actuator animation
This commit is contained in:
@@ -2,8 +2,64 @@
|
||||
#define CHARACTER_ANIMATION_MODULE_H_
|
||||
#include <Ogre.h>
|
||||
#include <flecs.h>
|
||||
#include "GameData.h"
|
||||
#include "LuaData.h"
|
||||
namespace ECS
|
||||
{
|
||||
struct AnimationTrigger;
|
||||
struct AnimationTriggerSubscriber {
|
||||
virtual void operator()(const AnimationTrigger *trigger) = 0;
|
||||
};
|
||||
struct AnimationTrigger {
|
||||
Ogre::String name;
|
||||
float time;
|
||||
float weight;
|
||||
std::vector<AnimationTriggerSubscriber *> subscriber_list;
|
||||
float getTriggerTime() const
|
||||
{
|
||||
return time;
|
||||
}
|
||||
float getMinWeight() const
|
||||
{
|
||||
return weight;
|
||||
}
|
||||
const Ogre::String &getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
void notify(float weight)
|
||||
{
|
||||
int i;
|
||||
if (weight < this->weight)
|
||||
return;
|
||||
for (i = 0; i < subscriber_list.size(); i++)
|
||||
(*subscriber_list[i])(this);
|
||||
}
|
||||
void addSubscriber(AnimationTriggerSubscriber *sub)
|
||||
{
|
||||
if (std::find(subscriber_list.begin(), subscriber_list.end(),
|
||||
sub) != subscriber_list.end())
|
||||
return;
|
||||
subscriber_list.push_back(sub);
|
||||
}
|
||||
void removeSubscriber(AnimationTriggerSubscriber *sub)
|
||||
{
|
||||
auto it = std::find(subscriber_list.begin(),
|
||||
subscriber_list.end(), sub);
|
||||
if (it != subscriber_list.end())
|
||||
subscriber_list.erase(it);
|
||||
}
|
||||
void clearSubscribers()
|
||||
{
|
||||
subscriber_list.clear();
|
||||
}
|
||||
AnimationTrigger(const Ogre::String name, float time, float weight)
|
||||
: name(name)
|
||||
, time(time)
|
||||
, weight(weight)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct Animation {
|
||||
Ogre::AnimationState *mAnimationState;
|
||||
Ogre::Animation *mSkelAnimation;
|
||||
@@ -11,6 +67,7 @@ struct Animation {
|
||||
Ogre::NodeAnimationTrack *mRootTrack;
|
||||
float m_weight;
|
||||
float m_accWeight;
|
||||
std::multimap<float, AnimationTrigger *> trigger_list;
|
||||
Animation(Ogre::AnimationState *animState,
|
||||
Ogre::Animation *skelAnimation)
|
||||
: mAnimationState(animState)
|
||||
@@ -30,19 +87,25 @@ struct Animation {
|
||||
// mRootTracks[i]->removeAllKeyFrames();
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
OgreAssert(mHipsTrack, "no hips track");
|
||||
OgreAssert(mRootTrack, "no Root track");
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
Ogre::Vector3 motion = Ogre::Vector3::ZERO;
|
||||
for (j = 0; j < mRootTrack->getNumKeyFrames(); j++) {
|
||||
Ogre::Vector3 trans =
|
||||
mRootTrack->getNodeKeyFrame(j)->getTranslate();
|
||||
if (j == 0)
|
||||
delta = trans;
|
||||
else
|
||||
delta = trans - motion;
|
||||
mRootTrack->getNodeKeyFrame(j)->setTranslate(delta);
|
||||
motion = trans;
|
||||
#endif
|
||||
if (mRootTrack) {
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
Ogre::Vector3 motion = Ogre::Vector3::ZERO;
|
||||
for (j = 0; j < mRootTrack->getNumKeyFrames(); j++) {
|
||||
Ogre::Vector3 trans =
|
||||
mRootTrack->getNodeKeyFrame(j)
|
||||
->getTranslate();
|
||||
if (j == 0)
|
||||
delta = trans;
|
||||
else
|
||||
delta = trans - motion;
|
||||
mRootTrack->getNodeKeyFrame(j)->setTranslate(
|
||||
delta);
|
||||
motion = trans;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ogre::String getName()
|
||||
@@ -78,7 +141,9 @@ struct Animation {
|
||||
}
|
||||
void addTime(float time)
|
||||
{
|
||||
preUpdateTriggers();
|
||||
mAnimationState->addTime(time);
|
||||
postUpdateTriggers(time);
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
@@ -96,6 +161,67 @@ struct Animation {
|
||||
{
|
||||
return m_accWeight;
|
||||
}
|
||||
void addTrigger(AnimationTrigger *trigger)
|
||||
{
|
||||
trigger_list.insert(std::pair<float, AnimationTrigger *>(
|
||||
trigger->getTriggerTime(), trigger));
|
||||
}
|
||||
void clearTriggers()
|
||||
{
|
||||
auto it = trigger_list.begin();
|
||||
while (it != trigger_list.end()) {
|
||||
delete it->second;
|
||||
it++;
|
||||
}
|
||||
trigger_list.clear();
|
||||
}
|
||||
float mpreUpdateTime;
|
||||
void preUpdateTriggers()
|
||||
{
|
||||
mpreUpdateTime = mAnimationState->getTimePosition() /
|
||||
mAnimationState->getLength();
|
||||
}
|
||||
void postUpdateTriggers(float delta)
|
||||
{
|
||||
float postUpdateTime = mAnimationState->getTimePosition() /
|
||||
mAnimationState->getLength();
|
||||
bool positive = delta >= 0.0f;
|
||||
if (positive)
|
||||
updateTriggers(mpreUpdateTime, postUpdateTime);
|
||||
else
|
||||
updateTriggers(postUpdateTime, mpreUpdateTime);
|
||||
}
|
||||
void updateTriggers(float currentTime, float nextTime)
|
||||
{
|
||||
int i;
|
||||
float weight = getWeight();
|
||||
if (currentTime <= nextTime) {
|
||||
auto it = trigger_list.lower_bound(currentTime);
|
||||
while (it != trigger_list.end()) {
|
||||
if (nextTime <=
|
||||
it->second->getTriggerTime()) // in future, sorrted by time
|
||||
return;
|
||||
it->second->notify(weight);
|
||||
}
|
||||
} else {
|
||||
updateTriggers(currentTime, 1);
|
||||
updateTriggers(0, nextTime);
|
||||
}
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
if (getEnabled())
|
||||
return mAnimationState->getLength();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
if (getEnabled())
|
||||
return mAnimationState->getTimePosition();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimationNode {
|
||||
@@ -109,6 +235,8 @@ struct AnimationNode {
|
||||
virtual void addTime(float time) = 0;
|
||||
virtual void setWeight(float weight) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual float getLength() const = 0;
|
||||
virtual float getTimePosition() const = 0;
|
||||
float getWeight()
|
||||
{
|
||||
return m_weight;
|
||||
@@ -121,6 +249,13 @@ struct AnimationNode {
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
virtual float getTime() const
|
||||
{
|
||||
float l = getLength();
|
||||
if (l > 0.0f)
|
||||
return getTimePosition() / l;
|
||||
return 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimationNodeAnimation : AnimationNode {
|
||||
@@ -144,6 +279,20 @@ struct AnimationNodeAnimation : AnimationNode {
|
||||
{
|
||||
mAnimation->reset();
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
if (enabled)
|
||||
return mAnimation->getLength();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
if (enabled)
|
||||
return mAnimation->getTimePosition();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
};
|
||||
struct AnimationNodeStateMachineState : AnimationNode {
|
||||
AnimationNodeStateMachineState()
|
||||
@@ -164,6 +313,14 @@ struct AnimationNodeStateMachineState : AnimationNode {
|
||||
{
|
||||
children[0]->reset();
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
return children[0]->getLength();
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
return children[0]->getLength();
|
||||
}
|
||||
};
|
||||
struct AnimationNodeSpeed : AnimationNode {
|
||||
float m_speed;
|
||||
@@ -187,6 +344,25 @@ struct AnimationNodeSpeed : AnimationNode {
|
||||
{
|
||||
children[0]->reset();
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
if (m_speed > 0.0f || m_speed < 0.0f)
|
||||
return children[0]->getLength() / m_speed;
|
||||
return 0.0f;
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
if (m_speed > 0.0f || m_speed < 0.0f)
|
||||
return children[0]->getTimePosition() / m_speed;
|
||||
return 0.0f;
|
||||
}
|
||||
float getTime() const override
|
||||
{
|
||||
float l = children[0]->getLength();
|
||||
if (l > 0.0f)
|
||||
return children[0]->getTimePosition() / l;
|
||||
return 0.0f;
|
||||
}
|
||||
};
|
||||
struct AnimationNodeStateMachine : AnimationNode {
|
||||
std::map<Ogre::String, AnimationNode *> stateMap;
|
||||
@@ -215,8 +391,10 @@ struct AnimationNodeStateMachine : AnimationNode {
|
||||
configured = true;
|
||||
}
|
||||
if (debug) {
|
||||
std::cout<< "state machine addTime" << std::endl;
|
||||
std::cout << "state machine children: " << children.size() << std::endl;
|
||||
std::cout << "state machine addTime" << std::endl;
|
||||
std::cout
|
||||
<< "state machine children: " << children.size()
|
||||
<< std::endl;
|
||||
}
|
||||
for (i = 0; i < children.size(); i++) {
|
||||
if (debug)
|
||||
@@ -230,8 +408,10 @@ struct AnimationNodeStateMachine : AnimationNode {
|
||||
child->setWeight(Ogre::Math::Clamp<Ogre::Real>(
|
||||
newWeight * m_weight, 0, m_weight));
|
||||
if (debug) {
|
||||
std::cout << "fade in: " << newWeight << std::endl;
|
||||
std::cout << "m_weight: " << m_weight << std::endl;
|
||||
std::cout << "fade in: " << newWeight
|
||||
<< std::endl;
|
||||
std::cout << "m_weight: " << m_weight
|
||||
<< std::endl;
|
||||
}
|
||||
if (newWeight >= 1)
|
||||
fade_in.erase(child);
|
||||
@@ -254,7 +434,8 @@ struct AnimationNodeStateMachine : AnimationNode {
|
||||
int i;
|
||||
if (weight > m_weight && currentAnim)
|
||||
fade_in.insert(currentAnim);
|
||||
if (weight < m_weight && currentAnim && currentAnim->getWeight() > weight)
|
||||
if (weight < m_weight && currentAnim &&
|
||||
currentAnim->getWeight() > weight)
|
||||
currentAnim->setWeight(weight);
|
||||
m_weight = weight;
|
||||
bool enabled = weight > 0.001f;
|
||||
@@ -273,7 +454,8 @@ struct AnimationNodeStateMachine : AnimationNode {
|
||||
{
|
||||
int i;
|
||||
if (debug)
|
||||
std::cout << "children: " << children.size() << std::endl;
|
||||
std::cout << "children: " << children.size()
|
||||
<< std::endl;
|
||||
for (i = 0; i < children.size(); i++)
|
||||
addState(children[i]);
|
||||
if (debug)
|
||||
@@ -312,6 +494,20 @@ struct AnimationNodeStateMachine : AnimationNode {
|
||||
{
|
||||
return mCurrentStateName;
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
if (currentAnim)
|
||||
return currentAnim->getLength();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
if (currentAnim)
|
||||
return currentAnim->getTimePosition();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
#define ANIM_FADE_SPEED \
|
||||
@@ -340,6 +536,14 @@ struct AnimationNodeOutput : AnimationNode {
|
||||
{
|
||||
children[0]->reset();
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
return children[0]->getLength();
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
return children[0]->getTimePosition();
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimationSystem : AnimationNode {
|
||||
@@ -353,6 +557,7 @@ struct AnimationSystem : AnimationNode {
|
||||
std::vector<Animation *> vanimation_list;
|
||||
void add_animation(const Ogre::String &name, Animation *animation)
|
||||
{
|
||||
OgreAssert(animation, "No animation " + name);
|
||||
animation_list[name] = animation;
|
||||
vanimation_list.push_back(animation);
|
||||
}
|
||||
@@ -388,13 +593,49 @@ struct AnimationSystem : AnimationNode {
|
||||
OgreAssert(parent, "bad parent");
|
||||
Animation *animation =
|
||||
mAnimationSystem->animation_list[animation_name];
|
||||
OgreAssert(animation,
|
||||
"bad animation " + animation_name);
|
||||
AnimationNodeAnimation *onode =
|
||||
new AnimationNodeAnimation(animation);
|
||||
OgreAssert(onode, "bad animation");
|
||||
OgreAssert(onode->mAnimation, "bad animation");
|
||||
animation_nodes.push_back(onode);
|
||||
parent->children.push_back(onode);
|
||||
animationNodeList.push_back(onode);
|
||||
return this;
|
||||
}
|
||||
AnimationSystemBuilder *trigger(flecs::entity e,
|
||||
const Ogre::String &name,
|
||||
float time,
|
||||
const Ogre::String &event)
|
||||
{
|
||||
struct EventSubscriber : AnimationTriggerSubscriber {
|
||||
flecs::entity ent;
|
||||
Ogre::String event;
|
||||
void operator()(const AnimationTrigger *trigger)
|
||||
{
|
||||
ECS::get_mut<LuaData>().call_handler(
|
||||
event, ent, ent);
|
||||
}
|
||||
EventSubscriber(flecs::entity e,
|
||||
const Ogre::String &event)
|
||||
: ent(e)
|
||||
, event(event)
|
||||
{
|
||||
}
|
||||
};
|
||||
OgreAssert(parent, "bad parent");
|
||||
Animation *animation =
|
||||
static_cast<AnimationNodeAnimation *>(parent)
|
||||
->mAnimation;
|
||||
OgreAssert(animation, "bad animation");
|
||||
AnimationTrigger *trigger =
|
||||
new AnimationTrigger(name, time, 0.1f);
|
||||
EventSubscriber *sub = new EventSubscriber(e, event);
|
||||
trigger->addSubscriber(sub);
|
||||
animation->addTrigger(trigger);
|
||||
return this;
|
||||
}
|
||||
AnimationSystemBuilder *speed(float speed,
|
||||
const Ogre::String &anchor = "")
|
||||
{
|
||||
@@ -451,6 +692,7 @@ struct AnimationSystem : AnimationNode {
|
||||
for (i = 0; i < m_builder.animationNodeList.size(); i++) {
|
||||
AnimationNodeAnimation *anim =
|
||||
m_builder.animationNodeList[i];
|
||||
OgreAssert(anim->mAnimation, "No animation");
|
||||
float weight = anim->getWeight();
|
||||
anim->mAnimation->increaseAccWeight(weight);
|
||||
#ifdef VDEBUG
|
||||
@@ -490,6 +732,14 @@ struct AnimationSystem : AnimationNode {
|
||||
{
|
||||
return static_cast<T *>(m_builder.nodeMap[name]);
|
||||
}
|
||||
float getLength() const
|
||||
{
|
||||
return m_builder.animation_nodes[0]->getLength();
|
||||
}
|
||||
float getTimePosition() const
|
||||
{
|
||||
return m_builder.animation_nodes[0]->getTimePosition();
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimationControl {
|
||||
|
||||
Reference in New Issue
Block a user