aboutsummaryrefslogtreecommitdiff
path: root/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java')
-rw-r--r--engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java313
1 files changed, 313 insertions, 0 deletions
diff --git a/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java b/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java
new file mode 100644
index 0000000..e83c92a
--- /dev/null
+++ b/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.jme3.input.awt;
+
+import com.jme3.input.MouseInput;
+import com.jme3.input.RawInputListener;
+import com.jme3.input.event.MouseButtonEvent;
+import com.jme3.input.event.MouseMotionEvent;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.SwingUtilities;
+
+/**
+ * <code>AwtMouseInput</code>
+ *
+ * @author Joshua Slack
+ * @author MHenze (cylab)
+ *
+ * @version $Revision$
+ */
+public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListener, MouseMotionListener {
+
+ public static int WHEEL_AMP = 40; // arbitrary... Java's mouse wheel seems to report something a lot lower than lwjgl's
+
+ private static final Logger logger = Logger.getLogger(AwtMouseInput.class.getName());
+
+ private boolean visible = true;
+
+ private RawInputListener listener;
+
+ private Component component;
+
+ private final ArrayList<MouseButtonEvent> eventQueue = new ArrayList<MouseButtonEvent>();
+ private final ArrayList<MouseButtonEvent> eventQueueCopy = new ArrayList<MouseButtonEvent>();
+
+ private int lastEventX;
+ private int lastEventY;
+ private int lastEventWheel;
+
+ private Cursor transparentCursor;
+
+ private Robot robot;
+ private int wheelPos;
+ private Point location;
+ private Point centerLocation;
+ private Point centerLocationOnScreen;
+ private Point lastKnownLocation;
+ private boolean isRecentering;
+ private boolean cursorMoved;
+ private int eventsSinceRecenter;
+
+ public AwtMouseInput() {
+ location = new Point();
+ centerLocation = new Point();
+ centerLocationOnScreen = new Point();
+ lastKnownLocation = new Point();
+
+ try{
+ robot = new Robot();
+ }catch (java.awt.AWTException e){
+ logger.log(Level.SEVERE, "Could not create a robot, so the mouse cannot be grabbed! ", e);
+ }
+ }
+
+ public void setInputSource(Component comp){
+ if (component != null){
+ component.removeMouseListener(this);
+ component.removeMouseMotionListener(this);
+ component.removeMouseWheelListener(this);
+
+ eventQueue.clear();
+
+ wheelPos = 0;
+ isRecentering = false;
+ eventsSinceRecenter = 0;
+ lastEventX = 0;
+ lastEventY = 0;
+ lastEventWheel = 0;
+ location = new Point();
+ centerLocation = new Point();
+ centerLocationOnScreen = new Point();
+ lastKnownLocation = new Point();
+ }
+
+ component = comp;
+ component.addMouseListener(this);
+ component.addMouseMotionListener(this);
+ component.addMouseWheelListener(this);
+ }
+
+ public void initialize() {
+ }
+
+ public void destroy() {
+ }
+
+ public boolean isInitialized() {
+ return true;
+ }
+
+ public void setInputListener(RawInputListener listener){
+ this.listener = listener;
+ }
+
+ public long getInputTimeNanos() {
+ return System.nanoTime();
+ }
+
+ public void setCursorVisible(boolean visible){
+ if (this.visible != visible){
+
+ lastKnownLocation.x = lastKnownLocation.y = 0;
+
+ this.visible = visible;
+ final boolean newVisible = visible;
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ component.setCursor(newVisible ? null : getTransparentCursor());
+ if (!newVisible)
+ recenterMouse(component);
+ }
+ });
+ }
+ }
+
+ public void update() {
+ if (cursorMoved){
+ int newX = location.x;
+ int newY = location.y;
+ int newWheel = wheelPos;
+
+ // invert DY
+ int actualX = lastKnownLocation.x;
+ int actualY = component.getHeight() - lastKnownLocation.y;
+ MouseMotionEvent evt = new MouseMotionEvent(actualX, actualY,
+ newX - lastEventX,
+ lastEventY - newY,
+ wheelPos, lastEventWheel - wheelPos);
+ listener.onMouseMotionEvent(evt);
+
+ lastEventX = newX;
+ lastEventY = newY;
+ lastEventWheel = newWheel;
+
+ cursorMoved = false;
+ }
+
+ synchronized (eventQueue){
+ eventQueueCopy.clear();
+ eventQueueCopy.addAll(eventQueue);
+ eventQueue.clear();
+ }
+
+ int size = eventQueueCopy.size();
+ for (int i = 0; i < size; i++){
+ listener.onMouseButtonEvent(eventQueueCopy.get(i));
+ }
+ }
+
+ private Cursor getTransparentCursor() {
+ if (transparentCursor == null){
+ BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ cursorImage.setRGB(0, 0, 0);
+ transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImage, new Point(0, 0), "empty cursor");
+ }
+ return transparentCursor;
+ }
+
+// public void setHardwareCursor(URL file, int xHotspot, int yHotspot) {
+// //Create the image from the provided url
+// java.awt.Image cursorImage = new ImageIcon( file ).getImage( );
+// //Create a custom cursor with this image
+// opaqueCursor = Toolkit.getDefaultToolkit().createCustomCursor( cursorImage , new Point( xHotspot , yHotspot ) , "custom cursor" );
+// //Use this cursor
+// setCursorVisible( isCursorVisible );
+// }
+
+
+ public int getButtonCount() {
+ return 3;
+ }
+
+ public void mouseClicked(MouseEvent arg0) {
+// MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), false);
+// listener.onMouseButtonEvent(evt);
+ }
+
+ public void mousePressed(MouseEvent arg0) {
+ MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), true, arg0.getX(), arg0.getY());
+ evt.setTime(arg0.getWhen());
+ synchronized (eventQueue){
+ eventQueue.add(evt);
+ }
+ }
+
+ public void mouseReleased(MouseEvent arg0) {
+ MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), false, arg0.getX(), arg0.getY());
+ evt.setTime(arg0.getWhen());
+ synchronized (eventQueue){
+ eventQueue.add(evt);
+ }
+ }
+
+ public void mouseEntered(MouseEvent arg0) {
+ if (!visible)
+ recenterMouse(arg0.getComponent());
+ }
+
+ public void mouseExited(MouseEvent arg0) {
+ if (!visible)
+ recenterMouse(arg0.getComponent());
+ }
+
+ public void mouseWheelMoved(MouseWheelEvent arg0) {
+ int dwheel = arg0.getUnitsToScroll();
+ wheelPos += dwheel * WHEEL_AMP;
+ cursorMoved = true;
+ }
+
+ public void mouseDragged(MouseEvent arg0) {
+ mouseMoved(arg0);
+ }
+
+ public void mouseMoved(MouseEvent arg0) {
+ if (isRecentering) {
+ // MHenze (cylab) Fix Issue 35:
+ // As long as the MouseInput is in recentering mode, nothing is done until the mouse is entered in the component
+ // by the events generated by the robot. If this happens, the last known location is resetted.
+ if ((centerLocation.x == arg0.getX() && centerLocation.y == arg0.getY()) || eventsSinceRecenter++ == 5) {
+ lastKnownLocation.x = arg0.getX();
+ lastKnownLocation.y = arg0.getY();
+ isRecentering = false;
+ }
+ } else {
+ // MHenze (cylab) Fix Issue 35:
+ // Compute the delta and absolute coordinates and recenter the mouse if necessary
+ int dx = arg0.getX() - lastKnownLocation.x;
+ int dy = arg0.getY() - lastKnownLocation.y;
+ location.x += dx;
+ location.y += dy;
+ if (!visible) {
+ recenterMouse(arg0.getComponent());
+ }
+ lastKnownLocation.x = arg0.getX();
+ lastKnownLocation.y = arg0.getY();
+
+ cursorMoved = true;
+ }
+ }
+
+ // MHenze (cylab) Fix Issue 35: A method to generate recenter the mouse to allow the InputSystem to "grab" the mouse
+ private void recenterMouse(final Component component) {
+ if (robot != null) {
+ eventsSinceRecenter = 0;
+ isRecentering = true;
+ centerLocation.setLocation(component.getWidth()/2, component.getHeight()/2);
+ centerLocationOnScreen.setLocation(centerLocation);
+ SwingUtilities.convertPointToScreen(centerLocationOnScreen, component);
+ robot.mouseMove(centerLocationOnScreen.x, centerLocationOnScreen.y);
+ }
+ }
+
+ private int getJMEButtonIndex( MouseEvent arg0 ) {
+ int index;
+ switch (arg0.getButton()) {
+ default:
+ case MouseEvent.BUTTON1: //left
+ index = MouseInput.BUTTON_LEFT;
+ break;
+ case MouseEvent.BUTTON2: //middle
+ index = MouseInput.BUTTON_MIDDLE;
+ break;
+ case MouseEvent.BUTTON3: //right
+ index = MouseInput.BUTTON_RIGHT;
+ break;
+ }
+ return index;
+ }
+}