virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { if (_releaseKey) // we hit a key and release it execute an action { osgAnimation::Timeline* tml = _manager->getTimeline(); // dont play if already playing if (!tml->isActive(_scratchNose.get())) { // add this animation on top of two other // we add one to evaluate the animation at the next frame, else we // will miss the current frame tml->addActionAt(tml->getCurrentFrame() + 1, _scratchNose.get(), 2); } _releaseKey = false; } } else { osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv); if (ev && ev->getActionAdapter() && !ev->getEvents().empty()) { for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin(); itr != ev->getEvents().end(); ++itr) { handleWithCheckAgainstIgnoreHandledEventsMask(*(*itr), *(ev->getActionAdapter()), node, nv); } } } traverse(node, nv); }
ExampleTimelineUsage(osgAnimation::TimelineAnimationManager* manager) { _releaseKey = false; _manager = manager; const osgAnimation::AnimationList& list = _manager->getAnimationList(); osgAnimation::AnimationMap map; for (osgAnimation::AnimationList::const_iterator it = list.begin(); it != list.end(); it++) map[(*it)->getName()] = *it; _mainLoop = new osgAnimation::ActionStripAnimation(map["Idle_Main"].get(),0.0,0.0); _mainLoop->setLoop(0); // means forever _scratchHead = new osgAnimation::ActionStripAnimation(map["Idle_Head_Scratch.02"].get(),0.2,0.3); _scratchHead->setLoop(1); // one time map["Idle_Nose_Scratch.01"]->setDuration(10.0); // set this animation duration to 10 seconds _scratchNose = new osgAnimation::ActionStripAnimation(map["Idle_Nose_Scratch.01"].get(),0.2,0.3); _scratchNose->setLoop(1); // one time // add the main loop at priority 0 at time 0. osgAnimation::Timeline* tml = _manager->getTimeline(); tml->play(); tml->addActionAt(0.0, _mainLoop.get(), 0); // add a scratch head priority 1 at 3.0 second. tml->addActionAt(5.0, _scratchHead.get(), 1); // populate time with scratch head for (int i = 1; i < 20; i++) { // we add a scratch head priority 1 each 10 second // note: // it's possible to add the same instance more then once on the timeline // the only things you need to take care is if you remove it. It will remove // all instance that exist on the timeline. If you need to differtiate // it's better to create a new instance tml->addActionAt(5.0 + 10.0 * i, _scratchHead.get(), 1); } // we will add the scratch nose action only when the player hit a key // in the operator() // now we will add callback at end and begin of animation of Idle_Nose_Scratch.02 _scratchNose->setCallback(0.0, new NoseBegin); _scratchNose->setCallback(_scratchNose->getNumFrames()-1, new NoseEnd); }