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

Fix InputEvent device id clash (reverted) #97707

Merged
merged 1 commit into from
Oct 21, 2024

Conversation

Sauermann
Copy link
Contributor

@Sauermann Sauermann commented Oct 1, 2024

InputMap::ALL_DEVICES and InputEvent::DEVICE_ID_EMULATION have the same value -1, but since both are used for device ids of input events, there could potentially be cases, where they are clashing.

Change value of InputMap::All_DEVICES so that it's different from InputEvent::DEVICE_ID_EMULATION. InputEvent::DEVICE_ID_EMULATION is part of the API and can't be changed without potentially breaking projects.

Gather all special device constants in a single location inside InputEvent.

Add a converter to project settings, that takes care of adjusting project files during loading.

Relevant PRs:

@Sauermann Sauermann added this to the 4.4 milestone Oct 1, 2024
@Sauermann Sauermann requested review from a team as code owners October 1, 2024 19:06
Copy link
Contributor

@RadiantUwU RadiantUwU left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctly implemented

@RandomShaper
Copy link
Member

Makes sense. I have a little concern though. Is the former value for "all devices" stored somewhere? In that case, it'd be appropriate to leave -1 for that.

@Sauermann
Copy link
Contributor Author

The only place, where it is used to set something, is within the Editor.
In InputEventConfigurationDialog it is used to configure an OptionButton.

_set_current_device(InputMap::ALL_DEVICES);

I didn't find any indication, that this OptionButton is saved anywhere.

@Sauermann Sauermann marked this pull request as draft October 2, 2024 21:08
@Sauermann
Copy link
Contributor Author

Sauermann commented Oct 2, 2024

While the OptionButton doesn't get saved, using "All Devices" in the project input map will store -1 within the project.godot file.

devicealltest={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":8,"canceled":false,"pressed":false,"double_click":false,"script":null)
]

Projects that are loaded with the change in its current state will interpret previous ALL_DEVICE input map as DEVICE_ID_EMULATION which could cause problems.

One option to work around this would be:

  • Adjust the device value from -1 to the new value at the time, when the Input Map is loaded from the project.godot file.
  • This could work, because currently only the values -1, ..., 7 can appear there, so that the mapping can happen in an unambiguous way.
  • This compatibility conversion would need to be removed at a time in the future, when compatibility with old project files can be broken.
  • Before trying to implement this change, I would like feedback if this is a sensible way to deal with this situation.

@RandomShaper
Copy link
Member

Why don't just leave -1 for "all devices" and use, say, -2 for emulation?

@Sauermann
Copy link
Contributor Author

Sauermann commented Oct 3, 2024

Same problem, because DEVICE_ID_EMULATION is exposed to GDScript and part of the API, so changing the value would need to be considered as breaking compatibility. I would like to try to avoid this.

@RandomShaper
Copy link
Member

So, being that the case, your proposed workaround seems to be the most sensible thing to do.

@Sauermann Sauermann marked this pull request as ready for review October 17, 2024 16:30
@Sauermann Sauermann requested review from a team as code owners October 17, 2024 16:30
@Sauermann Sauermann force-pushed the fix-input-device-clash branch 2 times, most recently from 586f614 to c327824 Compare October 20, 2024 13:19
@Sauermann
Copy link
Contributor Author

It was necessary to add additional conversion code to InputEventConfigurationDialog.

@@ -508,6 +508,21 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
}
}
}
if (p_from_version <= 5) {
Copy link
Member

@KoBeWi KoBeWi Oct 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to increment project version, otherwise this code will run every time.

static const int CONFIG_VERSION = 5;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to unnecessarily increment the project version number.

This conversion can be implemented without incrementing the project version.
Before this PR, possible values of device id in the project file are: -1, 0, ..., 7
With this PR, possible values of device id in the project file are: -3, 0, ..., 7
So the conversion doesn't affect projects, that are saved with this PR. The conversion just makes sure, that all projects use -3 for "all devices" after they are loaded.

Also it is compatible with future project version increments.

The conversion happens only once during loading, so there shouldn't be any noticeable delay.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least wrap it in DISABLE_DEPRECATED check then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I wrap the section above also in a DISABLE_DEPRECATED check?

if (p_from_version <= 3) {
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
Variant value = E.value.variant;
if (String(E.key).begins_with("input/") && value.get_type() == Variant::ARRAY) {
Array array = value;
Dictionary action;
action["deadzone"] = Variant(0.5f);
action["events"] = array;
E.value.variant = action;
}
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh the other sections is irrelevant at this point. Version 5 is used since 4.0.
But yeah, it should be wrapped too.

core/input/input_event.h Outdated Show resolved Hide resolved
`InputMap::ALL_DEVICES` and `InputEvent::DEVICE_ID_EMULATION` have the
same value `-1`.

Change value of `InputMap::All_DEVICES` so that it's different from
`InputEvent::DEVICE_ID_EMULATION`. `InputEvent::DEVICE_ID_EMULATION`
is part of the API and can't be changed without potentially breaking
projects.

Gather all special device constants in a single location inside
`InputEvent`.

Add a converter to project settings, that takes care of adjusting
project files during loading.
@RandomShaper
Copy link
Member

5 approvals! 😃

@Repiteo Repiteo merged commit ecc2eb7 into godotengine:master Oct 21, 2024
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Oct 21, 2024

Thanks!

@Sauermann Sauermann deleted the fix-input-device-clash branch October 21, 2024 21:51
@passivestar
Copy link
Contributor

Hey, this change breaks compat 🙂

I'm storing keymaps in InputEvent resources because project settings aren't portable. Keyboard stopped working for me, had to figure out why and remap. Not a big deal, just fyi in case you want to add this to a list of breaking changes

@mgiuca
Copy link

mgiuca commented Nov 10, 2024

This also causes a pretty large change to the project.godot file (every action changes its device ID when you open a project and save it in 4.4-dev4). Might be worth calling out in the release notes as well.

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

Successfully merging this pull request may close these issues.