fyrox_animation/machine/
parameter.rs1use crate::core::{algebra::Vector2, reflect::prelude::*, visitor::prelude::*};
24use fxhash::FxHashMap;
25use fyrox_core::uuid_provider;
26use std::{
27 cell::{Cell, RefCell},
28 ops::{Deref, DerefMut},
29};
30use strum_macros::{AsRefStr, EnumString, VariantNames};
31
32#[derive(Copy, Clone, Debug, PartialEq, Reflect, Visit, VariantNames, EnumString, AsRefStr)]
36pub enum Parameter {
37 Weight(f32),
39
40 Rule(bool),
42
43 Index(u32),
45
46 SamplingPoint(Vector2<f32>),
48}
49
50uuid_provider!(Parameter = "ace1b8ea-15ee-444d-97be-1682cd9e4245");
51
52impl Default for Parameter {
53 fn default() -> Self {
54 Self::Weight(0.0)
55 }
56}
57
58#[derive(Debug, Visit, Clone, PartialEq, Reflect, VariantNames, EnumString, AsRefStr)]
60pub enum PoseWeight {
61 Constant(f32),
63
64 Parameter(String),
66}
67
68uuid_provider!(PoseWeight = "46af44ea-eae9-4f3e-803c-06306caed23f");
69
70impl PoseWeight {
71 pub fn value(&self, params: &ParameterContainer) -> Option<f32> {
73 match self {
74 PoseWeight::Constant(val) => Some(*val),
75 PoseWeight::Parameter(name) => params.get(name).and_then(|p| {
76 if let Parameter::Weight(weight) = p {
77 Some(*weight)
78 } else {
79 None
80 }
81 }),
82 }
83 }
84}
85
86impl Default for PoseWeight {
87 fn default() -> Self {
88 Self::Constant(0.0)
89 }
90}
91
92#[derive(Reflect, Visit, Default, Debug, Clone, PartialEq)]
94pub struct ParameterDefinition {
95 pub name: String,
97
98 pub value: Parameter,
100}
101
102uuid_provider!(ParameterDefinition = "6cbba5c9-8daf-4f4c-a920-9716ed233d89");
103
104#[derive(Default, Debug, Clone)]
105struct Wrapper {
106 parameters: Vec<ParameterDefinition>,
107 dirty: Cell<bool>,
108}
109
110impl PartialEq for Wrapper {
111 fn eq(&self, other: &Self) -> bool {
112 self.parameters == other.parameters
113 }
114}
115
116impl Visit for Wrapper {
117 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
118 self.parameters.visit(name, visitor)
119 }
120}
121
122impl Deref for Wrapper {
123 type Target = Vec<ParameterDefinition>;
124
125 fn deref(&self) -> &Self::Target {
126 &self.parameters
127 }
128}
129
130impl DerefMut for Wrapper {
131 fn deref_mut(&mut self) -> &mut Self::Target {
132 self.dirty.set(true);
133 &mut self.parameters
134 }
135}
136
137#[derive(Reflect, Visit, Default, Debug)]
139pub struct ParameterContainer {
140 #[reflect(deref)]
141 parameters: Wrapper,
142
143 #[reflect(hidden)]
144 #[visit(skip)]
145 lookup: RefCell<FxHashMap<String, usize>>,
146}
147
148impl PartialEq for ParameterContainer {
149 fn eq(&self, other: &Self) -> bool {
150 self.parameters == other.parameters
151 }
152}
153
154impl Clone for ParameterContainer {
155 fn clone(&self) -> Self {
156 Self {
157 parameters: self.parameters.clone(),
158 lookup: RefCell::new(self.lookup.borrow().clone()),
159 }
160 }
161}
162
163impl ParameterContainer {
164 fn update_index(&self) {
165 if self.parameters.dirty.get() {
166 *self.lookup.borrow_mut() = self
167 .parameters
168 .parameters
169 .iter()
170 .enumerate()
171 .map(|(i, p)| (p.name.clone(), i))
172 .collect();
173 self.parameters.dirty.set(false);
174 }
175 }
176
177 pub fn add(&mut self, name: &str, value: Parameter) {
179 self.parameters.push(ParameterDefinition {
180 name: name.to_string(),
181 value,
182 })
183 }
184
185 pub fn get(&self, name: &str) -> Option<&Parameter> {
187 self.update_index();
188 self.lookup
189 .borrow()
190 .get(name)
191 .and_then(|i| self.parameters.parameters.get(*i).map(|d| &d.value))
192 }
193
194 pub fn get_mut(&mut self, name: &str) -> Option<&mut Parameter> {
196 self.update_index();
197 self.lookup
198 .borrow()
199 .get(name)
200 .and_then(|i| self.parameters.parameters.get_mut(*i).map(|d| &mut d.value))
201 }
202}