/** Test that a custom animator can remove itself cleanly from an ISceneNode during its * own animateNode() loop. * http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=32271 */ bool removeCustomAnimator(void) { IrrlichtDevice * device = irr::createDevice(video::EDT_NULL, dimension2du(160, 120)); assert(device); if(!device) return false; ISceneManager * smgr = device->getSceneManager(); ISceneNode * node = smgr->addEmptySceneNode(); CustomAnimator * instantlyElapsing1 = new CustomAnimator(); CustomAnimator * instantlyElapsing2 = new CustomAnimator(); node->addAnimator(instantlyElapsing1); node->addAnimator(instantlyElapsing2); // This should result in both custom animators being removed and // deleted cleanly, without a crash. node->OnAnimate(0); device->drop(); // If we didn't crash, then the test passed. return true; }
//! Overide OnAnimate void CGameColladaContainerSceneNode::OnAnimate(irr::u32 timeMs) { if ( IsVisible == false ) return; // animate this node with all animators ISceneNodeAnimatorList::Iterator ait = Animators.begin(), aend = Animators.end(); while (ait != aend) { (*ait)->animateNode(this, timeMs); ++ait; } // update absolute position updateAbsolutePosition(); // call child OnAnimate and destroy recursive std::queue<ISceneNode*> queue; ISceneNodeList::ConstIterator it = Children.begin(), end = Children.end(); while ( it != end ) { queue.push( (*it) ); it++; } while ( queue.size() ) { ISceneNode* top = queue.front(); queue.pop(); // call child OnAnimate top->OnAnimate( timeMs ); it = top->getChildren().begin(); end = top->getChildren().end(); while ( it != end ) { queue.push( (*it) ); it++; } } // update node reference for ( int i = 0, n = (int)m_nodeReference.size(); i < n; i++) { CGameColladaSceneNode *colladaNode1 = (CGameColladaSceneNode*) m_nodeReference[i].node1; CGameColladaSceneNode *colladaNode2 = (CGameColladaSceneNode*) m_nodeReference[i].node2; // check anim layer int currentLayer = colladaNode2->getCurrentAnimLayer(); if ( colladaNode1->getCurrentAnimLayer() != currentLayer ) continue; // calc reference matrix core::matrix4 matParentInv = colladaNode2->BaseAbsoluteAnimationMatrixLayer[currentLayer]; core::matrix4 matNode = colladaNode1->BaseAbsoluteAnimationMatrixLayer[currentLayer]; matParentInv.makeInverse(); core::matrix4 relativeMtx = matParentInv*matNode; // recalc animation matrix colladaNode1->AbsoluteAnimationMatrix = colladaNode2->AbsoluteAnimationMatrix*relativeMtx; // calc absolute transform core::matrix4 absoluteTransform = colladaNode2->getAbsoluteTransformation()*relativeMtx; colladaNode1->setAbsoluteTransform(absoluteTransform); colladaNode1->updateChildAbsoluteTransform(); } // update skin std::vector<ISceneNode*>::iterator itSkin = m_boudingMeshNode.begin(), endSkin = m_boudingMeshNode.end(); while ( itSkin != endSkin ) { ((CGameColladaSceneNode*)(*itSkin))->skin(); itSkin++; } }