Input System (Issue 146)

I started to work on the input system, trying to make it more consistent (also regarding joystick support), introducing an additional event based mode and cleaning it up a bit.

Does someone really need MouseInput.get[Previous]ButtonState()? I would like to remove it as it is not nice IMO to combine button states into a single value and it is not used within jme.

It's used in nui but that can be changed easily and to the better.

To align joystick with keyboard and mouse a method getJoystickInput() in InputSystem should be created - but this cannot be done if joystick becomes a jmex package. What do you prefer?



Edit: what about making MouseInput and KeyboardInput abstract classes and add a get() method?

First, I don't mind Joystick going into the core (i.e. it doesn't have to be a jmex item). So, however you see fit to work things in such that you get the cleanest design.



Second, since you looking at the input system, you might want to take a look at the InputHandler as well. It's due for a revamp. Renanse and I chatted about it, and we thought it might be a good idea if there was a singleton class called InputSystem (or similar) that took an arbitrary number of InputHandlers. During its update it would then call the updates on all its handlers. This would allow you to add any number of handlers. Next, you should be able to enable/disable handlers in InputSystem, effectively allowing you to switch modes, for instance. And lastly, the existing InputHandlers should have mouse and keyboard checks seperated. The most efficient use would to always keep handlers handling one input type (keyboard, mouse, controller, etc). We could enforce this if necessary by creating MouseHandler, Keyboardhandler, etc.



This would allow someone to mix and match handlers. For example, someone might add the mouselook from jME, the FirstPerson movement from jME (WASD) (NOTE: This would be seperate handlers after this change), then create their own handler for chatting. Then when a trigger is called, the movement is disabled and chatting is enabled, and vice versa.

I've proceeded in cleaning up the current input system and think about some conceptual things now:



After discussing with Mark I plan to organize the InputHandlers in a tree. Each InputHandler would have a list of child handlers (composite) and an 'enabled' flag. If the handler is enabled it invokes actions upon events and calls child handlers, if not enabled the update method simply returns. Top level handlers would be called somewhere in the application, e.g. in simpleUpdate.



Another thing I would like is unifying mouse, keyboard and joystick events. So one can create such "configure controls" menus like known from current games. The user may choose whether he wants to steer left/right with his mouse, his joystick or with the keyboard… I'm not sure if this is contradictory to your ideas to separate key- from mouse-handlers - I would say camera look should be separated from camera move - is that your point, too?

Plans for the "event based" handlers look like this:

The key- mouse- and joystick-event listeners are called within the update method of the input system (no separate thread like e.g. in Swing!). A handler does subscribe a listener for each type of input it handles (commonly only one). When the listener receives a call and its handler is enabled it determines the actions that should be invoked (e.g. by a hashtable or an array) and invokes them. An alternative would be to queue the actions and invoke them in the handlers update method (which might be invoked at another time that the input systems update).

The changes should not require any action on jME users or get many classes changed as it's mostly inside InputHandler itself (and a bit in KeyBindingManager, see below).



Additionally I would like to change KeyBindingManager to support multiple commands per key (e.g. 'W' could be "walk forward" and "menu up") even if allowRepeats is false. And it should allow to define keys that must not be down to cause an action (to distinguish between e.g. 'W' and 'shift+W'). A method for querying commands triggered by specified key is also needed.

The old interface would get extended but stays backward compatible.



@renanse: you asked "just wondering what other classes would be altered" - is that question sufficiently answered? Are you unhappy with my cleanup of the input system? (it changed alot of classes)

Hey, irrisor, just looking at some of the changes. So here's something I've noticed:



InputActionEvent only contains time. However, I do need some of its functionality (namely, I need to know what other actions were called (some of my actions depend on others)). This was contained in the eventList in InputActionEvent previous. How would I do that now?



If you have been able to move InputActionEvent's functionality elsewhere, that's fine. But if all it is going to contain is time, we might as well get rid of it and pass a float.

Just talked to you on IM about it, but to "log" it:



While the eventList will probably need to exist somewhere (I put it in for a couple folks that needed to know all events called for some game logic). I don't really need it like I thought, what I need is a String added to InputActionEvent? (I put a question mark as you might have a better place). This String will contain the "trigger" that caused the Action to be fired. I want this because I have actions that are called by a multiple buttons and vary only slightly. For example, "turnLeft" and "turnRight" call the same action, but a (-1) is used on one but not the other. That sort of thing. That seems to me like a good thing for the event to contain, and allow me to check in a clean way.

Hey, you were faster  :slight_smile:



I want to mentioned some more we discussed on IM:

  • add some data about wich key was pressed, how the mouse state changed - depending on the kind of action trigger
  • Action should not need to care about the kind of trigger (mouse, keyboard, joystick, …)
  • use e.g. a trigger name, a float, a boolean and a character (data defined by some contracts for mouse/joystick axes, buttons, etc.)

    -> the developer can let the user choose which controls he would like to use a lot more easily

Regarding the number of classes that would be touched: As Mark wants a single action to be invoked with different triggers, the trigger command can not be stored in the action any more. This requires many classes to be changed. But this time I can keep nearly the complete old functionality, so developers are not forced to change everything immediately, but the methods in the actions got deprecated. Some classes will have to be changed to adapt for the change that InputAction is an abstract class now instead of an interface.



Just posting this because Joshua asked for the number of classes…

I have finished the work on the handlers and would like to commit these changes (patch + new files).

To see important new features in action have a look at TestInputHandler, AbsoluteMouse and InputHandler.addAction(InputAction, String, int, int, boolean).

New features:

  • mouse / keyboard / joystick / other devices nearly completely exchangeable because of common addAction method and triggers
  • pluggable application defined devices to be used by InputHandler possible (I will demonstrate this with a "GUI-Device" soon)
  • AbsoluteMouse location update happens only if mouse is moved, cursor could be controlled by joystick (if some application need that)

Forgot to mention: most JavaDoc (most important are in), feature explanation and HowTo for the Wiki will follow. As well as using the new features more intensively in jME itself.

Go ahead and commit. I didn't mean to imply that people have to ask for permission before committing (just have an issue to commit against).

Started writing a Wiki article - let me know what you think…

I just noticed that if you move the mouse and the keyboard at the same time (eg. look around with the mouse while moving with the keyboard) that the keyboard is ignored.  I see that only on my win2k nvidia box though… very odd.  My winxp box does not exhibit this behavior.  They have the same keyboard and mouse hardware.

In deed very odd - care to debug that to check if it's a jME or a lwjgl problem?  :slight_smile: