From 39bbf3854a5c91e3d8e410d01b34d4e88df20879 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Wed, 1 Jun 2011 07:42:40 +0000 Subject: [PATCH] BGE Animations: Reimplemented the continuous function of the action actuator. * To do this, I've added Get/SetFrame() functions. * I've also cleaned up a little bit of the wrap around logic in BL_Action.cpp. --- .../Converter/BL_ActionActuator.cpp | 13 ++++++-- source/gameengine/Ketsji/BL_Action.cpp | 33 +++++++++++++++++-- source/gameengine/Ketsji/BL_Action.h | 6 ++++ source/gameengine/Ketsji/BL_ActionManager.cpp | 14 ++++++++ source/gameengine/Ketsji/BL_ActionManager.h | 4 +++ source/gameengine/Ketsji/KX_GameObject.cpp | 10 ++++++ source/gameengine/Ketsji/KX_GameObject.h | 18 ++++++++++ 7 files changed, 93 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 15727cc3f71..7e5e4e1d1d9 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -173,12 +173,21 @@ bool BL_ActionActuator::Update(double curtime, bool frame) { m_is_going = true; obj->PlayAction(m_action->id.name+2, m_startframe, m_endframe, 0, m_blendin, play_mode); + if (m_end_reset) + obj->SetActionFrame(0, m_localtime); } else if (m_is_going && bNegativeEvent) { m_is_going = false; - obj->StopAction(0); - return false; + + if (!m_end_reset) + { + obj->StopAction(0); + return false; + } + + m_localtime = obj->GetActionFrame(0); + obj->StopAction(0); // Stop the action after getting the frame } // Handle a finished animation diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index 5630179a049..77cb5de1398 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -27,6 +27,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include + #include "BL_Action.h" #include "BL_ArmatureObject.h" #include "KX_IpoConvert.h" @@ -106,6 +108,33 @@ void BL_Action::InitIPO() m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, false); } +float BL_Action::GetFrame() +{ + return m_localtime; +} + +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_starttime -= dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed); +} + void BL_Action::SetLocalTime(float curtime) { float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed; @@ -127,9 +156,7 @@ void BL_Action::Update(float curtime) SetLocalTime(curtime); // Handle wrap around - bool bforward = m_startframe < m_endframe; - if (bforward && (m_localtime < m_startframe || m_localtime > m_endframe) || - !bforward && (m_localtime > m_startframe || m_localtime < m_endframe)) + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) { switch(m_playmode) { diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h index 203714a3b2f..f7d0feb20af 100644 --- a/source/gameengine/Ketsji/BL_Action.h +++ b/source/gameengine/Ketsji/BL_Action.h @@ -77,6 +77,12 @@ public: bool IsDone() {return m_done;} void Update(float curtime); + // Accessors + float GetFrame(); + + // Mutators + void SetFrame(float frame); + enum { ACT_MODE_PLAY = 0, diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp index ddbf287e501..2570cc1f140 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.cpp +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -42,6 +42,20 @@ BL_ActionManager::~BL_ActionManager() StopAction(i); } +float BL_ActionManager::GetActionFrame(short layer) +{ + if (m_layers[layer]) + return m_layers[layer]->GetFrame(); + + return 0.f; +} + +void BL_ActionManager::SetActionFrame(short layer, float frame) +{ + if (m_layers[layer]) + m_layers[layer]->SetFrame(frame); +} + void BL_ActionManager::PlayAction(class KX_GameObject* gameobj, const char* name, float start, diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h index 4509020926f..32e6ce82a76 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.h +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -51,10 +51,14 @@ public: short play_mode=0, short blend_mode=0, float playback_speed=1.f); + + float GetActionFrame(short layer); + void SetActionFrame(short layer, float frame); void StopAction(short layer); bool IsActionDone(short layer); void Update(float); + #ifdef WITH_CXX_GUARDEDALLOC public: void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_ActionManager"); } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index f5115f50d81..0ea775e3fbc 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -379,6 +379,16 @@ void KX_GameObject::UpdateActionManager(float curtime) m_actionManager->Update(curtime); } +float KX_GameObject::GetActionFrame(short layer) +{ + return m_actionManager->GetActionFrame(layer); +} + +void KX_GameObject::SetActionFrame(short layer, float frame) +{ + m_actionManager->SetActionFrame(layer, frame); +} + void KX_GameObject::ProcessReplica() { SCA_IObject::ProcessReplica(); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 75c71833ce1..48d290d289a 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -202,6 +202,10 @@ public: */ void RemoveParent(KX_Scene *scene); + /********************************* + * Animation API + *********************************/ + /** * Adds an action to the object's action manager */ @@ -214,6 +218,16 @@ public: short blend_mode=0, float playback_speed=1.f); + /** + * Gets the current frame of an action + */ + float GetActionFrame(short layer); + + /** + * Sets the current frame of an action + */ + void SetActionFrame(short layer, float frame); + /** * Remove an action from the object's action manager */ @@ -229,6 +243,10 @@ public: */ void UpdateActionManager(float curtime); + /********************************* + * End Animation API + *********************************/ + /** * Construct a game object. This class also inherits the * default constructors - use those with care!