oxihuman_export/
constraint_export.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, PartialEq)]
10pub enum ConstraintKind {
11 CopyLocation,
12 CopyRotation,
13 CopyScale,
14 LimitRotation,
15 LimitLocation,
16}
17
18#[derive(Debug, Clone)]
19pub struct ConstraintExport {
20 pub name: String,
21 pub kind: ConstraintKind,
22 pub target: String,
23 pub influence: f32,
24}
25
26pub fn new_constraint_export(name: &str, kind: ConstraintKind, target: &str) -> ConstraintExport {
27 ConstraintExport {
28 name: name.to_string(),
29 kind,
30 target: target.to_string(),
31 influence: 1.0,
32 }
33}
34
35pub fn constraint_is_active(constraint: &ConstraintExport) -> bool {
36 constraint.influence > 0.0
37}
38
39pub fn constraint_to_json_legacy(constraint: &ConstraintExport) -> String {
40 format!(
41 "{{\"name\":\"{}\",\"kind\":\"{}\",\"target\":\"{}\",\"influence\":{}}}",
42 constraint.name,
43 constraint_kind_name(constraint),
44 constraint.target,
45 constraint.influence
46 )
47}
48
49pub fn constraint_kind_name(constraint: &ConstraintExport) -> &'static str {
50 match constraint.kind {
51 ConstraintKind::CopyLocation => "CopyLocation",
52 ConstraintKind::CopyRotation => "CopyRotation",
53 ConstraintKind::CopyScale => "CopyScale",
54 ConstraintKind::LimitRotation => "LimitRotation",
55 ConstraintKind::LimitLocation => "LimitLocation",
56 }
57}
58
59pub fn constraint_set_influence(constraint: &mut ConstraintExport, influence: f32) {
60 constraint.influence = influence.clamp(0.0, 1.0);
61}
62
63pub fn constraint_validate(constraint: &ConstraintExport) -> bool {
64 !constraint.name.is_empty()
65 && !constraint.target.is_empty()
66 && (0.0..=1.0).contains(&constraint.influence)
67}
68
69#[derive(Debug, Clone)]
73pub struct ConstraintData {
74 pub name: String,
75 pub constraint_type: String,
76 pub target: String,
77 pub influence: f32,
78 pub active: bool,
79}
80
81pub fn new_constraint_data(name: &str, constraint_type: &str, target: &str) -> ConstraintData {
83 ConstraintData {
84 name: name.to_string(),
85 constraint_type: constraint_type.to_string(),
86 target: target.to_string(),
87 influence: 1.0,
88 active: true,
89 }
90}
91
92pub fn constraint_to_json(c: &ConstraintData) -> String {
94 format!(
95 "{{\"name\":\"{}\",\"type\":\"{}\",\"target\":\"{}\",\"influence\":{},\"active\":{}}}",
96 c.name, c.constraint_type, c.target, c.influence, c.active
97 )
98}
99
100pub fn constraints_to_json(cs: &[ConstraintData]) -> String {
102 let inner: Vec<String> = cs.iter().map(constraint_to_json).collect();
103 format!("[{}]", inner.join(","))
104}
105
106pub fn constraint_is_active_spec(c: &ConstraintData) -> bool {
108 c.active && c.influence > 0.0
109}
110
111pub fn constraint_count(cs: &[ConstraintData]) -> usize {
113 cs.len()
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_new_constraint_data() {
122 let c = new_constraint_data("c", "COPY_LOC", "Head");
123 assert_eq!(c.name, "c");
124 assert!(c.active);
125 }
126
127 #[test]
128 fn test_constraint_to_json() {
129 let c = new_constraint_data("c", "COPY_ROT", "Spine");
130 let j = constraint_to_json(&c);
131 assert!(j.contains("COPY_ROT"));
132 }
133
134 #[test]
135 fn test_constraints_to_json() {
136 let cs = vec![
137 new_constraint_data("a", "COPY_LOC", "X"),
138 new_constraint_data("b", "LIMIT_ROT", "Y"),
139 ];
140 let j = constraints_to_json(&cs);
141 assert!(j.starts_with('['));
142 }
143
144 #[test]
145 fn test_constraint_is_active_spec() {
146 let c = new_constraint_data("c", "T", "t");
147 assert!(constraint_is_active_spec(&c));
148 }
149
150 #[test]
151 fn test_constraint_count() {
152 let cs = vec![new_constraint_data("a", "T", "x")];
153 assert_eq!(constraint_count(&cs), 1);
154 }
155}