Skip to content

Commit

Permalink
Added set_cursor_icon(...) to Window (bevyengine#3395)
Browse files Browse the repository at this point in the history
# Objective

The window's cursor should be settable without having to implement a custom cursor icon solution. This will especially be helpful when creating user-interfaces that might like to use the cursor to denote some meaning (e.g., _clickable_, _resizable_, etc.).

## Solution

Added a `CursorIcon` enum that maps one-to-one to winit's `CursorIcon` enum, as well as a method to set/get it for the given `Window`.
  • Loading branch information
MrGVSV authored and mockersf committed Dec 21, 2021
1 parent 69952bc commit 3f9a0ef
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 2 deletions.
39 changes: 39 additions & 0 deletions crates/bevy_window/src/cursor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// The icon to display for a window's cursor
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum CursorIcon {
Default,
Crosshair,
Hand,
Arrow,
Move,
Text,
Wait,
Help,
Progress,
NotAllowed,
ContextMenu,
Cell,
VerticalText,
Alias,
Copy,
NoDrop,
Grab,
Grabbing,
AllScroll,
ZoomIn,
ZoomOut,
EResize,
NResize,
NeResize,
NwResize,
SResize,
SeResize,
SwResize,
WResize,
EwResize,
NsResize,
NeswResize,
NwseResize,
ColResize,
RowResize,
}
6 changes: 4 additions & 2 deletions crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
mod cursor;
mod event;
mod raw_window_handle;
mod system;
mod window;
mod windows;

pub use crate::raw_window_handle::*;
pub use cursor::*;
pub use event::*;
pub use system::*;
pub use window::*;
Expand All @@ -13,8 +15,8 @@ pub use windows::*;
pub mod prelude {
#[doc(hidden)]
pub use crate::{
CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter, Window,
WindowDescriptor, WindowMoved, Windows,
CursorEntered, CursorIcon, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter,
Window, WindowDescriptor, WindowMoved, Windows,
};
}

Expand Down
16 changes: 16 additions & 0 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl WindowId {
}
}

use crate::CursorIcon;
use std::fmt;

