shity basic one shot

This commit is contained in:
2026-09-18 14:01:10 +01:00
parent 5851077659
commit 42a1234e7f
81 changed files with 3484 additions and 76 deletions
+188
View File
@@ -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(&parameter.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(&parameter.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)
}