1 /* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
2  *
3  * This software is open source and may be redistributed and/or modified under
4  * the terms of the GNU General Public License (GPL) version 2.0.
5  * The full license is in LICENSE.txt file included with this distribution,.
6  *
7  * This software is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * include LICENSE.txt for more details.
11 */
12 
13 #include <osgPresentation/SlideEventHandler>
14 #include <osgPresentation/SlideShowConstructor>
15 #include <osgPresentation/AnimationMaterial>
16 
17 #include <osg/AnimationPath>
18 #include <osg/Transform>
19 #include <osg/TexEnvCombine>
20 #include <osg/LightSource>
21 #include <osg/AlphaFunc>
22 #include <osg/io_utils>
23 
24 #include <osgUtil/TransformCallback>
25 #include <osgUtil/GLObjectsVisitor>
26 
27 #include <osgDB/WriteFile>
28 
29 #include <osgGA/AnimationPathManipulator>
30 
31 
32 #include <iostream>
33 
34 using namespace osgPresentation;
35 
36 static osg::observer_ptr<SlideEventHandler> s_seh;
37 
instance()38 SlideEventHandler* SlideEventHandler::instance() { return s_seh.get(); }
39 
jump(SlideEventHandler * seh) const40 bool JumpData::jump(SlideEventHandler* seh) const
41 {
42         OSG_NOTICE<<"Requires jump"<<seh<<", "<<relativeJump<<", "<<slideNum<<", "<<layerNum<<", "<<slideName<<", "<<layerName<<std::endl;
43 
44         int slideNumToUse = slideNum;
45         int layerNumToUse = layerNum;
46 
47         if (!slideName.empty())
48         {
49             osg::Switch* presentation = seh->getPresentationSwitch();
50             if (presentation)
51             {
52                 for(unsigned int i=0; i<presentation->getNumChildren(); ++i)
53                 {
54                     osg::Node* node = seh->getSlide(i);
55                     std::string name;
56                     if (node->getUserValue("name",name) && slideName==name)
57                     {
58                         slideNumToUse = i;
59                         break;
60                     }
61                 }
62             }
63         }
64         else if (relativeJump)
65         {
66             slideNumToUse = seh->getActiveSlide() + slideNum;
67         }
68 
69 
70         if (!layerName.empty())
71         {
72             osg::Switch* slide = seh->getSlide(slideNumToUse);
73             if (slide)
74             {
75                 unsigned int i;
76                 for(i=0; i<slide->getNumChildren(); ++i)
77                 {
78                     osg::Node* node = slide->getChild(i);
79                     std::string name;
80                     if (node->getUserValue("name",name))
81                     {
82                         if (layerName==name)
83                         {
84                             layerNumToUse = i;
85                             break;
86                         }
87                     }
88                 }
89                 if (i==slide->getNumChildren())
90                 {
91                     OSG_INFO<<"Could not find layer with "<<layerName<<std::endl;
92                 }
93             }
94             else
95             {
96                 OSG_INFO<<"No appropriate Slide found."<<std::endl;
97             }
98         }
99         else if (relativeJump)
100         {
101             layerNumToUse = seh->getActiveLayer() + layerNum;
102         }
103 
104         if (slideNumToUse<0) slideNumToUse = 0;
105         if (layerNumToUse<0) layerNumToUse = 0;
106 
107         OSG_INFO<<"   jump to "<<slideNumToUse<<", "<<layerNumToUse<<std::endl;
108         return seh->selectSlide(slideNumToUse,layerNumToUse);
109 }
110 
callEnterCallbacks(osg::Node * node)111 void LayerAttributes::callEnterCallbacks(osg::Node* node)
112 {
113     OSG_INFO<<"LayerAttributes::callEnterCallbacks("<<node<<")"<<std::endl;
114     for(LayerCallbacks::iterator itr = _enterLayerCallbacks.begin();
115         itr != _enterLayerCallbacks.end();
116         ++itr)
117     {
118         (*(*itr))(node);
119     }
120 }
121 
callLeaveCallbacks(osg::Node * node)122 void LayerAttributes::callLeaveCallbacks(osg::Node* node)
123 {
124     OSG_INFO<<"LayerAttributes::callLeaveCallbacks("<<node<<")"<<std::endl;
125     for(LayerCallbacks::iterator itr = _leaveLayerCallbacks.begin();
126         itr != _leaveLayerCallbacks.end();
127         ++itr)
128     {
129         (*(*itr))(node);
130     }
131 }
132 
133 
134 struct InteractiveImageSequenceOperator : public ObjectOperator
135 {
InteractiveImageSequenceOperatorInteractiveImageSequenceOperator136     InteractiveImageSequenceOperator(osg::ImageSequence* imageSequence):
137         _imageSequence(imageSequence) {}
138 
ptrInteractiveImageSequenceOperator139     virtual void* ptr() const { return _imageSequence.get(); }
140 
enterInteractiveImageSequenceOperator141     virtual void enter(SlideEventHandler* seh)
142     {
143         set(seh);
144         // need to pause till the load has been completed.
145     }
146 
maintainInteractiveImageSequenceOperator147     virtual void maintain(SlideEventHandler* /*seh*/)
148     {
149     }
150 
leaveInteractiveImageSequenceOperator151     virtual void leave(SlideEventHandler* /*seh*/)
152     {
153     }
154 
setPauseInteractiveImageSequenceOperator155     virtual void setPause(SlideEventHandler* /*seh*/, bool /*pause*/)
156     {
157     }
158 
resetInteractiveImageSequenceOperator159     virtual void reset(SlideEventHandler* seh)
160     {
161         set(seh);
162     }
163 
setInteractiveImageSequenceOperator164     void set(SlideEventHandler* /*seh*/)
165     {
166         //OSG_NOTICE<<"InteractiveImageSequenceOperator::set(..)"<<std::endl;
167     }
168 
169     osg::ref_ptr<osg::ImageSequence>  _imageSequence;
170 };
171 
172 struct ImageStreamOperator : public ObjectOperator
173 {
ImageStreamOperatorImageStreamOperator174     ImageStreamOperator(osg::ImageStream* imageStream):
175         _imageStream(imageStream),
176         _delayTime(0.0),
177         _startTime(0.0),
178         _stopTime(-1.0),
179         _timeOfLastReset(0.0),
180         _started(false),
181         _stopped(false)
182     {
183         _imageStream->getUserValue("delay",_delayTime);
184         _imageStream->getUserValue("start",_startTime);
185         _imageStream->getUserValue("stop",_stopTime);
186     }
187 
ptrImageStreamOperator188     virtual void* ptr() const { return _imageStream.get(); }
189 
190 
enterImageStreamOperator191     virtual void enter(SlideEventHandler* seh)
192     {
193         OSG_NOTICE<<"enter() : _imageStream->rewind() + play"<<std::endl;
194 
195         reset(seh);
196     }
197 
frameImageStreamOperator198     virtual void frame(SlideEventHandler* seh)
199     {
200         if (_delayTime!=0.0 && !_started && !_stopped)
201         {
202             double timeSinceLastRest = seh->getReferenceTime()-_timeOfLastReset;
203             if (timeSinceLastRest>_delayTime)
204             {
205                 OSG_NOTICE<<"ImageStreamOperator::frame("<<seh->getReferenceTime()<<") calling start"<<std::endl;
206                 start(seh);
207             }
208         }
209         if (_stopTime>0.0 && _started && !_stopped)
210         {
211             double timeSinceLastReset = seh->getReferenceTime()-_timeOfLastReset;
212             double timeSinceStart = (timeSinceLastReset-_delayTime);
213             if ((timeSinceStart+_startTime)>_stopTime)
214             {
215                 OSG_NOTICE<<"ImageStreamOperator::frame("<<seh->getReferenceTime()<<") calling stop"<<std::endl;
216                 stop(seh);
217             }
218         }
219     }
220 
maintainImageStreamOperator221     virtual void maintain(SlideEventHandler*)
222     {
223         OSG_NOTICE<<"ImageStreamOperator::maintain()"<<std::endl;
224     }
225 
leaveImageStreamOperator226     virtual void leave(SlideEventHandler*)
227     {
228        OSG_NOTICE<<"leave() : _imageStream->pause()"<<std::endl;
229 
230         _imageStream->pause();
231     }
232 
setPauseImageStreamOperator233     virtual void setPause(SlideEventHandler*, bool pause)
234     {
235        OSG_INFO<<"_imageStream->setPause("<<pause<<")"<<std::endl;
236 
237         if (_started)
238         {
239             if (pause) _imageStream->pause();
240             else _imageStream->play();
241         }
242     }
243 
resetImageStreamOperator244     virtual void reset(SlideEventHandler* seh)
245     {
246         OSG_NOTICE<<"ImageStreamOperator::reset()"<<std::endl;
247 
248         _timeOfLastReset = seh->getReferenceTime();
249         _stopped = false;
250 
251         if (_delayTime==0.0)
252         {
253             start(seh);
254         }
255     }
256 
startImageStreamOperator257     void start(SlideEventHandler*)
258     {
259         if (_started) return;
260 
261         _started = true;
262         _stopped = false;
263 
264         if (_startTime!=0.0) _imageStream->seek(_startTime);
265         else _imageStream->rewind();
266 
267         //_imageStream->setVolume(previousVolume);
268 
269         _imageStream->play();
270 
271         // add a delay so that movie thread has a chance to do the rewind
272         float microSecondsToDelay = SlideEventHandler::instance()->getTimeDelayOnNewSlideWithMovies() * 1000000.0f;
273         OpenThreads::Thread::microSleep(static_cast<unsigned int>(microSecondsToDelay));
274     }
275 
stopImageStreamOperator276     void stop(SlideEventHandler* /*seh*/)
277     {
278         if (!_started) return;
279 
280         _started = false;
281         _stopped = true;
282 
283         _imageStream->pause();
284     }
285 
286     osg::ref_ptr<osg::ImageStream>  _imageStream;
287     double      _delayTime;
288     double      _startTime;
289     double      _stopTime;
290     double      _timeOfLastReset;
291     bool        _started;
292     bool        _stopped;
293 };
294 
295 struct CallbackOperator : public ObjectOperator
296 {
CallbackOperatorCallbackOperator297     CallbackOperator(osg::Node* node, osg::Referenced* callback):
298         _node(node),
299         _callback(callback) {}
300 
ptrCallbackOperator301     virtual void* ptr() const { return _callback.get(); }
302 
enterCallbackOperator303     virtual void enter(SlideEventHandler* seh)
304     {
305         reset(seh);
306     }
307 
maintainCallbackOperator308     virtual void maintain(SlideEventHandler*)
309     {
310     }
311 
leaveCallbackOperator312     virtual void leave(SlideEventHandler*)
313     {
314     }
315 
setPauseCallbackOperator316     virtual void setPause(SlideEventHandler*, bool pause)
317     {
318         osg::NodeCallback* nc = dynamic_cast<osg::NodeCallback*>(_callback.get());
319         osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
320         osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
321         AnimationMaterialCallback* amc = dynamic_cast<AnimationMaterialCallback*>(_callback.get());
322         PropertyAnimation* pa = dynamic_cast<PropertyAnimation*>(_callback.get());
323         if (apc)
324         {
325             OSG_INFO<<"apc->setPause("<<pause<<")"<<std::endl;
326             apc->setPause(pause);
327         }
328         else if (tc)
329         {
330             OSG_INFO<<"tc->setPause("<<pause<<")"<<std::endl;
331             tc->setPause(pause);
332         }
333         else if (amc)
334         {
335             OSG_INFO<<"amc->setPause("<<pause<<")"<<std::endl;
336             amc->setPause(pause);
337         }
338         else if (pa)
339         {
340             pa->setPause(pause);
341         }
342         else if (nc)
343         {
344             OSG_INFO<<"Need to pause callback : "<<nc->className()<<std::endl;
345         }
346 
347     }
348 
resetCallbackOperator349     virtual void reset(SlideEventHandler*)
350     {
351         osg::NodeCallback* nc = dynamic_cast<osg::NodeCallback*>(_callback.get());
352         osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
353         osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
354         AnimationMaterialCallback* amc = dynamic_cast<AnimationMaterialCallback*>(_callback.get());
355         PropertyAnimation* pa = dynamic_cast<PropertyAnimation*>(_callback.get());
356         if (apc)
357         {
358             apc->reset();
359             apc->update(*_node);
360         }
361         else if (tc)
362         {
363         }
364         else if (amc)
365         {
366             amc->reset();
367             amc->update(*_node);
368         }
369         else if (pa)
370         {
371             pa->reset();
372             pa->update(*_node);
373         }
374         else
375         {
376             OSG_INFO<<"Need to reset callback : "<<nc->className()<<std::endl;
377         }
378     }
379 
380 
381     osg::ref_ptr<osg::Node>         _node;
382     osg::ref_ptr<osg::Referenced>   _callback;
383 };
384 
385 struct LayerAttributesOperator : public ObjectOperator
386 {
LayerAttributesOperatorLayerAttributesOperator387     LayerAttributesOperator(osg::Node* node, LayerAttributes* la):
388         _node(node),
389         _layerAttribute(la)
390     {
391     }
392 
ptrLayerAttributesOperator393     virtual void* ptr() const { return _layerAttribute.get(); }
394 
enterLayerAttributesOperator395     virtual void enter(SlideEventHandler*)
396     {
397         _layerAttribute->callEnterCallbacks(_node.get());
398 
399         if (!_layerAttribute->_keys.empty())
400         {
401             OSG_INFO<<"applyKeys {"<<std::endl;
402 
403             for(LayerAttributes::Keys::iterator itr = _layerAttribute->_keys.begin();
404                 itr != _layerAttribute->_keys.end();
405                 ++itr)
406             {
407                 SlideEventHandler::instance()->dispatchEvent(*itr);
408             }
409 
410             OSG_INFO<<"}"<<std::endl;
411         }
412         if (!_layerAttribute->_runStrings.empty())
413         {
414             for(LayerAttributes::RunStrings::iterator itr = _layerAttribute->_runStrings.begin();
415                 itr != _layerAttribute->_runStrings.end();
416                 ++itr)
417             {
418 
419                 OSG_NOTICE<<"Run "<<itr->c_str()<<std::endl;
420                 osg::Timer_t startTick = osg::Timer::instance()->tick();
421 
422                 int result = system(itr->c_str());
423 
424                 OSG_INFO<<"system("<<*itr<<") result "<<result<<std::endl;
425 
426                 double timeForRun = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
427 
428                 osgGA::EventQueue* eq = SlideEventHandler::instance()->getViewer()->getEventQueue();
429                 if (eq)
430                 {
431                     osg::Timer_t new_startTick = eq->getStartTick() + osg::Timer_t(timeForRun / osg::Timer::instance()->getSecondsPerTick());
432                     eq->setStartTick(new_startTick);
433                 }
434             }
435         }
436 
437     }
438 
maintainLayerAttributesOperator439     virtual void maintain(SlideEventHandler*)
440     {
441     }
442 
leaveLayerAttributesOperator443     virtual void leave(SlideEventHandler*)
444     {
445         OSG_INFO<<"LayerAttribute leave"<<std::endl;
446 
447          _layerAttribute->callLeaveCallbacks(_node.get());
448     }
449 
setPauseLayerAttributesOperator450     virtual void setPause(SlideEventHandler*, bool /*pause*/)
451     {
452     }
453 
resetLayerAttributesOperator454     virtual void reset(SlideEventHandler*)
455     {
456     }
457 
458 
459     osg::ref_ptr<osg::Node>                             _node;
460     osg::ref_ptr<LayerAttributes> _layerAttribute;
461 };
462 
463 
464 class FindOperatorsVisitor : public osg::NodeVisitor
465 {
466 public:
FindOperatorsVisitor(ActiveOperators::OperatorList & operatorList,osg::NodeVisitor::TraversalMode tm)467     FindOperatorsVisitor(ActiveOperators::OperatorList& operatorList, osg::NodeVisitor::TraversalMode tm):
468         osg::NodeVisitor(tm),
469         _operatorList(operatorList) {}
470 
META_NodeVisitor(osgPresentation,FindOperatorsVisitor)471     META_NodeVisitor(osgPresentation, FindOperatorsVisitor)
472 
473     void apply(osg::Node& node)
474     {
475         if (node.getStateSet()) process(node.getStateSet());
476 
477         if (node.getUpdateCallback())
478         {
479             _operatorList.insert(new CallbackOperator(&node, node.getUpdateCallback()));
480         }
481 
482         LayerAttributes* la = dynamic_cast<LayerAttributes*>(node.getUserData());
483         if (la)
484         {
485             if ((_objectsHandled[la]++)==0)
486             {
487                 OSG_INFO<<"LayerAttributeOperator for "<<la<<" required, assigning one."<<std::endl;
488                 _operatorList.insert(new LayerAttributesOperator(&node, la));
489             }
490             else
491             {
492                 OSG_INFO<<"LayerAttributeOperator for "<<la<<" not required, as one already assigned."<<std::endl;
493             }
494         }
495 
496         traverse(node);
497     }
498 
apply(osg::Geode & node)499     void apply(osg::Geode& node)
500     {
501         apply((osg::Node&)node);
502         for(unsigned int i=0;i<node.getNumDrawables();++i)
503         {
504             osg::Drawable* drawable = node.getDrawable(i);
505             if (drawable->getStateSet()) process(drawable->getStateSet());
506         }
507     }
508 
process(osg::StateSet * ss)509     virtual void process(osg::StateSet* ss)
510     {
511         for(unsigned int i=0;i<ss->getTextureAttributeList().size();++i)
512         {
513             osg::Texture* texture = dynamic_cast<osg::Texture*>(ss->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
514             osg::Image* image = texture ? texture->getImage(0) : 0;
515             osg::ImageSequence* imageSequence = dynamic_cast<osg::ImageSequence*>(image);
516             osg::ImageStream* imageStream = dynamic_cast<osg::ImageStream*>(image);
517             if (imageSequence && imageSequence->getName()=="USE_MOUSE_X_POSITION")
518             {
519                 if ((_objectsHandled[image]++)==0)
520                 {
521                     OSG_INFO<<"ImageSequenceOperator for"<<imageSequence<<" required, assigning one, name = '"<<image->getName()<<"'"<<std::endl;
522                     _operatorList.insert(new InteractiveImageSequenceOperator(imageSequence));
523                 }
524                 else
525                 {
526                     OSG_INFO<<"ImageSequenceOperator for"<<imageSequence<<" not required, as one already assigned"<<std::endl;
527                 }
528             }
529             else if (imageStream)
530             {
531                 if ((_objectsHandled[image]++)==0)
532                 {
533                     OSG_INFO<<"ImageStreamOperator for"<<imageStream<<" required, assigning one"<<std::endl;
534                     _operatorList.insert(new ImageStreamOperator(imageStream));
535                 }
536                 else
537                 {
538                     OSG_INFO<<"ImageStreamOperator for"<<imageStream<<" not required, as one already assigned"<<std::endl;
539                 }
540             }
541         }
542     }
543 
544     typedef std::map<osg::Referenced*,unsigned int> ObjectsHandled;
545     ObjectsHandled _objectsHandled;
546 
547     ActiveOperators::OperatorList& _operatorList;
548 };
549 
550 
ActiveOperators()551 ActiveOperators::ActiveOperators():
552     _pause(false)
553 {
554 }
555 
~ActiveOperators()556 ActiveOperators::~ActiveOperators()
557 {
558 }
559 
collect(osg::Node * incomingNode,osg::NodeVisitor::TraversalMode tm)560 void ActiveOperators::collect(osg::Node* incomingNode, osg::NodeVisitor::TraversalMode tm)
561 {
562     _previous.swap(_current);
563 
564     _current.clear();
565 
566     FindOperatorsVisitor fov(_current, tm);
567 
568     if (incomingNode)
569     {
570         incomingNode->accept(fov);
571     }
572     else
573     {
574         OSG_NOTICE<<"ActiveOperators::collect() incomingNode="<<incomingNode<<std::endl;
575     }
576 
577     OSG_INFO<<"ActiveOperators::collect("<<incomingNode<<")"<<std::endl;
578     OSG_INFO<<"  _previous.size()="<<_previous.size()<<std::endl;
579     OSG_INFO<<"  _current.size()="<<_current.size()<<std::endl;
580 
581     _outgoing.clear();
582     _incoming.clear();
583     _maintained.clear();
584 
585     for(OperatorList::iterator itr = _previous.begin();
586         itr != _previous.end();
587         ++itr)
588     {
589         ObjectOperator* prev = itr->get();
590         if (_current.count(prev)==0) _outgoing.insert(prev);
591         else _maintained.insert(prev);
592     }
593 
594     for(OperatorList::iterator itr = _current.begin();
595         itr != _current.end();
596         ++itr)
597     {
598         ObjectOperator* curr = itr->get();
599         if (_previous.count(curr)==0) _incoming.insert(curr);
600     }
601 }
602 
frame(SlideEventHandler * seh)603 void ActiveOperators::frame(SlideEventHandler* seh)
604 {
605     for(OperatorList::iterator itr = _current.begin();
606         itr != _current.end();
607         ++itr)
608     {
609         (*itr)->frame(seh);
610     }
611 }
612 
setPause(SlideEventHandler * seh,bool pause)613 void ActiveOperators::setPause(SlideEventHandler* seh, bool pause)
614 {
615     _pause = pause;
616     for(OperatorList::iterator itr = _current.begin();
617         itr != _current.end();
618         ++itr)
619     {
620         (*itr)->setPause(seh, _pause);
621     }
622 }
623 
624 
reset(SlideEventHandler * seh)625 void ActiveOperators::reset(SlideEventHandler* seh)
626 {
627     for(OperatorList::iterator itr = _current.begin();
628         itr != _current.end();
629         ++itr)
630     {
631         (*itr)->reset(seh);
632     }
633 }
634 
process(SlideEventHandler * seh)635 void ActiveOperators::process(SlideEventHandler* seh)
636 {
637     processOutgoing(seh);
638     processMaintained(seh);
639     processIncoming(seh);
640 }
641 
processOutgoing(SlideEventHandler * seh)642 void ActiveOperators::processOutgoing(SlideEventHandler* seh)
643 {
644     OSG_INFO<<"  outgoing.size()="<<_outgoing.size()<<std::endl;
645     for(OperatorList::iterator itr = _outgoing.begin();
646         itr != _outgoing.end();
647         ++itr)
648     {
649         (*itr)->leave(seh);
650     }
651 }
652 
processMaintained(SlideEventHandler * seh)653 void ActiveOperators::processMaintained(SlideEventHandler* seh)
654 {
655     OSG_INFO<<"  maintained.size()="<<_maintained.size()<<std::endl;
656     for(OperatorList::iterator itr = _maintained.begin();
657         itr != _maintained.end();
658         ++itr)
659     {
660         (*itr)->maintain(seh);
661     }
662 }
663 
processIncoming(SlideEventHandler * seh)664 void ActiveOperators::processIncoming(SlideEventHandler* seh)
665 {
666     OSG_INFO<<"  incoming.size()="<<_incoming.size()<<std::endl;
667     for(OperatorList::iterator itr = _incoming.begin();
668         itr != _incoming.end();
669         ++itr)
670     {
671         (*itr)->enter(seh);
672         (*itr)->setPause(seh, _pause);
673     }
674 }
675 
676 
677 
678 
679 class FindHomePositionVisitor : public osg::NodeVisitor
680 {
681 public:
682 
FindHomePositionVisitor()683     FindHomePositionVisitor():
684         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
685 
apply(osg::Node & node)686     void apply(osg::Node& node)
687     {
688         HomePosition* homePosition = dynamic_cast<HomePosition*>(node.getUserData());
689         if (homePosition)
690         {
691             _homePosition = homePosition;
692         }
693 
694         traverse(node);
695     }
696 
697     osg::ref_ptr<HomePosition> _homePosition;
698 
699 };
700 
701 class FindNamedSwitchVisitor : public osg::NodeVisitor
702 {
703 public:
704 
FindNamedSwitchVisitor(const std::string & name)705     FindNamedSwitchVisitor(const std::string& name):
706         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
707         _name(name),
708         _switch(0) {}
709 
apply(osg::Switch & sw)710     void apply(osg::Switch& sw)
711     {
712         if (sw.getName().find(_name)!=std::string::npos)
713         {
714             _switch = &sw;
715             return; // note, no need to do traverse now we've located the relevant switch
716         }
717 
718         traverse(sw);
719     }
720 
721     std::string     _name;
722     osg::Switch*    _switch;
723 
724 };
725 
726 
727 class FindFilePathDataVisitor : public osg::NodeVisitor
728 {
729 public:
730 
FindFilePathDataVisitor()731     FindFilePathDataVisitor():
732         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
733 
apply(osg::Node & node)734     void apply(osg::Node& node)
735     {
736         FilePathData* fdd = dynamic_cast<FilePathData*>(node.getUserData());
737         if (fdd)
738         {
739             OSG_INFO<<"Recorded FilePathData"<<std::endl;
740             osgDB::setDataFilePathList(fdd->filePathList);
741         }
742 
743         traverse(node);
744     }
745 
746 };
747 
748 class UpdateLightVisitor : public osg::NodeVisitor
749 {
750 public:
751 
UpdateLightVisitor(const osg::Matrixd & viewMatrix,float currentX,float currentY)752     UpdateLightVisitor(const osg::Matrixd& viewMatrix, float currentX, float currentY):
753         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
754         _viewMatrix(viewMatrix),
755         _currentX(currentX), _currentY(currentY) {}
756 
apply(osg::Node & node)757     void apply(osg::Node& node)
758     {
759         traverse(node);
760     }
761 
apply(osg::LightSource & lightsource)762     void apply(osg::LightSource& lightsource)
763     {
764         if (lightsource.getLight())
765         {
766             if (lightsource.getReferenceFrame()==osg::LightSource::RELATIVE_RF)
767             {
768                 apply( osg::Matrix::identity(), lightsource.getLight());
769             }
770             else
771             {
772                 apply(osg::computeEyeToLocal(_viewMatrix,_nodePath), lightsource.getLight());
773             }
774         }
775 
776         traverse(lightsource);
777     }
778 
apply(const osg::Matrixd & matrix,osg::Light * light)779     void apply(const osg::Matrixd& matrix, osg::Light* light)
780     {
781         // compute direction of light based on a projecting onto a hemi-sphere.
782         float sum_x2_y2 = _currentX*_currentX + _currentY*_currentY;
783         osg::Vec3 direction;
784         if (sum_x2_y2<1.0) direction.set(_currentX, _currentY, sqrtf(1.0-sum_x2_y2));
785         else direction.set(_currentX, _currentY, 0.0);
786 
787         direction.normalize();
788 
789         direction = osg::Matrixd::transform3x3(matrix, direction);
790         direction.normalize();
791 
792         light->setPosition(osg::Vec4(direction,0.0f));
793     }
794 
795     osg::Matrixd    _viewMatrix;
796     float           _currentX, _currentY;
797 
798 };
799 
800 class UpdateAlphaVisitor : public osg::NodeVisitor
801 {
802 public:
803 
UpdateAlphaVisitor(bool modAlphaFunc,bool modMaterial,float currentX,float currentY)804     UpdateAlphaVisitor(bool modAlphaFunc, bool modMaterial, float currentX, float currentY):
805         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
806         _modAlphaFunc(modAlphaFunc), _modMaterial(modMaterial),
807         _currentX(currentX), _currentY(currentY) {}
808 
apply(osg::Node & node)809     void apply(osg::Node& node)
810     {
811         if (node.getStateSet()) apply(*node.getStateSet());
812         traverse(node);
813     }
814 
apply(osg::StateSet & stateset)815     void apply(osg::StateSet& stateset)
816     {
817         if (_modAlphaFunc)
818         {
819             osg::AlphaFunc* alphaFunc = dynamic_cast<osg::AlphaFunc*>(stateset.getAttribute(osg::StateAttribute::ALPHAFUNC));
820             if (alphaFunc)
821             {
822                 OSG_INFO<<"Adjusting alpha func"<<std::endl;
823 
824                 float alpha = alphaFunc->getReferenceValue();
825                 alpha = osg::clampBetween((1.0f-_currentY)*0.5f,0.0f,1.0f);
826 
827                 alphaFunc->setReferenceValue(alpha);
828             }
829         }
830 
831         if (_modMaterial)
832         {
833             osg::Material* material = dynamic_cast<osg::Material*>(stateset.getAttribute(osg::StateAttribute::MATERIAL));
834             if (material)
835             {
836                 OSG_INFO<<"Adjusting material func"<<std::endl;
837                 float alpha = osg::clampBetween((_currentY+1.0f)*0.5f,0.0f,1.0f);
838                 material->setAlpha(osg::Material::FRONT_AND_BACK,alpha);
839             }
840         }
841     }
842 
843     bool _modAlphaFunc, _modMaterial;
844     float   _currentX, _currentY;
845 
846 };
847 
848 
849 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
850 //
851 // SlideEventHandler
852 //
SlideEventHandler(osgViewer::Viewer * viewer)853 SlideEventHandler::SlideEventHandler(osgViewer::Viewer* viewer):
854     _viewer(viewer),
855     _presentationSwitch(0),
856     _activeSlide(0),
857     _slideSwitch(0),
858     _activeLayer(0),
859     _firstTraversal(true),
860     _referenceTime(-1.0),
861     _previousTime(-1.0),
862     _timePerSlide(1.0),
863     _autoSteppingActive(false),
864     _loopPresentation(false),
865     _pause(false),
866     _hold(false),
867     _updateLightActive(false),
868     _updateOpacityActive(false),
869     _previousX(0), _previousY(0),
870     _cursorOn(true),
871     _releaseAndCompileOnEachNewSlide(false),
872     _firstSlideOrLayerChange(true),
873     _tickAtFirstSlideOrLayerChange(0),
874     _tickAtLastSlideOrLayerChange(0),
875     _timeDelayOnNewSlideWithMovies(0.25f),
876     _minimumTimeBetweenKeyPresses(0.25),
877     _timeLastKeyPresses(-1.0),
878     _requestReload(false)
879 {
880     s_seh = this;
881 }
882 
getDuration(const osg::Node * node) const883 double SlideEventHandler::getDuration(const osg::Node* node) const
884 {
885     const LayerAttributes* la = dynamic_cast<const LayerAttributes*>(node->getUserData());
886     return la ? la->_duration : -1.0;
887 }
888 
set(osg::Node * model)889 void SlideEventHandler::set(osg::Node* model)
890 {
891 #if 0
892     // pause all slides, then just reenable the current slide.
893     ActivityUpdateCallbacksVisitor aucv(ALL_OBJECTS, true);
894     aucv.setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
895     model->accept(aucv);
896 #endif
897     _firstSlideOrLayerChange = true;
898     _tickAtFirstSlideOrLayerChange = 0;
899     _tickAtLastSlideOrLayerChange = 0;
900     _timeLastKeyPresses = -1;
901 
902     ActiveOperators operators;
903     operators.collect(model, osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
904     operators.setPause(this, true);
905 
906     FindNamedSwitchVisitor findPresentation("Presentation");
907     model->accept(findPresentation);
908 
909     if (findPresentation._switch)
910     {
911         OSG_INFO<<"Presentation '"<<model->getName()<<"'"<<std::endl;
912         _presentationSwitch = findPresentation._switch;
913 
914         double duration = getDuration(_presentationSwitch.get());
915         if (duration>=0.0)
916         {
917             OSG_INFO<<"Presentation time set to "<<duration<<std::endl;
918             _timePerSlide = duration;
919         }
920 
921         //selectSlide(0);
922     }
923     else
924     {
925         OSG_INFO<<"No presentation present in scene."<<std::endl;
926 
927         _presentationSwitch = 0;
928         _activeSlide = 0;
929 
930         FindNamedSwitchVisitor findSlide("Slide");
931         model->accept(findSlide);
932 
933         if (findSlide._switch)
934         {
935             OSG_INFO<<"Found presentation slide"<<findSlide._switch->getName()<<std::endl;
936 
937             _slideSwitch = findSlide._switch;
938             //selectLayer(0);
939         }
940         else
941         {
942             OSG_INFO<<"No slides present in scene, unable to operate as a slideshow."<<std::endl;
943         }
944 
945     }
946 }
947 
getCurrentTimeDelayBetweenSlides() const948 double SlideEventHandler::getCurrentTimeDelayBetweenSlides() const
949 {
950     if (_slideSwitch.valid())
951     {
952         double duration = -1.0;
953         if (_activeLayer<static_cast<int>(_slideSwitch->getNumChildren()))
954         {
955             duration = getDuration(_slideSwitch->getChild(_activeLayer));
956         }
957 
958         if (duration < 0.0)
959         {
960             duration = getDuration(_slideSwitch.get());
961         }
962 
963         if (duration >=0 )
964         {
965             return duration;
966         }
967     }
968 
969     return _timePerSlide;
970 }
971 
handle(const osgGA::GUIEventAdapter & ea,osgGA::GUIActionAdapter & aa)972 bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
973 {
974 
975     if (!_viewer)
976     {
977         _viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
978         selectSlide(0);
979         home();
980         OSG_NOTICE<<"Assigned viewer. to SlideEventHandler"<<std::endl;
981     }
982     //else  OSG_NOTICE<<"SlideEventHandler::handle() "<<ea.getTime()<<std::endl;
983 
984     if (ea.getHandled()) return false;
985 
986     _referenceTime = ea.getTime();
987 
988     switch(ea.getEventType())
989     {
990         case(osgGA::GUIEventAdapter::FRAME):
991         {
992             if (_autoSteppingActive && !_pause)
993             {
994                 double time = ea.time();
995 
996                 if (_firstTraversal)
997                 {
998                     _firstTraversal = false;
999                     _previousTime = time;
1000                 }
1001                 else if (time-_previousTime>=getCurrentTimeDelayBetweenSlides())
1002                 {
1003                     // _previousTime = time;
1004 
1005                     if (!_hold)
1006                     {
1007                         // increment the previous by the required time delay, note relative to the current
1008                         // to keep the time relative to an absolute time signal, thus avoid drift of timing.
1009                         _previousTime += getCurrentTimeDelayBetweenSlides();
1010 
1011                         nextLayerOrSlide();
1012                     }
1013                     else
1014                     {
1015                         // we're holding of the move to next layer to slide, but we need slip the time forward accordingly
1016                         // componensate for the extra time that this frame is receiving.
1017                         _previousTime = time-getCurrentTimeDelayBetweenSlides();
1018                     }
1019                 }
1020             }
1021             _activeOperators.frame(this);
1022 
1023             return false;
1024         }
1025 
1026         case(osgGA::GUIEventAdapter::KEYDOWN):
1027         {
1028             double time = ea.time();
1029             double deltaTime = time - _timeLastKeyPresses;
1030             if (deltaTime < _minimumTimeBetweenKeyPresses)
1031             {
1032                  break;
1033             }
1034 
1035             _timeLastKeyPresses = time;
1036 
1037             if (ea.getKey()=='g')
1038             {
1039                 if (!_autoSteppingActive)
1040                 {
1041                     _autoSteppingActive = true;
1042                     _previousTime = ea.time();
1043                 }
1044                 return true;
1045             }
1046             else if (ea.getKey()=='h')
1047             {
1048                 if (_autoSteppingActive)
1049                 {
1050                     _autoSteppingActive = false;
1051                     _previousTime = ea.time();
1052                 }
1053                 return true;
1054             }
1055             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Home ||
1056                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Home)
1057             {
1058                 _autoSteppingActive = false;
1059                 selectSlide(0);
1060                 home(ea,aa);
1061                 return true;
1062             }
1063             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_End ||
1064                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_End)
1065             {
1066                 _autoSteppingActive = false;
1067                 selectSlide(LAST_POSITION,LAST_POSITION);
1068                 home(ea,aa);
1069                 return true;
1070             }
1071             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Down ||
1072                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Down)
1073             {
1074                 _autoSteppingActive = false;
1075                 nextLayer();
1076                 return true;
1077             }
1078             else if (ea.getKey()=='n')
1079             {
1080                 _autoSteppingActive = false;
1081                 nextLayerOrSlide();
1082                 return true;
1083             }
1084             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Up ||
1085                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Up)
1086             {
1087                 _autoSteppingActive = false;
1088                 previousLayer();
1089                 return true;
1090             }
1091             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Page_Down ||
1092                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Down)
1093             {
1094                 _autoSteppingActive = false;
1095                 nextLayerOrSlide();
1096                 return true;
1097             }
1098             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Page_Up ||
1099                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Up)
1100             {
1101                 _autoSteppingActive = false;
1102                 previousLayerOrSlide();
1103                 return true;
1104             }
1105             else if (ea.getKey()=='N' ||
1106                      ea.getKey()==osgGA::GUIEventAdapter::KEY_Right ||
1107                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Right)
1108             {
1109                 _autoSteppingActive = false;
1110                 nextSlide();
1111                 home(ea,aa);
1112                 return true;
1113             }
1114             else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left ||
1115                      ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Left)
1116             {
1117                 _autoSteppingActive = false;
1118                 previousSlide();
1119                 home(ea,aa);
1120                 return true;
1121             }
1122             else if (ea.getKey()=='p')
1123             {
1124                 if (!_pause)
1125                 {
1126                     _pause = true;
1127 #if 0
1128                     resetUpdateCallbackActivity(ALL_OBJECTS);
1129 #endif
1130                     _activeOperators.setPause(this, _pause);
1131                 }
1132 
1133                 return true;
1134 
1135             }
1136             else if (ea.getKey()=='o')
1137             {
1138                 if (_pause)
1139                 {
1140                     _pause = false;
1141 #if 0
1142                     resetUpdateCallbackActivity(ALL_OBJECTS);
1143 #endif
1144                     _activeOperators.setPause(this, _pause);
1145                 }
1146                 return true;
1147 
1148             }
1149             else if (ea.getKey()=='h')
1150             {
1151                 _hold = true;
1152                 return true;
1153             }
1154             else if (ea.getKey()=='r')
1155             {
1156 #if 0
1157                 resetUpdateCallbacks(ALL_OBJECTS);
1158 #endif
1159                 _activeOperators.reset(this);
1160                 return true;
1161             }
1162 /*
1163             else if (ea.getKey()=='c')
1164             {
1165                 _cursorOn = !_cursorOn;
1166 
1167                 for( unsigned int i = 0; i < _viewer->getCameraConfig()->getNumberOfCameras(); i++ )
1168                 {
1169                     Producer::Camera* cam = _viewer->getCameraConfig()->getCamera(i);
1170                     Producer::RenderSurface* rs = cam->getRenderSurface();
1171                     rs->useCursor(_cursorOn);
1172                 }
1173 
1174                 return true;
1175             }
1176 */
1177             else if (ea.getKey()=='u')
1178             {
1179                 updateAlpha(true,false,ea.getXnormalized(),ea.getYnormalized());
1180                 return true;
1181             }
1182             else if (ea.getKey()=='i')
1183             {
1184                 updateAlpha(false,true,ea.getXnormalized(),ea.getYnormalized());
1185                 return true;
1186             }
1187             else if (ea.getKey()=='k')
1188             {
1189                 updateLight(ea.getXnormalized(),ea.getYnormalized());
1190                 return true;
1191             }
1192 
1193             return false;
1194         }
1195         case(osgGA::GUIEventAdapter::KEYUP):
1196         {
1197             if (ea.getKey()=='h')
1198             {
1199                 _hold = false;
1200                 return true;
1201             }
1202             else if (ea.getKey()=='u')
1203             {
1204                 setRequestReload(true);
1205                 return true;
1206             }
1207             return false;
1208         }
1209         default:
1210             return false;
1211     }
1212     return false;
1213 }
1214 
getUsage(osg::ApplicationUsage & usage) const1215 void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const
1216 {
1217     usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image");
1218     usage.addKeyboardMouseBinding("n","Advance to next layer or slide");
1219     usage.addKeyboardMouseBinding("p","Move to previous layer or slide");
1220 }
1221 
getNumSlides()1222 unsigned int SlideEventHandler::getNumSlides()
1223 {
1224     if (_presentationSwitch.valid()) return _presentationSwitch->getNumChildren();
1225     else return 0;
1226 }
1227 
getSlide(int slideNum)1228 osg::Switch* SlideEventHandler::getSlide(int slideNum)
1229 {
1230     if (slideNum<0 || slideNum>static_cast<int>(_presentationSwitch->getNumChildren())) return 0;
1231 
1232     FindNamedSwitchVisitor findSlide("Slide");
1233     _presentationSwitch->getChild(slideNum)->accept(findSlide);
1234     return findSlide._switch;
1235 }
1236 
getLayer(int slideNum,int layerNum)1237 osg::Node* SlideEventHandler::getLayer(int slideNum, int layerNum)
1238 {
1239     osg::Switch* slide = getSlide(slideNum);
1240     return (slide && (layerNum>=0 && layerNum<static_cast<int>(slide->getNumChildren()))) ? slide->getChild(layerNum) : 0;
1241 }
1242 
1243 
selectSlide(int slideNum,int layerNum)1244 bool SlideEventHandler::selectSlide(int slideNum,int layerNum)
1245 {
1246     if (!_presentationSwitch) return false;
1247 
1248     OSG_INFO<<"selectSlide("<<slideNum<<","<<layerNum<<")"<<std::endl;
1249 
1250     if (slideNum>=static_cast<int>(_presentationSwitch->getNumChildren()))
1251     {
1252         slideNum = LAST_POSITION;
1253     }
1254 
1255     if (slideNum==LAST_POSITION && _presentationSwitch->getNumChildren()>0)
1256     {
1257         slideNum = _presentationSwitch->getNumChildren()-1;
1258     }
1259 
1260     if (slideNum>=static_cast<int>(_presentationSwitch->getNumChildren())) return false;
1261 
1262 
1263     osg::Timer_t tick = osg::Timer::instance()->tick();
1264 
1265     if (_firstSlideOrLayerChange)
1266     {
1267         _firstSlideOrLayerChange = false;
1268         _tickAtFirstSlideOrLayerChange = tick;
1269         _tickAtLastSlideOrLayerChange = tick;
1270     }
1271 
1272     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;
1273 
1274     _tickAtLastSlideOrLayerChange = tick;
1275 
1276     // dectivate movies etc on current active slide.
1277     bool newSlide = _activeSlide!=slideNum;
1278     if (newSlide)
1279     {
1280         if (_releaseAndCompileOnEachNewSlide)
1281         {
1282             releaseSlide(_activeSlide);
1283         }
1284     }
1285 
1286     _activeSlide = slideNum;
1287     _presentationSwitch->setSingleChildOn(_activeSlide);
1288 
1289     //OSG_INFO<<"Selected slide '"<<_presentationSwitch->getChild(_activeSlide)->getName()<<"'"<<std::endl;
1290 
1291 
1292     FindNamedSwitchVisitor findSlide("Slide");
1293     _presentationSwitch->getChild(_activeSlide)->accept(findSlide);
1294 
1295     bool result = false;
1296     if (findSlide._switch)
1297     {
1298         //OSG_INFO<<"Found slide '"<<findSlide._switch->getName()<<"'"<<std::endl;
1299         _slideSwitch = findSlide._switch;
1300 
1301         result = selectLayer(layerNum);
1302 
1303 
1304     }
1305     else
1306     {
1307         //OSG_INFO<<"Not found slide"<<std::endl;
1308         updateOperators();
1309     }
1310 
1311 
1312     // refersh the viewer.
1313     //_viewer->getKeySwitchMatrixManipulator()->setMinimumDistance(0.001);
1314 
1315     if (_viewer->getCameraManipulator())
1316     {
1317         _viewer->getCameraManipulator()->setNode(_slideSwitch.get());
1318 
1319         _viewer->computeActiveCoordinateSystemNodePath();
1320     }
1321 
1322     // resetUpdateCallbacks(ALL_OBJECTS);
1323 
1324     bool _useSlideFilePaths = false;
1325     if (_useSlideFilePaths)
1326     {
1327         // set up the file paths
1328         FindFilePathDataVisitor ffpdv;
1329         _presentationSwitch->accept(ffpdv);
1330     }
1331 
1332     if (newSlide && _releaseAndCompileOnEachNewSlide)
1333     {
1334         compileSlide(slideNum);
1335     }
1336 
1337     return result;
1338 
1339 }
1340 
selectLayer(int layerNum)1341 bool SlideEventHandler::selectLayer(int layerNum)
1342 {
1343     if (!_slideSwitch) return false;
1344 
1345     bool withinSlide = true;
1346 
1347     if (layerNum>=static_cast<int>(_slideSwitch->getNumChildren()))
1348     {
1349         withinSlide = false;
1350         layerNum = LAST_POSITION;
1351     }
1352 
1353     if (layerNum==LAST_POSITION && _slideSwitch->getNumChildren()>0)
1354     {
1355         layerNum = _slideSwitch->getNumChildren()-1;
1356     }
1357 
1358     if (layerNum>=static_cast<int>(_slideSwitch->getNumChildren())) return false;
1359 
1360     _activeLayer = layerNum;
1361     _slideSwitch->setSingleChildOn(_activeLayer);
1362 
1363     updateOperators();
1364 
1365     OSG_INFO<<"Selected layer '"<<_slideSwitch->getChild(_activeLayer)->getName()<<"' num="<<_activeLayer<< std::endl;
1366 
1367     return withinSlide;
1368 }
1369 
nextLayerOrSlide()1370 bool SlideEventHandler::nextLayerOrSlide()
1371 {
1372     if (nextLayer())
1373     {
1374         return true;
1375     }
1376     else
1377     {
1378         return nextSlide();
1379     }
1380 }
1381 
previousLayerOrSlide()1382 bool SlideEventHandler::previousLayerOrSlide()
1383 {
1384     OSG_INFO<<"previousLayerOrSlide()"<<std::endl;
1385     if (previousLayer()) return true;
1386     else return previousSlide();
1387 }
1388 
nextSlide()1389 bool SlideEventHandler::nextSlide()
1390 {
1391     OSG_INFO<<"nextSlide()"<<std::endl;
1392     LayerAttributes* la = _slideSwitch.valid() ? dynamic_cast<LayerAttributes*>(_slideSwitch->getUserData()) : 0;
1393     if (la && la->getJumpData().requiresJump())
1394     {
1395         return la->getJumpData().jump(this);
1396     }
1397 
1398     if (selectSlide(_activeSlide+1)) return true;
1399     else if (_loopPresentation) return selectSlide(0);
1400     else return false;
1401 }
1402 
previousSlide()1403 bool SlideEventHandler::previousSlide()
1404 {
1405     OSG_INFO<<"previousSlide()"<<std::endl;
1406 #if 1
1407     // start position when doing previous slide set to top of slide
1408     if (_activeSlide>0) return selectSlide(_activeSlide-1);
1409     else if (_loopPresentation && _presentationSwitch.valid()) return selectSlide(_presentationSwitch->getNumChildren()-1);
1410     else return false;
1411 #else
1412     // start position when doing previous slide set to end of slide
1413     if (_activeSlide>0) return selectSlide(_activeSlide-1,LAST_POSITION);
1414     else if (_loopPresentation && _presentationSwitch.valid()) return selectSlide(_presentationSwitch->getNumChildren()-1,LAST_POSITION);
1415     else return false;
1416 #endif
1417 }
1418 
nextLayer()1419 bool SlideEventHandler::nextLayer()
1420 {
1421     LayerAttributes* la = (_slideSwitch.valid() && _activeLayer<static_cast<int>(_slideSwitch->getNumChildren())) ? dynamic_cast<LayerAttributes*>(_slideSwitch->getChild(_activeLayer)->getUserData()) : 0;
1422     if (la)
1423     {
1424         la->callLeaveCallbacks(_slideSwitch->getChild(_activeLayer));
1425 
1426         if (la->getJumpData().requiresJump())
1427         {
1428             return la->getJumpData().jump(this);
1429         }
1430     }
1431 
1432     OSG_INFO<<"nextLayer() calling selectLayer("<<_activeLayer+1<<")"<<std::endl;
1433     return selectLayer(_activeLayer+1);
1434 }
1435 
previousLayer()1436 bool SlideEventHandler::previousLayer()
1437 {
1438     OSG_INFO<<"previousLayer()"<<std::endl;
1439     if (_activeLayer>0) return selectLayer(_activeLayer-1);
1440     else return false;
1441 }
1442 
1443 
updateOperators()1444 void SlideEventHandler::updateOperators()
1445 {
1446     _activeOperators.collect(_slideSwitch.get());
1447     _activeOperators.process(this);
1448 
1449     if (_viewer.valid())
1450     {
1451         updateLight(0.0f,0.0f);
1452     }
1453 }
1454 
home(const osgGA::GUIEventAdapter & ea,osgGA::GUIActionAdapter & aa)1455 bool SlideEventHandler::home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
1456 {
1457     FindHomePositionVisitor fhpv;
1458     osg::Node* node = _viewer->getSceneData();
1459     if (node) node->accept(fhpv);
1460 
1461     if (_viewer->getCameraManipulator())
1462     {
1463         if (fhpv._homePosition.valid())
1464         {
1465             OSG_INFO<<"Doing home for stored home position."<<std::endl;
1466 
1467             _viewer->getCameraManipulator()->setAutoComputeHomePosition(false);
1468             _viewer->getCameraManipulator()->setHomePosition(
1469                                                 fhpv._homePosition->eye,
1470                                                 fhpv._homePosition->center,
1471                                                 fhpv._homePosition->up);
1472         }
1473         else
1474         {
1475             _viewer->getCameraManipulator()->setAutoComputeHomePosition(true);
1476         }
1477         _viewer->getCameraManipulator()->home(ea,aa);
1478     }
1479 
1480     return true;
1481 }
1482 
home()1483 bool SlideEventHandler::home()
1484 {
1485     osg::ref_ptr<osgGA::GUIEventAdapter> ea =  new osgGA::GUIEventAdapter;
1486     ea->setEventType(osgGA::GUIEventAdapter::FRAME);
1487     ea->setTime(_viewer->getEventQueue()->getTime());
1488 
1489     home(*ea,*_viewer);
1490     return true;
1491 }
1492 
updateAlpha(bool modAlphaFunc,bool modMaterial,float x,float y)1493 void SlideEventHandler::updateAlpha(bool modAlphaFunc, bool modMaterial, float x, float y)
1494 {
1495     OSG_INFO<<"updateAlpha("<<x<<","<<y<<")"<<std::endl;
1496 
1497     UpdateAlphaVisitor uav(modAlphaFunc, modMaterial, x,y);
1498     if (_presentationSwitch.valid()) _presentationSwitch->accept(uav);
1499     else if (_viewer->getSceneData()) _viewer->getSceneData()->accept(uav);
1500 }
1501 
1502 
updateLight(float x,float y)1503 void SlideEventHandler::updateLight(float x, float y)
1504 {
1505     OSG_INFO<<"updateLight("<<x<<", "<<y<<")"<<std::endl;
1506 
1507     UpdateLightVisitor uav(_viewer->getCamera()->getViewMatrix(),x,y);
1508     _viewer->getSceneData()->accept(uav);
1509 
1510     if (_viewer->getLightingMode()!= osg::View::NO_LIGHT && _viewer->getLight())
1511     {
1512         if (_viewer->getLightingMode()== osg::View::SKY_LIGHT)
1513         {
1514             uav.apply(_viewer->getCamera()->getViewMatrix(), _viewer->getLight());
1515         }
1516         else if (_viewer->getLightingMode()== osg::View::HEADLIGHT)
1517         {
1518             uav.apply(osg::Matrix::identity(), _viewer->getLight());
1519         }
1520     }
1521 
1522 }
1523 
compileSlide(unsigned int slideNum)1524 void SlideEventHandler::compileSlide(unsigned int slideNum)
1525 {
1526     if (!_compileSlideCallback)
1527     {
1528         _compileSlideCallback = new CompileSlideCallback();
1529 
1530         osgViewer::Viewer::Cameras cameras;
1531         _viewer->getCameras(cameras);
1532 
1533         for(osgViewer::Viewer::Cameras::iterator itr = cameras.begin();
1534             itr != cameras.end();
1535             ++itr)
1536         {
1537             (*itr)->setPreDrawCallback(_compileSlideCallback.get());
1538         }
1539 
1540     }
1541 
1542     _compileSlideCallback->needCompile(_presentationSwitch->getChild(slideNum));
1543 
1544 }
1545 
releaseSlide(unsigned int slideNum)1546 void SlideEventHandler::releaseSlide(unsigned int slideNum)
1547 {
1548     osgUtil::GLObjectsVisitor globjVisitor(osgUtil::GLObjectsVisitor::RELEASE_DISPLAY_LISTS|
1549                                            osgUtil::GLObjectsVisitor::RELEASE_STATE_ATTRIBUTES);
1550     globjVisitor.setNodeMaskOverride(0xffffffff);
1551 
1552     _presentationSwitch->getChild(slideNum)->accept(globjVisitor);
1553 }
1554 
forwardEventToDevices(osgGA::Event * event)1555 void SlideEventHandler::forwardEventToDevices(osgGA::Event* event)
1556 {
1557     if (!event) return;
1558 
1559     // dispatch cloned event to devices
1560     if (!_viewer)
1561     {
1562         OSG_NOTICE<<"Warning: SlideEventHandler::forwardEventToDevices(Event*) error, no Viewer to dispatch to."<<std::endl;
1563         return;
1564     }
1565 
1566     osgViewer::View::Devices& devices = _viewer->getDevices();
1567     for(osgViewer::View::Devices::iterator i = devices.begin(); i != devices.end(); ++i)
1568     {
1569         if((*i)->getCapabilities() & osgGA::Device::SEND_EVENTS)
1570         {
1571             (*i)->sendEvent(*event);
1572         }
1573     }
1574 }
1575 
dispatchEvent(osgGA::Event * event)1576 void SlideEventHandler::dispatchEvent(osgGA::Event* event)
1577 {
1578     if (!event) return;
1579 
1580     // dispatch cloned event to devices
1581     if (!_viewer)
1582     {
1583         OSG_NOTICE<<"Warning: SlideEventHandler::forwardEventToDevices(Event*) error, no Viewer to dispatch to."<<std::endl;
1584         return;
1585     }
1586 
1587     osgGA::EventQueue* eq = _viewer!=0 ? _viewer->getEventQueue() : 0;
1588     if (!eq)
1589     {
1590         OSG_NOTICE<<"Warning: SlideEventHandler::dispatchEvent(KeyPosition&) error, no EventQueue to dispatch to."<<std::endl;
1591         return;
1592     }
1593 
1594     eq->addEvent(event);
1595 }
1596 
dispatchEvent(const KeyPosition & keyPosition)1597 void SlideEventHandler::dispatchEvent(const KeyPosition& keyPosition)
1598 {
1599     if (!_viewer)
1600     {
1601         OSG_NOTICE<<"Warning: SlideEventHandler::dispatchEvent(KeyPosition*) error, no Viewer to dispatch to."<<std::endl;
1602         return;
1603     }
1604 
1605     if (keyPosition._forwardToDevices)
1606     {
1607         osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter();
1608         event->setKey(keyPosition._key);
1609         event->setTime(_viewer->getEventQueue()->getTime());
1610 
1611         // forward key-down
1612         event->setEventType(osgGA::GUIEventAdapter::KEYDOWN);
1613         forwardEventToDevices(event.get());
1614 
1615         // forward key-up
1616         event->setEventType(osgGA::GUIEventAdapter::KEYUP);
1617         forwardEventToDevices(event.get());
1618 
1619         // ignore local event-queue
1620         return;
1621     }
1622 
1623     osgGA::EventQueue* eq = _viewer!=0 ? _viewer->getEventQueue() : 0;
1624     if (!eq)
1625     {
1626         OSG_NOTICE<<"Warning: SlideEventHandler::dispatchEvent(KeyPosition&) error, no EventQueue to dispatch to."<<std::endl;
1627         return;
1628     }
1629 
1630     // reset the time of the last key press to ensure that the event is disgarded as a key repeat.
1631     _timeLastKeyPresses = -1.0;
1632 
1633     if (keyPosition._x!=FLT_MAX)
1634     {
1635         float xRescaled = eq->getCurrentEventState()->getXmin() + (keyPosition._x+1.0f)*0.5f*(eq->getCurrentEventState()->getXmax()-eq->getCurrentEventState()->getXmin());
1636         eq->getCurrentEventState()->setX(xRescaled);
1637     }
1638 
1639     if (keyPosition._y!=FLT_MAX)
1640     {
1641         float y = (eq->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS) ?
1642                    keyPosition._y : -keyPosition._y;
1643 
1644         float yRescaled = eq->getCurrentEventState()->getYmin() + (y+1.0f)*0.5f*(eq->getCurrentEventState()->getYmax()-eq->getCurrentEventState()->getYmin());
1645         eq->getCurrentEventState()->setY(yRescaled);
1646     }
1647 
1648     eq->keyPress(keyPosition._key);
1649     eq->keyRelease(keyPosition._key);
1650 }
1651 
1652 
setRequestReload(bool flag)1653 void SlideEventHandler::setRequestReload(bool flag)
1654 {
1655     _requestReload = flag;
1656 }
1657 
1658