veloren_voxygen/settings/
control.rs1use crate::{game_input::GameInput, window::KeyMouse};
2use hashbrown::{HashMap, HashSet};
3use serde::{Deserialize, Serialize};
4use strum::IntoEnumIterator;
5use winit::event::{MouseButton, VirtualKeyCode};
6
7#[derive(Serialize, Deserialize)]
10struct ControlSettingsSerde {
11 keybindings: HashMap<GameInput, Option<KeyMouse>>,
12}
13
14impl From<ControlSettings> for ControlSettingsSerde {
15 fn from(control_settings: ControlSettings) -> Self {
16 let mut user_bindings: HashMap<GameInput, Option<KeyMouse>> = HashMap::new();
17 for (k, v) in control_settings.keybindings {
20 if ControlSettings::default_binding(k) != v {
21 user_bindings.insert(k, v);
23 }
24 }
25 ControlSettingsSerde {
26 keybindings: user_bindings,
27 }
28 }
29}
30
31#[derive(Clone, Debug, Serialize, Deserialize)]
33#[serde(from = "ControlSettingsSerde", into = "ControlSettingsSerde")]
34pub struct ControlSettings {
35 pub keybindings: HashMap<GameInput, Option<KeyMouse>>,
36 pub inverse_keybindings: HashMap<KeyMouse, HashSet<GameInput>>, }
38
39impl From<ControlSettingsSerde> for ControlSettings {
40 fn from(control_serde: ControlSettingsSerde) -> Self {
41 let user_keybindings = control_serde.keybindings;
42 let mut control_settings = ControlSettings::default();
43 for (k, maybe_v) in user_keybindings {
44 match maybe_v {
45 Some(v) => control_settings.modify_binding(k, v),
46 None => control_settings.remove_binding(k),
47 }
48 }
49 control_settings
50 }
51}
52
53#[cfg(target_os = "macos")]
59const MIDDLE_CLICK_KEY: KeyMouse = KeyMouse::Key(VirtualKeyCode::Grave);
60#[cfg(not(target_os = "macos"))]
61const MIDDLE_CLICK_KEY: KeyMouse = KeyMouse::Mouse(MouseButton::Middle);
62
63impl ControlSettings {
64 pub fn remove_binding(&mut self, game_input: GameInput) {
65 if let Some(inverse) = self
66 .keybindings
67 .insert(game_input, None)
68 .flatten()
69 .and_then(|key_mouse| self.inverse_keybindings.get_mut(&key_mouse))
70 {
71 inverse.remove(&game_input);
72 }
73 }
74
75 pub fn get_binding(&self, game_input: GameInput) -> Option<KeyMouse> {
76 self.keybindings.get(&game_input).copied().flatten()
77 }
78
79 pub fn get_associated_game_inputs(&self, key_mouse: &KeyMouse) -> Option<&HashSet<GameInput>> {
80 self.inverse_keybindings.get(key_mouse)
81 }
82
83 pub fn insert_binding(&mut self, game_input: GameInput, key_mouse: KeyMouse) {
84 self.keybindings.insert(game_input, Some(key_mouse));
85 self.inverse_keybindings
86 .entry(key_mouse)
87 .or_default()
88 .insert(game_input);
89 }
90
91 pub fn modify_binding(&mut self, game_input: GameInput, key_mouse: KeyMouse) {
92 if let Some(old_binding) = self.get_binding(game_input) {
95 self.inverse_keybindings
96 .entry(old_binding)
97 .or_default()
98 .remove(&game_input);
99 }
100 self.inverse_keybindings
102 .entry(key_mouse)
103 .or_default()
104 .insert(game_input);
105 self.keybindings.insert(game_input, Some(key_mouse));
107 }
108
109 pub fn has_conflicting_bindings(&self, key_mouse: KeyMouse) -> bool {
112 if let Some(game_inputs) = self.inverse_keybindings.get(&key_mouse) {
113 for a in game_inputs.iter() {
114 for b in game_inputs.iter() {
115 if !GameInput::can_share_bindings(*a, *b) {
116 return true;
117 }
118 }
119 }
120 }
121 false
122 }
123
124 pub fn default_binding(game_input: GameInput) -> Option<KeyMouse> {
125 match game_input {
127 GameInput::Primary => Some(KeyMouse::Mouse(MouseButton::Left)),
128 GameInput::Secondary => Some(KeyMouse::Mouse(MouseButton::Right)),
129 GameInput::Block => Some(KeyMouse::Key(VirtualKeyCode::LAlt)),
130 GameInput::ToggleCursor => Some(KeyMouse::Key(VirtualKeyCode::Comma)),
131 GameInput::Escape => Some(KeyMouse::Key(VirtualKeyCode::Escape)),
132 GameInput::Chat => Some(KeyMouse::Key(VirtualKeyCode::Return)),
133 GameInput::Command => Some(KeyMouse::Key(VirtualKeyCode::Slash)),
134 GameInput::MoveForward => Some(KeyMouse::Key(VirtualKeyCode::W)),
135 GameInput::MoveLeft => Some(KeyMouse::Key(VirtualKeyCode::A)),
136 GameInput::MoveBack => Some(KeyMouse::Key(VirtualKeyCode::S)),
137 GameInput::MoveRight => Some(KeyMouse::Key(VirtualKeyCode::D)),
138 GameInput::Jump => Some(KeyMouse::Key(VirtualKeyCode::Space)),
139 GameInput::Sit => Some(KeyMouse::Key(VirtualKeyCode::K)),
140 GameInput::Crawl => Some(KeyMouse::Key(VirtualKeyCode::Down)),
141 GameInput::Dance => Some(KeyMouse::Key(VirtualKeyCode::J)),
142 GameInput::Greet => Some(KeyMouse::Key(VirtualKeyCode::H)),
143 GameInput::Glide => Some(KeyMouse::Key(VirtualKeyCode::LControl)),
144 GameInput::Climb => Some(KeyMouse::Key(VirtualKeyCode::Space)),
145 GameInput::ClimbDown => Some(KeyMouse::Key(VirtualKeyCode::LShift)),
146 GameInput::SwimUp => Some(KeyMouse::Key(VirtualKeyCode::Space)),
147 GameInput::SwimDown => Some(KeyMouse::Key(VirtualKeyCode::LShift)),
148 GameInput::Fly => Some(KeyMouse::Key(VirtualKeyCode::H)),
149 GameInput::Sneak => Some(KeyMouse::Key(VirtualKeyCode::LShift)),
150 GameInput::ToggleLantern => Some(KeyMouse::Key(VirtualKeyCode::G)),
151 GameInput::Mount => Some(KeyMouse::Key(VirtualKeyCode::F)),
152 GameInput::StayFollow => Some(KeyMouse::Key(VirtualKeyCode::V)),
153 GameInput::Map => Some(KeyMouse::Key(VirtualKeyCode::M)),
154 GameInput::Inventory => Some(KeyMouse::Key(VirtualKeyCode::I)),
155 GameInput::Trade => Some(KeyMouse::Key(VirtualKeyCode::T)),
156 GameInput::Social => Some(KeyMouse::Key(VirtualKeyCode::O)),
157 GameInput::Crafting => Some(KeyMouse::Key(VirtualKeyCode::C)),
158 GameInput::Diary => Some(KeyMouse::Key(VirtualKeyCode::P)),
159 GameInput::Settings => Some(KeyMouse::Key(VirtualKeyCode::F10)),
160 GameInput::Controls => Some(KeyMouse::Key(VirtualKeyCode::F1)),
161 GameInput::ToggleInterface => Some(KeyMouse::Key(VirtualKeyCode::F2)),
162 GameInput::ToggleDebug => Some(KeyMouse::Key(VirtualKeyCode::F3)),
163 #[cfg(feature = "egui-ui")]
164 GameInput::ToggleEguiDebug => Some(KeyMouse::Key(VirtualKeyCode::F7)),
165 GameInput::ToggleChat => Some(KeyMouse::Key(VirtualKeyCode::F5)),
166 GameInput::Fullscreen => Some(KeyMouse::Key(VirtualKeyCode::F11)),
167 GameInput::Screenshot => Some(KeyMouse::Key(VirtualKeyCode::F4)),
168 GameInput::ToggleIngameUi => Some(KeyMouse::Key(VirtualKeyCode::F6)),
169 GameInput::Roll => Some(MIDDLE_CLICK_KEY),
170 GameInput::GiveUp => Some(KeyMouse::Key(VirtualKeyCode::Space)),
171 GameInput::Respawn => Some(KeyMouse::Key(VirtualKeyCode::Space)),
172 GameInput::Interact => Some(KeyMouse::Key(VirtualKeyCode::E)),
173 GameInput::ToggleWield => Some(KeyMouse::Key(VirtualKeyCode::R)),
174 GameInput::FreeLook => Some(KeyMouse::Key(VirtualKeyCode::L)),
175 GameInput::AutoWalk => Some(KeyMouse::Key(VirtualKeyCode::Period)),
176 GameInput::ZoomIn => Some(KeyMouse::Key(VirtualKeyCode::RBracket)),
177 GameInput::ZoomOut => Some(KeyMouse::Key(VirtualKeyCode::LBracket)),
178 GameInput::ZoomLock => None,
179 GameInput::CameraClamp => Some(KeyMouse::Key(VirtualKeyCode::Apostrophe)),
180 GameInput::CycleCamera => Some(KeyMouse::Key(VirtualKeyCode::Key0)),
181 GameInput::Slot1 => Some(KeyMouse::Key(VirtualKeyCode::Key1)),
182 GameInput::Slot2 => Some(KeyMouse::Key(VirtualKeyCode::Key2)),
183 GameInput::Slot3 => Some(KeyMouse::Key(VirtualKeyCode::Key3)),
184 GameInput::Slot4 => Some(KeyMouse::Key(VirtualKeyCode::Key4)),
185 GameInput::Slot5 => Some(KeyMouse::Key(VirtualKeyCode::Key5)),
186 GameInput::Slot6 => Some(KeyMouse::Key(VirtualKeyCode::Key6)),
187 GameInput::Slot7 => Some(KeyMouse::Key(VirtualKeyCode::Key7)),
188 GameInput::Slot8 => Some(KeyMouse::Key(VirtualKeyCode::Key8)),
189 GameInput::Slot9 => Some(KeyMouse::Key(VirtualKeyCode::Key9)),
190 GameInput::Slot10 => Some(KeyMouse::Key(VirtualKeyCode::Q)),
191 GameInput::SwapLoadout => Some(KeyMouse::Key(VirtualKeyCode::Tab)),
192 GameInput::Select => Some(KeyMouse::Key(VirtualKeyCode::X)),
193 GameInput::AcceptGroupInvite => Some(KeyMouse::Key(VirtualKeyCode::Y)),
194 GameInput::DeclineGroupInvite => Some(KeyMouse::Key(VirtualKeyCode::N)),
195 GameInput::MapZoomIn => Some(KeyMouse::Key(VirtualKeyCode::Plus)),
196 GameInput::MapZoomOut => Some(KeyMouse::Key(VirtualKeyCode::Minus)),
197 GameInput::MapSetMarker => Some(KeyMouse::Mouse(MouseButton::Middle)),
198 GameInput::SpectateSpeedBoost => Some(KeyMouse::Key(VirtualKeyCode::LControl)),
199 GameInput::SpectateViewpoint => Some(KeyMouse::Mouse(MouseButton::Middle)),
200 GameInput::MuteMaster => Some(KeyMouse::Key(VirtualKeyCode::Mute)),
201 GameInput::MuteInactiveMaster => None,
202 GameInput::MuteMusic => Some(KeyMouse::Key(VirtualKeyCode::F8)),
203 GameInput::MuteSfx => None,
204 GameInput::MuteAmbience => None,
205 GameInput::ToggleWalk => Some(KeyMouse::Key(VirtualKeyCode::B)),
206 }
207 }
208}
209
210impl Default for ControlSettings {
211 fn default() -> Self {
212 let mut new_settings = Self {
213 keybindings: HashMap::new(),
214 inverse_keybindings: HashMap::new(),
215 };
216 for game_input in GameInput::iter() {
218 match ControlSettings::default_binding(game_input) {
219 None => {},
220 Some(default) => new_settings.insert_binding(game_input, default),
221 };
222 }
223 new_settings
224 }
225}