This feature makes it easier to editor an presentation that is already running in Present3D, once the edits are done pressing 'u' in Present3D then loads the file again.
1732 lines
50 KiB
C++
1732 lines
50 KiB
C++
/* -*-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 <osgPresentation/SlideEventHandler>
|
|
#include <osgPresentation/SlideShowConstructor>
|
|
#include <osgPresentation/AnimationMaterial>
|
|
|
|
#include <osg/AnimationPath>
|
|
#include <osg/Transform>
|
|
#include <osg/TexEnvCombine>
|
|
#include <osg/LightSource>
|
|
#include <osg/AlphaFunc>
|
|
#include <osg/Timer>
|
|
#include <osg/io_utils>
|
|
|
|
#include <osgUtil/TransformCallback>
|
|
#include <osgUtil/GLObjectsVisitor>
|
|
|
|
#include <osgDB/WriteFile>
|
|
|
|
#include <osgGA/AnimationPathManipulator>
|
|
|
|
|
|
#include <iostream>
|
|
|
|
using namespace osgPresentation;
|
|
|
|
static osg::observer_ptr<SlideEventHandler> s_seh;
|
|
|
|
SlideEventHandler* SlideEventHandler::instance() { return s_seh.get(); }
|
|
|
|
bool JumpData::jump(SlideEventHandler* seh) const
|
|
{
|
|
OSG_NOTICE<<"Requires jump"<<seh<<", "<<relativeJump<<", "<<slideNum<<", "<<layerNum<<", "<<slideName<<", "<<layerName<<std::endl;
|
|
|
|
int slideNumToUse = slideNum;
|
|
int layerNumToUse = layerNum;
|
|
|
|
if (!slideName.empty())
|
|
{
|
|
osg::Switch* presentation = seh->getPresentationSwitch();
|
|
if (presentation)
|
|
{
|
|
for(unsigned int i=0; i<presentation->getNumChildren(); ++i)
|
|
{
|
|
osg::Node* node = seh->getSlide(i);
|
|
std::string name;
|
|
if (node->getUserValue("name",name) && slideName==name)
|
|
{
|
|
slideNumToUse = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (relativeJump)
|
|
{
|
|
slideNumToUse = seh->getActiveSlide() + slideNum;
|
|
}
|
|
|
|
|
|
if (!layerName.empty())
|
|
{
|
|
osg::Switch* slide = seh->getSlide(slideNumToUse);
|
|
if (slide)
|
|
{
|
|
unsigned int i;
|
|
for(i=0; i<slide->getNumChildren(); ++i)
|
|
{
|
|
osg::Node* node = slide->getChild(i);
|
|
std::string name;
|
|
if (node->getUserValue("name",name))
|
|
{
|
|
if (layerName==name)
|
|
{
|
|
layerNumToUse = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (i==slide->getNumChildren())
|
|
{
|
|
OSG_INFO<<"Could not find layer with "<<layerName<<std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"No appropriate Slide found."<<std::endl;
|
|
}
|
|
}
|
|
else if (relativeJump)
|
|
{
|
|
layerNumToUse = seh->getActiveLayer() + layerNum;
|
|
}
|
|
|
|
if (slideNumToUse<0) slideNumToUse = 0;
|
|
if (layerNumToUse<0) layerNumToUse = 0;
|
|
|
|
OSG_INFO<<" jump to "<<slideNumToUse<<", "<<layerNumToUse<<std::endl;
|
|
return seh->selectSlide(slideNumToUse,layerNumToUse);
|
|
}
|
|
|
|
void LayerAttributes::callEnterCallbacks(osg::Node* node)
|
|
{
|
|
OSG_INFO<<"LayerAttributes::callEnterCallbacks("<<node<<")"<<std::endl;
|
|
for(LayerCallbacks::iterator itr = _enterLayerCallbacks.begin();
|
|
itr != _enterLayerCallbacks.end();
|
|
++itr)
|
|
{
|
|
(*(*itr))(node);
|
|
}
|
|
}
|
|
|
|
void LayerAttributes::callLeaveCallbacks(osg::Node* node)
|
|
{
|
|
OSG_INFO<<"LayerAttributes::callLeaveCallbacks("<<node<<")"<<std::endl;
|
|
for(LayerCallbacks::iterator itr = _leaveLayerCallbacks.begin();
|
|
itr != _leaveLayerCallbacks.end();
|
|
++itr)
|
|
{
|
|
(*(*itr))(node);
|
|
}
|
|
}
|
|
|
|
|
|
struct InteractiveImageSequenceOperator : public ObjectOperator
|
|
{
|
|
InteractiveImageSequenceOperator(osg::ImageSequence* imageSequence):
|
|
_imageSequence(imageSequence) {}
|
|
|
|
virtual void* ptr() const { return _imageSequence.get(); }
|
|
|
|
virtual void enter(SlideEventHandler* seh)
|
|
{
|
|
set(seh);
|
|
// need to pause till the load has been completed.
|
|
}
|
|
|
|
virtual void maintain(SlideEventHandler* /*seh*/)
|
|
{
|
|
}
|
|
|
|
virtual void leave(SlideEventHandler* /*seh*/)
|
|
{
|
|
}
|
|
|
|
virtual void setPause(SlideEventHandler* /*seh*/, bool /*pause*/)
|
|
{
|
|
}
|
|
|
|
virtual void reset(SlideEventHandler* seh)
|
|
{
|
|
set(seh);
|
|
}
|
|
|
|
void set(SlideEventHandler* /*seh*/)
|
|
{
|
|
//OSG_NOTICE<<"InteractiveImageSequenceOperator::set(..)"<<std::endl;
|
|
}
|
|
|
|
osg::ref_ptr<osg::ImageSequence> _imageSequence;
|
|
};
|
|
|
|
struct ImageStreamOperator : public ObjectOperator
|
|
{
|
|
ImageStreamOperator(osg::ImageStream* imageStream):
|
|
_imageStream(imageStream),
|
|
_delayTime(0.0),
|
|
_startTime(0.0),
|
|
_stopTime(-1.0),
|
|
_timeOfLastReset(0.0),
|
|
_started(false),
|
|
_stopped(false)
|
|
{
|
|
_imageStream->getUserValue("delay",_delayTime);
|
|
_imageStream->getUserValue("start",_startTime);
|
|
_imageStream->getUserValue("stop",_stopTime);
|
|
}
|
|
|
|
virtual void* ptr() const { return _imageStream.get(); }
|
|
|
|
|
|
virtual void enter(SlideEventHandler* seh)
|
|
{
|
|
OSG_NOTICE<<"enter() : _imageStream->rewind() + play"<<std::endl;
|
|
|
|
reset(seh);
|
|
}
|
|
|
|
virtual void frame(SlideEventHandler* seh)
|
|
{
|
|
if (_delayTime!=0.0 && !_started && !_stopped)
|
|
{
|
|
double timeSinceLastRest = seh->getReferenceTime()-_timeOfLastReset;
|
|
if (timeSinceLastRest>_delayTime)
|
|
{
|
|
OSG_NOTICE<<"ImageStreamOperator::frame("<<seh->getReferenceTime()<<") calling start"<<std::endl;
|
|
start(seh);
|
|
}
|
|
}
|
|
if (_stopTime>0.0 && _started && !_stopped)
|
|
{
|
|
double timeSinceLastReset = seh->getReferenceTime()-_timeOfLastReset;
|
|
double timeSinceStart = (timeSinceLastReset-_delayTime);
|
|
if ((timeSinceStart+_startTime)>_stopTime)
|
|
{
|
|
OSG_NOTICE<<"ImageStreamOperator::frame("<<seh->getReferenceTime()<<") calling stop"<<std::endl;
|
|
stop(seh);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void maintain(SlideEventHandler*)
|
|
{
|
|
OSG_NOTICE<<"ImageStreamOperator::maintain()"<<std::endl;
|
|
}
|
|
|
|
virtual void leave(SlideEventHandler*)
|
|
{
|
|
OSG_NOTICE<<"leave() : _imageStream->pause()"<<std::endl;
|
|
|
|
_imageStream->pause();
|
|
}
|
|
|
|
virtual void setPause(SlideEventHandler*, bool pause)
|
|
{
|
|
OSG_INFO<<"_imageStream->setPause("<<pause<<")"<<std::endl;
|
|
|
|
if (_started)
|
|
{
|
|
if (pause) _imageStream->pause();
|
|
else _imageStream->play();
|
|
}
|
|
}
|
|
|
|
virtual void reset(SlideEventHandler* seh)
|
|
{
|
|
OSG_NOTICE<<"ImageStreamOperator::reset()"<<std::endl;
|
|
|
|
_timeOfLastReset = seh->getReferenceTime();
|
|
_stopped = false;
|
|
|
|
if (_delayTime==0.0)
|
|
{
|
|
start(seh);
|
|
}
|
|
}
|
|
|
|
void start(SlideEventHandler*)
|
|
{
|
|
if (_started) return;
|
|
|
|
_started = true;
|
|
_stopped = false;
|
|
|
|
if (_startTime!=0.0) _imageStream->seek(_startTime);
|
|
else _imageStream->rewind();
|
|
|
|
//_imageStream->setVolume(previousVolume);
|
|
|
|
_imageStream->play();
|
|
|
|
// add a delay so that movie thread has a chance to do the rewind
|
|
float microSecondsToDelay = SlideEventHandler::instance()->getTimeDelayOnNewSlideWithMovies() * 1000000.0f;
|
|
OpenThreads::Thread::microSleep(static_cast<unsigned int>(microSecondsToDelay));
|
|
}
|
|
|
|
void stop(SlideEventHandler* /*seh*/)
|
|
{
|
|
if (!_started) return;
|
|
|
|
_started = false;
|
|
_stopped = true;
|
|
|
|
_imageStream->pause();
|
|
}
|
|
|
|
osg::ref_ptr<osg::ImageStream> _imageStream;
|
|
double _delayTime;
|
|
double _startTime;
|
|
double _stopTime;
|
|
double _timeOfLastReset;
|
|
bool _started;
|
|
bool _stopped;
|
|
};
|
|
|
|
struct CallbackOperator : public ObjectOperator
|
|
{
|
|
CallbackOperator(osg::Node* node, osg::Referenced* callback):
|
|
_node(node),
|
|
_callback(callback) {}
|
|
|
|
virtual void* ptr() const { return _callback.get(); }
|
|
|
|
virtual void enter(SlideEventHandler* seh)
|
|
{
|
|
reset(seh);
|
|
}
|
|
|
|
virtual void maintain(SlideEventHandler*)
|
|
{
|
|
}
|
|
|
|
virtual void leave(SlideEventHandler*)
|
|
{
|
|
}
|
|
|
|
virtual void setPause(SlideEventHandler*, bool pause)
|
|
{
|
|
osg::NodeCallback* nc = dynamic_cast<osg::NodeCallback*>(_callback.get());
|
|
osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
|
|
osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
|
|
AnimationMaterialCallback* amc = dynamic_cast<AnimationMaterialCallback*>(_callback.get());
|
|
PropertyAnimation* pa = dynamic_cast<PropertyAnimation*>(_callback.get());
|
|
if (apc)
|
|
{
|
|
OSG_INFO<<"apc->setPause("<<pause<<")"<<std::endl;
|
|
apc->setPause(pause);
|
|
}
|
|
else if (tc)
|
|
{
|
|
OSG_INFO<<"tc->setPause("<<pause<<")"<<std::endl;
|
|
tc->setPause(pause);
|
|
}
|
|
else if (amc)
|
|
{
|
|
OSG_INFO<<"amc->setPause("<<pause<<")"<<std::endl;
|
|
amc->setPause(pause);
|
|
}
|
|
else if (pa)
|
|
{
|
|
pa->setPause(pause);
|
|
}
|
|
else if (nc)
|
|
{
|
|
OSG_INFO<<"Need to pause callback : "<<nc->className()<<std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
virtual void reset(SlideEventHandler*)
|
|
{
|
|
osg::NodeCallback* nc = dynamic_cast<osg::NodeCallback*>(_callback.get());
|
|
osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
|
|
osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
|
|
AnimationMaterialCallback* amc = dynamic_cast<AnimationMaterialCallback*>(_callback.get());
|
|
PropertyAnimation* pa = dynamic_cast<PropertyAnimation*>(_callback.get());
|
|
if (apc)
|
|
{
|
|
apc->reset();
|
|
apc->update(*_node);
|
|
}
|
|
else if (tc)
|
|
{
|
|
}
|
|
else if (amc)
|
|
{
|
|
amc->reset();
|
|
amc->update(*_node);
|
|
}
|
|
else if (pa)
|
|
{
|
|
pa->reset();
|
|
pa->update(*_node);
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"Need to reset callback : "<<nc->className()<<std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
osg::ref_ptr<osg::Node> _node;
|
|
osg::ref_ptr<osg::Referenced> _callback;
|
|
};
|
|
|
|
struct LayerAttributesOperator : public ObjectOperator
|
|
{
|
|
LayerAttributesOperator(osg::Node* node, LayerAttributes* la):
|
|
_node(node),
|
|
_layerAttribute(la)
|
|
{
|
|
}
|
|
|
|
virtual void* ptr() const { return _layerAttribute.get(); }
|
|
|
|
virtual void enter(SlideEventHandler*)
|
|
{
|
|
_layerAttribute->callEnterCallbacks(_node.get());
|
|
|
|
if (!_layerAttribute->_keys.empty())
|
|
{
|
|
OSG_INFO<<"applyKeys {"<<std::endl;
|
|
|
|
for(LayerAttributes::Keys::iterator itr = _layerAttribute->_keys.begin();
|
|
itr != _layerAttribute->_keys.end();
|
|
++itr)
|
|
{
|
|
SlideEventHandler::instance()->dispatchEvent(*itr);
|
|
}
|
|
|
|
OSG_INFO<<"}"<<std::endl;
|
|
}
|
|
if (!_layerAttribute->_runStrings.empty())
|
|
{
|
|
for(LayerAttributes::RunStrings::iterator itr = _layerAttribute->_runStrings.begin();
|
|
itr != _layerAttribute->_runStrings.end();
|
|
++itr)
|
|
{
|
|
|
|
OSG_NOTICE<<"Run "<<itr->c_str()<<std::endl;
|
|
osg::Timer_t startTick = osg::Timer::instance()->tick();
|
|
|
|
int result = system(itr->c_str());
|
|
|
|
OSG_INFO<<"system("<<*itr<<") result "<<result<<std::endl;
|
|
|
|
double timeForRun = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
|
|
|
|
osgGA::EventQueue* eq = SlideEventHandler::instance()->getViewer()->getEventQueue();
|
|
if (eq)
|
|
{
|
|
osg::Timer_t new_startTick = eq->getStartTick() + osg::Timer_t(timeForRun / osg::Timer::instance()->getSecondsPerTick());
|
|
eq->setStartTick(new_startTick);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
virtual void maintain(SlideEventHandler*)
|
|
{
|
|
}
|
|
|
|
virtual void leave(SlideEventHandler*)
|
|
{
|
|
OSG_INFO<<"LayerAttribute leave"<<std::endl;
|
|
|
|
_layerAttribute->callLeaveCallbacks(_node.get());
|
|
}
|
|
|
|
virtual void setPause(SlideEventHandler*, bool /*pause*/)
|
|
{
|
|
}
|
|
|
|
virtual void reset(SlideEventHandler*)
|
|
{
|
|
}
|
|
|
|
|
|
osg::ref_ptr<osg::Node> _node;
|
|
osg::ref_ptr<LayerAttributes> _layerAttribute;
|
|
};
|
|
|
|
|
|
class FindOperatorsVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
FindOperatorsVisitor(ActiveOperators::OperatorList& operatorList, osg::NodeVisitor::TraversalMode tm):
|
|
osg::NodeVisitor(tm),
|
|
_operatorList(operatorList) {}
|
|
|
|
META_NodeVisitor(osgPresentation, FindOperatorsVisitor)
|
|
|
|
void apply(osg::Node& node)
|
|
{
|
|
if (node.getStateSet()) process(node.getStateSet());
|
|
|
|
if (node.getUpdateCallback())
|
|
{
|
|
_operatorList.insert(new CallbackOperator(&node, node.getUpdateCallback()));
|
|
}
|
|
|
|
LayerAttributes* la = dynamic_cast<LayerAttributes*>(node.getUserData());
|
|
if (la)
|
|
{
|
|
if ((_objectsHandled[la]++)==0)
|
|
{
|
|
OSG_INFO<<"LayerAttributeOperator for "<<la<<" required, assigning one."<<std::endl;
|
|
_operatorList.insert(new LayerAttributesOperator(&node, la));
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"LayerAttributeOperator for "<<la<<" not required, as one already assigned."<<std::endl;
|
|
}
|
|
}
|
|
|
|
traverse(node);
|
|
}
|
|
|
|
void apply(osg::Geode& node)
|
|
{
|
|
apply((osg::Node&)node);
|
|
for(unsigned int i=0;i<node.getNumDrawables();++i)
|
|
{
|
|
osg::Drawable* drawable = node.getDrawable(i);
|
|
if (drawable->getStateSet()) process(drawable->getStateSet());
|
|
}
|
|
}
|
|
|
|
virtual void process(osg::StateSet* ss)
|
|
{
|
|
for(unsigned int i=0;i<ss->getTextureAttributeList().size();++i)
|
|
{
|
|
osg::Texture* texture = dynamic_cast<osg::Texture*>(ss->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
|
|
osg::Image* image = texture ? texture->getImage(0) : 0;
|
|
osg::ImageSequence* imageSequence = dynamic_cast<osg::ImageSequence*>(image);
|
|
osg::ImageStream* imageStream = dynamic_cast<osg::ImageStream*>(image);
|
|
if (imageSequence && imageSequence->getName()=="USE_MOUSE_X_POSITION")
|
|
{
|
|
if ((_objectsHandled[image]++)==0)
|
|
{
|
|
OSG_INFO<<"ImageSequenceOperator for"<<imageSequence<<" required, assigning one, name = '"<<image->getName()<<"'"<<std::endl;
|
|
_operatorList.insert(new InteractiveImageSequenceOperator(imageSequence));
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"ImageSequenceOperator for"<<imageSequence<<" not required, as one already assigned"<<std::endl;
|
|
}
|
|
}
|
|
else if (imageStream)
|
|
{
|
|
if ((_objectsHandled[image]++)==0)
|
|
{
|
|
OSG_INFO<<"ImageStreamOperator for"<<imageStream<<" required, assigning one"<<std::endl;
|
|
_operatorList.insert(new ImageStreamOperator(imageStream));
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"ImageStreamOperator for"<<imageStream<<" not required, as one already assigned"<<std::endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef std::map<osg::Referenced*,unsigned int> ObjectsHandled;
|
|
ObjectsHandled _objectsHandled;
|
|
|
|
ActiveOperators::OperatorList& _operatorList;
|
|
};
|
|
|
|
|
|
ActiveOperators::ActiveOperators():
|
|
_pause(false)
|
|
{
|
|
}
|
|
|
|
ActiveOperators::~ActiveOperators()
|
|
{
|
|
}
|
|
|
|
void ActiveOperators::collect(osg::Node* incomingNode, osg::NodeVisitor::TraversalMode tm)
|
|
{
|
|
_previous.swap(_current);
|
|
|
|
_current.clear();
|
|
|
|
FindOperatorsVisitor fov(_current, tm);
|
|
|
|
if (incomingNode)
|
|
{
|
|
incomingNode->accept(fov);
|
|
}
|
|
else
|
|
{
|
|
OSG_NOTICE<<"ActiveOperators::collect() incomingNode="<<incomingNode<<std::endl;
|
|
}
|
|
|
|
OSG_INFO<<"ActiveOperators::collect("<<incomingNode<<")"<<std::endl;
|
|
OSG_INFO<<" _previous.size()="<<_previous.size()<<std::endl;
|
|
OSG_INFO<<" _current.size()="<<_current.size()<<std::endl;
|
|
|
|
_outgoing.clear();
|
|
_incoming.clear();
|
|
_maintained.clear();
|
|
|
|
for(OperatorList::iterator itr = _previous.begin();
|
|
itr != _previous.end();
|
|
++itr)
|
|
{
|
|
ObjectOperator* prev = itr->get();
|
|
if (_current.count(prev)==0) _outgoing.insert(prev);
|
|
else _maintained.insert(prev);
|
|
}
|
|
|
|
for(OperatorList::iterator itr = _current.begin();
|
|
itr != _current.end();
|
|
++itr)
|
|
{
|
|
ObjectOperator* curr = itr->get();
|
|
if (_previous.count(curr)==0) _incoming.insert(curr);
|
|
}
|
|
}
|
|
|
|
void ActiveOperators::frame(SlideEventHandler* seh)
|
|
{
|
|
for(OperatorList::iterator itr = _current.begin();
|
|
itr != _current.end();
|
|
++itr)
|
|
{
|
|
(*itr)->frame(seh);
|
|
}
|
|
}
|
|
|
|
void ActiveOperators::setPause(SlideEventHandler* seh, bool pause)
|
|
{
|
|
_pause = pause;
|
|
for(OperatorList::iterator itr = _current.begin();
|
|
itr != _current.end();
|
|
++itr)
|
|
{
|
|
(*itr)->setPause(seh, _pause);
|
|
}
|
|
}
|
|
|
|
|
|
void ActiveOperators::reset(SlideEventHandler* seh)
|
|
{
|
|
for(OperatorList::iterator itr = _current.begin();
|
|
itr != _current.end();
|
|
++itr)
|
|
{
|
|
(*itr)->reset(seh);
|
|
}
|
|
}
|
|
|
|
void ActiveOperators::process(SlideEventHandler* seh)
|
|
{
|
|
processOutgoing(seh);
|
|
processMaintained(seh);
|
|
processIncoming(seh);
|
|
}
|
|
|
|
void ActiveOperators::processOutgoing(SlideEventHandler* seh)
|
|
{
|
|
OSG_INFO<<" outgoing.size()="<<_outgoing.size()<<std::endl;
|
|
for(OperatorList::iterator itr = _outgoing.begin();
|
|
itr != _outgoing.end();
|
|
++itr)
|
|
{
|
|
(*itr)->leave(seh);
|
|
}
|
|
}
|
|
|
|
void ActiveOperators::processMaintained(SlideEventHandler* seh)
|
|
{
|
|
OSG_INFO<<" maintained.size()="<<_maintained.size()<<std::endl;
|
|
for(OperatorList::iterator itr = _maintained.begin();
|
|
itr != _maintained.end();
|
|
++itr)
|
|
{
|
|
(*itr)->maintain(seh);
|
|
}
|
|
}
|
|
|
|
void ActiveOperators::processIncoming(SlideEventHandler* seh)
|
|
{
|
|
OSG_INFO<<" incoming.size()="<<_incoming.size()<<std::endl;
|
|
for(OperatorList::iterator itr = _incoming.begin();
|
|
itr != _incoming.end();
|
|
++itr)
|
|
{
|
|
(*itr)->enter(seh);
|
|
(*itr)->setPause(seh, _pause);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
class FindHomePositionVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
|
|
FindHomePositionVisitor():
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
|
|
|
|
void apply(osg::Node& node)
|
|
{
|
|
HomePosition* homePosition = dynamic_cast<HomePosition*>(node.getUserData());
|
|
if (homePosition)
|
|
{
|
|
_homePosition = homePosition;
|
|
}
|
|
|
|
traverse(node);
|
|
}
|
|
|
|
osg::ref_ptr<HomePosition> _homePosition;
|
|
|
|
};
|
|
|
|
class FindNamedSwitchVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
|
|
FindNamedSwitchVisitor(const std::string& name):
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
|
_name(name),
|
|
_switch(0) {}
|
|
|
|
void apply(osg::Switch& sw)
|
|
{
|
|
if (sw.getName().find(_name)!=std::string::npos)
|
|
{
|
|
_switch = &sw;
|
|
return; // note, no need to do traverse now we've located the relevant switch
|
|
}
|
|
|
|
traverse(sw);
|
|
}
|
|
|
|
std::string _name;
|
|
osg::Switch* _switch;
|
|
|
|
};
|
|
|
|
|
|
class FindFilePathDataVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
|
|
FindFilePathDataVisitor():
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
|
|
|
|
void apply(osg::Node& node)
|
|
{
|
|
FilePathData* fdd = dynamic_cast<FilePathData*>(node.getUserData());
|
|
if (fdd)
|
|
{
|
|
OSG_INFO<<"Recorded FilePathData"<<std::endl;
|
|
osgDB::setDataFilePathList(fdd->filePathList);
|
|
}
|
|
|
|
traverse(node);
|
|
}
|
|
|
|
};
|
|
|
|
class UpdateLightVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
|
|
UpdateLightVisitor(const osg::Matrixd& viewMatrix, float currentX, float currentY):
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
|
|
_viewMatrix(viewMatrix),
|
|
_currentX(currentX), _currentY(currentY) {}
|
|
|
|
void apply(osg::Node& node)
|
|
{
|
|
traverse(node);
|
|
}
|
|
|
|
void apply(osg::LightSource& lightsource)
|
|
{
|
|
if (lightsource.getLight())
|
|
{
|
|
if (lightsource.getReferenceFrame()==osg::LightSource::RELATIVE_RF)
|
|
{
|
|
apply( osg::Matrix::identity(), lightsource.getLight());
|
|
}
|
|
else
|
|
{
|
|
apply(osg::computeEyeToLocal(_viewMatrix,_nodePath), lightsource.getLight());
|
|
}
|
|
}
|
|
|
|
traverse(lightsource);
|
|
}
|
|
|
|
void apply(const osg::Matrixd& matrix, osg::Light* light)
|
|
{
|
|
// compute direction of light based on a projecting onto a hemi-sphere.
|
|
float sum_x2_y2 = _currentX*_currentX + _currentY*_currentY;
|
|
osg::Vec3 direction;
|
|
if (sum_x2_y2<1.0) direction.set(_currentX, _currentY, sqrtf(1.0-sum_x2_y2));
|
|
else direction.set(_currentX, _currentY, 0.0);
|
|
|
|
direction.normalize();
|
|
|
|
direction = osg::Matrixd::transform3x3(matrix, direction);
|
|
direction.normalize();
|
|
|
|
light->setPosition(osg::Vec4(direction,0.0f));
|
|
}
|
|
|
|
osg::Matrixd _viewMatrix;
|
|
float _currentX, _currentY;
|
|
|
|
};
|
|
|
|
class UpdateAlphaVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
|
|
UpdateAlphaVisitor(bool modAlphaFunc, bool modMaterial, float currentX, float currentY):
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
|
|
_modAlphaFunc(modAlphaFunc), _modMaterial(modMaterial),
|
|
_currentX(currentX), _currentY(currentY) {}
|
|
|
|
void apply(osg::Node& node)
|
|
{
|
|
if (node.getStateSet()) apply(*node.getStateSet());
|
|
traverse(node);
|
|
}
|
|
|
|
void apply(osg::StateSet& stateset)
|
|
{
|
|
if (_modAlphaFunc)
|
|
{
|
|
osg::AlphaFunc* alphaFunc = dynamic_cast<osg::AlphaFunc*>(stateset.getAttribute(osg::StateAttribute::ALPHAFUNC));
|
|
if (alphaFunc)
|
|
{
|
|
OSG_INFO<<"Adjusting alpha func"<<std::endl;
|
|
|
|
float alpha = alphaFunc->getReferenceValue();
|
|
alpha = osg::clampBetween((1.0f-_currentY)*0.5f,0.0f,1.0f);
|
|
|
|
alphaFunc->setReferenceValue(alpha);
|
|
}
|
|
}
|
|
|
|
if (_modMaterial)
|
|
{
|
|
osg::Material* material = dynamic_cast<osg::Material*>(stateset.getAttribute(osg::StateAttribute::MATERIAL));
|
|
if (material)
|
|
{
|
|
OSG_INFO<<"Adjusting material func"<<std::endl;
|
|
float alpha = osg::clampBetween((_currentY+1.0f)*0.5f,0.0f,1.0f);
|
|
material->setAlpha(osg::Material::FRONT_AND_BACK,alpha);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool _modAlphaFunc, _modMaterial;
|
|
float _currentX, _currentY;
|
|
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SlideEventHandler
|
|
//
|
|
SlideEventHandler::SlideEventHandler(osgViewer::Viewer* viewer):
|
|
_viewer(viewer),
|
|
_presentationSwitch(0),
|
|
_activeSlide(0),
|
|
_slideSwitch(0),
|
|
_activeLayer(0),
|
|
_firstTraversal(true),
|
|
_referenceTime(-1.0),
|
|
_previousTime(-1.0),
|
|
_timePerSlide(1.0),
|
|
_autoSteppingActive(false),
|
|
_loopPresentation(false),
|
|
_pause(false),
|
|
_hold(false),
|
|
_updateLightActive(false),
|
|
_updateOpacityActive(false),
|
|
_previousX(0), _previousY(0),
|
|
_cursorOn(true),
|
|
_releaseAndCompileOnEachNewSlide(false),
|
|
_firstSlideOrLayerChange(true),
|
|
_tickAtFirstSlideOrLayerChange(0),
|
|
_tickAtLastSlideOrLayerChange(0),
|
|
_timeDelayOnNewSlideWithMovies(0.25f),
|
|
_minimumTimeBetweenKeyPresses(0.25),
|
|
_timeLastKeyPresses(-1.0),
|
|
_requestReload(false)
|
|
{
|
|
s_seh = this;
|
|
}
|
|
|
|
double SlideEventHandler::getDuration(const osg::Node* node) const
|
|
{
|
|
const LayerAttributes* la = dynamic_cast<const LayerAttributes*>(node->getUserData());
|
|
return la ? la->_duration : -1.0;
|
|
}
|
|
|
|
void SlideEventHandler::set(osg::Node* model)
|
|
{
|
|
#if 0
|
|
// pause all slides, then just reenable the current slide.
|
|
ActivityUpdateCallbacksVisitor aucv(ALL_OBJECTS, true);
|
|
aucv.setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
|
|
model->accept(aucv);
|
|
#endif
|
|
_firstSlideOrLayerChange = true;
|
|
_tickAtFirstSlideOrLayerChange = 0;
|
|
_tickAtLastSlideOrLayerChange = 0;
|
|
_timeLastKeyPresses = -1;
|
|
|
|
ActiveOperators operators;
|
|
operators.collect(model, osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
|
|
operators.setPause(this, true);
|
|
|
|
FindNamedSwitchVisitor findPresentation("Presentation");
|
|
model->accept(findPresentation);
|
|
|
|
std::string fullpath;
|
|
model->getUserValue("fullpath", fullpath);
|
|
if (!fullpath.empty()) setUserValue("fullpath", fullpath);
|
|
|
|
if (findPresentation._switch)
|
|
{
|
|
OSG_INFO<<"Presentation '"<<model->getName()<<"'"<<std::endl;
|
|
_presentationSwitch = findPresentation._switch;
|
|
|
|
double duration = getDuration(_presentationSwitch.get());
|
|
if (duration>=0.0)
|
|
{
|
|
OSG_INFO<<"Presentation time set to "<<duration<<std::endl;
|
|
_timePerSlide = duration;
|
|
}
|
|
|
|
//selectSlide(0);
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"No presentation present in scene."<<std::endl;
|
|
|
|
_presentationSwitch = 0;
|
|
_activeSlide = 0;
|
|
|
|
FindNamedSwitchVisitor findSlide("Slide");
|
|
model->accept(findSlide);
|
|
|
|
if (findSlide._switch)
|
|
{
|
|
OSG_INFO<<"Found presentation slide"<<findSlide._switch->getName()<<std::endl;
|
|
|
|
_slideSwitch = findSlide._switch;
|
|
//selectLayer(0);
|
|
}
|
|
else
|
|
{
|
|
OSG_INFO<<"No slides present in scene, unable to operate as a slideshow."<<std::endl;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
double SlideEventHandler::getCurrentTimeDelayBetweenSlides() const
|
|
{
|
|
if (_slideSwitch.valid())
|
|
{
|
|
double duration = -1.0;
|
|
if (_activeLayer<static_cast<int>(_slideSwitch->getNumChildren()))
|
|
{
|
|
duration = getDuration(_slideSwitch->getChild(_activeLayer));
|
|
}
|
|
|
|
if (duration < 0.0)
|
|
{
|
|
duration = getDuration(_slideSwitch.get());
|
|
}
|
|
|
|
if (duration >=0 )
|
|
{
|
|
return duration;
|
|
}
|
|
}
|
|
|
|
return _timePerSlide;
|
|
}
|
|
|
|
bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
|
|
{
|
|
|
|
if (!_viewer)
|
|
{
|
|
_viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
|
|
selectSlide(0);
|
|
home();
|
|
OSG_NOTICE<<"Assigned viewer. to SlideEventHandler"<<std::endl;
|
|
}
|
|
//else OSG_NOTICE<<"SlideEventHandler::handle() "<<ea.getTime()<<std::endl;
|
|
|
|
if (ea.getHandled()) return false;
|
|
|
|
_referenceTime = ea.getTime();
|
|
|
|
switch(ea.getEventType())
|
|
{
|
|
case(osgGA::GUIEventAdapter::FRAME):
|
|
{
|
|
if (_autoSteppingActive && !_pause)
|
|
{
|
|
double time = ea.time();
|
|
|
|
if (_firstTraversal)
|
|
{
|
|
_firstTraversal = false;
|
|
_previousTime = time;
|
|
}
|
|
else if (time-_previousTime>=getCurrentTimeDelayBetweenSlides())
|
|
{
|
|
// _previousTime = time;
|
|
|
|
if (!_hold)
|
|
{
|
|
// increment the previous by the required time delay, note relative to the current
|
|
// to keep the time relative to an absolute time signal, thus avoid drift of timing.
|
|
_previousTime += getCurrentTimeDelayBetweenSlides();
|
|
|
|
nextLayerOrSlide();
|
|
aa.requestRedraw();
|
|
}
|
|
else
|
|
{
|
|
// we're holding of the move to next layer to slide, but we need slip the time forward accordingly
|
|
// componensate for the extra time that this frame is receiving.
|
|
_previousTime = time-getCurrentTimeDelayBetweenSlides();
|
|
}
|
|
}
|
|
}
|
|
_activeOperators.frame(this);
|
|
|
|
return false;
|
|
}
|
|
|
|
case(osgGA::GUIEventAdapter::KEYDOWN):
|
|
{
|
|
double time = ea.time();
|
|
double deltaTime = time - _timeLastKeyPresses;
|
|
if (deltaTime < _minimumTimeBetweenKeyPresses)
|
|
{
|
|
break;
|
|
}
|
|
|
|
_timeLastKeyPresses = time;
|
|
|
|
if (ea.getKey()=='g')
|
|
{
|
|
if (!_autoSteppingActive)
|
|
{
|
|
_autoSteppingActive = true;
|
|
_previousTime = ea.time();
|
|
}
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='h')
|
|
{
|
|
if (_autoSteppingActive)
|
|
{
|
|
_autoSteppingActive = false;
|
|
_previousTime = ea.time();
|
|
}
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Home ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Home)
|
|
{
|
|
_autoSteppingActive = false;
|
|
selectSlide(0);
|
|
home(ea,aa);
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_End ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_End)
|
|
{
|
|
_autoSteppingActive = false;
|
|
selectSlide(LAST_POSITION,LAST_POSITION);
|
|
home(ea,aa);
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Down ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Down)
|
|
{
|
|
_autoSteppingActive = false;
|
|
nextLayer();
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='n')
|
|
{
|
|
_autoSteppingActive = false;
|
|
nextLayerOrSlide();
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Up ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Up)
|
|
{
|
|
_autoSteppingActive = false;
|
|
previousLayer();
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Page_Down ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Down)
|
|
{
|
|
_autoSteppingActive = false;
|
|
nextLayerOrSlide();
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Page_Up ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Up)
|
|
{
|
|
_autoSteppingActive = false;
|
|
previousLayerOrSlide();
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='N' ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_Right ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Right)
|
|
{
|
|
_autoSteppingActive = false;
|
|
nextSlide();
|
|
home(ea,aa);
|
|
return true;
|
|
}
|
|
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left ||
|
|
ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Left)
|
|
{
|
|
_autoSteppingActive = false;
|
|
previousSlide();
|
|
home(ea,aa);
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='p')
|
|
{
|
|
if (!_pause)
|
|
{
|
|
_pause = true;
|
|
#if 0
|
|
resetUpdateCallbackActivity(ALL_OBJECTS);
|
|
#endif
|
|
_activeOperators.setPause(this, _pause);
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
else if (ea.getKey()=='o')
|
|
{
|
|
if (_pause)
|
|
{
|
|
_pause = false;
|
|
#if 0
|
|
resetUpdateCallbackActivity(ALL_OBJECTS);
|
|
#endif
|
|
_activeOperators.setPause(this, _pause);
|
|
}
|
|
return true;
|
|
|
|
}
|
|
else if (ea.getKey()=='h')
|
|
{
|
|
_hold = true;
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='r')
|
|
{
|
|
#if 0
|
|
resetUpdateCallbacks(ALL_OBJECTS);
|
|
#endif
|
|
_activeOperators.reset(this);
|
|
return true;
|
|
}
|
|
/*
|
|
else if (ea.getKey()=='c')
|
|
{
|
|
_cursorOn = !_cursorOn;
|
|
|
|
for( unsigned int i = 0; i < _viewer->getCameraConfig()->getNumberOfCameras(); i++ )
|
|
{
|
|
Producer::Camera* cam = _viewer->getCameraConfig()->getCamera(i);
|
|
Producer::RenderSurface* rs = cam->getRenderSurface();
|
|
rs->useCursor(_cursorOn);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
*/
|
|
else if (ea.getKey()=='u')
|
|
{
|
|
updateAlpha(true,false,ea.getXnormalized(),ea.getYnormalized());
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='i')
|
|
{
|
|
updateAlpha(false,true,ea.getXnormalized(),ea.getYnormalized());
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='k')
|
|
{
|
|
updateLight(ea.getXnormalized(),ea.getYnormalized());
|
|
return true;
|
|
}
|
|
|
|
else if (ea.getKey()=='U')
|
|
{
|
|
char* editor = getenv("P3D_EDITOR");
|
|
if (!editor) editor = getenv("EDITOR");
|
|
|
|
std::string filename;
|
|
if (editor && getUserValue("fullpath", filename) && !filename.empty())
|
|
{
|
|
std::stringstream command;
|
|
command<<editor<<" "<<filename<<" &"<<std::endl;
|
|
|
|
int result = system(command.str().c_str());
|
|
|
|
OSG_INFO<<"system("<<command.str()<<") result "<<result<<std::endl;
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
case(osgGA::GUIEventAdapter::KEYUP):
|
|
{
|
|
if (ea.getKey()=='h')
|
|
{
|
|
_hold = false;
|
|
return true;
|
|
}
|
|
else if (ea.getKey()=='u')
|
|
{
|
|
setRequestReload(true);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const
|
|
{
|
|
usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image");
|
|
usage.addKeyboardMouseBinding("n","Advance to next layer or slide");
|
|
usage.addKeyboardMouseBinding("p","Move to previous layer or slide");
|
|
}
|
|
|
|
unsigned int SlideEventHandler::getNumSlides()
|
|
{
|
|
if (_presentationSwitch.valid()) return _presentationSwitch->getNumChildren();
|
|
else return 0;
|
|
}
|
|
|
|
osg::Switch* SlideEventHandler::getSlide(int slideNum)
|
|
{
|
|
if (slideNum<0 || slideNum>static_cast<int>(_presentationSwitch->getNumChildren())) return 0;
|
|
|
|
FindNamedSwitchVisitor findSlide("Slide");
|
|
_presentationSwitch->getChild(slideNum)->accept(findSlide);
|
|
return findSlide._switch;
|
|
}
|
|
|
|
osg::Node* SlideEventHandler::getLayer(int slideNum, int layerNum)
|
|
{
|
|
osg::Switch* slide = getSlide(slideNum);
|
|
return (slide && (layerNum>=0 && layerNum<static_cast<int>(slide->getNumChildren()))) ? slide->getChild(layerNum) : 0;
|
|
}
|
|
|
|
|
|
bool SlideEventHandler::selectSlide(int slideNum,int layerNum)
|
|
{
|
|
if (!_presentationSwitch) return false;
|
|
|
|
OSG_INFO<<"selectSlide("<<slideNum<<","<<layerNum<<")"<<std::endl;
|
|
|
|
if (slideNum>=static_cast<int>(_presentationSwitch->getNumChildren()))
|
|
{
|
|
slideNum = LAST_POSITION;
|
|
}
|
|
|
|
if (slideNum==LAST_POSITION && _presentationSwitch->getNumChildren()>0)
|
|
{
|
|
slideNum = _presentationSwitch->getNumChildren()-1;
|
|
}
|
|
|
|
if (slideNum>=static_cast<int>(_presentationSwitch->getNumChildren())) return false;
|
|
|
|
|
|
osg::Timer_t tick = osg::Timer::instance()->tick();
|
|
|
|
if (_firstSlideOrLayerChange)
|
|
{
|
|
_firstSlideOrLayerChange = false;
|
|
_tickAtFirstSlideOrLayerChange = tick;
|
|
_tickAtLastSlideOrLayerChange = tick;
|
|
}
|
|
|
|
OSG_INFO<<"selectSlide("<<slideNum<<","<<layerNum<<") at time "<<osg::Timer::instance()->delta_s(_tickAtFirstSlideOrLayerChange, tick)<<" seconds, length ="<<osg::Timer::instance()->delta_s(_tickAtLastSlideOrLayerChange, tick)<<" seconds"<<std::endl;
|
|
|
|
_tickAtLastSlideOrLayerChange = tick;
|
|
|
|
// dectivate movies etc on current active slide.
|
|
bool newSlide = _activeSlide!=slideNum;
|
|
if (newSlide)
|
|
{
|
|
if (_releaseAndCompileOnEachNewSlide)
|
|
{
|
|
releaseSlide(_activeSlide);
|
|
}
|
|
}
|
|
|
|
_activeSlide = slideNum;
|
|
_presentationSwitch->setSingleChildOn(_activeSlide);
|
|
|
|
//OSG_INFO<<"Selected slide '"<<_presentationSwitch->getChild(_activeSlide)->getName()<<"'"<<std::endl;
|
|
|
|
|
|
FindNamedSwitchVisitor findSlide("Slide");
|
|
_presentationSwitch->getChild(_activeSlide)->accept(findSlide);
|
|
|
|
bool result = false;
|
|
if (findSlide._switch)
|
|
{
|
|
//OSG_INFO<<"Found slide '"<<findSlide._switch->getName()<<"'"<<std::endl;
|
|
_slideSwitch = findSlide._switch;
|
|
|
|
result = selectLayer(layerNum);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
//OSG_INFO<<"Not found slide"<<std::endl;
|
|
updateOperators();
|
|
}
|
|
|
|
|
|
// refersh the viewer.
|
|
//_viewer->getKeySwitchMatrixManipulator()->setMinimumDistance(0.001);
|
|
|
|
if (_viewer->getCameraManipulator())
|
|
{
|
|
_viewer->getCameraManipulator()->setNode(_slideSwitch.get());
|
|
|
|
_viewer->computeActiveCoordinateSystemNodePath();
|
|
}
|
|
|
|
// resetUpdateCallbacks(ALL_OBJECTS);
|
|
|
|
bool _useSlideFilePaths = false;
|
|
if (_useSlideFilePaths)
|
|
{
|
|
// set up the file paths
|
|
FindFilePathDataVisitor ffpdv;
|
|
_presentationSwitch->accept(ffpdv);
|
|
}
|
|
|
|
if (newSlide && _releaseAndCompileOnEachNewSlide)
|
|
{
|
|
compileSlide(slideNum);
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
bool SlideEventHandler::selectLayer(int layerNum)
|
|
{
|
|
if (!_slideSwitch) return false;
|
|
|
|
bool withinSlide = true;
|
|
|
|
if (layerNum>=static_cast<int>(_slideSwitch->getNumChildren()))
|
|
{
|
|
withinSlide = false;
|
|
layerNum = LAST_POSITION;
|
|
}
|
|
|
|
if (layerNum==LAST_POSITION && _slideSwitch->getNumChildren()>0)
|
|
{
|
|
layerNum = _slideSwitch->getNumChildren()-1;
|
|
}
|
|
|
|
if (layerNum>=static_cast<int>(_slideSwitch->getNumChildren())) return false;
|
|
|
|
_activeLayer = layerNum;
|
|
_slideSwitch->setSingleChildOn(_activeLayer);
|
|
|
|
updateOperators();
|
|
|
|
OSG_INFO<<"Selected layer '"<<_slideSwitch->getChild(_activeLayer)->getName()<<"' num="<<_activeLayer<< std::endl;
|
|
|
|
return withinSlide;
|
|
}
|
|
|
|
bool SlideEventHandler::nextLayerOrSlide()
|
|
{
|
|
if (nextLayer())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return nextSlide();
|
|
}
|
|
}
|
|
|
|
bool SlideEventHandler::previousLayerOrSlide()
|
|
{
|
|
OSG_INFO<<"previousLayerOrSlide()"<<std::endl;
|
|
if (previousLayer()) return true;
|
|
else return previousSlide();
|
|
}
|
|
|
|
bool SlideEventHandler::nextSlide()
|
|
{
|
|
OSG_INFO<<"nextSlide()"<<std::endl;
|
|
LayerAttributes* la = _slideSwitch.valid() ? dynamic_cast<LayerAttributes*>(_slideSwitch->getUserData()) : 0;
|
|
if (la && la->getJumpData().requiresJump())
|
|
{
|
|
return la->getJumpData().jump(this);
|
|
}
|
|
|
|
if (selectSlide(_activeSlide+1)) return true;
|
|
else if (_loopPresentation) return selectSlide(0);
|
|
else return false;
|
|
}
|
|
|
|
bool SlideEventHandler::previousSlide()
|
|
{
|
|
OSG_INFO<<"previousSlide()"<<std::endl;
|
|
#if 1
|
|
// start position when doing previous slide set to top of slide
|
|
if (_activeSlide>0) return selectSlide(_activeSlide-1);
|
|
else if (_loopPresentation && _presentationSwitch.valid()) return selectSlide(_presentationSwitch->getNumChildren()-1);
|
|
else return false;
|
|
#else
|
|
// start position when doing previous slide set to end of slide
|
|
if (_activeSlide>0) return selectSlide(_activeSlide-1,LAST_POSITION);
|
|
else if (_loopPresentation && _presentationSwitch.valid()) return selectSlide(_presentationSwitch->getNumChildren()-1,LAST_POSITION);
|
|
else return false;
|
|
#endif
|
|
}
|
|
|
|
bool SlideEventHandler::nextLayer()
|
|
{
|
|
LayerAttributes* la = (_slideSwitch.valid() && _activeLayer<static_cast<int>(_slideSwitch->getNumChildren())) ? dynamic_cast<LayerAttributes*>(_slideSwitch->getChild(_activeLayer)->getUserData()) : 0;
|
|
if (la)
|
|
{
|
|
la->callLeaveCallbacks(_slideSwitch->getChild(_activeLayer));
|
|
|
|
if (la->getJumpData().requiresJump())
|
|
{
|
|
return la->getJumpData().jump(this);
|
|
}
|
|
}
|
|
|
|
OSG_INFO<<"nextLayer() calling selectLayer("<<_activeLayer+1<<")"<<std::endl;
|
|
return selectLayer(_activeLayer+1);
|
|
}
|
|
|
|
bool SlideEventHandler::previousLayer()
|
|
{
|
|
OSG_INFO<<"previousLayer()"<<std::endl;
|
|
if (_activeLayer>0) return selectLayer(_activeLayer-1);
|
|
else return false;
|
|
}
|
|
|
|
|
|
void SlideEventHandler::updateOperators()
|
|
{
|
|
_activeOperators.collect(_slideSwitch.get());
|
|
_activeOperators.process(this);
|
|
|
|
if (_viewer.valid())
|
|
{
|
|
updateLight(0.0f,0.0f);
|
|
}
|
|
}
|
|
|
|
bool SlideEventHandler::home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
|
|
{
|
|
FindHomePositionVisitor fhpv;
|
|
osg::Node* node = _viewer->getSceneData();
|
|
if (node) node->accept(fhpv);
|
|
|
|
if (_viewer->getCameraManipulator())
|
|
{
|
|
if (fhpv._homePosition.valid())
|
|
{
|
|
OSG_INFO<<"Doing home for stored home position."<<std::endl;
|
|
|
|
_viewer->getCameraManipulator()->setAutoComputeHomePosition(false);
|
|
_viewer->getCameraManipulator()->setHomePosition(
|
|
fhpv._homePosition->eye,
|
|
fhpv._homePosition->center,
|
|
fhpv._homePosition->up);
|
|
}
|
|
else
|
|
{
|
|
_viewer->getCameraManipulator()->setAutoComputeHomePosition(true);
|
|
}
|
|
_viewer->getCameraManipulator()->home(ea,aa);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SlideEventHandler::home()
|
|
{
|
|
osg::ref_ptr<osgGA::GUIEventAdapter> ea = new osgGA::GUIEventAdapter;
|
|
ea->setEventType(osgGA::GUIEventAdapter::FRAME);
|
|
ea->setTime(_viewer->getEventQueue()->getTime());
|
|
|
|
home(*ea,*_viewer);
|
|
return true;
|
|
}
|
|
|
|
void SlideEventHandler::updateAlpha(bool modAlphaFunc, bool modMaterial, float x, float y)
|
|
{
|
|
OSG_INFO<<"updateAlpha("<<x<<","<<y<<")"<<std::endl;
|
|
|
|
UpdateAlphaVisitor uav(modAlphaFunc, modMaterial, x,y);
|
|
if (_presentationSwitch.valid()) _presentationSwitch->accept(uav);
|
|
else if (_viewer->getSceneData()) _viewer->getSceneData()->accept(uav);
|
|
}
|
|
|
|
|
|
void SlideEventHandler::updateLight(float x, float y)
|
|
{
|
|
OSG_INFO<<"updateLight("<<x<<", "<<y<<")"<<std::endl;
|
|
|
|
UpdateLightVisitor uav(_viewer->getCamera()->getViewMatrix(),x,y);
|
|
_viewer->getSceneData()->accept(uav);
|
|
|
|
if (_viewer->getLightingMode()!= osg::View::NO_LIGHT && _viewer->getLight())
|
|
{
|
|
if (_viewer->getLightingMode()== osg::View::SKY_LIGHT)
|
|
{
|
|
uav.apply(_viewer->getCamera()->getViewMatrix(), _viewer->getLight());
|
|
}
|
|
else if (_viewer->getLightingMode()== osg::View::HEADLIGHT)
|
|
{
|
|
uav.apply(osg::Matrix::identity(), _viewer->getLight());
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void SlideEventHandler::compileSlide(unsigned int slideNum)
|
|
{
|
|
if (!_compileSlideCallback)
|
|
{
|
|
_compileSlideCallback = new CompileSlideCallback();
|
|
|
|
osgViewer::Viewer::Cameras cameras;
|
|
_viewer->getCameras(cameras);
|
|
|
|
for(osgViewer::Viewer::Cameras::iterator itr = cameras.begin();
|
|
itr != cameras.end();
|
|
++itr)
|
|
{
|
|
(*itr)->setPreDrawCallback(_compileSlideCallback.get());
|
|
}
|
|
|
|
}
|
|
|
|
_compileSlideCallback->needCompile(_presentationSwitch->getChild(slideNum));
|
|
|
|
}
|
|
|
|
void SlideEventHandler::releaseSlide(unsigned int slideNum)
|
|
{
|
|
osgUtil::GLObjectsVisitor globjVisitor(osgUtil::GLObjectsVisitor::RELEASE_DISPLAY_LISTS|
|
|
osgUtil::GLObjectsVisitor::RELEASE_STATE_ATTRIBUTES);
|
|
globjVisitor.setNodeMaskOverride(0xffffffff);
|
|
|
|
_presentationSwitch->getChild(slideNum)->accept(globjVisitor);
|
|
}
|
|
|
|
void SlideEventHandler::forwardEventToDevices(osgGA::Event* event)
|
|
{
|
|
if (!event) return;
|
|
|
|
// dispatch cloned event to devices
|
|
if (!_viewer)
|
|
{
|
|
OSG_NOTICE<<"Warning: SlideEventHandler::forwardEventToDevices(Event*) error, no Viewer to dispatch to."<<std::endl;
|
|
return;
|
|
}
|
|
|
|
osgViewer::View::Devices& devices = _viewer->getDevices();
|
|
for(osgViewer::View::Devices::iterator i = devices.begin(); i != devices.end(); ++i)
|
|
{
|
|
if((*i)->getCapabilities() & osgGA::Device::SEND_EVENTS)
|
|
{
|
|
(*i)->sendEvent(*event);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SlideEventHandler::dispatchEvent(osgGA::Event* event)
|
|
{
|
|
if (!event) return;
|
|
|
|
// dispatch cloned event to devices
|
|
if (!_viewer)
|
|
{
|
|
OSG_NOTICE<<"Warning: SlideEventHandler::forwardEventToDevices(Event*) error, no Viewer to dispatch to."<<std::endl;
|
|
return;
|
|
}
|
|
|
|
osgGA::EventQueue* eq = _viewer!=0 ? _viewer->getEventQueue() : 0;
|
|
if (!eq)
|
|
{
|
|
OSG_NOTICE<<"Warning: SlideEventHandler::dispatchEvent(KeyPosition&) error, no EventQueue to dispatch to."<<std::endl;
|
|
return;
|
|
}
|
|
|
|
eq->addEvent(event);
|
|
}
|
|
|
|
void SlideEventHandler::dispatchEvent(const KeyPosition& keyPosition)
|
|
{
|
|
if (!_viewer)
|
|
{
|
|
OSG_NOTICE<<"Warning: SlideEventHandler::dispatchEvent(KeyPosition*) error, no Viewer to dispatch to."<<std::endl;
|
|
return;
|
|
}
|
|
|
|
if (keyPosition._forwardToDevices)
|
|
{
|
|
osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter();
|
|
event->setKey(keyPosition._key);
|
|
event->setTime(_viewer->getEventQueue()->getTime());
|
|
|
|
// forward key-down
|
|
event->setEventType(osgGA::GUIEventAdapter::KEYDOWN);
|
|
forwardEventToDevices(event.get());
|
|
|
|
// forward key-up
|
|
event->setEventType(osgGA::GUIEventAdapter::KEYUP);
|
|
forwardEventToDevices(event.get());
|
|
|
|
// ignore local event-queue
|
|
return;
|
|
}
|
|
|
|
osgGA::EventQueue* eq = _viewer!=0 ? _viewer->getEventQueue() : 0;
|
|
if (!eq)
|
|
{
|
|
OSG_NOTICE<<"Warning: SlideEventHandler::dispatchEvent(KeyPosition&) error, no EventQueue to dispatch to."<<std::endl;
|
|
return;
|
|
}
|
|
|
|
// reset the time of the last key press to ensure that the event is disgarded as a key repeat.
|
|
_timeLastKeyPresses = -1.0;
|
|
|
|
if (keyPosition._x!=FLT_MAX)
|
|
{
|
|
float xRescaled = eq->getCurrentEventState()->getXmin() + (keyPosition._x+1.0f)*0.5f*(eq->getCurrentEventState()->getXmax()-eq->getCurrentEventState()->getXmin());
|
|
eq->getCurrentEventState()->setX(xRescaled);
|
|
}
|
|
|
|
if (keyPosition._y!=FLT_MAX)
|
|
{
|
|
float y = (eq->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS) ?
|
|
keyPosition._y : -keyPosition._y;
|
|
|
|
float yRescaled = eq->getCurrentEventState()->getYmin() + (y+1.0f)*0.5f*(eq->getCurrentEventState()->getYmax()-eq->getCurrentEventState()->getYmin());
|
|
eq->getCurrentEventState()->setY(yRescaled);
|
|
}
|
|
|
|
eq->keyPress(keyPosition._key);
|
|
eq->keyRelease(keyPosition._key);
|
|
}
|
|
|
|
|
|
void SlideEventHandler::setRequestReload(bool flag)
|
|
{
|
|
_requestReload = flag;
|
|
}
|
|
|
|
bool SlideEventHandler::checkNeedToDoFrame()
|
|
{
|
|
if (_viewer.valid())
|
|
{
|
|
if (_viewer->getRequestRedraw()) return true;
|
|
if (_viewer->getRequestContinousUpdate()) return true;
|
|
|
|
// If the database pager is going to update the scene the render flag is
|
|
// set so that the updates show up
|
|
if(_viewer->getDatabasePager()->requiresUpdateSceneGraph() || _viewer->getDatabasePager()->getRequestsInProgress()) return true;
|
|
|
|
// if there update callbacks then we need to do frame.
|
|
if (_viewer->getCamera()->getUpdateCallback()) return true;
|
|
|
|
if (!_pause)
|
|
{
|
|
if (_slideSwitch.valid() && _activeLayer<static_cast<int>(_slideSwitch->getNumChildren()))
|
|
{
|
|
if (_slideSwitch->getChild(_activeLayer)->getNumChildrenRequiringUpdateTraversal()>0) return true;
|
|
}
|
|
else if (_viewer->getSceneData()!=0 && _viewer->getSceneData()->getNumChildrenRequiringUpdateTraversal()>0) return true;
|
|
|
|
if (_autoSteppingActive)
|
|
{
|
|
if (_firstTraversal) return true;
|
|
else
|
|
{
|
|
osg::Timer_t tick = osg::Timer::instance()->tick();
|
|
double currentTime = osg::Timer::instance()->delta_s(_viewer->getStartTick(), tick);
|
|
if ((currentTime-_previousTime)>=getCurrentTimeDelayBetweenSlides()) return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if events are available and need processing
|
|
if (_viewer->checkEvents()) return true;
|
|
|
|
// now check if any of the event handles have prompted a redraw.
|
|
if (_viewer->getRequestRedraw()) return true;
|
|
if (_viewer->getRequestContinousUpdate()) return true;
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|