Added support for new event visitor type into osgGA and osgProducer::Viewer,

and event callback into Drawable.
This commit is contained in:
Robert Osfield 2005-02-25 14:02:48 +00:00
parent 82d8bcd2af
commit 0f61af08bd
11 changed files with 319 additions and 10 deletions

View File

@ -25,7 +25,7 @@
typedef std::vector<std::string> FileList; typedef std::vector<std::string> FileList;
class SlideEventHandler : public osgGA::GUIEventHandler, public osg::NodeCallback class SlideEventHandler : public osgGA::GUIEventHandler
{ {
public: public:

View File

@ -265,6 +265,28 @@ class SG_EXPORT Drawable : public Object
const UpdateCallback* getUpdateCallback() const { return _updateCallback.get(); } const UpdateCallback* getUpdateCallback() const { return _updateCallback.get(); }
struct EventCallback : public virtual osg::Object
{
EventCallback() {}
EventCallback(const EventCallback&,const CopyOp&) {}
META_Object(osg,EventCallback);
/** do customized Event code.*/
virtual void event(osg::NodeVisitor*, osg::Drawable*) {}
};
/** Set the EventCallback which allows users to attach customize the updating of an object during the Event traversal.*/
virtual void setEventCallback(EventCallback* ac);
/** Get the non const EventCallback.*/
EventCallback* getEventCallback() { return _eventCallback.get(); }
/** Get the const EventCallback.*/
const EventCallback* getEventCallback() const { return _eventCallback.get(); }
struct CullCallback : public virtual osg::Object struct CullCallback : public virtual osg::Object
{ {
CullCallback() {} CullCallback() {}
@ -697,6 +719,7 @@ class SG_EXPORT Drawable : public Object
mutable GLObjectList _vboList; mutable GLObjectList _vboList;
ref_ptr<UpdateCallback> _updateCallback; ref_ptr<UpdateCallback> _updateCallback;
ref_ptr<EventCallback> _eventCallback;
ref_ptr<CullCallback> _cullCallback; ref_ptr<CullCallback> _cullCallback;
ref_ptr<DrawCallback> _drawCallback; ref_ptr<DrawCallback> _drawCallback;
}; };

131
include/osgGA/EventVisitor Normal file
View File

@ -0,0 +1,131 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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 OSGGA_EVENTVISITOR
#define OSGGA_EVENTVISITOR 1
#include <osg/NodeVisitor>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Billboard>
#include <osg/LOD>
#include <osg/Switch>
#include <osg/LightSource>
#include <osg/Transform>
#include <osg/Projection>
#include <osg/Impostor>
#include <osg/OccluderNode>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>
#include <list>
namespace osgGA {
/**
* Basic EventVisitor implementation for animating a scene.
* This visitor traverses the scene graph, calling each nodes appCallback if
* it exists.
*/
class OSGGA_EXPORT EventVisitor : public osg::NodeVisitor
{
public:
EventVisitor();
virtual ~EventVisitor();
void setActionAdapter(osgGA::GUIActionAdapter* actionAdapter) { _actionAdapter=actionAdapter; }
osgGA::GUIActionAdapter* getActionAdapter() { return _actionAdapter; }
const osgGA::GUIActionAdapter* getActionAdapter() const { return _actionAdapter; }
typedef std::list< osg::ref_ptr<GUIEventAdapter> > EventList;
void setEventList(const EventList& events) { _events = events; }
EventList& getEventList() { return _events; }
const EventList& getEventList() const { return _events; }
void addEvent(GUIEventAdapter* event);
void removeEvent(GUIEventAdapter* event);
virtual void reset();
/** During traversal each type of node calls its callbacks and its children traversed. */
virtual void apply(osg::Node& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::Geode& node) { handle_geode_callbacks(node); }
virtual void apply(osg::Billboard& node) { handle_geode_callbacks(node); }
virtual void apply(osg::LightSource& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::Group& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::Transform& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::Projection& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::Switch& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::LOD& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::Impostor& node) { handle_callbacks_and_traverse(node); }
virtual void apply(osg::OccluderNode& node) { handle_callbacks_and_traverse(node); }
protected:
// /** Prevent unwanted copy construction.*/
// EventVisitor(const EventVisitor&):osg::NodeVisitor() {}
/** Prevent unwanted copy operator.*/
EventVisitor& operator = (const EventVisitor&) { return *this; }
inline void handle_callbacks_and_traverse(osg::Node& node)
{
osg::NodeCallback* callback = node.getEventCallback();
if (callback) (*callback)(&node,this);
else if (node.getNumChildrenRequiringEventTraversal()>0) traverse(node);
}
inline void handle_geode_callbacks(osg::Geode& node)
{
osg::NodeCallback* callback = node.getEventCallback();
if (callback) (*callback)(&node,this);
/*else if (node.getNumChildrenRequiringEventTraversal()>0)*/
traverseGeode(node);
}
inline void traverseGeode(osg::Geode& geode)
{
traverse((osg::Node&)geode);
// Call the app callbacks on the drawables.
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::Drawable::EventCallback* callback = geode.getDrawable(i)->getEventCallback();
if (callback) callback->event(this,geode.getDrawable(i));
}
}
osgGA::GUIActionAdapter* _actionAdapter;
EventList _events;
};
}
#endif

View File

@ -16,8 +16,8 @@
#include <vector> #include <vector>
#include <osg/Referenced> #include <osg/NodeCallback>
#include <osg/Object> #include <osg/Drawable>
#include <osg/ApplicationUsage> #include <osg/ApplicationUsage>
#include <osgGA/Export> #include <osgGA/Export>
@ -49,7 +49,7 @@ This request is made via the GUIActionAdapter class.
*/ */
class OSGGA_EXPORT GUIEventHandler : public virtual osg::Object class OSGGA_EXPORT GUIEventHandler : public osg::NodeCallback, public osg::Drawable::EventCallback
{ {
public: public:
@ -58,6 +58,12 @@ public:
META_Object(osgGA,GUIEventHandler); META_Object(osgGA,GUIEventHandler);
/** Event traversal node callback method.*/
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
/** Event traversal drawable callback method.*/
virtual void event(osg::NodeVisitor* nv, osg::Drawable* drawable);
/** Returns 0 if this GUIEventHandler is not a CompositeGUIEventHandler. */ /** Returns 0 if this GUIEventHandler is not a CompositeGUIEventHandler. */
virtual const CompositeGUIEventHandler* getComposite() const { return 0; } virtual const CompositeGUIEventHandler* getComposite() const { return 0; }

View File

@ -24,6 +24,7 @@
#include <osgGA/GUIActionAdapter> #include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventHandler> #include <osgGA/GUIEventHandler>
#include <osgGA/EventVisitor>
#include <osgGA/KeySwitchMatrixManipulator> #include <osgGA/KeySwitchMatrixManipulator>
#include <osgProducer/OsgCameraGroup> #include <osgProducer/OsgCameraGroup>
@ -205,6 +206,17 @@ class OSGPRODUCER_EXPORT Viewer : public OsgCameraGroup, public osgGA::GUIAction
/** Get the const update visitor.*/ /** Get the const update visitor.*/
const osg::NodeVisitor* getUpdateVisitor() const { return _updateVisitor.get(); } const osg::NodeVisitor* getUpdateVisitor() const { return _updateVisitor.get(); }
/** Set the update visitor which does the event traversal of the scene graph. Automatically called by the update() method.*/
void setEventVisitor(osgGA::EventVisitor* nv) { _eventVisitor = nv; }
/** Get the update visitor.*/
osgGA::EventVisitor* getEventVisitor() { return _eventVisitor.get(); }
/** Get the const update visitor.*/
const osgGA::EventVisitor* getEventVisitor() const { return _eventVisitor.get(); }
void computeActiveCoordindateSystemNodePath(); void computeActiveCoordindateSystemNodePath();
void setCoordindateSystemNodePath(const osg::RefNodePath& nodePath) { _coordinateSystemNodePath = nodePath; } void setCoordindateSystemNodePath(const osg::RefNodePath& nodePath) { _coordinateSystemNodePath = nodePath; }
@ -299,6 +311,7 @@ class OSGPRODUCER_EXPORT Viewer : public OsgCameraGroup, public osgGA::GUIAction
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> _keyswitchManipulator; osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> _keyswitchManipulator;
osg::ref_ptr<osg::NodeVisitor> _updateVisitor; osg::ref_ptr<osg::NodeVisitor> _updateVisitor;
osg::ref_ptr<osgGA::EventVisitor> _eventVisitor;
osg::RefNodePath _coordinateSystemNodePath; osg::RefNodePath _coordinateSystemNodePath;

View File

@ -497,6 +497,27 @@ void Drawable::setUpdateCallback(UpdateCallback* ac)
} }
} }
void Drawable::setEventCallback(EventCallback* ac)
{
if (_eventCallback==ac) return;
int delta = 0;
if (_eventCallback.valid()) --delta;
if (ac) ++delta;
_eventCallback = ac;
if (delta!=0)
{
for(ParentList::iterator itr=_parents.begin();
itr!=_parents.end();
++itr)
{
(*itr)->setNumChildrenRequiringEventTraversal((*itr)->getNumChildrenRequiringEventTraversal()+delta);
}
}
}
struct ComputeBound : public PrimitiveFunctor struct ComputeBound : public PrimitiveFunctor
{ {
ComputeBound():_vertices(0) {} ComputeBound():_vertices(0) {}

View File

@ -62,6 +62,11 @@ bool Geode::addDrawable( Drawable *drawable )
setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
} }
if (drawable->getEventCallback())
{
setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+1);
}
dirtyBound(); dirtyBound();
return true; return true;
@ -88,12 +93,14 @@ bool Geode::removeDrawable(unsigned int pos,unsigned int numDrawablesToRemove)
} }
unsigned int updateCallbackRemoved = 0; unsigned int updateCallbackRemoved = 0;
unsigned int eventCallbackRemoved = 0;
for(unsigned i=pos;i<endOfRemoveRange;++i) for(unsigned i=pos;i<endOfRemoveRange;++i)
{ {
// remove this Geode from the child parent list. // remove this Geode from the child parent list.
_drawables[i]->removeParent(this); _drawables[i]->removeParent(this);
// update the number of app calbacks removed // update the number of app calbacks removed
if (_drawables[i]->getUpdateCallback()) ++updateCallbackRemoved; if (_drawables[i]->getUpdateCallback()) ++updateCallbackRemoved;
if (_drawables[i]->getEventCallback()) ++eventCallbackRemoved;
} }
_drawables.erase(_drawables.begin()+pos,_drawables.begin()+endOfRemoveRange); _drawables.erase(_drawables.begin()+pos,_drawables.begin()+endOfRemoveRange);
@ -103,6 +110,11 @@ bool Geode::removeDrawable(unsigned int pos,unsigned int numDrawablesToRemove)
setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-updateCallbackRemoved); setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-updateCallbackRemoved);
} }
if (eventCallbackRemoved)
{
setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-eventCallbackRemoved);
}
dirtyBound(); dirtyBound();
return true; return true;
@ -129,14 +141,23 @@ bool Geode::setDrawable( unsigned int i, Drawable* newDrawable )
Drawable* origDrawable = _drawables[i].get(); Drawable* origDrawable = _drawables[i].get();
int delta = 0; int deltaUpdate = 0;
if (origDrawable->getUpdateCallback()) --delta; if (origDrawable->getUpdateCallback()) --deltaUpdate;
if (newDrawable->getUpdateCallback()) ++delta; if (newDrawable->getUpdateCallback()) ++deltaUpdate;
if (delta!=0) if (deltaUpdate!=0)
{ {
setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+delta); setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+deltaUpdate);
} }
int deltaEvent = 0;
if (origDrawable->getEventCallback()) --deltaEvent;
if (newDrawable->getEventCallback()) ++deltaEvent;
if (deltaEvent!=0)
{
setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+deltaEvent);
}
// remove from origDrawable's parent list. // remove from origDrawable's parent list.
origDrawable->removeParent(this); origDrawable->removeParent(this);

