shity basic one shot
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
use crate::builder::*;
|
||||
use crate::graph::*;
|
||||
use crate::rhai_api::err;
|
||||
use rhai::{Engine, EvalAltResult};
|
||||
|
||||
pub fn register(engine: &mut Engine) {
|
||||
register_clips(engine);
|
||||
register_blend_trees(engine);
|
||||
register_state_motion(engine);
|
||||
}
|
||||
|
||||
fn clip_ref(clip: &ClipBuilder) -> MotionRef {
|
||||
MotionRef::Clip {
|
||||
name: clip.name.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn tree_ref(tree: &BlendTreeBuilder) -> MotionRef {
|
||||
MotionRef::BlendTree {
|
||||
name: tree.name.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn register_clips(engine: &mut Engine) {
|
||||
engine.register_fn("clip", |a: &mut Aac, name: &str| -> Result<ClipBuilder, Box<EvalAltResult>> {
|
||||
if name.trim().is_empty() {
|
||||
return Err(err("clip name is empty".to_string()));
|
||||
}
|
||||
if a.write(|graph| graph.clips.iter().any(|clip| clip.name == name)) {
|
||||
return Err(err(format!("clip `{name}` is already declared")));
|
||||
}
|
||||
a.write(|graph| {
|
||||
graph.clips.push(ClipData {
|
||||
name: name.to_string(),
|
||||
looping: false,
|
||||
curves: Vec::new(),
|
||||
})
|
||||
});
|
||||
Ok(ClipBuilder {
|
||||
aac: a.clone(),
|
||||
name: name.to_string(),
|
||||
})
|
||||
});
|
||||
|
||||
engine.register_fn("looping", |clip: ClipBuilder, value: bool| {
|
||||
clip.data_mut(|data| data.looping = value);
|
||||
clip
|
||||
});
|
||||
|
||||
engine.register_fn(
|
||||
"keyframe",
|
||||
|clip: ClipBuilder, path: &str, property: &str, time: f64, value: f64| -> Result<ClipBuilder, Box<EvalAltResult>> {
|
||||
clip.push_key(path, property, Keyframe::linear(time as f32, value as f32))
|
||||
.map_err(err)?;
|
||||
Ok(clip)
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn("toggle", |clip: ClipBuilder, path: &str, value: bool| -> Result<ClipBuilder, Box<EvalAltResult>> {
|
||||
let value = if value { 1.0 } else { 0.0 };
|
||||
// A one-frame constant, matching AAC's toggling semantics.
|
||||
clip.push_key(path, "m_IsActive", Keyframe::linear(0.0, value))
|
||||
.map_err(err)?;
|
||||
clip.push_key(path, "m_IsActive", Keyframe::linear(1.0 / 60.0, value))
|
||||
.map_err(err)?;
|
||||
Ok(clip)
|
||||
});
|
||||
|
||||
engine.register_fn(
|
||||
"blend_shape",
|
||||
|clip: ClipBuilder, path: &str, shape: &str, time: f64, value: f64| -> Result<ClipBuilder, Box<EvalAltResult>> {
|
||||
let property = format!("blendShape.{shape}");
|
||||
clip.push_key(path, &property, Keyframe::linear(time as f32, value as f32))
|
||||
.map_err(err)?;
|
||||
Ok(clip)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn register_blend_trees(engine: &mut Engine) {
|
||||
engine.register_fn("blend_tree", |a: &mut Aac, name: &str| -> Result<BlendTreeBuilder, Box<EvalAltResult>> {
|
||||
if name.trim().is_empty() {
|
||||
return Err(err("blend tree name is empty".to_string()));
|
||||
}
|
||||
if a.write(|graph| graph.blend_trees.iter().any(|tree| tree.name == name)) {
|
||||
return Err(err(format!("blend tree `{name}` is already declared")));
|
||||
}
|
||||
a.write(|graph| {
|
||||
graph.blend_trees.push(BlendTreeData {
|
||||
name: name.to_string(),
|
||||
blend_type: BlendType::Simple1D,
|
||||
param_x: String::new(),
|
||||
param_y: None,
|
||||
children: Vec::new(),
|
||||
use_automatic_thresholds: false,
|
||||
})
|
||||
});
|
||||
Ok(BlendTreeBuilder {
|
||||
aac: a.clone(),
|
||||
name: name.to_string(),
|
||||
})
|
||||
});
|
||||
|
||||
engine.register_fn("simple_1d", |tree: BlendTreeBuilder, x: FloatParam| {
|
||||
tree.configure(BlendType::Simple1D, &x.name, None).map_err(err)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("simple_directional_2d", |tree: BlendTreeBuilder, x: FloatParam, y: FloatParam| {
|
||||
tree.configure(BlendType::SimpleDirectional2D, &x.name, Some(&y.name))
|
||||
.map_err(err)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("freeform_directional_2d", |tree: BlendTreeBuilder, x: FloatParam, y: FloatParam| {
|
||||
tree.configure(BlendType::FreeformDirectional2D, &x.name, Some(&y.name))
|
||||
.map_err(err)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("freeform_cartesian_2d", |tree: BlendTreeBuilder, x: FloatParam, y: FloatParam| {
|
||||
tree.configure(BlendType::FreeformCartesian2D, &x.name, Some(&y.name))
|
||||
.map_err(err)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("direct", |tree: BlendTreeBuilder| {
|
||||
tree.configure(BlendType::Direct, "", None).map_err(err)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("automatic_thresholds", |tree: BlendTreeBuilder, value: bool| {
|
||||
tree.data_mut(|data| data.use_automatic_thresholds = value);
|
||||
tree
|
||||
});
|
||||
|
||||
engine.register_fn("add_motion", |tree: BlendTreeBuilder, clip: ClipBuilder, threshold: f64| {
|
||||
push_child(&tree, clip_ref(&clip), threshold, None, None)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("add_motion", |tree: BlendTreeBuilder, child: BlendTreeBuilder, threshold: f64| {
|
||||
push_child(&tree, tree_ref(&child), threshold, None, None)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("add_motion", |tree: BlendTreeBuilder, clip: ClipBuilder, x: f64, y: f64| {
|
||||
push_child(&tree, clip_ref(&clip), x, Some(y), None)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("add_motion", |tree: BlendTreeBuilder, child: BlendTreeBuilder, x: f64, y: f64| {
|
||||
push_child(&tree, tree_ref(&child), x, Some(y), None)?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
|
||||
engine.register_fn("add_motion_direct", |tree: BlendTreeBuilder, clip: ClipBuilder, parameter: FloatParam| {
|
||||
push_child(&tree, clip_ref(&clip), 0.0, None, Some(¶meter.name))?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
engine.register_fn("add_motion_direct", |tree: BlendTreeBuilder, child: BlendTreeBuilder, parameter: FloatParam| {
|
||||
push_child(&tree, tree_ref(&child), 0.0, None, Some(¶meter.name))?;
|
||||
Ok::<BlendTreeBuilder, Box<EvalAltResult>>(tree)
|
||||
});
|
||||
}
|
||||
|
||||
fn register_state_motion(engine: &mut Engine) {
|
||||
engine.register_fn("set_clip", |state: StateRef, clip: ClipBuilder| {
|
||||
state.set_motion(clip_ref(&clip));
|
||||
state
|
||||
});
|
||||
engine.register_fn("set_motion", |state: StateRef, clip: ClipBuilder| {
|
||||
state.set_motion(clip_ref(&clip));
|
||||
state
|
||||
});
|
||||
engine.register_fn("set_motion", |state: StateRef, tree: BlendTreeBuilder| {
|
||||
state.set_motion(tree_ref(&tree));
|
||||
state
|
||||
});
|
||||
}
|
||||
|
||||
fn push_child(
|
||||
tree: &BlendTreeBuilder,
|
||||
motion: MotionRef,
|
||||
threshold: f64,
|
||||
threshold_y: Option<f64>,
|
||||
direct_param: Option<&str>,
|
||||
) -> Result<(), Box<EvalAltResult>> {
|
||||
let child = BlendChild {
|
||||
motion,
|
||||
threshold: threshold as f32,
|
||||
threshold_y: threshold_y.map(|y| y as f32),
|
||||
direct_param: direct_param.map(str::to_string),
|
||||
};
|
||||
tree.push_child(child).map_err(err)
|
||||
}
|
||||
Reference in New Issue
Block a user