1#![allow(dead_code)]
2#[allow(dead_code)]
8#[derive(Debug, Clone)]
9pub struct BoneTransform {
10 pub bone_id: u32,
11 pub name: String,
12 pub position: [f32; 3],
13 pub rotation: [f32; 4],
14 pub scale: [f32; 3],
15}
16
17#[allow(dead_code)]
18#[derive(Debug, Clone)]
19pub struct PoseExport {
20 pub name: String,
21 pub bones: Vec<BoneTransform>,
22}
23
24#[allow(dead_code)]
25pub fn new_pose_export(name: &str) -> PoseExport {
26 PoseExport {
27 name: name.to_string(),
28 bones: Vec::new(),
29 }
30}
31
32#[allow(dead_code)]
33pub fn add_bone_transform(
34 p: &mut PoseExport,
35 id: u32,
36 name: &str,
37 pos: [f32; 3],
38 rot: [f32; 4],
39 scale: [f32; 3],
40) {
41 p.bones.push(BoneTransform {
42 bone_id: id,
43 name: name.to_string(),
44 position: pos,
45 rotation: rot,
46 scale,
47 });
48}
49
50#[allow(dead_code)]
51pub fn export_pose_to_json(p: &PoseExport) -> String {
52 let mut bones_json = String::new();
53 for (i, b) in p.bones.iter().enumerate() {
54 if i > 0 {
55 bones_json.push(',');
56 }
57 bones_json.push_str(&format!(
58 r#"{{"id":{},"name":"{}","position":[{},{},{}],"rotation":[{},{},{},{}],"scale":[{},{},{}]}}"#,
59 b.bone_id, b.name,
60 b.position[0], b.position[1], b.position[2],
61 b.rotation[0], b.rotation[1], b.rotation[2], b.rotation[3],
62 b.scale[0], b.scale[1], b.scale[2],
63 ));
64 }
65 format!(r#"{{"name":"{}","bones":[{}]}}"#, p.name, bones_json)
66}
67
68#[allow(dead_code)]
69pub fn bone_count(p: &PoseExport) -> usize {
70 p.bones.len()
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn new_pose_export_empty() {
79 let p = new_pose_export("idle");
80 assert_eq!(p.name, "idle");
81 assert_eq!(bone_count(&p), 0);
82 }
83
84 #[test]
85 fn add_bone_increases_count() {
86 let mut p = new_pose_export("run");
87 add_bone_transform(&mut p, 0, "root", [0.0; 3], [0.0, 0.0, 0.0, 1.0], [1.0; 3]);
88 assert_eq!(bone_count(&p), 1);
89 }
90
91 #[test]
92 fn bone_transform_fields() {
93 let mut p = new_pose_export("test");
94 add_bone_transform(
95 &mut p,
96 5,
97 "spine",
98 [1.0, 2.0, 3.0],
99 [0.0, 0.0, 0.0, 1.0],
100 [1.0; 3],
101 );
102 assert_eq!(p.bones[0].bone_id, 5);
103 assert_eq!(p.bones[0].name, "spine");
104 }
105
106 #[test]
107 fn export_pose_to_json_contains_name() {
108 let p = new_pose_export("walk");
109 let j = export_pose_to_json(&p);
110 assert!(j.contains("walk"));
111 }
112
113 #[test]
114 fn export_pose_to_json_bones_array() {
115 let mut p = new_pose_export("t");
116 add_bone_transform(&mut p, 0, "b0", [0.0; 3], [0.0, 0.0, 0.0, 1.0], [1.0; 3]);
117 let j = export_pose_to_json(&p);
118 assert!(j.contains("bones"));
119 assert!(j.contains("b0"));
120 }
121
122 #[test]
123 fn multiple_bones() {
124 let mut p = new_pose_export("t");
125 for i in 0..5 {
126 add_bone_transform(&mut p, i, "b", [0.0; 3], [0.0, 0.0, 0.0, 1.0], [1.0; 3]);
127 }
128 assert_eq!(bone_count(&p), 5);
129 }
130
131 #[test]
132 fn export_json_has_position() {
133 let mut p = new_pose_export("t");
134 add_bone_transform(
135 &mut p,
136 0,
137 "b",
138 [1.0, 2.0, 3.0],
139 [0.0, 0.0, 0.0, 1.0],
140 [1.0; 3],
141 );
142 let j = export_pose_to_json(&p);
143 assert!(j.contains("position"));
144 }
145
146 #[test]
147 fn export_json_has_rotation() {
148 let mut p = new_pose_export("t");
149 add_bone_transform(&mut p, 0, "b", [0.0; 3], [0.1, 0.2, 0.3, 0.9], [1.0; 3]);
150 let j = export_pose_to_json(&p);
151 assert!(j.contains("rotation"));
152 }
153
154 #[test]
155 fn export_json_has_scale() {
156 let mut p = new_pose_export("t");
157 add_bone_transform(
158 &mut p,
159 0,
160 "b",
161 [0.0; 3],
162 [0.0, 0.0, 0.0, 1.0],
163 [2.0, 2.0, 2.0],
164 );
165 let j = export_pose_to_json(&p);
166 assert!(j.contains("scale"));
167 }
168}