/* -*-c++-*- * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #ifndef OSGANIMATION_UPDATE_CALLBACK_H #define OSGANIMATION_UPDATE_CALLBACK_H #include #include #include #include #include #include #include namespace osgAnimation { class AnimationUpdateCallbackBase { public: virtual osg::Object* clone(const osg::CopyOp& copyop) const = 0; virtual AnimationManagerBase* getAnimationManager() = 0; virtual bool needLink() const = 0; virtual bool link(osgAnimation::Channel* channel) = 0; virtual int link(osgAnimation::Animation* animation) = 0; virtual void updateLink() = 0; virtual const std::string& getName() const = 0; virtual ~AnimationUpdateCallbackBase() {} }; template class AnimationUpdateCallback : public AnimationUpdateCallbackBase, public T { protected: osg::observer_ptr _manager; public: AnimationUpdateCallback(const std::string& name) { T::setName(name);} AnimationUpdateCallback(const AnimationUpdateCallback& apc,const osg::CopyOp& copyop): T(apc, copyop), _manager(apc._manager) {} osgAnimation::AnimationManagerBase* getAnimationManager() { return _manager.get(); } const std::string& getName() const { return T::getName(); } int link(osgAnimation::Animation* animation) { if (T::getName().empty()) osg::notify(osg::WARN) << "An update callback has no name, it means it can link only with \"\" named Target, often an error" << std::endl; int nbLinks = 0; for (osgAnimation::ChannelList::iterator it = animation->getChannels().begin(); it != animation->getChannels().end(); it++) { std::string targetName = (*it)->getTargetName(); if (targetName == T::getName()) { AnimationUpdateCallbackBase* a = this; a->link((*it).get()); nbLinks++; } } return nbLinks; } void updateLink() { if (_manager.valid()) { if (needLink()) { /** this item is not linked yet then we do it for all animation registered in the manager. Maybe this function should be on the manager side like _manager->linkItem(Bone); */ const AnimationList& animationList = _manager->getAnimationList(); for (AnimationList::const_iterator it = animationList.begin(); it != animationList.end(); it++) { AnimationUpdateCallbackBase* a = this; a->link(it->get()); } _manager->buildTargetReference(); } } } }; class OSGANIMATION_EXPORT UpdateTransform : public AnimationUpdateCallback { protected: osg::ref_ptr _euler; osg::ref_ptr _position; osg::ref_ptr _scale; public: META_Object(osgAnimation, UpdateTransform); UpdateTransform(const std::string& name = ""); UpdateTransform(const UpdateTransform& apc,const osg::CopyOp& copyop); /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); void update(osg::MatrixTransform& mat); void update(osg::PositionAttitudeTransform& pat); bool needLink() const; bool link(osgAnimation::Channel* channel); osgAnimation::Vec3Target* getEuler() {return _euler.get();} osgAnimation::Vec3Target* getPosition() {return _position.get();} osgAnimation::Vec3Target* getScale() {return _scale.get();} }; class OSGANIMATION_EXPORT UpdateMaterial : public AnimationUpdateCallback { protected: osg::ref_ptr _diffuse; public: META_Object(osgAnimation, UpdateMaterial); UpdateMaterial(const std::string& name = ""); UpdateMaterial(const UpdateMaterial& apc,const osg::CopyOp& copyop); /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator () (osg::StateAttribute*, osg::NodeVisitor*); void update(osg::Material& material); bool needLink() const; bool link(osgAnimation::Channel* channel); }; } #endif