2 * Copyright (c) 2003-2009 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 package com.jme.input.util;
34 import java.util.HashMap;
37 import com.jme.input.InputHandler;
38 import com.jme.input.action.InputAction;
39 import com.jme.input.action.InputActionEvent;
40 import com.jme.intersection.PickData;
41 import com.jme.intersection.TrianglePickResults;
42 import com.jme.math.Ray;
43 import com.jme.math.Vector2f;
44 import com.jme.math.Vector3f;
45 import com.jme.scene.Geometry;
46 import com.jme.scene.Spatial;
47 import com.jme.system.DisplaySystem;
49 public class PickDevice {
50 private final Spatial root;
51 private final InputHandler inputHandler;
52 private final Vector2f mousePosition = new Vector2f();
53 private final Vector3f pickedScreenPos = new Vector3f();
54 private PickAction pickAction;
55 private MoveAction moveAction;
56 private Geometry picked;
57 private SyntheticButton pickedButton;
59 private Map<Spatial, SyntheticButton> buttons = new HashMap<Spatial, SyntheticButton>();
61 public PickDevice( Spatial root, InputHandler inputHandler ) {
63 this.inputHandler = new InputHandler();
64 inputHandler.addToAttachedHandlers( this.inputHandler );
66 pickAction = new PickAction();
67 this.inputHandler.addAction( pickAction, InputHandler.DEVICE_MOUSE, 0, InputHandler.AXIS_NONE, false );
69 moveAction = new MoveAction();
70 this.inputHandler.addAction( moveAction, InputHandler.DEVICE_MOUSE, InputHandler.BUTTON_NONE,
71 InputHandler.AXIS_ALL, false );
74 public SyntheticButton createButton( Spatial toPick ) {
75 SyntheticButton button = buttons.get( toPick );
76 if ( button == null ) {
77 button = new SyntheticButton( toPick.getName() );
78 buttons.put( toPick, button );
83 public SyntheticButton getPickedButton() {
87 private class PickAction extends InputAction {
88 private final Ray pickRay = new Ray();
89 private final TrianglePickResults pickResults = new TrianglePickResults();
91 public void performAction( InputActionEvent evt ) {
92 if ( evt.getTriggerPressed() ) {
93 DisplaySystem.getDisplaySystem().getWorldCoordinates( mousePosition, 0, pickRay.origin );
94 DisplaySystem.getDisplaySystem().getWorldCoordinates( mousePosition, 0.3f, pickRay.direction );
95 pickRay.direction.subtractLocal( pickRay.origin ).normalizeLocal();
98 pickResults.setCheckDistance( true );
99 root.findPick( pickRay, pickResults );
101 for ( int i = 0; i < pickResults.getNumber(); i++ ) {
102 PickData data = pickResults.getPickData( i );
103 if ( data.getTargetTris() != null && data.getTargetTris().size() > 0 ) {
104 Geometry geom = data.getTargetMesh();
105 Spatial target = geom;
106 while ( target != null ) {
107 SyntheticButton button = buttons.get( target );
108 if ( button != null ) {
109 button.trigger( 0, (char) 0, 0, evt.getTriggerPressed(), geom );
110 pickedButton = button;
113 //todo: for dragging:
114 // DisplaySystem.getDisplaySystem().getScreenCoordinates( geom.getWorldTranslation(), pickedScreenPos );
115 // DisplaySystem.getDisplaySystem().getWorldCoordinates( mousePosition, pickedScreenPos.z, pickedWorldOffset );
116 // pickedWorldOffset.subtractLocal( geom.getWorldTranslation() );
120 target = target.getParent();
125 if ( pickedButton != null ) {
126 pickedButton.trigger( 0, (char) 0, 0, evt.getTriggerPressed(), picked );
133 private class MoveAction extends InputAction {
134 public void performAction( InputActionEvent evt ) {
136 switch ( evt.getTriggerIndex() ) {
138 mousePosition.x = evt.getTriggerPosition() * DisplaySystem.getDisplaySystem().getWidth();
141 mousePosition.y = evt.getTriggerPosition() * DisplaySystem.getDisplaySystem().getHeight();
144 // move into z direction with the wheel
145 if ( evt.getTriggerDelta() > 0 ) {
146 pickedScreenPos.z += ( 1 - pickedScreenPos.z ) / 10;
148 pickedScreenPos.z = ( 10 * pickedScreenPos.z - 1 ) / 9;
153 //todo: implement dragging:
154 // if ( pickedButton != null ) {
155 // DisplaySystem.getDisplaySystem().getWorldCoordinates( mousePosition, pickedScreenPos.z, anchor );
156 // geom.getLocalTranslation().set( anchor.subtractLocal( pickedWorldOffset ) );
163 * $Log: PickDevice.java,v $
164 * Revision 1.1 2007/09/22 16:46:35 irrisor
165 * Minor: fixed problems with calculating distance after pick (updateWorldVectors not called twice anymore), fixed bouding problems with floating point precision (scene was culled if values were large)