OSDN Git Service

Set optimal mime types and executable settings.
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / input / util / PickDevice.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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.
31  */
32 package com.jme.input.util;
33
34 import java.util.HashMap;
35 import java.util.Map;
36
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;
48
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;
58
59     private Map<Spatial, SyntheticButton> buttons = new HashMap<Spatial, SyntheticButton>();
60
61     public PickDevice( Spatial root, InputHandler inputHandler ) {
62         this.root = root;
63         this.inputHandler = new InputHandler();
64         inputHandler.addToAttachedHandlers( this.inputHandler );
65
66         pickAction = new PickAction();
67         this.inputHandler.addAction( pickAction, InputHandler.DEVICE_MOUSE, 0, InputHandler.AXIS_NONE, false );
68
69         moveAction = new MoveAction();
70         this.inputHandler.addAction( moveAction, InputHandler.DEVICE_MOUSE, InputHandler.BUTTON_NONE,
71                 InputHandler.AXIS_ALL, false );
72     }
73
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 );
79         }
80         return button;
81     }
82
83     public SyntheticButton getPickedButton() {
84         return pickedButton;
85     }
86
87     private class PickAction extends InputAction {
88         private final Ray pickRay = new Ray();
89         private final TrianglePickResults pickResults = new TrianglePickResults();
90
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();
96
97                 pickResults.clear();
98                 pickResults.setCheckDistance( true );
99                 root.findPick( pickRay, pickResults );
100                 loopResults:
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;
111                                 picked = geom;
112
113                                 //todo: for dragging:
114 //                                DisplaySystem.getDisplaySystem().getScreenCoordinates( geom.getWorldTranslation(), pickedScreenPos );
115 //                                DisplaySystem.getDisplaySystem().getWorldCoordinates( mousePosition, pickedScreenPos.z, pickedWorldOffset );
116 //                                pickedWorldOffset.subtractLocal( geom.getWorldTranslation() );
117
118                                 break loopResults;
119                             }
120                             target = target.getParent();
121                         }
122                     }
123                 }
124             } else {
125                 if ( pickedButton != null ) {
126                     pickedButton.trigger( 0, (char) 0, 0, evt.getTriggerPressed(), picked );
127                     pickedButton = null;
128                 }
129             }
130         }
131     }
132
133     private class MoveAction extends InputAction {
134         public void performAction( InputActionEvent evt ) {
135
136             switch ( evt.getTriggerIndex() ) {
137                 case 0:
138                     mousePosition.x = evt.getTriggerPosition() * DisplaySystem.getDisplaySystem().getWidth();
139                     break;
140                 case 1:
141                     mousePosition.y = evt.getTriggerPosition() * DisplaySystem.getDisplaySystem().getHeight();
142                     break;
143                 case 2:
144                     // move into z direction with the wheel
145                     if ( evt.getTriggerDelta() > 0 ) {
146                         pickedScreenPos.z += ( 1 - pickedScreenPos.z ) / 10;
147                     } else {
148                         pickedScreenPos.z = ( 10 * pickedScreenPos.z - 1 ) / 9;
149                     }
150                     break;
151             }
152
153             //todo: implement dragging:
154 //            if ( pickedButton != null ) {
155 //                DisplaySystem.getDisplaySystem().getWorldCoordinates( mousePosition, pickedScreenPos.z, anchor );
156 //                geom.getLocalTranslation().set( anchor.subtractLocal( pickedWorldOffset ) );
157 //            }
158         }
159     }
160 }
161
162 /*
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)
166  *
167  */
168