# Objective
- Fixes#12639.
- `ReceivedCharacter` was deprecated in #12868 for 0.14, and should be
removed for 0.15.
## Solution
- Remove all instances of `ReceivedCharacter`, including the relevant
`#[allow(deprecated)]` lint attributes.
## Migration Guide
`ReceivedCharacter` was deprecated in 0.14 due to `winit` reworking
their keyboard system. It has now been fully removed. Switch to using
`KeyboardInput` instead.
```rust
// 0.14
fn listen_characters(events: EventReader<ReceivedCharacter>) {
for event in events.read() {
info!("{}", event.char);
}
}
// 0.15
fn listen_characters(events: EventReader<KeyboardInput>) {
for event in events.read() {
// Only check for characters when the key is pressed.
if !event.state.is_pressed() {
continue;
}
// Note that some keys such as `Space` and `Tab` won't be detected as a character.
// Instead, check for them as separate enum variants.
match &event.logical_key {
Key::Character(character) => {
info!("{} pressed.", character);
},
Key::Space => {
info!("Space pressed.");
},
_ => {},
}
}
}
```
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
# Objective
- Add custom images as cursors
- Fixes#9557
## Solution
- Change cursor type to accommodate both native and image cursors
- I don't really like this solution because I couldn't use
`Handle<Image>` directly. I would need to import `bevy_assets` and that
causes a circular dependency. Alternatively we could use winit's
`CustomCursor` smart pointers, but that seems hard because the event
loop is needed to create those and is not easily accessable for users.
So now I need to copy around rgba buffers which is sad.
- I use a cache because especially on the web creating cursor images is
really slow
- Sorry to #14196 for yoinking, I just wanted to make a quick solution
for myself and thought that I should probably share it too.
Update:
- Now uses `Handle<Image>`, reads rgba data in `bevy_render` and uses
resources to send the data to `bevy_winit`, where the final cursors are
created.
## Testing
- Added example which works fine at least on Linux Wayland (winit side
has been tested with all platforms).
- I haven't tested if the url cursor works.
## Migration Guide
- `CursorIcon` is no longer a field in `Window`, but a separate
component can be inserted to a window entity. It has been changed to an
enum that can hold custom images in addition to system icons.
- `Cursor` is renamed to `CursorOptions` and `cursor` field of `Window`
is renamed to `cursor_options`
- `CursorIcon` is renamed to `SystemCursorIcon`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
# Objective
Adds a new `Monitor` component representing a winit `MonitorHandle` that
can be used to spawn new windows and check for system monitor
information.
Closes#12955.
## Solution
For every winit event, check available monitors and spawn them into the
world as components.
## Testing
TODO:
- [x] Test plugging in and unplugging monitor during app runtime
- [x] Test spawning a window on a second monitor by entity id
- [ ] Since this touches winit, test all platforms
---
## Changelog
- Adds a new `Monitor` component that can be queried for information
about available system monitors.
## Migration Guide
- `WindowMode` variants now take a `MonitorSelection`, which can be set
to `MonitorSelection::Primary` to mirror the old behavior.
---------
Co-authored-by: Pascal Hertleif <pascal@technocreatives.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
# Objective
- Continue to pare down the uses on NonSend resources in the engine. In
this case, EventLoopProxy used to be `!Sync`, but is now `Sync` in the
latest version of winit.
## Solution
- New type `EventLoopProxy` as `EventLoopProxyWrapper` to make it into a
normal resource.
- Update the `custom_user_event` example as it no longer needs to
indirectly access the `EventLoopProxy` through a static variable
anymore.
## Testing
- Ran the example. The resource exists just for users to use, so there
aren't any in engine uses for it currently.
---
## Changelog
- make EventLoopProxy into a regular resource.
## Migration Guide
`EventLoopProxy` has been renamed to `EventLoopProxyWrapper` and is now
`Send`, making it an ordinary resource.
Before:
```rust
event_loop_system(event_loop: NonSend<EventLoopProxy<MyEvent>>) {
event_loop.send_event(MyEvent);
}
```
After:
```rust
event_loop_system(event_loop: Res<EventLoopProxy<MyEvent>>) {
event_loop.send_event(MyEvent);
}
```
# Objective
- Bevy currently has lot of invalid intra-doc links, let's fix them!
- Also make CI test them, to avoid future regressions.
- Helps with #1983 (but doesn't fix it, as there could still be explicit
links to docs.rs that are broken)
## Solution
- Make `cargo r -p ci -- doc-check` check fail on warnings (could also
be changed to just some specific lints)
- Manually fix all the warnings (note that in some cases it was unclear
to me what the fix should have been, I'll try to highlight them in a
self-review)
# Objective
- Often in games you will want to create chains of systems that modify
some event. For example, a chain of damage systems that handle a
DamageEvent and modify the underlying value before the health system
finally consumes the event. Right now this requires either:
* Using a component added to the entity
* Consuming and refiring events
Neither is ideal when really all we want to do is read the events value,
modify it, and write it back.
## Solution
- Create an EventMutator class similar to EventReader but with ResMut<T>
and iterators that return &mut so that events can be mutated.
## Testing
- I replicated all the existing tests for EventReader to make sure
behavior was the same (I believe) and added a number of tests specific
to testing that 1) events can actually be mutated, and that 2)
EventReader sees changes from EventMutator for events it hasn't already
seen.
## Migration Guide
Users currently using `ManualEventReader` should use `EventCursor`
instead. `ManualEventReader` will be removed in Bevy 0.16. Additionally,
`Events::get_reader` has been replaced by `Events::get_cursor`.
Users currently directly accessing the `Events` resource for mutation
should move to `EventMutator` if possible.
---------
Co-authored-by: poopy <gonesbird@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#13299
On Linux/X11, changing focus into a winit window will produce winit
KeyboardInput events with a "is_synthetic=true" flag that are not
intended to be used. Bevy erroneously passes them on to the user,
resulting in phantom key presses.
## Solution
This patch properly filters out winit KeyboardInput events with
"is_synthetic=true".
For example, pressing Alt+Tab to focus a bevy winit window results in a
permanently stuck Tab key until the user presses Tab once again to
produce a winit KeyboardInput release event. The Tab key press event
that causes this problem is "synthetic", should not be used according to
the winit devs, and simply ignoring it fixes this problem.
Synthetic key **releases** are still evaluated though, as they are
essential for correct release key handling. For example, if the user
binds the key combination Alt+1 to the action "move the window to
workspace 1", places the bevy game in workspace 2, focuses the game and
presses Alt+1, then the key release event for the "1" key will be
synthetic. If we would filter out all synthetic keys, the bevy game
would think that the 1 key remains pressed forever, until the user
manually presses+releases the key again inside bevy.
Reference:
https://docs.rs/winit/0.30.0/winit/event/enum.WindowEvent.html#variant.KeyboardInput.field.is_synthetic
Relevant discussion: https://github.com/rust-windowing/winit/issues/3543
## Testing
Tested with the "keyboard_input_events" example. Entering/exiting the
window with various keys, as well as changing its workspace, produces
the correct press/release events.
This was adopted from #12878. I rebased the changes resolved the
following merge conflicts:
- moved over the changes originally done in bevy_winit/src/lib.rs's
`handle_winit_event` into bevy_winit/src/state.rs's `window_event`
function
- moved WinitEvent::KeyboardFocusLost event forwarding originally done
in bevy_winit/src/winit_event.rs to the equivalent in
bevy_winit/src/state.rs
Tested this by following the modified keyboard_input example from the
original PR.
First, I verified I could reproduce the issue without the changes. Then,
after applying the changes, I verified that when I Alt+Tabbed away from
the running example that the log showed I released Alt and when I tabbed
back it didn't behave like Alt was stuck.
The following is from the original pull request by @gavlig
# Objective
This helps avoiding stuck key presses after switching from and back to
Bevy window. Key press event gets stuck because window loses focus
before receiving a key release event thus we end up with false positive
in ButtonInput.
## Solution
I saw two ways to fix this:
1. add bevy_window as dependency and read WindowFocus events
2. add a KeyboardFocusLost event specifically for this.
I chose the latter because adding another dependency felt wrong, but if
that is more preferable changing this pr won't be a problem. Also if
someone sees another way please let me know.
To test the bug use this small modification over
examples/keyboard_input.rs: (it will work only if you have Alt-Tab
combination for switching between windows in your OS, otherwise change
AltLeft accordingly)
```
//! Demonstrates handling a key press/release.
use bevy::{prelude::*, input:⌨️:KeyboardInput};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, keyboard_input_system)
.run();
}
/// This system prints 'Alt' key state
fn keyboard_input_system(keyboard_input: Res<ButtonInput<KeyCode>>, mut
keyboard_input_events: EventReader<KeyboardInput>) {
for event in keyboard_input_events.read() {
info!("{:?}", event);
}
if keyboard_input.pressed(KeyCode::AltLeft) {
info!("'Alt' currently pressed");
}
if keyboard_input.just_pressed(KeyCode::AltLeft) {
info!("'Alt' just pressed");
}
if keyboard_input.just_released(KeyCode::AltLeft) {
info!("'Alt' just released");
}
}
```
Here i made a quick video with demo of the fix:
https://youtu.be/qTvUCk4IHvo In first part i press Alt and Alt+Tab to
switch back and forth from example app, logs will indicate that too. In
second part I applied fix and you'll see that Alt will no longer be
pressed when window gets unfocused
## Migration Guide
`WinitEvent` has a new enum variant: `WinitEvent::KeyboardFocusLost`.
Co-authored-by: gavlig <gavlig@gmail.com>
# Objective
- With the recent winit update, touchpad specific events can also be
triggered on mobile
## Solution
- Rename them to gestures and add support for the new ones
## Testing
- Tested on the mobile example on iOS
https://github.com/bevyengine/bevy/assets/8672791/da4ed23f-ff0a-41b2-9dcd-726e8546bef2
## Migration Guide
- `TouchpadMagnify` has been renamed to `PinchGesture`
- `TouchpadRotate` has been renamed to `RotationGesture `
---------
Co-authored-by: mike <ramirezmike2@gmail.com>
# Objective
- Upgrade winit to v0.30
- Fixes https://github.com/bevyengine/bevy/issues/13331
## Solution
This is a rewrite/adaptation of the new trait system described and
implemented in `winit` v0.30.
## Migration Guide
The custom UserEvent is now renamed as WakeUp, used to wake up the loop
if anything happens outside the app (a new
[custom_user_event](https://github.com/bevyengine/bevy/pull/13366/files#diff-2de8c0a8d3028d0059a3d80ae31b2bbc1cde2595ce2d317ea378fe3e0cf6ef2d)
shows this behavior.
The internal `UpdateState` has been removed and replaced internally by
the AppLifecycle. When changed, the AppLifecycle is sent as an event.
The `UpdateMode` now accepts only two values: `Continuous` and
`Reactive`, but the latter exposes 3 new properties to enable reactive
to device, user or window events. The previous `UpdateMode::Reactive` is
now equivalent to `UpdateMode::reactive()`, while
`UpdateMode::ReactiveLowPower` to `UpdateMode::reactive_low_power()`.
The `ApplicationLifecycle` has been renamed as `AppLifecycle`, and now
contains the possible values of the application state inside the event
loop:
* `Idle`: the loop has not started yet
* `Running` (previously called `Started`): the loop is running
* `WillSuspend`: the loop is going to be suspended
* `Suspended`: the loop is suspended
* `WillResume`: the loop is going to be resumed
Note: the `Resumed` state has been removed since the resumed app is just
running.
Finally, now that `winit` enables this, it extends the `WinitPlugin` to
support custom events.
## Test platforms
- [x] Windows
- [x] MacOs
- [x] Linux (x11)
- [x] Linux (Wayland)
- [x] Android
- [x] iOS
- [x] WASM/WebGPU
- [x] WASM/WebGL2
## Outstanding issues / regressions
- [ ] iOS: build failed in CI
- blocking, but may just be flakiness
- [x] Cross-platform: when the window is maximised, changes in the scale
factor don't apply, to make them apply one has to make the window
smaller again. (Re-maximising keeps the updated scale factor)
- non-blocking, but good to fix
- [ ] Android: it's pretty easy to quickly open and close the app and
then the music keeps playing when suspended.
- non-blocking but worrying
- [ ] Web: the application will hang when switching tabs
- Not new, duplicate of https://github.com/bevyengine/bevy/issues/13486
- [ ] Cross-platform?: Screenshot failure, `ERROR present_frames:
wgpu_core::present: No work has been submitted for this frame before`
taking the first screenshot, but after pressing space
- non-blocking, but good to fix
---------
Co-authored-by: François <francois.mockers@vleue.com>