View File

@ -0,0 +1,44 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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.
*/
#include <osgGA/EventVisitor>
#include <algorithm>
using namespace osg;
using namespace osgGA;
EventVisitor::EventVisitor():NodeVisitor(UPDATE_VISITOR,TRAVERSE_ALL_CHILDREN)
{
}
EventVisitor::~EventVisitor()
{
}
void EventVisitor::addEvent(GUIEventAdapter* event)
{
_events.push_back(event);
}
void EventVisitor::removeEvent(GUIEventAdapter* event)
{
EventList::iterator itr = std::find(_events.begin(),_events.end(),event);
if (itr!=_events.end()) _events.erase(itr);
}
void EventVisitor::reset()
{
_events.clear();
}

View File

@ -6,6 +6,7 @@ CXXFILES = \
AnimationPathManipulator.cpp\ AnimationPathManipulator.cpp\
MatrixManipulator.cpp\ MatrixManipulator.cpp\
DriveManipulator.cpp\ DriveManipulator.cpp\
EventVisitor.cpp\
FlightManipulator.cpp\ FlightManipulator.cpp\
GUIEventAdapter.cpp\ GUIEventAdapter.cpp\
GUIEventHandler.cpp\ GUIEventHandler.cpp\

View File

@ -12,9 +12,40 @@
*/ */
#include <osgGA/GUIEventHandler> #include <osgGA/GUIEventHandler>
#include <osgGA/EventVisitor>
using namespace osgGA; using namespace osgGA;
void GUIEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
if (ev && ev->getActionAdapter() && !ev->getEventList().empty())
{
for(osgGA::EventVisitor::EventList::iterator itr = ev->getEventList().begin();
itr != ev->getEventList().end();
++itr)
{
handle(*(*itr), *(ev->getActionAdapter()));
}
}
traverse(node,nv);
}
void GUIEventHandler::event(osg::NodeVisitor* nv, osg::Drawable* /*drawable*/)
{
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
if (ev && ev->getActionAdapter() && !ev->getEventList().empty())
{
for(osgGA::EventVisitor::EventList::iterator itr = ev->getEventList().begin();
itr != ev->getEventList().end();
++itr)
{
handle(*(*itr), *(ev->getActionAdapter()));
}
}
}
void CompositeGUIEventHandler::getUsage(osg::ApplicationUsage& usage) const void CompositeGUIEventHandler::getUsage(osg::ApplicationUsage& usage) const
{ {
for (ChildList::const_iterator itr=_children.begin(); for (ChildList::const_iterator itr=_children.begin();

View File

@ -5,6 +5,7 @@
#include <osgDB/Registry> #include <osgDB/Registry>
#include <osgGA/EventVisitor>
#include <osgGA/AnimationPathManipulator> #include <osgGA/AnimationPathManipulator>
#include <osgGA/TrackballManipulator> #include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator> #include <osgGA/FlightManipulator>
@ -482,6 +483,10 @@ void Viewer::setUpViewer(unsigned int options)
_updateVisitor->setFrameStamp(_frameStamp.get()); _updateVisitor->setFrameStamp(_frameStamp.get());
if (!_eventVisitor) _eventVisitor = new osgGA::EventVisitor;
_eventVisitor->setActionAdapter(this);
if (options&TRACKBALL_MANIPULATOR) addCameraManipulator(new osgGA::TrackballManipulator); if (options&TRACKBALL_MANIPULATOR) addCameraManipulator(new osgGA::TrackballManipulator);
if (options&FLIGHT_MANIPULATOR) addCameraManipulator(new osgGA::FlightManipulator); if (options&FLIGHT_MANIPULATOR) addCameraManipulator(new osgGA::FlightManipulator);
if (options&DRIVE_MANIPULATOR) addCameraManipulator(new osgGA::DriveManipulator); if (options&DRIVE_MANIPULATOR) addCameraManipulator(new osgGA::DriveManipulator);
@ -632,6 +637,11 @@ void Viewer::update()
frame_event->adaptFrame(_frameStamp->getReferenceTime()); frame_event->adaptFrame(_frameStamp->getReferenceTime());
queue.push_back(frame_event); queue.push_back(frame_event);
if (_eventVisitor.valid())
{
_eventVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
}
// dispatch the events in order of arrival. // dispatch the events in order of arrival.
for(osgProducer::KeyboardMouseCallback::EventQueue::iterator event_itr=queue.begin(); for(osgProducer::KeyboardMouseCallback::EventQueue::iterator event_itr=queue.begin();
event_itr!=queue.end(); event_itr!=queue.end();
@ -644,8 +654,15 @@ void Viewer::update()
{ {
handled = (*handler_itr)->handle(*(*event_itr),*this); handled = (*handler_itr)->handle(*(*event_itr),*this);
} }
if (!handled && _eventVisitor.valid())
{
_eventVisitor->reset();
_eventVisitor->addEvent(event_itr->get());
getTopMostSceneData()->accept(*_eventVisitor);
}
} }
if (osgDB::Registry::instance()->getDatabasePager()) if (osgDB::Registry::instance()->getDatabasePager())
{ {
// update the scene graph by remove expired subgraphs and merge newly loaded subgraphs // update the scene graph by remove expired subgraphs and merge newly loaded subgraphs
@ -661,6 +678,7 @@ void Viewer::update()
getTopMostSceneData()->accept(*_updateVisitor); getTopMostSceneData()->accept(*_updateVisitor);
} }
// update the main producer camera // update the main producer camera
if (_keyswitchManipulator.valid() && _keyswitchManipulator->getCurrentMatrixManipulator()) if (_keyswitchManipulator.valid() && _keyswitchManipulator->getCurrentMatrixManipulator())
{ {