oxihuman_morph/
proximity_pin.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct ProximityPin {
10 pub vertex_index: usize,
11 pub target_position: [f32; 3],
12 pub influence: f32,
13 pub enabled: bool,
14}
15
16impl ProximityPin {
17 pub fn new(vertex_index: usize, target: [f32; 3]) -> Self {
18 ProximityPin {
19 vertex_index,
20 target_position: target,
21 influence: 1.0,
22 enabled: true,
23 }
24 }
25}
26
27#[derive(Debug, Clone, Default)]
29pub struct ProximityPinSet {
30 pub pins: Vec<ProximityPin>,
31}
32
33pub fn new_pin_set() -> ProximityPinSet {
35 ProximityPinSet::default()
36}
37
38pub fn pin_add(set: &mut ProximityPinSet, vertex_index: usize, target: [f32; 3]) {
40 set.pins.push(ProximityPin::new(vertex_index, target));
41}
42
43pub fn pin_remove(set: &mut ProximityPinSet, pin_index: usize) {
45 if pin_index < set.pins.len() {
46 set.pins.remove(pin_index);
47 }
48}
49
50pub fn pin_set_influence(set: &mut ProximityPinSet, pin_index: usize, influence: f32) {
52 if pin_index < set.pins.len() {
53 set.pins[pin_index].influence = influence.clamp(0.0, 1.0);
54 }
55}
56
57pub fn pin_set_enabled(set: &mut ProximityPinSet, pin_index: usize, enabled: bool) {
59 if pin_index < set.pins.len() {
60 set.pins[pin_index].enabled = enabled;
61 }
62}
63
64pub fn pin_count(set: &ProximityPinSet) -> usize {
66 set.pins.len()
67}
68
69pub fn pin_enabled_count(set: &ProximityPinSet) -> usize {
71 set.pins.iter().filter(|p| p.enabled).count()
72}
73
74pub fn pin_set_to_json(set: &ProximityPinSet) -> String {
76 format!(
77 r#"{{"pins":{},"enabled":{}}}"#,
78 set.pins.len(),
79 set.pins.iter().filter(|p| p.enabled).count()
80 )
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_new_pin_set_empty() {
89 let s = new_pin_set();
90 assert_eq!(pin_count(&s), 0 ,);
91 }
92
93 #[test]
94 fn test_add_pin_increases_count() {
95 let mut s = new_pin_set();
96 pin_add(&mut s, 0, [0.0, 1.0, 0.0]);
97 assert_eq!(pin_count(&s), 1 ,);
98 }
99
100 #[test]
101 fn test_remove_pin_decreases_count() {
102 let mut s = new_pin_set();
103 pin_add(&mut s, 0, [0.0; 3]);
104 pin_remove(&mut s, 0);
105 assert_eq!(
106 pin_count(&s),
107 0, );
109 }
110
111 #[test]
112 fn test_pin_enabled_by_default() {
113 let mut s = new_pin_set();
114 pin_add(&mut s, 0, [0.0; 3]);
115 assert!(s.pins[0].enabled ,);
116 }
117
118 #[test]
119 fn test_set_enabled_false() {
120 let mut s = new_pin_set();
121 pin_add(&mut s, 0, [0.0; 3]);
122 pin_set_enabled(&mut s, 0, false);
123 assert!(!s.pins[0].enabled ,);
124 }
125
126 #[test]
127 fn test_enabled_count() {
128 let mut s = new_pin_set();
129 pin_add(&mut s, 0, [0.0; 3]);
130 pin_add(&mut s, 1, [1.0, 0.0, 0.0]);
131 pin_set_enabled(&mut s, 0, false);
132 assert_eq!(
133 pin_enabled_count(&s),
134 1, );
136 }
137
138 #[test]
139 fn test_set_influence_clamps() {
140 let mut s = new_pin_set();
141 pin_add(&mut s, 0, [0.0; 3]);
142 pin_set_influence(&mut s, 0, 3.0);
143 assert!((s.pins[0].influence - 1.0).abs() < 1e-5, );
144 }
145
146 #[test]
147 fn test_to_json_contains_pins() {
148 let s = new_pin_set();
149 let j = pin_set_to_json(&s);
150 assert!(j.contains("pins") ,);
151 }
152
153 #[test]
154 fn test_remove_out_of_bounds_ignored() {
155 let mut s = new_pin_set();
156 pin_remove(&mut s, 99);
157 assert_eq!(pin_count(&s), 0 ,);
158 }
159
160 #[test]
161 fn test_vertex_index_stored() {
162 let mut s = new_pin_set();
163 pin_add(&mut s, 42, [0.0; 3]);
164 assert_eq!(
165 s.pins[0].vertex_index,
166 42, );
168 }
169}