Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MouseMovement to InputMap #3070

Open
addmix opened this issue Aug 1, 2021 · 17 comments
Open

Add MouseMovement to InputMap #3070

addmix opened this issue Aug 1, 2021 · 17 comments

Comments

@addmix
Copy link

addmix commented Aug 1, 2021

Describe the project you are working on

Multiplayer FPS focused on high levels of customization

Describe the problem or limitation you are having in your project

There is no way to bind InputEventMouseMotion to an InputEvent, not allowing players to either:
A. bind keys to camera movement
B. bind mouse movements to other controls such as walking

Beyond this, there is no standard way to control sensitivity on InputEvents without writing a custom system, making it more difficult for developers to implement customization of the sensitivity of "key to analog" controls.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

InputEventMouseMotion can trigger InputMap actions after surpassing the deadzone value, similar to InputEventJoyAxis inputs. This allows developers the option to use InputEvent.is_action("action") for mouse movements, and allows easier integration of Keyboard, Joystick, and Mouse input options.

The sensitivity value is added to InputEvent, allowing a uniform location to find sensitivity multipliers. This allows controlling sensitivity on a per-input basis, for cases where you would like to hotswap between two input modes.

The MovementType enum is added to InputEvent, with the Button, Joystick, and Movement values, indicating how the input should be interpreted, whether it be like a key, Joypad joystick, or mouse movement respectively. This helps to identify how an input should behave, in the case that you desire an input to be interpreted differently (i.e. having a keyboard input be interpreted as a mouse input)

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

using InputEventMouseMotion as a
if InputEventMouseMotion.relative > deadzone: ##InputMap action evaluates to true
if Input.is_action_pressed("MouseMotion"): ##the player is moving the mouse

InputEvent sensitivity
func _unhandled_input(event): if event is InputEventMouseMotion: move_camera(event.relative * event.sensitivity)

InputEvent movement type
if event.movement_type == InputEvent.MOVEMENT_TYPE_JOYSTICK: ##use joystick movement mode

If this enhancement will not be used often, can it be worked around with a few lines of script?

Hardcoding these behaviors can be easily done, but a system outside of InputMap that could allow players to customize controls would be very time consuming for developers.

Is there a reason why this should be core and not an add-on in the asset library?

It extends the InputMap's functionality, and could not be extended without a custom build of Godot.

@Calinou
Copy link
Member

Calinou commented Aug 1, 2021

This is a good idea on paper – I'd like to have an easier way to support both mouse and controller aiming in FPS controllers and the like.

The issue is that unlike joystick analog axes, mouse speed has no maximum value. High-end mice can be flicked at several meters per second with the sensor still being able to track the movement correctly. This means its axis' strength could go above 1.0 momentarily. (You really don't want to clamp the strength to 1.0, as this would make fast mouse movements ineffective in first-person aiming.)

@addmix
Copy link
Author

addmix commented Aug 1, 2021

Realistically, I see no reason it needs to be clamped to 0-1, use the current 0-1 value of joystick axis multiplied by sensitivity to get a ready to interpret value, which can also be done for key press events.
Maybe an addition of a function similar to InputEvent.get_action_strength(), but for the non-clamped, sensitivity adjusted value.

@groud
Copy link
Member

groud commented Aug 1, 2021

I don't see the point. First, mouse input and joystick/keyboard input are very different systems which, as mentioned by @Calinou do not work on similar scales. The InputMap system is, as its name suggests, an input mapping system. I see no game, and thus no real life use case, that would allow you to remap a mouse movement to a key-based action. That would be quite confusing.

The sensitivity problem thing is a matter of multiplying the key/joystick value by a number. There's no need to make it built-in to the input mapping system, it's kind of out of its scope.

Overall, I think this proposal makes things more complex for not very significant gains, and can be worked around with very few lines of code. Thus I don't think it's worth.

@addmix
Copy link
Author

addmix commented Aug 1, 2021

There are many uses for non-standard input methods, so much so, the Xbox adaptive controller exists, because not everyone does input the same. To enable things such as this, there should be a method to bind a mouse axis to an action, just like you can with a joypad axis, which, if you have one, it doesn't make sense to exclude the other, as they are similar, and used in similar situations. The recent increases of optical/laser keyboards on the market only furthers the necessity to adjust how inputs work on a fundamental level.

