/* -*-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 SLIDEEVENTHANDLER #define SLIDEEVENTHANDLER 1 #include #include #include #include #include namespace osgPresentation { /// Operations related to click to run/load/key events. enum Operation { RUN, LOAD, EVENT, JUMP }; struct HomePosition : public virtual osg::Referenced { HomePosition() {} HomePosition(const osg::Vec3& in_eye, const osg::Vec3& in_center, const osg::Vec3& in_up): eye(in_eye), center(in_center), up(in_up) {} osg::Vec3 eye; osg::Vec3 center; osg::Vec3 up; }; struct KeyPosition { KeyPosition(unsigned int key=0, float x=FLT_MAX, float y=FLT_MAX): _key((osgGA::GUIEventAdapter::KeySymbol)key), _x(x), _y(y) {} void set(unsigned int key=0, float x=FLT_MAX, float y=FLT_MAX) { _key = (osgGA::GUIEventAdapter::KeySymbol)key; _x = x; _y = y; } osgGA::GUIEventAdapter::KeySymbol _key; float _x; float _y; }; struct LayerCallback : public virtual osg::Referenced { virtual void operator() (osg::Node* node) const = 0; }; struct OSGPRESENTATION_EXPORT LayerAttributes : public virtual osg::Referenced { LayerAttributes():_duration(0),_relativeJump(true),_slideNum(0),_layerNum(0) {} LayerAttributes(double in_duration):_duration(in_duration),_relativeJump(true),_slideNum(0),_layerNum(0) {} void setDuration(double duration) { _duration = duration; } double getDuration() const { return _duration; } typedef std::vector Keys; typedef std::vector RunStrings; void setKeys(const Keys& keys) { _keys = keys; } const Keys& getKeys() const { return _keys; } void addKey(const KeyPosition& kp) { _keys.push_back(kp); } void setRunStrings(const RunStrings& runStrings) { _runStrings = runStrings; } const RunStrings& getRunStrings() const { return _runStrings; } void addRunString(const std::string& runString) { _runStrings.push_back(runString); } void setJump(bool relativeJump, int slideNum, int layerNum) { _relativeJump = relativeJump; _slideNum = slideNum; _layerNum = layerNum; } bool getRelativeJump() const { return _relativeJump; } int getSlideNum() const { return _slideNum; } int getLayerNum() const { return _layerNum; } bool requiresJump() const { return _relativeJump ? (_slideNum!=0 || _layerNum!=0) : true; } double _duration; Keys _keys; RunStrings _runStrings; bool _relativeJump; int _slideNum; int _layerNum; void addEnterCallback(LayerCallback* lc) { _enterLayerCallbacks.push_back(lc); } void addLeaveCallback(LayerCallback* lc) { _leaveLayerCallbacks.push_back(lc); } void callEnterCallbacks(osg::Node* node); void callLeaveCallbacks(osg::Node* node); typedef std::list< osg::ref_ptr > LayerCallbacks; LayerCallbacks _enterLayerCallbacks; LayerCallbacks _leaveLayerCallbacks; }; struct FilePathData : public virtual osg::Referenced { FilePathData(const osgDB::FilePathList& fpl):filePathList(fpl) {} osgDB::FilePathList filePathList; }; struct dereference_less { template inline bool operator() (const T& lhs,const U& rhs) const { return *lhs < *rhs; } }; struct ObjectOperator : public osg::Referenced { inline bool operator < (const ObjectOperator& rhs) const { return ptr() < rhs.ptr(); } virtual void* ptr() const = 0; virtual void enter() = 0; virtual void maintain() = 0; virtual void leave() = 0; virtual void setPause(bool pause) = 0; virtual void reset() = 0; virtual ~ObjectOperator() {} }; class OSGPRESENTATION_EXPORT ActiveOperators { public: ActiveOperators(); ~ActiveOperators(); void collect(osg::Node* incommingNode, osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); void process(); void setPause(bool pause); bool getPause() const { return _pause; } void reset(); typedef std::set< osg::ref_ptr, dereference_less > OperatorList; protected: void processOutgoing(); void processIncomming(); void processMaintained(); bool _pause; OperatorList _previous; OperatorList _current; OperatorList _outgoing; OperatorList _incomming; OperatorList _maintained; }; class OSGPRESENTATION_EXPORT SlideEventHandler : public osgGA::GUIEventHandler { public: SlideEventHandler(osgViewer::Viewer* viewer=0); static SlideEventHandler* instance(); META_Object(osgslideshowApp,SlideEventHandler); void set(osg::Node* model); virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); } /** Event traversal node callback method.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&); virtual void getUsage(osg::ApplicationUsage& usage) const; osgViewer::Viewer* getViewer() { return _viewer.get(); } enum WhichPosition { FIRST_POSITION = 0, LAST_POSITION = -1 }; void compileSlide(unsigned int slideNum); void releaseSlide(unsigned int slideNum); unsigned int getNumSlides(); int getActiveSlide() const { return _activeSlide; } int getActiveLayer() const { return _activeLayer; } bool selectSlide(int slideNum,int layerNum=FIRST_POSITION); bool selectLayer(int layerNum); bool nextLayerOrSlide(); bool previousLayerOrSlide(); bool nextSlide(); bool previousSlide(); bool nextLayer(); bool previousLayer(); bool home(); void setAutoSteppingActive(bool flag = true) { _autoSteppingActive = flag; } bool getAutoSteppingActive() const { return _autoSteppingActive; } void setTimeDelayBetweenSlides(double dt) { _timePerSlide = dt; } double getTimeDelayBetweenSlides() const { return _timePerSlide; } double getDuration(const osg::Node* node) const; double getCurrentTimeDelayBetweenSlides() const; void setReleaseAndCompileOnEachNewSlide(bool flag) { _releaseAndCompileOnEachNewSlide = flag; } bool getReleaseAndCompileOnEachNewSlide() const { return _releaseAndCompileOnEachNewSlide; } void setTimeDelayOnNewSlideWithMovies(float t) { _timeDelayOnNewSlideWithMovies = t; } float getTimeDelayOnNewSlideWithMovies() const { return _timeDelayOnNewSlideWithMovies; } void setLoopPresentation(bool loop) { _loopPresentation = loop; } bool getLoopPresentation() const { return _loopPresentation; } void dispatchEvent(const KeyPosition& keyPosition); enum ObjectMask { MOVIE = 1<<0, OBJECTS = 1<<1, ALL_OBJECTS = MOVIE | OBJECTS }; protected: ~SlideEventHandler() {} SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {} bool home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa); void updateAlpha(bool, bool, float x, float y); void updateLight(float x, float y); osg::observer_ptr _viewer; osg::observer_ptr _showSwitch; int _activePresentation; osg::observer_ptr _presentationSwitch; int _activeSlide; osg::observer_ptr _slideSwitch; int _activeLayer; bool _firstTraversal; double _previousTime; double _timePerSlide; bool _autoSteppingActive; bool _loopPresentation; bool _pause; bool _hold; bool _updateLightActive; bool _updateOpacityActive; float _previousX, _previousY; bool _cursorOn; bool _releaseAndCompileOnEachNewSlide; bool _firstSlideOrLayerChange; osg::Timer_t _tickAtFirstSlideOrLayerChange; osg::Timer_t _tickAtLastSlideOrLayerChange; float _timeDelayOnNewSlideWithMovies; double _minimumTimeBetweenKeyPresses; double _timeLastKeyPresses; ActiveOperators _activeOperators; osg::ref_ptr _compileSlideCallback; void updateOperators(); }; } #endif