root/OpenSceneGraph/trunk/applications/present3D/SlideEventHandler.cpp @ 10207

Revision 10207, 38.4 kB (checked in by robert, 6 years ago)

Integrated support for relative paths, and http hosted presentations

Line 
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 "SlideEventHandler.h"
14#include "SlideShowConstructor.h"
15
16#include <osg/AnimationPath>
17#include <osg/Transform>
18#include <osg/TexEnvCombine>
19#include <osg/LightSource>
20#include <osg/AlphaFunc>
21#include <osg/io_utils>
22
23#include <osgUtil/TransformCallback>
24#include <osgUtil/GLObjectsVisitor>
25
26#include <osgGA/AnimationPathManipulator>
27
28#include "AnimationMaterial.h"
29
30#include <iostream>
31
32using namespace osgPresentation;
33
34static osg::observer_ptr<SlideEventHandler> s_seh;
35
36SlideEventHandler* SlideEventHandler::instance() { return s_seh.get(); }
37
38void LayerAttributes::callEnterCallbacks(osg::Node* node)
39{
40    osg::notify(osg::INFO)<<"LayerAttributes::callEnterCallbacks("<<node<<")"<<std::endl;
41    for(LayerCallbacks::iterator itr = _enterLayerCallbacks.begin();
42        itr != _enterLayerCallbacks.end();
43        ++itr)
44    {
45        (*(*itr))(node);
46    }
47}
48
49void LayerAttributes::callLeaveCallbacks(osg::Node* node)
50{
51    osg::notify(osg::INFO)<<"LayerAttributes::callLeaveCallbacks("<<node<<")"<<std::endl;
52    for(LayerCallbacks::iterator itr = _leaveLayerCallbacks.begin();
53        itr != _leaveLayerCallbacks.end();
54        ++itr)
55    {
56        (*(*itr))(node);
57    }
58}
59
60
61struct ImageStreamOperator : public ObjectOperator
62{
63    ImageStreamOperator(osg::ImageStream* imageStream):
64        _imageStream(imageStream) {}
65
66    virtual void* ptr() const { return _imageStream.get(); }
67
68    virtual void enter()
69    {
70        osg::notify(osg::INFO)<<"enter() : _imageStream->rewind() + play"<<std::endl;
71
72        reset();
73    }
74   
75    virtual void maintain()
76    {
77    }
78   
79    virtual void leave()
80    {
81       osg::notify(osg::INFO)<<"leave() : _imageStream->pause()"<<std::endl;
82
83        _imageStream->pause();
84    }
85
86    virtual void setPause(bool pause)
87    {
88       osg::notify(osg::INFO)<<"_imageStream->setPause("<<pause<<")"<<std::endl;
89
90        if (pause) _imageStream->pause();
91        else _imageStream->play();
92    }
93   
94    virtual void reset()
95    {
96        osg::ImageStream::StreamStatus previousStatus = _imageStream->getStatus();
97
98        _imageStream->rewind();
99
100
101        //_imageStream->setVolume(previousVolume);
102       
103        if(previousStatus==osg::ImageStream::PLAYING)
104        {
105            _imageStream->play();
106        }
107
108        // add a delay so that movie thread has a chance to do the rewind   
109        float microSecondsToDelay = SlideEventHandler::instance()->getTimeDelayOnNewSlideWithMovies() * 1000000.0f;
110        OpenThreads::Thread::microSleep(static_cast<unsigned int>(microSecondsToDelay));
111    }
112
113    osg::ref_ptr<osg::ImageStream>  _imageStream;
114};
115
116struct CallbackOperator : public ObjectOperator
117{
118    CallbackOperator(osg::Node* node, osg::Referenced* callback):
119        _node(node),
120        _callback(callback) {}
121
122    virtual void* ptr() const { return _callback.get(); }
123
124    virtual void enter()
125    {
126        reset();
127    }
128   
129    virtual void maintain()
130    {
131    }
132   
133    virtual void leave()
134    {
135    }
136
137    virtual void setPause(bool pause)
138    {
139        osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
140        osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
141        ss3d::AnimationMaterialCallback* amc = dynamic_cast<ss3d::AnimationMaterialCallback*>(_callback.get());
142        if (apc)
143        {
144            osg::notify(osg::INFO)<<"apc->setPause("<<pause<<")"<<std::endl;
145            apc->setPause(pause);
146        }
147        if (tc)
148        {
149            osg::notify(osg::INFO)<<"tc->setPause("<<pause<<")"<<std::endl;
150            tc->setPause(pause);
151        }
152        if (amc)
153        {
154            osg::notify(osg::INFO)<<"amc->setPause("<<pause<<")"<<std::endl;
155            amc->setPause(pause);
156        }
157    }
158
159    virtual void reset()
160    {
161        osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
162        osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
163        ss3d::AnimationMaterialCallback* amc = dynamic_cast<ss3d::AnimationMaterialCallback*>(_callback.get());
164        if (apc)
165        {
166            apc->reset();
167            apc->update(*_node);
168        }
169        if (tc)
170        {
171        }
172        if (amc)
173        {
174            amc->reset();
175            amc->update(*_node);
176        }
177    }
178
179
180    osg::ref_ptr<osg::Node>         _node;
181    osg::ref_ptr<osg::Referenced>   _callback;
182};
183
184struct LayerAttributesOperator : public ObjectOperator
185{
186    LayerAttributesOperator(osg::Node* node, LayerAttributes* la):
187        _node(node),
188        _layerAttribute(la)
189    {
190    }
191
192    virtual void* ptr() const { return _layerAttribute.get(); }
193
194    virtual void enter()
195    {
196        _layerAttribute->callEnterCallbacks(_node.get());
197
198        if (!_layerAttribute->_keys.empty())
199        {
200            osg::notify(osg::INFO)<<"applyKeys {"<<std::endl;
201
202            for(LayerAttributes::Keys::iterator itr = _layerAttribute->_keys.begin();
203                itr != _layerAttribute->_keys.end();
204                ++itr)
205            {
206                SlideEventHandler::instance()->dispatchEvent(*itr);
207            }
208
209            osg::notify(osg::INFO)<<"}"<<std::endl;
210        }   
211        if (!_layerAttribute->_runStrings.empty())
212        {
213            for(LayerAttributes::RunStrings::iterator itr = _layerAttribute->_runStrings.begin();
214                itr != _layerAttribute->_runStrings.end();
215                ++itr)
216            {
217
218                osg::notify(osg::NOTICE)<<"Run "<<itr->c_str()<<std::endl;
219                osg::Timer_t startTick = osg::Timer::instance()->tick();
220
221                int result = system(itr->c_str());
222
223                osg::notify(osg::INFO)<<"system("<<*itr<<") result "<<result<<std::endl;
224
225                double timeForRun = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
226
227                osgGA::EventQueue* eq = SlideEventHandler::instance()->getViewer()->getEventQueue();
228                if (eq)
229                {
230                    osg::Timer_t new_startTick = eq->getStartTick() + osg::Timer_t(timeForRun / osg::Timer::instance()->getSecondsPerTick());
231                    eq->setStartTick(new_startTick);
232                }
233            }
234        }
235
236    }
237   
238    virtual void maintain()
239    {
240    }
241   
242    virtual void leave()
243    {
244        osg::notify(osg::INFO)<<"LayerAttribute leave"<<std::endl;
245
246         _layerAttribute->callLeaveCallbacks(_node.get());
247    }
248
249    virtual void setPause(bool pause)
250    {
251    }
252
253    virtual void reset()
254    {
255    }
256
257
258    osg::ref_ptr<osg::Node>                             _node;
259    osg::ref_ptr<LayerAttributes> _layerAttribute;
260};
261
262
263class FindOperatorsVisitor : public osg::NodeVisitor
264{
265public:
266    FindOperatorsVisitor(ActiveOperators::OperatorList& operatorList, osg::NodeVisitor::TraversalMode tm):
267        osg::NodeVisitor(tm),
268        _operatorList(operatorList) {}
269
270    void apply(osg::Node& node)
271    {
272        if (node.getStateSet()) process(node.getStateSet());
273
274        if (node.getUpdateCallback())
275        {
276            _operatorList.insert(new CallbackOperator(&node, node.getUpdateCallback()));
277        }
278
279        LayerAttributes* la = dynamic_cast<LayerAttributes*>(node.getUserData());
280        if (la)
281        {
282            _operatorList.insert(new LayerAttributesOperator(&node, la));
283        }
284
285        traverse(node);
286    }
287
288    void apply(osg::Geode& node)   
289    {
290        apply((osg::Node&)node);
291        for(unsigned int i=0;i<node.getNumDrawables();++i)
292        {
293            osg::Drawable* drawable = node.getDrawable(i);
294            if (drawable->getStateSet()) process(drawable->getStateSet());
295        }
296    }
297
298    virtual void process(osg::StateSet* ss)
299    {
300        for(unsigned int i=0;i<ss->getTextureAttributeList().size();++i)
301        {
302            osg::Texture* texture = dynamic_cast<osg::Texture*>(ss->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
303            osg::Image* image = texture ? texture->getImage(0) : 0;
304            osg::ImageStream* imageStream = image ? dynamic_cast<osg::ImageStream*>(image) : 0;
305            if (imageStream)
306            {
307                _operatorList.insert(new ImageStreamOperator(imageStream));
308            }
309        }
310    }
311
312    ActiveOperators::OperatorList& _operatorList;
313};
314
315
316ActiveOperators::ActiveOperators():
317    _pause(false)
318{
319}
320
321ActiveOperators::~ActiveOperators()
322{
323}
324
325void ActiveOperators::collect(osg::Node* incommingNode, osg::NodeVisitor::TraversalMode tm)
326{
327    _previous.swap(_current);
328   
329    _current.clear();
330   
331    FindOperatorsVisitor fov(_current, tm);
332    incommingNode->accept(fov);
333   
334    osg::notify(osg::INFO)<<"ActiveOperators::collect("<<incommingNode<<")"<<std::endl;
335    osg::notify(osg::INFO)<<"  _previous.size()="<<_previous.size()<<std::endl;
336    osg::notify(osg::INFO)<<"  _current.size()="<<_current.size()<<std::endl;
337   
338    _outgoing.clear();
339    _incomming.clear();
340    _maintained.clear();
341   
342    for(OperatorList::iterator itr = _previous.begin();
343        itr != _previous.end();
344        ++itr)
345    {
346        ObjectOperator* prev = itr->get();
347        if (_current.count(prev)==0) _outgoing.insert(prev);
348        else _maintained.insert(prev);
349    }
350   
351    for(OperatorList::iterator itr = _current.begin();
352        itr != _current.end();
353        ++itr)
354    {
355        ObjectOperator* curr = itr->get();
356        if (_previous.count(curr)==0) _incomming.insert(curr);
357    }
358}
359
360void ActiveOperators::setPause(bool pause)
361{
362    _pause = pause;
363    for(OperatorList::iterator itr = _current.begin();
364        itr != _current.end();
365        ++itr)
366    {
367        (*itr)->setPause(_pause);
368    }
369}
370
371
372void ActiveOperators::reset()
373{
374    for(OperatorList::iterator itr = _current.begin();
375        itr != _current.end();
376        ++itr)
377    {
378        (*itr)->reset();
379    }
380}
381
382void ActiveOperators::process()
383{
384    processOutgoing();
385    processMaintained();
386    processIncomming();
387}
388
389void ActiveOperators::processOutgoing()
390{
391    osg::notify(osg::INFO)<<"  outgoing.size()="<<_outgoing.size()<<std::endl;   
392    for(OperatorList::iterator itr = _outgoing.begin();
393        itr != _outgoing.end();
394        ++itr)
395    {
396        (*itr)->leave();
397    }
398}
399
400void ActiveOperators::processMaintained()
401{
402    osg::notify(osg::INFO)<<"  maintained.size()="<<_maintained.size()<<std::endl;
403    for(OperatorList::iterator itr = _maintained.begin();
404        itr != _maintained.end();
405        ++itr)
406    {
407        (*itr)->maintain();
408    }
409}
410
411void ActiveOperators::processIncomming()
412{
413    osg::notify(osg::INFO)<<"  incomming.size()="<<_incomming.size()<<std::endl;
414    for(OperatorList::iterator itr = _incomming.begin();
415        itr != _incomming.end();
416        ++itr)
417    {
418        (*itr)->enter();
419        (*itr)->setPause(_pause);
420    }
421}
422
423
424
425
426class FindHomePositionVisitor : public osg::NodeVisitor
427{
428public:
429
430    FindHomePositionVisitor():
431        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
432       
433    void apply(osg::Node& node)
434    {
435        HomePosition* homePosition = dynamic_cast<HomePosition*>(node.getUserData());
436        if (homePosition)
437        {
438            _homePosition = homePosition;
439        }
440       
441        traverse(node);
442    }
443       
444    osg::ref_ptr<HomePosition> _homePosition;
445       
446};
447
448class FindNamedSwitchVisitor : public osg::NodeVisitor
449{
450public:
451
452    FindNamedSwitchVisitor(const std::string& name):
453        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
454        _name(name),
455        _switch(0) {}
456       
457    void apply(osg::Switch& sw)
458    {
459        if (sw.getName().find(_name)!=std::string::npos)
460        {
461            _switch = &sw;
462            return; // note, no need to do traverse now we've located the relevant switch
463        }
464       
465        traverse(sw);
466    }
467       
468    std::string     _name;
469    osg::Switch*    _switch;
470       
471};
472
473
474class FindFilePathDataVisitor : public osg::NodeVisitor
475{
476public:
477
478    FindFilePathDataVisitor():
479        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
480       
481    void apply(osg::Node& node)
482    {
483        FilePathData* fdd = dynamic_cast<FilePathData*>(node.getUserData());
484        if (fdd)
485        {
486            osg::notify(osg::INFO)<<"Recorded FilePathData"<<std::endl;
487            osgDB::setDataFilePathList(fdd->filePathList);
488        }
489       
490        traverse(node);
491    }
492       
493};
494
495class UpdateLightVisitor : public osg::NodeVisitor
496{
497public:
498
499    UpdateLightVisitor(const osg::Matrixd& viewMatrix, float currentX, float currentY):
500        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
501        _viewMatrix(viewMatrix),
502        _currentX(currentX), _currentY(currentY) {}
503       
504    void apply(osg::Node& node)
505    {
506        if (node.getStateSet())
507        {
508            apply(*node.getStateSet());
509        }
510       
511        traverse(node);
512    }
513   
514    void apply(osg::LightSource& lightsource)
515    {
516        if (lightsource.getStateSet())
517        {
518            apply(*lightsource.getStateSet());
519        }
520   
521        if (lightsource.getLight())
522        {
523            osg::notify(osg::INFO)<<"Adjusting light"<<std::endl;
524
525            osg::Light* light = lightsource.getLight();
526
527            float azim = _currentX*osg::PI;
528            float elevation = _currentY*osg::PI_2;
529            osg::Vec3 direction(sin(azim)*cos(elevation),sin(elevation),cos(azim)*cos(elevation));
530           
531            if (lightsource.getReferenceFrame()==osg::LightSource::RELATIVE_RF)
532            {
533                osg::notify(osg::INFO)<<"Relative to absolute"<<std::endl;
534            }
535            else
536            {
537                osg::Matrix matrix(osg::computeEyeToLocal(_viewMatrix,_nodePath));
538                osg::notify(osg::INFO)<<"ModelView"<<matrix<<std::endl;
539
540                //direction = osg::Matrixd::transform3x3(matrix,direction);
541                //direction.normalize();
542
543                //direction = direction*matrix;
544                //direction.normalize();
545
546            }
547
548            light->setPosition(osg::Vec4(direction,0.0f));
549
550        }
551       
552        traverse(lightsource);
553    }
554
555    void apply(osg::StateSet& stateset)
556    {
557        osg::TexEnvCombine* texenvcombine = dynamic_cast<osg::TexEnvCombine*>(stateset.getTextureAttribute(0,osg::StateAttribute::TEXENV));
558        if (texenvcombine)
559        {
560            apply(*texenvcombine);
561        }
562    }
563       
564    void apply(osg::TexEnvCombine& texenv)
565    {
566        osg::notify(osg::INFO)<<"Adjusting tex env combine"<<std::endl;
567       
568        osg::Matrix matrix(osg::computeEyeToLocal(_viewMatrix,_nodePath));
569       
570        osg::notify(osg::INFO)<<"ModelView"<<matrix<<std::endl;
571
572        float azim = _currentX*osg::PI;
573        float elevation = _currentY*osg::PI_2;
574        osg::Vec3 direction(sin(azim)*cos(elevation),sin(elevation),cos(azim)*cos(elevation));
575
576        direction = osg::Matrixd::transform3x3(matrix,direction);
577        direction.normalize();
578
579        texenv.setConstantColor(osg::Vec4((direction.x()+1.0f)*0.5f,(direction.y()+1.0f)*0.5f,(direction.z()+1.0f)*0.5f,1.0f));
580    }
581
582
583    osg::Matrixd    _viewMatrix;
584    float           _currentX, _currentY;
585       
586};
587
588class UpdateAlphaVisitor : public osg::NodeVisitor
589{
590public:
591
592    UpdateAlphaVisitor(bool modAlphaFunc, bool modMaterial, float currentX, float currentY):
593        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
594        _modAlphaFunc(modAlphaFunc), _modMaterial(modMaterial),
595        _currentX(currentX), _currentY(currentY) {}
596       
597    void apply(osg::Node& node)
598    {
599        if (node.getStateSet()) apply(*node.getStateSet());
600        traverse(node);
601    }
602   
603    void apply(osg::StateSet& stateset)
604    {
605        if (_modAlphaFunc)
606        {
607            osg::AlphaFunc* alphaFunc = dynamic_cast<osg::AlphaFunc*>(stateset.getAttribute(osg::StateAttribute::ALPHAFUNC));
608            if (alphaFunc)
609            {
610                osg::notify(osg::INFO)<<"Adjusting alpha func"<<std::endl;
611
612                float alpha = alphaFunc->getReferenceValue();
613                alpha = osg::clampBetween((1.0f-_currentY)*0.5f,0.0f,1.0f);
614
615                alphaFunc->setReferenceValue(alpha);
616            }
617        }
618       
619        if (_modMaterial)
620        {       
621            osg::Material* material = dynamic_cast<osg::Material*>(stateset.getAttribute(osg::StateAttribute::MATERIAL));
622            if (material)
623            {
624                osg::notify(osg::INFO)<<"Adjusting material func"<<std::endl;
625                float alpha = osg::clampBetween((_currentY+1.0f)*0.5f,0.0f,1.0f);
626                material->setAlpha(osg::Material::FRONT_AND_BACK,alpha);
627            }
628        }
629    }
630
631    bool _modAlphaFunc, _modMaterial;
632    float   _currentX, _currentY;
633       
634};
635
636
637///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
638//
639// SlideEventHandler
640//
641SlideEventHandler::SlideEventHandler(osgViewer::Viewer* viewer):
642    _viewer(viewer),
643    _presentationSwitch(0),
644    _activeSlide(0),
645    _slideSwitch(0),
646    _activeLayer(0),
647    _firstTraversal(true),
648    _previousTime(-1.0f),
649    _timePerSlide(1.0),
650    _autoSteppingActive(false),
651    _loopPresentation(false),
652    _pause(false),
653    _hold(false),
654    _updateLightActive(false),
655    _updateOpacityActive(false),
656    _previousX(0), _previousY(0),
657    _cursorOn(true),
658    _releaseAndCompileOnEachNewSlide(false),
659    _firstSlideOrLayerChange(true),
660    _tickAtFirstSlideOrLayerChange(0),
661    _tickAtLastSlideOrLayerChange(0),
662    _timeDelayOnNewSlideWithMovies(0.25f),
663    _minimumTimeBetweenKeyPresses(0.25),
664    _timeLastKeyPresses(-1.0)
665{
666    s_seh = this;
667}
668
669double SlideEventHandler::getDuration(const osg::Node* node) const
670{
671    const LayerAttributes* la = dynamic_cast<const LayerAttributes*>(node->getUserData());
672    return la ? la->_duration : -1.0;
673}
674
675void SlideEventHandler::set(osg::Node* model)
676{
677#if 0
678    // pause all slides, then just reenable the current slide.
679    ActivityUpdateCallbacksVisitor aucv(ALL_OBJECTS, true);
680    aucv.setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
681    model->accept(aucv);
682#endif
683
684    ActiveOperators operators;
685    operators.collect(model, osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
686    operators.setPause(true);
687
688    FindNamedSwitchVisitor findPresentation("Presentation");
689    model->accept(findPresentation);
690   
691    if (findPresentation._switch)
692    {
693        osg::notify(osg::INFO)<<"Presentation '"<<model->getName()<<"'"<<std::endl;
694        _presentationSwitch = findPresentation._switch;
695       
696        double duration = getDuration(_presentationSwitch.get());
697        if (duration>=0.0)
698        {
699            osg::notify(osg::INFO)<<"Presentation time set to "<<duration<<std::endl;
700            _timePerSlide = duration;
701        }
702       
703        //selectSlide(0);
704    }
705    else
706    {
707        osg::notify(osg::INFO)<<"No presentation present in scene."<<std::endl;
708
709        _presentationSwitch = 0;
710        _activeSlide = 0;
711       
712        FindNamedSwitchVisitor findSlide("Slide");
713        model->accept(findSlide);
714       
715        if (findSlide._switch)
716        {
717            osg::notify(osg::INFO)<<"Found presentation slide"<<findSlide._switch->getName()<<std::endl;
718
719            _slideSwitch = findSlide._switch;
720            //selectLayer(0);
721        }
722        else
723        {
724            osg::notify(osg::INFO)<<"No slides present in scene, unable to operate as a slideshow."<<std::endl;
725        }
726   
727    }
728}
729
730double SlideEventHandler::getCurrentTimeDelayBetweenSlides() const
731{
732    if (_slideSwitch.valid())
733    {
734        double duration = -1.0;
735        if (_activeLayer<static_cast<int>(_slideSwitch->getNumChildren()))
736        {
737            duration = getDuration(_slideSwitch->getChild(_activeLayer));
738        }
739
740        if (duration < 0.0)
741        {
742            duration = getDuration(_slideSwitch.get());
743        }
744
745        if (duration >=0 )
746        {
747            return duration;
748        }       
749    }
750       
751    return _timePerSlide;
752}
753
754
755void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv)
756{
757    osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
758    if (ev)
759    {
760        if (node->getNumChildrenRequiringEventTraversal()>0) traverse(node,nv);
761
762        if (ev->getActionAdapter() && !ev->getEvents().empty())
763        {
764            for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
765                itr != ev->getEvents().end();
766                ++itr)
767            {
768                handleWithCheckAgainstIgnoreHandledEventsMask(*(*itr), *(ev->getActionAdapter()), node, nv);
769            }
770        }
771    }
772}
773
774bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
775{
776
777    if (!_viewer)
778    {
779        _viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
780        selectSlide(0);
781        home();
782        osg::notify(osg::NOTICE)<<"Assigned viewer. to SlideEventHandler"<<std::endl;
783    }
784    // else  osg::notify(osg::NOTICE)<<"SlideEventHandler::handle()"<<std::endl;
785
786
787    if (ea.getHandled()) return false;
788
789    switch(ea.getEventType())
790    {
791        case(osgGA::GUIEventAdapter::FRAME):
792        {
793            if (_autoSteppingActive && !_pause)
794            {
795                double time = ea.time();
796               
797                if (_firstTraversal)
798                {
799                    _firstTraversal = false;
800                    _previousTime = time;
801                }
802                else if (time-_previousTime>=getCurrentTimeDelayBetweenSlides())
803                {
804                    // _previousTime = time;
805                   
806                    if (!_hold)
807                    {
808                        // increment the previous by the required time delay, note relative to the current
809                        // to keep the time relative to an absolute time signal, thus avoid drift of timing.
810                        _previousTime += getCurrentTimeDelayBetweenSlides();
811
812                        nextLayerOrSlide();
813                    }
814                    else
815                    {
816                        // we're holding of the move to next layer to slide, but we need slip the time forward accordingly
817                        // componensate for the extra time that this frame is recieving.
818                        _previousTime = time-getCurrentTimeDelayBetweenSlides();
819                    }
820                }
821            }
822            return false;
823        }
824
825        case(osgGA::GUIEventAdapter::KEYDOWN):
826        {
827            double time = ea.time();
828            double deltaTime = time - _timeLastKeyPresses;
829            if (deltaTime < _minimumTimeBetweenKeyPresses)
830            {
831                 break;
832            }
833           
834            _timeLastKeyPresses = time;
835
836            if (ea.getKey()=='a')
837            {
838                if (!_autoSteppingActive)
839                {
840                    _autoSteppingActive = true;
841                    _previousTime = ea.time();
842                }
843                return true;
844            }
845            else if (ea.getKey()=='q')
846            {
847                if (_autoSteppingActive)
848                {
849                    _autoSteppingActive = false;
850                    _previousTime = ea.time();
851                }
852                return true;
853            }
854            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Home ||
855                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Home)
856            {
857                _autoSteppingActive = false;
858                selectSlide(0);
859                home(ea,aa);
860                return true;
861            }
862            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_End ||
863                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_End)
864            {
865                _autoSteppingActive = false;
866                selectSlide(LAST_POSITION,LAST_POSITION);
867                home(ea,aa);
868                return true;
869            }
870            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Down ||
871                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Down)
872            {
873                _autoSteppingActive = false;
874                nextLayer();
875                return true;
876            }
877            else if (ea.getKey()=='n')
878            {
879                _autoSteppingActive = false;
880                nextLayerOrSlide();
881                return true;
882            }
883            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Up ||
884                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Up)
885            {
886                _autoSteppingActive = false;
887                previousLayer();
888                return true;
889            }
890            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Page_Down ||
891                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Down)
892            {
893                _autoSteppingActive = false;
894                nextLayerOrSlide();
895                return true;
896            }
897            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Page_Up ||
898                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Up)
899            {
900                _autoSteppingActive = false;
901                previousLayerOrSlide();
902                return true;
903            }
904            else if (ea.getKey()=='N' ||
905                     ea.getKey()==osgGA::GUIEventAdapter::KEY_Right ||
906                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Right)
907            {
908                _autoSteppingActive = false;
909                nextSlide();
910                home(ea,aa);
911                return true;
912            }
913            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left ||
914                     ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Left)
915            {
916                _autoSteppingActive = false;
917                previousSlide();
918                home(ea,aa);
919                return true;
920            }
921            else if (ea.getKey()=='p')
922            {
923                if (!_pause)
924                {
925                    _pause = true;
926#if 0                   
927                    resetUpdateCallbackActivity(ALL_OBJECTS);
928#endif
929                    _activeOperators.setPause(_pause);
930                }
931               
932                return true;
933               
934            }
935            else if (ea.getKey()=='o')
936            {
937                if (_pause)
938                {
939                    _pause = false;
940#if 0                   
941                    resetUpdateCallbackActivity(ALL_OBJECTS);
942#endif
943                    _activeOperators.setPause(_pause);
944                }
945                return true;
946               
947            }
948            else if (ea.getKey()=='h')
949            {
950                _hold = true;
951                return true;
952            }
953            else if (ea.getKey()=='r')
954            {
955#if 0
956                resetUpdateCallbacks(ALL_OBJECTS);
957#endif
958                _activeOperators.reset();
959                return true;
960            }
961/*           
962            else if (ea.getKey()=='c')
963            {
964                _cursorOn = !_cursorOn;
965           
966                for( unsigned int i = 0; i < _viewer->getCameraConfig()->getNumberOfCameras(); i++ )
967                {
968                    Producer::Camera* cam = _viewer->getCameraConfig()->getCamera(i);
969                    Producer::RenderSurface* rs = cam->getRenderSurface();
970                    rs->useCursor(_cursorOn);
971                }
972
973                return true;
974            }
975*/
976            else if (ea.getKey()=='u')
977            {
978                updateAlpha(true,false,ea.getX(),ea.getY());
979                return true;
980            }
981            else if (ea.getKey()=='i')
982            {
983                updateAlpha(false,true,ea.getX(),ea.getY());
984                return true;
985            }
986            else if (ea.getKey()=='k')
987            {
988                updateLight(ea.getX(),ea.getY());
989                return true;
990            }
991
992            return false;
993        }
994        case(osgGA::GUIEventAdapter::KEYUP):
995        {
996            if (ea.getKey()=='h')
997            {
998                _hold = false;
999                return true;
1000            }
1001            return false;
1002        }
1003        default:
1004            return false;
1005    }
1006    return false;
1007}
1008
1009void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const
1010{
1011    usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image");
1012    usage.addKeyboardMouseBinding("n","Advance to next layer or slide");
1013    usage.addKeyboardMouseBinding("p","Move to previous layer or slide");
1014}
1015
1016unsigned int SlideEventHandler::getNumSlides()
1017{
1018    if (_presentationSwitch.valid()) return _presentationSwitch->getNumChildren();
1019    else return 0;
1020}
1021
1022
1023bool SlideEventHandler::selectSlide(int slideNum,int layerNum)
1024{
1025    if (!_presentationSwitch) return false;
1026
1027    osg::notify(osg::INFO)<<"selectSlide("<<slideNum<<","<<layerNum<<")"<<std::endl;
1028   
1029    if (slideNum==LAST_POSITION && _presentationSwitch->getNumChildren()>0)
1030    {
1031        slideNum = _presentationSwitch->getNumChildren()-1;
1032    }
1033   
1034    if (slideNum>=static_cast<int>(_presentationSwitch->getNumChildren())) return false;
1035
1036
1037    osg::Timer_t tick = osg::Timer::instance()->tick();
1038
1039    if (_firstSlideOrLayerChange)
1040    {
1041        _firstSlideOrLayerChange = false;
1042        _tickAtFirstSlideOrLayerChange = tick;
1043        _tickAtLastSlideOrLayerChange = tick;
1044    }
1045
1046    osg::notify(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;
1047   
1048    _tickAtLastSlideOrLayerChange = tick;
1049   
1050    // dectivate movies etc on current active slide.
1051    bool newSlide = _activeSlide!=slideNum;
1052    if (newSlide)
1053    {
1054        if (_releaseAndCompileOnEachNewSlide)
1055        {
1056            releaseSlide(_activeSlide);
1057        }
1058    }
1059
1060    _activeSlide = slideNum;
1061    _presentationSwitch->setSingleChildOn(_activeSlide);
1062
1063    //osg::notify(osg::INFO)<<"Selected slide '"<<_presentationSwitch->getChild(_activeSlide)->getName()<<"'"<<std::endl;
1064
1065   
1066    FindNamedSwitchVisitor findSlide("Slide");
1067    _presentationSwitch->getChild(_activeSlide)->accept(findSlide);
1068
1069    bool result = false;
1070    if (findSlide._switch)
1071    {
1072        //osg::notify(osg::INFO)<<"Found slide '"<<findSlide._switch->getName()<<"'"<<std::endl;
1073        _slideSwitch = findSlide._switch;
1074
1075        result = selectLayer(layerNum);
1076
1077       
1078    }
1079    else
1080    {
1081        //osg::notify(osg::INFO)<<"Not found slide"<<std::endl;
1082        updateOperators();
1083    }
1084   
1085
1086    // refersh the viewer.
1087    //_viewer->getKeySwitchMatrixManipulator()->setMinimumDistance(0.001);
1088   
1089    _viewer->getCameraManipulator()->setNode(_slideSwitch.get());
1090   
1091    _viewer->computeActiveCoordinateSystemNodePath();
1092   
1093    // resetUpdateCallbacks(ALL_OBJECTS);
1094   
1095    bool _useSlideFilePaths = false;
1096    if (_useSlideFilePaths)
1097    {
1098        // set up the file paths
1099        FindFilePathDataVisitor ffpdv;
1100        _presentationSwitch->accept(ffpdv);
1101    }
1102   
1103    if (newSlide && _releaseAndCompileOnEachNewSlide)
1104    {
1105        compileSlide(slideNum);
1106    }
1107
1108    return result;
1109   
1110}
1111
1112bool SlideEventHandler::selectLayer(int layerNum)
1113{
1114    if (!_slideSwitch) return false;
1115
1116    if (layerNum==LAST_POSITION && _slideSwitch->getNumChildren()>0)
1117    {
1118        layerNum = _slideSwitch->getNumChildren()-1;
1119    }
1120
1121    if (layerNum>=static_cast<int>(_slideSwitch->getNumChildren())) return false;
1122   
1123    _activeLayer = layerNum;
1124    _slideSwitch->setSingleChildOn(_activeLayer);
1125
1126    updateOperators();
1127
1128    osg::notify(osg::INFO)<<"Selected layer '"<<_slideSwitch->getChild(_activeLayer)->getName()<<"' num="<<_activeLayer<< std::endl;
1129
1130    return true;
1131}
1132
1133bool SlideEventHandler::nextLayerOrSlide()
1134{
1135    if (nextLayer()) return true;
1136    else return nextSlide();
1137}
1138
1139bool SlideEventHandler::previousLayerOrSlide()
1140{
1141    if (previousLayer()) return true;
1142    else return previousSlide();
1143}
1144
1145bool SlideEventHandler::nextSlide()
1146{
1147    LayerAttributes* la = _slideSwitch.valid() ? dynamic_cast<LayerAttributes*>(_slideSwitch->getUserData()) : 0;
1148    if (la && la->requiresJump())
1149    {
1150        if (la->getRelativeJump())
1151        {
1152            int previousSlide = getActiveSlide();
1153            int previousLayer = getActiveLayer();
1154            int newSlide = previousSlide + la->getSlideNum();
1155            int newLayer = previousLayer + la->getLayerNum();
1156            if (newLayer<0)
1157            {
1158                newLayer = 0;
1159            }
1160
1161            return selectSlide(newSlide, newLayer);
1162        }
1163        else
1164        {
1165            return selectSlide(la->getSlideNum(),la->getLayerNum());
1166        }
1167    }
1168
1169    if (selectSlide(_activeSlide+1)) return true;
1170    else if (_loopPresentation) return selectSlide(0);
1171    else return false;
1172}
1173
1174bool SlideEventHandler::previousSlide()
1175{
1176#if 1
1177    // start position when doing previous slide set to top of slide
1178    if (_activeSlide>0) return selectSlide(_activeSlide-1);
1179    else if (_loopPresentation && _presentationSwitch.valid()) return selectSlide(_presentationSwitch->getNumChildren()-1);
1180    else return false;
1181#else
1182    // start position when doing previous slide set to end of slide
1183    if (_activeSlide>0) return selectSlide(_activeSlide-1,LAST_POSITION);
1184    else if (_loopPresentation && _presentationSwitch.valid()) return selectSlide(_presentationSwitch->getNumChildren()-1,LAST_POSITION);
1185    else return false;
1186#endif
1187}
1188
1189bool SlideEventHandler::nextLayer()
1190{
1191    LayerAttributes* la = (_slideSwitch.valid() && _activeLayer>=0) ? dynamic_cast<LayerAttributes*>(_slideSwitch->getChild(_activeLayer)->getUserData()) : 0;
1192    if (la)
1193    {
1194        la->callLeaveCallbacks(_slideSwitch->getChild(_activeLayer));
1195   
1196        if (la->requiresJump())
1197        {
1198            if (la->getRelativeJump())
1199            {
1200                int previousSlide = getActiveSlide();
1201                int previousLayer = getActiveLayer();
1202                int newSlide = previousSlide + la->getSlideNum();
1203                int newLayer = previousLayer + la->getLayerNum();
1204                if (newLayer<0)
1205                {
1206                    newLayer = 0;
1207                }
1208
1209                return selectSlide(newSlide, newLayer);
1210            }
1211            else
1212            {
1213                return selectSlide(la->getSlideNum(),la->getLayerNum());
1214            }
1215        }
1216    }
1217
1218    return selectLayer(_activeLayer+1);
1219}
1220
1221bool SlideEventHandler::previousLayer()
1222{
1223    if (_activeLayer>0) return selectLayer(_activeLayer-1);
1224    else return false;
1225}
1226
1227
1228void SlideEventHandler::updateOperators()
1229{
1230    _activeOperators.collect(_slideSwitch.get());
1231    _activeOperators.process();
1232
1233    if (_viewer.valid())
1234    {
1235        UpdateLightVisitor uav(_viewer->getCamera()->getViewMatrix(),0.0f,0.0f);
1236        _viewer->getSceneData()->accept(uav);
1237    }
1238}
1239
1240bool SlideEventHandler::home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
1241{
1242    FindHomePositionVisitor fhpv;
1243    osg::Node* node = _viewer->getSceneData();
1244    if (node) node->accept(fhpv);
1245
1246    if (fhpv._homePosition.valid())
1247    {
1248        osg::notify(osg::INFO)<<"Doing home for stored home position."<<std::endl;
1249
1250        _viewer->getCameraManipulator()->setAutoComputeHomePosition(false);
1251        _viewer->getCameraManipulator()->setHomePosition(
1252                                             fhpv._homePosition->eye,
1253                                             fhpv._homePosition->center,
1254                                             fhpv._homePosition->up);
1255    }
1256    else
1257    {
1258        _viewer->getCameraManipulator()->setAutoComputeHomePosition(true);
1259    }
1260    _viewer->getCameraManipulator()->home(ea,aa);
1261
1262    return true;
1263}
1264
1265bool SlideEventHandler::home()
1266{
1267    osg::ref_ptr<osgGA::GUIEventAdapter> ea =  new osgGA::GUIEventAdapter;
1268    ea->setEventType(osgGA::GUIEventAdapter::FRAME);
1269    ea->setTime(_viewer->getEventQueue()->getTime());
1270
1271    home(*ea,*_viewer);
1272    return true;
1273}
1274
1275void SlideEventHandler::updateAlpha(bool modAlphaFunc, bool modMaterial, float x, float y)
1276{
1277    osg::notify(osg::INFO)<<"updateAlpha("<<x<<","<<y<<")"<<std::endl;
1278   
1279    UpdateAlphaVisitor uav(modAlphaFunc, modMaterial, x,y);
1280    if (_presentationSwitch.valid()) _presentationSwitch->accept(uav);
1281    else if (_viewer->getSceneData()) _viewer->getSceneData()->accept(uav);
1282}
1283
1284
1285void SlideEventHandler::updateLight(float x, float y)
1286{
1287    osg::notify(osg::INFO)<<"updateLight("<<x<<", "<<y<<")"<<std::endl;
1288
1289    UpdateLightVisitor uav(_viewer->getCamera()->getViewMatrix(),x,y);
1290    _viewer->getSceneData()->accept(uav);
1291}
1292
1293void SlideEventHandler::compileSlide(unsigned int slideNum)
1294{
1295    if (!_compileSlideCallback)
1296    {
1297        _compileSlideCallback = new ss3d::CompileSlideCallback();
1298
1299        osgViewer::Viewer::Cameras cameras;
1300        _viewer->getCameras(cameras);
1301
1302        for(osgViewer::Viewer::Cameras::iterator itr = cameras.begin();
1303            itr != cameras.end();
1304            ++itr)
1305        {
1306            (*itr)->setPreDrawCallback(_compileSlideCallback.get());
1307        }
1308
1309    }           
1310   
1311    _compileSlideCallback->needCompile(_presentationSwitch->getChild(slideNum));
1312   
1313}
1314
1315void SlideEventHandler::releaseSlide(unsigned int slideNum)
1316{
1317    osgUtil::GLObjectsVisitor globjVisitor(osgUtil::GLObjectsVisitor::RELEASE_DISPLAY_LISTS|
1318                                           osgUtil::GLObjectsVisitor::RELEASE_STATE_ATTRIBUTES);
1319    globjVisitor.setNodeMaskOverride(0xffffffff);
1320   
1321    _presentationSwitch->getChild(slideNum)->accept(globjVisitor);
1322}
1323
1324void SlideEventHandler::dispatchEvent(const KeyPosition& keyPosition)
1325{
1326    osg::notify(osg::INFO)<<" keyPosition._key "<<keyPosition._key<<" "<<keyPosition._x<<" "<<keyPosition._y<<std::endl;
1327
1328    osgGA::EventQueue* eq = _viewer->getEventQueue();
1329
1330    // reset the time of the last key press to ensure thatthe event is disgarded as a key repeat.
1331    _timeLastKeyPresses = -1.0;
1332   
1333    if (keyPosition._x!=FLT_MAX)
1334    {
1335        float xRescaled = eq->getCurrentEventState()->getXmin() + (keyPosition._x+1.0f)*0.5f*(eq->getCurrentEventState()->getXmax()-eq->getCurrentEventState()->getXmin());
1336        eq->getCurrentEventState()->setX(xRescaled);
1337    }
1338   
1339    if (keyPosition._y!=FLT_MAX)
1340    {
1341        float yRescaled = eq->getCurrentEventState()->getYmin() + (keyPosition._y+1.0f)*0.5f*(eq->getCurrentEventState()->getXmax()-eq->getCurrentEventState()->getYmin());
1342        eq->getCurrentEventState()->setY(yRescaled);
1343    }
1344
1345    eq->keyPress(keyPosition._key);
1346    eq->keyRelease(keyPosition._key);
1347}
1348
1349
Note: See TracBrowser for help on using the browser.