BGE: Fix T46381 : last action frame not updated.

It fix T46381. Normally BL_Action::Update (manage action time, end, loop…) should be called the same number of times as BL_Action::UpdateIPO (update action position, scale ect… in the game object).
But the bug report shows that UpdateIPO is called one less time than Update. To fix it i revert the commit 362b25b382 and implement a mutex in BL_Action::Update.
Example file : {F245823}

Reviewers: lordloki, kupoman, campbellbarton, youle, moguri, sybren

Reviewed By: youle, moguri, sybren

Maniphest Tasks: T39928, T46381

Differential Revision: https://developer.blender.org/D1562
This commit is contained in:
Porteries Tristan 2015-10-19 16:03:40 +02:00 committed by Campbell Barton
parent 349609c743
commit bedc58ac4e
Notes: blender-bot 2023-02-14 08:26:27 +01:00
Referenced by issue #46755, Animation gets broken (needs properer title).
8 changed files with 36 additions and 39 deletions

View File

@ -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),
@ -506,15 +515,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_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
BLI_spin_unlock(&BL_ActionLock);
if (m_done)
ClearControllerList();
}
void BL_Action::UpdateIPOs()
void BL_Action::InitLock()
{
if (!m_done)
m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
BLI_spin_init(&BL_ActionLock);
}
void BL_Action::EndLock()
{
BLI_spin_end(&BL_ActionLock);
}

View File

@ -105,10 +105,6 @@ public:
* Update the action's frame, etc.
*/
void Update(float curtime);
/**
* Update object IPOs (note: not thread-safe!)
*/
void UpdateIPOs();
// Accessors
float GetFrame();
@ -144,6 +140,11 @@ public:
ACT_IPOFLAG_CHILD = 8,
};
/// Initialize a lock for animation thread issues.
static void InitLock();
/// Finalize a lock for animation thread issues.
static void EndLock();
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:BL_Action")
#endif

View File

@ -170,13 +170,3 @@ void BL_ActionManager::Update(float curtime)
}
}
}
void BL_ActionManager::UpdateIPOs()
{
BL_ActionMap::iterator it;
for (it = m_layers.begin(); it != m_layers.end(); ++it)
{
if (!it->second->IsDone())
it->second->UpdateIPOs();
}
}

View File

@ -129,11 +129,6 @@ public:
*/
void Update(float);
/**
* Update object IPOs (note: not thread-safe!)
*/
void UpdateIPOs();
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:BL_ActionManager")
#endif

View File

@ -484,11 +484,6 @@ void KX_GameObject::UpdateActionManager(float curtime)
GetActionManager()->Update(curtime);
}
void KX_GameObject::UpdateActionIPOs()
{
GetActionManager()->UpdateIPOs();
}
float KX_GameObject::GetActionFrame(short layer)
{
return GetActionManager()->GetActionFrame(layer);
@ -952,6 +947,9 @@ void KX_GameObject::InitIPO(bool ipo_as_force,
void KX_GameObject::UpdateIPO(float curframetime,
bool recurse)
{
/* This function shouldn't call BL_Action::Update, not even indirectly,
* as it will cause deadlock due to the lock in BL_Action::Update. */
// just the 'normal' update procedure.
GetSGNode()->SetSimulatedTime(curframetime,recurse);
GetSGNode()->UpdateWorldData(curframetime);

View File

@ -321,12 +321,6 @@ public:
*/
void UpdateActionManager(float curtime);
/**
* Have the action manager update IPOs
* note: not thread-safe!
*/
void UpdateActionIPOs();
/*********************************
* End Animation API
*********************************/

View File

@ -75,6 +75,8 @@
#include "KX_NavMeshObject.h"
#include "BL_Action.h" // For managing action lock.
#define DEFAULT_LOGIC_TIC_RATE 60.0
//#define DEFAULT_PHYSICS_TIC_RATE 60.0
@ -181,6 +183,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
#endif
m_taskscheduler = BLI_task_scheduler_create(TASK_SCHEDULER_AUTO_THREADS);
BL_Action::InitLock();
}
@ -200,6 +204,8 @@ KX_KetsjiEngine::~KX_KetsjiEngine()
if (m_taskscheduler)
BLI_task_scheduler_free(m_taskscheduler);
BL_Action::EndLock();
}

View File

@ -1678,10 +1678,6 @@ void KX_Scene::UpdateAnimations(double curtime)
BLI_task_pool_work_and_wait(pool);
BLI_task_pool_free(pool);
for (int i=0; i<m_animatedlist->GetCount(); ++i) {
((KX_GameObject*)m_animatedlist->GetValue(i))->UpdateActionIPOs();
}
}
void KX_Scene::LogicUpdateFrame(double curtime, bool frame)