Skip to content

Commit 6edb78a

Browse files
authored
Inverse bevy_render bevy_winit dependency and move cursor to bevy_winit (#15649)
# Objective - `bevy_render` should not depend on `bevy_winit` - Fixes #15565 ## Solution - `bevy_render` no longer depends on `bevy_winit` - The following is behind the `custom_cursor` feature - Move custom cursor code from `bevy_render` to `bevy_winit` behind the `custom_cursor` feature - `bevy_winit` now depends on `bevy_render` (for `Image` and `TextureFormat`) - `bevy_winit` now depends on `bevy_asset` (for `Assets`, `Handle` and `AssetId`) - `bevy_winit` now depends on `bytemuck` (already in tree) - Custom cursor code in `bevy_winit` reworked to use `AssetId` (other than that it is taken over 1:1) - Rework `bevy_winit` custom cursor interface visibility now that the logic is all contained in `bevy_winit` ## Testing - I ran the screenshot and window_settings examples - Tested on linux wayland so far --- ## Migration Guide `CursorIcon` and `CustomCursor` previously provided by `bevy::render::view::cursor` is now available from `bevy::winit`. A new feature `custom_cursor` enables this functionality (default feature).
1 parent 4a23dc4 commit 6edb78a

File tree

12 files changed

+64
-40
lines changed

12 files changed

+64
-40
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ default = [
132132
"webgl2",
133133
"sysinfo_plugin",
134134
"android-game-activity",
135+
"custom_cursor",
135136
]
136137

137138
# Provides an implementation for picking sprites
@@ -417,6 +418,9 @@ track_change_detection = ["bevy_internal/track_change_detection"]
417418
# Enable function reflection
418419
reflect_functions = ["bevy_internal/reflect_functions"]
419420

421+
# Enable winit custom cursor support
422+
custom_cursor = ["bevy_internal/custom_cursor"]
423+
420424
[dependencies]
421425
bevy_internal = { path = "crates/bevy_internal", version = "0.15.0-dev", default-features = false }
422426

crates/bevy_internal/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ reflect_functions = [
223223
"bevy_ecs/reflect_functions",
224224
]
225225

226+
# Enable winit custom cursor support
227+
custom_cursor = ["bevy_winit/custom_cursor"]
228+
226229
[dependencies]
227230
# bevy
228231
bevy_a11y = { path = "../bevy_a11y", version = "0.15.0-dev" }

crates/bevy_render/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ bevy_render_macros = { path = "macros", version = "0.15.0-dev" }
6666
bevy_time = { path = "../bevy_time", version = "0.15.0-dev" }
6767
bevy_transform = { path = "../bevy_transform", version = "0.15.0-dev" }
6868
bevy_window = { path = "../bevy_window", version = "0.15.0-dev" }
69-
bevy_winit = { path = "../bevy_winit", version = "0.15.0-dev" }
7069
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
7170
bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" }
7271
bevy_image = { path = "../bevy_image", version = "0.15.0-dev" }

crates/bevy_render/src/view/window/mod.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ use core::{
1515
num::NonZero,
1616
ops::{Deref, DerefMut},
1717
};
18-
use cursor::CursorPlugin;
1918
use wgpu::{
2019
SurfaceConfiguration, SurfaceTargetUnsafe, TextureFormat, TextureUsages, TextureViewDescriptor,
2120
};
2221

23-
pub mod cursor;
2422
pub mod screenshot;
2523

2624
use screenshot::{ScreenshotPlugin, ScreenshotToScreenPipeline};
@@ -29,7 +27,7 @@ pub struct WindowRenderPlugin;
2927

3028
impl Plugin for WindowRenderPlugin {
3129
fn build(&self, app: &mut App) {
32-
app.add_plugins((ScreenshotPlugin, CursorPlugin));
30+
app.add_plugins(ScreenshotPlugin);
3331

3432
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
3533
render_app

crates/bevy_winit/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ serialize = ["serde", "bevy_input/serialize", "bevy_window/serialize"]
1818
android-native-activity = ["winit/android-native-activity"]
1919
android-game-activity = ["winit/android-game-activity"]
2020

21+
custom_cursor = ["bevy_image", "bevy_asset", "bytemuck", "wgpu-types"]
22+
2123

2224
[dependencies]
2325
# bevy
@@ -34,6 +36,10 @@ bevy_window = { path = "../bevy_window", version = "0.15.0-dev" }
3436
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
3537
bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" }
3638

39+
# bevy optional
40+
bevy_asset = { path = "../bevy_asset", version = "0.15.0-dev", optional = true }
41+
bevy_image = { path = "../bevy_image", version = "0.15.0-dev", optional = true }
42+
3743
# other
3844
# feature rwh_06 refers to [email protected]
3945
winit = { version = "0.30", default-features = false, features = ["rwh_06"] }
@@ -44,6 +50,8 @@ approx = { version = "0.5", default-features = false }
4450
cfg-if = "1.0"
4551
raw-window-handle = "0.6"
4652
serde = { version = "1.0", features = ["derive"], optional = true }
53+
bytemuck = { version = "1.5", optional = true }
54+
wgpu-types = { version = "22", optional = true }
4755

4856
[target.'cfg(target_arch = "wasm32")'.dependencies]
4957
wasm-bindgen = { version = "0.2" }

crates/bevy_winit/src/converters.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use bevy_input::{
66
ButtonState,
77
};
88
use bevy_math::Vec2;
9-
use bevy_window::{EnabledButtons, SystemCursorIcon, WindowLevel, WindowTheme};
9+
#[cfg(feature = "custom_cursor")]
10+
use bevy_window::SystemCursorIcon;
11+
use bevy_window::{EnabledButtons, WindowLevel, WindowTheme};
1012
use winit::keyboard::{Key, NamedKey, NativeKey};
1113

1214
pub fn convert_keyboard_input(
@@ -628,6 +630,7 @@ pub fn convert_native_key(native_key: &NativeKey) -> bevy_input::keyboard::Nativ
628630
}
629631
}
630632

633+
#[cfg(feature = "custom_cursor")]
631634
/// Converts a [`SystemCursorIcon`] to a [`winit::window::CursorIcon`].
632635
pub fn convert_system_cursor_icon(cursor_icon: SystemCursorIcon) -> winit::window::CursorIcon {
633636
match cursor_icon {

crates/bevy_render/src/view/window/cursor.rs renamed to crates/bevy_winit/src/cursor.rs

+17-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
//! Components to customize winit cursor
2+
3+
use crate::{
4+
converters::convert_system_cursor_icon,
5+
state::{CursorSource, CustomCursorCache, CustomCursorCacheKey, PendingCursor},
6+
WinitCustomCursor,
7+
};
18
use bevy_app::{App, Last, Plugin};
2-
use bevy_asset::{AssetId, Assets, Handle};
9+
use bevy_asset::{Assets, Handle};
310
use bevy_ecs::{
411
change_detection::DetectChanges,
512
component::Component,
@@ -10,18 +17,13 @@ use bevy_ecs::{
1017
system::{Commands, Local, Query, Res},
1118
world::{OnRemove, Ref},
1219
};
20+
use bevy_image::Image;
1321
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
1422
use bevy_utils::{tracing::warn, HashSet};
1523
use bevy_window::{SystemCursorIcon, Window};
16-
use bevy_winit::{
17-
convert_system_cursor_icon, CursorSource, CustomCursorCache, CustomCursorCacheKey,
18-
PendingCursor,
19-
};
20-
use wgpu::TextureFormat;
21-
22-
use crate::prelude::Image;
24+
use wgpu_types::TextureFormat;
2325

24-
pub struct CursorPlugin;
26+
pub(crate) struct CursorPlugin;
2527

2628
impl Plugin for CursorPlugin {
2729
fn build(&self, app: &mut App) {
@@ -85,7 +87,7 @@ pub enum CustomCursor {
8587
},
8688
}
8789

88-
pub fn update_cursors(
90+
fn update_cursors(
8991
mut commands: Commands,
9092
windows: Query<(Entity, Ref<CursorIcon>), With<Window>>,
9193
cursor_cache: Res<CustomCursorCache>,
@@ -99,12 +101,7 @@ pub fn update_cursors(
99101

100102
let cursor_source = match cursor.as_ref() {
101103
CursorIcon::Custom(CustomCursor::Image { handle, hotspot }) => {
102-
let cache_key = match handle.id() {
103-
AssetId::Index { index, .. } => {
104-
CustomCursorCacheKey::AssetIndex(index.to_bits())
105-
}
106-
AssetId::Uuid { uuid } => CustomCursorCacheKey::AssetUuid(uuid.as_u128()),
107-
};
104+
let cache_key = CustomCursorCacheKey::Asset(handle.id());
108105

109106
if cursor_cache.0.contains_key(&cache_key) {
110107
CursorSource::CustomCached(cache_key)
@@ -123,7 +120,7 @@ pub fn update_cursors(
123120

124121
let width = image.texture_descriptor.size.width;
125122
let height = image.texture_descriptor.size.height;
126-
let source = match bevy_winit::WinitCustomCursor::from_rgba(
123+
let source = match WinitCustomCursor::from_rgba(
127124
rgba,
128125
width as u16,
129126
height as u16,
@@ -147,9 +144,8 @@ pub fn update_cursors(
147144
if cursor_cache.0.contains_key(&cache_key) {
148145
CursorSource::CustomCached(cache_key)
149146
} else {
150-
use bevy_winit::CustomCursorExtWebSys;
151-
let source =
152-
bevy_winit::WinitCustomCursor::from_url(url.clone(), hotspot.0, hotspot.1);
147+
use crate::CustomCursorExtWebSys;
148+
let source = WinitCustomCursor::from_url(url.clone(), hotspot.0, hotspot.1);
153149
CursorSource::Custom((cache_key, source))
154150
}
155151
}
@@ -165,7 +161,7 @@ pub fn update_cursors(
165161
}
166162

167163
/// Resets the cursor to the default icon when `CursorIcon` is removed.
168-
pub fn on_remove_cursor_icon(trigger: Trigger<OnRemove, CursorIcon>, mut commands: Commands) {
164+
fn on_remove_cursor_icon(trigger: Trigger<OnRemove, CursorIcon>, mut commands: Commands) {
169165
// Use `try_insert` to avoid panic if the window is being destroyed.
170166
commands
171167
.entity(trigger.entity())

crates/bevy_winit/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ use bevy_a11y::AccessibilityRequested;
2323
use bevy_app::{App, Last, Plugin};
2424
use bevy_ecs::prelude::*;
2525
use bevy_window::{exit_on_all_closed, Window, WindowCreated};
26-
pub use converters::convert_system_cursor_icon;
27-
pub use state::{CursorSource, CustomCursorCache, CustomCursorCacheKey, PendingCursor};
2826
use system::{changed_windows, check_keyboard_focus_lost, despawn_windows};
2927
pub use system::{create_monitors, create_windows};
3028
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
@@ -44,6 +42,8 @@ use crate::{
4442

4543
pub mod accessibility;
4644
mod converters;
45+
#[cfg(feature = "custom_cursor")]
46+
pub mod cursor;
4747
mod state;
4848
mod system;
4949
mod winit_config;
@@ -131,6 +131,8 @@ impl<T: Event> Plugin for WinitPlugin<T> {
131131
);
132132

133133
app.add_plugins(AccessKitPlugin);
134+
#[cfg(feature = "custom_cursor")]
135+
app.add_plugins(cursor::CursorPlugin);
134136

135137
let event_loop = event_loop_builder
136138
.build()

crates/bevy_winit/src/state.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use approx::relative_eq;
22
use bevy_app::{App, AppExit, PluginsState};
3+
#[cfg(feature = "custom_cursor")]
4+
use bevy_asset::AssetId;
35
use bevy_ecs::{
46
change_detection::{DetectChanges, NonSendMut, Res},
57
entity::Entity,
@@ -8,6 +10,8 @@ use bevy_ecs::{
810
system::SystemState,
911
world::FromWorld,
1012
};
13+
#[cfg(feature = "custom_cursor")]
14+
use bevy_image::Image;
1115
use bevy_input::{
1216
gestures::*,
1317
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
@@ -16,7 +20,9 @@ use bevy_log::{error, trace, warn};
1620
use bevy_math::{ivec2, DVec2, Vec2};
1721
#[cfg(not(target_arch = "wasm32"))]
1822
use bevy_tasks::tick_global_task_pools_on_main_thread;
19-
use bevy_utils::{HashMap, Instant};
23+
#[cfg(feature = "custom_cursor")]
24+
use bevy_utils::HashMap;
25+
use bevy_utils::Instant;
2026
use core::marker::PhantomData;
2127
use winit::{
2228
application::ApplicationHandler,
@@ -88,6 +94,7 @@ struct WinitAppRunnerState<T: Event> {
8894

8995
impl<T: Event> WinitAppRunnerState<T> {
9096
fn new(mut app: App) -> Self {
97+
#[cfg(feature = "custom_cursor")]
9198
app.add_event::<T>().init_resource::<CustomCursorCache>();
9299

93100
let event_writer_system_state: SystemState<(
@@ -134,23 +141,25 @@ impl<T: Event> WinitAppRunnerState<T> {
134141
}
135142
}
136143

144+
#[cfg(feature = "custom_cursor")]
137145
/// Identifiers for custom cursors used in caching.
138146
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
139147
pub enum CustomCursorCacheKey {
140-
/// u64 is used instead of `AssetId`, because `bevy_asset` can't be imported here.
141-
AssetIndex(u64),
142-
/// u128 is used instead of `AssetId`, because `bevy_asset` can't be imported here.
143-
AssetUuid(u128),
144-
/// A URL to a cursor.
148+
/// An `AssetId` to a cursor.
149+
Asset(AssetId<Image>),
150+
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
151+
/// An URL to a cursor.
145152
Url(String),
146153
}
147154

155+
#[cfg(feature = "custom_cursor")]
148156
/// Caches custom cursors. On many platforms, creating custom cursors is expensive, especially on
149157
/// the web.
150158
#[derive(Debug, Clone, Default, Resource)]
151159
pub struct CustomCursorCache(pub HashMap<CustomCursorCacheKey, winit::window::CustomCursor>);
152160

153-
/// A source for a cursor. Is created in `bevy_render` and consumed by the winit event loop.
161+
#[cfg(feature = "custom_cursor")]
162+
/// A source for a cursor. Consumed by the winit event loop.
154163
#[derive(Debug)]
155164
pub enum CursorSource {
156165
/// A custom cursor was identified to be cached, no reason to recreate it.
@@ -161,6 +170,7 @@ pub enum CursorSource {
161170
System(winit::window::CursorIcon),
162171
}
163172

173+
#[cfg(feature = "custom_cursor")]
164174
/// Component that indicates what cursor should be used for a window. Inserted
165175
/// automatically after changing `CursorIcon` and consumed by the winit event
166176
/// loop.
@@ -547,6 +557,7 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
547557
// This is a temporary solution, full solution is mentioned here: https://github.com/bevyengine/bevy/issues/1343#issuecomment-770091684
548558
if !self.ran_update_since_last_redraw || all_invisible {
549559
self.run_app_update();
560+
#[cfg(feature = "custom_cursor")]
550561
self.update_cursors(event_loop);
551562
self.ran_update_since_last_redraw = true;
552563
} else {
@@ -775,6 +786,7 @@ impl<T: Event> WinitAppRunnerState<T> {
775786
.send_batch(buffered_events);
776787
}
777788

789+
#[cfg(feature = "custom_cursor")]
778790
fn update_cursors(&mut self, event_loop: &ActiveEventLoop) {
779791
let mut windows_state: SystemState<(
780792
NonSendMut<WinitWindows>,

docs/cargo_features.md

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ The default feature set enables most of the expected features of a game engine,
3434
|bevy_ui|A custom ECS-driven UI framework|
3535
|bevy_ui_picking_backend|Provides an implementation for picking ui|
3636
|bevy_winit|winit window and input backend|
37+
|custom_cursor|Enable winit custom cursor support|
3738
|default_font|Include a default font, containing only ASCII characters, at the cost of a 20kB binary size increase|
3839
|hdr|HDR image format support|
3940
|ktx2|KTX2 compressed texture support|

examples/window/screenshot.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
33
use bevy::{
44
prelude::*,
5-
render::view::{
6-
cursor::CursorIcon,
7-
screenshot::{save_to_disk, Capturing, Screenshot},
8-
},
5+
render::view::screenshot::{save_to_disk, Capturing, Screenshot},
96
window::SystemCursorIcon,
7+
winit::cursor::CursorIcon,
108
};
119

1210
fn main() {

examples/window/window_settings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use bevy::{
55
core::FrameCount,
66
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
77
prelude::*,
8-
render::view::cursor::{CursorIcon, CustomCursor},
98
window::{CursorGrabMode, PresentMode, SystemCursorIcon, WindowLevel, WindowTheme},
9+
winit::cursor::{CursorIcon, CustomCursor},
1010
};
1111

1212
fn main() {

0 commit comments

Comments
 (0)