From afae3ee553097dab7b6fbdc05530c9db9d3d14c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Aug 2026 08:39:05 +0000 Subject: [PATCH 1/3] Initial plan From 61bacec23232fd9e5158b7a52d8e7c2aea88b514 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Aug 2026 08:43:55 +0000 Subject: [PATCH 2/3] Add touch controls to FlyByCamera Co-authored-by: riccardobl <4943530+riccardobl@users.noreply.github.com> --- .../main/java/com/jme3/input/FlyByCamera.java | 20 ++++- .../java/com/jme3/input/FlyByCameraTest.java | 77 +++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 jme3-core/src/test/java/com/jme3/input/FlyByCameraTest.java diff --git a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java index 8e176b85e9..e4d520326a 100644 --- a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java +++ b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java @@ -37,6 +37,9 @@ 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.TouchTrigger; +import com.jme3.input.event.TouchEvent; import com.jme3.math.Matrix3f; import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; @@ -54,12 +57,13 @@ * - WASD keys for moving forward/backward and strafing * - QZ keys raise or lower the camera */ -public class FlyByCamera implements AnalogListener, ActionListener, JoystickConnectionListener { +public class FlyByCamera implements AnalogListener, ActionListener, JoystickConnectionListener, TouchListener { private static final String FLYCAM_JOYSTICK_LEFT = "FLYCAM_JoystickLeft"; private static final String FLYCAM_JOYSTICK_RIGHT = "FLYCAM_JoystickRight"; private static final String FLYCAM_JOYSTICK_UP = "FLYCAM_JoystickUp"; private static final String FLYCAM_JOYSTICK_DOWN = "FLYCAM_JoystickDown"; + private static final String FLYCAM_TOUCH = "FLYCAM_Touch"; private static final String[] mappings = new String[]{ CameraInput.FLYCAM_LEFT, @@ -84,7 +88,8 @@ public class FlyByCamera implements AnalogListener, ActionListener, JoystickConn FLYCAM_JOYSTICK_LEFT, FLYCAM_JOYSTICK_RIGHT, FLYCAM_JOYSTICK_UP, - FLYCAM_JOYSTICK_DOWN + FLYCAM_JOYSTICK_DOWN, + FLYCAM_TOUCH }; /** * camera controlled by this controller (not null) @@ -306,6 +311,7 @@ private void registerInputMappings() { inputManager.addMapping(CameraInput.FLYCAM_ZOOMIN, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false)); inputManager.addMapping(CameraInput.FLYCAM_ZOOMOUT, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true)); inputManager.addMapping(CameraInput.FLYCAM_ROTATEDRAG, new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); + inputManager.addMapping(FLYCAM_TOUCH, new TouchTrigger(TouchInput.ALL)); // keyboard only WASD for movement and WZ for rise/lower height inputManager.addMapping(CameraInput.FLYCAM_STRAFELEFT, new KeyTrigger(KeyInput.KEY_A)); @@ -567,4 +573,14 @@ public void onAction(String name, boolean isPressed, float tpf) { } } } + + @Override + public void onTouch(String name, TouchEvent event, float tpf) { + if (!enabled || !name.equals(FLYCAM_TOUCH) || event.getType() != TouchEvent.Type.MOVE) { + return; + } + + rotateCamera(-event.getDeltaX() / 1024f, initialUpVec, true); + rotateCamera(-event.getDeltaY() / 1024f * (invertY ? -1 : 1), cam.getLeft(tempLeft), true); + } } diff --git a/jme3-core/src/test/java/com/jme3/input/FlyByCameraTest.java b/jme3-core/src/test/java/com/jme3/input/FlyByCameraTest.java new file mode 100644 index 0000000000..f978965eed --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/input/FlyByCameraTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2026 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. + * + * * 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; + +import com.jme3.input.event.TouchEvent; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +class FlyByCameraTest { + + @Test + void touchDragRotatesCamera() { + Camera camera = new Camera(640, 480); + FlyByCamera flyCam = new FlyByCamera(camera); + Vector3f initialDirection = camera.getDirection().clone(); + + flyCam.onTouch("FLYCAM_Touch", + new TouchEvent(TouchEvent.Type.MOVE, 0f, 0f, 128f, 0f), 0f); + + assertFalse(initialDirection.equals(camera.getDirection())); + } + + @Test + void touchDragRotatesCameraWhenDragToRotateIsEnabled() { + Camera camera = new Camera(640, 480); + FlyByCamera flyCam = new FlyByCamera(camera); + flyCam.setDragToRotate(true); + Vector3f initialDirection = camera.getDirection().clone(); + + flyCam.onTouch("FLYCAM_Touch", + new TouchEvent(TouchEvent.Type.MOVE, 0f, 0f, 128f, 0f), 0f); + + assertFalse(initialDirection.equals(camera.getDirection())); + } + + @Test + void disabledFlyByCameraIgnoresTouchDrag() { + Camera camera = new Camera(640, 480); + FlyByCamera flyCam = new FlyByCamera(camera); + flyCam.setEnabled(false); + Vector3f initialDirection = camera.getDirection().clone(); + + flyCam.onTouch("FLYCAM_Touch", + new TouchEvent(TouchEvent.Type.MOVE, 0f, 0f, 128f, 0f), 0f); + + assertEquals(initialDirection, camera.getDirection()); + } +} From 84f4232e20b5598713790fe4e023f674c5c7d48c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Aug 2026 08:44:51 +0000 Subject: [PATCH 3/3] Clarify touch rotation scale Co-authored-by: riccardobl <4943530+riccardobl@users.noreply.github.com> --- jme3-core/src/main/java/com/jme3/input/FlyByCamera.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java index e4d520326a..cba0de8113 100644 --- a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java +++ b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java @@ -64,6 +64,7 @@ public class FlyByCamera implements AnalogListener, ActionListener, JoystickConn private static final String FLYCAM_JOYSTICK_UP = "FLYCAM_JoystickUp"; private static final String FLYCAM_JOYSTICK_DOWN = "FLYCAM_JoystickDown"; private static final String FLYCAM_TOUCH = "FLYCAM_Touch"; + private static final float TOUCH_ROTATION_SCALE = 1f / 1024f; private static final String[] mappings = new String[]{ CameraInput.FLYCAM_LEFT, @@ -580,7 +581,7 @@ public void onTouch(String name, TouchEvent event, float tpf) { return; } - rotateCamera(-event.getDeltaX() / 1024f, initialUpVec, true); - rotateCamera(-event.getDeltaY() / 1024f * (invertY ? -1 : 1), cam.getLeft(tempLeft), true); + rotateCamera(-event.getDeltaX() * TOUCH_ROTATION_SCALE, initialUpVec, true); + rotateCamera(-event.getDeltaY() * TOUCH_ROTATION_SCALE * (invertY ? -1 : 1), cam.getLeft(tempLeft), true); } }