/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * 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 OSG_CALLBACK #define OSG_CALLBACK 1 #include #include namespace osg { class OSG_EXPORT Callback : public virtual Object { public : Callback(){} Callback(const Callback& cb,const CopyOp& copyop): osg::Object(cb, copyop), _nestedCallback(cb._nestedCallback) {} META_Object(osg, Callback); /** Invoke the callback, first parameter is the Object that the callback is attached to, * the second parameter, the data, is typically the NodeVisitor that is invoking the callback. * The run(..) method may be overriden by users directly, or if the user is using one of the old * style callbacks such as NodeCallback or Drawable::UpdateCallback then you can just override * the appropriate callback method on those callback subclasses. * If you are implementing your own callback then one should call traverse() to make sure nested callbacks * and visitor traversal() is completed. */ virtual bool run(osg::Object* object, osg::Object* data) { return traverse(object, data); } /** traverse the nested callbacks or call NodeVisitor::traverse() if the object is Node, and data is NodeVisitor.*/ bool traverse(osg::Object* object, osg::Object* data); void setNestedCallback(osg::Callback* cb) { _nestedCallback = cb; } osg::Callback* getNestedCallback() { return _nestedCallback.get(); } const osg::Callback* getNestedCallback() const { return _nestedCallback.get(); } inline void addNestedCallback(osg::Callback* nc) { if (nc) { if (_nestedCallback.valid()) { _nestedCallback->addNestedCallback(nc); } else { _nestedCallback = nc; } } } inline void removeNestedCallback(osg::Callback* nc) { if (nc) { if (_nestedCallback==nc) { ref_ptr new_nested_callback = _nestedCallback->getNestedCallback(); _nestedCallback->setNestedCallback(0); _nestedCallback = new_nested_callback; } else if (_nestedCallback.valid()) { _nestedCallback->removeNestedCallback(nc); } } } protected: virtual ~Callback() {} ref_ptr _nestedCallback; }; typedef std::vector< osg::ref_ptr > Parameters; /** Callback for attaching a script to a Node's via there UserDataContainer for the purpose of overriding class methods within scripts.*/ class OSG_EXPORT CallbackObject : public virtual osg::Callback { public: CallbackObject() {} CallbackObject(const std::string& name) { setName(name); } CallbackObject(const CallbackObject& co, const osg::CopyOp copyop=osg::CopyOp::SHALLOW_COPY): osg::Object(co, copyop), osg::Callback(co,copyop) {} META_Object(osg, CallbackObject); virtual CallbackObject* asCallbackObject() { return this; } virtual const CallbackObject* asCallbackObject() const { return this; } /** override Callback::run() entry point to adapt to CallbackObject::run(..) method.*/ bool run(osg::Object* object, osg::Object* data); inline bool run(osg::Object* object) const { osg::Parameters inputParameters; osg::Parameters outputParameters; return run(object, inputParameters, outputParameters); } virtual bool run(osg::Object* object, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const; }; /** Convenience function for getting the CallbackObject associated with specificed name from an Object's UserDataContainer.*/ inline CallbackObject* getCallbackObject(osg::Object* object, const std::string& name) { osg::UserDataContainer* udc = object->getUserDataContainer(); return udc ? dynamic_cast(udc->getUserObject(name)) : 0; } /** Convenience function for getting the CallbackObject associated with specificed name from an Object's UserDataContainer.*/ inline const CallbackObject* getCallbackObject(const osg::Object* object, const std::string& name) { const osg::UserDataContainer* udc = object->getUserDataContainer(); return udc ? dynamic_cast(udc->getUserObject(name)) : 0; } /** Call run(..) on named CallbackObjects attached to specified Object. Return true if at least one CallbackObject has been successfully invoked.*/ inline bool runNamedCallbackObjects(osg::Object* object, const std::string& name, osg::Parameters& inputParameters, osg::Parameters& outputParameters) { bool result = false; osg::UserDataContainer* udc = object->getUserDataContainer(); if (udc) { for(unsigned int i = 0; igetNumUserObjects(); ++i) { osg::Object* obj = udc->getUserObject(i); if (obj && obj->getName()==name) { osg::CallbackObject* co = dynamic_cast(obj); if (co) result = co->run(object, inputParameters, outputParameters) | result; } } } return result; } // forward declare class Node; class NodeVisitor; /** Deprecated. */ class OSG_EXPORT NodeCallback : public virtual Callback { public : NodeCallback(){} NodeCallback(const NodeCallback& nc,const CopyOp& copyop): Callback(nc,copyop) {} META_Object(osg,NodeCallback); /** NodeCallback overrides the Callback::run() method to adapt it the old style NodeCallback::operator()(Node* node, NodeVisitor* nv) method.*/ virtual bool run(osg::Object* object, osg::Object* data); /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(Node* node, NodeVisitor* nv); protected: virtual ~NodeCallback() {} }; // forward declare class StateAttribute; /** Deprecated. */ class OSG_EXPORT StateAttributeCallback : public virtual osg::Callback { public: StateAttributeCallback() {} StateAttributeCallback(const StateAttributeCallback&,const CopyOp&) {} META_Object(osg,StateAttributeCallback); /** override Callback::run() entry point to adapt to StateAttributeCallback::run(..) method.*/ virtual bool run(osg::Object* object, osg::Object* data); /** do customized update code.*/ virtual void operator () (StateAttribute*, NodeVisitor*) {} }; } // namespace #endif