/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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 GNU
* Lesser General Public License for more details.
*/
package org.geotools.renderer3d.navigationgestures;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import org.geotools.renderer3d.utils.CursorChanger;
import javax.swing.event.MouseInputAdapter;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
/**
* Contains common functionality for navigationGestureListeners.
*
* @author Hans H�ggstr�m
*/
public abstract class AbstractNavigationGesture
extends MouseInputAdapter
implements NavigationGesture
{
//======================================================================
// Private Fields
private CameraAccessor myCameraAccessor = null;
private CursorChanger myCursorChanger;
private Robot myRobot;
private Component myComponent;
//======================================================================
// Non-Private Fields
private final float mySensitivity;
//======================================================================
// Public Methods
//----------------------------------------------------------------------
// MouseWheelListener Implementation
public void mouseWheelMoved( final MouseWheelEvent e )
{
// Override if needed
}
//----------------------------------------------------------------------
// NavigationGesture Implementation
public void init( final Component component,
final CursorChanger cursorChanger,
final CameraAccessor cameraAccessor )
{
setComponent( component );
setCursorChanger( cursorChanger );
setCameraAccessor( cameraAccessor );
}
public void deInit()
{
setComponent( null );
setCursorChanger( null );
setCameraAccessor( null );
}
//----------------------------------------------------------------------
// Other Public Methods
/**
* @return a scaling factor to apply to the gesture.
*/
public final float getSensitivity()
{
return mySensitivity;
}
//======================================================================
// Protected Methods
//----------------------------------------------------------------------
// Protected Constructors
protected AbstractNavigationGesture( final float sensitivity )
{
try
{
myRobot = new Robot();
}
catch ( AWTException e )
{
e.printStackTrace();
}
mySensitivity = sensitivity;
}
/**
* Moves the mouse position to the specified canvas coordinates
*/
protected final void setMousePos( int x, int y )
{
final Point locationOnScreen = myComponent.getLocationOnScreen();
myRobot.mouseMove( locationOnScreen.x + x, locationOnScreen.y + y );
}
/**
* @return an interface that can be used to change the mouse cursor on the 3D canvas we are rendering to (or hide it).
*/
protected final CursorChanger getCursorChanger()
{
return myCursorChanger;
}
private void setCursorChanger( final CursorChanger cursorChanger )
{
if ( cursorChanger == null && myCursorChanger != null )
{
myCursorChanger.resetCursor( this );
}
myCursorChanger = cursorChanger;
}
/**
* @return the camera that has been assigned to this navigation gesture listener, or null if no camera has yet been assigned.
*/
protected final Camera getCamera()
{
if ( myCameraAccessor != null )
{
return myCameraAccessor.getCamera();
}
else
{
return null;
}
}
/**
* @return a multiplication factor calculated from the altitude, used to adjust the move and pan operations.
*/
protected final float getAltitudeFactor()
{
final Camera camera = getCamera();
if ( camera != null )
{
final float altitude = getAltitudeAt( camera.getLocation() );
// Less movement lower, more higher. Use a non linear function (square root) of the altitude.
return (float) ( 0.4 * Math.sqrt( Math.abs( altitude ) ) + 0.01f );
}
else
{
return 1;
}
}
protected boolean isMouseButtonPressed( final MouseEvent e, final int buttonDownMask )
{
return ( e.getModifiersEx() & buttonDownMask ) != 0;
}
//======================================================================
// Private Methods
/**
* REFACTOR: Move to some terrain or map class and make public.
*
* @param location A location to calculate the altitude of.
*
* @return the altitude of the specified location above the ground. The accuracy can be calculated relative to the altitude,
* if the location is closer to the ground, higher accuracy is used than if it is further from the ground.
*/
private float getAltitudeAt( final Vector3f location )
{
return location.z - getTerrainHeightAt( location );
}
/**
* REFACTOR: Move to some terrain or map class and make public.
*
* @param location some location in the world. Usually only the x and y values are used, z is ignored.
* The z value can be used to determine the accuracy to calculate the terrain height at. If the location is far above (or below) the ground,
* less accuracy is needed, while if it is close to the ground, greater accuracy is needed.
*
* @return the terrain height at the specified location.
*/
private float getTerrainHeightAt( final Vector3f location )
{
// TODO: Get terrain height at the specified location
return (float) 0;
}
private void setComponent( final Component component )
{
if ( myComponent != null )
{
myComponent.removeMouseMotionListener( this );
myComponent.removeMouseListener( this );
myComponent.removeMouseWheelListener( this );
}
myComponent = component;
component.addMouseMotionListener( this );
component.addMouseListener( this );
component.addMouseWheelListener( this );
}
private void setCameraAccessor( final CameraAccessor cameraAccessor )
{
myCameraAccessor = cameraAccessor;
}
}