mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
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:
parent
17e504812b
commit
565616622b
5 changed files with 48 additions and 16 deletions
|
@ -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 {
|
||||
|
|
|
@ -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>> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
#[cfg(feature = "custom_cursor")]
|
||||
fn update_cursors(&mut self, event_loop: &ActiveEventLoop) {
|
||||
fn update_cursors(&mut self, #[cfg(feature = "custom_cursor")] event_loop: &ActiveEventLoop) {
|
||||
#[cfg(feature = "custom_cursor")]
|
||||
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());
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue