From 5901a95363b5e0675023fd5b61878cf829753c50 Mon Sep 17 00:00:00 2001 From: Paul Speed Date: Sun, 31 Mar 2019 20:18:11 -0400 Subject: [PATCH] Added new JoystickAxis.LEFT_TRIGGER/RIGHT_TRIGGER. Updated JoystickCompatibilityMappings to support normalizing joystick names based on a regex. For example: XBOX.regex=(?i).*xbox.* ...will allow configuring all joysticks with xbox in the name with one XBOX configuration. --- .../java/com/jme3/input/JoystickAxis.java | 23 +++++++ .../input/JoystickCompatibilityMappings.java | 60 +++++++++++++++++-- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/input/JoystickAxis.java b/jme3-core/src/main/java/com/jme3/input/JoystickAxis.java index c951ef321..45a073311 100644 --- a/jme3-core/src/main/java/com/jme3/input/JoystickAxis.java +++ b/jme3-core/src/main/java/com/jme3/input/JoystickAxis.java @@ -42,6 +42,29 @@ public interface JoystickAxis { public static final String Y_AXIS = "y"; public static final String Z_AXIS = "z"; public static final String Z_ROTATION = "rz"; + public static final String LEFT_TRIGGER = "rx"; + public static final String RIGHT_TRIGGER = "ry"; + + // Note: the left/right trigger bit may be a bit controversial in + // the sense that this is one case where XBox controllers make a lot + // more sense. + // I've seen the following mappings for various things: + // + // Axis | XBox | Non-Xbox (generally) (includes actual Sony PS4 controllers) + // --------------+-------+--------------- + // left trigger | z | rx (also button 6) + // right trigger | rz | ry (also button 7) + // left stick x | x | x + // left stick y | y | y + // right stick x | rx | z + // right stick y | ry | rz + // + // The issue is that in all cases I've seen, the XBox controllers will + // use the name "xbox" somewhere in their name. The Non-XBox controllers + // never mention anything uniform... even the PS4 controller only calls + // itself "Wireless Controller". In that light, it seems easier to make + // the default the ugly case and the "XBox" way the exception because it + // can more easily be identified. public static final String POV_X = "pov_x"; public static final String POV_Y = "pov_y"; 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 ee2434d54..db3b4aec9 100644 --- a/jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java +++ b/jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java @@ -41,6 +41,8 @@ import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** @@ -63,6 +65,10 @@ public class JoystickCompatibilityMappings { private static Map> joystickMappings = new HashMap>(); + // Remaps names by regex. + private static Map nameRemappings = new HashMap<>(); + private static Map nameCache = new HashMap<>(); + static { loadDefaultMappings(); } @@ -81,11 +87,29 @@ public class JoystickCompatibilityMappings { * is a mapping for it otherwise it returns the original name. */ public static String remapComponent( String joystickName, String componentId ) { - Map map = getMappings(joystickName.trim(), false); - if( map == null ) + 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)); + 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 = getMappings(joystickName, false); + 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); } @@ -130,8 +154,36 @@ public class JoystickCompatibilityMappings { String stick = key.substring(0, split).trim(); String component = key.substring(split+1).trim(); String value = String.valueOf(e.getValue()).trim(); - addMapping(stick, component, value); + if( "regex".equals(component) ) { + // It's a name remapping + addJoystickNameRegex(value, stick); + } + addMapping(stick, component, value); + } + } + + /** + * Maps a regular expression to a normalized name for that joystick. + */ + public static void addJoystickNameRegex( String regex, String name ) { + logger.log(Level.FINE, "addJoystickNameRegex(" + regex + ", " + name + ")"); + nameRemappings.put(Pattern.compile(regex), name); + } + + protected static String getNormalizedName( String name ) { + String result = nameCache.get(name); + if( result != null ) { + return result; + } + for( Map.Entry e : nameRemappings.entrySet() ) { + Pattern p = e.getKey(); + Matcher m = p.matcher(name); + if( m.matches() ) { + nameCache.put(name, e.getValue()); + return e.getValue(); + } } + return null; } /**