diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java index 141c503e16..2dff5ec047 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java @@ -177,6 +177,7 @@ public List loadJoysticks(int joyId, InputManager inputManager) { public boolean onGenericMotion(MotionEvent event) { boolean consumed = false; + float rawValue, value; // logger.log(Level.INFO, "onGenericMotion event: {0}", event); event.getDeviceId(); event.getSource(); @@ -185,7 +186,8 @@ public boolean onGenericMotion(MotionEvent event) { if (joystick != null) { for (int androidAxis: joystick.getAndroidAxes()) { String axisName = MotionEvent.axisToString(androidAxis); - float value = event.getAxisValue(androidAxis); + rawValue = event.getAxisValue(androidAxis); + value = JoystickCompatibilityMappings.remapAxisRange(joystick.getAxis(androidAxis), rawValue); int action = event.getAction(); if (action == MotionEvent.ACTION_MOVE) { // logger.log(Level.INFO, "MOVE axis num: {0}, axisName: {1}, value: {2}", @@ -194,7 +196,7 @@ public boolean onGenericMotion(MotionEvent event) { if (axis != null) { // logger.log(Level.INFO, "MOVE axis num: {0}, axisName: {1}, value: {2}, deadzone: {3}", // new Object[]{androidAxis, axisName, value, axis.getDeadZone()}); - JoyAxisEvent axisEvent = new JoyAxisEvent(axis, value); + JoyAxisEvent axisEvent = new JoyAxisEvent(axis, value, rawValue); joyInput.addEvent(axisEvent); consumed = true; } else { @@ -316,7 +318,7 @@ protected JoystickButton addButton( int keyCode ) { original = JoystickButton.BUTTON_11; } - String logicalId = JoystickCompatibilityMappings.remapComponent( getName(), original ); + String logicalId = JoystickCompatibilityMappings.remapButton( getName(), original ); if( logicalId == null ? original != null : !logicalId.equals(original) ) { logger.log(Level.FINE, "Remapped: {0} to: {1}", new Object[]{original, logicalId}); @@ -347,7 +349,7 @@ protected JoystickAxis addAxis(MotionRange motionRange) { } else if (motionRange.getAxis() == MotionEvent.AXIS_HAT_Y) { original = JoystickAxis.POV_Y; } - String logicalId = JoystickCompatibilityMappings.remapComponent( getName(), original ); + String logicalId = JoystickCompatibilityMappings.remapAxis( getName(), original ); if( logicalId == null ? original != null : !logicalId.equals(original) ) { logger.log(Level.FINE, "Remapped: {0} to: {1}", new Object[]{original, logicalId}); diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java index b24f72059e..2217e6e1bc 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java @@ -374,7 +374,7 @@ private boolean updateOrientation() { sensorData.haveData = true; } else { if (axis.isChanged()) { - joyInput.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue())); + joyInput.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue(), axis.getJoystickAxisValue())); } } } @@ -553,7 +553,7 @@ public void onSensorChanged(SensorEvent se) { sensorData.haveData = true; } else { if (axis.isChanged()) { - JoyAxisEvent event = new JoyAxisEvent(axis, axis.getJoystickAxisValue()); + JoyAxisEvent event = new JoyAxisEvent(axis, axis.getJoystickAxisValue(), axis.getJoystickAxisValue()); // logger.log(Level.INFO, "adding JoyAxisEvent: {0}", event); joyInput.addEvent(event); // joyHandler.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue())); diff --git a/jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java b/jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java index cff4af956f..6529847820 100644 --- a/jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java +++ b/jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java @@ -46,14 +46,15 @@ /** - * Provides compatibility mapping to different joysticks - * that both report their name in a unique way and require - * remapping to achieve a proper default layout. + * Provides compatibility mapping to different joysticks + * that both report their name in a unique way and require + * remapping to achieve a proper default layout. * - *

All mappings MUST be defined before the joystick support - * has been initialized in the InputManager.

+ *

All mappings MUST be defined before the joystick support + * has been initialized in the InputManager.

* - * @author Paul Speed + * @author Paul Speed + * @author Markil3 */ public class JoystickCompatibilityMappings { @@ -61,9 +62,12 @@ public class JoystickCompatibilityMappings { // List of resource paths to check for the joystick-mapping.properties // files. - final private static String[] searchPaths = { "joystick-mapping.properties" }; + private static String[] searchPaths = {"joystick-mapping.properties"}; - final private static Map> joystickMappings = new HashMap>(); + private static Map> joystickMappings = new HashMap>(); + private static Map> axisMappings = new HashMap>(); + private static Map axisRangeMappings = new HashMap<>(); + private static Map> buttonMappings = new HashMap>(); // Remaps names by regex. final private static Map nameRemappings = new HashMap<>(); @@ -79,159 +83,466 @@ public class JoystickCompatibilityMappings { private JoystickCompatibilityMappings() { } - protected static Map getMappings( String joystickName, boolean create ) { - Map result = joystickMappings.get(joystickName.trim()); - if( result == null && create ) { - result = new HashMap(); - joystickMappings.put(joystickName.trim(),result); + protected static Map getMappings(String joystickName, boolean create) { + Map result = joystickMappings.get(joystickName.trim()); + if (result == null && create) { + result = new HashMap(); + joystickMappings.put(joystickName.trim(), result); } - return result; + return result; } - + + /** + * Obtains mappings specific to the joystick axis + * + * @param joystickName - The name of the joystick type to obtain mappings for. + * @param create - If there are no mappings present and this parameter is true, then a new entry for this joystick is created. + * @return The various axis remappings for the requested joystick, or null of there are none. + * @author Markil3 + */ + protected static Map getAxisMappings(String joystickName, boolean create) { + Map result = axisMappings.get(joystickName.trim()); + if (result == null && create) { + result = new HashMap(); + axisMappings.put(joystickName.trim(), result); + } + return result; + } + + /** + * Obtains mappings specific to the joystick buttons + * + * @param joystickName - The name of the joystick type to obtain mappings for. + * @param create - If there are no mappings present and this parameter is true, then a new entry for this joystick is created. + * @return The various button remappings for the requested joystick, or null of there are none. + * @author Markil3 + */ + protected static Map getButtonMappings(String joystickName, boolean create) { + Map result = buttonMappings.get(joystickName.trim()); + if (result == null && create) { + result = new HashMap(); + buttonMappings.put(joystickName.trim(), result); + } + return result; + } + + /** + * This method will take a "raw" axis value from the system and rescale it based on what the remapper has specified. For example, if the remapper specified an axis to be scaled to [0.0,1.0], then a raw value of -0.5 would be converted to 0.25. + * + * @param axis - The axis to remap. + * @param currentValue - The raw value the system is outputting, on a scale of -1.0 to 1.0. + * @return The new value that will be provided to listeners, on a scale specified by the remappings file. + * @author Markil3 + */ + public static float remapAxisRange(JoystickAxis axis, float currentValue) { + String joyName = axis.getJoystick().getName(); + Map map; + float[] range = axisRangeMappings.get(axis); + if (range == null) { + map = getAxisMappings(joyName, false); + if (map != null && map.containsKey(axis.getName())) { + range = map.get(axis.getName()).range; + axisRangeMappings.put(axis, range); + } else { + // Try the normalized name + joyName = getNormalizedName(joyName); + if (joyName != null) { + map = getAxisMappings(joyName, false); + if (map != null && map.containsKey(axis.getName())) { + range = map.get(axis.getName()).range; + axisRangeMappings.put(axis, range); + } + } + } + } + if (range == null) { + axisRangeMappings.put(axis, new float[0]); + return currentValue; + } + + /* + * If we have an array of size 0, that means we have acknowledged this axis (so we don't + * need to go searching for it every tick), but that there is no remapping. + */ + if (range.length == 0) { + return currentValue; + } + + return (currentValue + range[1] + range[0]) * ((range[1] - range[0]) / 2); + } + + /** + * Takes the original name of an axis, specifically, and returns the new name it will function under. + * + * @param joystickName - The joystick type the axis comes from. + * @param componentId - The system-provided name for the axis. + * @return The new name for the axis, or just componentId if no remapping was provided. + * @author Markil3 + */ + public static String remapAxis(String joystickName, String componentId) { + logger.log(Level.FINE, "remapAxis(" + joystickName + ", " + componentId + ")"); + + // Always try the specific name first. + joystickName = joystickName.trim(); + Map map = getAxisMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped axis:" + map.get(componentId)); + return ((AxisData) map.get(componentId)).name; + } + + map = getMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped axis:" + map.get(componentId)); + return ((String) map.get(componentId)); + } + + // Try the normalized name + joystickName = getNormalizedName(joystickName); + logger.log(Level.FINE, "normalized joystick name:" + joystickName); + if (joystickName == null) { + return componentId; + } + + map = getAxisMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); + return ((AxisData) map.get(componentId)).name; + } + + map = getMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); + return ((String) map.get(componentId)); + } + + return componentId; + } + + /** + * Takes the original name of an button, specifically, and returns the new name it will function under. + * + * @param joystickName - The joystick type the axis comes from. + * @param componentId - The system-provided name for the button. + * @return The new name for the button, or just componentId if no remapping was provided. + * @author Markil3 + */ + public static String remapButton(String joystickName, String componentId) { + logger.log(Level.FINE, "remapAxis(" + joystickName + ", " + componentId + ")"); + + + // Always try the specific name first. + joystickName = joystickName.trim(); + Map map = getButtonMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped axis:" + map.get(componentId)); + return map.get(componentId); + } + + map = getMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped axis:" + map.get(componentId)); + return map.get(componentId); + } + + // Try the normalized name + joystickName = getNormalizedName(joystickName); + logger.log(Level.FINE, "normalized joystick name:" + joystickName); + if (joystickName == null) { + return componentId; + } + + map = getButtonMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); + return map.get(componentId); + } + + map = getMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); + return map.get(componentId); + } + + return componentId; + } + /** - * Returns the remapped version of the axis/button name if there - * is a mapping for it otherwise it returns the original name. + * Returns the remapped version of the axis/button name if there + * is a mapping for it otherwise it returns the original name. */ - public static String remapComponent( String joystickName, String componentId ) { + public static String remapComponent(String joystickName, String componentId) { logger.log(Level.FINE, "remapComponent(" + joystickName + ", " + componentId + ")"); - + // Always try the specific name first. - joystickName = joystickName.trim(); - Map map = getMappings(joystickName, false); - if( map != null && map.containsKey(componentId) ) { - logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); + joystickName = joystickName.trim(); + Map map = getMappings(joystickName, false); + if (map != null && map.containsKey(componentId)) { + logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); return map.get(componentId); } // Try the normalized name joystickName = getNormalizedName(joystickName); - logger.log(Level.FINE, "normalized joystick name:" + joystickName); - if( joystickName == null ) { + logger.log(Level.FINE, "normalized joystick name:" + joystickName); + if (joystickName == null) { return componentId; } map = getMappings(joystickName, false); - if( map == null ) { + if (map == null) { return componentId; - } - if( !map.containsKey(componentId) ) { + } + if (!map.containsKey(componentId)) { return componentId; } - logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); - return map.get(componentId); - } - + logger.log(Level.FINE, "returning remapped:" + map.get(componentId)); + return map.get(componentId); + } + + /** + * Returns a set of Joystick axis name remappings if they exist otherwise + * it returns an empty map. + * + * @author Markil3 + */ + public static Map getJoystickAxisMappings(String joystickName) { + Map result = getAxisMappings(joystickName.trim(), false); + if (result == null) + return Collections.emptyMap(); + return Collections.unmodifiableMap(result); + } + /** - * Returns a set of Joystick axis/button name remappings if they exist otherwise - * it returns an empty map. + * Returns a set of Joystick button name remappings if they exist otherwise + * it returns an empty map. + * + * @author Markil3 */ - public static Map getJoystickMappings( String joystickName ) { - Map result = getMappings(joystickName.trim(), false); - if( result == null ) + public static Map getJoystickButtonMappings(String joystickName) { + Map result = getButtonMappings(joystickName.trim(), false); + if (result == null) return Collections.emptyMap(); return Collections.unmodifiableMap(result); } - + + /** + * Returns a set of Joystick axis/button name remappings if they exist otherwise + * it returns an empty map. + */ + public static Map getJoystickMappings(String joystickName) { + Map result = getMappings(joystickName.trim(), false); + if (result == null) + return Collections.emptyMap(); + return Collections.unmodifiableMap(result); + } + + /** + * Adds a single Joystick axis or button remapping based on the + * joystick's name and axis/button name. The "remap" value will be + * used instead. + * + * @author Markil3 + */ + public static void addAxisMapping(String stickName, String sourceComponentId, String remapId) { + logger.log(Level.FINE, "addAxisMapping(" + stickName + ", " + sourceComponentId + ", " + remapId + ")"); + getAxisMappings(stickName, true).put(sourceComponentId, new AxisData(remapId, new float[0])); + } + + /** + * Adds a single Joystick axis or button remapping based on the + * joystick's name and axis/button name. The "remap" value will be + * used instead. + * + * @author Markil3 + */ + public static void addAxisMapping(String stickName, String sourceComponentId, String remapId, float[] range) { + logger.log(Level.FINE, "addAxisMapping(" + stickName + ", " + sourceComponentId + ", " + remapId + ")"); + if (range.length != 2) { + throw new IllegalArgumentException("The range must have exactly 2 elements"); + } + getAxisMappings(stickName, true).put(sourceComponentId, new AxisData(remapId, range)); + } + /** - * Adds a single Joystick axis or button remapping based on the - * joystick's name and axis/button name. The "remap" value will be - * used instead. + * Adds a single Joystick axis or button remapping based on the + * joystick's name and axis/button name. The "remap" value will be + * used instead. + * + * @author Markil3 */ - public static void addMapping( String stickName, String sourceComponentId, String remapId ) { - logger.log(Level.FINE, "addMapping(" + stickName + ", " + sourceComponentId + ", " + remapId + ")" ); - getMappings(stickName, true).put( sourceComponentId, remapId ); - } - + public static void addButtonMapping(String stickName, String sourceComponentId, String remapId) { + logger.log(Level.FINE, "addButtonMapping(" + stickName + ", " + sourceComponentId + ", " + remapId + ")"); + getButtonMappings(stickName, true).put(sourceComponentId, remapId); + } + /** - * Adds a preconfigured set of mappings in Properties object - * form where the names are dot notation "joystick"."axis/button" - * and the values are the remapped component name. This calls - * addMapping(stickName, sourceComponent, remap) for every property - * that it is able to parse. + * Adds a single Joystick axis or button remapping based on the + * joystick's name and axis/button name. The "remap" value will be + * used instead. */ - public static void addMappings( Properties p ) { - for( Map.Entry e : p.entrySet() ) { + public static void addMapping(String stickName, String sourceComponentId, String remapId) { + logger.log(Level.FINE, "addMapping(" + stickName + ", " + sourceComponentId + ", " + remapId + ")"); + getMappings(stickName, true).put(sourceComponentId, remapId); + } + + /** + * Adds a preconfigured set of mappings in Properties object + * form where the names are dot notation + * "axis"/"button"/"". "joystick"."axis/button name" + * and the values are the remapped component name. This calls + * addMapping(stickName, sourceComponent, remap) for every property + * that it is able to parse. + * + * @author Paul Speed + * @author Markil 3 + */ + public static void addMappings(Properties p) { + final String AXIS_LABEL = "axis"; + final String BUTTON_LABEL = "button"; + + float[] range; + int lBrackIndex, rBrackIndex, commaIndex; + + for (Map.Entry e : p.entrySet()) { + range = null; String key = String.valueOf(e.getKey()).trim(); - - int split = key.lastIndexOf( '.' ); - if( split < 0 ) { + + int firstSplit = key.indexOf('.'); + int split = key.lastIndexOf('.'); + if (split < 0) { logger.log(Level.WARNING, "Skipping mapping:{0}", e); continue; } - - String stick = key.substring(0, split).trim(); - String component = key.substring(split+1).trim(); + + String type; + if (firstSplit >= 0 && firstSplit != split) { + type = key.substring(0, firstSplit).trim(); + if (!type.equals(AXIS_LABEL) && !type.equals(BUTTON_LABEL)) { + /* + * In this case, the "type" is probably a part of the + * joystick name. + */ + firstSplit = -1; + type = ""; + } + } else { + firstSplit = -1; + type = ""; + } + String stick = key.substring(firstSplit + 1, split).trim(); + String component = key.substring(split + 1).trim(); String value = String.valueOf(e.getValue()).trim(); - if( "regex".equals(component) ) { + if ("regex".equals(component)) { // It's a name remapping addJoystickNameRegex(value, stick); } - addMapping(stick, component, value); + if ((lBrackIndex = value.indexOf('[')) > 0) { + /* + * This means that there is an axis range. + */ + range = new float[2]; + rBrackIndex = value.indexOf(']'); + commaIndex = value.indexOf(','); + if (rBrackIndex > -1 && commaIndex > -1) { + try { + range[0] = Float.parseFloat(value.substring(lBrackIndex + 1, commaIndex).trim()); + range[1] = Float.parseFloat(value.substring(commaIndex + 1, rBrackIndex).trim()); + value = value.substring(0, lBrackIndex).trim(); + type = AXIS_LABEL; + } catch (NumberFormatException nfe) { + logger.log(Level.SEVERE, "Could not parse axis range \"" + value.substring(lBrackIndex) + "\"", nfe); + } + } + } + switch (type) { + case AXIS_LABEL: + if (range == null) { + addAxisMapping(stick, component, value); + } else { + addAxisMapping(stick, component, value, range); + } + break; + case BUTTON_LABEL: + addButtonMapping(stick, component, value); + break; + default: + addMapping(stick, component, value); + } } } - + /** - * Maps a regular expression to a normalized name for that joystick. + * Maps a regular expression to a normalized name for that joystick. */ - public static void addJoystickNameRegex( String regex, String name ) { + public static void addJoystickNameRegex(String regex, String name) { logger.log(Level.FINE, "addJoystickNameRegex(" + regex + ", " + name + ")"); - nameRemappings.put(Pattern.compile(regex), name); + nameRemappings.put(Pattern.compile(regex), name); } - - protected static String getNormalizedName( String name ) { + + protected static String getNormalizedName(String name) { String result = nameCache.get(name); - if( result != null ) { + if (result != null) { return result; } - for( Map.Entry e : nameRemappings.entrySet() ) { + for (Map.Entry e : nameRemappings.entrySet()) { Pattern p = e.getKey(); Matcher m = p.matcher(name); - if( m.matches() ) { + if (m.matches()) { nameCache.put(name, e.getValue()); return e.getValue(); } } return null; } - + /** - * Loads a set of compatibility mappings from the property file - * specified by the given URL. - */ - public static void loadMappingProperties( URL u ) throws IOException { + * Loads a set of compatibility mappings from the property file + * specified by the given URL. + */ + public static void loadMappingProperties(URL u) throws IOException { logger.log(Level.FINE, "Loading mapping properties:{0}", u); InputStream in = u.openStream(); - try { + try { Properties p = new Properties(); p.load(in); - addMappings(p); + addMappings(p); } finally { in.close(); - } + } } - protected static void loadMappings( ClassLoader cl, String path ) throws IOException { + protected static void loadMappings(ClassLoader cl, String path) throws IOException { logger.log(Level.FINE, "Searching for mappings for path:{0}", path); - for( Enumeration en = cl.getResources(path); en.hasMoreElements(); ) { + for (Enumeration en = cl.getResources(path); en.hasMoreElements(); ) { URL u = en.nextElement(); - try { + try { loadMappingProperties(u); - } catch( IOException e ) { - logger.log(Level.SEVERE, "Error loading:" + u, e); - } - } - + } catch (IOException e) { + logger.log(Level.SEVERE, "Error loading:" + u, e); + } + } + } /** - * Loads the default compatibility mappings by looking for - * joystick-mapping.properties files on the classpath. + * Loads the default compatibility mappings by looking for + * joystick-mapping.properties files on the classpath. */ protected static void loadDefaultMappings() { - for( String s : searchPaths ) { - try { + for (String s : searchPaths) { + try { loadMappings(JoystickCompatibilityMappings.class.getClassLoader(), s); - } catch( IOException e ) { + } catch (IOException e) { logger.log(Level.SEVERE, "Error searching resource path:{0}", s); } } - } + } + + private static class AxisData { + String name; + float[] range; + + AxisData(String name, float[] range) { + this.name = name; + this.range = range; + } + } } diff --git a/jme3-core/src/main/java/com/jme3/input/event/JoyAxisEvent.java b/jme3-core/src/main/java/com/jme3/input/event/JoyAxisEvent.java index 819823bc8f..71d59e06f6 100644 --- a/jme3-core/src/main/java/com/jme3/input/event/JoyAxisEvent.java +++ b/jme3-core/src/main/java/com/jme3/input/event/JoyAxisEvent.java @@ -36,17 +36,36 @@ /** * Joystick axis event. - * + * * @author Kirill Vainer, Paul Speed */ public class JoyAxisEvent extends InputEvent { - final private JoystickAxis axis; - final private float value; + private JoystickAxis axis; + private float value; + private float rawValue; + /** + * Creates a new event for a joystick axis. + * + * @param axis - The axis that generated this event. + * @param value - The value of the axis. + */ public JoyAxisEvent(JoystickAxis axis, float value) { + this(axis, value, value); + } + + /** + * Creates a new event for a joystick axis. + * + * @param axis - The axis that generated this event. + * @param value - The value of the axis, after rescaling took place. + * @param rawValue - The original axis value before it was rescaled by {@link com.jme3.input.JoystickCompatibilityMappings JoystickCompatibilityMappings}. + */ + public JoyAxisEvent(JoystickAxis axis, float value, float rawValue) { this.axis = axis; this.value = value; + this.rawValue = rawValue; } /** @@ -60,9 +79,8 @@ public JoystickAxis getAxis() { /** * Returns the joystick axis index. - * + * * @return joystick axis index. - * * @see com.jme3.input.JoystickAxis#assignAxis(java.lang.String, java.lang.String) */ public int getAxisIndex() { @@ -71,10 +89,9 @@ public int getAxisIndex() { /** * The joystick index. - * + * * @return joystick index. - * - * @see InputManager#getJoysticks() + * @see InputManager#getJoysticks() */ public int getJoyIndex() { return axis.getJoystick().getJoyId(); @@ -82,10 +99,19 @@ public int getJoyIndex() { /** * The value of the axis. - * + * * @return value of the axis. */ public float getValue() { return value; } + + /** + * The value of the axis before it was remapped. + * + * @return value of the axis. + */ + public float getRawValue() { + return rawValue; + } } diff --git a/jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java b/jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java index b467c8cb69..04e0a6a14b 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java +++ b/jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java @@ -65,13 +65,13 @@ public class JInputJoyInput implements JoyInput { private RawInputListener listener; private Map joystickIndex = new HashMap<>(); - + @Override public void setJoyRumble(int joyId, float amount){ - if( joyId >= joysticks.length ) + if( joyId >= joysticks.length ) throw new IllegalArgumentException(); - + Controller c = joysticks[joyId].controller; for (Rumbler r : c.getRumblers()){ r.rumble(amount); @@ -84,34 +84,33 @@ public Joystick[] loadJoysticks(InputManager inputManager){ ControllerEnvironment.getDefaultEnvironment(); Controller[] cs = ce.getControllers(); - List list = new ArrayList<>(); for( Controller c : ce.getControllers() ) { if (c.getType() == Controller.Type.KEYBOARD || c.getType() == Controller.Type.MOUSE) continue; - logger.log(Level.FINE, "Attempting to create joystick for: \"{0}\"", c); - + logger.log(Level.FINE, "Attempting to create joystick for: \"{0}\"", c); + // Try to create it like a joystick - JInputJoystick stick = new JInputJoystick(inputManager, this, c, list.size(), c.getName()); + JInputJoystick stick = new JInputJoystick(inputManager, this, c, list.size(), c.getName()); for( Component comp : c.getComponents() ) { - stick.addComponent(comp); + stick.addComponent(comp); } - + // If it has no axes then we'll assume it's not // a joystick if( stick.getAxisCount() == 0 ) { logger.log(Level.FINE, "Not a joystick: {0}", c); continue; } - + joystickIndex.put(c, stick); - list.add(stick); + list.add(stick); } joysticks = list.toArray( new JInputJoystick[list.size()] ); - + return joysticks; } @@ -129,60 +128,63 @@ public void update() { Event e = new Event(); for (int i = 0; i < cs.length; i++){ Controller c = cs[i]; - + JInputJoystick stick = joystickIndex.get(c); if( stick == null ) continue; - + if( !c.poll() ) continue; - + int joyId = stick.getJoyId(); - + EventQueue q = c.getEventQueue(); while (q.getNextEvent(e)){ Identifier id = e.getComponent().getIdentifier(); if (id == Identifier.Axis.POV){ - float x = 0, y = 0; + float rawX = 0, rawY = 0, x, y; float v = e.getValue(); - + if (v == POV.CENTER){ - x = 0; y = 0; + rawX = 0; rawY = 0; }else if (v == POV.DOWN){ - x = 0; y = -1f; + rawX = 0; rawY = -1f; }else if (v == POV.DOWN_LEFT){ - x = -1f; y = -1f; + rawX = -1f; rawY = -1f; }else if (v == POV.DOWN_RIGHT){ - x = 1f; y = -1f; + rawX = 1f; rawY = -1f; }else if (v == POV.LEFT){ - x = -1f; y = 0; + rawX = -1f; rawY = 0; }else if (v == POV.RIGHT){ - x = 1f; y = 0; + rawX = 1f; rawY = 0; }else if (v == POV.UP){ - x = 0; y = 1f; + rawX = 0; rawY = 1f; }else if (v == POV.UP_LEFT){ - x = -1f; y = 1f; + rawX = -1f; rawY = 1f; }else if (v == POV.UP_RIGHT){ - x = 1f; y = 1f; + rawX = 1f; rawY = 1f; } - JoyAxisEvent evt1 = new JoyAxisEvent(stick.povX, x); - JoyAxisEvent evt2 = new JoyAxisEvent(stick.povY, y); + x = JoystickCompatibilityMappings.remapAxisRange(stick.povX, rawX); + y = JoystickCompatibilityMappings.remapAxisRange(stick.povY, rawY); + JoyAxisEvent evt1 = new JoyAxisEvent(stick.povX, x, rawX); + JoyAxisEvent evt2 = new JoyAxisEvent(stick.povY, y, rawY); listener.onJoyAxisEvent(evt1); listener.onJoyAxisEvent(evt2); }else if (id instanceof Axis){ - float value = e.getValue(); - + float rawValue = e.getValue(); + float value = JoystickCompatibilityMappings.remapAxisRange(stick.povY, rawValue); + JoystickAxis axis = stick.axisIndex.get(e.getComponent()); - JoyAxisEvent evt = new JoyAxisEvent(axis, value); + JoyAxisEvent evt = new JoyAxisEvent(axis, value, rawValue); listener.onJoyAxisEvent(evt); }else if (id instanceof Button){ - - JoystickButton button = stick.buttonIndex.get(e.getComponent()); + + JoystickButton button = stick.buttonIndex.get(e.getComponent()); JoyButtonEvent evt = new JoyButtonEvent(button, e.getValue() == 1f); listener.onJoyButtonEvent(evt); } - } + } } } @@ -209,7 +211,7 @@ public long getInputTimeNanos() { protected class JInputJoystick extends AbstractJoystick { private JoystickAxis nullAxis; - private Controller controller; + private Controller controller; private JoystickAxis xAxis; private JoystickAxis yAxis; private JoystickAxis povX; @@ -217,22 +219,22 @@ protected class JInputJoystick extends AbstractJoystick { private Map axisIndex = new HashMap<>(); private Map buttonIndex = new HashMap<>(); - public JInputJoystick( InputManager inputManager, JoyInput joyInput, Controller controller, + public JInputJoystick( InputManager inputManager, JoyInput joyInput, Controller controller, int joyId, String name ) { super( inputManager, joyInput, joyId, name ); - + this.controller = controller; - - this.nullAxis = new DefaultJoystickAxis( getInputManager(), this, -1, + + this.nullAxis = new DefaultJoystickAxis( getInputManager(), this, -1, "Null", "null", false, false, 0 ); - this.xAxis = nullAxis; - this.yAxis = nullAxis; + this.xAxis = nullAxis; + this.yAxis = nullAxis; this.povX = nullAxis; - this.povY = nullAxis; + this.povY = nullAxis; } protected void addComponent( Component comp ) { - + Identifier id = comp.getIdentifier(); if( id instanceof Button ) { addButton(comp); @@ -244,99 +246,99 @@ protected void addComponent( Component comp ) { } protected void addButton( Component comp ) { - + logger.log(Level.FINE, "Adding button: \"{0}\" id:" + comp.getIdentifier(), comp); - - Identifier id = comp.getIdentifier(); + + Identifier id = comp.getIdentifier(); if( !(id instanceof Button) ) { throw new IllegalArgumentException( "Component is not an button:" + comp ); } String name = comp.getName(); String original = id.getName(); - try { + try { Integer.parseInt(original); } catch (NumberFormatException e){ original = String.valueOf(buttonIndex.size()); } - String logicalId = JoystickCompatibilityMappings.remapComponent( controller.getName(), original ); + String logicalId = JoystickCompatibilityMappings.remapButton( controller.getName(), original ); if( logicalId != original ) { logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId); } - + JoystickButton button = new DefaultJoystickButton( getInputManager(), this, getButtonCount(), name, logicalId ); - addButton(button); + addButton(button); buttonIndex.put( comp, button ); } - + protected void addAxis( Component comp ) { logger.log(Level.FINE, "Adding axis: \"{0}\" id:" + comp.getIdentifier(), comp ); - + Identifier id = comp.getIdentifier(); if( !(id instanceof Axis) ) { throw new IllegalArgumentException( "Component is not an axis:" + comp ); } - + String name = comp.getName(); String original = id.getName(); - String logicalId = JoystickCompatibilityMappings.remapComponent( controller.getName(), original ); + String logicalId = JoystickCompatibilityMappings.remapAxis( controller.getName(), original ); if( logicalId != original ) { logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId); } - - JoystickAxis axis = new DefaultJoystickAxis( getInputManager(), + + JoystickAxis axis = new DefaultJoystickAxis( getInputManager(), this, getAxisCount(), name, logicalId, - comp.isAnalog(), comp.isRelative(), + comp.isAnalog(), comp.isRelative(), comp.getDeadZone() ); - addAxis(axis); + addAxis(axis); axisIndex.put( comp, axis ); - + // Support the X/Y axis indexes if( id == Axis.X ) { xAxis = axis; } else if( id == Axis.Y ) { yAxis = axis; } else if( id == Axis.POV ) { - + // Add two fake axes for the JME provided convenience // axes: AXIS_POV_X, AXIS_POV_Y - povX = new DefaultJoystickAxis( getInputManager(), - this, getAxisCount(), JoystickAxis.POV_X, + povX = new DefaultJoystickAxis( getInputManager(), + this, getAxisCount(), JoystickAxis.POV_X, id.getName() + "_x", comp.isAnalog(), comp.isRelative(), comp.getDeadZone() ); logger.log(Level.FINE, "Adding axis: \"{0}\" id:" + id.getName() + "_x", povX.getName() ); addAxis(povX); - povY = new DefaultJoystickAxis( getInputManager(), - this, getAxisCount(), JoystickAxis.POV_Y, + povY = new DefaultJoystickAxis( getInputManager(), + this, getAxisCount(), JoystickAxis.POV_Y, id.getName() + "_y", comp.isAnalog(), comp.isRelative(), comp.getDeadZone() ); logger.log(Level.FINE, "Adding axis: \"{0}\" id:" + id.getName() + "_y", povY.getName() ); addAxis(povY); } - + } - + @Override public JoystickAxis getXAxis() { return xAxis; - } + } @Override public JoystickAxis getYAxis() { return yAxis; - } + } @Override public JoystickAxis getPovXAxis() { return povX; - } + } @Override public JoystickAxis getPovYAxis() { return povY; - } + } @Override public int getXAxisIndex(){ @@ -347,7 +349,7 @@ public int getXAxisIndex(){ public int getYAxisIndex(){ return yAxis.getAxisId(); } - } + } } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java index 6f3f6a3799..942bbda5d9 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java @@ -100,7 +100,7 @@ public Joystick[] loadJoysticks(final InputManager inputManager) { while (floatBuffer.hasRemaining()) { floatBuffer.get(); - final String logicalId = JoystickCompatibilityMappings.remapComponent(joystick.getName(), convertAxisIndex(axisIndex)); + final String logicalId = JoystickCompatibilityMappings.remapAxis(joystick.getName(), convertAxisIndex(axisIndex)); final JoystickAxis joystickAxis = new DefaultJoystickAxis(inputManager, joystick, axisIndex, convertAxisIndex(axisIndex), logicalId, true, false, 0.0f); joystick.addAxis(axisIndex, joystickAxis); axisIndex++; @@ -112,10 +112,10 @@ public Joystick[] loadJoysticks(final InputManager inputManager) { while (byteBuffer.hasRemaining()) { byteBuffer.get(); - final String logicalId = JoystickCompatibilityMappings.remapComponent(joystick.getName(), String.valueOf(buttonIndex)); + final String logicalId = JoystickCompatibilityMappings.remapButton(joystick.getName(), String.valueOf(buttonIndex)); final JoystickButton button = new DefaultJoystickButton(inputManager, joystick, buttonIndex, String.valueOf(buttonIndex), logicalId); joystick.addButton(button); - joyButtonPressed.put(button, false); + joyButtonPressed.put(button, false); buttonIndex++; } } @@ -145,6 +145,7 @@ public void initialize() { @Override public void update() { + float rawValue, value; for (final Map.Entry entry : joysticks.entrySet()) { // Axes @@ -157,8 +158,9 @@ public void update() { if (axisValues != null) { for (final JoystickAxis axis : entry.getValue().getAxes()) { - final float value = axisValues.get(axis.getAxisId()); - listener.onJoyAxisEvent(new JoyAxisEvent(axis, value)); + rawValue = axisValues.get(axis.getAxisId()); + value = JoystickCompatibilityMappings.remapAxisRange(axis, rawValue); + listener.onJoyAxisEvent(new JoyAxisEvent(axis, value, rawValue)); } }