luminol_data/
commands.rs

1use serde::{Deserialize, Serialize};
2use strum::{EnumIter, IntoStaticStr};
3
4type Code = u16;
5type Parameters = Vec<Parameter>;
6
7#[derive(Deserialize, Serialize, Clone, Debug)]
8pub struct CommandDescription {
9    /// The code of this command
10    pub code: Code,
11    /// The name of the command
12    pub name: String,
13    /// The description for the command
14    /// Shows up when hovering over the command and in the command ui
15    #[serde(default)]
16    pub description: String,
17    /// The type of command this is
18    #[serde(default)]
19    pub kind: CommandKind,
20    /// Hide this in the command ui
21    #[serde(default)]
22    pub hidden: bool,
23
24    /// The text used by lumi!
25    #[serde(default)]
26    pub lumi_text: String,
27
28    /// A unique guid
29    ///
30    /// Used mainly in command-gen to prevent conflicts with egui::Id
31    #[serde(skip)]
32    #[serde(default = "rand::random")]
33    pub guid: u64,
34}
35
36impl CommandDescription {
37    /// How many total parameters does the command have?
38    pub fn parameter_count(&self) -> u8 {
39        match self.kind {
40            CommandKind::Branch { ref parameters, .. } | CommandKind::Single(ref parameters) => {
41                parameters.len() as u8
42                    + parameters
43                        .iter()
44                        .map(Parameter::parameter_count)
45                        .sum::<u8>()
46            }
47            CommandKind::Multi { .. } => 1,
48        }
49    }
50}
51
52impl Default for CommandDescription {
53    fn default() -> Self {
54        CommandDescription {
55            code: 0,
56            name: "New Command".to_string(),
57            description: "".to_string(),
58            kind: CommandKind::default(),
59            hidden: false,
60            lumi_text: "".to_string(),
61            guid: rand::random(),
62        }
63    }
64}
65
66#[derive(Deserialize, Serialize, Clone, Debug, EnumIter, IntoStaticStr)]
67pub enum CommandKind {
68    /// This command is a branch
69    ///
70    /// The Code is used to place an empty EventCommand at the end of the branch
71    Branch {
72        end_code: Code,
73        parameters: Parameters,
74    },
75    /// This command spans multiple event commands
76    ///
77    /// This type is reserved for multiline text commands
78    Multi { code: Code, highlight: bool },
79    /// This is a basic command
80    Single(Parameters),
81}
82
83impl Default for CommandKind {
84    fn default() -> Self {
85        CommandKind::Single(vec![])
86    }
87}
88
89// This is for the sake of command-gen
90impl PartialEq for CommandKind {
91    fn eq(&self, other: &Self) -> bool {
92        std::mem::discriminant(self) == std::mem::discriminant(other)
93    }
94}
95
96#[derive(Deserialize, Serialize, Clone, Debug, Default, EnumIter, IntoStaticStr)]
97pub enum Parameter {
98    Selection {
99        /// The index for this parameter
100        #[serde(default)]
101        index: Index,
102        /// Parameters are stored in a Vec of (i8, Parameter)
103        ///
104        /// The first tuple field (the i8) denotes what value should select this parameter
105        parameters: Vec<(i8, Parameter)>,
106
107        /// Ignore, used for command-gen
108        #[serde(skip)]
109        #[serde(default = "rand::random")]
110        guid: u64,
111    },
112    Group {
113        /// Groups parameters together
114        parameters: Parameters,
115
116        /// Ignore, used for command-gen
117        #[serde(skip)]
118        #[serde(default = "rand::random")]
119        guid: u64,
120    },
121    Single {
122        /// The index for this parameter
123        #[serde(default)]
124        index: Index,
125        /// Description of this parameter
126        description: String,
127        /// Parameter name
128        name: String,
129        /// Type of parameter
130        kind: ParameterKind,
131
132        /// Ignore, used for command-gen
133        #[serde(skip)]
134        #[serde(default = "rand::random")]
135        guid: u64,
136    },
137
138    /// A dummy parameter used for padding
139    #[default]
140    Dummy,
141
142    /// A parameter used as a label
143    Label(String),
144}
145
146#[derive(Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Eq)]
147pub enum Index {
148    /// The index is assumed
149    ///
150    /// The algorithm for assuming indices is as follows:
151    /// - Global index starts at 0
152    /// - The command iterates over its parameters
153    /// - If the parameter is single, it adds 1 to the global index
154    /// - If a group, it calculates the indexes for its parameters and adds them to the global index
155    /// - If a selection, add 1 to the global index, store the global index for each selection, and add the max value to the global index.
156    ///   All selections inside a selection will start off with the same index
157    Assumed(u8),
158    /// The index is set by the user
159    Overridden(u8),
160}
161
162impl Index {
163    /// Convert this to a u8
164    pub fn as_u8(self) -> u8 {
165        match self {
166            Self::Assumed(i) | Self::Overridden(i) => i,
167        }
168    }
169
170    pub fn as_usize(self) -> usize {
171        self.as_u8() as usize
172    }
173}
174
175impl Default for Index {
176    fn default() -> Self {
177        Self::Assumed(0)
178    }
179}
180
181impl PartialEq for Parameter {
182    fn eq(&self, other: &Self) -> bool {
183        std::mem::discriminant(self) == std::mem::discriminant(other)
184    }
185}
186
187impl Parameter {
188    pub fn parameter_count(&self) -> u8 {
189        match self {
190            Self::Group { ref parameters, .. } => {
191                parameters.len() as u8
192                    + parameters
193                        .iter()
194                        .map(Parameter::parameter_count)
195                        .sum::<u8>()
196            }
197            Self::Selection { ref parameters, .. } => {
198                parameters.len() as u8
199                    + parameters
200                        .iter()
201                        .map(|(_, p)| p)
202                        .map(Parameter::parameter_count)
203                        .sum::<u8>()
204            }
205            _ => 0,
206        }
207    }
208}
209
210#[derive(Deserialize, Serialize, Clone, Debug, EnumIter, IntoStaticStr, Default)]
211pub enum ParameterKind {
212    /// Parameter is a switch
213    Switch,
214    /// Parameter is a variable
215    Variable,
216    /// Parameter is a self switch
217    SelfSwitch,
218
219    /// Parameter is a string
220    String,
221
222    /// Parameter is a signed integer
223    #[default]
224    Int,
225    /// Parameter is a bool stored as an integer
226    IntBool,
227
228    /// Parameter is a choice between a set of enums
229    ///
230    /// The variants are a Vec of (String, i8) with the String being the variant, and the i8 being the value
231    Enum { variants: Vec<(String, i8)> },
232}
233
234impl PartialEq for ParameterKind {
235    fn eq(&self, other: &Self) -> bool {
236        std::mem::discriminant(self) == std::mem::discriminant(other)
237    }
238}