package cz.cuni.jagrlib.testing;
import cz.cuni.jagrlib.*;
import cz.cuni.jagrlib.iface.Trigger;
import cz.cuni.jagrlib.reg.*;
/**
* Computes 3D-to-2D transformation matrix from interactive mouse/keyboard events.
*
* @version 0.24 $Rev: 183 $ $Date: 2006-02-08 01:24:54 +0100 (st, 08 II 2006) $ $Author: pepca $
* @since 0.24
* @see InteractiveProjection.java
*/
public class InteractiveProjection extends DefaultInputListener
{
//==========================================================================
// Data:
/** Zoom coefficient for one mouse-wheel "tick" minus 1.0d. */
public static final double WHEEL_ZOOM = 0.03d;
/** Actual window width in pixels. */
protected int width = 0;
/** Actual window height in pixels. */
protected int height = 0;
/** Actual projection matrix. */
protected TrMatrix proj = new TrMatrix( 4, 3 );
protected double rotZ = 0.0d;
protected double rotX = 0.0d;
/** Actual result zoom factor. */
protected double zoom = 1.0d;
/** Zoom factor produces by the mouse-wheel. */
protected double wheelZoom = 1.0d;
/** Mouse-move processing is switched on? */
protected boolean live = false;
/** Actual translation component. */
protected double[] transl = { 0.0d, 0.0d, 0.0d };
//==========================================================================
// Support:
/** Assembles the projection matrix and triggers the "redraw" action. */
protected void updateMatrix ()
{
proj.identity( 4, 3 );
proj.rotateAxis3D( 2, rotZ, null );
proj.rotateAxis3D( 0, rotX + 0.5d * Math.PI, null );
proj.scale3D( null, zoom * wheelZoom, null );
proj.translate3D( transl, null );
Trigger t = (Trigger)getInterface( PL_OUTPUT, IFACE+"Trigger" );
if ( t != null ) t.fire( 0 );
}
//==========================================================================
// Interface InputListener:
/**
* Change the window shape.
*
* @param width Horizontal window size in pixels.
* @param height Vertical window size in pixels.
*/
@Override
public void setWindowSize ( int width, int height )
{
this.width = width;
this.height = height;
transl[0] = 0.5d * width;
transl[1] = 0.5d * height;
zoom = Math.min( transl[0], transl[1] );
updateMatrix();
}
/**
* Mouse button was pressed/released.
*
* @param when System time in milliseconds.
* @param x Horizontal screen position in pixels.
* @param y Vertical screen position in pixels.
* @param button Button number (0, 1, etc.).
* @param press Was it press or release?
* @param flags Input system status (key shifts/alts, ..).
*/
@Override
public void mouseButton ( long when, int x, int y, int button, boolean press, int flags )
{
if ( button != 1 || press ) return;
live = !live;
}
/**
* Mouse pointer was moved.
*
* @param when System time in milliseconds.
* @param x Horizontal screen position in pixels.
* @param y Vertical screen position in pixels.
* @param flags Input system status (key shifts/alts, ..).
*/
@Override
public void mouseMove ( long when, int x, int y, int flags )
{
if ( !live ) return;
rotZ = ((double)x / width - 0.5d) * 2.0d * Math.PI;
rotX = -((double)y / width - 0.5d) * 2.0d * Math.PI;
updateMatrix();
}
/**
* Mouse wheel was rotated.
*
* @param when System time in milliseconds.
* @param x Horizontal screen position in pixels.
* @param y Vertical screen position in pixels.
* @param wheel Wheel number (0, 1, etc.).
* @param amount Rotation angle (positive number means down - or towards the user).
* @param flags Input system status (key shifts/alts, ..).
*/
@Override
public void mouseWheel ( long when, int x, int y, int wheel, int amount, int flags )
{
if ( amount == 0 ) return;
wheelZoom *= 1.0d + WHEEL_ZOOM * amount;
updateMatrix();
}
//==========================================================================
// Interface Property:
public final static String MATRIX = "Matrix";
/**
* Sets the given property.
*
* @param key Key string.
* @param value The new value.
*/
public void set ( String key, Object value )
{
if ( key == null || value == null ) return;
// MATRIX:
if ( key.compareTo(MATRIX) == 0 )
{
if ( value != null && value instanceof TrMatrix )
proj = (TrMatrix)value;
return;
}
}
/**
* Gets the given property.
*
* @param key Key string.
* @return The actual value or null
.
*/
public Object get ( String key )
{
if ( key == null )
return null;
if ( key.compareTo(MATRIX) == 0 )
return proj;
return null;
}
//==========================================================================
// Module registration:
/** Object name. */
private final static String NAME = "InteractiveProjection";
/** Object template identifier. */
protected final static String TEMPLATE_NAME = "InputListenerToTrigger";
/** Object description. */
private final static String DESCRIPTION = "Computes projection matrix from interactive mouse events.";
/** Object category. */
protected final static String CATEGORY = C_3D + ".projection";
/**
* General-purpose registration routine.
* Sets all plugs, strings, etc. to the given Template.
*/
public static int setTemplate ( Template t, int ord )
{
if ( t != null && ord <= 0 )
{
t.setRegStrings( NAME, TEMPLATE_NAME, CATEGORY, DESCRIPTION );
// Plugs:
t.newInputPlug( PL_INPUT, IFACE+"InputListener" );
t.newOptOutputPlug( PL_OUTPUT, IFACE+"Trigger" );
// Property:
t.propBegin( MATRIX, TYPE_OBJECT, "Projection matrix", false );
t.propEnd();
}
return 1;
}
/**
* Static registration instance for this class.
* Automatically initialized in class-loading time.
*/
public static final RegPiece reg;
static
{
reg = new RegPiece();
setTemplate( reg, 0 );
}
}