Control Double-Activation, Pseudo Events?
<i>This post was originally made by <b>skyjake</b> on the dengDevs blog. It was posted under the category: Engine.</i>
I have been continuing my work on the player controls, and it seems that the double-activation feature (which in the past has been used for example for opening a door by triggering the Use control by double-clicking the Forward control) may need a new event type.
My current reasoning is that because we are tracking double activation on all types of controls, including numeric and impulse controls, when the double activation is triggered, it needs to generate an event to which any commands can be bound. However, we currently only have device events (keyboard, mouse, joystick). Furthermore, the data for this double activation event should contain the name of the activated control as well as information about how the activation occurred (e.g., "forward-double", "forward-doublenegative"). Naturally the player number also needs to be included with the event.
The alternative to all this is to just generate "regular" double-click events from the devices (key, mouse, joystick). The trouble is that with device axes they require logic that we already have in the device bindings evaluation, and we also have angle events that would need to be separately processed. So, taken these factors into account, it's better to track the activation of the controls themselves for this kind of "double-clicks". Thus I was thinking that one solution might be to introduce a new kind of event called a pseudo event, which is generated at the time when a control is double-activated. It could contain nothing else besides a text string, which could be used as-is in a "bindevent" command.
The alternative is to add an event type that has the player number, control index, and double-activation state as numerical parameters, but that seems a bit more work to bind events against, as it requires also the routines for saving to and restoring bindings from textual format.
Well, I'll think about this and continue it some other day...
I have been continuing my work on the player controls, and it seems that the double-activation feature (which in the past has been used for example for opening a door by triggering the Use control by double-clicking the Forward control) may need a new event type.
My current reasoning is that because we are tracking double activation on all types of controls, including numeric and impulse controls, when the double activation is triggered, it needs to generate an event to which any commands can be bound. However, we currently only have device events (keyboard, mouse, joystick). Furthermore, the data for this double activation event should contain the name of the activated control as well as information about how the activation occurred (e.g., "forward-double", "forward-doublenegative"). Naturally the player number also needs to be included with the event.
The alternative to all this is to just generate "regular" double-click events from the devices (key, mouse, joystick). The trouble is that with device axes they require logic that we already have in the device bindings evaluation, and we also have angle events that would need to be separately processed. So, taken these factors into account, it's better to track the activation of the controls themselves for this kind of "double-clicks". Thus I was thinking that one solution might be to introduce a new kind of event called a pseudo event, which is generated at the time when a control is double-activated. It could contain nothing else besides a text string, which could be used as-is in a "bindevent" command.
The alternative is to add an event type that has the player number, control index, and double-activation state as numerical parameters, but that seems a bit more work to bind events against, as it requires also the routines for saving to and restoring bindings from textual format.
Well, I'll think about this and continue it some other day...
Comments
Given that a user chooses to "bind w walk" and "bind w-double use" and as double-clicks inherently mean we need to wait an amount of time before triggering; this introduces a logic decision into the engine which is actually game-scope. Do we:
A) Start "walking" and then "use" if/when the time comes.
Wait until we are sure we arn't "use"ing and then start "walking".
In the above example, the user would probably want (A) but it is conceivable that with other control combinations the desired outcome would be (B). For example, in DOOM - changing to the shotgun with a double-press of "3" without having to wait for the super-shotgun to raise before pressing again to change to the shotgun as desired.
In addition, logically, if we handle double-click within the engine it could be argued that other gestural concepts like click-and-hold should be also.
This suggests to me that binding at device-event level is perhaps not the right approach and that if we want the engine to handle things like double-clicks then we should be presenting a higher-level interface to the game, including event combinations and other logic rules.
The problem with that is we can't really expect to be able to cover all input gestures that a game might want (click-and-hold, click-and-drag and even cheat-combinations could even be considered to fall within the same scope). Not to mention the implementation complexity of any such system.
However, I can also appreciate that it would be nice to offer double-click as a feature of the engine as it is such a commonly required gesture, that leaving it to each game to implement similar logic is not ideal.
Saying all that though, my argument is somewhat academic as we could make an exception for double-clicks and leave it to the game(s) to implement anything fancier that they have need for. So perhaps I'm arguing for the sake of clarity of concept/design.
If we want double-clicks to be handled within the engine, shouldn't the double-click threshold be specified per double-activation (in the bind command) rather than one setting that effects all or is that unnecessary?
When it comes to choosing whether to do a single-click or double-click binding, I would always opt for A), but it is possible for the engine to also provide a separate "walk-single" event, which only occurs after the double activation threshold has timed out.
While other gestures such as click-and-hold are interesting, I don't see much value in them. IIRC no one has ever requested them as a feature. We should try to concentrate on doing things that have an actual use, and the double-click thing is something that has been in the original games and that (at least some) people really use.
On a more philosophical level, I think that the engine is the right place for this kind of input controller processing. The games should handle the game logic, not the low-level input events. The double-activation is basically just a generic pattern that the engine can recognize and then notify the rest of system (which can then lead to command execution via a binding).
Regarding the threshold: I don't see any motivation for a per-binding threshold. A user is likely to have his own personal "double clicking rate" that applies to an entire device as a whole. We might have a threshold for each type of device (key, button, axis), but even that I doubt will be useful to anyone.
Ah I see. In that case, yes, that seems to me to be the most logical way to handle double-clicks within the engine.