diff options
author | Mitchell Stokes <mogurijin@gmail.com> | 2011-07-05 09:22:02 +0400 |
---|---|---|
committer | Mitchell Stokes <mogurijin@gmail.com> | 2011-07-05 09:22:02 +0400 |
commit | ceabc6d119caa8132182697bf655f595c468dc2e (patch) | |
tree | eb97faa07b43f9d638875cc07d2026d6c448748a /source/gameengine | |
parent | afd77d081aa9c9fb51e22961e962b13f90da6cd8 (diff) |
BGE Animations: Various fixes and bits of cleanup to get the action actuator to behave more like it did in trunk. The Pepper version is still more sensitive to pulses than the trunk version, but this is more accurate. I might try to address this, but I'm not sure.
Diffstat (limited to 'source/gameengine')
-rw-r--r-- | source/gameengine/Converter/BL_ActionActuator.cpp | 145 | ||||
-rw-r--r-- | source/gameengine/Converter/BL_ActionActuator.h | 53 | ||||
-rw-r--r-- | source/gameengine/Ketsji/BL_Action.cpp | 34 | ||||
-rw-r--r-- | source/gameengine/Ketsji/BL_Action.h | 2 | ||||
-rw-r--r-- | source/gameengine/Ketsji/BL_ActionManager.cpp | 6 | ||||
-rw-r--r-- | source/gameengine/Ketsji/BL_ActionManager.h | 2 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 5 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 6 |
8 files changed, 168 insertions, 85 deletions
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 1cfd46c7e11..f52f8387a6d 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -61,6 +61,49 @@ extern "C" { #include "RNA_define.h" } +BL_ActionActuator::BL_ActionActuator(SCA_IObject* gameobj, + const STR_String& propname, + const STR_String& framepropname, + float starttime, + float endtime, + struct bAction *action, + short playtype, + short blendin, + short priority, + short layer, + float layer_weight, + short ipo_flags, + short end_reset, + float stride) + : SCA_IActuator(gameobj, KX_ACT_ACTION), + + m_lastpos(0, 0, 0), + m_blendframe(0), + m_flag(0), + m_startframe (starttime), + m_endframe(endtime) , + m_starttime(0), + m_localtime(starttime), + m_lastUpdate(-1), + m_blendin(blendin), + m_blendstart(0), + m_stridelength(stride), + m_playtype(playtype), + m_priority(priority), + m_layer(layer), + m_layer_weight(layer_weight), + m_ipo_flags(ipo_flags), + m_pose(NULL), + m_blendpose(NULL), + m_userpose(NULL), + m_action(action), + m_propname(propname), + m_framepropname(framepropname) +{ + if (!end_reset) + m_flag |= ACT_FLAG_CONTINUE; +}; + BL_ActionActuator::~BL_ActionActuator() { if (m_pose) @@ -92,6 +135,7 @@ CValue* BL_ActionActuator::GetReplica() { return replica; } +#if 0 bool BL_ActionActuator::ClampLocalTime() { if (m_startframe < m_endframe) @@ -143,7 +187,7 @@ void BL_ActionActuator::SetLocalTime(float curtime) else m_localtime = m_endframe - delta_time; } - +#endif bool BL_ActionActuator::Update(double curtime, bool frame) { bool bNegativeEvent = false; @@ -156,10 +200,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame) if (!m_action) return false; - // Don't do anything if we're not "active" - if (!frame) - return true; - // Convert playmode if (m_playtype == ACT_ACTION_LOOP_END) play_mode = BL_Action::ACT_MODE_LOOP; @@ -173,32 +213,56 @@ bool BL_ActionActuator::Update(double curtime, bool frame) play_mode = BL_Action::ACT_MODE_PLAY; start = end = prop->GetNumber(); - m_is_going = false; } - + + // Handle events - bNegativeEvent = m_negevent; - bPositiveEvent = m_posevent; - RemoveAllEvents(); - - if (!m_is_going && bPositiveEvent) - { - m_is_going = true; - if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, play_mode, m_layer_weight, m_ipo_flags) && m_end_reset) - obj->SetActionFrame(m_layer, m_localtime); + if (frame) + { + bNegativeEvent = m_negevent; + bPositiveEvent = m_posevent; + RemoveAllEvents(); } - else if (m_is_going && bNegativeEvent) - { - if (m_playtype == ACT_ACTION_LOOP_STOP) + + if (bPositiveEvent) + { + if (m_flag & ACT_FLAG_ACTIVE && m_flag & ACT_FLAG_CONTINUE) + start = m_localtime = obj->GetActionFrame(m_layer); + + if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, play_mode, m_layer_weight, m_ipo_flags)) { - if (!m_end_reset) - { - obj->StopAction(m_layer); - return false; - } + m_flag |= ACT_FLAG_ACTIVE; + if (m_flag & ACT_FLAG_CONTINUE) + obj->SetActionFrame(m_layer, m_localtime); + + if (m_playtype == ACT_ACTION_PLAY) + m_flag |= ACT_FLAG_PLAY_END; + else + m_flag &= ~ACT_FLAG_PLAY_END; + } + else + return false; + } + else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent) + { + bAction *curr_action = obj->GetCurrentAction(m_layer); + if (curr_action && curr_action != m_action) + { + // Someone changed the action on us, so we wont mess with it + // Hopefully there wont be too many problems with two actuators using + // the same action... + m_flag &= ~ACT_FLAG_ACTIVE; + return false; + } + if (m_playtype == ACT_ACTION_LOOP_STOP) + { m_localtime = obj->GetActionFrame(m_layer); obj->StopAction(m_layer); // Stop the action after getting the frame + + // We're done + m_flag &= ~ACT_FLAG_ACTIVE; + return false; } else if (m_playtype == ACT_ACTION_LOOP_END) { @@ -207,7 +271,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) obj->StopAction(m_layer); obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags); - return true; + m_flag |= ACT_FLAG_PLAY_END; } else if (m_playtype == ACT_ACTION_FLIPPER) { @@ -217,14 +281,12 @@ bool BL_ActionActuator::Update(double curtime, bool frame) obj->StopAction(m_layer); obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags); - return true; + m_flag |= ACT_FLAG_PLAY_END; } - - m_is_going = false; } // Handle a frame property if it's defined - if (m_is_going && m_framepropname[0] != 0) + if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0) { CValue* oldprop = obj->GetProperty(m_framepropname); CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer)); @@ -235,10 +297,11 @@ bool BL_ActionActuator::Update(double curtime, bool frame) newval->Release(); } + // Handle a finished animation - if (m_is_going && obj->IsActionDone(m_layer)) + if ((m_flag & ACT_FLAG_PLAY_END) && obj->IsActionDone(m_layer)) { - m_is_going = false; + m_flag &= ~ACT_FLAG_ACTIVE; obj->StopAction(m_layer); return false; } @@ -740,7 +803,7 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame), KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname), KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname), - KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset), + KX_PYATTRIBUTE_RW_FUNCTION("useContinue", BL_ActionActuator, pyattr_get_use_continue, pyattr_set_use_continue), KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime), KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType), { NULL } //Sentinel @@ -800,4 +863,22 @@ PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYA return ret; } +PyObject* BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v); + return PyBool_FromLong(self->m_flag & ACT_FLAG_CONTINUE); +} + +int BL_ActionActuator::pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v); + + if (PyObject_IsTrue(value)) + self->m_flag |= ACT_FLAG_CONTINUE; + else + self->m_flag &= ~ACT_FLAG_CONTINUE; + + return PY_SET_ATTR_SUCCESS; +} + #endif // WITH_PYTHON diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 3004aa2e6ca..7b4200fa19b 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -56,35 +56,8 @@ public: float layer_weight, short ipo_flags, short end_reset, - float stride) - : SCA_IActuator(gameobj, KX_ACT_ACTION), - - m_lastpos(0, 0, 0), - m_blendframe(0), - m_flag(0), - m_startframe (starttime), - m_endframe(endtime) , - m_starttime(0), - m_localtime(starttime), - m_lastUpdate(-1), - m_blendin(blendin), - m_blendstart(0), - m_stridelength(stride), - m_playtype(playtype), - m_priority(priority), - m_layer(layer), - m_layer_weight(layer_weight), - m_ipo_flags(ipo_flags), - m_end_reset(end_reset), - m_is_going(false), - m_pose(NULL), - m_blendpose(NULL), - m_userpose(NULL), - m_action(action), - m_propname(propname), - m_framepropname(framepropname) - { - }; + float stride); + virtual ~BL_ActionActuator(); virtual bool Update(double curtime, bool frame); virtual CValue* GetReplica(); @@ -103,6 +76,9 @@ public: static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + /* attribute check */ static int CheckFrame(void *self, const PyAttributeDef*) { @@ -147,9 +123,9 @@ public: protected: - void SetStartTime(float curtime); - void SetLocalTime(float curtime); - bool ClampLocalTime(); + //void SetStartTime(float curtime); + //void SetLocalTime(float curtime); + //bool ClampLocalTime(); MT_Point3 m_lastpos; float m_blendframe; @@ -172,8 +148,6 @@ protected: short m_priority; short m_layer; short m_ipo_flags; - bool m_end_reset; - bool m_is_going; struct bPose* m_pose; struct bPose* m_blendpose; struct bPose* m_userpose; @@ -183,10 +157,13 @@ protected: }; enum { - ACT_FLAG_REVERSE = 0x00000001, - ACT_FLAG_LOCKINPUT = 0x00000002, - ACT_FLAG_KEYUP = 0x00000004, - ACT_FLAG_ACTIVE = 0x00000008 + ACT_FLAG_REVERSE = 1<<0, + ACT_FLAG_LOCKINPUT = 1<<1, + ACT_FLAG_KEYUP = 1<<2, + ACT_FLAG_ACTIVE = 1<<3, + ACT_FLAG_CONTINUE = 1<<4, + ACT_FLAG_PLAY_END = 1<<5 + }; #endif diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index 04d05d87c06..f1b53fc4151 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -62,8 +62,7 @@ BL_Action::BL_Action(class KX_GameObject* gameobj) m_blendinpose(NULL), m_sg_contr(NULL), m_ptrrna(NULL), - m_done(true), - m_bcalc_local_time(true) + m_done(true) { if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { @@ -197,6 +196,11 @@ void BL_Action::InitIPO() m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL); } +bAction *BL_Action::GetAction() +{ + return (IsDone()) ? NULL : m_action; +} + float BL_Action::GetFrame() { return m_localtime; @@ -204,14 +208,24 @@ float BL_Action::GetFrame() void BL_Action::SetFrame(float frame) { + float dt; + // Clamp the frame to the start and end frame if (frame < min(m_startframe, m_endframe)) frame = min(m_startframe, m_endframe); else if (frame > max(m_startframe, m_endframe)) frame = max(m_startframe, m_endframe); + + // We don't set m_localtime directly since it's recalculated + // in the next update. So, we modify the value (m_starttime) + // used to calculate m_localtime the next time SetLocalTime() is called. + + dt = frame-m_startframe; + + if (m_endframe < m_startframe) + dt = -dt; - m_localtime = frame; - m_bcalc_local_time = false; + m_starttime -= dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed); } void BL_Action::SetLocalTime(float curtime) @@ -263,16 +277,8 @@ void BL_Action::Update(float curtime) if (m_done) return; - // We only want to calculate the current time if we weren't given a frame (e.g., from SetFrame()) - if (m_bcalc_local_time) - { - curtime -= KX_KetsjiEngine::GetSuspendedDelta(); - SetLocalTime(curtime); - } - else - { - m_bcalc_local_time = true; - } + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + SetLocalTime(curtime); // Handle wrap around if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h index eea00b15036..f7c5a811721 100644 --- a/source/gameengine/Ketsji/BL_Action.h +++ b/source/gameengine/Ketsji/BL_Action.h @@ -66,7 +66,6 @@ private: short m_ipo_flags; bool m_done; - bool m_bcalc_local_time; void InitIPO(); void SetLocalTime(float curtime); @@ -91,6 +90,7 @@ public: // Accessors float GetFrame(); + struct bAction *GetAction(); // Mutators void SetFrame(float frame); diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp index 8d862c38961..c3b4dc5d4db 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.cpp +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -56,6 +56,12 @@ void BL_ActionManager::SetActionFrame(short layer, float frame) m_layers[layer]->SetFrame(frame); } +struct bAction *BL_ActionManager::GetCurrentAction(short layer) +{ + if (m_layers[layer]) + return m_layers[layer]->GetAction(); +} + bool BL_ActionManager::PlayAction(const char* name, float start, float end, diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h index 3836c6b59d2..c527c7bbd3a 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.h +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -56,6 +56,8 @@ public: float GetActionFrame(short layer); void SetActionFrame(short layer, float frame); + struct bAction *GetCurrentAction(short layer); + void StopAction(short layer); bool IsActionDone(short layer); void Update(float); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 334868d283a..3404cd227f0 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -399,6 +399,11 @@ void KX_GameObject::SetActionFrame(short layer, float frame) GetActionManager()->SetActionFrame(layer, frame); } +bAction *KX_GameObject::GetCurrentAction(short layer) +{ + return GetActionManager()->GetCurrentAction(layer); +} + void KX_GameObject::ProcessReplica() { SCA_IObject::ProcessReplica(); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 96bd42ba702..6e22dc5fbc3 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -65,6 +65,7 @@ class PHY_IGraphicController; class PHY_IPhysicsEnvironment; class BL_ActionManager; struct Object; +struct bAction; #ifdef WITH_PYTHON /* utility conversion function */ @@ -233,6 +234,11 @@ public: void SetActionFrame(short layer, float frame); /** + * Gets the currently running action on the given layer + */ + bAction *GetCurrentAction(short layer); + + /** * Remove an action from the object's action manager */ void StopAction(short layer); |