oxihuman_morph/
alar_base_control.rs1#![allow(dead_code)]
7
8#[allow(dead_code)]
10#[derive(Debug, Clone)]
11pub struct AlarBaseParams {
12 pub width: f32,
14 pub flare: f32,
16 pub height: f32,
18}
19
20#[allow(dead_code)]
21impl Default for AlarBaseParams {
22 fn default() -> Self {
23 Self {
24 width: 0.5,
25 flare: 0.0,
26 height: 0.0,
27 }
28 }
29}
30
31#[allow(dead_code)]
33#[derive(Debug, Clone)]
34pub struct AlarBaseWeights {
35 pub width_w: f32,
36 pub flare_w: f32,
37 pub height_w: f32,
38}
39
40#[allow(dead_code)]
42pub fn default_alar_base() -> AlarBaseParams {
43 AlarBaseParams::default()
44}
45
46#[allow(dead_code)]
48pub fn evaluate_alar_base(p: &AlarBaseParams) -> AlarBaseWeights {
49 AlarBaseWeights {
50 width_w: p.width.clamp(0.0, 1.0),
51 flare_w: p.flare.clamp(0.0, 1.0),
52 height_w: p.height.clamp(-1.0, 1.0),
53 }
54}
55
56#[allow(dead_code)]
58pub fn blend_alar_base(a: &AlarBaseParams, b: &AlarBaseParams, t: f32) -> AlarBaseParams {
59 let t = t.clamp(0.0, 1.0);
60 AlarBaseParams {
61 width: a.width + (b.width - a.width) * t,
62 flare: a.flare + (b.flare - a.flare) * t,
63 height: a.height + (b.height - a.height) * t,
64 }
65}
66
67#[allow(dead_code)]
69pub fn set_alar_width(p: &mut AlarBaseParams, value: f32) {
70 p.width = value.clamp(0.0, 1.0);
71}
72
73#[allow(dead_code)]
75pub fn set_alar_flare(p: &mut AlarBaseParams, value: f32) {
76 p.flare = value.clamp(0.0, 1.0);
77}
78
79#[allow(dead_code)]
81pub fn is_valid_alar_base(p: &AlarBaseParams) -> bool {
82 (0.0..=1.0).contains(&p.width)
83 && (0.0..=1.0).contains(&p.flare)
84 && (-1.0..=1.0).contains(&p.height)
85}
86
87#[allow(dead_code)]
89pub fn reset_alar_base(p: &mut AlarBaseParams) {
90 *p = AlarBaseParams::default();
91}
92
93#[allow(dead_code)]
95pub fn alar_base_to_json(p: &AlarBaseParams) -> String {
96 format!(
97 r#"{{"width":{:.4},"flare":{:.4},"height":{:.4}}}"#,
98 p.width, p.flare, p.height
99 )
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_default() {
108 let p = AlarBaseParams::default();
109 assert!((p.width - 0.5).abs() < 1e-6);
110 assert!(p.flare.abs() < 1e-6);
111 }
112
113 #[test]
114 fn test_evaluate_clamps() {
115 let p = AlarBaseParams {
116 width: 2.0,
117 flare: -1.0,
118 height: 0.0,
119 };
120 let w = evaluate_alar_base(&p);
121 assert!((w.width_w - 1.0).abs() < 1e-6);
122 assert!(w.flare_w < 1e-6);
123 }
124
125 #[test]
126 fn test_blend_identity() {
127 let a = AlarBaseParams::default();
128 let b = AlarBaseParams::default();
129 let m = blend_alar_base(&a, &b, 0.5);
130 assert!((m.width - 0.5).abs() < 1e-6);
131 }
132
133 #[test]
134 fn test_blend_midpoint() {
135 let a = AlarBaseParams {
136 width: 0.0,
137 flare: 0.0,
138 height: 0.0,
139 };
140 let b = AlarBaseParams {
141 width: 1.0,
142 flare: 1.0,
143 height: 1.0,
144 };
145 let m = blend_alar_base(&a, &b, 0.5);
146 assert!((m.width - 0.5).abs() < 1e-5);
147 }
148
149 #[test]
150 fn test_set_width_clamped() {
151 let mut p = AlarBaseParams::default();
152 set_alar_width(&mut p, -5.0);
153 assert!(p.width < 1e-6);
154 }
155
156 #[test]
157 fn test_set_flare_clamped() {
158 let mut p = AlarBaseParams::default();
159 set_alar_flare(&mut p, 5.0);
160 assert!((p.flare - 1.0).abs() < 1e-6);
161 }
162
163 #[test]
164 fn test_is_valid_default() {
165 assert!(is_valid_alar_base(&AlarBaseParams::default()));
166 }
167
168 #[test]
169 fn test_reset() {
170 let mut p = AlarBaseParams {
171 width: 0.9,
172 flare: 0.8,
173 height: 0.5,
174 };
175 reset_alar_base(&mut p);
176 assert!((p.width - 0.5).abs() < 1e-6);
177 }
178
179 #[test]
180 fn test_to_json_contains_fields() {
181 let j = alar_base_to_json(&AlarBaseParams::default());
182 assert!(j.contains("width"));
183 assert!(j.contains("flare"));
184 }
185}