/* -*-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 #include #include #include namespace osgPresentation { // forward declare class SlideEventHandler; /// Operations related to click to run/load/key events. enum Operation { RUN, LOAD, EVENT, JUMP, FORWARD_MOUSE_EVENT, FORWARD_TOUCH_EVENT }; struct JumpData : public osg::Object { JumpData(): relativeJump(true), slideNum(0), layerNum(0) {} JumpData(bool in_relativeJump, int in_slideNum, int in_layerNum): relativeJump(in_relativeJump), slideNum(in_slideNum), layerNum(in_layerNum) {} JumpData(const std::string& in_slideName, const std::string& in_layerName): relativeJump(true), slideNum(0), layerNum(0), slideName(in_slideName), layerName(in_layerName) {} JumpData(const JumpData& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osg::Object(rhs, copyop), relativeJump(rhs.relativeJump), slideNum(rhs.slideNum), layerNum(rhs.layerNum), slideName(rhs.slideName), layerName(rhs.layerName) {} JumpData& operator = (const JumpData& rhs) { if (&rhs==this) return *this; relativeJump = rhs.relativeJump; slideNum = rhs.slideNum; layerNum = rhs.layerNum; slideName = rhs.slideName; layerName = rhs.layerName; return *this; } META_Object(osgPresentation, JumpData); bool requiresJump() const { if (!slideName.empty() || !layerName.empty()) return true; return relativeJump ? (slideNum!=0 || layerNum!=0) : true; } bool jump(SlideEventHandler* seh) const; void setRelativeJump(bool flag) { relativeJump = flag; } bool getRelativeJump() const { return relativeJump; } void setSlideNum(int num) { slideNum = num; } int getSlideNum() const { return slideNum; } void setLayerNum(int num) { layerNum = num; } int getLayerNum() const { return layerNum; } void setSlideName(const std::string& name) { slideName = name; } const std::string& getSlideName() const { return slideName; } void setLayerName(const std::string& name) { layerName = name; } const std::string& getLayerName() const { return layerName; } bool relativeJump; int slideNum; int layerNum; std::string slideName; std::string layerName; }; struct HomePosition : public osg::Object { HomePosition(): eye(0.0, -1.0, 0.0), center(0.0, 0.0, 0.0), up(0.0, 0.0, 1.0) {} 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) {} HomePosition(const HomePosition& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osg::Object(rhs, copyop), eye(rhs.eye), center(rhs.center), up(rhs.up) {} HomePosition& operator = (const HomePosition& rhs) { if (&rhs==this) return *this; eye = rhs.eye; center = rhs.center; up = rhs.up; return *this; } META_Object(osgPresentation, HomePosition); void setEye(const osg::Vec3d& e) { eye = e; } const osg::Vec3d& getEye() const { return eye; } void setCenter(const osg::Vec3d& c) { center = c; } const osg::Vec3d& getCenter() const { return center; } void setUp(const osg::Vec3d& u) { up = u; } const osg::Vec3d& getUp() const { return up; } osg::Vec3d eye; osg::Vec3d center; osg::Vec3d up; }; struct KeyPosition : public osg::Object { KeyPosition(unsigned int key=0, float x=FLT_MAX, float y=FLT_MAX, bool forward_to_devices = false): _key((osgGA::GUIEventAdapter::KeySymbol)key), _x(x), _y(y), _forwardToDevices(forward_to_devices) {} KeyPosition(const KeyPosition& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osg::Object(rhs, copyop), _key(rhs._key), _x(rhs._x), _y(rhs._y), _forwardToDevices(rhs._forwardToDevices) {} META_Object(osgPresentation, KeyPosition); KeyPosition& operator = (const KeyPosition& rhs) { if (&rhs==this) return *this; _key = rhs._key; _x = rhs._x; _y = rhs._y; _forwardToDevices = rhs._forwardToDevices; return *this; } void set(unsigned int key=0, float x=FLT_MAX, float y=FLT_MAX, bool forward_to_devices = false) { _key = (osgGA::GUIEventAdapter::KeySymbol)key; _x = x; _y = y; _forwardToDevices = forward_to_devices; } void setKey(int key) { _key = static_cast(key); } int getKey() const { return _key; } void setX(float x) { _x = x; } float getX() const { return _x; } void setY(float y) { _y = y; } float getY() const { return _y; } void setForwardToDevices(bool flag) { _forwardToDevices = flag; } bool getForwardToDevices() const { return _forwardToDevices; } osgGA::GUIEventAdapter::KeySymbol _key; float _x; float _y; bool _forwardToDevices; }; 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) {} LayerAttributes(double in_duration):_duration(in_duration) {} 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(const JumpData& jumpData) { _jumpData = jumpData; } const JumpData& getJumpData() const { return _jumpData; } double _duration; Keys _keys; RunStrings _runStrings; JumpData _jumpData; 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(SlideEventHandler*) = 0; virtual void frame(SlideEventHandler*) {} ; virtual void maintain(SlideEventHandler*) = 0; virtual void leave(SlideEventHandler*) = 0; virtual void setPause(SlideEventHandler*, bool pause) = 0; virtual void reset(SlideEventHandler*) = 0; virtual ~ObjectOperator() {} }; class OSGPRESENTATION_EXPORT ActiveOperators { public: ActiveOperators(); ~ActiveOperators(); void collect(osg::Node* incomingNode, osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); void process(SlideEventHandler* seh); void frame(SlideEventHandler*); void setPause(SlideEventHandler* seh, bool pause); bool getPause() const { return _pause; } void reset(SlideEventHandler* seh); typedef std::set< osg::ref_ptr, dereference_less > OperatorList; protected: void processOutgoing(SlideEventHandler* seh); void processIncoming(SlideEventHandler* seh); void processMaintained(SlideEventHandler* seh); bool _pause; OperatorList _previous; OperatorList _current; OperatorList _outgoing; OperatorList _incoming; OperatorList _maintained; }; class OSGPRESENTATION_EXPORT SlideEventHandler : public osgGA::GUIEventHandler { public: SlideEventHandler(osgViewer::Viewer* viewer=0); SlideEventHandler(const SlideEventHandler& seh,const osg::CopyOp& copyop); static SlideEventHandler* instance(); META_Object(osgPresentation,SlideEventHandler); void set(osg::Node* model); virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&); virtual void getUsage(osg::ApplicationUsage& usage) const; osgViewer::Viewer* getViewer() { return _viewer.get(); } osg::Switch* getPresentationSwitch() { return _presentationSwitch.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; } osg::Switch* getSlide(int slideNum); osg::Node* getLayer(int slideNum, int layerNum); 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); void dispatchEvent(osgGA::Event* event); void forwardEventToDevices(osgGA::Event* event); void setRequestReload(bool flag); bool getRequestReload() const { return _requestReload; } double getReferenceTime() const { return _referenceTime; } virtual bool checkNeedToDoFrame(); protected: ~SlideEventHandler() {} bool home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa); void updateAlpha(bool, bool, float x, float y); void updateLight(float x, float y); void updateOperators(); 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 _referenceTime; 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; bool _requestReload; }; } #endif