feat(engine): clip move, clip effect_input, mandatory static FFmpeg

- oakengine_sequence_move_clip implemented for real (oaktimeline
  TrackMoveBlockCommand; fixes the graph-ownership/gap-anchor/ripple
  trim bugs the stub was hiding); same-track via the frozen C ABI,
  cross-track supported by the module command
- oaknode clip blocks now declare a tex_in texture input and set
  effect_input to it, so timeline clips can host effect chains; facade
  test covers effect insert/remove on a real clip
- oakffmpeg-link: FFMPEG_DIR is now mandatory with a clear panic (a
  Homebrew upgrade left the system ffmpeg .pc pointing at a deleted
  dav1d Cellar path, breaking links); reads a git-ignored workspace
  .env for IDEs that cannot inject env vars (RustRover); links the C++
  stdlib for C++ codec libs (svt-av1)
- oakengine re-exports oaknode so tests share one crate instance;
  it_node uses the direct instance's value type where it calls the
  module FFI (the --workspace dev-dependency feature split builds
  oaknode twice)
This commit is contained in:
2026-08-11 23:04:48 +08:00
parent a209f63d52
commit 18ff60f147
351 changed files with 32880 additions and 15939 deletions
+11 -8
View File
@@ -63,7 +63,11 @@ pub fn copy_inputs(
// C++ copies per-element too — array elements are covered when the
// array family lands).
for id in &src_inputs {
if !graph.get(dst).map(|e| e.core.has_input(id)).unwrap_or(false) {
if !graph
.get(dst)
.map(|e| e.core.has_input(id))
.unwrap_or(false)
{
continue;
}
let value = {
@@ -72,16 +76,16 @@ pub fn copy_inputs(
};
let declared = {
let entry = graph.get(src).ok_or(Error::NotFound)?;
entry.core.input_data_type(id).unwrap_or(crate::value::ValueType::None)
entry
.core
.input_data_type(id)
.unwrap_or(crate::value::ValueType::None)
};
let value = {
// Re-quantize to the destination's declared type so the copy
// never stores a mismatched payload.
let entry = graph.get(dst).ok_or(Error::NotFound)?;
let dst_declared = entry
.core
.input_data_type(id)
.ok_or(Error::NotFound)?;
let dst_declared = entry.core.input_data_type(id).ok_or(Error::NotFound)?;
if dst_declared == declared {
value
} else {
@@ -294,8 +298,7 @@ pub fn set_value_at_time_command(
move || {
let mut g = lock_any(&project_undo);
if let Some(e) = g.graph.get_mut(node) {
e.core
.set_standard_value(&input_undo, element, old.clone());
e.core.set_standard_value(&input_undo, element, old.clone());
}
},
)