1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#![allow(clippy::trivially_copy_pass_by_ref)]
use crate::{
hotkey::Hotkey,
platform::prelude::*,
settings::{Field, SettingsDescription, Value},
};
use serde::{Deserialize, Serialize};
/// The configuration to use for a [`HotkeySystem`](crate::HotkeySystem). It describes which [`Hotkey`](livesplit_hotkey::Hotkey) to use as hotkeys for the different actions.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(default)]
pub struct HotkeyConfig {
/// The key to use for splitting and starting a new attempt.
pub split: Option<Hotkey>,
/// The key to use for resetting the current attempt.
pub reset: Option<Hotkey>,
/// The key to use for undoing the last split.
pub undo: Option<Hotkey>,
/// The key to use for skipping the current split.
pub skip: Option<Hotkey>,
/// The key to use for pausing the current attempt and starting a new
/// attempt.
pub pause: Option<Hotkey>,
/// The key to use for removing all the pause times from the current time.
pub undo_all_pauses: Option<Hotkey>,
/// The key to use for switching to the previous comparison.
pub previous_comparison: Option<Hotkey>,
/// The key to use for switching to the next comparison.
pub next_comparison: Option<Hotkey>,
/// The key to use for toggling between the `Real Time` and `Game Time`
/// timing methods.
pub toggle_timing_method: Option<Hotkey>,
}
impl Default for HotkeyConfig {
fn default() -> Self {
use crate::hotkey::KeyCode::*;
Self {
split: Some(Numpad1.into()),
reset: Some(Numpad3.into()),
undo: Some(Numpad8.into()),
skip: Some(Numpad2.into()),
pause: Some(Numpad5.into()),
undo_all_pauses: None,
previous_comparison: Some(Numpad4.into()),
next_comparison: Some(Numpad6.into()),
toggle_timing_method: None,
}
}
}
impl HotkeyConfig {
/// Accesses a generic description of the settings available for the hotkey
/// configuration and their current values.
pub fn settings_description(&self) -> SettingsDescription {
SettingsDescription::with_fields(vec![
Field::new("Start / Split".into(), self.split.into()),
Field::new("Reset".into(), self.reset.into()),
Field::new("Undo Split".into(), self.undo.into()),
Field::new("Skip Split".into(), self.skip.into()),
Field::new("Pause".into(), self.pause.into()),
Field::new("Undo All Pauses".into(), self.undo_all_pauses.into()),
Field::new(
"Previous Comparison".into(),
self.previous_comparison.into(),
),
Field::new("Next Comparison".into(), self.next_comparison.into()),
Field::new(
"Toggle Timing Method".into(),
self.toggle_timing_method.into(),
),
])
}
/// Sets a setting's value by its index to the given value.
///
/// # Errors
///
/// An error is returned if a hotkey is already in use by a different
/// action.
///
/// # Panics
///
/// This panics if the type of the value to be set is not compatible with
/// the type of the setting's value. A panic can also occur if the index of
/// the setting provided is out of bounds.
pub fn set_value(&mut self, index: usize, value: Value) -> Result<(), ()> {
let value: Option<Hotkey> = value.into();
if value.is_some() {
let any = [
self.split,
self.reset,
self.undo,
self.skip,
self.pause,
self.undo_all_pauses,
self.previous_comparison,
self.next_comparison,
self.toggle_timing_method,
]
.into_iter()
.enumerate()
.filter(|&(i, _)| i != index)
.any(|(_, v)| v == value);
if any {
return Err(());
}
}
match index {
0 => self.split = value,
1 => self.reset = value,
2 => self.undo = value,
3 => self.skip = value,
4 => self.pause = value,
5 => self.undo_all_pauses = value,
6 => self.previous_comparison = value,
7 => self.next_comparison = value,
8 => self.toggle_timing_method = value,
_ => panic!("Unsupported Setting Index"),
}
Ok(())
}
/// Decodes the hotkey configuration from JSON.
#[cfg(feature = "std")]
pub fn from_json<R>(reader: R) -> serde_json::Result<Self>
where
R: std::io::Read,
{
serde_json::from_reader(reader)
}
/// Encodes the hotkey configuration as JSON.
#[cfg(feature = "std")]
pub fn write_json<W>(&self, writer: W) -> serde_json::Result<()>
where
W: std::io::Write,
{
serde_json::to_writer(writer, self)
}
}