Sensitivity lies naturally in the InputEvent class, as sensitivity of an input belongs with that input. Adjustable sensitivity is present in almost every game, and would be utilized by most projects. If this simple value was added to InputEvents, developers dont need to make a system to save and load sensitivities, while also disorganizing their input editing menu to implement this separate system.

Sensitivity is such a ubiquitous option in the modern day, it makes little sense to not include in the systems already in place. Whether it affects the value of InputEventMouseMotion.relative or not, it being readily accessible would greatly improve usability, without the prerequisite of making your own input system.

@groud
Copy link
Member

groud commented Aug 2, 2021

I mean, all what you describe is right. But I still don't see the need for it. All of this has nothing to do with input mapping. It is simply a matter of handling different input devices and having a menu to support remapping.
The only situation where I guess it could be useful is when you want to be able to move a cursor with keys/joypad axies, but this cannot be done in the input mapping class as it require to tell the OS to move the mouse itself (at least on PC). It's another system that would require much more than input mapping. (I guess we could have built-in actions to do that?)

Sensitivity can be handled by the user, I see no point in adding it to the input event class, as it's not something that's generated by the OS. It's very few lines of code and not every games would need it.

I'd be happy to be proven wrong, but for now, I can't seem to find any real life use cases where what you describe is absolutely needed. Adding two properties to input events (relative and sensitivity I guess) only to support mapping mouse motion events to actions is making the system more complex for no real-life gain IMHO.

@addmix
Copy link
Author

addmix commented Aug 2, 2021

I am wiling to concede the adding of mouse movements to the input map, it still makes little sense to include joysticks axis, while excluding mouse movements. You could work around the entire InputMap system with the same amount of code as it takes to implement sensitivity outside the InputMap. (also, mouse gestures would be easier if mouse movements were in the input map).

The sensitivity property on InputEvents, and the UI to set the value would be maybe 5 lines of code in the engine, to achieve the same effect as an addon to the engine, would take significantly more code, and not be very performant. It's a small addition, with huge potential. Those of us who played a significant amount of Kerbal Space Program understand how useful adjustsable sensitivity on mouse controls is (docking spacecraft, and getting the perfect orbit is hard with the default on/off sensitivity of keys).

I would be more than willing to do it myself, I'm just not sure if it would be accepted or not.

@addmix
Copy link
Author

addmix commented Aug 2, 2021

Maybe not even calling it "sensitivity" and just having it as an ambiguous value for InputEvent.

@Calinou
Copy link
Member

Calinou commented Aug 2, 2021

Isn't mouse sensitivity just implemented as a multiplier for whatever action is being done? To me, it seems this should be handled by game code since there are some cases where you'll want to change this at run-time (e.g. the player sprinting or being incapacited by certain debuffs). It's hard to provide a "one size fits all" solution here.

@addmix
Copy link
Author

addmix commented Aug 2, 2021

Again, to reiterate, I desire the sensitivity modifier on the base InputEvent class, so it could be used for keys, joypad buttons, or axis. The sensitivity value on the InputEvent is to cover the input side, acting similar to a joystick axis clamped value, but making it more available for the end user to customize. As you mention, sprinting, incapacitation, or debuffs would be handled by game code modifiers, which wouldn't require the same saving/loading system that a sensitivity setting would.

Beyond this, it being an abitrary value in the InputEvent class, and having no effect on event.relative values, developers can choose where and when to apply sensitivity, removing a large burden for making sensitivity settings separate from the inputmap.

@addmix
Copy link
Author

addmix commented Aug 11, 2021

Then again, with blended input modes like how the Steam controller had dual purpose trackpad/joysticks, which could act in two different ways depending on context, this only strengthens the need for this addition.

@ghost
Copy link

ghost commented Aug 4, 2023

As referenced by @AThousandShips I didn't realize this proposal process existed and wrote an implementation of this because I also felt it was odd that I couldn't access mouse axes through the input map system.

Longer term I really would like to try implementing something like Unreal's Enhanced Input or Unity's new Input System which allow for configuring sensitivity and such directly in the map which would alleviate the concerns that mouse axes and joystick axes are on different scales.

That said, even if my game has to have "Look Up (Mouse)" and "Look Up (Joystick)", due to the aforementioned input scale issues, that still feels like a win because my GDScript can be more readable by having to only use Input.get_axis for mouse/joystick and then picking the value that's non-zero. The current system requires me to learn an entirely different way of input handling (with events) and thus scatters my input handling into two functions.

@Servail
Copy link

Servail commented Nov 14, 2023

