diff options
Diffstat (limited to 'source/gameengine/Ketsji/BL_Action.cpp')
-rw-r--r-- | source/gameengine/Ketsji/BL_Action.cpp | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index 12a1caee221..5889f5ed412 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -56,6 +56,15 @@ extern "C" { #include "BKE_library.h" #include "BKE_global.h" +#include "BLI_threads.h" // for lock + +/* Lock to solve animation thread issues. + * A spin lock is better than a mutex in case of short wait + * because spin lock stop the thread by a loop contrary to mutex + * which switch all memory, process. + */ +static SpinLock BL_ActionLock; + BL_Action::BL_Action(class KX_GameObject* gameobj) : m_action(NULL), @@ -65,8 +74,7 @@ BL_Action::BL_Action(class KX_GameObject* gameobj) m_obj(gameobj), m_startframe(0.f), m_endframe(0.f), - m_endtime(0.f), - m_localtime(0.f), + m_localframe(0.f), m_blendin(0.f), m_blendframe(0.f), m_blendstart(0.f), @@ -252,12 +260,11 @@ bool BL_Action::Play(const char* name, // Now that we have an action, we have something we can play m_starttime = -1.f; // We get the start time on our first update - m_startframe = m_localtime = start; + m_startframe = m_localframe = start; m_endframe = end; m_blendin = blendin; m_playmode = play_mode; m_blendmode = blend_mode; - m_endtime = 0.f; m_blendframe = 0.f; m_blendstart = 0.f; m_speed = playback_speed; @@ -268,11 +275,6 @@ bool BL_Action::Play(const char* name, return true; } -void BL_Action::Stop() -{ - m_done = true; -} - bool BL_Action::IsDone() { return m_done; @@ -298,7 +300,7 @@ bAction *BL_Action::GetAction() float BL_Action::GetFrame() { - return m_localtime; + return m_localframe; } const char *BL_Action::GetName() @@ -321,7 +323,7 @@ void BL_Action::SetFrame(float frame) else if (frame > max(m_startframe, m_endframe)) frame = max(m_startframe, m_endframe); - m_localtime = frame; + m_localframe = frame; m_calc_localtime = false; } @@ -343,12 +345,12 @@ void BL_Action::SetLocalTime(float curtime) if (m_endframe < m_startframe) dt = -dt; - m_localtime = m_startframe + dt; + m_localframe = m_startframe + dt; } void BL_Action::ResetStartTime(float curtime) { - float dt = (m_localtime > m_startframe) ? m_localtime - m_startframe : m_startframe - m_localtime; + float dt = (m_localframe > m_startframe) ? m_localframe - m_startframe : m_startframe - m_localframe; m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed); SetLocalTime(curtime); @@ -396,7 +398,7 @@ void BL_Action::Update(float curtime) curtime -= KX_KetsjiEngine::GetSuspendedDelta(); - // Grab the start time here so we don't end up with a negative m_localtime when + // Grab the start time here so we don't end up with a negative m_localframe when // suspending and resuming scenes. if (m_starttime < 0) m_starttime = curtime; @@ -410,16 +412,16 @@ void BL_Action::Update(float curtime) } // Handle wrap around - if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) { + if (m_localframe < min(m_startframe, m_endframe) || m_localframe > max(m_startframe, m_endframe)) { switch (m_playmode) { case ACT_MODE_PLAY: // Clamp - m_localtime = m_endframe; + m_localframe = m_endframe; m_done = true; break; case ACT_MODE_LOOP: // Put the time back to the beginning - m_localtime = m_startframe; + m_localframe = m_startframe; m_starttime = curtime; break; case ACT_MODE_PING_PONG: @@ -442,7 +444,7 @@ void BL_Action::Update(float curtime) obj->GetPose(&m_blendpose); // Extract the pose from the action - obj->SetPoseByAction(m_tmpaction, m_localtime); + obj->SetPoseByAction(m_tmpaction, m_localframe); // Handle blending between armature actions if (m_blendin && m_blendframe<m_blendin) @@ -476,7 +478,7 @@ void BL_Action::Update(float curtime) PointerRNA ptrrna; RNA_id_pointer_create(&key->id, &ptrrna); - animsys_evaluate_action(&ptrrna, m_tmpaction, NULL, m_localtime); + animsys_evaluate_action(&ptrrna, m_tmpaction, NULL, m_localframe); // Handle blending between shape actions if (m_blendin && m_blendframe < m_blendin) @@ -506,15 +508,23 @@ void BL_Action::Update(float curtime) } } - // This isn't thread-safe, so we move it into it's own function for now - //m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD); + BLI_spin_lock(&BL_ActionLock); + /* This function is not thread safe because of recursive scene graph transform + * updates on children. e.g: If an object and one of its children is animated, + * the both can write transform at the same time. A thread lock avoid problems. */ + m_obj->UpdateIPO(m_localframe, m_ipo_flags & ACT_IPOFLAG_CHILD); + BLI_spin_unlock(&BL_ActionLock); if (m_done) ClearControllerList(); } -void BL_Action::UpdateIPOs() +void BL_Action::InitLock() +{ + BLI_spin_init(&BL_ActionLock); +} + +void BL_Action::EndLock() { - if (!m_done) - m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD); + BLI_spin_end(&BL_ActionLock); } |