#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MuscleGroup {
Arms,
Shoulders,
Chest,
Abdomen,
Back,
Legs,
Glutes,
Neck,
}
#[derive(Debug, Clone)]
pub struct MuscleToneMorph {
pub global_tone: f32,
pub group_overrides: Vec<(MuscleGroup, f32)>,
pub definition: f32,
pub morph_count: usize,
pub enabled: bool,
}
impl MuscleToneMorph {
pub fn new(morph_count: usize) -> Self {
MuscleToneMorph {
global_tone: 0.5,
group_overrides: Vec::new(),
definition: 0.5,
morph_count,
enabled: true,
}
}
}
pub fn new_muscle_tone_morph(morph_count: usize) -> MuscleToneMorph {
MuscleToneMorph::new(morph_count)
}
pub fn mtm_set_tone(morph: &mut MuscleToneMorph, tone: f32) {
morph.global_tone = tone.clamp(0.0, 1.0);
}
pub fn mtm_set_definition(morph: &mut MuscleToneMorph, definition: f32) {
morph.definition = definition.clamp(0.0, 1.0);
}
pub fn mtm_set_group_override(morph: &mut MuscleToneMorph, group: MuscleGroup, tone: f32) {
let clamped = tone.clamp(0.0, 1.0);
if let Some(entry) = morph.group_overrides.iter_mut().find(|(g, _)| *g == group) {
entry.1 = clamped;
} else {
morph.group_overrides.push((group, clamped));
}
}
pub fn mtm_evaluate(morph: &MuscleToneMorph) -> Vec<f32> {
if !morph.enabled || morph.morph_count == 0 {
return vec![];
}
let w = morph.global_tone * morph.definition;
vec![w; morph.morph_count]
}
pub fn mtm_set_enabled(morph: &mut MuscleToneMorph, enabled: bool) {
morph.enabled = enabled;
}
pub fn mtm_override_count(morph: &MuscleToneMorph) -> usize {
morph.group_overrides.len()
}
pub fn mtm_to_json(morph: &MuscleToneMorph) -> String {
format!(
r#"{{"global_tone":{},"definition":{},"morph_count":{},"enabled":{}}}"#,
morph.global_tone, morph.definition, morph.morph_count, morph.enabled
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_tone() {
let m = new_muscle_tone_morph(8);
assert!((m.global_tone - 0.5).abs() < 1e-6 );
}
#[test]
fn test_set_tone_clamps() {
let mut m = new_muscle_tone_morph(4);
mtm_set_tone(&mut m, 1.5);
assert!((m.global_tone - 1.0).abs() < 1e-6 );
}
#[test]
fn test_set_definition() {
let mut m = new_muscle_tone_morph(4);
mtm_set_definition(&mut m, 0.8);
assert!((m.definition - 0.8).abs() < 1e-5 );
}
#[test]
fn test_group_override_added() {
let mut m = new_muscle_tone_morph(4);
mtm_set_group_override(&mut m, MuscleGroup::Arms, 0.9);
assert_eq!(
mtm_override_count(&m),
1
);
}
#[test]
fn test_group_override_updated() {
let mut m = new_muscle_tone_morph(4);
mtm_set_group_override(&mut m, MuscleGroup::Arms, 0.5);
mtm_set_group_override(&mut m, MuscleGroup::Arms, 0.9);
assert_eq!(
mtm_override_count(&m),
1
);
}
#[test]
fn test_evaluate_length() {
let m = new_muscle_tone_morph(5);
let out = mtm_evaluate(&m);
assert_eq!(out.len(), 5 );
}
#[test]
fn test_evaluate_disabled() {
let mut m = new_muscle_tone_morph(4);
mtm_set_enabled(&mut m, false);
assert!(mtm_evaluate(&m).is_empty() );
}
#[test]
fn test_to_json_has_fields() {
let m = new_muscle_tone_morph(4);
let j = mtm_to_json(&m);
assert!(j.contains("\"global_tone\"") );
}
#[test]
fn test_enabled_default() {
let m = new_muscle_tone_morph(4);
assert!(m.enabled );
}
#[test]
fn test_evaluate_product() {
let mut m = new_muscle_tone_morph(2);
mtm_set_tone(&mut m, 0.4);
mtm_set_definition(&mut m, 0.5);
let out = mtm_evaluate(&m);
assert!((out[0] - 0.2).abs() < 1e-5 );
}
}