Skip to main content

vn_settings/
lib.rs

1mod color;
2mod layer;
3mod layout;
4mod object;
5mod timing;
6
7pub use color::ColorSettings;
8pub use layer::LayerSettings;
9pub use layout::{BoxLayoutSettings, LayoutSettings, ViewLayoutSettings};
10pub use object::ObjectSettings;
11pub use timing::TimingSettings;
12
13use color::{BoxColorParameter, ColorParameter, SelectableBoxColorParameter};
14use layer::{
15    LayerAnchorParameter, LayerImageParameter, LayerLayoutParameter, LayerObjectLayoutParameter,
16};
17use layout::{BoxLayoutParameter, LayoutParameter, ViewLayoutParameter};
18use object::{ObjectAnchorParameter, ObjectImageParameter, ObjectScaleParameter};
19use timing::TimingParameter;
20
21use dialogi::{DialogChange, DialogParameter};
22use indexmap::IndexMap;
23use simple_color::Color;
24
25use std::collections::{HashMap, HashSet};
26
27trait Settings<Parameter> {
28    type Value;
29
30    fn get_mut(&mut self, parameter: &Parameter) -> &mut Self::Value;
31}
32
33trait Resettable {
34    fn reset(&mut self) {}
35    fn reset_aspects(&mut self) {}
36}
37
38#[derive(Default)]
39pub struct Override<T> {
40    default: T,
41    characters_default: HashMap<Box<str>, T>,
42    characters_aspect: HashMap<Box<str>, T>,
43    aspect: Option<T>,
44    characters_scene: HashMap<Box<str>, T>,
45    scene: Option<T>,
46}
47
48impl<T> Override<T> {
49    fn set_default(&mut self, name: Option<Box<str>>, value: T) {
50        if let Some(name) = name {
51            self.characters_default.insert(name, value);
52        } else {
53            self.default = value;
54        }
55    }
56
57    fn set_aspect(&mut self, name: Option<&str>, value: Option<T>) {
58        let Some(name) = name else {
59            self.aspect = value;
60            return;
61        };
62
63        if let Some(value) = value {
64            self.characters_aspect.insert(name.into(), value);
65        } else {
66            self.characters_aspect.remove(name);
67        }
68    }
69
70    fn set_scene(&mut self, name: Option<&str>, value: Option<T>) {
71        let Some(name) = name else {
72            self.scene = value;
73            return;
74        };
75
76        if let Some(value) = value {
77            self.characters_scene.insert(name.into(), value);
78        } else {
79            self.characters_scene.remove(name);
80        }
81    }
82}
83
84impl<T> Resettable for Override<T> {
85    fn reset(&mut self) {
86        self.scene = None;
87    }
88
89    fn reset_aspects(&mut self) {
90        self.aspect = None;
91        self.characters_aspect.clear();
92    }
93}
94
95impl<T> From<T> for Override<T> {
96    fn from(default: T) -> Self {
97        Self {
98            default,
99            characters_default: HashMap::new(),
100            characters_aspect: HashMap::new(),
101            aspect: None,
102            characters_scene: HashMap::new(),
103            scene: None,
104        }
105    }
106}
107
108impl<T> Override<T> {
109    pub fn get(&self, name: &str) -> T
110    where
111        T: Copy,
112    {
113        *self.get_ref(name)
114    }
115
116    pub fn get_ref(&self, name: &str) -> &T {
117        if let Some(scene) = &self.scene {
118            scene
119        } else if name.is_empty() {
120            if let Some(aspect) = &self.aspect {
121                aspect
122            } else {
123                &self.default
124            }
125        } else if let Some(character_scene) = self.characters_scene.get(name) {
126            character_scene
127        } else if let Some(aspect) = &self.aspect {
128            aspect
129        } else if let Some(character_aspect) = self.characters_aspect.get(name) {
130            character_aspect
131        } else if let Some(character_default) = self.characters_default.get(name) {
132            character_default
133        } else {
134            &self.default
135        }
136    }
137}
138
139#[derive(Default)]
140pub struct Names {
141    pub default: HashMap<Box<str>, Box<str>>,
142    pub aspect: HashMap<Box<str>, Box<str>>,
143    pub scene: HashMap<Box<str>, Box<str>>,
144}
145
146impl Names {
147    pub fn new() -> Self {
148        Self::default()
149    }
150
151    pub fn reset(&mut self) {
152        self.scene.clear();
153    }
154
155    pub fn reset_aspects(&mut self) {
156        self.aspect.clear();
157    }
158
159    pub fn get<'a>(&'a self, name: &'a str) -> &'a str {
160        self.scene
161            .get(name)
162            .or_else(|| self.aspect.get(name))
163            .or_else(|| self.default.get(name))
164            .map_or(name, |v| v)
165    }
166}
167
168type OvrrideColorSettings = ColorSettings<Override<Color>>;
169type OverrideTimingSettings = TimingSettings<Override<f32>>;
170type OverrideObjectSettings =
171    ObjectSettings<Override<Option<Box<str>>>, Override<[f32; 2]>, Override<f32>>;
172type OverrideLayerSettings =
173    LayerSettings<Override<Option<usize>>, Override<f32>, Override<Option<usize>>>;
174type OverrideLayoutSettings = LayoutSettings<Override<f32>>;
175
176pub struct PlayerSettings {
177    pub colors: OvrrideColorSettings,
178    pub timing: OverrideTimingSettings,
179    pub objects: OverrideObjectSettings,
180    pub layers: OverrideLayerSettings,
181    pub layout: OverrideLayoutSettings,
182    pub names: Names,
183    pub custom_colors: HashMap<Box<str>, Override<Color>>,
184    pub custom_floats: HashMap<Box<str>, Override<f32>>,
185}
186
187impl PlayerSettings {
188    pub fn common() -> Self {
189        Self {
190            colors: ColorSettings::common(),
191            timing: TimingSettings::common(),
192            objects: ObjectSettings::common(),
193            layers: LayerSettings::common(),
194            layout: LayoutSettings::common(),
195            names: Names::new(),
196            custom_colors: HashMap::new(),
197            custom_floats: HashMap::new(),
198        }
199    }
200
201    pub fn apply_setting(&mut self, context: &mut SettingsContext, key: &str, value: &str) {
202        if let Some(parameter) = Parameter::create(key, context) {
203            let setter = parameter.value_setter(value, context);
204            self.set_character_default(setter);
205        }
206    }
207
208    pub fn extract_settings(
209        &mut self,
210        context: &mut SettingsContext,
211        config_map: &mut IndexMap<Box<str>, Box<str>>,
212    ) {
213        for (key, value) in config_map.drain(..) {
214            self.apply_setting(context, &key, &value);
215        }
216    }
217
218    pub fn reset(&mut self) {
219        self.colors.reset();
220        self.timing.reset();
221        self.layers.reset();
222        self.layout.reset();
223        self.names.reset();
224        for override_value in self.custom_colors.values_mut() {
225            override_value.reset();
226        }
227        for override_value in self.custom_floats.values_mut() {
228            override_value.reset();
229        }
230    }
231
232    pub fn set_aspect(&mut self, setter: Setter) {
233        use Setter::*;
234        match setter {
235            Color(parameter, value) => self
236                .colors
237                .get_mut(&parameter.parameter)
238                .set_aspect(parameter.name.as_deref(), Some(value)),
239            Timing(parameter, value) => self
240                .timing
241                .get_mut(&parameter.parameter)
242                .set_aspect(parameter.name.as_deref(), Some(value)),
243            ObjectImage(parameter, value) => self
244                .objects
245                .get_mut(&parameter.parameter)
246                .set_aspect(parameter.name.as_deref(), Some(value)),
247            ObjectAnchor(parameter, value) => self
248                .objects
249                .get_mut(&parameter.parameter)
250                .set_aspect(parameter.name.as_deref(), Some(value)),
251            ObjectScale(parameter, value) => self
252                .objects
253                .get_mut(&parameter.parameter)
254                .set_aspect(parameter.name.as_deref(), Some(value)),
255            LayerImage(parameter, value) => self
256                .layers
257                .get_mut(&parameter.parameter)
258                .set_aspect(parameter.name.as_deref(), Some(value)),
259            LayerLayout(parameter, value) => self
260                .layers
261                .get_mut(&parameter.parameter)
262                .set_aspect(parameter.name.as_deref(), Some(value)),
263            LayerAnchor(parameter, value) => self
264                .layers
265                .get_mut(&parameter.parameter)
266                .set_aspect(parameter.name.as_deref(), Some(value)),
267            Layout(parameter, value) => self
268                .layout
269                .get_mut(&parameter.parameter)
270                .set_aspect(parameter.name.as_deref(), Some(value)),
271            Name(parameter, value) => {
272                self.names.aspect.insert(parameter, value);
273            }
274            CustomColor(parameter, value) => self
275                .custom_colors
276                .entry(parameter.parameter.clone())
277                .or_default()
278                .set_aspect(parameter.name.as_deref(), Some(value)),
279            CustomFloat(parameter, value) => self
280                .custom_floats
281                .entry(parameter.parameter.clone())
282                .or_default()
283                .set_aspect(parameter.name.as_deref(), Some(value)),
284        }
285    }
286
287    pub fn reset_aspects(&mut self) {
288        self.colors.reset_aspects();
289        self.timing.reset_aspects();
290        self.objects.reset_aspects();
291        self.layers.reset_aspects();
292        self.layout.reset_aspects();
293        self.names.reset_aspects();
294        for override_value in self.custom_colors.values_mut() {
295            override_value.reset_aspects();
296        }
297        for override_value in self.custom_floats.values_mut() {
298            override_value.reset_aspects();
299        }
300    }
301}
302
303#[derive(Clone, Debug, PartialEq, Eq, Hash)]
304pub struct NamedParameter<T> {
305    name: Option<Box<str>>,
306    parameter: T,
307}
308
309trait ParameterNamer: Sized {
310    fn named(self, name: Option<Box<str>>) -> NamedParameter<Self> {
311        NamedParameter {
312            name,
313            parameter: self,
314        }
315    }
316}
317
318impl<T> ParameterNamer for T {}
319
320type NamedColorParameter = NamedParameter<ColorParameter>;
321type NamedTimingParameter = NamedParameter<TimingParameter>;
322type NamedObjectImageParameter = NamedParameter<ObjectImageParameter>;
323type NamedObjectAnchorParameter = NamedParameter<ObjectAnchorParameter>;
324type NamedObjectScaleParameter = NamedParameter<ObjectScaleParameter>;
325type NamedLayerImageParameter = NamedParameter<LayerImageParameter>;
326type NamedLayerLayoutParameter = NamedParameter<LayerLayoutParameter>;
327type NamedLayerAnchorParameter = NamedParameter<LayerAnchorParameter>;
328type NamedLayoutParameter = NamedParameter<LayoutParameter>;
329
330#[derive(Clone, Debug, PartialEq, Eq, Hash)]
331pub enum Parameter {
332    Color(NamedColorParameter),
333    Timing(NamedTimingParameter),
334    ObjectImage(NamedObjectImageParameter),
335    ObjectAnchor(NamedObjectAnchorParameter),
336    ObjectScale(NamedObjectScaleParameter),
337    LayerImage(NamedLayerImageParameter),
338    LayerLayout(NamedLayerLayoutParameter),
339    LayerAnchor(NamedLayerAnchorParameter),
340    Layout(NamedLayoutParameter),
341    Name(Box<str>),
342    CustomColor(NamedParameter<Box<str>>),
343    CustomFloat(NamedParameter<Box<str>>),
344}
345
346pub struct Object {
347    index: usize,
348    images: HashMap<Box<str>, usize>,
349}
350
351impl Object {
352    fn new(index: usize) -> Self {
353        Self {
354            index,
355            images: HashMap::new(),
356        }
357    }
358}
359
360pub struct LayerInfo {
361    pub name: Box<str>,
362    pub path: Box<str>,
363}
364
365pub fn extract_layers(layers: &mut Vec<LayerInfo>, config_map: &mut IndexMap<Box<str>, Box<str>>) {
366    let keys: Vec<_> = config_map.keys().cloned().collect();
367    for key in keys {
368        let Some(("Layer", name)) = key.split_once(':') else {
369            continue;
370        };
371
372        let path = config_map.shift_remove(&key).expect("Invalid layer");
373        layers.push(LayerInfo {
374            name: name.into(),
375            path,
376        });
377    }
378
379    if layers.is_empty() {
380        layers.push(LayerInfo {
381            name: "Background".into(),
382            path: Box::default(),
383        });
384        layers.push(LayerInfo {
385            name: "Character".into(),
386            path: Box::default(),
387        });
388    }
389}
390
391#[derive(Default)]
392pub struct SettingsContext {
393    pub object_cache: HashMap<Box<str>, Object>,
394    pub layers: Vec<LayerInfo>,
395    pub anchors: HashMap<Box<str>, usize>,
396    pub custom_color_names: HashSet<Box<str>>,
397    pub custom_float_names: HashSet<Box<str>>,
398}
399
400impl SettingsContext {
401    pub fn new() -> Self {
402        Self::default()
403    }
404}
405
406impl Parameter {
407    fn create_character(name: &str, context: &mut SettingsContext) -> Option<Self> {
408        let (main, sub) = name.split_once(':')?;
409
410        if main != "Character" {
411            return None;
412        }
413
414        let (character_name, option) = sub.split_once(':')?;
415
416        let character_name = character_name.into();
417        if option == "name" {
418            Some(Self::Name(character_name))
419        } else {
420            create_parameter(option, Some(character_name), context)
421        }
422    }
423
424    pub fn value_setter(self, value: &str, context: &mut SettingsContext) -> Setter {
425        fn color(repr: &str) -> Color {
426            match repr {
427                "black" => Color::BLACK,
428                "white" => Color::WHITE,
429
430                "red" => Color::RED,
431                "yellow" => Color::YELLOW,
432                "green" => Color::GREEN,
433                "cyan" => Color::CYAN,
434                "blue" => Color::BLUE,
435                "magenta" => Color::MAGENTA,
436
437                _ => repr
438                    .parse::<Color>()
439                    .unwrap_or_else(|_| panic!("Color '{repr}' does not exist")),
440            }
441        }
442
443        match self {
444            Self::Color(parameter) => Setter::Color(parameter, color(value)),
445            Self::Timing(parameter) => Setter::Timing(
446                parameter,
447                value.parse().expect("Parsing timing parameter failed"),
448            ),
449            Self::ObjectImage(parameter) => Setter::ObjectImage(parameter, Some(value.into())),
450            Self::ObjectAnchor(parameter) => Setter::ObjectAnchor(parameter, {
451                let (x, y) = value
452                    .split_once(char::is_whitespace)
453                    .expect("Parsing object anchor parameter failed");
454                let x = x.parse().expect("Parsing object anchor parameter failed");
455                let y = y.parse().expect("Parsing object anchor parameter failed");
456                [x, y]
457            }),
458            Self::ObjectScale(parameter) => Setter::ObjectScale(
459                parameter,
460                value.parse().expect("Parsing image scale parameter failed"),
461            ),
462            Self::LayerImage(parameter) => {
463                let index = if value.is_empty() {
464                    None
465                } else {
466                    let path = &context.layers[parameter.parameter.0].path;
467                    let path_holder;
468                    let full_path = if path.is_empty() {
469                        value
470                    } else {
471                        path_holder = format!("{path}:{value}");
472                        &path_holder
473                    };
474                    if let Some(Object { index, .. }) = context.object_cache.get(full_path) {
475                        Some(*index)
476                    } else {
477                        eprintln!("Undefined image object {value:?}");
478                        None
479                    }
480                };
481                Setter::LayerImage(parameter, index)
482            }
483            Self::LayerLayout(parameter) => Setter::LayerLayout(
484                parameter,
485                value
486                    .parse()
487                    .expect("Parsing object layout parameter failed"),
488            ),
489            Self::LayerAnchor(parameter) => {
490                let index = if value.is_empty() {
491                    None
492                } else {
493                    let anchor_index = context.anchors.len();
494                    Some(*context.anchors.entry(value.into()).or_insert(anchor_index))
495                };
496                Setter::LayerAnchor(parameter, index)
497            }
498            Self::Layout(parameter) => Setter::Layout(
499                parameter,
500                value.parse().expect("Parsing layout parameter failed"),
501            ),
502            Self::Name(parameter) => Setter::Name(parameter, value.into()),
503            Self::CustomColor(parameter) => Setter::CustomColor(parameter, color(value)),
504            Self::CustomFloat(parameter) => Setter::CustomFloat(
505                parameter,
506                value
507                    .parse()
508                    .unwrap_or_else(|_| panic!("Parsing custom float parameter failed: {value:?}")),
509            ),
510        }
511    }
512}
513
514fn create_parameter(
515    parameter_name: &str,
516    character_name: Option<Box<str>>,
517    context: &mut SettingsContext,
518) -> Option<Parameter> {
519    let (path, parameter_name) = parameter_name.split_once(':')?;
520    Some(match path {
521        "Color" => Parameter::Color(
522            match parameter_name {
523                "background" => ColorParameter::Background,
524                "foreground" => ColorParameter::Foreground,
525                "dialog-text-fill" => ColorParameter::Dialog(BoxColorParameter::TextFill),
526                "dialog-text-line" => ColorParameter::Dialog(BoxColorParameter::TextLine),
527                "dialog-name-fill" => ColorParameter::Dialog(BoxColorParameter::NameFill),
528                "dialog-name-line" => ColorParameter::Dialog(BoxColorParameter::NameLine),
529
530                "choice-default-text-fill" => ColorParameter::Choice(SelectableBoxColorParameter {
531                    selected: false,
532                    parameter: BoxColorParameter::TextFill,
533                }),
534                "choice-default-text-line" => ColorParameter::Choice(SelectableBoxColorParameter {
535                    selected: false,
536                    parameter: BoxColorParameter::TextLine,
537                }),
538                "choice-default-name-fill" => ColorParameter::Choice(SelectableBoxColorParameter {
539                    selected: false,
540                    parameter: BoxColorParameter::NameFill,
541                }),
542                "choice-default-name-line" => ColorParameter::Choice(SelectableBoxColorParameter {
543                    selected: false,
544                    parameter: BoxColorParameter::NameLine,
545                }),
546                "choice-select-text-fill" => ColorParameter::Choice(SelectableBoxColorParameter {
547                    selected: true,
548                    parameter: BoxColorParameter::TextFill,
549                }),
550                "choice-select-text-line" => ColorParameter::Choice(SelectableBoxColorParameter {
551                    selected: true,
552                    parameter: BoxColorParameter::TextLine,
553                }),
554                "choice-select-name-fill" => ColorParameter::Choice(SelectableBoxColorParameter {
555                    selected: true,
556                    parameter: BoxColorParameter::NameFill,
557                }),
558                "choice-select-name-line" => ColorParameter::Choice(SelectableBoxColorParameter {
559                    selected: true,
560                    parameter: BoxColorParameter::NameLine,
561                }),
562
563                "revert-default-text-fill" => ColorParameter::Revert(SelectableBoxColorParameter {
564                    selected: false,
565                    parameter: BoxColorParameter::TextFill,
566                }),
567                "revert-default-text-line" => ColorParameter::Revert(SelectableBoxColorParameter {
568                    selected: false,
569                    parameter: BoxColorParameter::TextLine,
570                }),
571                "revert-default-name-fill" => ColorParameter::Revert(SelectableBoxColorParameter {
572                    selected: false,
573                    parameter: BoxColorParameter::NameFill,
574                }),
575                "revert-default-name-line" => ColorParameter::Revert(SelectableBoxColorParameter {
576                    selected: false,
577                    parameter: BoxColorParameter::NameLine,
578                }),
579                "revert-select-text-fill" => ColorParameter::Revert(SelectableBoxColorParameter {
580                    selected: true,
581                    parameter: BoxColorParameter::TextFill,
582                }),
583                "revert-select-text-line" => ColorParameter::Revert(SelectableBoxColorParameter {
584                    selected: true,
585                    parameter: BoxColorParameter::TextLine,
586                }),
587                "revert-select-name-fill" => ColorParameter::Revert(SelectableBoxColorParameter {
588                    selected: true,
589                    parameter: BoxColorParameter::NameFill,
590                }),
591                "revert-select-name-line" => ColorParameter::Revert(SelectableBoxColorParameter {
592                    selected: true,
593                    parameter: BoxColorParameter::NameLine,
594                }),
595
596                _ => return None,
597            }
598            .named(character_name),
599        ),
600
601        "Timing" => Parameter::Timing(
602            match parameter_name {
603                "auto-next" => TimingParameter::AutoNext,
604                "letter" => TimingParameter::Letter,
605                "line" => TimingParameter::Line,
606                "select" => TimingParameter::Select,
607                "view" => TimingParameter::View,
608
609                _ => return None,
610            }
611            .named(character_name),
612        ),
613
614        "Image" => {
615            let (object_name, parameter_name) = parameter_name.rsplit_once(':')?;
616
617            let entry_count = context.object_cache.len();
618            let Object { index, images } = context
619                .object_cache
620                .entry(object_name.into())
621                .or_insert_with(|| Object::new(entry_count));
622
623            let image_index = images.len();
624            let parameter_index = *images.entry(parameter_name.into()).or_insert(image_index);
625
626            Parameter::ObjectImage(
627                ObjectImageParameter(*index, parameter_index).named(character_name),
628            )
629        }
630
631        "Anchor" => {
632            let (object_name, parameter_name) = parameter_name.rsplit_once(':')?;
633
634            let entry_count = context.object_cache.len();
635            let Object { index, .. } = context
636                .object_cache
637                .entry(object_name.into())
638                .or_insert_with(|| Object::new(entry_count));
639
640            let anchor_index = context.anchors.len();
641            let parameter_index = *context
642                .anchors
643                .entry(parameter_name.into())
644                .or_insert(anchor_index);
645
646            Parameter::ObjectAnchor(
647                ObjectAnchorParameter(*index, parameter_index).named(character_name),
648            )
649        }
650
651        "Transform" => {
652            let (object_name, parameter_name) = parameter_name.rsplit_once(':')?;
653
654            if parameter_name != "scale" {
655                return None;
656            }
657
658            let entry_count = context.object_cache.len();
659            let Object { index, .. } = context
660                .object_cache
661                .entry(object_name.into())
662                .or_insert_with(|| Object::new(entry_count));
663
664            Parameter::ObjectScale(ObjectScaleParameter(*index).named(character_name))
665        }
666
667        "Object" => {
668            let (layer_name, parameter_name) = parameter_name.split_once(':')?;
669            let layer = context
670                .layers
671                .iter()
672                .position(|layer| &*layer.name == layer_name)?;
673
674            match parameter_name {
675                "image" => Parameter::LayerImage(LayerImageParameter(layer).named(character_name)),
676                "hor" => Parameter::LayerLayout(
677                    LayerLayoutParameter {
678                        layer,
679                        layout: LayerObjectLayoutParameter::Hor,
680                    }
681                    .named(character_name),
682                ),
683                "ver" => Parameter::LayerLayout(
684                    LayerLayoutParameter {
685                        layer,
686                        layout: LayerObjectLayoutParameter::Ver,
687                    }
688                    .named(character_name),
689                ),
690                "scale" => Parameter::LayerLayout(
691                    LayerLayoutParameter {
692                        layer,
693                        layout: LayerObjectLayoutParameter::Scale,
694                    }
695                    .named(character_name),
696                ),
697                "anchor" => {
698                    Parameter::LayerAnchor(LayerAnchorParameter(layer).named(character_name))
699                }
700
701                _ => return None,
702            }
703        }
704
705        "Layout" => Parameter::Layout(
706            {
707                let (subpath, parameter_name) = parameter_name.split_once(':')?;
708                let box_layout_parameter = || {
709                    Some(match parameter_name {
710                        "hor" => BoxLayoutParameter::Hor,
711                        "ver" => BoxLayoutParameter::Ver,
712                        "width" => BoxLayoutParameter::Width,
713                        "height" => BoxLayoutParameter::Height,
714                        "corner" => BoxLayoutParameter::Corner,
715                        "line" => BoxLayoutParameter::Line,
716                        "text-size" => BoxLayoutParameter::TextSize,
717                        "name-size" => BoxLayoutParameter::NameSize,
718
719                        _ => return None,
720                    })
721                };
722
723                let view_layout_parameter = || {
724                    Some(match parameter_name {
725                        "hor" => ViewLayoutParameter::Hor,
726                        "ver" => ViewLayoutParameter::Ver,
727                        "zoom" => ViewLayoutParameter::Zoom,
728
729                        _ => return None,
730                    })
731                };
732
733                match subpath {
734                    "Main" => box_layout_parameter()?.main(),
735                    "List" => box_layout_parameter()?.list(),
736                    "View" => LayoutParameter::View(view_layout_parameter()?),
737
738                    _ => return None,
739                }
740            }
741            .named(character_name),
742        ),
743
744        "Parameter" => {
745            let (type_name, param_name) = parameter_name.split_once(':')?;
746            let param_name: Box<str> = param_name.into();
747            match type_name {
748                "Color" => {
749                    context.custom_color_names.insert(param_name.clone());
750                    Parameter::CustomColor(param_name.named(character_name))
751                }
752                "Number" => {
753                    context.custom_float_names.insert(param_name.clone());
754                    Parameter::CustomFloat(param_name.named(character_name))
755                }
756                _ => return None,
757            }
758        }
759
760        _ => return None,
761    })
762}
763
764impl Parameter {
765    pub fn create_setter(key: &str, value: &str, context: &mut SettingsContext) -> Option<Setter> {
766        let parameter = if let Some(p) = create_parameter(key, None, context) {
767            p
768        } else {
769            Self::create_character(key, context)?
770        };
771        Some(parameter.value_setter(value, context))
772    }
773}
774
775impl DialogParameter for Parameter {
776    type Context = SettingsContext;
777
778    fn create(name: &str, context: &mut SettingsContext) -> Option<Self> {
779        if name == "-" {
780            None
781        } else if let Some(parameter) = create_parameter(name, None, context) {
782            Some(parameter)
783        } else {
784            let result = Self::create_character(name, context);
785            if result.is_none() {
786                eprintln!("Setting not availabe: {name}");
787            }
788            result
789        }
790    }
791}
792
793#[derive(Clone)]
794pub enum Setter {
795    Color(NamedColorParameter, Color),
796    Timing(NamedTimingParameter, f32),
797    ObjectImage(NamedObjectImageParameter, Option<Box<str>>),
798    ObjectAnchor(NamedObjectAnchorParameter, [f32; 2]),
799    ObjectScale(NamedObjectScaleParameter, f32),
800    LayerImage(NamedLayerImageParameter, Option<usize>),
801    LayerLayout(NamedLayerLayoutParameter, f32),
802    LayerAnchor(NamedLayerAnchorParameter, Option<usize>),
803    Layout(NamedLayoutParameter, f32),
804    Name(Box<str>, Box<str>),
805    CustomColor(NamedParameter<Box<str>>, Color),
806    CustomFloat(NamedParameter<Box<str>>, f32),
807}
808
809impl Setter {
810    pub fn change(self) -> Change {
811        match self {
812            Self::Color(parameter, value) => Change::Color(parameter, Some(value)),
813            Self::Timing(parameter, value) => Change::Timing(parameter, Some(value)),
814            Self::ObjectImage(parameter, value) => Change::ObjectImage(parameter, Some(value)),
815            Self::ObjectAnchor(parameter, value) => Change::ObjectAnchor(parameter, Some(value)),
816            Self::ObjectScale(parameter, value) => Change::ObjectScale(parameter, Some(value)),
817            Self::LayerImage(parameter, value) => Change::LayerImage(parameter, Some(value)),
818            Self::LayerLayout(parameter, value) => Change::LayerLayout(parameter, Some(value)),
819            Self::LayerAnchor(parameter, value) => Change::LayerAnchor(parameter, Some(value)),
820            Self::Layout(parameter, value) => Change::Layout(parameter, Some(value)),
821            Self::Name(parameter, value) => Change::Name(parameter, Some(value)),
822            Self::CustomColor(parameter, value) => Change::CustomColor(parameter, Some(value)),
823            Self::CustomFloat(parameter, value) => Change::CustomFloat(parameter, Some(value)),
824        }
825    }
826}
827
828pub enum Change {
829    Color(NamedColorParameter, Option<Color>),
830    Timing(NamedTimingParameter, Option<f32>),
831    ObjectImage(NamedObjectImageParameter, Option<Option<Box<str>>>),
832    ObjectAnchor(NamedObjectAnchorParameter, Option<[f32; 2]>),
833    ObjectScale(NamedObjectScaleParameter, Option<f32>),
834    LayerImage(NamedLayerImageParameter, Option<Option<usize>>),
835    LayerLayout(NamedLayerLayoutParameter, Option<f32>),
836    LayerAnchor(NamedLayerAnchorParameter, Option<Option<usize>>),
837    Layout(NamedLayoutParameter, Option<f32>),
838    Name(Box<str>, Option<Box<str>>),
839    CustomColor(NamedParameter<Box<str>>, Option<Color>),
840    CustomFloat(NamedParameter<Box<str>>, Option<f32>),
841}
842
843impl Change {
844    pub fn parameter(&self) -> Parameter {
845        match self {
846            Self::Color(parameter, _) => Parameter::Color(parameter.clone()),
847            Self::Timing(parameter, _) => Parameter::Timing(parameter.clone()),
848            Self::ObjectImage(parameter, _) => Parameter::ObjectImage(parameter.clone()),
849            Self::ObjectAnchor(parameter, _) => Parameter::ObjectAnchor(parameter.clone()),
850            Self::ObjectScale(parameter, _) => Parameter::ObjectScale(parameter.clone()),
851            Self::LayerImage(parameter, _) => Parameter::LayerImage(parameter.clone()),
852            Self::LayerLayout(parameter, _) => Parameter::LayerLayout(parameter.clone()),
853            Self::LayerAnchor(parameter, _) => Parameter::LayerAnchor(parameter.clone()),
854            Self::Layout(parameter, _) => Parameter::Layout(parameter.clone()),
855            Self::Name(parameter, _) => Parameter::Name(parameter.clone()),
856            Self::CustomColor(parameter, _) => Parameter::CustomColor(parameter.clone()),
857            Self::CustomFloat(parameter, _) => Parameter::CustomFloat(parameter.clone()),
858        }
859    }
860}
861
862impl DialogChange for Change {
863    type Parameter = Parameter;
864
865    fn default_change(parameter: Parameter) -> Self {
866        match parameter {
867            Parameter::Color(parameter) => Self::Color(parameter, None),
868            Parameter::Timing(parameter) => Self::Timing(parameter, None),
869            Parameter::ObjectImage(parameter) => Self::ObjectImage(parameter, None),
870            Parameter::ObjectAnchor(parameter) => Self::ObjectAnchor(parameter, None),
871            Parameter::ObjectScale(parameter) => Self::ObjectScale(parameter, None),
872            Parameter::LayerImage(parameter) => Self::LayerImage(parameter, None),
873            Parameter::LayerLayout(parameter) => Self::LayerLayout(parameter, None),
874            Parameter::LayerAnchor(parameter) => Self::LayerAnchor(parameter, None),
875            Parameter::Layout(parameter) => Self::Layout(parameter, None),
876            Parameter::Name(parameter) => Self::Name(parameter, None),
877            Parameter::CustomColor(parameter) => Self::CustomColor(parameter, None),
878            Parameter::CustomFloat(parameter) => Self::CustomFloat(parameter, None),
879        }
880    }
881
882    fn value_change(parameter: Parameter, value: &str, context: &mut SettingsContext) -> Self {
883        parameter.value_setter(value, context).change()
884    }
885}
886
887impl PlayerSettings {
888    pub fn revert(&mut self, parameter: &Parameter) {
889        use Parameter::*;
890        match parameter {
891            Color(parameter) => self
892                .colors
893                .get_mut(&parameter.parameter)
894                .set_scene(parameter.name.as_deref(), None),
895            Timing(parameter) => self
896                .timing
897                .get_mut(&parameter.parameter)
898                .set_scene(parameter.name.as_deref(), None),
899            ObjectImage(parameter) => self
900                .objects
901                .get_mut(&parameter.parameter)
902                .set_scene(parameter.name.as_deref(), None),
903            ObjectAnchor(parameter) => self
904                .objects
905                .get_mut(&parameter.parameter)
906                .set_scene(parameter.name.as_deref(), None),
907            ObjectScale(parameter) => self
908                .objects
909                .get_mut(&parameter.parameter)
910                .set_scene(parameter.name.as_deref(), None),
911            LayerImage(parameter) => self
912                .layers
913                .get_mut(&parameter.parameter)
914                .set_scene(parameter.name.as_deref(), None),
915            LayerLayout(parameter) => self
916                .layers
917                .get_mut(&parameter.parameter)
918                .set_scene(parameter.name.as_deref(), None),
919            LayerAnchor(parameter) => self
920                .layers
921                .get_mut(&parameter.parameter)
922                .set_scene(parameter.name.as_deref(), None),
923            Layout(parameter) => self
924                .layout
925                .get_mut(&parameter.parameter)
926                .set_scene(parameter.name.as_deref(), None),
927            Name(parameter) => {
928                self.names.scene.remove(parameter);
929            }
930            CustomColor(parameter) => {
931                if let Some(override_value) = self.custom_colors.get_mut(&parameter.parameter) {
932                    override_value.set_scene(parameter.name.as_deref(), None);
933                }
934            }
935            CustomFloat(parameter) => {
936                if let Some(override_value) = self.custom_floats.get_mut(&parameter.parameter) {
937                    override_value.set_scene(parameter.name.as_deref(), None);
938                }
939            }
940        }
941    }
942
943    pub fn change(&mut self, change: &Change) {
944        use Change::*;
945        match change {
946            Color(parameter, value) => self
947                .colors
948                .get_mut(&parameter.parameter)
949                .set_scene(parameter.name.as_deref(), *value),
950            Timing(parameter, value) => self
951                .timing
952                .get_mut(&parameter.parameter)
953                .set_scene(parameter.name.as_deref(), *value),
954            ObjectImage(parameter, value) => self
955                .objects
956                .get_mut(&parameter.parameter)
957                .set_scene(parameter.name.as_deref(), value.clone()),
958            ObjectScale(parameter, value) => self
959                .objects
960                .get_mut(&parameter.parameter)
961                .set_scene(parameter.name.as_deref(), *value),
962            ObjectAnchor(parameter, value) => self
963                .objects
964                .get_mut(&parameter.parameter)
965                .set_scene(parameter.name.as_deref(), *value),
966            LayerImage(parameter, value) => self
967                .layers
968                .get_mut(&parameter.parameter)
969                .set_scene(parameter.name.as_deref(), *value),
970            LayerLayout(parameter, value) => self
971                .layers
972                .get_mut(&parameter.parameter)
973                .set_scene(parameter.name.as_deref(), *value),
974            LayerAnchor(parameter, value) => self
975                .layers
976                .get_mut(&parameter.parameter)
977                .set_scene(parameter.name.as_deref(), *value),
978            Layout(parameter, value) => self
979                .layout
980                .get_mut(&parameter.parameter)
981                .set_scene(parameter.name.as_deref(), *value),
982            Name(parameter, value) => {
983                if let Some(value) = value {
984                    self.names.scene.insert(parameter.clone(), value.clone());
985                } else {
986                    self.names.scene.remove(parameter);
987                }
988            }
989            CustomColor(parameter, value) => self
990                .custom_colors
991                .entry(parameter.parameter.clone())
992                .or_default()
993                .set_scene(parameter.name.as_deref(), *value),
994            CustomFloat(parameter, value) => self
995                .custom_floats
996                .entry(parameter.parameter.clone())
997                .or_default()
998                .set_scene(parameter.name.as_deref(), *value),
999        }
1000    }
1001
1002    pub fn set_character_default(&mut self, change: Setter) {
1003        use Setter::*;
1004        match change {
1005            Color(parameter, value) => self
1006                .colors
1007                .get_mut(&parameter.parameter)
1008                .set_default(parameter.name, value),
1009            Timing(parameter, value) => self
1010                .timing
1011                .get_mut(&parameter.parameter)
1012                .set_default(parameter.name, value),
1013            ObjectImage(parameter, value) => self
1014                .objects
1015                .get_mut(&parameter.parameter)
1016                .set_default(parameter.name, value),
1017            ObjectAnchor(parameter, value) => self
1018                .objects
1019                .get_mut(&parameter.parameter)
1020                .set_default(parameter.name, value),
1021            ObjectScale(parameter, value) => self
1022                .objects
1023                .get_mut(&parameter.parameter)
1024                .set_default(parameter.name, value),
1025            LayerImage(parameter, value) => self
1026                .layers
1027                .get_mut(&parameter.parameter)
1028                .set_default(parameter.name, value),
1029            LayerLayout(parameter, value) => self
1030                .layers
1031                .get_mut(&parameter.parameter)
1032                .set_default(parameter.name, value),
1033            LayerAnchor(parameter, value) => self
1034                .layers
1035                .get_mut(&parameter.parameter)
1036                .set_default(parameter.name, value),
1037            Layout(parameter, value) => self
1038                .layout
1039                .get_mut(&parameter.parameter)
1040                .set_default(parameter.name, value),
1041            Name(parameter, value) => {
1042                self.names.default.insert(parameter, value);
1043            }
1044            CustomColor(parameter, value) => self
1045                .custom_colors
1046                .entry(parameter.parameter.clone())
1047                .or_default()
1048                .set_default(parameter.name, value),
1049            CustomFloat(parameter, value) => self
1050                .custom_floats
1051                .entry(parameter.parameter.clone())
1052                .or_default()
1053                .set_default(parameter.name, value),
1054        }
1055    }
1056
1057    pub fn custom_color(&self, name: &str, character: &str) -> Option<Color> {
1058        self.custom_colors.get(name).map(|o| o.get(character))
1059    }
1060
1061    pub fn custom_float(&self, name: &str, character: &str) -> Option<f32> {
1062        self.custom_floats.get(name).map(|o| o.get(character))
1063    }
1064}