UI: `Interaction` has limited usefulness, should have feature parity with `Input`
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What problem does this solve or what need does it fill?
Currently `Interaction` only detects 3 conditions:
- `Clicked`: while pressed using mouse/touch
- `Hovered`: while the mouse pointer is on top
- `None`: none of the above
This is very limiting. For comparison, consider the kinds of things you can detect using `Input`:
- `pressed`: the button is held down (like `Interaction::Clicked`)
- `released`: the button is not pressed
- `just_pressed`: only true the first frame when the button got pressed
- `just_released`: only true the first frame when the button stopped being pressed
Notably, `just_pressed`/`just_released` allow detecting the moment when the mouse click starts or ends. Having such functionality available for UI too, would be *very useful*.
Consider a button in some UI. In many scenarios, you probably want to trigger its action only *once*, not repeatedly every frame while the button is held down (as currently happens if using `Interaction::Clicked`). Further, having the choice between doing it when the button is just pressed vs. just released, can be very useful depending on the intended user experience. Doing it on release can allow the user to cancel / back out of accidentally pressing the wrong UI button, by moving the cursor out of it before releasing. Doing it on on press means instant action/response with no delay, important for buttons in many game UIs.
## What solution would you like?
`Interaction`, instead of being an `enum`, could be converted to an API that mirrors that of `Input`, offering the `pressed`/`just_pressed`/`released`/`just_released` methods, + additionally also hover detection using a `hovered` method.
Pressing should only register if the event happened within the UI element. Pressing the mouse button outside, and then dragging the cursor in, should not cause the `Interaction` to become pressed.
`just_released` should only trigger if the release event happens within the UI element. If the user presses the UI element, then moves the cursor out of it and releases it there, there should be no `just_released`. Instead, we could provide a `canceled` method for detecting this situation.
Touchscreens should behave consistent with this behavior.
This would allow users to write UI code using the same familiar API as for gameplay input. UI has its own additional needs (like hover detection), and this is why I am not proposing to try to reuse `Input` itself outright.
## What alternative(s) have you considered?
Extending the `enum` with more variants:
```rust
enum Interaction {
None,
Hovered,
JustPressed,
Pressed,
JustReleased,
}
```
This is a more straightforward extension of what already exists. Hovever, it suffers from poor usability. The equivalent of the current `Clicked` (detect the button being held down) would have to check for either JustPressed OR Pressed.
## Additional context
I am currently working around the limitations of `Interaction` by also accessing `Res>` and trying to use both simultaneously, so that I can implement the desired behavior. I need `Interaction`, so that I know if the specific UI element is being interacted with, and then I need `Input` for `just_pressed`/`just_released` to figure out the missing information. This is very clunky and annoying, and does not support touch screens.
Contributor guide
Assessment
This issue has not been assessed yet.