EDIT:
@pspeed: Well, it can be done, but as of yet, I can’t actually use it for my purposes. Altering the Input Manager stops me from being able to use Nifty (due to the NiftyJmeDisplay becoming outdated). So unless someone knows how to get that to work again, I’m out of luck.
(apparently you can’t just remove the processor for it, create a new instance, and add the processor for the new instance). So I can either get a blank screen or a useless screen as of yet.
Anyway, here’re the dark deeds that seem to have been successful.
You need all of these things to do this. All of them are barely modified from their original versions, but still modified.
AdjustedControllerEnvironment.java
[java]package mygame;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import net.java.games.input.Controller;
import net.java.games.input.ControllerEnvironment;
import net.java.games.input.ControllerEvent;
import net.java.games.input.ControllerListener;
public abstract class AdaptedControllerEnvironment extends ControllerEnvironment
{
public static AdaptedControllerEnvironment defaultEnvironment = null;
protected final ArrayList controllerListeners = new ArrayList();
static void logln(String msg)
{
log(msg + “\n”);
}
static void log(String msg) {
System.out.print(msg);
}
public abstract Controller[] getControllers();
@Override
public void addControllerListener(ControllerListener l)
{
assert (l != null);
this.controllerListeners.add(l);
}
public abstract boolean isSupported();
@Override
public void removeControllerListener(ControllerListener l)
{
assert (l != null);
this.controllerListeners.remove(l);
}
@Override
protected void fireControllerAdded(Controller c)
{
ControllerEvent ev = new ControllerEvent©;
Iterator it = this.controllerListeners.iterator();
while (it.hasNext())
((ControllerListener)it.next()).controllerAdded(ev);
}
@Override
protected void fireControllerRemoved(Controller c)
{
ControllerEvent ev = new ControllerEvent©;
Iterator it = this.controllerListeners.iterator();
while (it.hasNext())
((ControllerListener)it.next()).controllerRemoved(ev);
}
public static AdaptedControllerEnvironment getDefaultEnvironment()
{
if (defaultEnvironment == null)
{
defaultEnvironment = new AdaptedDefaultControllerEnvironment();
}
return defaultEnvironment;
}
public static void resetEnvironment()
{
defaultEnvironment = null;
}
}[/java]
AdaptedDefaultControllerEnvironment.java
[java]package mygame;
import java.io.File;
import java.io.PrintStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.StringTokenizer;
import net.java.games.input.Controller;
import net.java.games.input.ControllerEnvironment;
import net.java.games.util.plugins.Plugins;
public class AdaptedDefaultControllerEnvironment extends AdaptedControllerEnvironment
{
static String libPath;
private ArrayList controllers;
private Collection loadedPlugins = new ArrayList();
static void loadLibrary(final String lib_name)
{
AccessController.doPrivileged(new PrivilegedAction() {
public final Object run() { String lib_path = System.getProperty("net.java.games.input.librarypath");
if (lib_path != null)
System.load(lib_path + File.separator + System.mapLibraryName(lib_name));
else
System.loadLibrary(lib_name);
return null; }
});
}
static String getPrivilegedProperty(final String property)
{
return (String)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() { return System.getProperty(property); }
});
}
static String getPrivilegedProperty(final String property, final String default_value)
{
return (String)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() { return System.getProperty(property, default_value); }
});
}
public Controller[] getControllers()
{
if (this.controllers == null)
{
this.controllers = new ArrayList();
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
AdaptedDefaultControllerEnvironment.this.scanControllers();
return null;
}
});
String pluginClasses = getPrivilegedProperty(“jinput.plugins”, “”) + " " + getPrivilegedProperty(“net.java.games.input.plugins”, “”);
if ((!getPrivilegedProperty(“jinput.useDefaultPlugin”, “true”).toLowerCase().trim().equals(“false”)) && (!getPrivilegedProperty(“net.java.games.input.useDefaultPlugin”, “true”).toLowerCase().trim().equals(“false”))) {
String osName = getPrivilegedProperty(“os.name”, “”).trim();
if (osName.equals(“Linux”)) {
pluginClasses = pluginClasses + " net.java.games.input.LinuxEnvironmentPlugin";
} else if (osName.equals(“Mac OS X”)) {
pluginClasses = pluginClasses + " net.java.games.input.OSXEnvironmentPlugin";
} else if ((osName.equals(“Windows XP”)) || (osName.equals(“Windows Vista”))) {
pluginClasses = pluginClasses + " net.java.games.input.DirectAndRawInputEnvironmentPlugin";
} else if ((osName.equals(“Windows 98”)) || (osName.equals(“Windows 2000”))) {
pluginClasses = pluginClasses + " net.java.games.input.DirectInputEnvironmentPlugin";
} else if (osName.startsWith(“Windows”)) {
System.out.println(“WARNING: Found unknown Windows version: " + osName);
System.out.println(“Attempting to use default windows plug-in.”);
System.out.flush();
pluginClasses = pluginClasses + " net.java.games.input.DirectAndRawInputEnvironmentPlugin”;
} else {
System.out.println(“Trying to use default plugin, OS name " + osName + " not recognised”);
}
}
StringTokenizer pluginClassTok = new StringTokenizer(pluginClasses, " \t\n\r\f,;:");
while (pluginClassTok.hasMoreTokens()) {
String className = pluginClassTok.nextToken();
try {
if (!this.loadedPlugins.contains(className)) {
System.out.println("Loading: " + className);
Class ceClass = Class.forName(className);
ControllerEnvironment ce = (ControllerEnvironment)ceClass.newInstance();
if (ce.isSupported()) {
addControllers(ce.getControllers());
this.loadedPlugins.add(ce.getClass().getName());
} else {
// logln(ceClass.getName() + " is not supported");
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
Controller[] ret = new Controller[this.controllers.size()];
Iterator it = this.controllers.iterator();
int i = 0;
while (it.hasNext()) {
ret[i] = ((Controller)it.next());
i++;
}
return ret;
}
private void scanControllers()
{
String pluginPathName = getPrivilegedProperty(“jinput.controllerPluginPath”);
if (pluginPathName == null) {
pluginPathName = “controller”;
}
scanControllersAt(getPrivilegedProperty("java.home") + File.separator + "lib" + File.separator + pluginPathName);
scanControllersAt(getPrivilegedProperty("user.dir") + File.separator + pluginPathName);
}
private void scanControllersAt(String path)
{
File file = new File(path);
if (!file.exists())
return;
try
{
Plugins plugins = new Plugins(file);
Class[] envClasses = plugins.getExtends(ControllerEnvironment.class);
for (int i = 0; i < envClasses.length; i++)
try {
// ControllerEnvironment.logln("ControllerEnvironment " + envClasses[i].getName() + " loaded by " + envClasses[i].getClassLoader());
ControllerEnvironment ce = (ControllerEnvironment)envClasses[i].newInstance();
if (ce.isSupported()) {
addControllers(ce.getControllers());
this.loadedPlugins.add(ce.getClass().getName());
} else {
// logln(envClasses[i].getName() + " is not supported");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private void addControllers(Controller[] c)
{
for (int i = 0; i < c.length; i++)
this.controllers.add(c[i]);
}
public boolean isSupported()
{
return true;
}
}[/java]
ShowdownJoyInput.java
[java]package mygame;
import com.jme3.input.AbstractJoystick;
import com.jme3.input.DefaultJoystickAxis;
import com.jme3.input.DefaultJoystickButton;
import com.jme3.input.InputManager;
import com.jme3.input.JoyInput;
import com.jme3.input.Joystick;
import com.jme3.input.JoystickAxis;
import com.jme3.input.JoystickButton;
import com.jme3.input.JoystickCompatibilityMappings;
import com.jme3.input.RawInputListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.java.games.input.*;
import net.java.games.input.Component.Identifier;
import net.java.games.input.Component.Identifier.Axis;
import net.java.games.input.Component.Identifier.Button;
import net.java.games.input.Component.POV;
public class ShowdownJoyInput implements JoyInput {
private static final Logger logger = Logger.getLogger(InputManager.class.getName());
private boolean inited = false;
private JInputJoystick[] joysticks;
private RawInputListener listener;
private Map<Controller, JInputJoystick> joystickIndex = new HashMap<Controller, JInputJoystick>();
public void setJoyRumble(int joyId, float amount){
if( joyId >= joysticks.length )
throw new IllegalArgumentException();
Controller c = joysticks[joyId].controller;
for (Rumbler r : c.getRumblers()){
r.rumble(amount);
}
}
public Joystick[] loadJoysticks(InputManager inputManager){
AdaptedControllerEnvironment ce =
AdaptedControllerEnvironment.getDefaultEnvironment();
Controller[] cs = ce.getControllers();
List<Joystick> list = new ArrayList<Joystick>();
for( Controller c : ce.getControllers() ) {
if (c.getType() == Controller.Type.KEYBOARD
|| c.getType() == Controller.Type.MOUSE)
continue;
logger.log(Level.INFO, "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());
for( Component comp : c.getComponents() ) {
stick.addComponent(comp);
}
// If it has no axes then we'll assume it's not
// a joystick
if( stick.getAxisCount() == 0 ) {
logger.log(Level.INFO, "Not a joystick: {0}", c);
continue;
}
joystickIndex.put(c, stick);
list.add(stick);
}
joysticks = list.toArray( new JInputJoystick[list.size()] );
return joysticks;
}
public void initialize() {
inited = true;
}
public void update() {
AdaptedControllerEnvironment ce =
AdaptedControllerEnvironment.getDefaultEnvironment();
Controller[] cs = ce.getControllers();
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 v = e.getValue();
if (v == POV.CENTER){
x = 0; y = 0;
}else if (v == POV.DOWN){
x = 0; y = -1f;
}else if (v == POV.DOWN_LEFT){
x = -1f; y = -1f;
}else if (v == POV.DOWN_RIGHT){
x = 1f; y = -1f;
}else if (v == POV.LEFT){
x = -1f; y = 0;
}else if (v == POV.RIGHT){
x = 1f; y = 0;
}else if (v == POV.UP){
x = 0; y = 1f;
}else if (v == POV.UP_LEFT){
x = -1f; y = 1f;
}else if (v == POV.UP_RIGHT){
x = 1f; y = 1f;
}
JoyAxisEvent evt1 = new JoyAxisEvent(stick.povX, x);
JoyAxisEvent evt2 = new JoyAxisEvent(stick.povY, y);
listener.onJoyAxisEvent(evt1);
listener.onJoyAxisEvent(evt2);
}else if (id instanceof Axis){
float value = e.getValue();
JoystickAxis axis = stick.axisIndex.get(e.getComponent());
JoyAxisEvent evt = new JoyAxisEvent(axis, value);
listener.onJoyAxisEvent(evt);
}else if (id instanceof Button){
JoystickButton button = stick.buttonIndex.get(e.getComponent());
JoyButtonEvent evt = new JoyButtonEvent(button, e.getValue() == 1f);
listener.onJoyButtonEvent(evt);
}
}
}
}
public void destroy() {
inited = false;
}
public boolean isInitialized() {
return inited;
}
public void setInputListener(RawInputListener listener) {
this.listener = listener;
}
public long getInputTimeNanos() {
return 0;
}
protected class JInputJoystick extends AbstractJoystick {
private JoystickAxis nullAxis;
private Controller controller;
private JoystickAxis xAxis;
private JoystickAxis yAxis;
private JoystickAxis povX;
private JoystickAxis povY;
private Map<Component, JoystickAxis> axisIndex = new HashMap<Component, JoystickAxis>();
private Map<Component, JoystickButton> buttonIndex = new HashMap<Component, JoystickButton>();
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,
"Null", "null", false, false, 0 );
this.xAxis = nullAxis;
this.yAxis = nullAxis;
this.povX = nullAxis;
this.povY = nullAxis;
}
protected void addComponent( Component comp ) {
Identifier id = comp.getIdentifier();
if( id instanceof Button ) {
addButton(comp);
} else if( id instanceof Axis ) {
addAxis(comp);
} else {
logger.log(Level.INFO, "Ignoring: \"{0}\"", comp);
}
}
protected void addButton( Component comp ) {
logger.log(Level.INFO, "Adding button: \"{0}\" id:" + comp.getIdentifier(), comp);
Identifier id = comp.getIdentifier();
if( !(id instanceof Button) ) {
throw new IllegalArgumentException( "Component is not an axis:" + comp );
}
String name = comp.getName();
String original = id.getName();
String logicalId = JoystickCompatibilityMappings.remapComponent( controller.getName(), original );
if( name != original ) {
logger.log(Level.INFO, "Remapped:" + original + " to:" + logicalId);
}
JoystickButton button = new DefaultJoystickButton( getInputManager(), this, getButtonCount(),
name, logicalId );
addButton(button);
buttonIndex.put( comp, button );
}
protected void addAxis( Component comp ) {
logger.log(Level.INFO, "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 );
if( name != original ) {
logger.log(Level.INFO, "Remapped:" + original + " to:" + logicalId);
}
JoystickAxis axis = new DefaultJoystickAxis( getInputManager(),
this, getAxisCount(), name, logicalId,
comp.isAnalog(), comp.isRelative(),
comp.getDeadZone() );
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,
id.getName() + "_x",
comp.isAnalog(), comp.isRelative(), comp.getDeadZone() );
logger.log(Level.INFO, "Adding axis: \"{0}\" id:" + id.getName() + "_x", povX.getName() );
addAxis(povX);
povY = new DefaultJoystickAxis( getInputManager(),
this, getAxisCount(), JoystickAxis.POV_Y,
id.getName() + "_y",
comp.isAnalog(), comp.isRelative(), comp.getDeadZone() );
logger.log(Level.INFO, "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(){
return xAxis.getAxisId();
}
@Override
public int getYAxisIndex(){
return yAxis.getAxisId();
}
}
}
[/java]
And lastly (sort of; there’s also the business of making sure all your files use the right input manager now), the following method in the extension of a SimpleApplication. The calling of this method should be the first thing in SimpleInitApp():
[java]public void rebuildInputManager()
{
if (AdaptedControllerEnvironment.defaultEnvironment != null)
{
AdaptedControllerEnvironment.resetEnvironment();
}
this.joyInput = new ShowdownJoyInput();
System.out.println("JOY to the world: " + joyInput.loadJoysticks(inputManager).length);
this.joyInput.initialize();
inputManager = new InputManager(this.mouseInput, this.keyInput, this.joyInput, this.touchInput);
if (inputManager != null)
{
if (context.getType() == Type.Display) {
inputManager.addMapping(INPUT_MAPPING_EXIT, new KeyTrigger(KeyInput.KEY_ESCAPE));
}
if (stateManager.getState(StatsAppState.class) != null) {
inputManager.addMapping(INPUT_MAPPING_HIDE_STATS, new KeyTrigger(KeyInput.KEY_F5));
inputManager.addListener(actionListener, INPUT_MAPPING_HIDE_STATS);
}
inputManager.addListener(actionListener, INPUT_MAPPING_EXIT);
}
System.out.println("Input Check");
System.out.println(inputManager);
System.out.println(this.getInputManager());
//if (niftyDisplay != null)
// {
// guiViewPort.removeProcessor(niftyDisplay);
// niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
// nifty = niftyDisplay.getNifty();
// guiViewPort.addProcessor(niftyDisplay);
// }
// initJoy();
}[/java]
The commented parts are just my attempt at getting nifty to work again. This method needs to be called every time you want to check for a change in input devices.
Anyway, probably not the best solution, but it does seem to work; provided you’re not using Nifty at all. I haven’t been able to test whether input maps properly, but a RawInputListener catches all the new controller’s movements, so I’d assume it would.
Well that’s what I’ve got; I’m still hoping to find a way around the Nifty issue, but even if I can’t, hopefully someone else can find some use from this.