#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct SpineSlot {
pub name: String,
pub bone: String,
pub attachment: Option<String>,
}
#[derive(Debug, Clone)]
pub struct SpineBone {
pub name: String,
pub parent: Option<String>,
pub length: f32,
}
#[derive(Debug, Clone)]
pub struct SpineExport {
pub name: String,
pub bones: Vec<SpineBone>,
pub slots: Vec<SpineSlot>,
}
impl SpineExport {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
bones: Vec::new(),
slots: Vec::new(),
}
}
pub fn add_bone(&mut self, bone: SpineBone) {
self.bones.push(bone);
}
pub fn add_slot(&mut self, slot: SpineSlot) {
self.slots.push(slot);
}
pub fn bone_count(&self) -> usize {
self.bones.len()
}
pub fn slot_count(&self) -> usize {
self.slots.len()
}
}
pub fn export_spine_json(doc: &SpineExport) -> String {
format!(
"{{\"skeleton\":{{\"name\":\"{}\"}},\"bones_count\":{},\"slots_count\":{}}}",
doc.name,
doc.bone_count(),
doc.slot_count()
)
}
pub fn find_bone<'a>(doc: &'a SpineExport, name: &str) -> Option<&'a SpineBone> {
doc.bones.iter().find(|b| b.name == name)
}
pub fn total_bone_length(doc: &SpineExport) -> f32 {
doc.bones.iter().map(|b| b.length).sum()
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_doc() -> SpineExport {
let mut doc = SpineExport::new("character");
doc.add_bone(SpineBone {
name: "root".into(),
parent: None,
length: 0.0,
});
doc.add_bone(SpineBone {
name: "spine".into(),
parent: Some("root".into()),
length: 50.0,
});
doc.add_slot(SpineSlot {
name: "body".into(),
bone: "spine".into(),
attachment: None,
});
doc
}
#[test]
fn test_bone_count() {
let d = sample_doc();
assert_eq!(d.bone_count(), 2);
}
#[test]
fn test_slot_count() {
let d = sample_doc();
assert_eq!(d.slot_count(), 1);
}
#[test]
fn test_export_json_not_empty() {
let d = sample_doc();
let json = export_spine_json(&d);
assert!(!json.is_empty());
}
#[test]
fn test_export_json_contains_name() {
let d = sample_doc();
let json = export_spine_json(&d);
assert!(json.contains("character"));
}
#[test]
fn test_find_bone_found() {
let d = sample_doc();
assert!(find_bone(&d, "spine").is_some());
}
#[test]
fn test_find_bone_not_found() {
let d = sample_doc();
assert!(find_bone(&d, "arm").is_none());
}
#[test]
fn test_total_bone_length() {
let d = sample_doc();
assert!((total_bone_length(&d) - 50.0).abs() < 1e-5);
}
#[test]
fn test_empty_document() {
let d = SpineExport::new("empty");
assert_eq!(d.bone_count(), 0);
assert_eq!(d.slot_count(), 0);
}
}