veloren_voxygen/
game_input.rs

1use serde::{Deserialize, Serialize};
2use std::convert::AsRef;
3use strum::{AsRefStr, EnumIter, EnumString};
4
5/// Represents a key that the game recognises after input mapping.
6#[derive(
7    Clone,
8    Copy,
9    Debug,
10    PartialEq,
11    Eq,
12    PartialOrd,
13    Ord,
14    Hash,
15    Deserialize,
16    Serialize,
17    AsRefStr,
18    EnumIter,
19    EnumString,
20)]
21pub enum GameInput {
22    #[strum(serialize = "gameinput-primary")]
23    Primary,
24    #[strum(serialize = "gameinput-secondary")]
25    Secondary,
26    #[strum(serialize = "gameinput-block")]
27    Block,
28    #[strum(serialize = "gameinput-slot1")]
29    Slot1,
30    #[strum(serialize = "gameinput-slot2")]
31    Slot2,
32    #[strum(serialize = "gameinput-slot3")]
33    Slot3,
34    #[strum(serialize = "gameinput-slot4")]
35    Slot4,
36    #[strum(serialize = "gameinput-slot5")]
37    Slot5,
38    #[strum(serialize = "gameinput-slot6")]
39    Slot6,
40    #[strum(serialize = "gameinput-slot7")]
41    Slot7,
42    #[strum(serialize = "gameinput-slot8")]
43    Slot8,
44    #[strum(serialize = "gameinput-slot9")]
45    Slot9,
46    #[strum(serialize = "gameinput-slot10")]
47    Slot10,
48    #[strum(serialize = "gameinput-togglecursor")]
49    ToggleCursor,
50    #[strum(serialize = "gameinput-moveforward")]
51    MoveForward,
52    #[strum(serialize = "gameinput-moveback")]
53    MoveBack,
54    #[strum(serialize = "gameinput-moveleft")]
55    MoveLeft,
56    #[strum(serialize = "gameinput-moveright")]
57    MoveRight,
58    #[strum(serialize = "gameinput-jump")]
59    Jump,
60    #[strum(serialize = "gameinput-walljump")]
61    WallJump,
62    #[strum(serialize = "gameinput-sit")]
63    Sit,
64    #[strum(serialize = "gameinput-crawl")]
65    Crawl,
66    #[strum(serialize = "gameinput-dance")]
67    Dance,
68    #[strum(serialize = "gameinput-greet")]
69    Greet,
70    #[strum(serialize = "gameinput-glide")]
71    Glide,
72    #[strum(serialize = "gameinput-swimup")]
73    SwimUp,
74    #[strum(serialize = "gameinput-swimdown")]
75    SwimDown,
76    #[strum(serialize = "gameinput-fly")]
77    Fly,
78    #[strum(serialize = "gameinput-sneak")]
79    Sneak,
80    #[strum(serialize = "gameinput-cancelclimb")]
81    CancelClimb,
82    #[strum(serialize = "gameinput-togglelantern")]
83    ToggleLantern,
84    #[strum(serialize = "gameinput-mount")]
85    Mount,
86    #[strum(serialize = "gameinput-stayfollow")]
87    StayFollow,
88    #[strum(serialize = "gameinput-chat")]
89    Chat,
90    #[strum(serialize = "gameinput-command")]
91    Command,
92    #[strum(serialize = "gameinput-escape")]
93    Escape,
94    #[strum(serialize = "gameinput-map")]
95    Map,
96    #[strum(serialize = "gameinput-inventory")]
97    Inventory,
98    #[strum(serialize = "gameinput-trade")]
99    Trade,
100    #[strum(serialize = "gameinput-social")]
101    Social,
102    #[strum(serialize = "gameinput-crafting")]
103    Crafting,
104    #[strum(serialize = "gameinput-diary")]
105    Diary,
106    #[strum(serialize = "gameinput-settings")]
107    Settings,
108    #[strum(serialize = "gameinput-controls")]
109    Controls,
110    #[strum(serialize = "gameinput-toggleinterface")]
111    ToggleInterface,
112    #[strum(serialize = "gameinput-toggledebug")]
113    ToggleDebug,
114    #[cfg(feature = "egui-ui")]
115    #[strum(serialize = "gameinput-toggle_egui_debug")]
116    ToggleEguiDebug,
117    #[strum(serialize = "gameinput-togglechat")]
118    ToggleChat,
119    #[strum(serialize = "gameinput-fullscreen")]
120    Fullscreen,
121    #[strum(serialize = "gameinput-screenshot")]
122    Screenshot,
123    #[strum(serialize = "gameinput-toggleingameui")]
124    ToggleIngameUi,
125    #[strum(serialize = "gameinput-roll")]
126    Roll,
127    #[strum(serialize = "gameinput-giveup")]
128    GiveUp,
129    #[strum(serialize = "gameinput-respawn")]
130    Respawn,
131    #[strum(serialize = "gameinput-interact")]
132    Interact,
133    #[strum(serialize = "gameinput-togglewield")]
134    ToggleWield,
135    #[strum(serialize = "gameinput-swaploadout")]
136    SwapLoadout,
137    #[strum(serialize = "gameinput-freelook")]
138    FreeLook,
139    #[strum(serialize = "gameinput-autowalk")]
140    AutoWalk,
141    #[strum(serialize = "gameinput-zoomin")]
142    ZoomIn,
143    #[strum(serialize = "gameinput-zoomout")]
144    ZoomOut,
145    #[strum(serialize = "gameinput-zoomlock")]
146    ZoomLock,
147    #[strum(serialize = "gameinput-cameraclamp")]
148    CameraClamp,
149    #[strum(serialize = "gameinput-cyclecamera")]
150    CycleCamera,
151    #[strum(serialize = "gameinput-select")]
152    Select,
153    #[strum(serialize = "gameinput-acceptgroupinvite")]
154    AcceptGroupInvite,
155    #[strum(serialize = "gameinput-declinegroupinvite")]
156    DeclineGroupInvite,
157    #[strum(serialize = "gameinput-mapzoomin")]
158    MapZoomIn,
159    #[strum(serialize = "gameinput-mapzoomout")]
160    MapZoomOut,
161    #[strum(serialize = "gameinput-map-locationmarkerbutton")]
162    MapSetMarker,
163    #[strum(serialize = "gameinput-spectatespeedboost")]
164    SpectateSpeedBoost,
165    #[strum(serialize = "gameinput-spectateviewpoint")]
166    SpectateViewpoint,
167    #[strum(serialize = "gameinput-mutemaster")]
168    MuteMaster,
169    #[strum(serialize = "gameinput-muteinactivemaster")]
170    MuteInactiveMaster,
171    #[strum(serialize = "gameinput-mutemusic")]
172    MuteMusic,
173    #[strum(serialize = "gameinput-mutesfx")]
174    MuteSfx,
175    #[strum(serialize = "gameinput-muteambience")]
176    MuteAmbience,
177    #[strum(serialize = "gameinput-togglewalk")]
178    ToggleWalk,
179}
180
181impl GameInput {
182    pub fn get_localization_key(&self) -> &str { self.as_ref() }
183
184    /// Return true if `a` and `b` are able to be bound to the same key at the
185    /// same time without conflict. For example, the player can't jump and climb
186    /// at the same time, so these can be bound to the same key.
187    pub fn can_share_bindings(a: GameInput, b: GameInput) -> bool {
188        let bindings_a = a.get_representative_bindings();
189        let bindings_b = b.get_representative_bindings();
190
191        if bindings_a.is_empty() && bindings_b.is_empty() {
192            return a == b;
193        }
194        if bindings_a.is_empty() {
195            return bindings_b.contains(&a);
196        }
197        if bindings_b.is_empty() {
198            return bindings_a.contains(&b);
199        }
200
201        bindings_a.iter().any(|x| bindings_b.contains(x))
202    }
203
204    /// If two GameInputs are able to be bound at the same time, then they will
205    /// return a slice that contains the other GameInput.
206    /// Since a GameInput might be fine to be shared with multiple other
207    /// GameInputs a slice is required instead of just a single GameInput.
208    /// This models the Find operation of a disjoint-set data
209    /// structure.
210    fn get_representative_bindings(self) -> &'static [GameInput] {
211        match self {
212            GameInput::SwimUp | GameInput::Respawn | GameInput::GiveUp => &[GameInput::Jump],
213
214            GameInput::AutoWalk | GameInput::FreeLook => &[GameInput::FreeLook],
215
216            GameInput::SpectateSpeedBoost => &[GameInput::Glide],
217            GameInput::WallJump => &[GameInput::Mount, GameInput::Jump],
218
219            GameInput::SwimDown | GameInput::Sneak | GameInput::CancelClimb => &[GameInput::Roll],
220
221            GameInput::SpectateViewpoint => &[GameInput::MapSetMarker],
222
223            _ => &[],
224        }
225    }
226}