Skip to main content

mirage_engine/input/
action.rs

1//! The action vocabularies a game reads its input through, and the three
2//! kinds they split into.
3
4use core::fmt;
5
6use crate::Seats;
7use crate::input::binding::{Axis2Binding, AxisBinding, ButtonBinding, Key};
8use crate::input::table::sealed::Binding as Persisted;
9
10/// Trait every action vocabulary implements, written by
11/// [`InputButtonAction`](crate::InputButtonAction),
12/// [`InputAxisAction`](crate::InputAxisAction) and
13/// [`InputAxis2Action`](crate::InputAxis2Action).
14///
15/// Required if you want to rebind or read an action generically; the kind
16/// traits are what a game implements by hand.
17pub trait InputAction: Copy + 'static {
18    /// Binding type for an action of this kind, which is what makes a
19    /// mis-kinded [`rebind`](crate::FrameContext::rebind) fail to compile.
20    type Binding: Persisted + fmt::Display;
21
22    /// Default controls this action is bound to, before a player changes
23    /// anything.
24    fn defaults(&self) -> Vec<Self::Binding>;
25
26    /// Every action of this vocabulary, which startup materializes into the
27    /// table a player rebinds; one this leaves out reads through nothing.
28    fn all() -> Vec<Self>;
29
30    /// Name this action is known by in code; also the name the store
31    /// keeps a rebind under.
32    fn name(&self) -> &'static str;
33
34    /// The action of this name, or `None` where the vocabulary has none.
35    fn from_name(name: &str) -> Option<Self>;
36}
37
38/// An action that reads back `true` while it is held.
39///
40/// Required if you want a verb with two states: a jump, a shot, a pause.
41pub trait InputButtonAction: InputAction<Binding = ButtonBinding> {
42    /// The controls this action starts out bound to; they are
43    /// alternatives, and any one of them holds it down.
44    fn bindings(&self) -> Vec<ButtonBinding>;
45}
46
47/// An action that reads back a number in `-1..=1`, or, bound to a
48/// [`PointerDelta`](crate::PointerDelta) or
49/// [`WheelDelta`](crate::WheelDelta) lane, how far it moved.
50///
51/// Required if you want a verb with a strength and a direction: a throttle,
52/// a lean, a turn.
53pub trait InputAxisAction: InputAction<Binding = AxisBinding> {
54    /// The controls this action starts out bound to; the one pushed
55    /// furthest is the one it reads.
56    fn bindings(&self) -> Vec<AxisBinding>;
57}
58
59/// An action that reads back a vector no longer than `1`, or, bound to
60/// [`Axis2Binding::pointer`](crate::Axis2Binding::pointer), how far the
61/// pointer moved.
62///
63/// Required if you want a verb with a direction in the plane: a walk, a
64/// look, a cursor.
65pub trait InputAxis2Action: InputAction<Binding = Axis2Binding> {
66    /// The controls this action starts out bound to; the one pushed
67    /// furthest is the one it reads.
68    fn bindings(&self) -> Vec<Axis2Binding>;
69}
70
71/// The three vocabularies one game plays with, named together as
72/// [`Game::InputActions`](crate::Game::InputActions).
73///
74/// Fill a kind a game has no verbs of with [`NoInputButtons`],
75/// [`NoInputAxes`] or [`NoInputAxes2`].
76pub trait InputActions {
77    /// The vocabulary whose actions read back as held or not.
78    type Button: InputButtonAction;
79    /// The vocabulary whose actions read back a number.
80    type Axis: InputAxisAction;
81    /// The vocabulary whose actions read back a vector.
82    type Axis2: InputAxis2Action;
83}
84
85impl<S: InputActions> Seats<S::Button, ButtonBinding> for S {}
86impl<S: InputActions> Seats<S::Axis, AxisBinding> for S {}
87impl<S: InputActions> Seats<S::Axis2, Axis2Binding> for S {}
88
89/// The input action set of a game that reads no input at all.
90///
91/// No value of it exists, so such a game reads no action.
92#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
93pub enum NoInputActions {}
94
95impl InputActions for NoInputActions {
96    type Button = NoInputButtons;
97    type Axis = NoInputAxes;
98    type Axis2 = NoInputAxes2;
99}
100
101/// The empty vocabulary of one kind: no value of it exists, so a game with
102/// no verb of that kind reads none.
103macro_rules! empty {
104    ($name:ident, $kind:ident, $binding:ident, $noun:literal) => {
105        #[doc = concat!("The vocabulary of a game with no ", $noun, " actions of its own.")]
106        ///
107        /// No value of it exists, so it fills the empty slot and nothing
108        /// else.
109        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
110        pub enum $name {}
111
112        impl InputAction for $name {
113            type Binding = $binding;
114
115            fn defaults(&self) -> Vec<$binding> {
116                match *self {}
117            }
118
119            fn all() -> Vec<Self> {
120                Vec::new()
121            }
122
123            fn name(&self) -> &'static str {
124                match *self {}
125            }
126
127            fn from_name(_name: &str) -> Option<Self> {
128                None
129            }
130        }
131
132        impl $kind for $name {
133            fn bindings(&self) -> Vec<$binding> {
134                match *self {}
135            }
136        }
137    };
138}
139
140empty!(NoInputButtons, InputButtonAction, ButtonBinding, "button");
141empty!(NoInputAxes, InputAxisAction, AxisBinding, "number");
142empty!(NoInputAxes2, InputAxis2Action, Axis2Binding, "vector");
143
144impl InputAction for Key {
145    type Binding = ButtonBinding;
146
147    fn defaults(&self) -> Vec<ButtonBinding> {
148        <Self as InputButtonAction>::bindings(self)
149    }
150
151    fn all() -> Vec<Self> {
152        Self::ALL.to_vec()
153    }
154
155    fn name(&self) -> &'static str {
156        self.token()
157    }
158
159    fn from_name(name: &str) -> Option<Self> {
160        Self::from_token(name)
161    }
162}
163
164/// A key is its own action, bound to itself: the vocabulary a prototype
165/// reads through before it has declared what the player does.
166impl InputButtonAction for Key {
167    fn bindings(&self) -> Vec<ButtonBinding> {
168        vec![ButtonBinding::Key(*self)]
169    }
170}
171
172impl InputActions for Key {
173    type Button = Key;
174    type Axis = NoInputAxes;
175    type Axis2 = NoInputAxes2;
176}