Actually, your input ideas match my coding very closely.
Here are some basics.
Code: Select all
class InputHandler
{
private:
static std::map<std::string /* Handler Name */,
InputHandler* /* Handler */> handlers;
public:
static std::set<std::string> getHandlerNames(std::set<std::string> &names);
static InputHandler* getHandler(const std::string &name, const std::string &data=std::string(""));
static InputHandler* getHandler(unsigned int player_num, const std::string &name,
const std::string &data=std::string(""));
static const std::string &getHandlerName(const InputHandler * const handler);
InputHandler(unsigned int player_num, const std::string &name);
InputHandler(const std::string &name);
virtual ~InputHandler(void);
std::string GetBindingID(void);
// When removed or set up as a key handler, used to reset the handler.
virtual void Reset(void)=0;
};
class InputInterface
{
private:
static std::set<InputInterface*> Interfaces;
public:
static bool ProcessAllInputs(int whichPlayer);
static bool BindAllInputs(const std::string &mode);
virtual bool ProcessInput(void)=0;
virtual bool BindInputs(const std::string &mode, int whichPlayer)=0;
InputInterface(void) {Interfaces.insert(this);}
virtual ~InputInterface(void) {Interfaces.erase(this);}
};
One of the specialties of this class is a textinputhandler, which gives "raw" key information (actually, not the raw keys, but ascii text from the keyboard all mapped into the active text handler).
There are support for Axis and Key bindings. These do not state which key it is, but instead state what the key went to. If you bind multiple keys to a single action, there would be no telling them apart.
To improve effeciency, I was going to have it so that once a key was pressed, it would indicate the same modifier information when released as when pressed. If you press
shift alt 1 release alt release shift release 1
the alt-shift-1 press and release actions would fire when the 1 was pressed and then released.
I have new handlers (consumers) written to allow this to be placed in now. My understanding was you were working on migrating to Ogre. I did not realize you would tackle a rewrite of the input system as well. I was hoping to help with the migration by giving you the input subsystem while you focused on the graphics side of things. I've already done some work with CEGIU, and was going to use C++ and CEGUI to build a in-game setup program.
I was going to use the events framework from SDL to do the initial input system.
Instead of waiting for events all the time, I was going to let them pile up and handle them during the current keyboard handling time. If nothing's changed, it won't take much time, else it will take the same time as it would have taken to handle the event asynchronously in a seperate thread, and gets rid of a number of race conditions. Since this is called several times a second, the input queue will never get very big. And since inputs are handled right before anything could use the data in the simulation, there would be no additional perceived delay by the user.
So my input processor would have a ProcessEvents function that would be called when it was time to act on the latest inputs. The events would be queued between calls to that function.
One thing this interface system will allow is the selection of seperate bindings for different conditions. For instance, if Player one leaves the Cockpit at a dock, then the bindings could go from Cockpit bindiings to Dock bindings. This should work really, really well with things like command modules versus cockpits and turrets where the input can be tailored to what the user is doing right then. It should also be really nice if a first person perspective is added later.
This input system has the nice advantage that registering an input handler does not bind it, and registering it gives the setup system information that can be used to create a setup screen in a more generic way. It's not finished, but its closer than not started.