-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
Improve ColorPicker picker shape keyboard and joypad accessibility #99374
base: master
Are you sure you want to change the base?
Improve ColorPicker picker shape keyboard and joypad accessibility #99374
Conversation
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 support this usability improvement in the proposal design, but it needs technical review.
We should make the controller send fake echo events in this case, so that various GUI nodes can handle these directly. However, this should also be done in a way that doesn't affect existing game logic, which is going to be difficult to handle. Perhaps this should only be done for the built-in actions (those starting with Edit: Proposal opened: |
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.
Some usability comments:
- The hue slider should go faster when you adjust it with the keyboard arrows or gamepad buttons. Compare its speed to the color value on the left:
color_value_vs_hue_slider.mp4
Ideally, the speed at which the hue is adjusted should match the color value on the left, which is probably 3× to 4× faster. This can be done by increasing the increment for each button press on the hue slider.
- When using a color picker with a wheel shape, moving upwards should "slide" along the circle when you've reached the top (same for any other edge):
color_value_wheel_slide.mp4
Right now, it stops so you need to manually move to the left then move back up again.
scene/gui/color_picker.cpp
Outdated
// HACK: I cannot draw focus stylebox on the wheel itself, as it's drawing based on shader. | ||
wheel_h_focus_display = memnew(Control); | ||
wheel_margin->add_child(wheel_h_focus_display); | ||
wheel_h_focus_display->set_mouse_filter(MOUSE_FILTER_PASS); | ||
wheel_h_focus_display->set_focus_mode(FOCUS_ALL); | ||
wheel_h_focus_display->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(3, wheel_h_focus_display)); | ||
wheel_h_focus_display->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_uv_input).bind(wheel_h_focus_display)); |
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.
We should be able to draw a special circle focus stylebox (using a dedicated StyleBoxFlat in the editor theme/default project theme), so it matches the wheel's shape. This can be left for a future PR as it's not essential.
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.
The hue slider goes exactly 3.6× slower than value slider in another shape, so your estimations were pretty correct. ^^ It is by design - value and saturation have values 0-100, but hue has values from range 0-360. Making each button press to increase hue in bigger increments always would miss some values. But I added a multiplier if the event is echo, so after few repetions it speeds up. But again, as for now it does not affect controllers. What I'm wondering now is if we should have it configurable in the editor, both for games and for ColorPickers in the editor somehow (in editor settings?). What do you think @Calinou ?
Fixed, please check it now: Nagrywanie.ekranu.2024-11-28.163308.mp4I thought about making the cursor to spin around on the edge if you keep holding the same button, but while it went well for the HSV Wheel shape, it was buggy for both Circle shapes, so I stashed it for now. This is how it looked for HSV Wheel: Nagrywanie.ekranu.2024-11-28.160945.mp4I am not sure if it is worth to try implementing it well for all Circle shapes or skip it, as I don't know if anyone will take advantage of this feature. |
This would be a pretty niche option, so I'd focus on picking a good default instead. |
#82979 could be used for better joypad navigation if it was merged. For now the only way is implement the behavior using NOTIFICATION_PROCESS manually, like it was done in Slider for example. Though the joypad navigation is a bit janky right now. When you enter the main color box, the only way out is either accepting or canceling; you can no longer select another element. There could be 2 focus modes here: one for navigating the elements and one for changing colors using the elements. You could switch them with accept/cancel. We have that in LineEdit. |
scene/gui/color_picker.h
Outdated
@@ -267,6 +274,8 @@ class ColorPicker : public VBoxContainer { | |||
void _sample_draw(); | |||
void _hsv_draw(int p_which, Control *c); | |||
void _slider_draw(int p_which); | |||
int get_wheel_h_change(Vector2 color_change_vector); |
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.
Unused.
scene/gui/color_picker.cpp
Outdated
// HACK: I cannot draw focus stylebox on the wheel itself, as it's drawing based on shader. | ||
wheel_h_focus_display = memnew(Control); |
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.
Can't you use wheel_uv
for that?
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.
In one moment I did. But it meant that I had to add logic for navigating between two focus modes for this control, capturing next/prev actions, because wheel_uv would be used to handle focus for both parts of HSV Wheel.
It added more complexity to the class that is already overloaded with a lot of ifs and was not working well always (like it was sometimes looping focus between those two states when holding ui_focus_prev
action instead of leaving the control and switching to the hex LineEdit. I thought that adding another control for both drawing the focus stylebox and making switching focus more reliable is a better choice.
If it's better to have few more ifs than using this empty control, I can work on it again.
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.
#99515 makes the code cleaner.
If your PR happens to be merged first, I'll simplify it and integrate with my changes.
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 changed the code to not use a dedicated new Control for handling focus of wheel in HSV Wheel shape. Now the wheel
control can grab focus in this shape, while focus stylebox is drawn on wheel_uv
. I had whith wheel_uv
handling everything and working well with ui_focus_prev
and ui_focus_next
, but it ui_up
was glitching and I choose approach that seemed to work always with some tweaks, without introducing a new control.
9826b67
to
bf82ac0
Compare
bf82ac0
to
84dcfa0
Compare
I believe the feature is done with suggestions applied, if I didn't miss something. I squashed all the commits already as well. I attach a sample project to make it easier to test it. It has configured ui next and prev actions on controller shoulder buttons and accept/cancel on A/B buttons of Xbox controller. I believe those buttons should be configured in the InputMap by default, but I think it should be separate PR. Is there anything else I should do? |
84dcfa0
to
b9495ba
Compare
b9495ba
to
c90efdb
Compare
4fe7a5c
to
74e506f
Compare
74e506f
to
aae0af2
Compare
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.
Some more feedback from things I noticed. These aren't critical and can be implemented in future PRs, as this PR already provides a decent baseline for keyboard/gamepad usability:
- It doesn't appear to be possible to select these buttons using the keyboard or gamepad only (highlighted in yellow). This includes using Tab on a keyboard:
- Is it possible to ensure the cursor on the color picker always appears in front of the focus outline? Right now, it'll appear behind the focus outline when at the edges of a circular (or square) picker shape.
The interactions are much better since I last checked. |
1a6056f
to
21e3195
Compare
Shape menu can't be opened with gamepad. It appears for 1 frame and disappears. Using keyboard works fine. EDIT: |
21e3195
to
c0e8c14
Compare
5ded5aa
to
96265b2
Compare
That's interesting. Could you send me the project that you use to test it? You can current version of my test projects attached. |
I use a random project with default ColorPicker on the scene. It's not project-specific. EDIT:
I think the main problem is that |
96265b2
to
da7ceb7
Compare
All controls mentioned by @Calinou should be accessible with keyboard and joypad now. You can now also add and remove presets. I added a new action for deleting preset, Tooltip for preset button describes how to use or remove the color with mouse: I have not pushed changes that dynamically add information about other events connected with deleting the color preset: I am not sure if this is a good idea. And if yes, should I manually modify translations in all *.po files to include extra While experimenting with that I realized that Additionally, I finally decided to add default joypad events for:
|
Translations are edited on Weblate. They are synchronized by maintainers, you should not edit .po files manually. |
While experimenting with accessibility, I realized that ColorPicker does not allow you to move the picker cursor around the color rectangle/wheel with keyboard or joypad (and I needed it, as it's the only part of ColorPicker that I want to show).
This PR implements:
How it works in game and in the editor:
ColorPicker.keyaboard.and.joypad.game.mp4
ColorPicker.keyboard.editor.mp4
I don't really like how it works with the controller, as I'm using
gui_input
to check for actions and the controller does not send echo events, but it's possible to use the controller at least.