use crate::utils::Vector3;
use std::cell::OnceCell;
use std::collections::HashMap;
pub const BONES: &[&str] = &[
"base",
"center",
"upper_body",
"upper_body2",
"lower_body",
"waist",
"neck",
"head",
"shoulder_l",
"shoulder_r",
"arm_l",
"arm_r",
"arm_twist_l",
"arm_twist_r",
"elbow_l",
"elbow_r",
"wrist_l",
"wrist_r",
"wrist_twist_l",
"wrist_twist_r",
"leg_l",
"leg_r",
"knee_l",
"knee_r",
"ankle_l",
"ankle_r",
"toe_l",
"toe_r",
"thumb_l",
"index_l",
"index_0_l",
"index_1_l",
"index_2_l",
"middle_l",
"middle_0_l",
"middle_1_l",
"middle_2_l",
"ring_l",
"ring_0_l",
"ring_1_l",
"ring_2_l",
"pinky_l",
"pinky_0_l",
"pinky_1_l",
"pinky_2_l",
"thumb_r",
"thumb_0_r",
"thumb_1_r",
"thumb_2_r",
"index_r",
"index_0_r",
"index_1_r",
"index_2_r",
"middle_r",
"middle_0_r",
"middle_1_r",
"middle_2_r",
"ring_r",
"ring_0_r",
"ring_1_r",
"ring_2_r",
"pinky_r",
"pinky_0_r",
"pinky_1_r",
"pinky_2_r",
];
#[derive(Debug, Clone)]
pub struct ActionRule {
pub axis: Vector3,
pub limit: f32,
}
pub struct BoneActionDatabase {
rules: HashMap<String, HashMap<String, HashMap<String, ActionRule>>>,
all_bones: Vec<String>,
bone_actions: HashMap<String, Vec<String>>,
bone_action_directions: HashMap<String, Vec<String>>,
bone_translations: HashMap<String, String>, }
impl BoneActionDatabase {
fn new() -> Self {
let rules = Self::build_rules();
Self::from_rules(rules)
}
fn from_rules(rules: HashMap<String, HashMap<String, HashMap<String, ActionRule>>>) -> Self {
let all_bones: Vec<String> = rules.keys().cloned().collect();
let mut bone_actions = HashMap::new();
let mut bone_action_directions = HashMap::new();
for (bone, actions) in &rules {
bone_actions.insert(bone.clone(), actions.keys().cloned().collect());
for (action, directions) in actions {
let key = format!("{}_{}", bone, action);
bone_action_directions.insert(key, directions.keys().cloned().collect());
}
}
let bone_translations = Self::build_translations();
Self {
rules,
all_bones,
bone_actions,
bone_action_directions,
bone_translations,
}
}
pub fn bones(&self) -> &[String] {
&self.all_bones
}
pub fn actions(&self, bone: &str) -> Option<&[String]> {
self.bone_actions.get(bone).map(|v| v.as_slice())
}
pub fn directions(&self, bone: &str, action: &str) -> Option<&[String]> {
let key = format!("{}_{}", bone, action);
self.bone_action_directions.get(&key).map(|v| v.as_slice())
}
pub fn validate(
&self,
bone: &str,
action: &str,
direction: &str,
degrees: f32,
) -> Result<(), String> {
match self
.rules
.get(bone)
.and_then(|actions| actions.get(action))
.and_then(|directions| directions.get(direction))
{
Some(rule) if degrees <= rule.limit => Ok(()),
Some(rule) => Err(format!(
"Max {} degrees for {} {} {}",
rule.limit, bone, action, direction
)),
None => Err(format!(
"Invalid combination: {} {} {}",
bone, action, direction
)),
}
}
pub fn get_rule(&self, bone: &str, action: &str, direction: &str) -> Option<&ActionRule> {
self.rules
.get(bone)
.and_then(|actions| actions.get(action))
.and_then(|directions| directions.get(direction))
}
pub fn japanese_name(&self, bone_en: &str) -> Option<&str> {
self.bone_translations.get(bone_en).map(|s| s.as_str())
}
pub fn english_name(&self, bone_jp: &str) -> Option<&str> {
self.bone_translations
.iter()
.find(|(_, v)| v == &&bone_jp.to_string())
.map(|(k, _)| k.as_str())
}
fn build_translations() -> HashMap<String, String> {
macro_rules! translations {
{ $( $en:literal => $jp:literal ),* $(,)? } => {{
let mut map = HashMap::new();
$( map.insert($en.to_string(), $jp.to_string()); )*
map
}};
}
translations! {
"base" => "全ての親",
"center" => "センター",
"upper_body" => "上半身",
"upper_body2" => "上半身2",
"lower_body" => "下半身",
"waist" => "腰",
"neck" => "首",
"head" => "頭",
"shoulder_l" => "左肩",
"shoulder_r" => "右肩",
"arm_l" => "左腕",
"arm_r" => "右腕",
"arm_twist_l" => "左腕捩",
"arm_twist_r" => "右腕捩",
"elbow_l" => "左ひじ",
"elbow_r" => "右ひじ",
"wrist_l" => "左手首",
"wrist_r" => "右手首",
"wrist_twist_l" => "左手捩",
"wrist_twist_r" => "右手捩",
"leg_l" => "左足",
"leg_r" => "右足",
"knee_l" => "左ひざ",
"knee_r" => "右ひざ",
"ankle_l" => "左足首",
"ankle_r" => "右足首",
"toe_l" => "左足先EX",
"toe_r" => "右足先EX",
"thumb_0_l" => "左親指1",
"thumb_1_l" => "左親指2",
"index_0_l" => "左人指1",
"index_1_l" => "左人指2",
"index_2_l" => "左人指3",
"middle_0_l" => "左中指1",
"middle_1_l" => "左中指2",
"middle_2_l" => "左中指3",
"ring_0_l" => "左薬指1",
"ring_1_l" => "左薬指2",
"ring_2_l" => "左薬指3",
"pinky_0_l" => "左小指1",
"pinky_1_l" => "左小指2",
"pinky_2_l" => "左小指3",
"thumb_0_r" => "右親指1",
"thumb_1_r" => "右親指2",
"index_0_r" => "右人指1",
"index_1_r" => "右人指2",
"index_2_r" => "右人指3",
"middle_0_r" => "右中指1",
"middle_1_r" => "右中指2",
"middle_2_r" => "右中指3",
"ring_0_r" => "右薬指1",
"ring_1_r" => "右薬指2",
"ring_2_r" => "右薬指3",
"pinky_0_r" => "右小指1",
"pinky_1_r" => "右小指2",
"pinky_2_r" => "右小指3",
}
}
fn build_rules() -> HashMap<String, HashMap<String, HashMap<String, ActionRule>>> {
macro_rules! rules {
{
$( $bone:literal => {
$( $action:literal => {
$( $direction:literal => [$x:expr, $y:expr, $z:expr], $limit:expr ),* $(,)?
} ),* $(,)?
} ),* $(,)?
} => {{
let mut rules = HashMap::new();
$(
let mut actions = HashMap::new();
$(
let mut directions = HashMap::new();
$(
directions.insert($direction.to_string(), ActionRule {
axis: Vector3::new($x, $y, $z),
limit: $limit,
});
)*
actions.insert($action.to_string(), directions);
)*
rules.insert($bone.to_string(), actions);
)*
rules
}};
}
rules! {
"base" => {
"move" => {
"forward" => [0.0, 0.0, -1.0], 100.0,
"backward" => [0.0, 0.0, 1.0], 100.0,
"left" => [1.0, 0.0, 0.0], 100.0,
"right" => [-1.0, 0.0, 0.0], 100.0,
"up" => [0.0, 1.0, 0.0], 100.0,
"down" => [0.0, -1.0, 0.0], 100.0,
},
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 90.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 180.0,
"right" => [0.0, 1.0, 0.0], 180.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 180.0,
"right" => [0.0, 0.0, 1.0], 180.0,
},
},
"center" => {
"move" => {
"forward" => [0.0, 0.0, -1.0], 100.0,
"backward" => [0.0, 0.0, 1.0], 100.0,
"left" => [1.0, 0.0, 0.0], 100.0,
"right" => [-1.0, 0.0, 0.0], 100.0,
"up" => [0.0, 1.0, 0.0], 100.0,
"down" => [0.0, -1.0, 0.0], 100.0,
},
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 180.0,
"backward" => [1.0, 0.0, 0.0], 180.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 180.0,
"right" => [0.0, 1.0, 0.0], 180.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 180.0,
"right" => [0.0, 0.0, 1.0], 180.0,
}
},
"head" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 60.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 60.0,
"right" => [0.0, 0.0, 1.0], 60.0,
},
},
"neck" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 60.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 60.0,
"right" => [0.0, 0.0, 1.0], 60.0,
},
},
"upper_body" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 90.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 90.0,
"right" => [0.0, 0.0, 1.0], 90.0,
},
},
"upper_body2" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 90.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 90.0,
"right" => [0.0, 0.0, 1.0], 90.0,
},
},
"lower_body" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 90.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 90.0,
"right" => [0.0, 0.0, 1.0], 90.0,
},
},
"waist" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 90.0,
"backward" => [1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, -1.0], 90.0,
"right" => [0.0, 0.0, 1.0], 90.0,
},
},
"shoulder_l" => {
"bend" => {
"forward" => [0.0, 0.0, -1.0], 90.0,
"backward" => [0.0, 0.0, 1.0], 90.0,
},
"sway" => {
"left" => [-0.6, -0.8, 0.0], 90.0,
"right" => [0.6, 0.8, 0.0], 90.0,
},
"turn" => {
"left" => [-0.8, 0.6, 0.0], 90.0,
"right" => [0.8, -0.6, 0.0], 90.0,
},
},
"shoulder_r" => {
"bend" => {
"forward" => [0.0, 0.0, 1.0], 90.0,
"backward" => [0.0, 0.0, -1.0], 90.0,
},
"sway" => {
"left" => [-0.6, 0.8, 0.0], 90.0,
"right" => [0.6, -0.8, 0.0], 90.0,
},
"turn" => {
"left" => [-0.8, -0.6, 0.0], 90.0,
"right" => [0.8, 0.6, 0.0], 90.0,
},
},
"arm_l" => {
"bend" => {
"forward" => [0.0, 0.0, -1.0], 90.0,
"backward" => [0.0, 0.0, 1.0], 90.0,
},
"sway" => {
"left" => [-0.6, -0.8, 0.0], 90.0,
"right" => [0.6, 0.8, 0.0], 90.0,
},
"turn" => {
"left" => [-0.8, 0.6, 0.0], 90.0,
"right" => [0.8, -0.6, 0.0], 90.0,
},
},
"arm_r" => {
"bend" => {
"forward" => [0.0, 0.0, 1.0], 90.0,
"backward" => [0.0, 0.0, -1.0], 90.0,
},
"sway" => {
"left" => [0.6, -0.8, 0.0], 90.0,
"right" => [-0.6, 0.8, 0.0], 90.0,
},
"turn" => {
"left" => [-0.8, -0.6, 0.0], 90.0,
"right" => [0.8, 0.6, 0.0], 90.0,
},
},
"arm_twist_l" => {
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
},
"arm_twist_r" => {
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
},
"elbow_l" => {
"bend" => {
"forward" => [0.6, 0.8, 0.0], 180.0,
},
},
"elbow_r" => {
"bend" => {
"forward" => [0.6, -0.8, 0.0], 180.0,
},
},
"wrist_l" => {
"bend" => {
"forward" => [0.0, 0.0, -1.0], 60.0,
"backward" => [0.0, 0.0, 1.0], 90.0,
},
"sway" => {
"left" => [-0.6, -0.8, 0.0], 90.0,
"right" => [0.6, 0.8, 0.0], 90.0,
},
"turn" => {
"left" => [-0.8, 0.6, 0.0], 90.0,
"right" => [0.8, -0.6, 0.0], 90.0,
},
},
"wrist_r" => {
"bend" => {
"forward" => [0.0, 0.0, 1.0], 60.0,
"backward" => [0.0, 0.0, -1.0], 90.0,
},
"sway" => {
"left" => [0.6, -0.8, 0.0], 90.0,
"right" => [-0.6, 0.8, 0.0], 90.0,
},
"turn" => {
"left" => [-0.8, -0.6, 0.0], 90.0,
"right" => [0.8, 0.6, 0.0], 90.0,
},
},
"wrist_twist_l" => {
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
},
"wrist_twist_r" => {
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
},
"leg_l" => {
"bend" => {
"forward" => [1.0, 0.0, 0.0], 180.0,
"backward" => [-1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 180.0,
"right" => [0.0, 0.0, -1.0], 30.0,
},
},
"leg_r" => {
"bend" => {
"forward" => [1.0, 0.0, 0.0], 180.0,
"backward" => [-1.0, 0.0, 0.0], 90.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 30.0,
"right" => [0.0, 0.0, -1.0], 180.0,
},
},
"knee_l" => {
"bend" => {
"backward" => [-1.0, 0.0, 0.0], 180.0,
},
},
"knee_r" => {
"bend" => {
"backward" => [-1.0, 0.0, 0.0], 180.0,
},
},
"ankle_l" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 60.0,
"backward" => [1.0, 0.0, 0.0], 60.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 30.0,
"right" => [0.0, 0.0, -1.0], 30.0,
},
},
"ankle_r" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 60.0,
"backward" => [1.0, 0.0, 0.0], 60.0,
},
"turn" => {
"left" => [0.0, -1.0, 0.0], 90.0,
"right" => [0.0, 1.0, 0.0], 90.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 30.0,
"right" => [0.0, 0.0, -1.0], 30.0,
},
},
"toe_l" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 60.0,
"backward" => [1.0, 0.0, 0.0], 60.0,
},
},
"toe_r" => {
"bend" => {
"forward" => [-1.0, 0.0, 0.0], 60.0,
"backward" => [1.0, 0.0, 0.0], 60.0,
},
},
"thumb_l" => {
"bend" => {
"forward" => [-1.0, -1.0, 0.0], 90.0,
"backward" => [1.0, 1.0, 0.0], 30.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 45.0,
"right" => [0.0, 0.0, -1.0], 45.0,
},
},
"thumb_0_l" => {
"bend" => {
"forward" => [-1.0, -1.0, 0.0], 90.0,
"backward" => [1.0, 1.0, 0.0], 30.0,
},
},
"thumb_1_l" => {
"bend" => {
"forward" => [-1.0, -1.0, 0.0], 90.0,
"backward" => [1.0, 1.0, 0.0], 30.0,
},
},
"index_l" => {
"bend" => {
"forward" => [-0.031, 0.0, -0.993], 90.0,
"backward" => [-0.031, 0.0, 0.993], 30.0,
},
"sway" => {
"left" => [0.53, -0.84, 0.0], 30.0,
"right" => [-0.53, 0.84, 0.0], 30.0,
},
},
"index_0_l" => {
"bend" => {
"forward" => [-0.031, 0.0, -0.993], 90.0,
"backward" => [-0.031, 0.0, 0.993], 30.0,
},
"sway" => {
"left" => [0.53, -0.84, 0.0], 30.0,
"right" => [-0.53, 0.84, 0.0], 30.0,
},
},
"index_1_l" => {
"bend" => {
"forward" => [-0.031, 0.0, -0.993], 90.0,
"backward" => [-0.031, 0.0, 0.993], 15.0,
},
},
"index_2_l" => {
"bend" => {
"forward" => [-0.031, 0.0, -0.993], 90.0,
"backward" => [-0.031, 0.0, 0.993], 30.0,
},
},
"middle_l" => {
"bend" => {
"forward" => [0.03, 0.0, -0.996], 90.0,
"backward" => [0.03, 0.0, 0.996], 30.0,
},
"sway" => {
"left" => [0.55, -0.83, -0.0], 30.0,
"right" => [-0.55, 0.83, -0.0], 30.0,
},
},
"middle_0_l" => {
"bend" => {
"forward" => [0.03, 0.0, -0.996], 90.0,
"backward" => [0.03, 0.0, 0.996], 30.0,
},
"sway" => {
"left" => [0.55, -0.83, -0.0], 30.0,
"right" => [-0.55, 0.83, -0.0], 30.0,
},
},
"middle_1_l" => {
"bend" => {
"forward" => [0.03, 0.0, -0.996], 90.0,
"backward" => [0.03, 0.0, 0.996], 30.0,
},
},
"middle_2_l" => {
"bend" => {
"forward" => [0.03, 0.0, -0.996], 90.0,
"backward" => [0.03, 0.0, 0.996], 30.0,
},
},
"ring_l" => {
"bend" => {
"forward" => [0.048, 0.0, -0.997], 90.0,
"backward" => [0.048, 0.0, 0.997], 30.0,
},
"sway" => {
"left" => [-0.475, -0.654, 0.0], 30.0,
"right" => [0.475, 0.654, 0.0], 30.0,
},
},
"ring_0_l" => {
"bend" => {
"forward" => [0.048, 0.0, -0.997], 90.0,
"backward" => [0.048, 0.0, 0.997], 30.0,
},
"sway" => {
"left" => [-0.475, -0.654, 0.0], 30.0,
"right" => [0.475, 0.654, 0.0], 30.0,
},
},
"ring_1_l" => {
"bend" => {
"forward" => [0.048, 0.0, -0.997], 90.0,
"backward" => [0.048, 0.0, 0.997], 30.0,
},
},
"ring_2_l" => {
"bend" => {
"forward" => [0.048, 0.0, -0.997], 90.0,
"backward" => [0.048, 0.0, 0.997], 30.0,
},
},
"pinky_l" => {
"bend" => {
"forward" => [0.088, 0.0, -0.997], 90.0,
"backward" => [0.088, 0.0, 0.997], 30.0,
},
"sway" => {
"left" => [-0.526, -0.851, 0.0], 30.0,
"right" => [0.526, 0.851, 0.0], 30.0,
},
},
"pinky_0_l" => {
"bend" => {
"forward" => [0.088, 0.0, -0.997], 90.0,
"backward" => [0.088, 0.0, 0.997], 30.0,
},
"sway" => {
"left" => [-0.526, -0.851, 0.0], 30.0,
"right" => [0.526, 0.851, 0.0], 30.0,
},
},
"pinky_1_l" => {
"bend" => {
"forward" => [0.088, 0.0, -0.997], 90.0,
"backward" => [0.088, 0.0, 0.997], 30.0,
},
},
"pinky_2_l" => {
"bend" => {
"forward" => [0.088, 0.0, -0.997], 90.0,
"backward" => [0.088, 0.0, 0.997], 30.0,
},
},
"thumb_r" => {
"bend" => {
"forward" => [-1.0, 1.0, 0.0], 90.0,
"backward" => [1.0, -1.0, 0.0], 30.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 45.0,
"right" => [0.0, 0.0, -1.0], 45.0,
},
},
"thumb_0_r" => {
"bend" => {
"forward" => [-1.0, 1.0, 0.0], 90.0,
"backward" => [1.0, -1.0, 0.0], 30.0,
},
"sway" => {
"left" => [0.0, 0.0, 1.0], 45.0,
"right" => [0.0, 0.0, -1.0], 45.0,
},
},
"thumb_1_r" => {
"bend" => {
"forward" => [-1.0, 1.0, 0.0], 90.0,
"backward" => [1.0, -1.0, 0.0], 30.0,
},
},
"index_r" => {
"bend" => {
"forward" => [-0.031, 0.0, 0.993], 90.0,
"backward" => [-0.031, 0.0, -0.993], 30.0,
},
"sway" => {
"left" => [0.53, -0.84, 0.0], 30.0,
"right" => [-0.53, 0.84, 0.0], 30.0,
},
},
"index_0_r" => {
"bend" => {
"forward" => [-0.031, 0.0, 0.993], 90.0,
"backward" => [-0.031, 0.0, -0.993], 30.0,
},
"sway" => {
"left" => [0.53, -0.84, 0.0], 30.0,
"right" => [-0.53, 0.84, 0.0], 30.0,
},
},
"index_1_r" => {
"bend" => {
"forward" => [-0.031, 0.0, 0.993], 90.0,
"backward" => [-0.031, 0.0, -0.993], 30.0,
},
},
"index_2_r" => {
"bend" => {
"forward" => [-0.031, 0.0, 0.993], 90.0,
"backward" => [-0.031, 0.0, -0.993], 30.0,
},
},
"middle_r" => {
"bend" => {
"forward" => [0.03, 0.0, 0.996], 90.0,
"backward" => [0.03, 0.0, -0.996], 30.0,
},
"sway" => {
"left" => [0.55, -0.83, 0.0], 30.0,
"right" => [-0.55, 0.83, 0.0], 30.0,
},
},
"middle_0_r" => {
"bend" => {
"forward" => [0.03, 0.0, 0.996], 90.0,
"backward" => [0.03, 0.0, -0.996], 30.0,
},
"sway" => {
"left" => [0.55, -0.83, -0.0], 30.0,
"right" => [-0.55, 0.83, -0.0], 30.0,
},
},
"middle_1_r" => {
"bend" => {
"forward" => [0.03, 0.0, 0.996], 90.0,
"backward" => [0.03, 0.0, -0.996], 30.0,
},
},
"middle_2_r" => {
"bend" => {
"forward" => [0.03, 0.0, 0.996], 90.0,
"backward" => [0.03, 0.0, -0.996], 30.0,
},
},
"ring_r" => {
"bend" => {
"forward" => [0.048, 0.0, 0.997], 90.0,
"backward" => [0.048, 0.0, -0.997], 30.0,
},
"sway" => {
"left" => [-0.475, -0.654, 0.0], 30.0,
"right" => [0.475, 0.654, 0.0], 30.0,
},
},
"ring_0_r" => {
"bend" => {
"forward" => [0.048, 0.0, 0.997], 90.0,
"backward" => [0.048, 0.0, -0.997], 30.0,
},
"sway" => {
"left" => [0.475, -0.654, 0.0], 30.0,
"right" => [-0.475, 0.654, 0.0], 30.0,
},
},
"ring_1_r" => {
"bend" => {
"forward" => [0.048, 0.0, 0.997], 90.0,
"backward" => [0.048, 0.0, -0.997], 15.0,
},
},
"ring_2_r" => {
"bend" => {
"forward" => [0.048, 0.0, 0.997], 90.0,
"backward" => [0.048, 0.0, -0.997], 30.0,
},
},
"pinky_r" => {
"bend" => {
"forward" => [0.088, 0.0, 0.997], 90.0,
"backward" => [0.088, 0.0, -0.997], 30.0,
},
"sway" => {
"left" => [-0.526, -0.851, 0.0], 30.0,
"right" => [0.526, 0.851, 0.0], 30.0,
},
},
"pinky_0_r" => {
"bend" => {
"forward" => [0.088, 0.0, 0.997], 90.0,
"backward" => [0.088, 0.0, -0.997], 30.0,
},
"sway" => {
"left" => [0.526, -0.851, 0.0], 30.0,
"right" => [-0.526, 0.851, 0.0], 30.0,
},
},
"pinky_1_r" => {
"bend" => {
"forward" => [0.088, 0.0, 0.997], 90.0,
"backward" => [0.088, 0.0, -0.997], 30.0,
},
},
"pinky_2_r" => {
"bend" => {
"forward" => [0.088, 0.0, 0.997], 90.0,
"backward" => [0.088, 0.0, -0.997], 30.0,
},
},
}
}
}
thread_local! {
static BONE_DB: OnceCell<BoneActionDatabase> = OnceCell::new();
}
pub fn with_bone_db<T>(f: impl FnOnce(&BoneActionDatabase) -> T) -> T {
BONE_DB.with(|db| f(db.get_or_init(|| BoneActionDatabase::new())))
}