Skip to main content

mirage_engine/input/
cursor.rs

1//! What the pointer is drawn as, and what the window and the UI each name
2//! it.
3
4/// What the pointer is drawn as, which
5/// [`FrameContext::set_cursor`](crate::FrameContext::set_cursor) takes.
6///
7/// Required if you want the pointer to show what it is over: the hand over
8/// what the player can press, the closed hand while they hold it.
9/// [`Cursor::Held`] draws no pointer and holds it in place.
10#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
11pub enum Cursor {
12    /// The arrow, which a frame that sets no cursor draws.
13    #[default]
14    Arrow,
15    /// The hand, over what the player can press.
16    Pointer,
17    /// The open hand, over what the player can take hold of.
18    Grab,
19    /// The closed hand, over what the player has taken hold of.
20    Grabbing,
21    /// The crosshair, over a position the player chooses exactly.
22    Crosshair,
23    /// The upright line, over text the player selects.
24    Text,
25    /// The four arrows, over what the player moves.
26    Move,
27    /// The circle with a line across it, over what the player cannot use.
28    NotAllowed,
29    /// The clock, while the game does work the player waits on.
30    Wait,
31    /// No pointer at all: it is hidden and held in place, and a frame
32    /// reads how far it moved rather than where it is.
33    Held,
34}
35
36impl Cursor {
37    /// Whether this cursor holds the pointer in place, so that only its
38    /// movement reaches the game.
39    pub(crate) fn holds_pointer(self) -> bool {
40        matches!(self, Self::Held)
41    }
42
43    /// This cursor as the window names it, or `None` where the window
44    /// draws no pointer at all.
45    #[cfg(not(feature = "ui"))]
46    pub(crate) fn window_icon(self) -> Option<winit::window::CursorIcon> {
47        Some(match self {
48            Self::Arrow => winit::window::CursorIcon::Default,
49            Self::Pointer => winit::window::CursorIcon::Pointer,
50            Self::Grab => winit::window::CursorIcon::Grab,
51            Self::Grabbing => winit::window::CursorIcon::Grabbing,
52            Self::Crosshair => winit::window::CursorIcon::Crosshair,
53            Self::Text => winit::window::CursorIcon::Text,
54            Self::Move => winit::window::CursorIcon::Move,
55            Self::NotAllowed => winit::window::CursorIcon::NotAllowed,
56            Self::Wait => winit::window::CursorIcon::Wait,
57            Self::Held => return None,
58        })
59    }
60
61    /// This cursor as the UI names it; a held pointer is the UI's own
62    /// `None`, which it draws nothing for.
63    #[cfg(feature = "ui")]
64    pub(crate) fn ui_icon(self) -> egui::CursorIcon {
65        match self {
66            Self::Arrow => egui::CursorIcon::Default,
67            Self::Pointer => egui::CursorIcon::PointingHand,
68            Self::Grab => egui::CursorIcon::Grab,
69            Self::Grabbing => egui::CursorIcon::Grabbing,
70            Self::Crosshair => egui::CursorIcon::Crosshair,
71            Self::Text => egui::CursorIcon::Text,
72            Self::Move => egui::CursorIcon::Move,
73            Self::NotAllowed => egui::CursorIcon::NotAllowed,
74            Self::Wait => egui::CursorIcon::Wait,
75            Self::Held => egui::CursorIcon::None,
76        }
77    }
78
79    /// The cursor nearest `icon`, or `None` where the UI set no cursor of
80    /// its own.
81    ///
82    /// The UI's own `None` hides the pointer rather than holding it in
83    /// place, so it is nearest [`Cursor::Arrow`] and a window hiding the
84    /// pointer reads back as the arrow.
85    #[cfg(feature = "ui")]
86    pub(crate) fn of_ui(icon: egui::CursorIcon) -> Option<Self> {
87        use egui::CursorIcon as Ui;
88
89        match icon {
90            Ui::Default => None,
91            Ui::PointingHand => Some(Self::Pointer),
92            Ui::Grab => Some(Self::Grab),
93            Ui::Grabbing => Some(Self::Grabbing),
94            Ui::Cell | Ui::Crosshair => Some(Self::Crosshair),
95            Ui::Text | Ui::VerticalText => Some(Self::Text),
96            Ui::NoDrop | Ui::NotAllowed => Some(Self::NotAllowed),
97            Ui::Progress | Ui::Wait => Some(Self::Wait),
98            Ui::AllScroll
99            | Ui::Move
100            | Ui::ResizeColumn
101            | Ui::ResizeEast
102            | Ui::ResizeHorizontal
103            | Ui::ResizeNeSw
104            | Ui::ResizeNorth
105            | Ui::ResizeNorthEast
106            | Ui::ResizeNorthWest
107            | Ui::ResizeNwSe
108            | Ui::ResizeRow
109            | Ui::ResizeSouth
110            | Ui::ResizeSouthEast
111            | Ui::ResizeSouthWest
112            | Ui::ResizeVertical
113            | Ui::ResizeWest => Some(Self::Move),
114            Ui::Alias
115            | Ui::ContextMenu
116            | Ui::Copy
117            | Ui::Help
118            | Ui::None
119            | Ui::ZoomIn
120            | Ui::ZoomOut => Some(Self::Arrow),
121        }
122    }
123}