shity basic one shot
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The complete description of one animator controller, produced entirely by a Rhai script.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ControllerGraph {
|
||||
pub system_name: String,
|
||||
pub asset_key: String,
|
||||
pub parameters: Vec<Parameter>,
|
||||
pub clips: Vec<ClipData>,
|
||||
pub blend_trees: Vec<BlendTreeData>,
|
||||
pub controller: Controller,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Controller {
|
||||
pub layers: Vec<Layer>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Layer {
|
||||
/// The layer suffix as written in the script. Unity's layer name is derived from it by the C# side.
|
||||
pub name: String,
|
||||
pub state_machine: StateMachine,
|
||||
}
|
||||
|
||||
/// Grid position in Unity's animator graph. Serialized as an object so C# can bind it directly.
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct GridPos {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl GridPos {
|
||||
pub fn new(x: i32, y: i32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct StateMachine {
|
||||
/// `None` for a layer's root machine, `Some` for a sub-state machine.
|
||||
pub name: Option<String>,
|
||||
pub position: GridPos,
|
||||
pub states: Vec<State>,
|
||||
pub sub_machines: Vec<StateMachine>,
|
||||
pub any_state_transitions: Vec<Transition>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct State {
|
||||
pub name: String,
|
||||
pub position: GridPos,
|
||||
pub motion: Option<MotionRef>,
|
||||
pub transitions: Vec<Transition>,
|
||||
}
|
||||
|
||||
/// References to entries in `ControllerGraph::clips` / `ControllerGraph::blend_trees`.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum MotionRef {
|
||||
Clip { name: String },
|
||||
BlendTree { name: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Transition {
|
||||
pub to: String,
|
||||
pub conditions: Vec<Condition>,
|
||||
pub has_exit_time: bool,
|
||||
pub exit_time: f32,
|
||||
pub duration: f32,
|
||||
pub ordered_interruption: bool,
|
||||
pub source_interruption: bool,
|
||||
pub can_transition_to_self: bool,
|
||||
}
|
||||
|
||||
impl Transition {
|
||||
/// Mirrors `AacDefaultsProvider.ConfigureTransition`, so unspecified fields match library defaults.
|
||||
pub fn new(to: impl Into<String>) -> Self {
|
||||
Self {
|
||||
to: to.into(),
|
||||
conditions: Vec::new(),
|
||||
has_exit_time: false,
|
||||
exit_time: 0.0,
|
||||
duration: 0.0,
|
||||
ordered_interruption: true,
|
||||
source_interruption: false,
|
||||
can_transition_to_self: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Condition {
|
||||
pub parameter: String,
|
||||
pub mode: CondMode,
|
||||
pub threshold: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CondMode {
|
||||
Greater,
|
||||
Less,
|
||||
Equals,
|
||||
NotEqual,
|
||||
If,
|
||||
IfNot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ClipData {
|
||||
pub name: String,
|
||||
pub looping: bool,
|
||||
pub curves: Vec<Curve>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Curve {
|
||||
pub path: String,
|
||||
pub target: TargetType,
|
||||
pub property: String,
|
||||
pub keys: Vec<Keyframe>,
|
||||
}
|
||||
|
||||
/// The Unity component a curve binds to. Closed set: an unknown property is an error, not a guess.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TargetType {
|
||||
GameObject,
|
||||
SkinnedMeshRenderer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Keyframe {
|
||||
pub time: f32,
|
||||
pub value: f32,
|
||||
pub in_tangent: f32,
|
||||
pub out_tangent: f32,
|
||||
}
|
||||
|
||||
impl Keyframe {
|
||||
pub fn linear(time: f32, value: f32) -> Self {
|
||||
Self {
|
||||
time,
|
||||
value,
|
||||
in_tangent: 0.0,
|
||||
out_tangent: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct BlendTreeData {
|
||||
pub name: String,
|
||||
pub blend_type: BlendType,
|
||||
pub param_x: String,
|
||||
pub param_y: Option<String>,
|
||||
pub children: Vec<BlendChild>,
|
||||
pub use_automatic_thresholds: bool,
|
||||
}
|
||||
|
||||
/// `rename_all = "snake_case"` would turn `SimpleDirectional2D` into `simple_directional2_d`,
|
||||
/// so every variant is renamed explicitly.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
pub enum BlendType {
|
||||
#[serde(rename = "simple_1d")]
|
||||
Simple1D,
|
||||
#[serde(rename = "simple_directional_2d")]
|
||||
SimpleDirectional2D,
|
||||
#[serde(rename = "freeform_directional_2d")]
|
||||
FreeformDirectional2D,
|
||||
#[serde(rename = "freeform_cartesian_2d")]
|
||||
FreeformCartesian2D,
|
||||
#[serde(rename = "direct")]
|
||||
Direct,
|
||||
}
|
||||
|
||||
impl BlendType {
|
||||
pub fn is_2d(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
BlendType::SimpleDirectional2D
|
||||
| BlendType::FreeformDirectional2D
|
||||
| BlendType::FreeformCartesian2D
|
||||
)
|
||||
}
|
||||
|
||||
/// Blend trees that place children by threshold rather than by a direct blend parameter.
|
||||
pub fn uses_thresholds(self) -> bool {
|
||||
self != BlendType::Direct
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct BlendChild {
|
||||
pub motion: MotionRef,
|
||||
pub threshold: f32,
|
||||
pub threshold_y: Option<f32>,
|
||||
/// Only meaningful on `Direct` blend trees.
|
||||
pub direct_param: Option<String>,
|
||||
}
|
||||
|
||||
impl BlendChild {
|
||||
pub fn motion(motion: MotionRef) -> Self {
|
||||
Self {
|
||||
motion,
|
||||
threshold: 0.0,
|
||||
threshold_y: None,
|
||||
direct_param: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum Parameter {
|
||||
Float { name: String, default: f32 },
|
||||
Int { name: String, default: i32 },
|
||||
Bool { name: String, default: bool },
|
||||
}
|
||||
|
||||
impl Parameter {
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
Parameter::Float { name, .. } | Parameter::Int { name, .. } | Parameter::Bool { name, .. } => name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Property-name -> component-type inference. Deliberately strict; an unmapped property is an error.
|
||||
pub fn infer_target(property: &str) -> Option<TargetType> {
|
||||
if property.starts_with("blendShape.") {
|
||||
return Some(TargetType::SkinnedMeshRenderer);
|
||||
}
|
||||
match property {
|
||||
"m_IsActive" => Some(TargetType::GameObject),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl ClipData {
|
||||
/// Find-or-create the curve for one (path, target, property) binding.
|
||||
pub fn curve_mut(&mut self, path: &str, target: TargetType, property: &str) -> &mut Curve {
|
||||
let index = match self
|
||||
.curves
|
||||
.iter()
|
||||
.position(|c| c.path == path && c.target == target && c.property == property)
|
||||
{
|
||||
Some(index) => index,
|
||||
None => {
|
||||
self.curves.push(Curve {
|
||||
path: path.to_string(),
|
||||
target,
|
||||
property: property.to_string(),
|
||||
keys: Vec::new(),
|
||||
});
|
||||
self.curves.len() - 1
|
||||
}
|
||||
};
|
||||
&mut self.curves[index]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user