use crate::raw_window_handle::RawWindowHandleWrapper;
Expand Down Expand Up @@ -123,6 +124,7 @@ pub struct Window {
vsync: bool,
resizable: bool,
decorations: bool,
cursor_icon: CursorIcon,
cursor_visible: bool,
cursor_locked: bool,
physical_cursor_position: Option<DVec2>,
Expand Down Expand Up @@ -162,6 +164,9 @@ pub enum WindowCommand {
SetCursorLockMode {
locked: bool,
},
SetCursorIcon {
icon: CursorIcon,
},
SetCursorVisibility {
visible: bool,
},
Expand Down Expand Up @@ -222,6 +227,7 @@ impl Window {
decorations: window_descriptor.decorations,
cursor_visible: window_descriptor.cursor_visible,
cursor_locked: window_descriptor.cursor_locked,
cursor_icon: CursorIcon::Default,
physical_cursor_position: None,
raw_window_handle: RawWindowHandleWrapper::new(raw_window_handle),
focused: true,
Expand Down Expand Up @@ -474,6 +480,16 @@ impl Window {
});
}

#[inline]
pub fn cursor_icon(&self) -> CursorIcon {
self.cursor_icon
}

pub fn set_cursor_icon(&mut self, icon: CursorIcon) {
self.command_queue
.push(WindowCommand::SetCursorIcon { icon });
}

/// The current mouse position, in physical pixels.
#[inline]
pub fn physical_cursor_position(&self) -> Option<DVec2> {
Expand Down
41 changes: 41 additions & 0 deletions crates/bevy_winit/src/converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use bevy_input::{
ElementState,
};
use bevy_math::Vec2;
use bevy_window::CursorIcon;

pub fn convert_keyboard_input(keyboard_input: &winit::event::KeyboardInput) -> KeyboardInput {
KeyboardInput {
Expand Down Expand Up @@ -225,3 +226,43 @@ pub fn convert_virtual_key_code(virtual_key_code: winit::event::VirtualKeyCode)
winit::event::VirtualKeyCode::Cut => KeyCode::Cut,
}
}

pub fn convert_cursor_icon(cursor_icon: CursorIcon) -> winit::window::CursorIcon {
match cursor_icon {
CursorIcon::Default => winit::window::CursorIcon::Default,
CursorIcon::Crosshair => winit::window::CursorIcon::Crosshair,
CursorIcon::Hand => winit::window::CursorIcon::Hand,
CursorIcon::Arrow => winit::window::CursorIcon::Arrow,
CursorIcon::Move => winit::window::CursorIcon::Move,
CursorIcon::Text => winit::window::CursorIcon::Text,
CursorIcon::Wait => winit::window::CursorIcon::Wait,
CursorIcon::Help => winit::window::CursorIcon::Help,
CursorIcon::Progress => winit::window::CursorIcon::Progress,
CursorIcon::NotAllowed => winit::window::CursorIcon::NotAllowed,
CursorIcon::ContextMenu => winit::window::CursorIcon::ContextMenu,
CursorIcon::Cell => winit::window::CursorIcon::Cell,
CursorIcon::VerticalText => winit::window::CursorIcon::VerticalText,
CursorIcon::Alias => winit::window::CursorIcon::Alias,
CursorIcon::Copy => winit::window::CursorIcon::Copy,
CursorIcon::NoDrop => winit::window::CursorIcon::NoDrop,
CursorIcon::Grab => winit::window::CursorIcon::Grab,
CursorIcon::Grabbing => winit::window::CursorIcon::Grabbing,
CursorIcon::AllScroll => winit::window::CursorIcon::AllScroll,
CursorIcon::ZoomIn => winit::window::CursorIcon::ZoomIn,
CursorIcon::ZoomOut => winit::window::CursorIcon::ZoomOut,
CursorIcon::EResize => winit::window::CursorIcon::EResize,
CursorIcon::NResize => winit::window::CursorIcon::NResize,
CursorIcon::NeResize => winit::window::CursorIcon::NeResize,
CursorIcon::NwResize => winit::window::CursorIcon::NwResize,
CursorIcon::SResize => winit::window::CursorIcon::SResize,
CursorIcon::SeResize => winit::window::CursorIcon::SeResize,
CursorIcon::SwResize => winit::window::CursorIcon::SwResize,
CursorIcon::WResize => winit::window::CursorIcon::WResize,
CursorIcon::EwResize => winit::window::CursorIcon::EwResize,
CursorIcon::NsResize => winit::window::CursorIcon::NsResize,
CursorIcon::NeswResize => winit::window::CursorIcon::NeswResize,
CursorIcon::NwseResize => winit::window::CursorIcon::NwseResize,
CursorIcon::ColResize => winit::window::CursorIcon::ColResize,
CursorIcon::RowResize => winit::window::CursorIcon::RowResize,
}
}
4 changes: 4 additions & 0 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ fn change_window(world: &mut World) {
let window = winit_windows.get_window(id).unwrap();
window.set_decorations(decorations);
}
bevy_window::WindowCommand::SetCursorIcon { icon } => {
let window = winit_windows.get_window(id).unwrap();
window.set_cursor_icon(converters::convert_cursor_icon(icon));
}
bevy_window::WindowCommand::SetCursorLockMode { locked } => {
let window = winit_windows.get_window(id).unwrap();
window
Expand Down
28 changes: 28 additions & 0 deletions examples/window/window_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_system(change_title)
.add_system(toggle_cursor)
.add_system(cycle_cursor_icon)
.run();
}

Expand All @@ -33,3 +34,30 @@ fn toggle_cursor(input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
window.set_cursor_visibility(!window.cursor_visible());
}
}

/// This system cycles the cursor's icon through a small set of icons when clicking
fn cycle_cursor_icon(
input: Res<Input<MouseButton>>,
mut windows: ResMut<Windows>,
mut index: Local<usize>,
) {
const ICONS: &[CursorIcon] = &[
CursorIcon::Default,
CursorIcon::Hand,
CursorIcon::Wait,
CursorIcon::Text,
CursorIcon::Copy,
];
let window = windows.get_primary_mut().unwrap();
if input.just_pressed(MouseButton::Left) {
*index = (*index + 1) % ICONS.len();
window.set_cursor_icon(ICONS[*index]);
} else if input.just_pressed(MouseButton::Right) {
*index = if *index == 0 {
ICONS.len() - 1
} else {
*index - 1
};
window.set_cursor_icon(ICONS[*index]);
}
}

0 comments on commit 3f9a0ef

Please sign in to comment.