multicam: wizard + AFV + node-graph preview + performance
- wizard: angle multi-select, sync modes, auto-align, create sequence; keeps the host sequence current (host clip = the multicam clip) - build_multicam_sequence: per-angle clip -> SOURCES_INPUT[element], array slot growth, audio angle tracks for AFV - AFV: host linked audio clip follows the switched source (one undo), muted host audio track disables it - node-graph preview: inline producer renders through the traverser (viewer/project-matched graph frames); sequence viewer uses the graph - multicam node value(): element-tagged row keys (sources_in[i]), reads the current source; build_row keys array inputs by element - angle grid: viewer=0 (single-track montage, not whole-graph) - project explorer: rename (dialog) + delete (undoable) real items - performance: decoded-frame LRU, per-process NVDEC quota (1 session, evict before open), GPU composite fail-once fallback, snapshot upload debounced on the engine tick, worker vram budget headroom - timeline clip: multicam overlay via ClipDecorator - wizard menu item moved to Sequence menu
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
//! `src/node/src/input/multicam/multicamnode.{h,cpp}`,
|
||||
//! `olive::MultiCamNode`).
|
||||
|
||||
use std::any::Any;
|
||||
use crate::factory::NodeMeta;
|
||||
use crate::id::NodeId;
|
||||
use crate::node::{Category, NodeBehavior, NodeCore};
|
||||
@@ -256,14 +257,12 @@ impl NodeBehavior for MultiCamNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate outputs (C++ `value()`): pushes the first value of the
|
||||
/// `sources_in` value array (which, per
|
||||
/// `active_elements_at_time`, is the currently selected source);
|
||||
/// pushes nothing when the array is empty.
|
||||
///
|
||||
/// The Rust row carries no array payload (the `sources_in` value is
|
||||
/// the single active element), so the connected value is pushed
|
||||
/// through as-is; when the input is absent nothing is pushed.
|
||||
/// Evaluate outputs (C++ `value()`): pushes the ARRAY element of
|
||||
/// `sources_in` selected by `current_in` (the current source) — the
|
||||
/// traverser stores array elements under `{input}[{element}]` keys
|
||||
/// ([`crate::traverser`]), so the selected source's texture is the
|
||||
/// value at `sources_in[source]`. A missing element (or an absent
|
||||
/// array) pushes nothing.
|
||||
fn value(
|
||||
&self,
|
||||
core: &NodeCore,
|
||||
@@ -271,7 +270,19 @@ impl NodeBehavior for MultiCamNode {
|
||||
time: Rational,
|
||||
table: &mut NodeValueTable,
|
||||
) {
|
||||
let _ = (core, time);
|
||||
let _ = time;
|
||||
let source = core.standard_value(CURRENT_INPUT, -1).to_double() as i32;
|
||||
let key = if source >= 0 {
|
||||
format!("{SOURCES_INPUT}[{source}]")
|
||||
} else {
|
||||
SOURCES_INPUT.to_string()
|
||||
};
|
||||
if let Some(v) = inputs.get(&key) {
|
||||
table.push(v.value_type(), v.clone(), None);
|
||||
return;
|
||||
}
|
||||
// Fallback: an unindexed source value (single-source wiring from
|
||||
// before the element-tagged rows).
|
||||
if let Some(v) = inputs.get(SOURCES_INPUT) {
|
||||
table.push(v.value_type(), v.clone(), None);
|
||||
}
|
||||
|
||||
@@ -254,6 +254,11 @@ fn build_row(
|
||||
// which elements are live at this time (C++
|
||||
// `GetActiveElementsAtTime` — a track pulls only the blocks
|
||||
// covering the frame). An empty answer means "no restriction".
|
||||
// Element-tagged keys: an array input's per-element values coexist
|
||||
// in the row under `{input}[{element}]` (C++ `GetValueAtTime`
|
||||
// indexes the array; the multi-cam node reads exactly the element
|
||||
// of its current source — a plain `id` key would collapse the
|
||||
// array to its last element).
|
||||
if conns.iter().any(|(_, e)| *e >= 0) {
|
||||
let active = entry.behavior.active_elements_at_time(id, time);
|
||||
if !active.is_empty() {
|
||||
@@ -271,7 +276,12 @@ fn build_row(
|
||||
.get(&(from, upstream_time))
|
||||
.map(|t| pick_value(t, entry.core.input_data_type(id)))
|
||||
.unwrap_or(NodeValue::None);
|
||||
row.insert(id.to_string(), value);
|
||||
let key = if element >= 0 {
|
||||
format!("{id}[{element}]")
|
||||
} else {
|
||||
id.to_string()
|
||||
};
|
||||
row.insert(key, value);
|
||||
}
|
||||
}
|
||||
row
|
||||
|
||||
Reference in New Issue
Block a user