#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PiercingLocation {
EarLobe,
Nostril,
Septum,
Eyebrow,
Lip,
Navel,
Other,
}
#[derive(Debug, Clone)]
pub struct PiercingEntry {
pub id: u32,
pub location: PiercingLocation,
pub gauge: f32,
pub deform_radius: f32,
}
#[derive(Debug, Clone)]
pub struct PiercingDeform {
pub piercings: Vec<PiercingEntry>,
pub morph_count: usize,
pub enabled: bool,
}
impl PiercingDeform {
pub fn new(morph_count: usize) -> Self {
PiercingDeform {
piercings: Vec::new(),
morph_count,
enabled: true,
}
}
}
pub fn new_piercing_deform(morph_count: usize) -> PiercingDeform {
PiercingDeform::new(morph_count)
}
pub fn pd_add_piercing(ctrl: &mut PiercingDeform, entry: PiercingEntry) {
ctrl.piercings.push(entry);
}
pub fn pd_remove_piercing(ctrl: &mut PiercingDeform, id: u32) {
ctrl.piercings.retain(|p| p.id != id);
}
pub fn pd_evaluate(ctrl: &PiercingDeform) -> Vec<f32> {
if !ctrl.enabled || ctrl.morph_count == 0 {
return vec![];
}
let w: f32 = ctrl
.piercings
.iter()
.map(|p| p.deform_radius)
.sum::<f32>()
.min(1.0);
vec![w; ctrl.morph_count]
}
pub fn pd_set_enabled(ctrl: &mut PiercingDeform, enabled: bool) {
ctrl.enabled = enabled;
}
pub fn pd_piercing_count(ctrl: &PiercingDeform) -> usize {
ctrl.piercings.len()
}
pub fn pd_to_json(ctrl: &PiercingDeform) -> String {
format!(
r#"{{"piercing_count":{},"morph_count":{},"enabled":{}}}"#,
ctrl.piercings.len(),
ctrl.morph_count,
ctrl.enabled
)
}
#[cfg(test)]
mod tests {
use super::*;
fn make_piercing(id: u32) -> PiercingEntry {
PiercingEntry {
id,
location: PiercingLocation::EarLobe,
gauge: 1.0,
deform_radius: 0.1,
}
}
#[test]
fn test_initial_empty() {
let c = new_piercing_deform(4);
assert_eq!(pd_piercing_count(&c), 0 );
}
#[test]
fn test_add_piercing() {
let mut c = new_piercing_deform(4);
pd_add_piercing(&mut c, make_piercing(1));
assert_eq!(pd_piercing_count(&c), 1 );
}
#[test]
fn test_remove_piercing() {
let mut c = new_piercing_deform(4);
pd_add_piercing(&mut c, make_piercing(1));
pd_remove_piercing(&mut c, 1);
assert_eq!(pd_piercing_count(&c), 0 );
}
#[test]
fn test_evaluate_length() {
let c = new_piercing_deform(6);
assert_eq!(
pd_evaluate(&c).len(),
6
);
}
#[test]
fn test_evaluate_disabled() {
let mut c = new_piercing_deform(4);
pd_set_enabled(&mut c, false);
assert!(pd_evaluate(&c).is_empty() );
}
#[test]
fn test_evaluate_capped() {
let mut c = new_piercing_deform(2);
for i in 0..20 {
pd_add_piercing(
&mut c,
PiercingEntry {
id: i,
location: PiercingLocation::Other,
gauge: 1.0,
deform_radius: 0.2,
},
);
}
let out = pd_evaluate(&c);
assert!(out[0] <= 1.0 );
}
#[test]
fn test_to_json_has_count() {
let c = new_piercing_deform(4);
let j = pd_to_json(&c);
assert!(j.contains("\"piercing_count\"") );
}
#[test]
fn test_enabled_default() {
let c = new_piercing_deform(4);
assert!(c.enabled );
}
#[test]
fn test_remove_nonexistent_is_noop() {
let mut c = new_piercing_deform(4);
pd_remove_piercing(&mut c, 999);
assert_eq!(
pd_piercing_count(&c),
0
);
}
}