mod read;
use serde::Serialize;
use crate::player::ObjRef;
pub fn name_hash(name: &str) -> u32 {
let mut crc = !0u32;
for byte in name.bytes() {
crc ^= u32::from(byte);
for _ in 0..8 {
crc = (crc >> 1) ^ (0xEDB8_8320 & 0u32.wrapping_sub(crc & 1));
}
}
!crc
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
pub struct Xform {
pub t: [f32; 3],
pub q: [f32; 4],
pub s: [f32; 3],
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
pub struct AvatarAxes {
pub pre_q: [f32; 4],
pub post_q: [f32; 4],
pub sgn: [f32; 3],
pub min: [f32; 3],
pub max: [f32; 3],
pub length: f32,
pub kind: i64,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
pub struct AvatarSkeleton {
pub nodes: Vec<(i64, i64)>,
pub ids: Vec<u32>,
pub axes: Vec<AvatarAxes>,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct AvatarHuman {
pub root: Xform,
pub skeleton: AvatarSkeleton,
pub pose: Vec<Xform>,
pub left_hand: Vec<i64>,
pub right_hand: Vec<i64>,
pub bone_index: Vec<i64>,
pub bone_mass: Vec<f32>,
pub scale: f32,
pub arm_twist: f32,
pub fore_arm_twist: f32,
pub upper_leg_twist: f32,
pub leg_twist: f32,
pub arm_stretch: f32,
pub leg_stretch: f32,
pub feet_spacing: f32,
pub has_left_hand: bool,
pub has_right_hand: bool,
pub has_translation_dof: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct HumanBone {
pub bone_name: String,
pub human_name: String,
pub min: [f32; 3],
pub max: [f32; 3],
pub value: [f32; 3],
pub length: f32,
pub modified: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct SkeletonBone {
pub name: String,
pub parent: String,
pub position: [f32; 3],
pub rotation: [f32; 4],
pub scale: [f32; 3],
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct HumanDescription {
pub human: Vec<HumanBone>,
pub skeleton: Vec<SkeletonBone>,
pub arm_twist: f32,
pub fore_arm_twist: f32,
pub upper_leg_twist: f32,
pub leg_twist: f32,
pub arm_stretch: f32,
pub leg_stretch: f32,
pub feet_spacing: f32,
pub global_scale: f32,
pub root_motion_bone_name: String,
pub has_translation_dof: bool,
pub has_extra_root: bool,
pub skeleton_has_parents: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct UnityAvatar {
pub avatar: ObjRef,
pub name: String,
pub skeleton: AvatarSkeleton,
pub skeleton_pose: Vec<Xform>,
pub default_pose: Vec<Xform>,
pub skeleton_name_ids: Vec<u32>,
pub human: Option<AvatarHuman>,
pub human_skeleton_index: Vec<i64>,
pub human_skeleton_reverse: Vec<i64>,
pub root_motion_bone_index: i64,
pub root_motion_bone: Xform,
pub root_motion_skeleton: AvatarSkeleton,
pub root_motion_pose: Vec<Xform>,
pub root_motion_skeleton_index: Vec<i64>,
pub tos: Vec<(u32, String)>,
pub description: HumanDescription,
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
pub struct Condition {
pub mode: i64,
pub parameter: u32,
pub threshold: f32,
pub exit_time: f32,
}
pub const SELECTOR_BASE: i64 = 30000;
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct Transition {
pub conditions: Vec<Condition>,
pub destination: i64,
pub full_path_id: u32,
pub id: u32,
pub user_id: u32,
pub duration: f32,
pub offset: f32,
pub exit_time: f32,
pub has_exit_time: bool,
pub has_fixed_duration: bool,
pub interruption_source: i64,
pub ordered_interruption: bool,
pub can_transition_to_self: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct BlendNode {
pub blend_type: i64,
pub event_id: u32,
pub event_y_id: u32,
pub children: Vec<u32>,
pub thresholds: Vec<f32>,
pub positions: Vec<[f32; 2]>,
pub magnitudes: Vec<f32>,
pub pair_vectors: Vec<[f32; 2]>,
pub pair_avg_mag_inv: Vec<f32>,
pub neighbors: Vec<Vec<u32>>,
pub direct_events: Vec<u32>,
pub normalized_blend_values: bool,
pub clip: u32,
pub duration: f32,
pub cycle_offset: f32,
pub mirror: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct State {
pub transitions: Vec<Transition>,
pub blend_tree_index: Vec<i64>,
pub blend_trees: Vec<Vec<BlendNode>>,
pub name_id: u32,
pub path_id: u32,
pub full_path_id: u32,
pub tag_id: u32,
pub speed_param: u32,
pub mirror_param: u32,
pub cycle_offset_param: u32,
pub time_param: u32,
pub speed: f32,
pub cycle_offset: f32,
pub ik_on_feet: bool,
pub write_default_values: bool,
pub looping: bool,
pub mirror: bool,
}
pub const NO_DESTINATION: u32 = u32::MAX;
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct SelectorTransition {
pub destination: Option<u32>,
pub conditions: Vec<Condition>,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct SelectorState {
pub transitions: Vec<SelectorTransition>,
pub full_path_id: u32,
pub is_entry: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct StateMachine {
pub states: Vec<State>,
pub any_state_transitions: Vec<Transition>,
pub selectors: Vec<SelectorState>,
pub default_state: i64,
pub synchronized_layer_count: i64,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct Layer {
pub state_machine: i64,
pub synchronized_layer: i64,
pub body_mask: [u32; 3],
pub skeleton_mask: Vec<(u32, f32)>,
pub binding: u32,
pub blending_mode: i64,
pub default_weight: f32,
pub ik_pass: bool,
pub synced_layer_affects_timing: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
pub struct Parameter {
pub id: u32,
pub kind: i64,
pub index: i64,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct UnityAnimatorController {
pub controller: ObjRef,
pub name: String,
pub layers: Vec<Layer>,
pub state_machines: Vec<StateMachine>,
pub parameters: Vec<Parameter>,
pub default_floats: Vec<f32>,
pub default_ints: Vec<i64>,
pub default_bools: Vec<bool>,
pub clips: Vec<Option<ObjRef>>,
pub behaviours: Vec<ObjRef>,
pub tos: Vec<(u32, String)>,
}
impl UnityAnimatorController {
pub fn name_of(&self, hash: u32) -> Option<&str> {
self.tos.iter().find(|(h, _)| *h == hash).map(|(_, n)| n.as_str())
}
}