From Jan Peciva, additional comments, and standarisation of throw and handling of mouse wheel.

This commit is contained in:
Robert Osfield
2010-06-14 15:20:47 +00:00
parent 7f7cc83f3f
commit da60a3c615
9 changed files with 207 additions and 59 deletions

View File

@@ -37,7 +37,7 @@ FirstPersonManipulator::FirstPersonManipulator( int flags )
setAcceleration( 0.25, true );
setMaxVelocity( 0.25, true );
setWheelMovement( 0.05, true );
if( _flags & SET_CENTER_ON_WHEEL_UP )
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
setAnimationTime( 0.2 );
}
@@ -233,50 +233,62 @@ void FirstPersonManipulator::init( const GUIEventAdapter& ea, GUIActionAdapter&
// doc in parent
bool FirstPersonManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAdapter& us )
{
switch( ea.getScrollingMotion() ) {
osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion();
// mouse scroll up event
case GUIEventAdapter::SCROLL_UP: {
// handle centering
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
{
if( _flags & SET_CENTER_ON_WHEEL_UP ) {
if( sm == GUIEventAdapter::SCROLL_DOWN && _wheelMovement > 0. ||
sm == GUIEventAdapter::SCROLL_UP && _wheelMovement < 0. )
{
// stop thrown animation
_thrown = false;
if( getAnimationTime() <= 0. )
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
else {
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
}
}
}
}
// move forward
moveForward( isAnimating() ? dynamic_cast< FirstPersonAnimationData* >( _animationData.get() )->_targetRot : _rotation,
_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
}
switch( sm ) {
// mouse scroll down event
case GUIEventAdapter::SCROLL_DOWN:
moveForward( -_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
_thrown = false;
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
// mouse scroll up event
case GUIEventAdapter::SCROLL_UP:
{
// move forward
moveForward( isAnimating() ? dynamic_cast< FirstPersonAnimationData* >( _animationData.get() )->_targetRot : _rotation,
-_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
}
// unhandled mouse scrolling motion
default:
return false;
}
// mouse scroll down event
case GUIEventAdapter::SCROLL_DOWN:
{
// move backward
moveForward( _wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
_thrown = false;
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
}
// unhandled mouse scrolling motion
default:
return false;
}
}

View File

@@ -114,6 +114,7 @@ bool FlightManipulator::handleKeyDown( const GUIEventAdapter& ea, GUIActionAdapt
}
/// General flight-style event handler
bool FlightManipulator::flightHandleEvent( const GUIEventAdapter& ea, GUIActionAdapter& us )
{
addMouseEvent( ea );

View File

@@ -36,7 +36,7 @@ OrbitManipulator::OrbitManipulator( int flags )
{
setMinimumDistance( 0.05, true );
setWheelZoomFactor( 0.1 );
if( _flags & SET_CENTER_ON_WHEEL_UP )
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
setAnimationTime( 0.2 );
}
@@ -148,34 +148,108 @@ void OrbitManipulator::getTransformation( osg::Vec3d& center, osg::Vec3d& eye, o
}
/** Sets the transformation by heading. Heading is given as an angle in radians giving a azimuth in xy plane.
Its meaning is similar to longitude used in cartography and navigation.
Positive number is going to the east direction.*/
void OrbitManipulator::setHeading( double azimuth )
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localUp = getUpVector( coordinateFrame );
Vec3d localRight = getSideVector( coordinateFrame );
Vec3d dir = Quat( getElevation(), localRight ) * Quat( azimuth, localUp ) * Vec3d( 0., -_distance, 0. );
setTransformation( _center, _center + dir, localUp );
}
/// Returns the heading in radians. \sa setHeading
double OrbitManipulator::getHeading() const
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localFront = getFrontVector( coordinateFrame );
Vec3d localRight = getSideVector( coordinateFrame );
Vec3d center, eye, tmp;
getTransformation( center, eye, tmp );
Plane frontPlane( localFront, center );
double frontDist = frontPlane.distance( eye );
Plane rightPlane( localRight, center );
double rightDist = rightPlane.distance( eye );
return atan2( rightDist, -frontDist );
}
/** Sets the transformation by elevation. Elevation is given as an angle in radians from xy plane.
Its meaning is similar to latitude used in cartography and navigation.
Positive number is going to the north direction, negative to the south.*/
void OrbitManipulator::setElevation( double elevation )
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localUp = getUpVector( coordinateFrame );
Vec3d localRight = getSideVector( coordinateFrame );
Vec3d dir = Quat( -elevation, localRight ) * Quat( getHeading(), localUp ) * Vec3d( 0., -_distance, 0. );
setTransformation( _center, _center + dir, localUp );
}
/// Returns the elevation in radians. \sa setElevation
double OrbitManipulator::getElevation() const
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localUp = getUpVector( coordinateFrame );
localUp.normalize();
Vec3d center, eye, tmp;
getTransformation( center, eye, tmp );
Plane plane( localUp, center );
double dist = plane.distance( eye );
return asin( -dist / (eye-center).length() );
}
// doc in parent
bool OrbitManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAdapter& us )
{
switch( ea.getScrollingMotion() )
osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion();
// handle centering
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
{
if( sm == GUIEventAdapter::SCROLL_DOWN && _wheelZoomFactor > 0. ||
sm == GUIEventAdapter::SCROLL_UP && _wheelZoomFactor < 0. )
{
if( getAnimationTime() <= 0. )
{
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
}
else
{
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
}
}
}
switch( sm )
{
// mouse scroll up event
case GUIEventAdapter::SCROLL_UP:
{
if( _flags & SET_CENTER_ON_WHEEL_UP )
{
if( getAnimationTime() <= 0. )
{
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
}
else
{
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
}
}
// perform zoom
zoomModel( -_wheelZoomFactor, true );
zoomModel( _wheelZoomFactor, true );
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
@@ -183,10 +257,13 @@ bool OrbitManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAda
// mouse scroll down event
case GUIEventAdapter::SCROLL_DOWN:
zoomModel( _wheelZoomFactor, true );
{
// perform zoom
zoomModel( -_wheelZoomFactor, true );
us.requestRedraw();
us.requestContinuousUpdate( false );
return true;
}
// unhandled mouse scrolling motion
default:
@@ -530,7 +607,8 @@ void OrbitManipulator::setTrackballSize( const double& size )
/** Set the mouse wheel zoom factor.
The amount of camera movement on each mouse wheel event
is computed as the current distance to the center multiplied by this factor.
For example, value of 0.1 will short distance to center by 10% on each wheel up event.*/
For example, value of 0.1 will short distance to center by 10% on each wheel up event.
Use negative value for reverse mouse wheel direction.*/
void OrbitManipulator::setWheelZoomFactor( double wheelZoomFactor )
{
_wheelZoomFactor = wheelZoomFactor;

View File

@@ -25,16 +25,16 @@ using namespace osgUtil;
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& eye, const osg::Quat& rotation );
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& eye, const osg::Quat& rotation )
Sets manipulator by eye position and eye orientation.*/
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& center, const osg::Vec3d& eye, const osg::Vec3d& up );
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& center, const osg::Vec3d& eye, const osg::Vec3d& up )
Sets manipulator by focal center, eye position, and up vector.*/
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation );
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation )
Gets manipulator's eye position and eye orientation.*/
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& center, osg::Vec3d& eye, osg::Vec3d& up );
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& center, osg::Vec3d& eye, osg::Vec3d& up )
Gets manipulator's focal center, eye position, and up vector.*/
@@ -51,6 +51,7 @@ int StandardManipulator::allocateRelativeFlag()
StandardManipulator::StandardManipulator( int flags )
: inherited(),
_thrown( false ),
_allowThrow( true ),
_mouseCenterX(0.0f), _mouseCenterY(0.0f),
_delta_frame_time(0.01), _last_frame_time(0.0),
_modelSize( 0. ),
@@ -65,6 +66,7 @@ StandardManipulator::StandardManipulator( int flags )
StandardManipulator::StandardManipulator( const StandardManipulator& uim, const CopyOp& copyOp )
: inherited( uim, copyOp ),
_thrown( uim._thrown ),
_allowThrow( uim._allowThrow ),
_mouseCenterX(0.0f), _mouseCenterY(0.0f),
_ga_t1( dynamic_cast< GUIEventAdapter* >( copyOp( uim._ga_t1.get() ) ) ),
_ga_t0( dynamic_cast< GUIEventAdapter* >( copyOp( uim._ga_t0.get() ) ) ),
@@ -364,7 +366,7 @@ bool StandardManipulator::handleMouseRelease( const GUIEventAdapter& ea, GUIActi
if( isMouseMoving() )
{
if( performMovement() )
if( performMovement() && _allowThrow )
{
us.requestRedraw();
us.requestContinuousUpdate( true );
@@ -583,6 +585,15 @@ bool StandardManipulator::isMouseMoving() const
}
/** Set the 'allow throw' flag. If it is set to true (default), releasing the mouse button
while moving the mouse results in a throw. If manipulator was thrown, it continues spinning
although no mouse button is down at the moment.*/
void StandardManipulator::setAllowThrow( bool allowThrow )
{
_allowThrow = allowThrow;
}
/** Returns the scale that should be applied on animation of "thrown" manipulator state
to avoid its dependency on varying frame rate.

View File

@@ -35,12 +35,16 @@ TerrainManipulator::TerrainManipulator( const TerrainManipulator& tm, const Copy
}
/** Sets the manipulator rotation mode. RotationMode is now deprecated by
osgGA::StandardManipulator::setVerticalAxisFixed() functionality,
that is used across StandardManipulator derived classes.*/
void TerrainManipulator::setRotationMode( TerrainManipulator::RotationMode mode )
{
setVerticalAxisFixed( mode == ELEVATION_AZIM );
}
/** Returns the manipulator rotation mode.*/
TerrainManipulator::RotationMode TerrainManipulator::getRotationMode() const
{
return getVerticalAxisFixed() ? ELEVATION_AZIM : ELEVATION_AZIM_ROLL;