oxihuman_export/
key_driver_export.rs1#![allow(dead_code)]
4
5#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct DriverCurve {
11 pub input_min: f32,
12 pub input_max: f32,
13 pub output_min: f32,
14 pub output_max: f32,
15 pub clamp_output: bool,
16}
17
18impl Default for DriverCurve {
19 fn default() -> Self {
20 Self {
21 input_min: 0.0,
22 input_max: 1.0,
23 output_min: 0.0,
24 output_max: 1.0,
25 clamp_output: true,
26 }
27 }
28}
29
30#[allow(dead_code)]
32#[derive(Debug, Clone)]
33pub struct KeyDriver {
34 pub name: String,
35 pub source_bone: String,
36 pub source_property: String,
37 pub target_shape: String,
38 pub curve: DriverCurve,
39}
40
41#[allow(dead_code)]
43#[derive(Debug, Clone, Default)]
44pub struct KeyDriverExport {
45 pub drivers: Vec<KeyDriver>,
46}
47
48#[allow(dead_code)]
50pub fn new_key_driver_export() -> KeyDriverExport {
51 KeyDriverExport::default()
52}
53
54#[allow(dead_code)]
56pub fn add_driver(export: &mut KeyDriverExport, driver: KeyDriver) {
57 export.drivers.push(driver);
58}
59
60#[allow(dead_code)]
62pub fn evaluate_curve(curve: &DriverCurve, input: f32) -> f32 {
63 let range_in = curve.input_max - curve.input_min;
64 let t = if range_in.abs() < 1e-8 {
65 0.0
66 } else {
67 (input - curve.input_min) / range_in
68 };
69 let out = curve.output_min + t * (curve.output_max - curve.output_min);
70 if curve.clamp_output {
71 out.clamp(
72 curve.output_min.min(curve.output_max),
73 curve.output_min.max(curve.output_max),
74 )
75 } else {
76 out
77 }
78}
79
80#[allow(dead_code)]
82pub fn evaluate_driver(export: &KeyDriverExport, name: &str, input: f32) -> Option<f32> {
83 export
84 .drivers
85 .iter()
86 .find(|d| d.name == name)
87 .map(|d| evaluate_curve(&d.curve, input))
88}
89
90#[allow(dead_code)]
92pub fn drivers_for_shape<'a>(export: &'a KeyDriverExport, shape: &str) -> Vec<&'a KeyDriver> {
93 export
94 .drivers
95 .iter()
96 .filter(|d| d.target_shape == shape)
97 .collect()
98}
99
100#[allow(dead_code)]
102pub fn driver_count(export: &KeyDriverExport) -> usize {
103 export.drivers.len()
104}
105
106#[allow(dead_code)]
108pub fn serialise_curve(curve: &DriverCurve) -> Vec<f32> {
109 vec![
110 curve.input_min,
111 curve.input_max,
112 curve.output_min,
113 curve.output_max,
114 ]
115}
116
117#[allow(dead_code)]
119pub fn names_unique(export: &KeyDriverExport) -> bool {
120 let mut seen = std::collections::HashSet::new();
121 export.drivers.iter().all(|d| seen.insert(d.name.clone()))
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 fn sample_driver(name: &str, shape: &str) -> KeyDriver {
129 KeyDriver {
130 name: name.to_string(),
131 source_bone: "arm".to_string(),
132 source_property: "rotation_x".to_string(),
133 target_shape: shape.to_string(),
134 curve: DriverCurve::default(),
135 }
136 }
137
138 #[test]
139 fn test_evaluate_curve_midpoint() {
140 let c = DriverCurve::default();
141 assert!((evaluate_curve(&c, 0.5) - 0.5).abs() < 1e-6);
142 }
143
144 #[test]
145 fn test_evaluate_curve_min() {
146 let c = DriverCurve::default();
147 assert!((evaluate_curve(&c, 0.0) - 0.0).abs() < 1e-6);
148 }
149
150 #[test]
151 fn test_evaluate_curve_max() {
152 let c = DriverCurve::default();
153 assert!((evaluate_curve(&c, 1.0) - 1.0).abs() < 1e-6);
154 }
155
156 #[test]
157 fn test_evaluate_curve_clamp() {
158 let c = DriverCurve::default();
159 let out = evaluate_curve(&c, 2.0);
160 assert!((0.0..=1.0).contains(&out));
161 }
162
163 #[test]
164 fn test_add_driver() {
165 let mut e = new_key_driver_export();
166 add_driver(&mut e, sample_driver("d1", "smile"));
167 assert_eq!(driver_count(&e), 1);
168 }
169
170 #[test]
171 fn test_evaluate_driver_found() {
172 let mut e = new_key_driver_export();
173 add_driver(&mut e, sample_driver("brow_up", "brow"));
174 let v = evaluate_driver(&e, "brow_up", 0.5);
175 assert!(v.is_some());
176 }
177
178 #[test]
179 fn test_evaluate_driver_not_found() {
180 let e = new_key_driver_export();
181 assert!(evaluate_driver(&e, "missing", 0.5).is_none());
182 }
183
184 #[test]
185 fn test_drivers_for_shape() {
186 let mut e = new_key_driver_export();
187 add_driver(&mut e, sample_driver("d1", "smile"));
188 add_driver(&mut e, sample_driver("d2", "frown"));
189 let r = drivers_for_shape(&e, "smile");
190 assert_eq!(r.len(), 1);
191 }
192
193 #[test]
194 fn test_serialise_curve_length() {
195 assert_eq!(serialise_curve(&DriverCurve::default()).len(), 4);
196 }
197
198 #[test]
199 fn test_names_unique() {
200 let mut e = new_key_driver_export();
201 add_driver(&mut e, sample_driver("d1", "s"));
202 add_driver(&mut e, sample_driver("d2", "s"));
203 assert!(names_unique(&e));
204 }
205}