oxihuman_export/
driver_export.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, PartialEq)]
10pub enum DriverType {
11 Linear,
12 Polynomial,
13 Scripted,
14}
15
16#[derive(Debug, Clone)]
17pub struct DriverExport {
18 pub name: String,
19 pub target_prop: String,
20 pub driver_type: DriverType,
21 pub coefficients: Vec<f32>,
22}
23
24pub fn new_driver_export(name: &str, target_prop: &str, driver_type: DriverType) -> DriverExport {
25 DriverExport {
26 name: name.to_string(),
27 target_prop: target_prop.to_string(),
28 driver_type,
29 coefficients: Vec::new(),
30 }
31}
32
33pub fn driver_evaluate(driver: &DriverExport, input: f32) -> f32 {
34 match driver.driver_type {
35 DriverType::Scripted => 0.0,
36 DriverType::Linear => {
37 let c0 = driver.coefficients.first().copied().unwrap_or(0.0);
38 let c1 = driver.coefficients.get(1).copied().unwrap_or(1.0);
39 c0 + c1 * input
40 }
41 DriverType::Polynomial => driver
42 .coefficients
43 .iter()
44 .enumerate()
45 .fold(0.0f32, |acc, (i, &c)| acc + c * input.powi(i as i32)),
46 }
47}
48
49pub fn driver_add_coefficient(driver: &mut DriverExport, coeff: f32) {
50 driver.coefficients.push(coeff);
51}
52
53pub fn driver_coefficient_count(driver: &DriverExport) -> usize {
54 driver.coefficients.len()
55}
56
57pub fn driver_to_json_legacy(driver: &DriverExport) -> String {
58 format!(
59 "{{\"name\":\"{}\",\"type\":\"{}\",\"coefficients\":{}}}",
60 driver.name,
61 driver_type_name(driver),
62 driver.coefficients.len()
63 )
64}
65
66pub fn driver_validate(driver: &DriverExport) -> bool {
67 !driver.name.is_empty() && !driver.target_prop.is_empty()
68}
69
70pub fn driver_type_name(driver: &DriverExport) -> &'static str {
71 match driver.driver_type {
72 DriverType::Linear => "Linear",
73 DriverType::Polynomial => "Polynomial",
74 DriverType::Scripted => "Scripted",
75 }
76}
77
78#[derive(Debug, Clone)]
82pub struct DriverData {
83 pub name: String,
84 pub expression: String,
85 pub target_prop: String,
86 pub variables: Vec<String>,
87}
88
89pub fn new_driver_data(name: &str, expression: &str, target_prop: &str) -> DriverData {
91 DriverData {
92 name: name.to_string(),
93 expression: expression.to_string(),
94 target_prop: target_prop.to_string(),
95 variables: Vec::new(),
96 }
97}
98
99pub fn driver_push_variable(d: &mut DriverData, var: &str) {
101 d.variables.push(var.to_string());
102}
103
104pub fn driver_to_json(d: &DriverData) -> String {
106 format!(
107 "{{\"name\":\"{}\",\"expression\":\"{}\",\"target\":\"{}\",\"vars\":{}}}",
108 d.name,
109 d.expression,
110 d.target_prop,
111 d.variables.len()
112 )
113}
114
115pub fn driver_variable_count(d: &DriverData) -> usize {
117 d.variables.len()
118}
119
120pub fn driver_has_expression(d: &DriverData) -> bool {
122 !d.expression.is_empty()
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_new_driver_data() {
131 let d = new_driver_data("drv", "x*2", "loc.x");
132 assert_eq!(d.name, "drv");
133 }
134
135 #[test]
136 fn test_driver_push_variable() {
137 let mut d = new_driver_data("d", "e", "p");
138 driver_push_variable(&mut d, "var1");
139 assert_eq!(driver_variable_count(&d), 1);
140 }
141
142 #[test]
143 fn test_driver_to_json() {
144 let d = new_driver_data("d", "x+1", "rot.y");
145 let j = driver_to_json(&d);
146 assert!(j.contains("x+1"));
147 }
148
149 #[test]
150 fn test_driver_has_expression() {
151 let d = new_driver_data("d", "x", "p");
152 assert!(driver_has_expression(&d));
153 }
154
155 #[test]
156 fn test_driver_no_expression() {
157 let d = new_driver_data("d", "", "p");
158 assert!(!driver_has_expression(&d));
159 }
160}