7 Commits

Author SHA1 Message Date
Markil3
2adb2a3b87 Enables the features added in https://github.com/Markil3/jmonkeyengine/tree/joyAxisUpdate. 2021-02-26 17:21:37 -07:00
Markil3
c9e0fce4d2 Optimizes the build and prepares for a new version. 2021-02-26 16:47:16 -07:00
Markil3
5e32ac16bb Allows the calibration screen to record ranges.
This will take advantage of changes in 3.4.
2021-02-26 16:17:14 -07:00
Markil3
e5c2828848 Fixes some errors in how joystick positions were calculated. 2021-02-26 16:14:08 -07:00
Markil3
dbb9ee23be Made the default axis value displayed "0.0"
"-1.0" didn't seem right.
2021-02-26 16:11:04 -07:00
Markil3
6a2c444910 Gives the calibrator the option of rendering unused buttons useless.
This prevents them from accidentally interfering with buttons we want.
2021-02-26 11:31:14 -07:00
Markil3
399b5a2b81 Fixes a bug with how the calibrater handled button DPads. 2021-02-26 10:44:43 -07:00
10 changed files with 544 additions and 86 deletions

View File

@@ -23,7 +23,7 @@ If you wish to change the colors of the buttons, simply change the color values
* jme3-lwjgl3 or jme3-lwjgl (if running as standalone) * jme3-lwjgl3 or jme3-lwjgl (if running as standalone)
* jme3-android (if running on Android) * jme3-android (if running on Android)
* jme3-android-natives (if running on Android) * jme3-android-natives (if running on Android)
* slf4j-api 1.7.15+ * slf4j-api 1.7.30+
## Building from Source ## Building from Source
To build from source, start by downloading the source from github. If you have the [git command line tool](https://git-scm.com/downloads) installed, the following line will download the git repository from github: To build from source, start by downloading the source from github. If you have the [git command line tool](https://git-scm.com/downloads) installed, the following line will download the git repository from github:
@@ -45,7 +45,7 @@ If you want to test this without implementing it in your software, simply downlo
This will run a bare-bones version dedicated to the utility using LWJGL3. This will run a bare-bones version dedicated to the utility using LWJGL3.
Alternativly, you can use the :desktopLegacy subproject for LWJGL2, or the :android subproject for testing on Android. Alternatively, you can use the :desktopLegacy subproject for LWJGL2, or the :android subproject for testing on Android.
## Troubleshooting ## Troubleshooting

View File

@@ -5,7 +5,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.1' classpath 'com.android.tools.build:gradle:4.1.2'
} }
} }
@@ -17,13 +17,13 @@ repositories {
} }
android { android {
compileSdkVersion 29 compileSdkVersion 30
buildToolsVersion "30.0.2" buildToolsVersion "30.0.3"
defaultConfig { defaultConfig {
applicationId "markil3.controller" applicationId "markil3.controller"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 29 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@@ -43,15 +43,17 @@ android {
} }
dependencies { dependencies {
api(project(":desktop")) { api(project(":library")) {
exclude module: "jme3-lwjgl3"
exclude module: "jme3-desktop"
exclude module: "slf4j-simple" exclude module: "slf4j-simple"
} }
implementation "uk.uuid.slf4j:slf4j-android:1.7.30-0" implementation "uk.uuid.slf4j:slf4j-android:1.7.30-0"
implementation "${jme3.g}:jme3-android:${jme3.version}" implementation "${jme3.g}:jme3-android:${jme3.version}"
implementation "${jme3.g}:jme3-android-native:${jme3.version}" implementation "${jme3.g}:jme3-android-native:${jme3.version}"
implementation "androidx.appcompat:appcompat:1.1.0" // implementation rootProject.files('libs/jme3-android.jar')
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' // implementation rootProject.files('libs/jme3-core.jar')
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.9" // implementation rootProject.files('libs/jme3-plugins.jar')
// implementation rootProject.files('libs/jme3-android-native.jar')
implementation "androidx.appcompat:appcompat:1.2.0"
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
} }

View File

@@ -0,0 +1,276 @@
/*
* Copyright 2020 Markil 3. All rights reserved.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package markil3.controller;
import com.jme3.app.DebugKeysAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
import com.jme3.font.BitmapText;
import com.jme3.input.JoystickCompatibilityMappings;
import com.jme3.input.controls.ActionListener;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeSystem;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* Launch point for the application. This is primarily for demo purposes, and
* games using this as a library can safely ignore it.
*
* @author Markil 3
* @version 1.0
*/
public class Main extends SimpleApplication implements ActionListener
{
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.
getLogger(Main.class);
public static File GAME_FOLDER;
public static File CALIBRATION_FILE;
public static File getGameFolder()
{
return GAME_FOLDER;
}
private static void initializeJoystickMappings()
{
if (CALIBRATION_FILE == null)
{
CALIBRATION_FILE =
new File(GAME_FOLDER, "controllerCalibration.properties");
URL mappingUrl;
switch (JmeSystem.getPlatform())
{
case Windows32:
case Windows64:
mappingUrl = Main.class.
getResource("/joystick-mapping.windows.properties");
break;
case MacOSX32:
case MacOSX64:
case MacOSX_PPC32:
case MacOSX_PPC64:
mappingUrl = Main.class.
getResource("/joystick-mapping.osx.properties");
break;
case Linux32:
case Linux64:
case Linux_ARM32:
case Linux_ARM64:
mappingUrl = Main.class.
getResource("/joystick-mapping.linux.properties");
break;
case Android_ARM5:
case Android_ARM6:
case Android_ARM7:
case Android_ARM8:
case Android_X86:
case Android_Other:
mappingUrl = Main.class.
getResource("/joystick-mapping.android.properties");
break;
case iOS_ARM:
case iOS_X86:
mappingUrl = Main.class.
getResource("/joystick-mapping.ios.properties");
break;
default:
mappingUrl = null;
}
if (mappingUrl != null)
{
try
{
JoystickCompatibilityMappings
.loadMappingProperties(mappingUrl);
}
catch (IOException e)
{
logger.error("Unable to load joystick mappings for " +
mappingUrl, e);
}
}
mappingUrl = Main.class.
getResource("/joystick-mapping." +
JmeSystem.getPlatform().toString().toLowerCase() +
".properties");
if (mappingUrl != null)
{
try
{
JoystickCompatibilityMappings
.loadMappingProperties(mappingUrl);
}
catch (IOException e)
{
logger.error("Unable to load joystick mappings for " +
mappingUrl, e);
}
}
if (CALIBRATION_FILE.isFile())
{
try
{
JoystickCompatibilityMappings.loadMappingProperties(
CALIBRATION_FILE.toURI().toURL());
}
catch (IOException e)
{
logger.error("Unable to load joystick mappings.", e);
}
}
}
}
public static void main(String[] args)
{
Main app;
AppSettings settings;
app = new Main();
settings = new AppSettings(true);
settings.setTitle("Joystick Preview");
settings.setUseJoysticks(true);
settings.setEmulateMouse(true);
settings.setVSync(true);
settings.setWidth(1280);
settings.setHeight(720);
app.setSettings(settings);
app.start();
}
private Node calibrateButton;
public Main()
{
super(new StatsAppState(), new DebugKeysAppState(),
new JoystickPreviewScreen());
}
@Override
public void initialize()
{
final File[] possibleGameDirs =
new File[]{new File(System.getProperty("user.dir")),
new File(System.getProperty("user.home")),
JmeSystem.getStorageFolder(
JmeSystem.StorageFolderType.External)};
int i, l;
if (GAME_FOLDER == null)
{
for (i = 0, l = possibleGameDirs.length; i < l; i++)
{
GAME_FOLDER = possibleGameDirs[i];
if (!GAME_FOLDER.isDirectory())
{
if (!GAME_FOLDER.mkdir())
{
logger.warn("Cannot make " + GAME_FOLDER);
continue;
}
}
if (!GAME_FOLDER.canWrite())
{
logger.warn("Cannot write to " + GAME_FOLDER);
continue;
}
break;
}
if (i == l)
{
throw new RuntimeException(
"Could not create game directory folder.");
}
}
/*
* Add custom joystick mappings before the input manager is loaded.
*/
initializeJoystickMappings();
super.initialize();
}
@Override
public void simpleInitApp()
{
this.calibrateButton =
GUIUtils.createButton(this.getAssetManager(), this.guiFont,
this.getContext().getTouchInput() != null, "calibrate",
"Calibrate Gamepad");
}
@Override
public void simpleUpdate(float tpf)
{
JoystickPreviewScreen screen =
this.getStateManager().getState(JoystickPreviewScreen.class);
if (this.calibrateButton.getParent() == null && screen != null)
{
this.guiNode.attachChild(this.calibrateButton);
this.calibrateButton.setLocalTranslation(
(this.getCamera().getWidth() -
((BitmapText) this.calibrateButton.getChild(1))
.getLineWidth() - 10) / 2F,
this.getCamera().getHeight(), 0);
this.inputManager.addListener(this, screen.CLICK_MAPPING);
}
else if (this.calibrateButton.getParent() != null && screen == null)
{
this.guiNode.detachChild(this.calibrateButton);
this.inputManager.removeListener(this);
}
}
@Override
public void onAction(String name, boolean isPressed, float tpf)
{
String buttonId;
JoystickPreviewScreen screen =
this.getStateManager().getState(JoystickPreviewScreen.class);
if (screen != null && name.equals(screen.CLICK_MAPPING))
{
buttonId = GUIUtils.handleButtonPress(this.calibrateButton,
this.getInputManager().getCursorPosition(), isPressed);
if (!isPressed && "calibrate".equals(buttonId))
{
this.getStateManager().detach(screen);
this.getStateManager()
.attach(new CalibrateInputScreen(CALIBRATION_FILE));
}
}
}
@Override
public void restart()
{
super.restart();
this.enqueue(() -> {
JoystickPreviewScreen previewScreen = this.getStateManager()
.getState(JoystickPreviewScreen.class);
CalibrateInputScreen calibrateScreen =
this.getStateManager().getState(CalibrateInputScreen.class);
if (previewScreen != null)
{
previewScreen.resize();
}
if (calibrateScreen != null)
{
calibrateScreen.resize();
}
this.calibrateButton.setLocalTranslation(
(this.getCamera().getWidth() -
((BitmapText) this.calibrateButton.getChild(1))
.getLineWidth() - 10) / 2F,
this.getCamera().getHeight(), 0);
});
}
}

View File

@@ -1,10 +1,8 @@
package markil3.controller; package markil3.controller;
import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import com.jme3.app.AndroidHarness; import com.jme3.app.AndroidHarness;
import com.jme3.system.AppSettings;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.LogManager; import java.util.logging.LogManager;

View File

@@ -12,7 +12,7 @@ ext {
jme3 = [version: '3.3.2-stable', g: 'org.jmonkeyengine'] jme3 = [version: '3.3.2-stable', g: 'org.jmonkeyengine']
versionNumber = 2 versionNumber = 2
} }
version = "1.1" version = "1.2"
task run { task run {
doFirst { doFirst {

View File

@@ -20,15 +20,41 @@ plugins {
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
//def lwjglVersion = '3.2.3'
dependencies { dependencies {
// Logging // Logging
implementation "org.slf4j:slf4j-api:1.7.15" implementation "org.slf4j:slf4j-api:1.7.30"
implementation "org.slf4j:slf4j-simple:1.7.5" implementation "org.slf4j:slf4j-simple:1.7.5"
implementation project(':library') implementation project(':library')
implementation "${jme3.g}:jme3-core:${jme3.version}" implementation "${jme3.g}:jme3-core:${jme3.version}"
implementation "${jme3.g}:jme3-desktop:${jme3.version}" implementation "${jme3.g}:jme3-desktop:${jme3.version}"
implementation "${jme3.g}:jme3-lwjgl3:${jme3.version}" implementation "${jme3.g}:jme3-lwjgl3:${jme3.version}"
// implementation rootProject.files('libs/jme3-core.jar')
// implementation rootProject.files('libs/jme3-desktop.jar')
// implementation rootProject.files('libs/jme3-lwjgl3.jar')
// implementation "org.lwjgl:lwjgl:${lwjglVersion}"
// implementation "org.lwjgl:lwjgl-glfw:${lwjglVersion}"
// implementation "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}"
// implementation "org.lwjgl:lwjgl-openal:${lwjglVersion}"
// implementation "org.lwjgl:lwjgl-opencl:${lwjglVersion}"
// implementation "org.lwjgl:lwjgl-opengl:${lwjglVersion}"
// runtime "org.lwjgl:lwjgl:${lwjglVersion}:natives-windows"
// runtime "org.lwjgl:lwjgl:${lwjglVersion}:natives-linux"
// runtime "org.lwjgl:lwjgl:${lwjglVersion}:natives-macos"
// runtime "org.lwjgl:lwjgl-glfw:${lwjglVersion}:natives-windows"
// runtime "org.lwjgl:lwjgl-glfw:${lwjglVersion}:natives-linux"
// runtime "org.lwjgl:lwjgl-glfw:${lwjglVersion}:natives-macos"
// runtime "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}:natives-windows"
// runtime "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}:natives-linux"
// runtime "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}:natives-macos"
// runtime "org.lwjgl:lwjgl-opengl:${lwjglVersion}:natives-windows"
// runtime "org.lwjgl:lwjgl-opengl:${lwjglVersion}:natives-linux"
// runtime "org.lwjgl:lwjgl-opengl:${lwjglVersion}:natives-macos"
// runtime "org.lwjgl:lwjgl-openal:${lwjglVersion}:natives-windows"
// runtime "org.lwjgl:lwjgl-openal:${lwjglVersion}:natives-linux"
// runtime "org.lwjgl:lwjgl-openal:${lwjglVersion}:natives-macos"
} }
// Define the main class for the application // Define the main class for the application
@@ -38,7 +64,7 @@ mainClassName = 'markil3.controller.Main'
* TODO - The default zipped distributions are a bit of a mess. * TODO - The default zipped distributions are a bit of a mess.
*/ */
jar { jar {
baseName rootProject.name baseName rootProject.name + "-desktop"
version rootProject.version version rootProject.version
manifest { manifest {
attributes "Main-Class": mainClassName, attributes "Main-Class": mainClassName,

View File

@@ -22,9 +22,18 @@ plugins {
dependencies { dependencies {
implementation(project(':desktop')) { implementation(project(':desktop')) {
exclude group: jme3.g, module: "jme3-lwjgl3" exclude module: "jme3-lwjgl3"
exclude group: "org.lwjgl"
} }
implementation "${jme3.g}:jme3-lwjgl:${jme3.version}" implementation "${jme3.g}:jme3-lwjgl:${jme3.version}"
// implementation rootProject.files('libs/jme3-lwjgl.jar')
// implementation 'org.lwjgl.lwjgl:lwjgl:2.9.3'
// /*
// * Upgrades the default jinput-2.0.5 to jinput-2.0.9 to fix a bug with gamepads on Linux.
// * See https://hub.jmonkeyengine.org/t/linux-gamepad-input-on-jme3-lwjgl-splits-input-between-two-logical-gamepads
// */
// implementation 'net.java.jinput:jinput:2.0.9'
// implementation 'net.java.jinput:jinput:2.0.9:natives-all'
} }
// Define the main class for the application // Define the main class for the application

View File

@@ -18,11 +18,13 @@ targetCompatibility = "1.8"
dependencies { dependencies {
// Logging // Logging
implementation "org.slf4j:slf4j-api:1.7.15" implementation "org.slf4j:slf4j-api:1.7.30"
implementation "org.slf4j:slf4j-simple:1.7.5" implementation "org.slf4j:slf4j-simple:1.7.5"
implementation "${jme3.g}:jme3-core:${jme3.version}" implementation "${jme3.g}:jme3-core:${jme3.version}"
implementation "${jme3.g}:jme3-testdata:${jme3.version}" implementation "${jme3.g}:jme3-testdata:${jme3.version}"
// implementation rootProject.files('libs/jme3-core.jar')
// implementation rootProject.files('libs/jme3-testdata.jar')
} }
processResources { processResources {

View File

@@ -19,7 +19,6 @@ import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent; import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent; import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent; import com.jme3.input.event.TouchEvent;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.scene.Node; import com.jme3.scene.Node;
@@ -27,6 +26,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@@ -52,8 +52,9 @@ import static markil3.controller.JoystickPreviewScreen.START;
/** /**
* Provides a series of prompts that will build a controller calibration file. * Provides a series of prompts that will build a controller calibration file.
*
* @author Markil3 * @author Markil3
* @version 1.1 * @version 1.2
*/ */
public class CalibrateInputScreen extends BaseAppState public class CalibrateInputScreen extends BaseAppState
implements RawInputListener, ActionListener implements RawInputListener, ActionListener
@@ -118,6 +119,8 @@ public class CalibrateInputScreen extends BaseAppState
private Node skipButton; private Node skipButton;
private Node cancelButton; private Node cancelButton;
private Node restartButton; private Node restartButton;
private Node yesButton;
private Node noButton;
private JoystickPreviewScreen.GamepadView gamepad; private JoystickPreviewScreen.GamepadView gamepad;
private BitmapText currentJoystick; private BitmapText currentJoystick;
@@ -141,12 +144,17 @@ public class CalibrateInputScreen extends BaseAppState
*/ */
private boolean triggers2; private boolean triggers2;
private HashMap<String, Object> maps = new HashMap<>(); private HashMap<String, Object> maps = new HashMap<>();
private HashMap<String, float[]> rangeMaps = new HashMap<>();
private HashMap<String, Boolean> mapBias = new HashMap<>(); private HashMap<String, Boolean> mapBias = new HashMap<>();
private HashMap<Object, Float> defaultValues = new HashMap<>(); private HashMap<Object, float[]> defaultValues = new HashMap<>();
private boolean clear;
private float greatestVal, smallestVal;
/** /**
* Creates a screen for calibrating and remapping a game controller. * Creates a screen for calibrating and remapping a game controller.
*
* @param calibrationFile - The file to store the results in. * @param calibrationFile - The file to store the results in.
*/ */
public CalibrateInputScreen(File calibrationFile) public CalibrateInputScreen(File calibrationFile)
@@ -181,8 +189,9 @@ public class CalibrateInputScreen extends BaseAppState
this.introCont.attachChild(text); this.introCont.attachChild(text);
this.startButton = this.startButton =
GUIUtils.createButton(app.getAssetManager(), this.guiFont, app.getContext().getTouchInput() != null, GUIUtils.createButton(app.getAssetManager(), this.guiFont,
"start", "Start"); app.getContext().getTouchInput() != null, "start",
"Start");
// this.startButton.addClickCommands(this); // this.startButton.addClickCommands(this);
this.introCont.attachChild(this.startButton); this.introCont.attachChild(this.startButton);
@@ -193,17 +202,28 @@ public class CalibrateInputScreen extends BaseAppState
"on the controller you want to calibrate.")); "on the controller you want to calibrate."));
this.skipButton = this.skipButton =
GUIUtils.createButton(app.getAssetManager(), this.guiFont, app.getContext().getTouchInput() != null, GUIUtils.createButton(app.getAssetManager(), this.guiFont,
"skip", "Skip"); app.getContext().getTouchInput() != null, "skip",
"Skip");
this.cancelButton = this.cancelButton =
GUIUtils.createButton(app.getAssetManager(), this.guiFont, app.getContext().getTouchInput() != null, GUIUtils.createButton(app.getAssetManager(), this.guiFont,
"cancel", "Cancel"); app.getContext().getTouchInput() != null, "cancel",
"Cancel");
this.introCont.attachChild(this.cancelButton); this.introCont.attachChild(this.cancelButton);
this.restartButton = this.restartButton =
GUIUtils.createButton(app.getAssetManager(), this.guiFont, app.getContext().getTouchInput() != null, GUIUtils.createButton(app.getAssetManager(), this.guiFont,
"close", "Close Application"); app.getContext().getTouchInput() != null, "close",
"Close Application");
this.yesButton =
GUIUtils.createButton(app.getAssetManager(), this.guiFont,
app.getContext().getTouchInput() != null, "yes",
"Yes");
this.noButton =
GUIUtils.createButton(app.getAssetManager(), this.guiFont,
app.getContext().getTouchInput() != null, "no",
"No");
this.gui.attachChild(this.introCont); this.gui.attachChild(this.introCont);
@@ -260,7 +280,7 @@ public class CalibrateInputScreen extends BaseAppState
case JoystickAxis.POV_X: case JoystickAxis.POV_X:
if (this.focusedJoyElement instanceof JoystickButton) if (this.focusedJoyElement instanceof JoystickButton)
{ {
this.maps.put(this.focusValue > 0 ? DPAD_RIGHT : this.maps.put(this.currentBias ? DPAD_RIGHT :
DPAD_LEFT, this.focusedJoyElement); DPAD_LEFT, this.focusedJoyElement);
} }
else else
@@ -272,7 +292,7 @@ public class CalibrateInputScreen extends BaseAppState
case JoystickAxis.POV_Y: case JoystickAxis.POV_Y:
if (this.focusedJoyElement instanceof JoystickButton) if (this.focusedJoyElement instanceof JoystickButton)
{ {
this.maps.put(this.focusValue > 0 ? DPAD_UP : DPAD_DOWN, this.maps.put(this.currentBias ? DPAD_UP : DPAD_DOWN,
this.focusedJoyElement); this.focusedJoyElement);
} }
else else
@@ -286,6 +306,17 @@ public class CalibrateInputScreen extends BaseAppState
break; break;
} }
this.mapBias.put(this.currentButton, this.focusValue > 0); this.mapBias.put(this.currentButton, this.focusValue > 0);
if (this.focusedJoyElement instanceof JoystickAxis)
{
if (!this.rangeMaps.containsKey(this.currentButton))
{
this.rangeMaps.put(this.currentButton, new float[2]);
}
this.rangeMaps.get(this.currentButton)[this.currentBias ?
1 :
0] =
this.greatestVal;
}
this.timeHeld = -1; this.timeHeld = -1;
this.focusedJoyElement = null; this.focusedJoyElement = null;
this.focusValue = 0; this.focusValue = 0;
@@ -340,6 +371,7 @@ public class CalibrateInputScreen extends BaseAppState
/** /**
* Scales and positions elements of this screen. * Scales and positions elements of this screen.
*
* @param width - The width to scale to. * @param width - The width to scale to.
* @param height - The height to scale to. * @param height - The height to scale to.
*/ */
@@ -420,6 +452,12 @@ public class CalibrateInputScreen extends BaseAppState
case "close": case "close":
this.getApplication().stop(); this.getApplication().stop();
break; break;
case "yes":
this.clearUnused();
break;
case "no":
this.recordFile();
break;
} }
} }
} }
@@ -427,8 +465,9 @@ public class CalibrateInputScreen extends BaseAppState
/** /**
* Set which joystick to use for calibration. This change affects all * Set which joystick to use for calibration. This change affects all
* joysticks sharing the same name, so you don't have to run this for * joysticks sharing the same name, so you don't have to run this for every
* every controller you have if some of them are identical. * controller you have if some of them are identical.
*
* @param joystick - The joystick to use for calibration. * @param joystick - The joystick to use for calibration.
*/ */
private void setJoystick(Joystick joystick) private void setJoystick(Joystick joystick)
@@ -626,27 +665,50 @@ public class CalibrateInputScreen extends BaseAppState
} }
else else
{ {
this.recordFile(); this.promptClearUnused();
} }
} }
private void promptClearUnused()
{
this.currentStage = null;
this.mainOptions.removeFromParent();
this.gamepad.removeFromParent();
this.introCont.detachAllChildren();
this.introCont.attachChild(this.guiFont.createLabel(
"Do you wish to set all buttons and axes not used to not " +
"trigger?\nThis has the benefit of ensuring unused " +
"buttons don't interfere with\n" +
"anything else."));
this.introCont.attachChild(this.yesButton);
this.introCont.attachChild(this.noButton);
this.gui.attachChild(this.introCont);
this.resize();
}
private void clearUnused()
{
this.clear = true;
this.recordFile();
}
/** /**
* Saves the calibration settings to the file and prompts for an * Saves the calibration settings to the file and prompts for an application
* application restart. * restart.
*/ */
private void recordFile() private void recordFile()
{ {
/* /*
* Enable this in JME 3.4. * Enable this in JME 3.4.
*/ */
boolean perComponentEnabled = false; boolean perComponentEnabled = true;
JoystickAxis axis; JoystickAxis axis;
JoystickButton button; JoystickButton button;
float[] range;
Properties props = new Properties(); Properties props = new Properties();
this.currentStage = null; this.introCont.removeFromParent();
this.mainOptions.removeFromParent();
this.gamepad.removeFromParent();
if (!calibrationFile.exists()) if (!calibrationFile.exists())
{ {
@@ -665,7 +727,7 @@ public class CalibrateInputScreen extends BaseAppState
this.introCont.attachChild(this.cancelButton); this.introCont.attachChild(this.cancelButton);
this.introCont.attachChild( this.introCont.attachChild(
this.guiFont.createLabel("Error Details:")); this.guiFont.createLabel("Error Details:"));
this.listStack(this.introCont, ioe, 0); this.listStack(this.introCont, ioe);
this.gui.attachChild(this.introCont); this.gui.attachChild(this.introCont);
this.resize(); this.resize();
} }
@@ -681,13 +743,17 @@ public class CalibrateInputScreen extends BaseAppState
} }
finally finally
{ {
ArrayList<Object> elements = new ArrayList<>();
elements.addAll(this.joystick.getAxes());
elements.addAll(this.joystick.getButtons());
for (Map.Entry<String, Object> calibrationEntry : this.maps for (Map.Entry<String, Object> calibrationEntry : this.maps
.entrySet()) .entrySet())
{ {
if (calibrationEntry.getValue() instanceof JoystickButton) if (calibrationEntry.getValue() instanceof JoystickButton)
{ {
button = (JoystickButton) calibrationEntry.getValue(); button = (JoystickButton) calibrationEntry.getValue();
if (!button.getName().equals(calibrationEntry.getKey())) if (!button.getName()
.equals(calibrationEntry.getKey()) || clear)
{ {
props.put((perComponentEnabled ? "button." : "") + props.put((perComponentEnabled ? "button." : "") +
this.joystick.getName() + "." + this.joystick.getName() + "." +
@@ -697,11 +763,42 @@ public class CalibrateInputScreen extends BaseAppState
else if (calibrationEntry.getValue() instanceof JoystickAxis) else if (calibrationEntry.getValue() instanceof JoystickAxis)
{ {
axis = (JoystickAxis) calibrationEntry.getValue(); axis = (JoystickAxis) calibrationEntry.getValue();
if (!axis.getName().equals(calibrationEntry.getKey())) if (!axis.getName()
.equals(calibrationEntry.getKey()) || clear)
{ {
range = this.rangeMaps.get(calibrationEntry.getKey());
// defaultValue = this.defaultValues.get(axis);
props.put((perComponentEnabled ? "axis." : "") + props.put((perComponentEnabled ? "axis." : "") +
this.joystick.getName() + "." + axis.getName(), this.joystick.getName() + "." + axis.getName(),
calibrationEntry.getKey()); calibrationEntry.getKey() + (perComponentEnabled && range != null ?
("[" + (range[0] != 0 ?
(1.0F / range[0]) :
0) + "," + (
range[1] != 0 ?
(1.0F / range[1]) :
0) + "]") :
""));
}
}
elements.remove(calibrationEntry.getValue());
}
if (this.clear)
{
for (Object element : elements)
{
if (element instanceof JoystickButton)
{
button = (JoystickButton) element;
props.put((perComponentEnabled ? "button." : "") +
this.joystick.getName() + "." +
button.getName(), "null");
}
else if (element instanceof JoystickAxis)
{
axis = (JoystickAxis) element;
props.put((perComponentEnabled ? "axis." : "") +
this.joystick.getName() + "." + axis.getName(),
"null");
} }
} }
} }
@@ -728,7 +825,7 @@ public class CalibrateInputScreen extends BaseAppState
this.introCont.attachChild(this.cancelButton); this.introCont.attachChild(this.cancelButton);
this.introCont.attachChild( this.introCont.attachChild(
this.guiFont.createLabel("Error Details:")); this.guiFont.createLabel("Error Details:"));
this.listStack(this.introCont, ioe, 0); this.listStack(this.introCont, ioe);
this.gui.attachChild(this.introCont); this.gui.attachChild(this.introCont);
this.resize(); this.resize();
} }
@@ -737,12 +834,12 @@ public class CalibrateInputScreen extends BaseAppState
/** /**
* Display an error stack trace on the screen. * Display an error stack trace on the screen.
*
* @param errorCont - The container to use for the error. * @param errorCont - The container to use for the error.
* @param error - The error. * @param error - The error.
* @param depth - How many levels of exceptions throwing exceptions we * in. This is for recursively calling the method.
* are in. This is for recursively calling the method.
*/ */
private void listStack(Node errorCont, Throwable error, int depth) private void listStack(Node errorCont, Throwable error)
{ {
StringBuilder errorBuilder = new StringBuilder(); StringBuilder errorBuilder = new StringBuilder();
Throwable cause = error; Throwable cause = error;
@@ -768,20 +865,24 @@ public class CalibrateInputScreen extends BaseAppState
@Override @Override
public void onJoyAxisEvent(JoyAxisEvent evt) public void onJoyAxisEvent(JoyAxisEvent evt)
{ {
float[] defaultValue = this.defaultValues.get(evt.getAxis());
// this.setJoystick(evt.getAxis().getJoystick()); // this.setJoystick(evt.getAxis().getJoystick());
if (this.joystick != null) if (this.joystick != null)
{ {
if (evt.getValue() != 0 && Math.abs(evt.getValue()) > 0.5 && // TODO - Use getRawValue() in 3.4
(this.defaultValues.get(evt.getAxis()) == null || Math.abs( if (evt.getRawValue() != 0 && Math.abs(evt.getRawValue()) > 0.5 &&
this.defaultValues.get(evt.getAxis()) - (defaultValue == null || Math.abs(
evt.getValue()) > 0.001F)) defaultValue[0] -
evt.getRawValue()) > 0.001F))
{ {
if (this.focusedJoyElement != evt.getAxis() || if (this.focusedJoyElement != evt.getAxis() ||
this.focusValue != evt.getValue()) this.focusValue != evt.getRawValue())
{ {
this.focusedJoyElement = evt.getAxis(); this.focusedJoyElement = evt.getAxis();
this.timeHeld = 0; this.timeHeld = 0;
this.focusValue = evt.getValue(); this.focusValue = evt.getRawValue();
this.greatestVal = 0;
this.smallestVal = evt.getRawValue();
this.currentElement.setText( this.currentElement.setText(
(this.focusValue > 0 ? "+ " : "- ") + (this.focusValue > 0 ? "+ " : "- ") +
evt.getAxis().getName()); evt.getAxis().getName());
@@ -789,6 +890,17 @@ public class CalibrateInputScreen extends BaseAppState
this.gui.attachChild(this.currentTime); this.gui.attachChild(this.currentTime);
this.resize(); this.resize();
} }
else
{
if (Math.abs(evt.getRawValue()) < Math.abs(this.smallestVal))
{
this.smallestVal = evt.getRawValue();
}
else if (Math.abs(evt.getRawValue()) > Math.abs(this.greatestVal))
{
this.greatestVal = evt.getRawValue();
}
}
} }
else else
{ {
@@ -804,8 +916,20 @@ public class CalibrateInputScreen extends BaseAppState
} }
else else
{ {
this.defaultValues.put(evt.getAxis(), evt.getValue()); defaultValue = new float[]{evt.getRawValue(), 0, 0};
this.defaultValues.put(evt.getAxis(), defaultValue);
} }
// if (defaultValue != null)
// {
// if (evt.getRawValue() < defaultValue[1])
// {
// defaultValue[1] = evt.getRawValue();
// }
// if (evt.getRawValue() > defaultValue[2])
// {
// defaultValue[2] = evt.getRawValue();
// }
// }
} }
@Override @Override
@@ -815,7 +939,7 @@ public class CalibrateInputScreen extends BaseAppState
{ {
if (evt.isPressed() && if (evt.isPressed() &&
(this.defaultValues.get(evt.getButton()) == null || (this.defaultValues.get(evt.getButton()) == null ||
Math.abs(this.defaultValues.get(evt.getButton()) - Math.abs(this.defaultValues.get(evt.getButton())[0] -
1F) > 0.001F)) 1F) > 0.001F))
{ {
if (this.focusedJoyElement != evt.getButton() || if (this.focusedJoyElement != evt.getButton() ||
@@ -845,7 +969,8 @@ public class CalibrateInputScreen extends BaseAppState
else else
{ {
this.defaultValues this.defaultValues
.put(evt.getButton(), evt.isPressed() ? 1.0F : 0.0F); .put(evt.getButton(),
new float[]{evt.isPressed() ? 1.0F : 0.0F, 0, 0});
} }
if (!evt.isPressed()) if (!evt.isPressed())
{ {

View File

@@ -47,12 +47,12 @@ import java.util.Map;
/** /**
* Adding this app state will display a GUI screen showing the controllers * Adding this app state will display a GUI screen showing the controllers
* connected and information on what buttons are pressed. It is primarily * connected and information on what buttons are pressed. It is primarily useful
* useful for debugging controllers. * for debugging controllers.
* <p>Note that this class relies on three textures not found in the default * <p>Note that this class relies on three textures not found in the default
* JME core: "Interface/Joystick/gamepad-buttons.png", * JME core: "Interface/Joystick/gamepad-buttons.png",
* "Interface/Joystick/gamepad-frame.png," and * "Interface/Joystick/gamepad-frame.png,"
* "Interface/Joystick/gamepad-stick.png." These textures can be obtained * and "Interface/Joystick/gamepad-stick.png." These textures can be obtained
* from the org.jmonkeyengine:jme3-testdata library.</p> * from the org.jmonkeyengine:jme3-testdata library.</p>
* *
* @author Markil 3 * @author Markil 3
@@ -61,6 +61,7 @@ import java.util.Map;
* @author Paul Speed * @author Paul Speed
* @author dokthar * @author dokthar
* @author Stephen Gold * @author Stephen Gold
* @version 1.2
*/ */
public class JoystickPreviewScreen extends BaseAppState public class JoystickPreviewScreen extends BaseAppState
implements RawInputListener, JoystickConnectionListener, ActionListener implements RawInputListener, JoystickConnectionListener, ActionListener
@@ -87,13 +88,13 @@ public class JoystickPreviewScreen extends BaseAppState
public static final String L1 = JoystickButton.BUTTON_4; public static final String L1 = JoystickButton.BUTTON_4;
public static final String R1 = JoystickButton.BUTTON_5; public static final String R1 = JoystickButton.BUTTON_5;
/** /**
* Some gamepads (Xbox controllers notable) will use * Some gamepads (Xbox controllers notable) will use {@link
* {@link JoystickAxis#LEFT_TRIGGER} instead. * JoystickAxis#LEFT_TRIGGER} instead.
*/ */
public static final String L2 = JoystickButton.BUTTON_6; public static final String L2 = JoystickButton.BUTTON_6;
/** /**
* Some gamepads (Xbox controllers notable) will use * Some gamepads (Xbox controllers notable) will use {@link
* {@link JoystickAxis#RIGHT_TRIGGER} instead. * JoystickAxis#RIGHT_TRIGGER} instead.
*/ */
public static final String R2 = JoystickButton.BUTTON_7; public static final String R2 = JoystickButton.BUTTON_7;
public static final String SELECT = JoystickButton.BUTTON_8; public static final String SELECT = JoystickButton.BUTTON_8;
@@ -125,8 +126,8 @@ public class JoystickPreviewScreen extends BaseAppState
final String CLICK_MAPPING = "previewButtonClick"; final String CLICK_MAPPING = "previewButtonClick";
/** /**
* This node serves as the center of logic for each gamepad connected to * This node serves as the center of logic for each gamepad connected to the
* the computer. * computer.
*/ */
static class GamepadView extends Node static class GamepadView extends Node
{ {
@@ -261,7 +262,7 @@ public class JoystickPreviewScreen extends BaseAppState
} }
else if (axis == axis.getJoystick().getYAxis()) else if (axis == axis.getJoystick().getYAxis())
{ {
setYAxis(-value); setYAxis(value);
} }
else if (axis == axis.getJoystick().getAxis(JoystickAxis.Z_AXIS)) else if (axis == axis.getJoystick().getAxis(JoystickAxis.Z_AXIS))
{ {
@@ -280,7 +281,7 @@ public class JoystickPreviewScreen extends BaseAppState
else if (axis == else if (axis ==
axis.getJoystick().getAxis(JoystickAxis.Z_ROTATION)) axis.getJoystick().getAxis(JoystickAxis.Z_ROTATION))
{ {
setZRotation(-value); setZRotation(value);
} }
else if (axis == else if (axis ==
axis.getJoystick().getAxis(JoystickAxis.LEFT_TRIGGER)) axis.getJoystick().getAxis(JoystickAxis.LEFT_TRIGGER))
@@ -467,8 +468,8 @@ public class JoystickPreviewScreen extends BaseAppState
float angle = dir.getAngle(); float angle = dir.getAngle();
float x = FastMath.cos(angle) * length * 10; float x = FastMath.cos(angle) * length * 10;
float y = FastMath.sin(angle) * length * 10; float y = FastMath.sin(-angle) * length * 10;
leftStick.setLocalTranslation(xBase + x, yBase + y, 0); leftStick.setLocalTranslation(xBase + x, yBase - y, 0);
xBase = 291; xBase = 291;
dir = new Vector2f(zAxis, zRotation); dir = new Vector2f(zAxis, zRotation);
@@ -477,8 +478,8 @@ public class JoystickPreviewScreen extends BaseAppState
angle = dir.getAngle(); angle = dir.getAngle();
x = FastMath.cos(angle) * length * 10; x = FastMath.cos(angle) * length * 10;
y = FastMath.sin(angle) * length * 10; y = FastMath.sin(-angle) * length * 10;
rightStick.setLocalTranslation(xBase + x, yBase + y, 0); rightStick.setLocalTranslation(xBase + x, yBase - y, 0);
} }
} }
@@ -531,8 +532,9 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Checks to see if the visual displays if the button is pressed. * Checks to see if the visual displays if the button is pressed.
* @return True if the visual displays that the button is pressed, *
* false otherwise. * @return True if the visual displays that the button is pressed, false
* otherwise.
*/ */
public boolean isDown() public boolean isDown()
{ {
@@ -541,6 +543,7 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Updates the button to display that it is pressed. * Updates the button to display that it is pressed.
*
* @see #up() * @see #up()
*/ */
public void down() public void down()
@@ -551,6 +554,7 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Updates the button to display that it is not pressed. * Updates the button to display that it is not pressed.
*
* @see #down() * @see #down()
*/ */
public void up() public void up()
@@ -699,8 +703,9 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Obtain the size of the screen based on the game camera. * Obtain the size of the screen based on the game camera.
* @return The screen size in a two-dimensional float vector. Note that *
* the numbers will always be integers. * @return The screen size in a two-dimensional float vector. Note that the
* numbers will always be integers.
*/ */
private Vector2f getScreenSize() private Vector2f getScreenSize()
{ {
@@ -738,11 +743,15 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Updates the values of the gamepad labels as buttons and axis are * Updates the values of the gamepad labels as buttons and axis are
* manipulated. * manipulated.
*
* @param joy - The gamepad to update. * @param joy - The gamepad to update.
*/ */
private void setLabels(Joystick joy) private void setLabels(Joystick joy)
{ {
int offset = this.getApplication().getContext().getTouchInput() != null ? 10: 0; int offset =
this.getApplication().getContext().getTouchInput() != null ?
10 :
0;
/* /*
* Removes the old labels. * Removes the old labels.
*/ */
@@ -767,7 +776,9 @@ public class JoystickPreviewScreen extends BaseAppState
// "Gamepad " + joy.getJoyId() + ": " + joy.getName()); // "Gamepad " + joy.getJoyId() + ": " + joy.getName());
this.labels[joy.getJoyId()][0] = this.labels[joy.getJoyId()][0] =
this.guiFont.createLabel(joy.getName()); this.guiFont.createLabel(joy.getName());
this.labels[joy.getJoyId()][0].setLocalTranslation(20, -25 - offset, 0); this.labels[joy.getJoyId()][0].setLocalTranslation(20,
-25 - offset,
0);
this.gamepadCont[joy.getJoyId()] this.gamepadCont[joy.getJoyId()]
.attachChild(this.labels[joy.getJoyId()][0]); .attachChild(this.labels[joy.getJoyId()][0]);
/* /*
@@ -780,7 +791,9 @@ public class JoystickPreviewScreen extends BaseAppState
*/ */
this.labels[joy.getJoyId()][1] = this.guiFont this.labels[joy.getJoyId()][1] = this.guiFont
.createLabel("Axis Index: Axis Name (logical ID, axis ID)"); .createLabel("Axis Index: Axis Name (logical ID, axis ID)");
this.labels[joy.getJoyId()][1].setLocalTranslation(20, -50 - offset, 0); this.labels[joy.getJoyId()][1].setLocalTranslation(20,
-50 - offset,
0);
this.gamepadCont[joy.getJoyId()] this.gamepadCont[joy.getJoyId()]
.attachChild(this.labels[joy.getJoyId()][1]); .attachChild(this.labels[joy.getJoyId()][1]);
/* /*
@@ -804,7 +817,7 @@ public class JoystickPreviewScreen extends BaseAppState
/* /*
* The current value of the axis. * The current value of the axis.
*/ */
BitmapText label2 = this.guiFont.createLabel("-1.0"); BitmapText label2 = this.guiFont.createLabel("0.0");
label2.setLocalTranslation(label.getLocalTranslation() label2.setLocalTranslation(label.getLocalTranslation()
.add(label.getLineWidth(), 0, 0)); .add(label.getLineWidth(), 0, 0));
this.labels[joy.getJoyId()][i * 2 + 2] = label2; this.labels[joy.getJoyId()][i * 2 + 2] = label2;
@@ -907,6 +920,7 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Scales and positions elements of this screen. * Scales and positions elements of this screen.
*
* @param width - The width to scale to. * @param width - The width to scale to.
* @param height - The height to scale to. * @param height - The height to scale to.
*/ */
@@ -919,7 +933,11 @@ public class JoystickPreviewScreen extends BaseAppState
for (int i = 0, l = this.gamepadHeaders.length; i < l; i++) for (int i = 0, l = this.gamepadHeaders.length; i < l; i++)
{ {
button = this.gamepadHeaders[i]; button = this.gamepadHeaders[i];
button.setLocalTranslation((this.getApplication().getContext().getTouchInput() != null ? 192 : 128) * i, 0, 0); button.setLocalTranslation((this.getApplication()
.getContext()
.getTouchInput() != null ?
192 :
128) * i, 0, 0);
} }
} }
if (this.gamepadView != null) if (this.gamepadView != null)
@@ -1015,8 +1033,9 @@ public class JoystickPreviewScreen extends BaseAppState
} }
/** /**
* Displays which button is which as the user hovers over the button. * Displays which button is which as the user hovers over the button. TODO -
* TODO - Doesn't trigger. * Doesn't trigger.
*
* @param evt - Input event data. * @param evt - Input event data.
*/ */
@Override @Override
@@ -1055,6 +1074,7 @@ public class JoystickPreviewScreen extends BaseAppState
/** /**
* Triggers the gamepad tab buttons. * Triggers the gamepad tab buttons.
*
* @param evt - Input event data. * @param evt - Input event data.
*/ */
@Override @Override