Doh... someone just implement this already using strength >1! It's essential if you want to cheap-unify camera movement with keys and mouse and joystick. Isn't that the point of input map? Elsefore, you still do code to access actions anyway, then why bother having joystick axes on input map (or even keys/buttons lol)?
It can be >0 absolute and <0 relative to differentiate for "sensitivity" and not breaking compat, or maybe begin with 1, but thats kinda stupid. Joysticks have shared sens multiplier with buttons right now and no problemo! I've seen unified "camera sensitivity" parameter in games, not ideal but real.
Also there is mouse-like relative value for joy axes - velocity! (I mean change in abs value over time.) It can be used in games like angry birds for example. So another "RelativeStrength" value is the best approach.
For now you just ending up writing your own input solution for anything more complex than "press x to win".
P.S.: There also may be multiple mouses or keyboards connected, think about it ;)

@addmix
Copy link
Author

addmix commented Nov 14, 2023

P.S.: There also may be multiple mouses or keyboards connected, think about it ;)

This would be a great feature to have. Unfortunately, Windows, and many other OS's don't categorize input between different keyboard and mouse devices, rather lumping them all together as if they were all a single mouse and single keyboard device.

Unfortunately, I'm not sure why #80259 was closed, as it seems that the blocking issue is resolved in 4.2. I may look into forking @ohthesetrees' implementation, and hopefully appease everyone's expectations. I do still believe that having a sensitivity value for each bound InputEvent would be the most effective, and have utility reaching far beyond mouse/joystick axis bindings.

@Servail
Copy link

Servail commented Nov 14, 2023

This would be a great feature to have. Unfortunately, Windows, and many other OS's don't categorize input between different keyboard and mouse devices, rather lumping them all together as if they were all a single mouse and single keyboard device.

I think I've seen some libraries to circumvent this. Since we don't need multiple cursors in OS session, it must be possible to just read raw events from devices before OS starts lumping them.

@Calinou
Copy link
Member

Calinou commented Nov 15, 2023

Please move the discussion about supporting multiple keyboards/mice to #19.

@addmix
Copy link
Author

addmix commented Feb 9, 2024

This is a good idea on paper – I'd like to have an easier way to support both mouse and controller aiming in FPS controllers and the like.

The issue is that unlike joystick analog axes, mouse speed has no maximum value. High-end mice can be flicked at several meters per second with the sensor still being able to track the movement correctly. This means its axis' strength could go above 1.0 momentarily. (You really don't want to clamp the strength to 1.0, as this would make fast mouse movements ineffective in first-person aiming.)

This problem has lingered in my mind, but I see where the disconnect of ideas is. Maximum value doesn't need to be enforced in all cases, for mice, or other novel control methods. Controller and mouse input don't need to coexist within the same inputmap action.

Here's what I have found to be the most effective way to implement mouse and controller camera movement that can coexist, and it's rather simple. Create separate sets of InputMap actions, one as direct input (mouse), and one as a cumulative input (controller). The two can both contribute to the camera's movement, but are still evaluated differently due to their separate actions.

Similarly, you would have two separate inputmap actions for hold sprint and toggle sprint, hold aim and toggle aim, hold crouch and toggle crouch, this allows a user to have both functionalities accessible simultaneously, which may be desirable for games where varied control schemes/input devices may be desired in certain circumstances (think: Player in a vehicle may want to use a racing wheel, but they may want to transition back to keyboard/mouse once they have exited).

image
image
image
This control scheme would still benefit from the addition of mouse axes to the input map.

There's no use in trying to combine two sets of functionality into one configuration, it only reduces the end user's ability to directly customize how their controls are interpreted in-game.

@Calinou
Copy link
Member

Calinou commented Feb 9, 2024

Here's what I have found to be the most effective way to implement mouse and controller camera movement that can coexist, and it's rather simple. Create separate sets of InputMap actions, one as direct input (mouse), and one as a cumulative input (controller). The two can both contribute to the camera's movement, but are still evaluated differently due to their separate actions.

Similarly, you would have two separate inputmap actions for hold sprint and toggle sprint, hold aim and toggle aim, hold crouch and toggle crouch, this allows a user to have both functionalities accessible simultaneously, which may be desirable for games where varied control schemes/input devices may be desired in certain circumstances (think: Player in a vehicle may want to use a racing wheel, but they may want to transition back to keyboard/mouse once they have exited).

I agree this is the way to go (see Minecraft and Thief respectively), although it leads to more complex options menus not all developers may be willing to put up with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants