2009-04-28 19:57:51 +08:00
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and / or modified under
* the terms of the GNU General Public License ( GPL ) version 2.0 .
* The full license is in LICENSE . txt file included with this distribution , .
*
* This software is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* include LICENSE . txt for more details .
*/
# include "SlideEventHandler.h"
# include "SlideShowConstructor.h"
# include <osg/AnimationPath>
# include <osg/Transform>
# include <osg/TexEnvCombine>
# include <osg/LightSource>
# include <osg/AlphaFunc>
# include <osg/io_utils>
# include <osgUtil/TransformCallback>
# include <osgUtil/GLObjectsVisitor>
# include <osgGA/AnimationPathManipulator>
# include "AnimationMaterial.h"
# include <iostream>
2009-04-28 22:03:02 +08:00
using namespace osgPresentation ;
2009-04-28 19:57:51 +08:00
static osg : : observer_ptr < SlideEventHandler > s_seh ;
SlideEventHandler * SlideEventHandler : : instance ( ) { return s_seh . get ( ) ; }
2009-04-28 22:03:02 +08:00
void LayerAttributes : : callEnterCallbacks ( osg : : Node * node )
{
osg : : notify ( osg : : INFO ) < < " LayerAttributes::callEnterCallbacks( " < < node < < " ) " < < std : : endl ;
for ( LayerCallbacks : : iterator itr = _enterLayerCallbacks . begin ( ) ;
itr ! = _enterLayerCallbacks . end ( ) ;
+ + itr )
{
( * ( * itr ) ) ( node ) ;
}
}
void LayerAttributes : : callLeaveCallbacks ( osg : : Node * node )
{
osg : : notify ( osg : : INFO ) < < " LayerAttributes::callLeaveCallbacks( " < < node < < " ) " < < std : : endl ;
for ( LayerCallbacks : : iterator itr = _leaveLayerCallbacks . begin ( ) ;
itr ! = _leaveLayerCallbacks . end ( ) ;
+ + itr )
{
( * ( * itr ) ) ( node ) ;
}
}
2009-04-28 19:57:51 +08:00
struct ImageStreamOperator : public ObjectOperator
{
ImageStreamOperator ( osg : : ImageStream * imageStream ) :
_imageStream ( imageStream ) { }
virtual void * ptr ( ) const { return _imageStream . get ( ) ; }
virtual void enter ( )
{
osg : : notify ( osg : : INFO ) < < " enter() : _imageStream->rewind() + play " < < std : : endl ;
reset ( ) ;
}
virtual void maintain ( )
{
}
virtual void leave ( )
{
osg : : notify ( osg : : INFO ) < < " leave() : _imageStream->pause() " < < std : : endl ;
_imageStream - > pause ( ) ;
}
virtual void setPause ( bool pause )
{
osg : : notify ( osg : : INFO ) < < " _imageStream->setPause( " < < pause < < " ) " < < std : : endl ;
if ( pause ) _imageStream - > pause ( ) ;
else _imageStream - > play ( ) ;
}
virtual void reset ( )
{
osg : : ImageStream : : StreamStatus previousStatus = _imageStream - > getStatus ( ) ;
_imageStream - > rewind ( ) ;
//_imageStream->setVolume(previousVolume);
if ( previousStatus = = osg : : ImageStream : : PLAYING )
{
_imageStream - > play ( ) ;
}
// add a delay so that movie thread has a chance to do the rewind
float microSecondsToDelay = SlideEventHandler : : instance ( ) - > getTimeDelayOnNewSlideWithMovies ( ) * 1000000.0f ;
OpenThreads : : Thread : : microSleep ( static_cast < unsigned int > ( microSecondsToDelay ) ) ;
}
osg : : ref_ptr < osg : : ImageStream > _imageStream ;
} ;
struct CallbackOperator : public ObjectOperator
{
CallbackOperator ( osg : : Node * node , osg : : Referenced * callback ) :
_node ( node ) ,
_callback ( callback ) { }
virtual void * ptr ( ) const { return _callback . get ( ) ; }
virtual void enter ( )
{
reset ( ) ;
}
virtual void maintain ( )
{
}
virtual void leave ( )
{
}
virtual void setPause ( bool pause )
{
osg : : AnimationPathCallback * apc = dynamic_cast < osg : : AnimationPathCallback * > ( _callback . get ( ) ) ;
osgUtil : : TransformCallback * tc = dynamic_cast < osgUtil : : TransformCallback * > ( _callback . get ( ) ) ;
ss3d : : AnimationMaterialCallback * amc = dynamic_cast < ss3d : : AnimationMaterialCallback * > ( _callback . get ( ) ) ;
if ( apc )
{
osg : : notify ( osg : : INFO ) < < " apc->setPause( " < < pause < < " ) " < < std : : endl ;
apc - > setPause ( pause ) ;
}
if ( tc )
{
osg : : notify ( osg : : INFO ) < < " tc->setPause( " < < pause < < " ) " < < std : : endl ;
tc - > setPause ( pause ) ;
}
if ( amc )
{
osg : : notify ( osg : : INFO ) < < " amc->setPause( " < < pause < < " ) " < < std : : endl ;
amc - > setPause ( pause ) ;
}
}
virtual void reset ( )
{
osg : : AnimationPathCallback * apc = dynamic_cast < osg : : AnimationPathCallback * > ( _callback . get ( ) ) ;
osgUtil : : TransformCallback * tc = dynamic_cast < osgUtil : : TransformCallback * > ( _callback . get ( ) ) ;
ss3d : : AnimationMaterialCallback * amc = dynamic_cast < ss3d : : AnimationMaterialCallback * > ( _callback . get ( ) ) ;
if ( apc )
{
apc - > reset ( ) ;
apc - > update ( * _node ) ;
}
if ( tc )
{
}
if ( amc )
{
amc - > reset ( ) ;
amc - > update ( * _node ) ;
}
}
osg : : ref_ptr < osg : : Node > _node ;
osg : : ref_ptr < osg : : Referenced > _callback ;
} ;
struct LayerAttributesOperator : public ObjectOperator
{
2009-04-28 22:03:02 +08:00
LayerAttributesOperator ( osg : : Node * node , LayerAttributes * la ) :
2009-04-28 19:57:51 +08:00
_node ( node ) ,
_layerAttribute ( la )
{
}
virtual void * ptr ( ) const { return _layerAttribute . get ( ) ; }
virtual void enter ( )
{
_layerAttribute - > callEnterCallbacks ( _node . get ( ) ) ;
if ( ! _layerAttribute - > _keys . empty ( ) )
{
osg : : notify ( osg : : INFO ) < < " applyKeys { " < < std : : endl ;
2009-04-28 22:03:02 +08:00
for ( LayerAttributes : : Keys : : iterator itr = _layerAttribute - > _keys . begin ( ) ;
2009-04-28 19:57:51 +08:00
itr ! = _layerAttribute - > _keys . end ( ) ;
+ + itr )
{
SlideEventHandler : : instance ( ) - > dispatchEvent ( * itr ) ;
}
osg : : notify ( osg : : INFO ) < < " } " < < std : : endl ;
}
if ( ! _layerAttribute - > _runStrings . empty ( ) )
{
2009-04-28 22:03:02 +08:00
for ( LayerAttributes : : RunStrings : : iterator itr = _layerAttribute - > _runStrings . begin ( ) ;
2009-04-28 19:57:51 +08:00
itr ! = _layerAttribute - > _runStrings . end ( ) ;
+ + itr )
{
osg : : notify ( osg : : NOTICE ) < < " Run " < < itr - > c_str ( ) < < std : : endl ;
osg : : Timer_t startTick = osg : : Timer : : instance ( ) - > tick ( ) ;
int result = system ( itr - > c_str ( ) ) ;
osg : : notify ( osg : : INFO ) < < " system( " < < * itr < < " ) result " < < result < < std : : endl ;
double timeForRun = osg : : Timer : : instance ( ) - > delta_s ( startTick , osg : : Timer : : instance ( ) - > tick ( ) ) ;
osgGA : : EventQueue * eq = SlideEventHandler : : instance ( ) - > getViewer ( ) - > getEventQueue ( ) ;
if ( eq )
{
osg : : Timer_t new_startTick = eq - > getStartTick ( ) + osg : : Timer_t ( timeForRun / osg : : Timer : : instance ( ) - > getSecondsPerTick ( ) ) ;
eq - > setStartTick ( new_startTick ) ;
}
}
}
}
virtual void maintain ( )
{
}
virtual void leave ( )
{
osg : : notify ( osg : : INFO ) < < " LayerAttribute leave " < < std : : endl ;
_layerAttribute - > callLeaveCallbacks ( _node . get ( ) ) ;
}
virtual void setPause ( bool pause )
{
}
virtual void reset ( )
{
}
osg : : ref_ptr < osg : : Node > _node ;
2009-04-28 22:03:02 +08:00
osg : : ref_ptr < LayerAttributes > _layerAttribute ;
2009-04-28 19:57:51 +08:00
} ;
class FindOperatorsVisitor : public osg : : NodeVisitor
{
public :
FindOperatorsVisitor ( ActiveOperators : : OperatorList & operatorList , osg : : NodeVisitor : : TraversalMode tm ) :
osg : : NodeVisitor ( tm ) ,
_operatorList ( operatorList ) { }
void apply ( osg : : Node & node )
{
if ( node . getStateSet ( ) ) process ( node . getStateSet ( ) ) ;
if ( node . getUpdateCallback ( ) )
{
_operatorList . insert ( new CallbackOperator ( & node , node . getUpdateCallback ( ) ) ) ;
}
2009-04-28 22:03:02 +08:00
LayerAttributes * la = dynamic_cast < LayerAttributes * > ( node . getUserData ( ) ) ;
2009-04-28 19:57:51 +08:00
if ( la )
{
_operatorList . insert ( new LayerAttributesOperator ( & node , la ) ) ;
}
traverse ( node ) ;
}
void apply ( osg : : Geode & node )
{
apply ( ( osg : : Node & ) node ) ;
for ( unsigned int i = 0 ; i < node . getNumDrawables ( ) ; + + i )
{
osg : : Drawable * drawable = node . getDrawable ( i ) ;
if ( drawable - > getStateSet ( ) ) process ( drawable - > getStateSet ( ) ) ;
}
}
virtual void process ( osg : : StateSet * ss )
{
for ( unsigned int i = 0 ; i < ss - > getTextureAttributeList ( ) . size ( ) ; + + i )
{
osg : : Texture * texture = dynamic_cast < osg : : Texture * > ( ss - > getTextureAttribute ( i , osg : : StateAttribute : : TEXTURE ) ) ;
osg : : Image * image = texture ? texture - > getImage ( 0 ) : 0 ;
osg : : ImageStream * imageStream = image ? dynamic_cast < osg : : ImageStream * > ( image ) : 0 ;
if ( imageStream )
{
_operatorList . insert ( new ImageStreamOperator ( imageStream ) ) ;
}
}
}
ActiveOperators : : OperatorList & _operatorList ;
} ;
ActiveOperators : : ActiveOperators ( ) :
_pause ( false )
{
}
ActiveOperators : : ~ ActiveOperators ( )
{
}
void ActiveOperators : : collect ( osg : : Node * incommingNode , osg : : NodeVisitor : : TraversalMode tm )
{
_previous . swap ( _current ) ;
_current . clear ( ) ;
FindOperatorsVisitor fov ( _current , tm ) ;
incommingNode - > accept ( fov ) ;
osg : : notify ( osg : : INFO ) < < " ActiveOperators::collect( " < < incommingNode < < " ) " < < std : : endl ;
osg : : notify ( osg : : INFO ) < < " _previous.size()= " < < _previous . size ( ) < < std : : endl ;
osg : : notify ( osg : : INFO ) < < " _current.size()= " < < _current . size ( ) < < std : : endl ;
_outgoing . clear ( ) ;
_incomming . clear ( ) ;
_maintained . clear ( ) ;
for ( OperatorList : : iterator itr = _previous . begin ( ) ;
itr ! = _previous . end ( ) ;
+ + itr )
{
ObjectOperator * prev = itr - > get ( ) ;
if ( _current . count ( prev ) = = 0 ) _outgoing . insert ( prev ) ;
else _maintained . insert ( prev ) ;
}
for ( OperatorList : : iterator itr = _current . begin ( ) ;
itr ! = _current . end ( ) ;
+ + itr )
{
ObjectOperator * curr = itr - > get ( ) ;
if ( _previous . count ( curr ) = = 0 ) _incomming . insert ( curr ) ;
}
}
void ActiveOperators : : setPause ( bool pause )
{
_pause = pause ;
for ( OperatorList : : iterator itr = _current . begin ( ) ;
itr ! = _current . end ( ) ;
+ + itr )
{
( * itr ) - > setPause ( _pause ) ;
}
}
void ActiveOperators : : reset ( )
{
for ( OperatorList : : iterator itr = _current . begin ( ) ;
itr ! = _current . end ( ) ;
+ + itr )
{
( * itr ) - > reset ( ) ;
}
}
void ActiveOperators : : process ( )
{
processOutgoing ( ) ;
processMaintained ( ) ;
processIncomming ( ) ;
}
void ActiveOperators : : processOutgoing ( )
{
osg : : notify ( osg : : INFO ) < < " outgoing.size()= " < < _outgoing . size ( ) < < std : : endl ;
for ( OperatorList : : iterator itr = _outgoing . begin ( ) ;
itr ! = _outgoing . end ( ) ;
+ + itr )
{
( * itr ) - > leave ( ) ;
}
}
void ActiveOperators : : processMaintained ( )
{
osg : : notify ( osg : : INFO ) < < " maintained.size()= " < < _maintained . size ( ) < < std : : endl ;
for ( OperatorList : : iterator itr = _maintained . begin ( ) ;
itr ! = _maintained . end ( ) ;
+ + itr )
{
( * itr ) - > maintain ( ) ;
}
}
void ActiveOperators : : processIncomming ( )
{
osg : : notify ( osg : : INFO ) < < " incomming.size()= " < < _incomming . size ( ) < < std : : endl ;
for ( OperatorList : : iterator itr = _incomming . begin ( ) ;
itr ! = _incomming . end ( ) ;
+ + itr )
{
( * itr ) - > enter ( ) ;
( * itr ) - > setPause ( _pause ) ;
}
}
class FindHomePositionVisitor : public osg : : NodeVisitor
{
public :
FindHomePositionVisitor ( ) :
osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ) { }
void apply ( osg : : Node & node )
{
2009-04-28 22:03:02 +08:00
HomePosition * homePosition = dynamic_cast < HomePosition * > ( node . getUserData ( ) ) ;
2009-04-28 19:57:51 +08:00
if ( homePosition )
{
_homePosition = homePosition ;
}
traverse ( node ) ;
}
2009-04-28 22:03:02 +08:00
osg : : ref_ptr < HomePosition > _homePosition ;
2009-04-28 19:57:51 +08:00
} ;
class FindNamedSwitchVisitor : public osg : : NodeVisitor
{
public :
FindNamedSwitchVisitor ( const std : : string & name ) :
osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ) ,
_name ( name ) ,
_switch ( 0 ) { }
void apply ( osg : : Switch & sw )
{
if ( sw . getName ( ) . find ( _name ) ! = std : : string : : npos )
{
_switch = & sw ;
return ; // note, no need to do traverse now we've located the relevant switch
}
traverse ( sw ) ;
}
std : : string _name ;
osg : : Switch * _switch ;
} ;
class FindFilePathDataVisitor : public osg : : NodeVisitor
{
public :
FindFilePathDataVisitor ( ) :
osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ) { }
void apply ( osg : : Node & node )
{
2009-04-28 22:03:02 +08:00
FilePathData * fdd = dynamic_cast < FilePathData * > ( node . getUserData ( ) ) ;
2009-04-28 19:57:51 +08:00
if ( fdd )
{
osg : : notify ( osg : : INFO ) < < " Recorded FilePathData " < < std : : endl ;
osgDB : : setDataFilePathList ( fdd - > filePathList ) ;
}
traverse ( node ) ;
}
} ;
class UpdateLightVisitor : public osg : : NodeVisitor
{
public :
UpdateLightVisitor ( const osg : : Matrixd & viewMatrix , float currentX , float currentY ) :
osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ) ,
_viewMatrix ( viewMatrix ) ,
_currentX ( currentX ) , _currentY ( currentY ) { }
void apply ( osg : : Node & node )
{
if ( node . getStateSet ( ) )
{
apply ( * node . getStateSet ( ) ) ;
}
traverse ( node ) ;
}
void apply ( osg : : LightSource & lightsource )
{
if ( lightsource . getStateSet ( ) )
{
apply ( * lightsource . getStateSet ( ) ) ;
}
if ( lightsource . getLight ( ) )
{
osg : : notify ( osg : : INFO ) < < " Adjusting light " < < std : : endl ;
osg : : Light * light = lightsource . getLight ( ) ;
float azim = _currentX * osg : : PI ;
float elevation = _currentY * osg : : PI_2 ;
osg : : Vec3 direction ( sin ( azim ) * cos ( elevation ) , sin ( elevation ) , cos ( azim ) * cos ( elevation ) ) ;
if ( lightsource . getReferenceFrame ( ) = = osg : : LightSource : : RELATIVE_RF )
{
osg : : notify ( osg : : INFO ) < < " Relative to absolute " < < std : : endl ;
}
else
{
osg : : Matrix matrix ( osg : : computeEyeToLocal ( _viewMatrix , _nodePath ) ) ;
osg : : notify ( osg : : INFO ) < < " ModelView " < < matrix < < std : : endl ;
//direction = osg::Matrixd::transform3x3(matrix,direction);
//direction.normalize();
//direction = direction*matrix;
//direction.normalize();
}
light - > setPosition ( osg : : Vec4 ( direction , 0.0f ) ) ;
}
traverse ( lightsource ) ;
}
void apply ( osg : : StateSet & stateset )
{
osg : : TexEnvCombine * texenvcombine = dynamic_cast < osg : : TexEnvCombine * > ( stateset . getTextureAttribute ( 0 , osg : : StateAttribute : : TEXENV ) ) ;
if ( texenvcombine )
{
apply ( * texenvcombine ) ;
}
}
void apply ( osg : : TexEnvCombine & texenv )
{
osg : : notify ( osg : : INFO ) < < " Adjusting tex env combine " < < std : : endl ;
osg : : Matrix matrix ( osg : : computeEyeToLocal ( _viewMatrix , _nodePath ) ) ;
osg : : notify ( osg : : INFO ) < < " ModelView " < < matrix < < std : : endl ;
float azim = _currentX * osg : : PI ;
float elevation = _currentY * osg : : PI_2 ;
osg : : Vec3 direction ( sin ( azim ) * cos ( elevation ) , sin ( elevation ) , cos ( azim ) * cos ( elevation ) ) ;
direction = osg : : Matrixd : : transform3x3 ( matrix , direction ) ;
direction . normalize ( ) ;
texenv . setConstantColor ( osg : : Vec4 ( ( direction . x ( ) + 1.0f ) * 0.5f , ( direction . y ( ) + 1.0f ) * 0.5f , ( direction . z ( ) + 1.0f ) * 0.5f , 1.0f ) ) ;
}
osg : : Matrixd _viewMatrix ;
float _currentX , _currentY ;
} ;
class UpdateAlphaVisitor : public osg : : NodeVisitor
{
public :
UpdateAlphaVisitor ( bool modAlphaFunc , bool modMaterial , float currentX , float currentY ) :
osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ) ,
_modAlphaFunc ( modAlphaFunc ) , _modMaterial ( modMaterial ) ,
_currentX ( currentX ) , _currentY ( currentY ) { }
void apply ( osg : : Node & node )
{
if ( node . getStateSet ( ) ) apply ( * node . getStateSet ( ) ) ;
traverse ( node ) ;
}
void apply ( osg : : StateSet & stateset )
{
if ( _modAlphaFunc )
{
osg : : AlphaFunc * alphaFunc = dynamic_cast < osg : : AlphaFunc * > ( stateset . getAttribute ( osg : : StateAttribute : : ALPHAFUNC ) ) ;
if ( alphaFunc )
{
osg : : notify ( osg : : INFO ) < < " Adjusting alpha func " < < std : : endl ;
float alpha = alphaFunc - > getReferenceValue ( ) ;
alpha = osg : : clampBetween ( ( 1.0f - _currentY ) * 0.5f , 0.0f , 1.0f ) ;
alphaFunc - > setReferenceValue ( alpha ) ;
}
}
if ( _modMaterial )
{
osg : : Material * material = dynamic_cast < osg : : Material * > ( stateset . getAttribute ( osg : : StateAttribute : : MATERIAL ) ) ;
if ( material )
{
osg : : notify ( osg : : INFO ) < < " Adjusting material func " < < std : : endl ;
float alpha = osg : : clampBetween ( ( _currentY + 1.0f ) * 0.5f , 0.0f , 1.0f ) ;
material - > setAlpha ( osg : : Material : : FRONT_AND_BACK , alpha ) ;
}
}
}
bool _modAlphaFunc , _modMaterial ;
float _currentX , _currentY ;
} ;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SlideEventHandler
//
SlideEventHandler : : SlideEventHandler ( osgViewer : : Viewer * viewer ) :
_viewer ( viewer ) ,
_presentationSwitch ( 0 ) ,
_activeSlide ( 0 ) ,
_slideSwitch ( 0 ) ,
_activeLayer ( 0 ) ,
_firstTraversal ( true ) ,
_previousTime ( - 1.0f ) ,
_timePerSlide ( 1.0 ) ,
_autoSteppingActive ( false ) ,
_loopPresentation ( false ) ,
_pause ( false ) ,
_hold ( false ) ,
_updateLightActive ( false ) ,
_updateOpacityActive ( false ) ,
_previousX ( 0 ) , _previousY ( 0 ) ,
_cursorOn ( true ) ,
_releaseAndCompileOnEachNewSlide ( true ) ,
_firstSlideOrLayerChange ( true ) ,
_tickAtFirstSlideOrLayerChange ( 0 ) ,
_tickAtLastSlideOrLayerChange ( 0 ) ,
_timeDelayOnNewSlideWithMovies ( 0.25f ) ,
_minimumTimeBetweenKeyPresses ( 0.25 ) ,
_timeLastKeyPresses ( - 1.0 )
{
s_seh = this ;
}
double SlideEventHandler : : getDuration ( const osg : : Node * node ) const
{
2009-04-28 22:03:02 +08:00
const LayerAttributes * la = dynamic_cast < const LayerAttributes * > ( node - > getUserData ( ) ) ;
2009-04-28 19:57:51 +08:00
return la ? la - > _duration : - 1.0 ;
}
void SlideEventHandler : : set ( osg : : Node * model )
{
#if 0
// pause all slides, then just reenable the current slide.
ActivityUpdateCallbacksVisitor aucv ( ALL_OBJECTS , true ) ;
aucv . setTraversalMode ( osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ) ;
model - > accept ( aucv ) ;
# endif
ActiveOperators operators ;
operators . collect ( model , osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ) ;
operators . setPause ( true ) ;
FindNamedSwitchVisitor findPresentation ( " Presentation " ) ;
model - > accept ( findPresentation ) ;
if ( findPresentation . _switch )
{
osg : : notify ( osg : : INFO ) < < " Presentation ' " < < model - > getName ( ) < < " ' " < < std : : endl ;
_presentationSwitch = findPresentation . _switch ;
double duration = getDuration ( _presentationSwitch . get ( ) ) ;
if ( duration > = 0.0 )
{
osg : : notify ( osg : : INFO ) < < " Presentation time set to " < < duration < < std : : endl ;
_timePerSlide = duration ;
}
selectSlide ( 0 ) ;
}
else
{
osg : : notify ( osg : : INFO ) < < " No presentation present in scene. " < < std : : endl ;
_presentationSwitch = 0 ;
_activeSlide = 0 ;
FindNamedSwitchVisitor findSlide ( " Slide " ) ;
model - > accept ( findSlide ) ;
if ( findSlide . _switch )
{
osg : : notify ( osg : : INFO ) < < " Found presentation slide " < < findSlide . _switch - > getName ( ) < < std : : endl ;
_slideSwitch = findSlide . _switch ;
selectLayer ( 0 ) ;
}
else
{
osg : : notify ( osg : : INFO ) < < " No slides present in scene, unable to operate as a slideshow. " < < std : : endl ;
}
}
}
double SlideEventHandler : : getCurrentTimeDelayBetweenSlides ( ) const
{
if ( _slideSwitch . valid ( ) )
{
double duration = - 1.0 ;
2009-05-02 15:50:37 +08:00
if ( _activeLayer < static_cast < int > ( _slideSwitch - > getNumChildren ( ) ) )
2009-04-28 19:57:51 +08:00
{
duration = getDuration ( _slideSwitch - > getChild ( _activeLayer ) ) ;
}
if ( duration < 0.0 )
{
duration = getDuration ( _slideSwitch . get ( ) ) ;
}
if ( duration > = 0 )
{
return duration ;
}
}
return _timePerSlide ;
}
bool SlideEventHandler : : handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & aa )
{
if ( ea . getHandled ( ) ) return false ;
switch ( ea . getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : FRAME ) :
{
if ( _autoSteppingActive & & ! _pause )
{
double time = ea . time ( ) ;
if ( _firstTraversal )
{
_firstTraversal = false ;
_previousTime = time ;
}
else if ( time - _previousTime > = getCurrentTimeDelayBetweenSlides ( ) )
{
// _previousTime = time;
if ( ! _hold )
{
// increment the previous by the required time delay, note relative to the current
// to keep the time relative to an absolute time signal, thus avoid drift of timing.
_previousTime + = getCurrentTimeDelayBetweenSlides ( ) ;
nextLayerOrSlide ( ) ;
}
else
{
// we're holding of the move to next layer to slide, but we need slip the time forward accordingly
// componensate for the extra time that this frame is recieving.
_previousTime = time - getCurrentTimeDelayBetweenSlides ( ) ;
}
}
}
return false ;
}
case ( osgGA : : GUIEventAdapter : : KEYDOWN ) :
{
double time = ea . time ( ) ;
double deltaTime = time - _timeLastKeyPresses ;
if ( deltaTime < _minimumTimeBetweenKeyPresses )
{
break ;
}
_timeLastKeyPresses = time ;
if ( ea . getKey ( ) = = ' a ' )
{
if ( ! _autoSteppingActive )
{
_autoSteppingActive = true ;
_previousTime = ea . time ( ) ;
}
return true ;
}
else if ( ea . getKey ( ) = = ' q ' )
{
if ( _autoSteppingActive )
{
_autoSteppingActive = false ;
_previousTime = ea . time ( ) ;
}
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Home | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Home )
{
_autoSteppingActive = false ;
selectSlide ( 0 ) ;
home ( ea , aa ) ;
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_End | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_End )
{
_autoSteppingActive = false ;
selectSlide ( LAST_POSITION , LAST_POSITION ) ;
home ( ea , aa ) ;
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Down | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Down )
{
_autoSteppingActive = false ;
nextLayer ( ) ;
return true ;
}
else if ( ea . getKey ( ) = = ' n ' )
{
_autoSteppingActive = false ;
nextLayerOrSlide ( ) ;
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Up | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Up )
{
_autoSteppingActive = false ;
previousLayer ( ) ;
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Page_Down | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Page_Down )
{
_autoSteppingActive = false ;
nextLayerOrSlide ( ) ;
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Page_Up | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Page_Up )
{
_autoSteppingActive = false ;
previousLayerOrSlide ( ) ;
return true ;
}
else if ( ea . getKey ( ) = = ' N ' | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Right | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Right )
{
_autoSteppingActive = false ;
nextSlide ( ) ;
home ( ea , aa ) ;
return true ;
}
else if ( ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_Left | |
ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Left )
{
_autoSteppingActive = false ;
previousSlide ( ) ;
home ( ea , aa ) ;
return true ;
}
else if ( ea . getKey ( ) = = ' p ' )
{
if ( ! _pause )
{
_pause = true ;
#if 0
resetUpdateCallbackActivity ( ALL_OBJECTS ) ;
# endif
_activeOperators . setPause ( _pause ) ;
}
return true ;
}
else if ( ea . getKey ( ) = = ' o ' )
{
if ( _pause )
{
_pause = false ;
#if 0
resetUpdateCallbackActivity ( ALL_OBJECTS ) ;
# endif
_activeOperators . setPause ( _pause ) ;
}
return true ;
}
else if ( ea . getKey ( ) = = ' h ' )
{
_hold = true ;
return true ;
}
else if ( ea . getKey ( ) = = ' r ' )
{
#if 0
resetUpdateCallbacks ( ALL_OBJECTS ) ;
# endif
_activeOperators . reset ( ) ;
return true ;
}
/*
else if ( ea . getKey ( ) = = ' c ' )
{
_cursorOn = ! _cursorOn ;
for ( unsigned int i = 0 ; i < _viewer - > getCameraConfig ( ) - > getNumberOfCameras ( ) ; i + + )
{
Producer : : Camera * cam = _viewer - > getCameraConfig ( ) - > getCamera ( i ) ;
Producer : : RenderSurface * rs = cam - > getRenderSurface ( ) ;
rs - > useCursor ( _cursorOn ) ;
}
return true ;
}
*/
else if ( ea . getKey ( ) = = ' u ' )
{
updateAlpha ( true , false , ea . getX ( ) , ea . getY ( ) ) ;
return true ;
}
else if ( ea . getKey ( ) = = ' i ' )
{
updateAlpha ( false , true , ea . getX ( ) , ea . getY ( ) ) ;
return true ;
}
else if ( ea . getKey ( ) = = ' k ' )
{
updateLight ( ea . getX ( ) , ea . getY ( ) ) ;
return true ;
}
return false ;
}
case ( osgGA : : GUIEventAdapter : : KEYUP ) :
{
if ( ea . getKey ( ) = = ' h ' )
{
_hold = false ;
return true ;
}
return false ;
}
default :
return false ;
}
return false ;
}
void SlideEventHandler : : getUsage ( osg : : ApplicationUsage & usage ) const
{
usage . addKeyboardMouseBinding ( " a " , " Toggle on/off the automatic advancement for image to image " ) ;
usage . addKeyboardMouseBinding ( " n " , " Advance to next layer or slide " ) ;
usage . addKeyboardMouseBinding ( " p " , " Move to previous layer or slide " ) ;
}
unsigned int SlideEventHandler : : getNumSlides ( )
{
if ( _presentationSwitch . valid ( ) ) return _presentationSwitch - > getNumChildren ( ) ;
else return 0 ;
}
2009-05-02 15:50:37 +08:00
bool SlideEventHandler : : selectSlide ( int slideNum , int layerNum )
2009-04-28 19:57:51 +08:00
{
if ( ! _presentationSwitch ) return false ;
osg : : notify ( osg : : INFO ) < < " selectSlide( " < < slideNum < < " , " < < layerNum < < " ) " < < std : : endl ;
if ( slideNum = = LAST_POSITION & & _presentationSwitch - > getNumChildren ( ) > 0 )
{
slideNum = _presentationSwitch - > getNumChildren ( ) - 1 ;
}
2009-05-02 15:50:37 +08:00
if ( slideNum > = static_cast < int > ( _presentationSwitch - > getNumChildren ( ) ) ) return false ;
2009-04-28 19:57:51 +08:00
osg : : Timer_t tick = osg : : Timer : : instance ( ) - > tick ( ) ;
if ( _firstSlideOrLayerChange )
{
_firstSlideOrLayerChange = false ;
_tickAtFirstSlideOrLayerChange = tick ;
_tickAtLastSlideOrLayerChange = tick ;
}
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 ;
_tickAtLastSlideOrLayerChange = tick ;
// dectivate movies etc on current active slide.
bool newSlide = _activeSlide ! = slideNum ;
if ( newSlide )
{
if ( _releaseAndCompileOnEachNewSlide )
{
releaseSlide ( _activeSlide ) ;
}
}
_activeSlide = slideNum ;
_presentationSwitch - > setSingleChildOn ( _activeSlide ) ;
//osg::notify(osg::INFO)<<"Selected slide '"<<_presentationSwitch->getChild(_activeSlide)->getName()<<"'"<<std::endl;
FindNamedSwitchVisitor findSlide ( " Slide " ) ;
_presentationSwitch - > getChild ( _activeSlide ) - > accept ( findSlide ) ;
bool result = false ;
if ( findSlide . _switch )
{
//osg::notify(osg::INFO)<<"Found slide '"<<findSlide._switch->getName()<<"'"<<std::endl;
_slideSwitch = findSlide . _switch ;
result = selectLayer ( layerNum ) ;
}
else
{
//osg::notify(osg::INFO)<<"Not found slide"<<std::endl;
updateOperators ( ) ;
}
// refersh the viewer.
//_viewer->getKeySwitchMatrixManipulator()->setMinimumDistance(0.001);
_viewer - > getCameraManipulator ( ) - > setNode ( _slideSwitch . get ( ) ) ;
_viewer - > computeActiveCoordinateSystemNodePath ( ) ;
// resetUpdateCallbacks(ALL_OBJECTS);
bool _useSlideFilePaths = false ;
if ( _useSlideFilePaths )
{
// set up the file paths
FindFilePathDataVisitor ffpdv ;
_presentationSwitch - > accept ( ffpdv ) ;
}
if ( newSlide & & _releaseAndCompileOnEachNewSlide )
{
compileSlide ( slideNum ) ;
}
return result ;
}
2009-05-02 15:50:37 +08:00
bool SlideEventHandler : : selectLayer ( int layerNum )
2009-04-28 19:57:51 +08:00
{
if ( ! _slideSwitch ) return false ;
if ( layerNum = = LAST_POSITION & & _slideSwitch - > getNumChildren ( ) > 0 )
{
layerNum = _slideSwitch - > getNumChildren ( ) - 1 ;
}
2009-05-02 15:50:37 +08:00
if ( layerNum > = static_cast < int > ( _slideSwitch - > getNumChildren ( ) ) ) return false ;
2009-04-28 19:57:51 +08:00
_activeLayer = layerNum ;
_slideSwitch - > setSingleChildOn ( _activeLayer ) ;
updateOperators ( ) ;
osg : : notify ( osg : : INFO ) < < " Selected layer ' " < < _slideSwitch - > getChild ( _activeLayer ) - > getName ( ) < < " ' num= " < < _activeLayer < < std : : endl ;
return true ;
}
bool SlideEventHandler : : nextLayerOrSlide ( )
{
if ( nextLayer ( ) ) return true ;
else return nextSlide ( ) ;
}
bool SlideEventHandler : : previousLayerOrSlide ( )
{
if ( previousLayer ( ) ) return true ;
else return previousSlide ( ) ;
}
bool SlideEventHandler : : nextSlide ( )
{
2009-04-28 22:03:02 +08:00
LayerAttributes * la = _slideSwitch . valid ( ) ? dynamic_cast < LayerAttributes * > ( _slideSwitch - > getUserData ( ) ) : 0 ;
2009-04-28 19:57:51 +08:00
if ( la & & la - > requiresJump ( ) )
{
if ( la - > getRelativeJump ( ) )
{
int previousSlide = getActiveSlide ( ) ;
int previousLayer = getActiveLayer ( ) ;
int newSlide = previousSlide + la - > getSlideNum ( ) ;
int newLayer = previousLayer + la - > getLayerNum ( ) ;
if ( newLayer < 0 )
{
newLayer = 0 ;
}
return selectSlide ( newSlide , newLayer ) ;
}
else
{
return selectSlide ( la - > getSlideNum ( ) , la - > getLayerNum ( ) ) ;
}
}
if ( selectSlide ( _activeSlide + 1 ) ) return true ;
else if ( _loopPresentation ) return selectSlide ( 0 ) ;
else return false ;
}
bool SlideEventHandler : : previousSlide ( )
{
# if 1
// start position when doing previous slide set to top of slide
if ( _activeSlide > 0 ) return selectSlide ( _activeSlide - 1 ) ;
else if ( _loopPresentation & & _presentationSwitch . valid ( ) ) return selectSlide ( _presentationSwitch - > getNumChildren ( ) - 1 ) ;
else return false ;
# else
// start position when doing previous slide set to end of slide
if ( _activeSlide > 0 ) return selectSlide ( _activeSlide - 1 , LAST_POSITION ) ;
else if ( _loopPresentation & & _presentationSwitch . valid ( ) ) return selectSlide ( _presentationSwitch - > getNumChildren ( ) - 1 , LAST_POSITION ) ;
else return false ;
# endif
}
bool SlideEventHandler : : nextLayer ( )
{
2009-04-28 22:03:02 +08:00
LayerAttributes * la = ( _slideSwitch . valid ( ) & & _activeLayer > = 0 ) ? dynamic_cast < LayerAttributes * > ( _slideSwitch - > getChild ( _activeLayer ) - > getUserData ( ) ) : 0 ;
2009-04-28 19:57:51 +08:00
if ( la )
{
la - > callLeaveCallbacks ( _slideSwitch - > getChild ( _activeLayer ) ) ;
if ( la - > requiresJump ( ) )
{
if ( la - > getRelativeJump ( ) )
{
int previousSlide = getActiveSlide ( ) ;
int previousLayer = getActiveLayer ( ) ;
int newSlide = previousSlide + la - > getSlideNum ( ) ;
int newLayer = previousLayer + la - > getLayerNum ( ) ;
if ( newLayer < 0 )
{
newLayer = 0 ;
}
return selectSlide ( newSlide , newLayer ) ;
}
else
{
return selectSlide ( la - > getSlideNum ( ) , la - > getLayerNum ( ) ) ;
}
}
}
return selectLayer ( _activeLayer + 1 ) ;
}
bool SlideEventHandler : : previousLayer ( )
{
if ( _activeLayer > 0 ) return selectLayer ( _activeLayer - 1 ) ;
else return false ;
}
void SlideEventHandler : : updateOperators ( )
{
_activeOperators . collect ( _slideSwitch . get ( ) ) ;
_activeOperators . process ( ) ;
UpdateLightVisitor uav ( _viewer - > getCamera ( ) - > getViewMatrix ( ) , 0.0f , 0.0f ) ;
_viewer - > getSceneData ( ) - > accept ( uav ) ;
}
bool SlideEventHandler : : home ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & aa )
{
FindHomePositionVisitor fhpv ;
osg : : Node * node = _viewer - > getSceneData ( ) ;
if ( node ) node - > accept ( fhpv ) ;
if ( fhpv . _homePosition . valid ( ) )
{
osg : : notify ( osg : : INFO ) < < " Doing home for stored home position. " < < std : : endl ;
_viewer - > getCameraManipulator ( ) - > setAutoComputeHomePosition ( false ) ;
_viewer - > getCameraManipulator ( ) - > setHomePosition (
fhpv . _homePosition - > eye ,
fhpv . _homePosition - > center ,
fhpv . _homePosition - > up ) ;
}
else
{
_viewer - > getCameraManipulator ( ) - > setAutoComputeHomePosition ( true ) ;
}
_viewer - > getCameraManipulator ( ) - > home ( ea , aa ) ;
return true ;
}
bool SlideEventHandler : : home ( )
{
osg : : ref_ptr < osgGA : : GUIEventAdapter > ea = new osgGA : : GUIEventAdapter ;
ea - > setEventType ( osgGA : : GUIEventAdapter : : FRAME ) ;
ea - > setTime ( _viewer - > getEventQueue ( ) - > getTime ( ) ) ;
home ( * ea , * _viewer ) ;
return true ;
}
void SlideEventHandler : : updateAlpha ( bool modAlphaFunc , bool modMaterial , float x , float y )
{
osg : : notify ( osg : : INFO ) < < " updateAlpha( " < < x < < " , " < < y < < " ) " < < std : : endl ;
UpdateAlphaVisitor uav ( modAlphaFunc , modMaterial , x , y ) ;
if ( _presentationSwitch . valid ( ) ) _presentationSwitch - > accept ( uav ) ;
else if ( _viewer - > getSceneData ( ) ) _viewer - > getSceneData ( ) - > accept ( uav ) ;
}
void SlideEventHandler : : updateLight ( float x , float y )
{
osg : : notify ( osg : : INFO ) < < " updateLight( " < < x < < " , " < < y < < " ) " < < std : : endl ;
UpdateLightVisitor uav ( _viewer - > getCamera ( ) - > getViewMatrix ( ) , x , y ) ;
_viewer - > getSceneData ( ) - > accept ( uav ) ;
}
void SlideEventHandler : : compileSlide ( unsigned int slideNum )
{
if ( ! _compileSlideCallback )
{
_compileSlideCallback = new ss3d : : CompileSlideCallback ( ) ;
osgViewer : : Viewer : : Cameras cameras ;
_viewer - > getCameras ( cameras ) ;
for ( osgViewer : : Viewer : : Cameras : : iterator itr = cameras . begin ( ) ;
itr ! = cameras . end ( ) ;
+ + itr )
{
( * itr ) - > setPreDrawCallback ( _compileSlideCallback . get ( ) ) ;
}
}
_compileSlideCallback - > needCompile ( _presentationSwitch - > getChild ( slideNum ) ) ;
}
void SlideEventHandler : : releaseSlide ( unsigned int slideNum )
{
osgUtil : : GLObjectsVisitor globjVisitor ( osgUtil : : GLObjectsVisitor : : RELEASE_DISPLAY_LISTS |
osgUtil : : GLObjectsVisitor : : RELEASE_STATE_ATTRIBUTES ) ;
globjVisitor . setNodeMaskOverride ( 0xffffffff ) ;
_presentationSwitch - > getChild ( slideNum ) - > accept ( globjVisitor ) ;
}
2009-04-28 22:03:02 +08:00
void SlideEventHandler : : dispatchEvent ( const KeyPosition & keyPosition )
2009-04-28 19:57:51 +08:00
{
osg : : notify ( osg : : INFO ) < < " keyPosition._key " < < keyPosition . _key < < " " < < keyPosition . _x < < " " < < keyPosition . _y < < std : : endl ;
osgGA : : EventQueue * eq = _viewer - > getEventQueue ( ) ;
// reset the time of the last key press to ensure thatthe event is disgarded as a key repeat.
_timeLastKeyPresses = - 1.0 ;
if ( keyPosition . _x ! = FLT_MAX )
{
float xRescaled = eq - > getCurrentEventState ( ) - > getXmin ( ) + ( keyPosition . _x + 1.0f ) * 0.5f * ( eq - > getCurrentEventState ( ) - > getXmax ( ) - eq - > getCurrentEventState ( ) - > getXmin ( ) ) ;
eq - > getCurrentEventState ( ) - > setX ( xRescaled ) ;
}
if ( keyPosition . _y ! = FLT_MAX )
{
float yRescaled = eq - > getCurrentEventState ( ) - > getYmin ( ) + ( keyPosition . _y + 1.0f ) * 0.5f * ( eq - > getCurrentEventState ( ) - > getXmax ( ) - eq - > getCurrentEventState ( ) - > getYmin ( ) ) ;
eq - > getCurrentEventState ( ) - > setY ( yRescaled ) ;
}
eq - > keyPress ( keyPosition . _key ) ;
eq - > keyRelease ( keyPosition . _key ) ;
}