-
-
Notifications
You must be signed in to change notification settings - Fork 18.7k
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 support for mouse axes in the input map #80259
Conversation
This kind of change requires a proposal, please open one here, this is to gauge support and various details One already exists that seems to fit this: |
Ah sorry, I didn't realize there was a proposal process for this. I've added a comment to that issue and linked this PR. |
@@ -91,6 +92,17 @@ String EventListenerLineEdit::get_event_text(const Ref<InputEvent> &p_event, boo | |||
if (text.is_empty()) { | |||
text = "(" + TTR("Unset") + ")"; | |||
} | |||
} else if (mouse_motion.is_valid()) { | |||
Vector2 rel = mouse_motion->get_relative(); | |||
if (rel.x < 0){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (rel.x < 0){ | |
if (rel.x < 0) { |
Please run clang-format
as you have several errors like this and indentation errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apologies. I'll get that setup and run later when I'm back on my personal machine.
if (rel.x < 0){ | ||
text = TTR("Mouse X (Left)"); | ||
} else if (rel.x > 0){ | ||
text = TTR("Mouse X (Right)"); | ||
} else if (rel.y < 0){ | ||
text = TTR("Mouse Y (Up)"); | ||
} else { | ||
text = TTR("Mouse Y (Down)"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested this, but on paper it sounds like checking for < or > exactly 0 would be problematic.
Not only do you have to keep your mouse perfectly still after pressing the button, to avoid a misdetected mouse input. But also you'd have to more your mouse perfectly straight to avoid detecting the wrong axis (or in the case of this code, the X axis is easier to trigger than the Y axis).
Suggestion would be to have a higher movement threshold value (e.g. something like "move at least 10 pixels"), and then take the axis with the highest magnitude and use that to decide which input was made. This avoids both issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for displaying the configured axis in the input configuration window. The events bound to those actions are always unit length on one axis. This is not a general to_string implementation for mouse moved events nor is it part of the logic of detecting the action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops my bad, I just looked at the class name and assumed that's what the code was doing without taking a closer look 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally, it works as expected.
Testing project: test_pr_80259.zip
Some comments:
-
Unfortunately, this PR will run into Movement doesn't work as expected when mapping keys and axes to the same action #45628 until it's fixed. Considering the main use case of this PR, I think this is a blocking issue as it breaks the point of this PR. You can see this in the testing project by changing the value of
NO_MOUSE
in the CharacterBody3D script, which uses a separate action without mouse axis inputs. -
I find that you can't really have an ideal mouse sensitivity and gamepad sensitivity with a single value.1 In the testing project, I've set my mouse sensitivity to be acceptable (still a bit high), but the gamepad sensitivity then becomes extremely low.
-
Most games expose mouse sensitivity and gamepad sensitivity as separate toggles, while we don't have any kind of built-in overrides for captured mouse sensitivity. As a result, you still need to identify the source of the input action to apply a dedicated sensitivity modifier. This kind of breaks the point of this PR, unfortunately.
-
Dedicated editor icons for mouse axes are missing, unlike joypad axes which have separate icons.
-
The class reference documentation for InputEventMouseMotion (
doc/classes/InputEventMouseMotion
) should mention that the action's deadzone is ignored for mouse axes. This might be obvious to some, but it's better to mention it explicitly 🙂
I think the core idea of this PR is encouraging, but it needs further work before it's really a net win in most situations.
Footnotes
-
For reference, I use an ASUS ROG Harpe Ace at 1600 dpi (2.4 GHz wireless) and a DualSense (wired) on Linux. ↩
Thank you for taking a look!
I wouldn't say this is the main use case. Given the sensitivities on joystick and mouse inputs are going to be quite different I would expect to not bind joystick and mouse axes to the same input. In my comment on the proposal I pointed out that I would still expect to bind one action for mouse input and a separate one for joystick input. This does mean the two are not treated uniformly, but it still is a win to me because I only have to interact with I also mentioned in that comment that I want to try and build a new input system for Godot that would hopefully be able to address many of these issues because it would be a net-new system that wouldn't need to be concerned with backward compatibility.
Absolutely. I think for now this is going to require multiple actions and two sensitivity values in GDScript. In my future system I'd like to be able to bind per-device sensitivities and such like Unreal and Unity allow.
True if you're trying to combine the actions, but again with the overall limits of the input system I wouldn't expect that to be the case with this PR. To reiterate: the point of this PR is not to enable a single action to handle both mouse and joystick input, it's to enable actions to handle mouse motion at all. In order to support actions that handle multiple device types it's going to be necessary to overhaul the existing system which is beyond the scope of what I was trying to achieve.
Yep that'd be a great thing to add but I'm no artist. Happy to incorporate an icon if folks have or make one.
Ah yes for sure I need to do a documentation pass if this feature is ultimately accepted. |
I think the best option to alleviate the controller/mouse sensitivity issue would be to add a Say you have an action called You cannot apply a multiplier to the result of If each input can have a strength/sensitivity associated with it, this can be avoided. The current convention is that This may cause need for input functions to evaluate an input's strength before any multipliers are applied, returning the unmodified 0-1 axis strength, as is available currently. This scheme would not break compatability, as all InputEvents would have a default Another rather simple feature that I believe would solve many complexity issues with input-related code is an option for input events to "echo" every frame. This would primarily be used to simplify controller camera movement. Currently, you need to use the If a controller axis input is beyond that axes' dead zone, and this echo functionality is enabled, then the controller axis event is fired every frame until the axis returns fo the dead zone. Then controller camera movement is handled in exactly the same way as mouse movement is handled currently. This echo functionality would also extend to key inputs, allowing easy camera control with keys/buttons. Using my input map entry listed above, implementing camera movement for mouse, joystick, and buttons is as simple as: Edit: I realized, after I had finalized this post, that these echoed inputs would also need to be adjusted for delta-time, ideally that would be done automatically, as there are limited use-cases for a framerate-dependent input like that.
Or, using proper input propagation
( This echo functionality combined with the input level strength/sensitivity multiplier creates a greatly streamlined input system, removing lots of repetitive and often boilerplate code, at the cost of two rather small options. |
I very much respect the opinions here. There are clear issues around the input map. That said I think the best solution for all of these is to work on a new input system. I feel the current one has enough deficiencies that continuing to build on it, while having to maintain compatibility, isn’t the wisest use of time. I’ve been wanting to work on an improved input system for Godot so perhaps I’ll come up with a fuller proposal once I have the free time. |
I've just tested this PR rebased against I'll label this as |
It felt odd to me that relative mouse motion could only be referenced by manually handling events in scripts so this PR adds the ability to bind actions to the various mouse axes. It looks like this:
This lets me setup a nice first person input map entirely in the editor:
With that input map setup one can configure a first person controller using only actions which feels a lot more intuitive:
It's my first time contributing to Godot so hopefully I followed all the patterns expected. I tried to keep my code formatted as similar to the surrounding code.