Correctly feature gate custom_cursor (#16093)

# Objective

Currently there's no way to change the window's cursor icon with the
`custom_cursor` feature **disabled**. You should still be able to set
system cursor icons.

Connections:

- https://github.com/bevyengine/bevy/pull/15649

## Solution

Move some `custom_cursor` feature gates around, as to expose the
`CursorIcon` type again.

Note this refactoring was mainly piloted by hunting after the compiler
warnings -- I shouldn't have missed anything, but FYI.

## Testing

Disabled the `custom_cursor` feature, ran the `window_settings` example.
This commit is contained in:
Friz64 2024-11-02 02:47:32 +01:00 committed by GitHub
parent 17e504812b
commit 565616622b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 48 additions and 16 deletions

View file

@ -6,7 +6,6 @@ use bevy_input::{
ButtonState,
};
use bevy_math::{CompassOctant, Vec2};
#[cfg(feature = "custom_cursor")]
use bevy_window::SystemCursorIcon;
use bevy_window::{EnabledButtons, WindowLevel, WindowTheme};
use winit::keyboard::{Key, NamedKey, NativeKey};
@ -630,7 +629,6 @@ pub fn convert_native_key(native_key: &NativeKey) -> bevy_input::keyboard::Nativ
}
}
#[cfg(feature = "custom_cursor")]
/// Converts a [`SystemCursorIcon`] to a [`winit::window::CursorIcon`].
pub fn convert_system_cursor_icon(cursor_icon: SystemCursorIcon) -> winit::window::CursorIcon {
match cursor_icon {

View file

@ -2,11 +2,18 @@
use crate::{
converters::convert_system_cursor_icon,
state::{CursorSource, CustomCursorCache, CustomCursorCacheKey, PendingCursor},
state::{CursorSource, PendingCursor},
};
#[cfg(feature = "custom_cursor")]
use crate::{
state::{CustomCursorCache, CustomCursorCacheKey},
WinitCustomCursor,
};
use bevy_app::{App, Last, Plugin};
#[cfg(feature = "custom_cursor")]
use bevy_asset::{Assets, Handle};
#[cfg(feature = "custom_cursor")]
use bevy_ecs::system::Res;
use bevy_ecs::{
change_detection::DetectChanges,
component::Component,
@ -14,21 +21,27 @@ use bevy_ecs::{
observer::Trigger,
query::With,
reflect::ReflectComponent,
system::{Commands, Local, Query, Res},
system::{Commands, Local, Query},
world::{OnRemove, Ref},
};
#[cfg(feature = "custom_cursor")]
use bevy_image::Image;
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_utils::{tracing::warn, HashSet};
#[cfg(feature = "custom_cursor")]
use bevy_utils::tracing::warn;
use bevy_utils::HashSet;
use bevy_window::{SystemCursorIcon, Window};
#[cfg(feature = "custom_cursor")]
use wgpu_types::TextureFormat;
pub(crate) struct CursorPlugin;
impl Plugin for CursorPlugin {
fn build(&self, app: &mut App) {
#[cfg(feature = "custom_cursor")]
app.init_resource::<CustomCursorCache>();
app.register_type::<CursorIcon>()
.init_resource::<CustomCursorCache>()
.add_systems(Last, update_cursors);
app.add_observer(on_remove_cursor_icon);
@ -39,6 +52,7 @@ impl Plugin for CursorPlugin {
#[derive(Component, Debug, Clone, Reflect, PartialEq, Eq)]
#[reflect(Component, Debug, Default, PartialEq)]
pub enum CursorIcon {
#[cfg(feature = "custom_cursor")]
/// Custom cursor image.
Custom(CustomCursor),
/// System provided cursor icon.
@ -57,12 +71,14 @@ impl From<SystemCursorIcon> for CursorIcon {
}
}
#[cfg(feature = "custom_cursor")]
impl From<CustomCursor> for CursorIcon {
fn from(cursor: CustomCursor) -> Self {
CursorIcon::Custom(cursor)
}
}
#[cfg(feature = "custom_cursor")]
/// Custom cursor image data.
#[derive(Debug, Clone, Reflect, PartialEq, Eq, Hash)]
pub enum CustomCursor {
@ -90,8 +106,8 @@ pub enum CustomCursor {
fn update_cursors(
mut commands: Commands,
windows: Query<(Entity, Ref<CursorIcon>), With<Window>>,
cursor_cache: Res<CustomCursorCache>,
images: Res<Assets<Image>>,
#[cfg(feature = "custom_cursor")] cursor_cache: Res<CustomCursorCache>,
#[cfg(feature = "custom_cursor")] images: Res<Assets<Image>>,
mut queue: Local<HashSet<Entity>>,
) {
for (entity, cursor) in windows.iter() {
@ -100,6 +116,7 @@ fn update_cursors(
}
let cursor_source = match cursor.as_ref() {
#[cfg(feature = "custom_cursor")]
CursorIcon::Custom(CustomCursor::Image { handle, hotspot }) => {
let cache_key = CustomCursorCacheKey::Asset(handle.id());
@ -170,6 +187,7 @@ fn on_remove_cursor_icon(trigger: Trigger<OnRemove, CursorIcon>, mut commands: C
))));
}
#[cfg(feature = "custom_cursor")]
/// Returns the image data as a `Vec<u8>`.
/// Only supports rgba8 and rgba32float formats.
fn image_to_rgba_pixels(image: &Image) -> Option<Vec<u8>> {

View file

@ -44,7 +44,6 @@ use crate::{
pub mod accessibility;
mod converters;
#[cfg(feature = "custom_cursor")]
pub mod cursor;
mod state;
mod system;
@ -136,7 +135,6 @@ impl<T: Event> Plugin for WinitPlugin<T> {
);
app.add_plugins(AccessKitPlugin);
#[cfg(feature = "custom_cursor")]
app.add_plugins(cursor::CursorPlugin);
let event_loop = event_loop_builder

View file

@ -158,19 +158,19 @@ pub enum CustomCursorCacheKey {
#[derive(Debug, Clone, Default, Resource)]
pub struct CustomCursorCache(pub HashMap<CustomCursorCacheKey, winit::window::CustomCursor>);
#[cfg(feature = "custom_cursor")]
/// A source for a cursor. Consumed by the winit event loop.
#[derive(Debug)]
pub enum CursorSource {
#[cfg(feature = "custom_cursor")]
/// A custom cursor was identified to be cached, no reason to recreate it.
CustomCached(CustomCursorCacheKey),
#[cfg(feature = "custom_cursor")]
/// A custom cursor was not cached, so it needs to be created by the winit event loop.
Custom((CustomCursorCacheKey, winit::window::CustomCursorSource)),
/// A system cursor was requested.
System(winit::window::CursorIcon),
}
#[cfg(feature = "custom_cursor")]
/// Component that indicates what cursor should be used for a window. Inserted
/// automatically after changing `CursorIcon` and consumed by the winit event
/// loop.
@ -560,6 +560,8 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
self.run_app_update();
#[cfg(feature = "custom_cursor")]
self.update_cursors(event_loop);
#[cfg(not(feature = "custom_cursor"))]
self.update_cursors();
self.ran_update_since_last_redraw = true;
} else {
self.redraw_requested = true;
@ -787,15 +789,23 @@ impl<T: Event> WinitAppRunnerState<T> {
.send_batch(buffered_events);
}
fn update_cursors(&mut self, #[cfg(feature = "custom_cursor")] event_loop: &ActiveEventLoop) {
#[cfg(feature = "custom_cursor")]
fn update_cursors(&mut self, event_loop: &ActiveEventLoop) {
let mut windows_state: SystemState<(
NonSendMut<WinitWindows>,
ResMut<CustomCursorCache>,
Query<(Entity, &mut PendingCursor), Changed<PendingCursor>>,
)> = SystemState::new(self.world_mut());
#[cfg(feature = "custom_cursor")]
let (winit_windows, mut cursor_cache, mut windows) =
windows_state.get_mut(self.world_mut());
#[cfg(not(feature = "custom_cursor"))]
let mut windows_state: SystemState<(
NonSendMut<WinitWindows>,
Query<(Entity, &mut PendingCursor), Changed<PendingCursor>>,
)> = SystemState::new(self.world_mut());
#[cfg(not(feature = "custom_cursor"))]
let (winit_windows, mut windows) = windows_state.get_mut(self.world_mut());
for (entity, mut pending_cursor) in windows.iter_mut() {
let Some(winit_window) = winit_windows.get_window(entity) else {
@ -806,6 +816,7 @@ impl<T: Event> WinitAppRunnerState<T> {
};
let final_cursor: winit::window::Cursor = match pending_cursor {
#[cfg(feature = "custom_cursor")]
CursorSource::CustomCached(cache_key) => {
let Some(cached_cursor) = cursor_cache.0.get(&cache_key) else {
error!("Cursor should have been cached, but was not found");
@ -813,6 +824,7 @@ impl<T: Event> WinitAppRunnerState<T> {
};
cached_cursor.clone().into()
}
#[cfg(feature = "custom_cursor")]
CursorSource::Custom((cache_key, cursor)) => {
let custom_cursor = event_loop.create_custom_cursor(cursor);
cursor_cache.0.insert(cache_key, custom_cursor.clone());

View file

@ -1,12 +1,14 @@
//! Illustrates how to change window settings and shows how to affect
//! the mouse pointer in various ways.
#[cfg(feature = "custom_cursor")]
use bevy::winit::cursor::CustomCursor;
use bevy::{
core::FrameCount,
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*,
window::{CursorGrabMode, PresentMode, SystemCursorIcon, WindowLevel, WindowTheme},
winit::cursor::{CursorIcon, CustomCursor},
winit::cursor::CursorIcon,
};
fn main() {
@ -152,12 +154,16 @@ fn toggle_theme(mut window: Single<&mut Window>, input: Res<ButtonInput<KeyCode>
#[derive(Resource)]
struct CursorIcons(Vec<CursorIcon>);
fn init_cursor_icons(mut commands: Commands, asset_server: Res<AssetServer>) {
fn init_cursor_icons(
mut commands: Commands,
#[cfg(feature = "custom_cursor")] asset_server: Res<AssetServer>,
) {
commands.insert_resource(CursorIcons(vec![
SystemCursorIcon::Default.into(),
SystemCursorIcon::Pointer.into(),
SystemCursorIcon::Wait.into(),
SystemCursorIcon::Text.into(),
#[cfg(feature = "custom_cursor")]
CustomCursor::Image {
handle: asset_server.load("branding/icon.png"),
hotspot: (128, 128),