#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ConstraintSlot {
pub id: u32,
pub name: String,
pub constraint_type: String,
pub influence: f32,
pub enabled: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct ConstraintListView {
pub constraints: Vec<ConstraintSlot>,
}
#[allow(dead_code)]
pub fn new_constraint_list_view() -> ConstraintListView {
ConstraintListView::default()
}
#[allow(dead_code)]
pub fn add_constraint_slot(view: &mut ConstraintListView, id: u32, name: &str, type_: &str) {
view.constraints.push(ConstraintSlot {
id,
name: name.to_string(),
constraint_type: type_.to_string(),
influence: 1.0,
enabled: true,
});
}
#[allow(dead_code)]
pub fn set_influence(view: &mut ConstraintListView, id: u32, inf: f32) {
if let Some(slot) = view.constraints.iter_mut().find(|c| c.id == id) {
slot.influence = inf.clamp(0.0, 1.0);
}
}
#[allow(dead_code)]
pub fn toggle_constraint(view: &mut ConstraintListView, id: u32) {
if let Some(slot) = view.constraints.iter_mut().find(|c| c.id == id) {
slot.enabled = !slot.enabled;
}
}
#[allow(dead_code)]
pub fn constraint_count(view: &ConstraintListView) -> usize {
view.constraints.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_view_is_empty() {
let v = new_constraint_list_view();
assert_eq!(constraint_count(&v), 0);
}
#[test]
fn add_constraint_increments_count() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 0, "IK", "INVERSE_KINEMATICS");
assert_eq!(constraint_count(&v), 1);
}
#[test]
fn added_constraint_defaults_enabled() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 0, "CopyLoc", "COPY_LOCATION");
assert!(v.constraints[0].enabled);
}
#[test]
fn added_constraint_influence_one() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 0, "X", "Y");
assert!((v.constraints[0].influence - 1.0).abs() < 1e-6);
}
#[test]
fn set_influence_clamps() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 0, "X", "Y");
set_influence(&mut v, 0, 2.5);
assert!((v.constraints[0].influence - 1.0).abs() < 1e-6);
}
#[test]
fn set_influence_valid() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 0, "X", "Y");
set_influence(&mut v, 0, 0.6);
assert!((v.constraints[0].influence - 0.6).abs() < 1e-6);
}
#[test]
fn toggle_constraint_disables() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 1, "A", "T");
toggle_constraint(&mut v, 1);
assert!(!v.constraints[0].enabled);
}
#[test]
fn toggle_constraint_unknown_id_no_panic() {
let mut v = new_constraint_list_view();
toggle_constraint(&mut v, 99);
}
#[test]
fn constraint_count_multiple() {
let mut v = new_constraint_list_view();
for i in 0..4u32 {
add_constraint_slot(&mut v, i, "c", "t");
}
assert_eq!(constraint_count(&v), 4);
}
#[test]
fn constraint_stores_type_name() {
let mut v = new_constraint_list_view();
add_constraint_slot(&mut v, 0, "c", "STRETCH_TO");
assert_eq!(v.constraints[0].constraint_type, "STRETCH_TO");
}
}