Group nodes
This commit is contained in:
parent
ffe7799b6a
commit
0bd933fd45
|
|
@ -1426,6 +1426,34 @@ impl Engine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Command::GraphSetGroups(track_id, groups) => {
|
||||||
|
let graph = match self.project.get_track_mut(track_id) {
|
||||||
|
Some(TrackNode::Midi(track)) => Some(&mut track.instrument_graph),
|
||||||
|
Some(TrackNode::Audio(track)) => Some(&mut track.effects_graph),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(graph) = graph {
|
||||||
|
graph.set_frontend_groups(groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Command::GraphSetGroupsInTemplate(track_id, voice_allocator_id, groups) => {
|
||||||
|
use crate::audio::node_graph::nodes::VoiceAllocatorNode;
|
||||||
|
let graph = match self.project.get_track_mut(track_id) {
|
||||||
|
Some(TrackNode::Midi(track)) => Some(&mut track.instrument_graph),
|
||||||
|
Some(TrackNode::Audio(track)) => Some(&mut track.effects_graph),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(graph) = graph {
|
||||||
|
let node_idx = NodeIndex::new(voice_allocator_id as usize);
|
||||||
|
if let Some(graph_node) = graph.get_node_mut(node_idx) {
|
||||||
|
if let Some(va_node) = graph_node.as_any_mut().downcast_mut::<VoiceAllocatorNode>() {
|
||||||
|
va_node.template_graph_mut().set_frontend_groups(groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Command::GraphSavePreset(track_id, preset_path, preset_name, description, tags) => {
|
Command::GraphSavePreset(track_id, preset_path, preset_name, description, tags) => {
|
||||||
let graph = match self.project.get_track(track_id) {
|
let graph = match self.project.get_track(track_id) {
|
||||||
Some(TrackNode::Midi(track)) => Some(&track.instrument_graph),
|
Some(TrackNode::Midi(track)) => Some(&track.instrument_graph),
|
||||||
|
|
@ -3029,6 +3057,16 @@ impl EngineController {
|
||||||
let _ = self.command_tx.push(Command::GraphSetOutputNode(track_id, node_id));
|
let _ = self.command_tx.push(Command::GraphSetOutputNode(track_id, node_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set frontend-only group definitions on a track's graph
|
||||||
|
pub fn graph_set_groups(&mut self, track_id: TrackId, groups: Vec<crate::audio::node_graph::preset::SerializedGroup>) {
|
||||||
|
let _ = self.command_tx.push(Command::GraphSetGroups(track_id, groups));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set frontend-only group definitions on a VA template graph
|
||||||
|
pub fn graph_set_groups_in_template(&mut self, track_id: TrackId, voice_allocator_id: u32, groups: Vec<crate::audio::node_graph::preset::SerializedGroup>) {
|
||||||
|
let _ = self.command_tx.push(Command::GraphSetGroupsInTemplate(track_id, voice_allocator_id, groups));
|
||||||
|
}
|
||||||
|
|
||||||
/// Save the current graph as a preset
|
/// Save the current graph as a preset
|
||||||
pub fn graph_save_preset(&mut self, track_id: TrackId, preset_path: String, preset_name: String, description: String, tags: Vec<String>) {
|
pub fn graph_save_preset(&mut self, track_id: TrackId, preset_path: String, preset_name: String, description: String, tags: Vec<String>) {
|
||||||
let _ = self.command_tx.push(Command::GraphSavePreset(track_id, preset_path, preset_name, description, tags));
|
let _ = self.command_tx.push(Command::GraphSavePreset(track_id, preset_path, preset_name, description, tags));
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,9 @@ pub struct AudioGraph {
|
||||||
|
|
||||||
/// Cached topological sort order (invalidated on graph mutation)
|
/// Cached topological sort order (invalidated on graph mutation)
|
||||||
topo_cache: Option<Vec<NodeIndex>>,
|
topo_cache: Option<Vec<NodeIndex>>,
|
||||||
|
|
||||||
|
/// Frontend-only group definitions (stored opaquely for persistence)
|
||||||
|
frontend_groups: Vec<crate::audio::node_graph::preset::SerializedGroup>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioGraph {
|
impl AudioGraph {
|
||||||
|
|
@ -117,6 +120,7 @@ impl AudioGraph {
|
||||||
node_positions: std::collections::HashMap::new(),
|
node_positions: std::collections::HashMap::new(),
|
||||||
playback_time: 0.0,
|
playback_time: 0.0,
|
||||||
topo_cache: None,
|
topo_cache: None,
|
||||||
|
frontend_groups: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -645,6 +649,10 @@ impl AudioGraph {
|
||||||
self.graph.node_weight(idx).map(|n| &*n.node)
|
self.graph.node_weight(idx).map(|n| &*n.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_node_mut(&mut self, idx: NodeIndex) -> Option<&mut (dyn AudioNode + 'static)> {
|
||||||
|
self.graph.node_weight_mut(idx).map(|n| &mut *n.node)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get oscilloscope data from a specific node
|
/// Get oscilloscope data from a specific node
|
||||||
pub fn get_oscilloscope_data(&self, idx: NodeIndex, sample_count: usize) -> Option<Vec<f32>> {
|
pub fn get_oscilloscope_data(&self, idx: NodeIndex, sample_count: usize) -> Option<Vec<f32>> {
|
||||||
self.get_node(idx).and_then(|node| node.get_oscilloscope_data(sample_count))
|
self.get_node(idx).and_then(|node| node.get_oscilloscope_data(sample_count))
|
||||||
|
|
@ -729,9 +737,17 @@ impl AudioGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clone frontend groups
|
||||||
|
new_graph.frontend_groups = self.frontend_groups.clone();
|
||||||
|
|
||||||
new_graph
|
new_graph
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set frontend-only group definitions (stored opaquely for persistence)
|
||||||
|
pub fn set_frontend_groups(&mut self, groups: Vec<crate::audio::node_graph::preset::SerializedGroup>) {
|
||||||
|
self.frontend_groups = groups;
|
||||||
|
}
|
||||||
|
|
||||||
/// Serialize the graph to a preset
|
/// Serialize the graph to a preset
|
||||||
pub fn to_preset(&self, name: impl Into<String>) -> crate::audio::node_graph::preset::GraphPreset {
|
pub fn to_preset(&self, name: impl Into<String>) -> crate::audio::node_graph::preset::GraphPreset {
|
||||||
use crate::audio::node_graph::preset::{GraphPreset, SerializedConnection, SerializedNode};
|
use crate::audio::node_graph::preset::{GraphPreset, SerializedConnection, SerializedNode};
|
||||||
|
|
@ -897,6 +913,9 @@ impl AudioGraph {
|
||||||
// Output node
|
// Output node
|
||||||
preset.output_node = self.output_node.map(|idx| idx.index() as u32);
|
preset.output_node = self.output_node.map(|idx| idx.index() as u32);
|
||||||
|
|
||||||
|
// Frontend groups (stored opaquely)
|
||||||
|
preset.groups = self.frontend_groups.clone();
|
||||||
|
|
||||||
preset
|
preset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1118,6 +1137,9 @@ impl AudioGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore frontend groups (stored opaquely)
|
||||||
|
graph.frontend_groups = preset.groups.clone();
|
||||||
|
|
||||||
Ok(graph)
|
Ok(graph)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,5 @@ pub mod preset;
|
||||||
|
|
||||||
pub use graph::{Connection, GraphNode, AudioGraph};
|
pub use graph::{Connection, GraphNode, AudioGraph};
|
||||||
pub use node_trait::{AudioNode, cv_input_or_default};
|
pub use node_trait::{AudioNode, cv_input_or_default};
|
||||||
pub use preset::{GraphPreset, PresetMetadata, SerializedConnection, SerializedNode};
|
pub use preset::{GraphPreset, PresetMetadata, SerializedConnection, SerializedNode, SerializedGroup, SerializedBoundaryConnection};
|
||||||
pub use types::{ConnectionError, NodeCategory, NodePort, Parameter, ParameterUnit, SignalType};
|
pub use types::{ConnectionError, NodeCategory, NodePort, Parameter, ParameterUnit, SignalType};
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,10 @@ pub struct GraphPreset {
|
||||||
|
|
||||||
/// Which node index is the audio output (None if not set)
|
/// Which node index is the audio output (None if not set)
|
||||||
pub output_node: Option<u32>,
|
pub output_node: Option<u32>,
|
||||||
|
|
||||||
|
/// Frontend-only group definitions (backend stores opaquely, does not interpret)
|
||||||
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
|
pub groups: Vec<SerializedGroup>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about the preset
|
/// Metadata about the preset
|
||||||
|
|
@ -121,6 +125,32 @@ pub struct SerializedNode {
|
||||||
pub sample_data: Option<SampleData>,
|
pub sample_data: Option<SampleData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serialized group definition (frontend-only visual grouping, stored opaquely by backend)
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SerializedGroup {
|
||||||
|
pub id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub member_nodes: Vec<u32>,
|
||||||
|
pub position: (f32, f32),
|
||||||
|
pub boundary_inputs: Vec<SerializedBoundaryConnection>,
|
||||||
|
pub boundary_outputs: Vec<SerializedBoundaryConnection>,
|
||||||
|
/// Parent group ID for nested groups (None = top-level group)
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parent_group_id: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialized boundary connection for group definitions
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SerializedBoundaryConnection {
|
||||||
|
pub external_node: u32,
|
||||||
|
pub external_port: usize,
|
||||||
|
pub internal_node: u32,
|
||||||
|
pub internal_port: usize,
|
||||||
|
pub port_name: String,
|
||||||
|
/// Signal type as string ("Audio", "Midi", "CV")
|
||||||
|
pub data_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// Serialized connection between nodes
|
/// Serialized connection between nodes
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct SerializedConnection {
|
pub struct SerializedConnection {
|
||||||
|
|
@ -152,6 +182,7 @@ impl GraphPreset {
|
||||||
connections: Vec::new(),
|
connections: Vec::new(),
|
||||||
midi_targets: Vec::new(),
|
midi_targets: Vec::new(),
|
||||||
output_node: None,
|
output_node: None,
|
||||||
|
groups: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,11 @@ pub enum Command {
|
||||||
/// Set which node is the audio output (track_id, node_index)
|
/// Set which node is the audio output (track_id, node_index)
|
||||||
GraphSetOutputNode(TrackId, u32),
|
GraphSetOutputNode(TrackId, u32),
|
||||||
|
|
||||||
|
/// Set frontend-only group definitions on a track's graph (track_id, serialized groups)
|
||||||
|
GraphSetGroups(TrackId, Vec<crate::audio::node_graph::preset::SerializedGroup>),
|
||||||
|
/// Set frontend-only group definitions on a VA template graph (track_id, voice_allocator_id, serialized groups)
|
||||||
|
GraphSetGroupsInTemplate(TrackId, u32, Vec<crate::audio::node_graph::preset::SerializedGroup>),
|
||||||
|
|
||||||
/// Save current graph as a preset (track_id, preset_path, preset_name, description, tags)
|
/// Save current graph as a preset (track_id, preset_path, preset_name, description, tags)
|
||||||
GraphSavePreset(TrackId, String, String, String, Vec<String>),
|
GraphSavePreset(TrackId, String, String, String, Vec<String>),
|
||||||
/// Load a preset into a track's graph (track_id, preset_path)
|
/// Load a preset into a track's graph (track_id, preset_path)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@ name = "accesskit"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99"
|
checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99"
|
||||||
|
dependencies = [
|
||||||
|
"enumn",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "accesskit_atspi_common"
|
name = "accesskit_atspi_common"
|
||||||
|
|
@ -145,6 +149,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"serde",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
@ -1798,6 +1803,7 @@ checksum = "71ddb8ac7643d1dba1bb02110e804406dd459a838efcb14011ced10556711a8e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"emath",
|
"emath",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1851,6 +1857,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"profiling",
|
"profiling",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
@ -1943,9 +1951,9 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "egui_node_graph2"
|
name = "egui_node_graph2"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "git+https://github.com/PVDoriginal/egui_node_graph2#a25a90822d8f9c956e729f3907aad98f59fa46bc"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"egui",
|
"egui",
|
||||||
|
"serde",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
|
|
@ -1964,6 +1972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32"
|
checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2022,6 +2031,17 @@ dependencies = [
|
||||||
"syn 2.0.110",
|
"syn 2.0.110",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enumn"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.110",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "epaint"
|
name = "epaint"
|
||||||
version = "0.33.3"
|
version = "0.33.3"
|
||||||
|
|
@ -2038,6 +2058,7 @@ dependencies = [
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"profiling",
|
"profiling",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3411,6 +3432,7 @@ dependencies = [
|
||||||
name = "lightningbeam-core"
|
name = "lightningbeam-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arboard",
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|
@ -5293,6 +5315,19 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bitflags 2.10.0",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roxmltree"
|
name = "roxmltree"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
|
|
@ -5629,6 +5664,7 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
|
checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"serde",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ pub struct GraphResponse<UserResponse: UserResponseTrait, NodeData: NodeDataTrai
|
||||||
pub cursor_in_editor: bool,
|
pub cursor_in_editor: bool,
|
||||||
/// Is the mouse currently hovering the node finder?
|
/// Is the mouse currently hovering the node finder?
|
||||||
pub cursor_in_finder: bool,
|
pub cursor_in_finder: bool,
|
||||||
|
/// Screen-space rects of all rendered nodes (for hit-testing)
|
||||||
|
pub node_rects: NodeRects,
|
||||||
}
|
}
|
||||||
impl<UserResponse: UserResponseTrait, NodeData: NodeDataTrait> Default
|
impl<UserResponse: UserResponseTrait, NodeData: NodeDataTrait> Default
|
||||||
for GraphResponse<UserResponse, NodeData>
|
for GraphResponse<UserResponse, NodeData>
|
||||||
|
|
@ -89,6 +91,7 @@ impl<UserResponse: UserResponseTrait, NodeData: NodeDataTrait> Default
|
||||||
node_responses: Default::default(),
|
node_responses: Default::default(),
|
||||||
cursor_in_editor: false,
|
cursor_in_editor: false,
|
||||||
cursor_in_finder: false,
|
cursor_in_finder: false,
|
||||||
|
node_rects: NodeRects::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -507,8 +510,8 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
self.selected_nodes = node_rects
|
self.selected_nodes = node_rects
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter_map(|(node_id, rect)| {
|
.filter_map(|(&node_id, &rect)| {
|
||||||
if selection_rect.intersects(rect) {
|
if selection_rect.intersects(rect) {
|
||||||
Some(node_id)
|
Some(node_id)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -568,6 +571,7 @@ where
|
||||||
node_responses: delayed_responses,
|
node_responses: delayed_responses,
|
||||||
cursor_in_editor,
|
cursor_in_editor,
|
||||||
cursor_in_finder,
|
cursor_in_finder,
|
||||||
|
node_rects,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,4 +215,9 @@ impl GraphBackend for AudioGraphBackend {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn query_template_state(&self, voice_allocator_id: u32) -> Result<String, String> {
|
||||||
|
let mut controller = self.audio_controller.lock().unwrap();
|
||||||
|
controller.query_template_state(self.track_id, voice_allocator_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ pub trait GraphBackend: Send {
|
||||||
input_node: BackendNodeId,
|
input_node: BackendNodeId,
|
||||||
input_port: usize,
|
input_port: usize,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
|
/// Get the state of a VoiceAllocator's template graph as JSON
|
||||||
|
fn query_template_state(&self, voice_allocator_id: u32) -> Result<String, String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializable graph state (for presets and save/load)
|
/// Serializable graph state (for presets and save/load)
|
||||||
|
|
|
||||||
|
|
@ -863,7 +863,7 @@ impl NodeTemplateIter for AllNodeTemplates {
|
||||||
NodeTemplate::Oscilloscope,
|
NodeTemplate::Oscilloscope,
|
||||||
// Advanced
|
// Advanced
|
||||||
NodeTemplate::VoiceAllocator,
|
NodeTemplate::VoiceAllocator,
|
||||||
NodeTemplate::Group,
|
// Note: Group is not in the node finder — groups are created via Ctrl+G selection.
|
||||||
// Note: TemplateInput/TemplateOutput are excluded from the default finder.
|
// Note: TemplateInput/TemplateOutput are excluded from the default finder.
|
||||||
// They are added dynamically when editing inside a subgraph.
|
// They are added dynamically when editing inside a subgraph.
|
||||||
// Outputs
|
// Outputs
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue