oxihuman_morph/
skin_thickness_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum SkinRegion {
10 Face,
11 Scalp,
12 Hands,
13 Feet,
14 Torso,
15 Limbs,
16}
17
18#[derive(Debug, Clone)]
20pub struct SkinThicknessMorph {
21 pub global_thickness: f32,
22 pub region_values: Vec<(SkinRegion, f32)>,
23 pub morph_count: usize,
24 pub enabled: bool,
25}
26
27impl SkinThicknessMorph {
28 pub fn new(morph_count: usize) -> Self {
29 SkinThicknessMorph {
30 global_thickness: 0.5,
31 region_values: Vec::new(),
32 morph_count,
33 enabled: true,
34 }
35 }
36}
37
38pub fn new_skin_thickness_morph(morph_count: usize) -> SkinThicknessMorph {
40 SkinThicknessMorph::new(morph_count)
41}
42
43pub fn stm_set_thickness(morph: &mut SkinThicknessMorph, thickness: f32) {
45 morph.global_thickness = thickness.clamp(0.0, 1.0);
46}
47
48pub fn stm_set_region(morph: &mut SkinThicknessMorph, region: SkinRegion, thickness: f32) {
50 let v = thickness.clamp(0.0, 1.0);
51 if let Some(e) = morph.region_values.iter_mut().find(|(r, _)| *r == region) {
52 e.1 = v;
53 } else {
54 morph.region_values.push((region, v));
55 }
56}
57
58pub fn stm_evaluate(morph: &SkinThicknessMorph) -> Vec<f32> {
60 if !morph.enabled || morph.morph_count == 0 {
62 return vec![];
63 }
64 vec![morph.global_thickness; morph.morph_count]
65}
66
67pub fn stm_set_enabled(morph: &mut SkinThicknessMorph, enabled: bool) {
69 morph.enabled = enabled;
70}
71
72pub fn stm_region_count(morph: &SkinThicknessMorph) -> usize {
74 morph.region_values.len()
75}
76
77pub fn stm_to_json(morph: &SkinThicknessMorph) -> String {
79 format!(
80 r#"{{"global_thickness":{},"morph_count":{},"regions":{},"enabled":{}}}"#,
81 morph.global_thickness,
82 morph.morph_count,
83 morph.region_values.len(),
84 morph.enabled
85 )
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_default_thickness() {
94 let m = new_skin_thickness_morph(4);
95 assert!((m.global_thickness - 0.5).abs() < 1e-6 );
96 }
97
98 #[test]
99 fn test_set_thickness_clamps() {
100 let mut m = new_skin_thickness_morph(4);
101 stm_set_thickness(&mut m, -1.0);
102 assert!((m.global_thickness).abs() < 1e-6 );
103 }
104
105 #[test]
106 fn test_region_added() {
107 let mut m = new_skin_thickness_morph(4);
108 stm_set_region(&mut m, SkinRegion::Face, 0.3);
109 assert_eq!(stm_region_count(&m), 1 );
110 }
111
112 #[test]
113 fn test_region_updated() {
114 let mut m = new_skin_thickness_morph(4);
115 stm_set_region(&mut m, SkinRegion::Hands, 0.2);
116 stm_set_region(&mut m, SkinRegion::Hands, 0.9);
117 assert_eq!(
118 stm_region_count(&m),
119 1 );
121 }
122
123 #[test]
124 fn test_evaluate_length() {
125 let m = new_skin_thickness_morph(7);
126 let out = stm_evaluate(&m);
127 assert_eq!(out.len(), 7 );
128 }
129
130 #[test]
131 fn test_evaluate_disabled() {
132 let mut m = new_skin_thickness_morph(4);
133 stm_set_enabled(&mut m, false);
134 assert!(stm_evaluate(&m).is_empty() );
135 }
136
137 #[test]
138 fn test_to_json_has_global_thickness() {
139 let m = new_skin_thickness_morph(4);
140 let j = stm_to_json(&m);
141 assert!(j.contains("\"global_thickness\"") );
142 }
143
144 #[test]
145 fn test_enabled_default() {
146 let m = new_skin_thickness_morph(4);
147 assert!(m.enabled );
148 }
149
150 #[test]
151 fn test_evaluate_value_matches_thickness() {
152 let mut m = new_skin_thickness_morph(3);
153 stm_set_thickness(&mut m, 0.7);
154 let out = stm_evaluate(&m);
155 assert!((out[0] - 0.7).abs() < 1e-5 );
156 }
157}