1use std::collections::BTreeMap;
2
3use pfx_load::scene::{Target, Value};
4
5use crate::tunables::TunableValue;
6
7#[derive(Clone, Debug, PartialEq)]
8pub enum Edit {
9 Scene {
10 target: Target,
11 path: Vec<String>,
12 value: Value,
13 },
14 Tunable {
15 name: String,
16 value: TunableValue,
17 },
18}
19
20impl Edit {
21 pub fn scene(target: Target, path: &[&str], value: impl Into<Value>) -> Edit {
22 Edit::Scene {
23 target,
24 path: path.iter().map(|key| key.to_string()).collect(),
25 value: value.into(),
26 }
27 }
28
29 pub fn tunable(name: &str, value: TunableValue) -> Edit {
30 Edit::Tunable {
31 name: name.to_string(),
32 value,
33 }
34 }
35
36 pub fn key(&self) -> String {
37 match self {
38 Edit::Scene { target, path, .. } => format!("{target} {}", path.join(".")),
39 Edit::Tunable { name, .. } => format!("tunable {name}"),
40 }
41 }
42}
43
44#[derive(Clone, Debug, PartialEq)]
45pub struct Stamped {
46 pub tick: u64,
47 pub edit: Edit,
48}
49
50#[derive(Clone, Debug, Default, PartialEq)]
51pub struct Pending {
52 edits: BTreeMap<String, Edit>,
53}
54
55impl Pending {
56 pub(crate) fn hold(&mut self, edit: Edit) {
57 self.edits.insert(edit.key(), edit);
58 }
59
60 pub fn is_empty(&self) -> bool {
61 self.edits.is_empty()
62 }
63
64 pub fn len(&self) -> usize {
65 self.edits.len()
66 }
67
68 pub fn get(&self, key: &str) -> Option<&Edit> {
69 self.edits.get(key)
70 }
71
72 pub fn contains(&self, key: &str) -> bool {
73 self.edits.contains_key(key)
74 }
75
76 pub fn iter(&self) -> impl Iterator<Item = &Edit> {
77 self.edits.values()
78 }
79
80 pub fn scene(&self) -> impl Iterator<Item = (&Target, &[String], &Value)> {
81 self.edits.values().filter_map(|edit| match edit {
82 Edit::Scene {
83 target,
84 path,
85 value,
86 } => Some((target, path.as_slice(), value)),
87 Edit::Tunable { .. } => None,
88 })
89 }
90
91 pub fn tunables(&self) -> impl Iterator<Item = (&str, TunableValue)> {
92 self.edits.values().filter_map(|edit| match edit {
93 Edit::Tunable { name, value } => Some((name.as_str(), *value)),
94 Edit::Scene { .. } => None,
95 })
96 }
97}