vrm_spec/
vrmc_spring_bone_1_0.rs1#[cfg(feature = "rustc_hash")]
4use rustc_hash::FxHashMap as HashMap;
5use serde::{Deserialize, Serialize};
6#[cfg(not(feature = "rustc_hash"))]
7use std::collections::HashMap;
8
9pub const VRMC_SPRING_BONE: &str = "VRMC_springBone";
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct VrmcSpringBoneSchema {
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub collider_groups: Option<Vec<ColliderGroup>>,
19
20 #[serde(skip_serializing_if = "Option::is_none")]
22 pub colliders: Option<Vec<Collider>>,
23
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub extensions: Option<HashMap<String, HashMap<String, Option<serde_json::Value>>>>,
26
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub extras: Option<serde_json::Value>,
29
30 pub spec_version: String,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub springs: Option<Vec<Spring>>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct ColliderGroup {
41 pub colliders: Vec<usize>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub extensions: Option<HashMap<String, HashMap<String, Option<serde_json::Value>>>>,
46
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub extras: Option<serde_json::Value>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub name: Option<String>,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct Collider {
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub extensions: Option<HashMap<String, HashMap<String, Option<serde_json::Value>>>>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub extras: Option<serde_json::Value>,
63
64 #[cfg(feature = "gltf_index")]
66 pub node: gltf::json::Index<gltf::json::Node>,
67 #[cfg(not(feature = "gltf_index"))]
68 pub node: usize,
69
70 pub shape: ColliderShape,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct ColliderShape {
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub capsule: Option<ColliderShapeCapsule>,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub extensions: Option<HashMap<String, HashMap<String, Option<serde_json::Value>>>>,
81
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub extras: Option<serde_json::Value>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub sphere: Option<ColliderShapeSphere>,
87}
88
89#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
90pub struct ColliderShapeCapsule {
91 #[serde(skip_serializing_if = "Option::is_none")]
93 pub offset: Option<[f64; 3]>,
94
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub radius: Option<f64>,
98
99 #[serde(skip_serializing_if = "Option::is_none")]
101 pub tail: Option<[f64; 3]>,
102}
103
104#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
105pub struct ColliderShapeSphere {
106 #[serde(skip_serializing_if = "Option::is_none")]
108 pub offset: Option<[f64; 3]>,
109
110 #[serde(skip_serializing_if = "Option::is_none")]
112 pub radius: Option<f64>,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct Spring {
119 #[cfg(feature = "gltf_index")]
121 pub center: Option<gltf::json::Index<gltf::json::Node>>,
122 #[cfg(not(feature = "gltf_index"))]
123 pub center: Option<usize>,
124
125 #[serde(skip_serializing_if = "Option::is_none")]
127 pub collider_groups: Option<Vec<i64>>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub extensions: Option<HashMap<String, HashMap<String, Option<serde_json::Value>>>>,
131
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub extras: Option<serde_json::Value>,
134
135 pub joints: Vec<SpringBoneJoint>,
138
139 #[serde(skip_serializing_if = "Option::is_none")]
141 pub name: Option<String>,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct SpringBoneJoint {
148 #[serde(skip_serializing_if = "Option::is_none")]
150 pub drag_force: Option<f64>,
151
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub extensions: Option<HashMap<String, HashMap<String, Option<serde_json::Value>>>>,
154
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub extras: Option<serde_json::Value>,
157
158 #[serde(skip_serializing_if = "Option::is_none")]
160 pub gravity_dir: Option<[f64; 3]>,
161
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub gravity_power: Option<f64>,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub hit_radius: Option<f64>,
169
170 #[cfg(feature = "gltf_index")]
172 pub node: gltf::json::Index<gltf::json::Node>,
173 #[cfg(not(feature = "gltf_index"))]
174 pub node: usize,
175
176 #[serde(skip_serializing_if = "Option::is_none")]
178 pub stiffness: Option<f64>,
179}