diff --git a/engine/src/core/com/jme3/app/Application.java b/engine/src/core/com/jme3/app/Application.java index 28a8c5e01..e387dcb48 100644 --- a/engine/src/core/com/jme3/app/Application.java +++ b/engine/src/core/com/jme3/app/Application.java @@ -36,6 +36,7 @@ import com.jme3.app.state.AppStateManager; import com.jme3.input.JoyInput; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; +import com.jme3.input.TouchInput; import com.jme3.system.*; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; @@ -90,6 +91,7 @@ public class Application implements SystemListener { protected MouseInput mouseInput; protected KeyInput keyInput; protected JoyInput joyInput; + protected TouchInput touchInput; protected InputManager inputManager; protected AppStateManager stateManager; @@ -222,6 +224,10 @@ public class Application implements SystemListener { keyInput = context.getKeyInput(); if (keyInput != null) keyInput.initialize(); + + touchInput = context.getTouchInput(); + if (touchInput != null) + touchInput.initialize(); if (!settings.getBoolean("DisableJoysticks")){ joyInput = context.getJoyInput(); @@ -229,7 +235,7 @@ public class Application implements SystemListener { joyInput.initialize(); } - inputManager = new InputManager(mouseInput, keyInput, joyInput); + inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput); } private void initStateManager(){ @@ -479,6 +485,9 @@ public class Application implements SystemListener { if (joyInput != null) joyInput.destroy(); + + if (touchInput != null) + touchInput.destroy(); inputManager = null; } diff --git a/engine/src/core/com/jme3/input/InputManager.java b/engine/src/core/com/jme3/input/InputManager.java index 9670a39dc..e3b7a02ae 100644 --- a/engine/src/core/com/jme3/input/InputManager.java +++ b/engine/src/core/com/jme3/input/InputManager.java @@ -39,6 +39,7 @@ import com.jme3.input.controls.JoyButtonTrigger; import com.jme3.input.controls.KeyTrigger; import com.jme3.input.controls.MouseAxisTrigger; import com.jme3.input.controls.MouseButtonTrigger; +import com.jme3.input.controls.TouchListener; import com.jme3.input.controls.Trigger; import com.jme3.input.event.InputEvent; import com.jme3.input.event.JoyAxisEvent; @@ -46,6 +47,7 @@ import com.jme3.input.event.JoyButtonEvent; import com.jme3.input.event.KeyInputEvent; import com.jme3.input.event.MouseButtonEvent; import com.jme3.input.event.MouseMotionEvent; +import com.jme3.input.event.TouchEvent; import com.jme3.math.FastMath; import com.jme3.math.Vector2f; import com.jme3.util.IntMap; @@ -70,6 +72,7 @@ public class InputManager implements RawInputListener { private final KeyInput keys; private final MouseInput mouse; private final JoyInput joystick; + private final TouchInput touch; private float frameTPF; private long lastLastUpdateTime = 0; private long lastUpdateTime = 0; @@ -108,7 +111,7 @@ public class InputManager implements RawInputListener { * @param joyInput * @throws IllegalArgumentException If either mouseInput or keyInput are null. */ - public InputManager(MouseInput mouse, KeyInput keys, JoyInput joystick) { + public InputManager(MouseInput mouse, KeyInput keys, JoyInput joystick, TouchInput touch) { if (keys == null || mouse == null) { throw new NullPointerException("Mouse or keyboard cannot be null"); } @@ -116,6 +119,7 @@ public class InputManager implements RawInputListener { this.keys = keys; this.mouse = mouse; this.joystick = joystick; + this.touch = touch; keys.setInputListener(this); mouse.setInputListener(this); @@ -123,6 +127,9 @@ public class InputManager implements RawInputListener { joystick.setInputListener(this); joysticks = joystick.loadJoysticks(this); } + if (touch != null) { + touch.setInputListener(this); + } firstTime = keys.getInputTimeNanos(); } @@ -528,6 +535,22 @@ public class InputManager implements RawInputListener { rawListenerArray = rawListeners.toArray(new RawInputListener[rawListeners.size()]); return rawListenerArray; } + + public TouchInput getTouchInput() { + return touch; + } + + public void setSimulateMouse(boolean value) { + if (touch != null) { + touch.setSimulateMouse(value); + } + } + + public void setSimulateKeyboard(boolean value) { + if (touch != null) { + touch.setSimulateKeyboard(value); + } + } private void processQueue() { int queueSize = inputQueue.size(); @@ -552,6 +575,8 @@ public class InputManager implements RawInputListener { listener.onJoyAxisEvent((JoyAxisEvent) event); } else if (event instanceof JoyButtonEvent) { listener.onJoyButtonEvent((JoyButtonEvent) event); + } else if (event instanceof TouchEvent) { + listener.onTouchEvent((TouchEvent) event); } else { assert false; } @@ -576,6 +601,8 @@ public class InputManager implements RawInputListener { onJoyAxisEventQueued((JoyAxisEvent) event); } else if (event instanceof JoyButtonEvent) { onJoyButtonEventQueued((JoyButtonEvent) event); + } else if (event instanceof TouchEvent) { + onTouchEventQueued((TouchEvent) event); } else { assert false; } @@ -603,6 +630,9 @@ public class InputManager implements RawInputListener { if (joystick != null) { joystick.update(); } + if (touch != null) { + touch.update(); + } eventsPermitted = false; @@ -612,4 +642,25 @@ public class InputManager implements RawInputListener { lastLastUpdateTime = lastUpdateTime; lastUpdateTime = currentTime; } + + /** + * Dispatches touch events to touch listeners + * @param evt + */ + public void onTouchEventQueued(TouchEvent evt) { + for (Mapping mapping : mappings.values()) { + for (InputListener listener : mapping.listeners) { + if (listener instanceof TouchListener) { + ((TouchListener) listener).onTouch(mapping.name, evt, frameTPF); + } + } + } + } + @Override + public void onTouchEvent(TouchEvent evt) { + if (!eventsPermitted) { + throw new UnsupportedOperationException("TouchInput has raised an event at an illegal time."); + } + inputQueue.add(evt); + } } diff --git a/engine/src/core/com/jme3/input/RawInputListener.java b/engine/src/core/com/jme3/input/RawInputListener.java index 1f49573e0..38511f222 100644 --- a/engine/src/core/com/jme3/input/RawInputListener.java +++ b/engine/src/core/com/jme3/input/RawInputListener.java @@ -37,6 +37,7 @@ import com.jme3.input.event.JoyButtonEvent; import com.jme3.input.event.KeyInputEvent; import com.jme3.input.event.MouseButtonEvent; import com.jme3.input.event.MouseMotionEvent; +import com.jme3.input.event.TouchEvent; /** * An interface used for receiving raw input from devices. @@ -51,4 +52,7 @@ public interface RawInputListener { public void onMouseMotionEvent(MouseMotionEvent evt); public void onMouseButtonEvent(MouseButtonEvent evt); public void onKeyEvent(KeyInputEvent evt); + + // Generic Smartphone input event, used by the Android platform currently + public void onTouchEvent(TouchEvent evt); } diff --git a/engine/src/core/com/jme3/input/TouchInput.java b/engine/src/core/com/jme3/input/TouchInput.java new file mode 100644 index 000000000..70fb2c910 --- /dev/null +++ b/engine/src/core/com/jme3/input/TouchInput.java @@ -0,0 +1,50 @@ +/* + * 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; + +/** + * A specific API for interfacing with smartphone touch devices + */ +public interface TouchInput extends Input { + + /** + * @param simulate Whether mouse events should be generated + */ + public void setSimulateMouse(boolean simulate); + + /** + * @param simulate Whether keyboard events should be generated + */ + public void setSimulateKeyboard(boolean simulate); + +} \ No newline at end of file diff --git a/engine/src/core/com/jme3/input/controls/TouchListener.java b/engine/src/core/com/jme3/input/controls/TouchListener.java new file mode 100644 index 000000000..92dd03141 --- /dev/null +++ b/engine/src/core/com/jme3/input/controls/TouchListener.java @@ -0,0 +1,49 @@ +/* + * 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.controls; + +import com.jme3.input.event.TouchEvent; + +/** + * TouchListener is used to receive events of inputs from smartphone touch devices + * + * @author larynx + */ +public interface TouchListener extends InputListener { + /** + * @param name - the name of the event + * @param event - the touch event itself + * @param tpf - how much time has passed since the last frame + */ + public void onTouch(String name, TouchEvent event, float tpf); +} \ No newline at end of file diff --git a/engine/src/core/com/jme3/input/controls/TouchTrigger.java b/engine/src/core/com/jme3/input/controls/TouchTrigger.java new file mode 100644 index 000000000..494b0a3b9 --- /dev/null +++ b/engine/src/core/com/jme3/input/controls/TouchTrigger.java @@ -0,0 +1,50 @@ +/* + * 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.controls; + +public class TouchTrigger implements Trigger { + + public TouchTrigger() { + super(); + } + + @Override + public int hashCode(){ + return 0xfedcba98; + } + + @Override + public String getName() { + return "TouchInput"; + } +} diff --git a/engine/src/core/com/jme3/input/event/TouchEvent.java b/engine/src/core/com/jme3/input/event/TouchEvent.java new file mode 100644 index 000000000..d3773f1d6 --- /dev/null +++ b/engine/src/core/com/jme3/input/event/TouchEvent.java @@ -0,0 +1,231 @@ +/* + * 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.event; + +import com.jme3.input.event.InputEvent; +import com.jme3.math.Vector2f; + +/** + * TouchEvent represents a single event from multi-touch input devices + * @author larynx + * + */ +public class TouchEvent extends InputEvent +{ + public static enum Type + { + /** + * Touch down event, fields: posX, posY + */ + DOWN, + + /** + * Move/Drag event, fields: posX, posY, deltaX, deltaY + */ + MOVE, + + /** + * Touch up event, fields: posX, posY + */ + UP, + + /** + * Virtual keyboard or hardware key event down, fields: keyCode, characters + */ + KEY_DOWN, + + /** + * Virtual keyboard or hardware key event up, fields: keyCode, characters + */ + KEY_UP, + + // Single finger gestures + FLING, + TAP, + DOUBLETAP, + LONGPRESSED, + + // Two finger scale events + /** + * Two finger scale event start, fields: posX/posY = getFocusX/Y, scaleFactor, scaleSpan + */ + SCALE_START, + /** + * Two finger scale event, fields: posX/posY = getFocusX/Y, scaleFactor, scaleSpan + */ + SCALE_MOVE, + /** + * Two finger scale event end, fields: posX/posY = getFocusX/Y, scaleFactor, scaleSpan + */ + SCALE_END, + + /** + * Scroll event + */ + SCROLL, + + /** + * The user has performed a down MotionEvent and not performed a move or up yet. This event is commonly used to provide visual feedback to the user to let them know that their action has been recognized i.e. highlight an element. + */ + SHOWPRESS, + + // Others + OUTSIDE, + IDLE} + + private Type type = Type.IDLE; + + + private int pointerId; + private float posX; + private float posY; + private float deltaX; + private float deltaY; + + // Used only with KEY* events + private int keyCode; + private String characters; + + // Used only with SCALE* events + private float scaleFactor; + private float scaleSpan; + + + public TouchEvent() + { + set(Type.IDLE, 0f, 0f, 0f, 0f); + } + public TouchEvent(Type type, float x, float y, float deltax, float deltay) + { + set(type, x, y, deltax, deltay); + } + + public void set(Type type) + { + this.type = type; + this.posX = 0f; + this.posY = 0f; + this.deltaX = 0f; + this.deltaY = 0f; + } + + public void set(Type type, float x, float y, float deltax, float deltay) + { + this.type = type; + this.posX = x; + this.posY = y; + this.deltaX = deltax; + this.deltaY = deltay; + } + + + public Type getType() + { + return type; + } + + public float getX() + { + return posX; + } + + public float getY() + { + return posY; + } + + public float getDeltaX() + { + return deltaX; + } + + public float getDeltaY() + { + return deltaY; + } + + public Vector2f getDelta() + { + return new Vector2f(deltaX,deltaY); + } + + public int getPointerId() + { + return pointerId; + } + + public void setPointerId(int pointerId) + { + this.pointerId = pointerId; + } + + public int getKeyCode() + { + return keyCode; + } + + public void setKeyCode(int keyCode) + { + this.keyCode = keyCode; + } + + public String getCharacters() + { + return characters; + } + + public void setCharacters(String characters) + { + this.characters = characters; + } + + public float getScaleFactor() + { + return scaleFactor; + } + + public void setScaleFactor(float scaleFactor) + { + this.scaleFactor = scaleFactor; + } + + public float getScaleSpan() + { + return scaleSpan; + } + + public void setScaleSpan(float scaleSpan) + { + this.scaleSpan = scaleSpan; + } +} diff --git a/engine/src/core/com/jme3/system/JmeContext.java b/engine/src/core/com/jme3/system/JmeContext.java index 10e18f477..37283a503 100644 --- a/engine/src/core/com/jme3/system/JmeContext.java +++ b/engine/src/core/com/jme3/system/JmeContext.java @@ -35,6 +35,7 @@ package com.jme3.system; import com.jme3.input.JoyInput; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; +import com.jme3.input.TouchInput; import com.jme3.renderer.Renderer; /** @@ -124,7 +125,12 @@ public interface JmeContext { * @return Joystick input implementation. May be null if not available. */ public JoyInput getJoyInput(); - + + /** + * @return Touch device input implementation. May be null if not available. + */ + public TouchInput getTouchInput(); + /** * @return The timer for this context, or null if not created yet. */ diff --git a/engine/src/core/com/jme3/system/NullContext.java b/engine/src/core/com/jme3/system/NullContext.java index 10590180c..75fdf2b5b 100644 --- a/engine/src/core/com/jme3/system/NullContext.java +++ b/engine/src/core/com/jme3/system/NullContext.java @@ -35,6 +35,7 @@ package com.jme3.system; import com.jme3.input.JoyInput; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; +import com.jme3.input.TouchInput; import com.jme3.input.dummy.DummyKeyInput; import com.jme3.input.dummy.DummyMouseInput; import com.jme3.renderer.Renderer; @@ -172,6 +173,10 @@ public class NullContext implements JmeContext, Runnable { public JoyInput getJoyInput() { return null; } + + public TouchInput getTouchInput() { + return null; + } public void setTitle(String title) { } @@ -222,5 +227,4 @@ public class NullContext implements JmeContext, Runnable { return true; // Doesn't really matter if true or false. Either way // RenderManager won't render anything. } - }