Open markusobi opened 6 years ago
I personally prefer the first approach, makes implementing Views easier and puts less responsibility on them
I am not sure whether the Views are suitable for this. I thought about a hierarchy of context classes. If the parent context gets enabled (e.g. menu shows up) all child contexts receive no more input. This is more or less the same as your suggestion but uses a separate class. Then if a view (or any other gameplay component) requires input it would activate its context. Keep in mind that not all views actually listen to user input (e.g. health bar). Furthermore one could store variables in the context, for example the this
pointer of the PlayerController
.
Since my original implementation of the callback system is often not used as intended I would like to propose a change. I would split up RegisterAction
into several functions:
RegisterTrigger(actionType, void(bool pressed, int slope))
only gets called when pressed
changes it's state. slope
tells you whether the button was pressed (+1) or released (-1). This resembles more or less the regular button.
RegisterTriggerContinuous(actionType, void(bool pressed, int slope))
gets called in every frame. slope
is 0 if button state did not change.
RegisterAxis(actionType, void(float state, float slope))
Represents an axis e.g. a locked mouse or a joystick. This function gets called every frame because there is little sense in determining whether a float value has changed.
RegisterPointer(actionType, void(float2 state, float2 slope))
x and y coordinates of a free mouse or the Nintendo Wii thing or whatever.
RegisterText(actionType, void(unicode character)
Still have to think about how exactly you would do this.
In each of the function you could access it's globally declared context and use this information to determine which character has to move etc.
Just a suggestion. @\all Please get involved and tell us what you think about it.
Keep in mind that not all views actually listen to user input (e.g. health bar).
Such Views would just pass all input through. It would be possible to define default behaviors via enums like:
consume_handled
: Consume all the InputActions, that was registered on it. (probably default behaviour)consume_all_input
: let's nothing through (i.e. for Loading Screen)In case of the Health Bar: consume_handled
+ No binding is registered on it
→ passthrough of all input.
Furthermore one could store variables in the context, for example the this pointer of the
PlayerController
.
Is it easier to update the context
than to update the View
, when the current controlled NPC changes or gets invalidated?
What is the advantage of keeping the context
up to date compared to a View
?
Where do the context
objects live? Inside a ContextTree/ContextList?
Also: You will still need to rebuild the whole ViewTree as ContextTree in order to get the order of Views right.
I would split up
RegisterAction
into several functions
I think this is a good idea. Luckily this change would be largely independent of the proposed change. So it should not be easier/harder to implement it with the current system than with the proposed system.
Okay I'm in favor of your solution because you can avoid the redundancy of defining the view tree twice. I just wonder how you would handle the 3D scene. Somehow put it into a view too or rather create a dummy view which does the input handling for the 3D scene?
Somehow put it into a view too or rather create a dummy view which does the input handling for the 3D scene?
I plan to use a dummy view for the player/camera controls.
@markusobi I would not call it "dummy view", but rather see the main 3d-scene as an UI-View on it's own: The UI-View which shows the game, if that makes sense.
@ataulien Should this 3d-Scene View actually draw the world? Should it directly call GameEngine::drawFrame
?
@markusobi not sure about that. It probably could though! It would allow for picture-in-picture and all such fancy things.
It would allow for picture-in-picture and all such fancy things.
Fancy things like mirrors :-)
And portals!!!
I sense a Gothic Portal Gun Mod. :D
I'm all for portals and mirrors! So, I'm also for this 3d- Scene View- thing :D (is this Option 2, the separate Chain of InputHandler?)
Well, mirrors, portals and other 3d-stuff is usually handled differently. This should not be the reason to chose any of the two options over the other one.
To make our Input system more maintainable/extendable I have worked out two concepts, which might help in this regard.
Concept 1: Views handle Input.
InputActions will be handled by Views ONLY. The topmost View on the screen will receive all input. Each View can decide to handle the InputAction and/or consume it independently.
A View can decide to handle+consume only specifiy InputActions and let all others through. Whether or not a View will consume InputActions will in most cases depend on it's visibility. I.e. when the Loading Screen is visible no binding shall be fired, except for the console (which is on top of the Loading Screen). If there is no associated View for a binding, one can add a empty Pseudo-View at the right position in the View-Tree. i.e. to be able to open the stats screen while the inventory is open, an invisible view can be inserted before the inventory view.
Advantage: Implicit order of InputAction handling/consumption through View draw order. Disadvantages: bound to View/Vieworder. Visibility of Pseudoviews has to be set somewhere.
Concept 2: Passing Input through a separate Chain of InputHandler.
This Concept is very similar to Concept 1, but in this case we are not using the View-Tree, but a separate chain of InputActing handling objects. Analog to Concept 1, an InputAction is passed through the Chain, where each object can decide whether to consume and/or handle it. A draft of how such chain could look like is found here:keyhandling.dot.pdf.
Advantages: Independent of View-Tree.
Goal
The goal behind these concepts is to make it easier to add new input consuming Views without having to add
isViewXYVisible
all over the place (currently all over the place in different InputAction handlers).Feedback is welcome.