From 1591fe09f30766cf1d4bb3f40975f783f9c2b238 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 23 Oct 2012 16:15:03 +0000 Subject: [PATCH] Added osgGA::Device class for integration of both physical and virtual devices. Added template readFile(..) function to make it more convinient to cast to a specific object type. Added support for osgGA::Device to osgViewer. Added sdl plugin to provides very basic joystick osgGA::Device integration. --- include/osgDB/ReadFile | 18 ++- include/osgGA/Device | 52 +++++++ include/osgViewer/View | 16 +++ include/osgViewer/ViewerBase | 1 - src/osgGA/CMakeLists.txt | 2 + src/osgGA/Device.cpp | 31 +++++ src/osgPlugins/CMakeLists.txt | 9 ++ src/osgPlugins/sdl/CMakeLists.txt | 16 +++ src/osgPlugins/sdl/JoystickDevice.cpp | 185 +++++++++++++++++++++++++ src/osgPlugins/sdl/JoystickDevice.h | 79 +++++++++++ src/osgPlugins/sdl/ReaderWriterSDL.cpp | 38 +++++ src/osgViewer/CompositeViewer.cpp | 15 ++ src/osgViewer/View.cpp | 17 +++ src/osgViewer/Viewer.cpp | 14 ++ 14 files changed, 491 insertions(+), 2 deletions(-) create mode 100644 include/osgGA/Device create mode 100644 src/osgGA/Device.cpp create mode 100644 src/osgPlugins/sdl/CMakeLists.txt create mode 100644 src/osgPlugins/sdl/JoystickDevice.cpp create mode 100644 src/osgPlugins/sdl/JoystickDevice.h create mode 100644 src/osgPlugins/sdl/ReaderWriterSDL.cpp diff --git a/include/osgDB/ReadFile b/include/osgDB/ReadFile index 7410ec212..0b9298a8a 100644 --- a/include/osgDB/ReadFile +++ b/include/osgDB/ReadFile @@ -43,9 +43,25 @@ extern OSGDB_EXPORT osg::Object* readObjectFile(const std::string& filename,cons * to read the specified file.*/ inline osg::Object* readObjectFile(const std::string& filename) { - return readObjectFile(filename,Registry::instance()->getOptions()); + return readObjectFile(filename, Registry::instance()->getOptions()); } +template +inline T* readFile(const std::string& filename, const Options* options) +{ + osg::ref_ptr object = readObjectFile(filename, options); + osg::ref_ptr t = dynamic_cast(object.get()); + object = 0; + return t.release(); +} + +template +inline T* readFile(const std::string& filename) +{ + return readFile(filename, Registry::instance()->getOptions()); +} + + /** Read an osg::Image from file. * Return valid osg::Image on success, * return NULL on failure. diff --git a/include/osgGA/Device b/include/osgGA/Device new file mode 100644 index 000000000..446961c81 --- /dev/null +++ b/include/osgGA/Device @@ -0,0 +1,52 @@ +/* -*-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 OSGGA_EVENTSOURCE +#define OSGGA_EVENTSOURCE 1 + +#include + +namespace osgGA { + +/** + * Device base class from abstracting away from devices/windows that can generate events. + */ +class OSGGA_EXPORT Device : public osg::Object +{ + public: + + Device(); + Device(const Device& es, const osg::CopyOp& copyop); + + META_Object(osgGA,Device); + + virtual void checkEvents() {}; + + void setEventQueue(osgGA::EventQueue* eventQueue) { _eventQueue = eventQueue; } + osgGA::EventQueue* getEventQueue() { return _eventQueue.get(); } + const osgGA::EventQueue* getEventQueue() const { return _eventQueue.get(); } + + protected: + + virtual ~Device(); + + /** Prevent unwanted copy operator.*/ + Device& operator = (const Device&) { return *this; } + + osg::ref_ptr _eventQueue; + +}; + +} + +#endif diff --git a/include/osgViewer/View b/include/osgViewer/View index 2f4ecd905..1dc279233 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,19 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter /** Get the const View's image pager.*/ const osgDB::ImagePager* getImagePager() const; + + /** Add a Device. + * The Device is polled on each new frame via it's Device::checkEvents() method and any events generated then collected via Device::getEventQueue()*/ + void addDevice(osgGA::Device* eventSource); + + /** Remove a Device. /*/ + void removeDevice(osgGA::Device* eventSource); + + typedef std::vector< osg::ref_ptr > Devices; + + Devices& getDevices() { return _eventSources; } + const Devices& getDevices() const { return _eventSources; } + /* Set the EventQueue that the View uses to integrate external non window related events.*/ void setEventQueue(osgGA::EventQueue* eventQueue) { _eventQueue = eventQueue; } @@ -250,6 +264,8 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter osg::Timer_t _startTick; + Devices _eventSources; + osg::ref_ptr _scene; osg::ref_ptr _eventQueue; osg::ref_ptr _cameraManipulator; diff --git a/include/osgViewer/ViewerBase b/include/osgViewer/ViewerBase index 966d31fc7..c6b9e09cd 100644 --- a/include/osgViewer/ViewerBase +++ b/include/osgViewer/ViewerBase @@ -117,7 +117,6 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object osg::BarrierOperation::PreBlockOp getEndBarrierOperation() const { return _endBarrierOperation; } - /** Set the done flag to signal the viewer's work is done and should exit the frame loop.*/ void setDone(bool done) { _done = done; } diff --git a/src/osgGA/CMakeLists.txt b/src/osgGA/CMakeLists.txt index e5d2e9763..f49321110 100644 --- a/src/osgGA/CMakeLists.txt +++ b/src/osgGA/CMakeLists.txt @@ -10,6 +10,7 @@ SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(TARGET_H ${HEADER_PATH}/AnimationPathManipulator ${HEADER_PATH}/DriveManipulator + ${HEADER_PATH}/Device ${HEADER_PATH}/EventQueue ${HEADER_PATH}/EventVisitor ${HEADER_PATH}/Export @@ -36,6 +37,7 @@ SET(TARGET_H SET(TARGET_SRC AnimationPathManipulator.cpp DriveManipulator.cpp + Device.cpp EventQueue.cpp EventVisitor.cpp FirstPersonManipulator.cpp diff --git a/src/osgGA/Device.cpp b/src/osgGA/Device.cpp new file mode 100644 index 000000000..a3d3f23fc --- /dev/null +++ b/src/osgGA/Device.cpp @@ -0,0 +1,31 @@ +/* -*-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. +*/ + +#include + +using namespace osgGA; + +Device::Device() +{ + setEventQueue(new EventQueue); +} + +Device::Device(const Device& es, const osg::CopyOp& copyop): + osg::Object(es,copyop) +{ + setEventQueue(new EventQueue); +} + +Device::~Device() +{ +} diff --git a/src/osgPlugins/CMakeLists.txt b/src/osgPlugins/CMakeLists.txt index e66d65d5c..388b49bef 100644 --- a/src/osgPlugins/CMakeLists.txt +++ b/src/osgPlugins/CMakeLists.txt @@ -256,6 +256,15 @@ ENDIF() ADD_SUBDIRECTORY(pvr) +#################################################### +# +# Device integration plugins +# +IF (SDL_FOUND) + ADD_SUBDIRECTORY(sdl) +ENDIF(SDL_FOUND) + + ##########to get all the variables of Cmake #GET_CMAKE_PROPERTY(MYVARS VARIABLES) #FOREACH(myvar ${MYVARS}) diff --git a/src/osgPlugins/sdl/CMakeLists.txt b/src/osgPlugins/sdl/CMakeLists.txt new file mode 100644 index 000000000..ff1502e36 --- /dev/null +++ b/src/osgPlugins/sdl/CMakeLists.txt @@ -0,0 +1,16 @@ +SET(TARGET_EXTERNAL_LIBRARIES ${SDL_LIBRARY} ) +INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR} ) + +SET(TARGET_SRC + JoystickDevice.cpp + ReaderWriterSDL.cpp +) + +SET(TARGET_H + JoystickDevice.h +) + +SET(TARGET_ADDED_LIBRARIES osgGA) + +#### end var setup ### +SETUP_PLUGIN(sdl sdl) diff --git a/src/osgPlugins/sdl/JoystickDevice.cpp b/src/osgPlugins/sdl/JoystickDevice.cpp new file mode 100644 index 000000000..2369cff7a --- /dev/null +++ b/src/osgPlugins/sdl/JoystickDevice.cpp @@ -0,0 +1,185 @@ +/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield + * + * This software is open source and may be redistributed and/or modified under + * the terms of the GNU General Public License (GPL) version 2.0. + * The full license is in LICENSE.txt file included with this distribution,. + * + * This software 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 + * include LICENSE.txt for more details. +*/ + +#include + +#include "JoystickDevice.h" + +#include +#include +#include + +#include + +JoystickDevice::JoystickDevice() +{ + _verbose = false; + + // init SDL + if ( SDL_Init(SDL_INIT_JOYSTICK) < 0 ) + { + fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + int numJoysticks = SDL_NumJoysticks(); + + if (_verbose) + { + std::cout<<"number of joysticks "<0 ? SDL_JoystickOpen(0) : 0; + + _numAxes = _joystick ? SDL_JoystickNumAxes(_joystick) : 0; + _numBalls = _joystick ? SDL_JoystickNumBalls(_joystick) : 0; + _numHats = _joystick ? SDL_JoystickNumHats(_joystick) : 0; + _numButtons = _joystick ? SDL_JoystickNumButtons(_joystick) : 0; + + if (_verbose) + { + std::cout<<"numAxes = "<<_numAxes<getTime() : 0.0; + osgGA::GUIEventAdapter* previous_event = eq->getCurrentEventState(); + float projected_mx = previous_event->getXmin() + (mx+1.0)*0.5*(previous_event->getXmax()-previous_event->getXmin()); + float projected_my = previous_event->getYmin() + (my+1.0)*0.5*(previous_event->getYmax()-previous_event->getYmin()); + + if (mx!=prev_mx || my!=prev_my) + { + eq->mouseMotion(projected_mx, projected_my, time); + } + + OSG_NOTICE<<"mx="<0) + { + if (newButtonValues[bi]==0) eq->mouseButtonRelease(projected_mx,projected_my,mouseButton,time); + else eq->mouseButtonPress(projected_mx,projected_my,mouseButton,time); + } + else if (key>0) + { + + if (newButtonValues[bi]==0) eq->keyRelease(key,time); + else eq->keyPress(key,time); + } + } + } + + _axisValues.swap(newAxisValues); + _buttonValues.swap(newButtonValues); + + } + +} + diff --git a/src/osgPlugins/sdl/JoystickDevice.h b/src/osgPlugins/sdl/JoystickDevice.h new file mode 100644 index 000000000..da20ba6a8 --- /dev/null +++ b/src/osgPlugins/sdl/JoystickDevice.h @@ -0,0 +1,79 @@ +/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield + * + * This software is open source and may be redistributed and/or modified under + * the terms of the GNU General Public License (GPL) version 2.0. + * The full license is in LICENSE.txt file included with this distribution,. + * + * This software 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 + * include LICENSE.txt for more details. +*/ + +#ifndef SDLINTEGRATION +#define SDLINTEGRATION + +#include + +#include +#include +#include + +#include +#include + +class JoystickDevice : public osgGA::Device +{ + public: + + JoystickDevice(); + + typedef std::vector ValueList; + typedef std::map ButtonMap; + + virtual void checkEvents(); + + void addMouseButtonMapping(int joystickButton, int mouseButton) + { + _mouseButtonMap[joystickButton] = mouseButton; + } + + int getMouseButtonMapping(int joystickButton) + { + ButtonMap::const_iterator itr = _mouseButtonMap.find(joystickButton); + if (itr != _mouseButtonMap.end()) return itr->second; + else return -1; + } + + void addKeyMapping(int joystickButton, int key) + { + _keyMap[joystickButton] = key; + } + + int getKeyMapping(int joystickButton) + { + ButtonMap::const_iterator itr = _keyMap.find(joystickButton); + if (itr != _keyMap.end()) return itr->second; + else return -1; + } + + protected: + + virtual ~JoystickDevice(); + + void capture(ValueList& axisValues, ValueList& buttonValues) const; + + SDL_Joystick* _joystick; + int _numAxes; + int _numBalls; + int _numHats; + int _numButtons; + bool _verbose; + + ValueList _axisValues; + ValueList _buttonValues; + ButtonMap _mouseButtonMap; + ButtonMap _keyMap; +}; + +#endif diff --git a/src/osgPlugins/sdl/ReaderWriterSDL.cpp b/src/osgPlugins/sdl/ReaderWriterSDL.cpp new file mode 100644 index 000000000..6e8c263c9 --- /dev/null +++ b/src/osgPlugins/sdl/ReaderWriterSDL.cpp @@ -0,0 +1,38 @@ +// Released under the OSGPL license, as part of the OpenSceneGraph distribution. +// +// ReaderWriter for sgi's .rgb format. +// specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html + +#include + +#include +#include + +#include "JoystickDevice.h" + + +class ReaderWriterSDL : public osgDB::ReaderWriter +{ + public: + + ReaderWriterSDL() + { + supportsExtension("sdl","SDL Device Integration"); + } + + virtual const char* className() const { return "SDL Device Integration plugin"; } + + virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const + { + if (file=="joystick.sdl") + { + return new JoystickDevice; + } + return ReadResult::FILE_NOT_HANDLED; + } + +}; + +// now register with Registry to instantiate the above +// reader/writer. +REGISTER_OSGPLUGIN(sdl, ReaderWriterSDL) diff --git a/src/osgViewer/CompositeViewer.cpp b/src/osgViewer/CompositeViewer.cpp index 4cb5f71dc..7dc266a83 100644 --- a/src/osgViewer/CompositeViewer.cpp +++ b/src/osgViewer/CompositeViewer.cpp @@ -735,6 +735,7 @@ void CompositeViewer::eventTraversal() masterCameraVPW *= viewport->computeWindowMatrix(); } + // get events from all windows attached to Viewer. for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) @@ -925,6 +926,20 @@ void CompositeViewer::eventTraversal() ++vitr) { View* view = vitr->get(); + + // get events from user Devices attached to Viewer. + for(osgViewer::View::Devices::iterator eitr = view->getDevices().begin(); + eitr != view->getDevices().end(); + ++eitr) + { + osgGA::Device* es = eitr->get(); + es->checkEvents(); + + // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events? + // for now assume now and just get the events directly without any reprojection. + es->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime); + } + view->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime); } diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index aab4308f5..f0eece4b8 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -2217,3 +2217,20 @@ bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath, } +void View::addDevice(osgGA::Device* eventSource) +{ + Devices::iterator itr = std::find( _eventSources.begin(), _eventSources.end(), eventSource ); + if (itr==_eventSources.end()) + { + _eventSources.push_back(eventSource); + } +} + +void View::removeDevice(osgGA::Device* eventSource) +{ + Devices::iterator itr = std::find( _eventSources.begin(), _eventSources.end(), eventSource ); + if (itr!=_eventSources.end()) + { + _eventSources.erase(itr); + } +} diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index ec4dbe093..419da8d13 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -645,6 +645,20 @@ void Viewer::eventTraversal() } + // get events from user Devices attached to Viewer. + for(Devices::iterator eitr = _eventSources.begin(); + eitr != _eventSources.end(); + ++eitr) + { + osgGA::Device* es = eitr->get(); + es->checkEvents(); + + // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events? + // for now assume now and just get the events directly without any reprojection. + es->getEventQueue()->takeEvents(events, cutOffTime); + } + + // get events from all windows attached to Viewer. for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr)