void MouseDialogNavigationTool::startPanning(void)
	{
	/* Calculate initial motion position: */
	motionStart=calcScreenPos();
	
	preScale=getNavigationTransformation();
	}
示例#2
0
void MapEntity::SetMapTilePosition(Vector2 tilePos, Vector2 scrollOffset, float tileSize)
{
	m_mapTilePos = tilePos;
	m_mapPos = Vector2(tilePos.x * tileSize, tilePos.y * tileSize);

	updateScreenPos(calcScreenPos(scrollOffset));
}
示例#3
0
void MouseNavigationTool::startPanning(void)
	{
	/* Calculate initial motion position: */
	motionStart=calcScreenPos();
	
	preScale=getNavigationTransformation();
	
	/* Go to panning mode: */
	navigationMode=PANNING;
	}
void MouseDialogNavigationTool::startScaling(void)
	{
	/* Calculate the scaling center: */
	screenCenter=calcScreenCenter();
	
	/* Calculate initial motion position: */
	motionStart=calcScreenPos();
	
	preScale=NavTrackerState::translateFromOriginTo(screenCenter);
	postScale=NavTrackerState::translateToOriginFrom(screenCenter);
	postScale*=getNavigationTransformation();
	}
void MouseDialogNavigationTool::startDollying(void)
	{
	/* Calculate the dollying direction: */
	if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0)
		dollyDirection=mouseAdapter->getWindow()->getViewer()->getHeadPosition()-calcScreenCenter();
	else
		dollyDirection=getMainViewer()->getHeadPosition()-calcScreenCenter();
	dollyDirection.normalize();
	
	/* Calculate initial motion position: */
	motionStart=calcScreenPos();
	
	preScale=getNavigationTransformation();
	}
void MouseDialogNavigationTool::startRotating(void)
	{
	/* Calculate the rotation center: */
	screenCenter=calcScreenCenter();
	
	/* Calculate initial rotation position: */
	lastRotationPos=calcScreenPos();
	
	/* Calculate the rotation offset vector: */
	rotateOffset=getMainScreen()->getScreenTransformation().transform(Vector(0,0,factory->rotatePlaneOffset));
	
	preScale=NavTrackerState::translateFromOriginTo(screenCenter);
	rotation=NavTrackerState::identity;
	postScale=NavTrackerState::translateToOriginFrom(screenCenter);
	postScale*=getNavigationTransformation();
	}
void MouseDialogNavigationTool::startRotating(void)
	{
	/* Calculate the rotation center: */
	screenCenter=calcScreenCenter();
	
	/* Calculate initial rotation position: */
	lastRotationPos=calcScreenPos();
	
	/* Get the transformation of the screen currently containing the input device: */
	Scalar viewport[4];
	ONTransform screenT=getMouseScreenTransform(mouseAdapter,viewport);
	
	/* Calculate the rotation offset vector: */
	rotateOffset=screenT.transform(Vector(0,0,factory->rotatePlaneOffset));
	
	preScale=NavTrackerState::translateFromOriginTo(screenCenter);
	rotation=NavTrackerState::identity;
	postScale=NavTrackerState::translateToOriginFrom(screenCenter);
	postScale*=getNavigationTransformation();
	}
示例#8
0
void MapEntity::SetMapPosition(Vector2 pos, Vector2 scrollOffset, float tileSize)
{
	static const float S_DEGREE_OF_ACCURACY = 0.001f; // Degree of accuracy
	
	float mapTileX = pos.x / tileSize;
	float mapTileY = pos.y / tileSize;
	m_mapPos = pos;
	m_mapTilePos = Vector2(floor(mapTileX), floor(mapTileY));
	float ceilTileX = ceil(mapTileX);
	float ceilTileY = ceil(mapTileY);
	if (mapTileX + S_DEGREE_OF_ACCURACY > ceilTileX)
	{
		m_mapTilePos.x = ceilTileX;
		m_mapPos.x = ceilTileX * tileSize + S_DEGREE_OF_ACCURACY;
	}
	if (mapTileY + S_DEGREE_OF_ACCURACY > ceilTileY)
	{
		m_mapTilePos.y = ceilTileY;
		m_mapPos.y = ceilTileY * tileSize + S_DEGREE_OF_ACCURACY;
	}

	updateScreenPos(calcScreenPos(scrollOffset));
}
示例#9
0
void MouseNavigationTool::frame(void)
	{
	/* Update the current mouse position: */
	Point newCurrentPos=calcScreenPos();
	if(currentPos!=newCurrentPos)
		{
		currentPos=calcScreenPos();
		lastMoveTime=getApplicationTime();
		}
	if(factory->interactWithWidgets)
		{
		/* Update the GUI interactor: */
		GUIInteractor::updateRay();
		GUIInteractor::move();
		}
	
	/* Act depending on this tool's current state: */
	switch(navigationMode)
		{
		case ROTATING:
			{
			/* Calculate the rotation position: */
			Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
			
			/* Calculate mouse displacement vector: */
			Point rotationPos=currentPos;
			Vector delta=rotationPos-lastRotationPos;
			lastRotationPos=rotationPos;
			
			/* Calculate incremental rotation: */
			Vector axis=Geometry::cross(offset,delta);
			Scalar angle=Geometry::mag(delta)/factory->rotateFactor;
			if(angle!=Scalar(0))
				rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateAxis(axis,angle)));
			
			NavTrackerState t=preScale;
			t*=rotation;
			t*=postScale;
			setNavigationTransformation(t);
			break;
			}
		
		case SPINNING:
			{
			/* Calculate incremental rotation: */
			rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(spinAngularVelocity*getFrameTime())));
			
			NavTrackerState t=preScale;
			t*=rotation;
			t*=postScale;
			setNavigationTransformation(t);
			
			scheduleUpdate(getApplicationTime()+1.0/125.0);
			
			break;
			}
		
		case PANNING:
			{
			/* Update the navigation transformation: */
			NavTrackerState t=NavTrackerState::translate(currentPos-motionStart);
			t*=preScale;
			setNavigationTransformation(t);
			break;
			}
		
		case DOLLYING:
			{
			/* Calculate the current dollying direction: */
			Scalar viewport[4];
			ONTransform screenT=getMouseScreenTransform(mouseAdapter,viewport);
			Vector dollyingDirection=screenT.transform(factory->screenDollyingDirection);
			
			/* Update the navigation transformation: */
			Scalar dollyDist=((currentPos-motionStart)*dollyingDirection)/factory->dollyFactor;
			NavTrackerState t=NavTrackerState::translate(dollyDirection*dollyDist);
			t*=preScale;
			setNavigationTransformation(t);
			break;
			}
		
		case SCALING:
			{
			/* Calculate the current scaling direction: */
			Scalar viewport[4];
			ONTransform screenT=getMouseScreenTransform(mouseAdapter,viewport);
			Vector scalingDirection=screenT.transform(factory->screenScalingDirection);
			
			/* Update the navigation transformation: */
			Scalar scale=((currentPos-motionStart)*scalingDirection)/factory->scaleFactor;
			NavTrackerState t=preScale;
			t*=NavTrackerState::scale(Math::exp(scale));
			t*=postScale;
			setNavigationTransformation(t);
			break;
			}
		
		case DOLLYING_WHEEL:
			{
			/* Update the navigation transformation: */
			Scalar scale=currentValue;
			currentWheelScale+=factory->wheelDollyFactor*scale;
			NavTrackerState t=NavTrackerState::translate(dollyDirection*currentWheelScale);
			t*=preScale;
			setNavigationTransformation(t);
			break;
			}
		
		case SCALING_WHEEL:
			{
			/* Update the navigation transformation: */
			Scalar scale=currentValue;
			currentWheelScale*=Math::pow(factory->wheelScaleFactor,scale);
			NavTrackerState t=preScale;
			t*=NavTrackerState::scale(currentWheelScale);
			t*=postScale;
			setNavigationTransformation(t);
			break;
			}
		
		default:
			;
		}
	}
示例#10
0
void MouseNavigationTool::buttonCallback(int buttonSlotIndex,InputDevice::ButtonCallbackData* cbData)
	{
	/* Process based on which button was pressed: */
	switch(buttonSlotIndex)
		{
		case 0:
			if(cbData->newButtonState) // Button has just been pressed
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case IDLE:
					case SPINNING:
						if(factory->interactWithWidgets)
							{
							/* Check if the GUI interactor accepts the event: */
							GUIInteractor::updateRay();
							if(GUIInteractor::buttonDown(false))
								{
								/* Deactivate this tool if it is spinning: */
								if(navigationMode==SPINNING)
									deactivate();
								
								/* Go to widget interaction mode: */
								navigationMode=WIDGETING;
								}
							else
								{
								/* Try activating this tool: */
								if(navigationMode==SPINNING||activate())
									startRotating();
								}
							}
						else
							{
							/* Try activating this tool: */
							if(navigationMode==SPINNING||activate())
								startRotating();
							}
						break;
					
					case PANNING:
						if(dolly)
							startDollying();
						else
							startScaling();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			else // Button has just been released
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case WIDGETING:
						{
						if(GUIInteractor::isActive())
							{
							/* Deliver the event: */
							GUIInteractor::buttonUp();
							}
						
						/* Deactivate this tool: */
						navigationMode=IDLE;
						break;
						}
					
					case ROTATING:
						{
						/* Check if the input device is still moving: */
						Point currentPos=calcScreenPos();
						Vector delta=currentPos-lastRotationPos;
						if(Geometry::mag(delta)>factory->spinThreshold)
							{
							/* Calculate spinning angular velocity: */
							Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
							Vector axis=Geometry::cross(offset,delta);
							Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*(getApplicationTime()-lastMoveTime));
							spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag());
							
							/* Go to spinning mode: */
							navigationMode=SPINNING;
							}
						else
							{
							/* Deactivate this tool: */
							deactivate();
							
							/* Go to idle mode: */
							navigationMode=IDLE;
							}
						break;
						}
					
					case DOLLYING:
					case SCALING:
						startPanning();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			break;
		
		case 1:
			if(cbData->newButtonState) // Button has just been pressed
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case IDLE:
					case SPINNING:
						/* Try activating this tool: */
						if(navigationMode==SPINNING||activate())
							startPanning();
						break;
					
					case ROTATING:
						if(dolly)
							startDollying();
						else
							startScaling();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			else // Button has just been released
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case PANNING:
						/* Deactivate this tool: */
						deactivate();
						
						/* Go to idle mode: */
						navigationMode=IDLE;
						break;
					
					case DOLLYING:
					case SCALING:
						startRotating();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			break;
		
		case 2:
			/* Set the dolly flag: */
			dolly=cbData->newButtonState;
			if(factory->invertDolly)
				dolly=!dolly;
			if(dolly) // Dollying has just been enabled
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case SCALING:
						startDollying();
						break;
					
					default:
						/* Nothing to do */
						break;
					}
				}
			else
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case DOLLYING:
						startScaling();
						break;
					
					default:
						/* Nothing to do */
						break;
					}
				}
			break;
		}
	}
void MouseDialogNavigationTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		bool takeEvent=true;
		if(factory->interactWithWidgets)
			{
			/* Check if the GUI interactor accepts the event: */
			GUIInteractor::updateRay();
			if(GUIInteractor::buttonDown(false))
				{
				/* Deactivate this tool if it is spinning: */
				if(spinning)
					deactivate();
				spinning=false;
				
				/* Disable navigation: */
				takeEvent=false;
				}
			}
		
		if(takeEvent)
			{
			/* Deactivate spinning: */
			spinning=false;
			
			/* Start navigating according to the current navigation mode: */
			switch(navigationMode)
				{
				case ROTATING:
					if(activate())
						startRotating();
					break;
				
				case PANNING:
					if(activate())
						startPanning();
					break;
				
				case DOLLYING:
					if(activate())
						startDollying();
					break;
				
				case SCALING:
					if(activate())
						startScaling();
					break;
				}
			}
		}
	else // Button has just been released
		{
		if(GUIInteractor::isActive())
			{
			/* Deliver the event: */
			GUIInteractor::buttonUp();
			}
		else
			{
			/* Check for spinning if currently in rotating mode: */
			if(navigationMode==ROTATING)
				{
				/* Check if the input device is still moving: */
				Point currentPos=calcScreenPos();
				Vector delta=currentPos-lastRotationPos;
				if(Geometry::mag(delta)>factory->spinThreshold)
					{
					/* Calculate spinning angular velocity: */
					Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
					Vector axis=Geometry::cross(offset,delta);
					Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*(getApplicationTime()-lastMoveTime));
					spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag());
					
					/* Enable spinning: */
					spinning=true;
					}
				else
					{
					/* Deactivate the tool: */
					deactivate();
					}
				}
			else
				{
				/* Deactivate the tool: */
				deactivate();
				}
			}
		}
	}
示例#12
0
void MouseNavigationTool::frame(void)
{
    /* Update the current mouse position: */
    currentPos=calcScreenPos();

    /* Act depending on this tool's current state: */
    switch(navigationMode)
    {
    case IDLE:
        /* Do nothing */
        break;

    case WIDGETING:
    {
        /* Deliver the event: */
        GLMotif::Event event(true);
        event.setWorldLocation(calcSelectionRay());
        getWidgetManager()->pointerMotion(event);

        if(draggedWidget!=0)
        {
            /* Update the dragged widget's transformation: */
            NavTrackerState current=NavTrackerState::translateFromOriginTo(calcScreenPos());
            current*=preScale;
            getWidgetManager()->setPrimaryWidgetTransformation(draggedWidget,GLMotif::WidgetManager::Transformation(current));
        }
        break;
    }

    case ROTATING:
    {
        /* Calculate the rotation position: */
        Vector offset=(lastRotationPos-screenCenter)+rotateOffset;

        /* Calculate mouse displacement vector: */
        Point rotationPos=currentPos;
        Vector delta=rotationPos-lastRotationPos;
        lastRotationPos=rotationPos;

        /* Calculate incremental rotation: */
        Vector axis=Geometry::cross(offset,delta);
        Scalar angle=Geometry::mag(delta)/factory->rotateFactor;
        if(angle!=Scalar(0))
            rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateAxis(axis,angle)));

        NavTrackerState t=preScale;
        t*=rotation;
        t*=postScale;
        setNavigationTransformation(t);
        break;
    }

    case SPINNING:
    {
        /* Calculate incremental rotation: */
        rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(spinAngularVelocity*getCurrentFrameTime())));

        NavTrackerState t=preScale;
        t*=rotation;
        t*=postScale;
        setNavigationTransformation(t);
        break;
    }

    case PANNING:
    {
        /* Update the navigation transformation: */
        NavTrackerState t=NavTrackerState::translate(currentPos-motionStart);
        t*=preScale;
        setNavigationTransformation(t);
        break;
    }

    case DOLLYING:
    {
        /* Calculate the current dollying direction: */
        Vector dollyingDirection;
        if(mouseAdapter!=0)
            dollyingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenDollyingDirection);
        else
            dollyingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenDollyingDirection);

        /* Update the navigation transformation: */
        Scalar dollyDist=((currentPos-motionStart)*dollyingDirection)/factory->dollyFactor;
        NavTrackerState t=NavTrackerState::translate(dollyDirection*dollyDist);
        t*=preScale;
        setNavigationTransformation(t);
        break;
    }

    case SCALING:
    {
        /* Calculate the current scaling direction: */
        Vector scalingDirection;
        if(mouseAdapter!=0)
            scalingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenScalingDirection);
        else
            scalingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenScalingDirection);

        /* Update the navigation transformation: */
        Scalar scale=((currentPos-motionStart)*scalingDirection)/factory->scaleFactor;
        NavTrackerState t=preScale;
        t*=NavTrackerState::scale(Math::exp(scale));
        t*=postScale;
        setNavigationTransformation(t);
        break;
    }

    case DOLLYING_WHEEL:
    {
        /* Update the navigation transformation: */
        Scalar scale=currentValue;
        currentWheelScale+=factory->wheelDollyFactor*scale;
        NavTrackerState t=NavTrackerState::translate(dollyDirection*currentWheelScale);
        t*=preScale;
        setNavigationTransformation(t);
        break;
    }

    case SCALING_WHEEL:
    {
        /* Update the navigation transformation: */
        Scalar scale=currentValue;
        currentWheelScale*=Math::pow(factory->wheelScaleFactor,scale);
        NavTrackerState t=preScale;
        t*=NavTrackerState::scale(currentWheelScale);
        t*=postScale;
        setNavigationTransformation(t);
        break;
    }
    }
}
示例#13
0
void MouseNavigationTool::buttonCallback(int,int buttonIndex,InputDevice::ButtonCallbackData* cbData)
{
    /* Process based on which button was pressed: */
    switch(buttonIndex)
    {
    case 0:
        if(cbData->newButtonState) // Button has just been pressed
        {
            /* Act depending on this tool's current state: */
            switch(navigationMode)
            {
            case IDLE:
            case SPINNING:
                if(factory->interactWithWidgets)
                {
                    /* Check if the mouse pointer is over a GLMotif widget: */
                    GLMotif::Event event(false);
                    event.setWorldLocation(calcSelectionRay());
                    if(getWidgetManager()->pointerButtonDown(event))
                    {
                        if(navigationMode==SPINNING)
                        {
                            /* Deactivate this tool: */
                            deactivate();
                        }

                        /* Go to widget interaction mode: */
                        navigationMode=WIDGETING;

                        /* Drag the entire root widget if the event's target widget is a title bar: */
                        if(dynamic_cast<GLMotif::TitleBar*>(event.getTargetWidget())!=0)
                        {
                            /* Start dragging: */
                            draggedWidget=event.getTargetWidget();

                            /* Calculate the dragging transformation: */
                            NavTrackerState initialTracker=NavTrackerState::translateFromOriginTo(calcScreenPos());
                            preScale=Geometry::invert(initialTracker);
                            GLMotif::WidgetManager::Transformation initialWidget=getWidgetManager()->calcWidgetTransformation(draggedWidget);
                            preScale*=NavTrackerState(initialWidget);
                        }
                        else
                            draggedWidget=0;
                    }
                    else
                    {
                        /* Try activating this tool: */
                        if(navigationMode==SPINNING||activate())
                            startRotating();
                    }
                }
                else
                {
                    /* Try activating this tool: */
                    if(navigationMode==SPINNING||activate())
                        startRotating();
                }
                break;

            case PANNING:
                if(dolly)
                    startDollying();
                else
                    startScaling();
                break;

            default:
                /* This shouldn't happen; just ignore the event */
                break;
            }
        }
        else // Button has just been released
        {
            /* Act depending on this tool's current state: */
            switch(navigationMode)
            {
            case WIDGETING:
            {
                /* Deliver the event: */
                GLMotif::Event event(true);
                event.setWorldLocation(calcSelectionRay());
                getWidgetManager()->pointerButtonUp(event);

                /* Deactivate this tool: */
                navigationMode=IDLE;
                draggedWidget=0;
                break;
            }

            case ROTATING:
            {
                /* Check if the input device is still moving: */
                Point currentPos=calcScreenPos();
                Vector delta=currentPos-lastRotationPos;
                if(Geometry::mag(delta)>factory->spinThreshold)
                {
                    /* Calculate spinning angular velocity: */
                    Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
                    Vector axis=Geometry::cross(offset,delta);
                    Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*getCurrentFrameTime());
                    spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag());

                    /* Go to spinning mode: */
                    navigationMode=SPINNING;
                }
                else
                {
                    /* Deactivate this tool: */
                    deactivate();

                    /* Go to idle mode: */
                    navigationMode=IDLE;
                }
                break;
            }

            case DOLLYING:
            case SCALING:
                startPanning();
                break;

            default:
                /* This shouldn't happen; just ignore the event */
                break;
            }
        }
        break;

    case 1:
        if(cbData->newButtonState) // Button has just been pressed
        {
            /* Act depending on this tool's current state: */
            switch(navigationMode)
            {
            case IDLE:
            case SPINNING:
                /* Try activating this tool: */
                if(navigationMode==SPINNING||activate())
                    startPanning();
                break;

            case ROTATING:
                if(dolly)
                    startDollying();
                else
                    startScaling();
                break;

            default:
                /* This shouldn't happen; just ignore the event */
                break;
            }
        }
        else // Button has just been released
        {
            /* Act depending on this tool's current state: */
            switch(navigationMode)
            {
            case PANNING:
                /* Deactivate this tool: */
                deactivate();

                /* Go to idle mode: */
                navigationMode=IDLE;
                break;

            case DOLLYING:
            case SCALING:
                startRotating();
                break;

            default:
                /* This shouldn't happen; just ignore the event */
                break;
            }
        }
        break;

    case 2:
        /* Set the dolly flag: */
        dolly=cbData->newButtonState;
        if(factory->invertDolly)
            dolly=!dolly;
        if(dolly) // Dollying has just been enabled
        {
            /* Act depending on this tool's current state: */
            switch(navigationMode)
            {
            case SCALING:
                startDollying();
                break;

            default:
                /* Nothing to do */
                break;
            }
        }
        else
        {
            /* Act depending on this tool's current state: */
            switch(navigationMode)
            {
            case DOLLYING:
                startScaling();
                break;

            default:
                /* Nothing to do */
                break;
            }
        }
        break;
    }
}
void MouseDialogNavigationTool::frame(void)
	{
	/* Update the current mouse position: */
	currentPos=calcScreenPos();
	
	/* Act depending on this tool's current state: */
	if(isActive())
		{
		if(spinning)
			{
			/* Calculate incremental rotation: */
			rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(spinAngularVelocity*getFrameTime())));
			
			NavTrackerState t=preScale;
			t*=rotation;
			t*=postScale;
			setNavigationTransformation(t);
			}
		else
			{
			switch(navigationMode)
				{
				case ROTATING:
					{
					/* Calculate the rotation position: */
					Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
					
					/* Calculate mouse displacement vector: */
					Point rotationPos=currentPos;
					Vector delta=rotationPos-lastRotationPos;
					lastRotationPos=rotationPos;
					
					/* Calculate incremental rotation: */
					Vector axis=Geometry::cross(offset,delta);
					Scalar angle=Geometry::mag(delta)/factory->rotateFactor;
					if(angle!=Scalar(0))
						rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateAxis(axis,angle)));
					
					NavTrackerState t=preScale;
					t*=rotation;
					t*=postScale;
					setNavigationTransformation(t);
					break;
					}
				
				case PANNING:
					{
					/* Update the navigation transformation: */
					NavTrackerState t=NavTrackerState::translate(currentPos-motionStart);
					t*=preScale;
					setNavigationTransformation(t);
					break;
					}
				
				case DOLLYING:
					{
					/* Calculate the current dollying direction: */
					Vector dollyingDirection;
					if(mouseAdapter!=0)
						dollyingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenDollyingDirection);
					else
						dollyingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenDollyingDirection);
					
					/* Update the navigation transformation: */
					Scalar dollyDist=((currentPos-motionStart)*dollyingDirection)/factory->dollyFactor;
					NavTrackerState t=NavTrackerState::translate(dollyDirection*dollyDist);
					t*=preScale;
					setNavigationTransformation(t);
					break;
					}
				
				case SCALING:
					{
					/* Calculate the current scaling direction: */
					Vector scalingDirection;
					if(mouseAdapter!=0)
						scalingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenScalingDirection);
					else
						scalingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenScalingDirection);
					
					/* Update the navigation transformation: */
					Scalar scale=((currentPos-motionStart)*scalingDirection)/factory->scaleFactor;
					NavTrackerState t=preScale;
					t*=NavTrackerState::scale(Math::exp(scale));
					t*=postScale;
					setNavigationTransformation(t);
					break;
					}
				}
			}
		}
	}
void MouseDialogNavigationTool::buttonCallback(int,int buttonIndex,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		/* Deactivate spinning: */
		spinning=false;
		
		/* Start navigating according to the current navigation mode: */
		switch(navigationMode)
			{
			case ROTATING:
				if(activate())
					startRotating();
				break;
			
			case PANNING:
				if(activate())
					startPanning();
				break;
			
			case DOLLYING:
				if(activate())
					startDollying();
				break;
			
			case SCALING:
				if(activate())
					startScaling();
				break;
			}
		}
	else // Button has just been released
		{
		/* Check for spinning if currently in rotating mode: */
		if(navigationMode==ROTATING)
			{
			/* Check if the input device is still moving: */
			Point currentPos=calcScreenPos();
			Vector delta=currentPos-lastRotationPos;
			if(Geometry::mag(delta)>factory->spinThreshold)
				{
				/* Calculate spinning angular velocity: */
				Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
				Vector axis=Geometry::cross(offset,delta);
				Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*getFrameTime());
				spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag());
				
				/* Enable spinning: */
				spinning=true;
				}
			else
				{
				/* Deactivate the tool: */
				deactivate();
				}
			}
		else
			{
			/* Deactivate the tool: */
			deactivate();
			}
		}
	}