The Zandalar project
The Zandalar Project is a codename for the new Input archtecture and GUI navigation features.
Contents
Input Aggregator & events
Use Cases
The use cases are described by steps. For each step there might be some actions done at different levels:
- Raw input = the data that comes directly from the input system the application is using (OIS, glfw, etc.).
- Input Injection = the `InjectedInputReceiver`-ish function called with the right parameters
- For backwards compatibility-ish, we can persist the same interface(InjectedInputReceiver), but provide in it a default implementation that generates the input events for the current interface's functions.
- InputEvent = the `InputEvent` type generated from the injected input. This is the final step, and this is fed to the CEGUI library.
Clicking a button using a mouse
Step description | Raw input | Input Injection | InputEvent fed to CEGUI |
---|---|---|---|
Move the mouse over the button | Mouse movement | injectMouseMove/injectMousePosition | PointerMovementInputEvent |
Press the LMB | Mouse button press | injectMouseButtonDown(LMB) | PointerActivationInputEvent |
Release the LMB | Mouse button release | injectMouseButtonUp(LMB) | PointerDeactivationInputEvent |
The button is clicked (Click event is triggered) | N/A | N/A | N/A |
Clicking/activating a button using the keyboard (new feature)
Step description | Raw input | Input Injection | InputEvent fed to CEGUI |
---|---|---|---|
Focus the button | Uses the use case "Focus a button using the keyboard/gamepad" | ||
Press the ENTER key (1) | Key Button press | injectKeyDown(Enter) | SemanticInputEvent(Confirm) |
Release the ENTER key *** | Key Button release | injectKeyUp(Enter) | ReleasedButtonInputEvent(Confirm) **** (check the semantics table) |
The button is clicked (Click event is triggered) | N/A | N/A | N/A |
(1) the key will be defined as per the NavigationStrategy (GUINavigation project part). If there is no such key defined, the event will be ignored.
Clicking/activating a button using a gamepad
The same as previous Clicking/activating a button using the keyboard, but with the difference that it uses a Gamepad button instead of a Keyboard one.
Type text into a textbox
Step description | Raw input | Input Injection | InputEvent fed to CEGUI |
---|---|---|---|
Focus the textbox | Uses the use case "Focus a textbox using the keyboard/gamepad" | ||
Press a character key | Char press | injectChar(chr) | TextInputEvent(chr) |
Press backspace (delete last char) | Key Button press | injectKeyDown(key) | SemanticInputEvent(DeleteLastCharacter) |
Scroll horizontally with the mouse wheel
Step description | Raw input | Input Injection | InputEvent fed to CEGUI |
---|---|---|---|
Rotate the wheel | Wheel rotation delta | injectMouseWheelChange(delta) | ScrollInputEvent(direction, delta) |
Proposed design
Events
For start, the following events will cover all existing functions in the 'InjectedInputReceiver' interface:
Input Event name | Data | Functions covered |
---|---|---|
PointerMovementInputEvent |
|
|
SemanticInputEvent |
|
|
TextInputEvent |
|
|
ScrollInputEvent |
|
|
Unmapped (yet) functions:
- injectMouseLeaves
Semantics Table
The following table represents the semantic values (members of an ENUM) and the raw event(s) from which they are generated.
injectMouseButtonDown + injectMouseButtonUp
- PointerActivate
- SelectMultipleItems (SHIFT + click)
- SelectCumulative (CTRL+CLICK)
injectMouseButtonClick
- PointerActivate
injectMouseButtonDoubleClick
- PointerActivate
- SelectWord (double click)
injectMouseButtonTripleClick
- PointerActivate
- SelectAll (triple click)
Question: Maybe we should create a standalone event type for pointer activation which also 'records' the number of activations? (for example in the case of double/triple click). The editbox uses double/triple click to select all text. Maybe let semantic action 'select all?'
Question2: What we do with the right/middle/extra mouse buttons (TabControl uses middle and nobutton buttons)?:
- Introduce the idea of 'PointerSource' which can be left/right/middle
- Add separate values: LeftPointerActivation, RightPointerActivation, etc? (I'd go for this)
injectMouseButtonUp
- PointerDeactivate
injectKeyDown + injectKeyUp
- DeleteLastCharacter (backspace)
- DeletePreviousCharacter (del)
- Confirm/Submit (Enter/tab/numpad enter -> This should go into the GUI navigation module)
- SelectLeftCharacter (SHIFT + left arrow)
- SelectRightCharacter (SHIFT + right arrow)
- GoToPreviousCharacter (left arrow)
- GoToPreviousWord (CTRL + left arrow)
- GoToNextCharacter (right arrow)
- GoToNextWord (CTRL + right arrow)
- GoToStartOfLine (home)
- GoToEndOfLine (end)
- SelectAll (CTRL+A)
- Back (escape)
- Undo (CTRL+Z)
- Redo (CTRL+Y)
- Cut (CTRL+X)
- Copy (CTRL+C)
- Paste (CTRL+V)
Decisions
Combining keyboard, gamepad and mouse button pressed actions
We have three ways of handling this.
- Using two types of events (Pressed/ReleasedButtonInputEvent) AND SemanticInputEvent
- We have a "big" enum which contains all possible values for a keyboard, mouse and the gamepad
- The 'raw' events (Pressed/ReleasedButtonInputEvent are triggered every time
- The semantic events are generated only based on a mapping configuration: (button_id) -> (semantic_value). If a specific (button_id) present in the mapping is pressed then a semantic event will be generated with the specified (semantic_value).
- (button_id) is a member of the "big" enum
- (semantic_value) is a user-defined value. Inside CEGUI's system we'll have an enum which is used instead of magic numbers. Users could define their own enum which has indices starting from the last CEGUI's enum member number.
- Using just the raw types of event (Pressed/ReleasedInputEvent) WITHOUT SemanticInputEvent
- This would involve ignoring the explicit click calls, and rather generate them inside the system.
- Using just SemanticInputEvent WITHOUT raw events.
Use cases
Focus a button using the keyboard/gamepad
Just calling focus()
Prerequisite: first control in the current window is focused; navigation is configured.
- Pressed("Tab") = focus next ("next")
- Pressed("CTRL + Tab") = focus previous ("previous")
Steps:
- Press `Tab`
- The next control is focused.
Prerequisite: first control in the current window is focused; navigation is configured:
- Pressed("left") = go left ("left")
- Pressed("right") = go left ("right")
- Pressed("top") = go left ("top")
- Pressed("up") = go left ("up")
- ^The same items but with the gamepad's D-Pad configuration instead of the keys
Steps
- Press a configured key/gamepad button.
- The control in the specified direction is focused.