Move all network metadata to node network

This commit is contained in:
Adam
2024-09-06 16:27:22 -07:00
parent 73a30368c0
commit de31dbfb19
5 changed files with 424 additions and 322 deletions
@@ -70,7 +70,7 @@ pub struct OldDocumentMessageHandler {
/// Sets whether or not the rulers should be drawn along the top and left edges of the viewport area. /// Sets whether or not the rulers should be drawn along the top and left edges of the viewport area.
pub rulers_visible: bool, pub rulers_visible: bool,
/// Sets whether or not the node graph is drawn (as an overlay) on top of the viewport area, or otherwise if it's hidden. /// Sets whether or not the node graph is drawn (as an overlay) on top of the viewport area, or otherwise if it's hidden.
pub graph_view_overlay_open: bool, pub graph_ui_open: bool,
/// The current user choices for snapping behavior, including whether snapping is enabled at all. /// The current user choices for snapping behavior, including whether snapping is enabled at all.
pub snapping_state: SnappingState, pub snapping_state: SnappingState,
} }
@@ -299,6 +299,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
} }
DocumentMessage::ClearLayersPanel => { DocumentMessage::ClearLayersPanel => {
// Send an empty layer list // Send an empty layer list
// TODO: Dont create a new document message handler just to get the default data buffer for an empty layer structure
let data_buffer: RawBuffer = Self::default().serialize_root(); let data_buffer: RawBuffer = Self::default().serialize_root();
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer }); responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer });
@@ -1326,7 +1327,7 @@ impl DocumentMessageHandler {
view_mode: old_message_handler.view_mode, view_mode: old_message_handler.view_mode,
overlays_visible: old_message_handler.overlays_visible, overlays_visible: old_message_handler.overlays_visible,
rulers_visible: old_message_handler.rulers_visible, rulers_visible: old_message_handler.rulers_visible,
graph_view_overlay_open: old_message_handler.graph_view_overlay_open, graph_view_overlay_open: old_message_handler.graph_ui_open,
snapping_state: old_message_handler.snapping_state, snapping_state: old_message_handler.snapping_state,
..Default::default() ..Default::default()
}; };
@@ -1979,7 +1980,7 @@ impl DocumentMessageHandler {
/// Create a network interface with a single export /// Create a network interface with a single export
fn default_document_network_interface() -> NodeNetworkInterface { fn default_document_network_interface() -> NodeNetworkInterface {
let mut network_interface = NodeNetworkInterface::default(); let mut network_interface = NodeNetworkInterface::default();
network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "".to_string(), &[]);
network_interface.insert_network_metadata(NodeNetworkPersistentMetadata::default(), &[]); network_interface.insert_network_metadata(NodeNetworkPersistentMetadata::default(), &[]);
network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "".to_string(), &[]);
network_interface network_interface
} }
@@ -7,8 +7,9 @@ use crate::messages::tool::common_functionality::graph_modification_utils;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork}; use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork};
use graph_craft::document::{InputConnector, OutputConnector, Previewing, RootNode, PTZ}; use graph_craft::document::{InputConnector, LayerOwner, NetworkEdgeDistance, OutputConnector, Ports, Previewing, RootNode, TransientMetadata, PTZ};
use graph_craft::{concrete, Type}; use graph_craft::{concrete, Type};
use graphene_std::memo::MemoHashGuard;
use graphene_std::renderer::{ClickTarget, Quad}; use graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::vector::{PointId, VectorData, VectorModificationType}; use graphene_std::vector::{PointId, VectorData, VectorModificationType};
use interpreted_executor::{dynamic_executor::ResolvedDocumentNodeTypes, node_registry::NODE_REGISTRY}; use interpreted_executor::{dynamic_executor::ResolvedDocumentNodeTypes, node_registry::NODE_REGISTRY};
@@ -24,6 +25,8 @@ pub struct NodeNetworkInterface {
/// The node graph that generates this document's artwork. It recursively stores its sub-graphs, so this root graph is the whole snapshot of the document content. /// The node graph that generates this document's artwork. It recursively stores its sub-graphs, so this root graph is the whole snapshot of the document content.
/// A public mutable reference should never be created. It should only be mutated through custom setters which perform the necessary side effects to keep network_metadata in sync /// A public mutable reference should never be created. It should only be mutated through custom setters which perform the necessary side effects to keep network_metadata in sync
network: NodeNetwork, network: NodeNetwork,
/// Stores all editor information for the document network as inputs to nodes. The node graph overlay nodes are added to this network.
metadata_network: NodeNetwork,
// TODO: Remove and store in node network with IDs based on Self::metadata_node_id // TODO: Remove and store in node network with IDs based on Self::metadata_node_id
/// Stores all editor information for a NodeNetwork. Should automatically kept in sync by the setter methods when changes to the document network are made. /// Stores all editor information for a NodeNetwork. Should automatically kept in sync by the setter methods when changes to the document network are made.
network_metadata: NodeNetworkMetadata, network_metadata: NodeNetworkMetadata,
@@ -39,8 +42,9 @@ pub struct NodeNetworkInterface {
transaction_status: TransactionStatus, transaction_status: TransactionStatus,
} }
//TODO: This could probably be merged into tagged values
// Enum to represent all metadata in the network, which can be used uniquely identify any stored value // Enum to represent all metadata in the network, which can be used uniquely identify any stored value
#[derive(Hash)] #[derive(Copy, Clone, Hash, Debug)]
pub enum MetadataType { pub enum MetadataType {
// Network persistent metadata // Network persistent metadata
Previewing, Previewing,
@@ -48,11 +52,11 @@ pub enum MetadataType {
SelectionUndoHistory, SelectionUndoHistory,
SelectionRedoHistory, SelectionRedoHistory,
// Network transient metadata // Network transient metadata
SelectedNodes,
StackDependents, StackDependents,
AllNodesBoundingBox, AllNodesBoundingBox,
OutwardWires, OutwardWires,
ImportExportPorts, ImportExportPorts,
RoundedNetworkEdgeDistance,
// Node persistent metadata // Node persistent metadata
Reference, Reference,
DisplayName, DisplayName,
@@ -69,7 +73,7 @@ pub enum MetadataType {
IsLayer, IsLayer,
} }
#[derive(Hash)] #[derive(Copy, Clone, Hash, Debug)]
pub enum NavigationMetadataType { pub enum NavigationMetadataType {
PTZ, PTZ,
NodeGraphToViewport, NodeGraphToViewport,
@@ -80,6 +84,7 @@ impl Clone for NodeNetworkInterface {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
network: self.network.clone(), network: self.network.clone(),
metadata_network: self.metadata_network.clone(),
network_metadata: self.network_metadata.clone(), network_metadata: self.network_metadata.clone(),
document_metadata: Default::default(), document_metadata: Default::default(),
resolved_types: Default::default(), resolved_types: Default::default(),
@@ -90,7 +95,7 @@ impl Clone for NodeNetworkInterface {
impl PartialEq for NodeNetworkInterface { impl PartialEq for NodeNetworkInterface {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.network == other.network && self.network_metadata == other.network_metadata self.network == other.network && self.metadata_network == other.metadata_network
} }
} }
@@ -101,6 +106,10 @@ impl NodeNetworkInterface {
self.network.nested_network(network_path) self.network.nested_network(network_path)
} }
pub fn metadata_network(&self, network_path: &[NodeId]) -> Option<&NodeNetwork> {
self.metadata_network.nested_network(network_path)
}
/// The network metadata should always exist for the current network /// The network metadata should always exist for the current network
pub fn network_metadata(&self, network_path: &[NodeId]) -> Option<&NodeNetworkMetadata> { pub fn network_metadata(&self, network_path: &[NodeId]) -> Option<&NodeNetworkMetadata> {
self.network_metadata.nested_metadata(network_path) self.network_metadata.nested_metadata(network_path)
@@ -504,7 +513,7 @@ impl NodeNetworkInterface {
fn metadata_value(&self, metadata: MetadataType, node_path: &[NodeId]) -> Option<&TaggedValue> { fn metadata_value(&self, metadata: MetadataType, node_path: &[NodeId]) -> Option<&TaggedValue> {
let node_id = Self::metadata_node_id(metadata, node_path); let node_id = Self::metadata_node_id(metadata, node_path);
let network = self.network(&[]).unwrap(); let network = self.metadata_network(&[]).unwrap();
let Some(node) = network.nodes.get(&node_id) else { let Some(node) = network.nodes.get(&node_id) else {
log::error!("Could not get node {node_id} in value_from_node_id"); log::error!("Could not get node {node_id} in value_from_node_id");
return None; return None;
@@ -512,6 +521,21 @@ impl NodeNetworkInterface {
node.inputs.first().expect("Metadata node should always have primary input to store data").as_value() node.inputs.first().expect("Metadata node should always have primary input to store data").as_value()
} }
/// Returns the MemoHashGuard, which much be dereferenced with .deref_mut() to access the mutable value
fn metadata_value_mut(&mut self, metadata: MetadataType, node_path: &[NodeId]) -> Option<MemoHashGuard<TaggedValue>> {
let network = self.metadata_network_mut(&[]).unwrap();
let metadata_node_id = Self::metadata_node_id(metadata, node_path);
let Some(metadata_node) = network.nodes.get_mut(&metadata_node_id) else {
log::error!("Could not get metadata {metadata:?} for node path {node_path:?} with id {metadata_node_id} in metadata_value_mut");
return None;
};
let Some(metadata_input) = metadata_node.inputs.get_mut(0) else {
log::error!("Could not get metadata input in metadata_value_mut");
return None;
};
metadata_input.as_value_mut()
}
/// Get the [`Type`] for any InputConnector /// Get the [`Type`] for any InputConnector
pub fn input_type(&self, input_connector: &InputConnector, network_path: &[NodeId]) -> Type { pub fn input_type(&self, input_connector: &InputConnector, network_path: &[NodeId]) -> Type {
// TODO: If the input_connector is a NodeInput::Value, return the type of the tagged value // TODO: If the input_connector is a NodeInput::Value, return the type of the tagged value
@@ -735,14 +759,13 @@ impl NodeNetworkInterface {
pub fn frontend_imports(&mut self, network_path: &[NodeId]) -> Option<Vec<(FrontendGraphOutput, i32, i32)>> { pub fn frontend_imports(&mut self, network_path: &[NodeId]) -> Option<Vec<(FrontendGraphOutput, i32, i32)>> {
self.import_export_ports(network_path).cloned().map(|import_export_ports| { self.import_export_ports(network_path).cloned().map(|import_export_ports| {
import_export_ports import_export_ports
.output_ports .output_ports()
.iter()
.filter_map(|(import_index, click_target)| { .filter_map(|(import_index, click_target)| {
// Get import name from parent node metadata input, which must match the number of imports. // Get import name from parent node metadata input, which must match the number of imports.
// Empty string means to use type, or "Import + index" if type can't be determined // Empty string means to use type, or "Import + index" if type can't be determined
let import_name = self let import_name = self
.encapsulating_node_metadata(network_path) .encapsulating_node_metadata(network_path)
.and_then(|encapsulating_metadata| encapsulating_metadata.persistent_metadata.input_names.get(*import_index).cloned()) .and_then(|encapsulating_metadata| encapsulating_metadata.persistent_metadata.input_names.get(import_index).cloned())
.unwrap_or_default(); .unwrap_or_default();
let mut import_metadata = None; let mut import_metadata = None;
@@ -751,14 +774,14 @@ impl NodeNetworkInterface {
let mut encapsulating_path = network_path.to_vec(); let mut encapsulating_path = network_path.to_vec();
let encapsulating_node_id = encapsulating_path.pop().unwrap(); let encapsulating_node_id = encapsulating_path.pop().unwrap();
let input_type = self.input_type(&InputConnector::node(encapsulating_node_id, *import_index), &encapsulating_path); let input_type = self.input_type(&InputConnector::node(encapsulating_node_id, import_index), &encapsulating_path);
let data_type = FrontendGraphDataType::with_type(&input_type); let data_type = FrontendGraphDataType::with_type(&input_type);
let import_name = if import_name.is_empty() { input_type.clone().nested_type().to_string() } else { import_name }; let import_name = if import_name.is_empty() { input_type.clone().nested_type().to_string() } else { import_name };
let connected_to = self let connected_to = self
.outward_wires(network_path) .outward_wires(network_path)
.and_then(|outward_wires| outward_wires.get(&OutputConnector::Import(*import_index))) .and_then(|outward_wires| outward_wires.get(&OutputConnector::Import(import_index)))
.cloned() .cloned()
.unwrap_or_else(|| { .unwrap_or_else(|| {
log::error!("Could not get OutputConnector::Import({import_index}) in outward wires"); log::error!("Could not get OutputConnector::Import({import_index}) in outward wires");
@@ -785,15 +808,14 @@ impl NodeNetworkInterface {
pub fn frontend_exports(&mut self, network_path: &[NodeId]) -> Option<Vec<(FrontendGraphInput, i32, i32)>> { pub fn frontend_exports(&mut self, network_path: &[NodeId]) -> Option<Vec<(FrontendGraphInput, i32, i32)>> {
self.import_export_ports(network_path).cloned().map(|import_export_ports| { self.import_export_ports(network_path).cloned().map(|import_export_ports| {
import_export_ports import_export_ports
.input_ports .input_ports()
.iter()
.filter_map(|(export_index, click_target)| { .filter_map(|(export_index, click_target)| {
let Some(network) = self.network(network_path) else { let Some(network) = self.network(network_path) else {
log::error!("Could not get network in frontend_exports"); log::error!("Could not get network in frontend_exports");
return None; return None;
}; };
let Some(export) = network.exports.get(*export_index) else { let Some(export) = network.exports.get(export_index) else {
log::error!("Could not get export {export_index} in frontend_exports"); log::error!("Could not get export {export_index} in frontend_exports");
return None; return None;
}; };
@@ -817,7 +839,7 @@ impl NodeNetworkInterface {
}; };
// First import index is visually connected to the root node instead of its actual export input so previewing does not change the connection // First import index is visually connected to the root node instead of its actual export input so previewing does not change the connection
let connected_to = if *export_index == 0 { let connected_to = if export_index == 0 {
self.root_node(network_path).map(|root_node| OutputConnector::node(root_node.node_id, root_node.output_index)) self.root_node(network_path).map(|root_node| OutputConnector::node(root_node.node_id, root_node.output_index))
} else if let NodeInput::Node { node_id, output_index, .. } = export { } else if let NodeInput::Node { node_id, output_index, .. } = export {
Some(OutputConnector::node(*node_id, *output_index)) Some(OutputConnector::node(*node_id, *output_index))
@@ -833,7 +855,7 @@ impl NodeNetworkInterface {
"Canvas".to_string() "Canvas".to_string()
} else { } else {
self.encapsulating_node_metadata(network_path) self.encapsulating_node_metadata(network_path)
.and_then(|encapsulating_metadata| encapsulating_metadata.persistent_metadata.output_names.get(*export_index).cloned()) .and_then(|encapsulating_metadata| encapsulating_metadata.persistent_metadata.output_names.get(export_index).cloned())
.unwrap_or_default() .unwrap_or_default()
}; };
@@ -1517,8 +1539,11 @@ impl NodeNetworkInterface {
nested_network_metadata.persistent_metadata.node_metadata.insert(node_id, node_metadata); nested_network_metadata.persistent_metadata.node_metadata.insert(node_id, node_metadata);
} }
} }
//TODO: Add metadata to this
let metadata_network = NodeNetwork::default();
Self { Self {
network: node_network, network: node_network,
metadata_network,
network_metadata, network_metadata,
document_metadata: DocumentMetadata::default(), document_metadata: DocumentMetadata::default(),
resolved_types: ResolvedDocumentNodeTypes::default(), resolved_types: ResolvedDocumentNodeTypes::default(),
@@ -1551,6 +1576,11 @@ impl NodeNetworkInterface {
self.network.nested_network_mut(network_path) self.network.nested_network_mut(network_path)
} }
fn metadata_network_mut(&mut self, network_path: &[NodeId]) -> Option<&mut NodeNetwork> {
self.metadata_network.nested_network_mut(network_path)
}
// TODO: Remove
fn network_metadata_mut(&mut self, network_path: &[NodeId]) -> Option<&mut NodeNetworkMetadata> { fn network_metadata_mut(&mut self, network_path: &[NodeId]) -> Option<&mut NodeNetworkMetadata> {
self.network_metadata.nested_metadata_mut(network_path) self.network_metadata.nested_metadata_mut(network_path)
} }
@@ -1568,15 +1598,15 @@ impl NodeNetworkInterface {
} }
/// Mutably get the network which the encapsulating node of the currently viewed network is part of. Will always be None in the document network. /// Mutably get the network which the encapsulating node of the currently viewed network is part of. Will always be None in the document network.
fn encapsulating_network_metadata_mut(&mut self, network_path: &[NodeId]) -> Option<&mut NodeNetworkMetadata> { // fn encapsulating_network_metadata_mut(&mut self, network_path: &[NodeId]) -> Option<&mut NodeNetworkMetadata> {
let mut encapsulating_path = network_path.to_vec(); // let mut encapsulating_path = network_path.to_vec();
encapsulating_path.pop()?; // encapsulating_path.pop()?;
let Some(parent_metadata) = self.network_metadata_mut(&encapsulating_path) else { // let Some(parent_metadata) = self.network_metadata_mut(&encapsulating_path) else {
log::error!("Could not get parent network in encapsulating_node_metadata"); // log::error!("Could not get parent network in encapsulating_node_metadata");
return None; // return None;
}; // };
Some(parent_metadata) // Some(parent_metadata)
} // }
/// Mutably get the node which encapsulates the currently viewed network. Will always be None in the document network. /// Mutably get the node which encapsulates the currently viewed network. Will always be None in the document network.
// fn encapsulating_node_mut(&mut self, network_path: &[NodeId]) -> Option<&mut DocumentNode> { // fn encapsulating_node_mut(&mut self, network_path: &[NodeId]) -> Option<&mut DocumentNode> {
@@ -1646,22 +1676,12 @@ impl NodeNetworkInterface {
} }
} }
let network = self.network_mut(&[]).unwrap(); let Some(mut value) = self.metadata_value_mut(MetadataType::SelectionUndoHistory, network_path) else {
let metadata_node_id = Self::metadata_node_id(MetadataType::SelectionUndoHistory, network_path); log::error!("Could not get tagged value in mutate_selected_nodes");
let Some(metadata_node) = network.nodes.get_mut(&metadata_node_id) else {
log::error!("Could not get metadata node with id {metadata_node_id} in set_metadata");
return;
};
let Some(metadata_input) = metadata_node.inputs.get_mut(0) else {
log::error!("Could not get metadata input in set_metadata");
return;
};
let Some(mut value) = metadata_input.as_value_mut() else {
log::error!("Could not get tagged value in set_metadata");
return; return;
}; };
let TaggedValue::SelectionHistory(selection_undo_history) = value.deref_mut() else { let TaggedValue::SelectionHistory(selection_undo_history) = value.deref_mut() else {
log::error!("Tagged value should be SelectionUndoHistory in set_metadata"); log::error!("Tagged value should be SelectionUndoHistory in mutate_selected_nodes");
return; return;
}; };
selection_undo_history.push_back(last_selection_state); selection_undo_history.push_back(last_selection_state);
@@ -1683,22 +1703,12 @@ impl NodeNetworkInterface {
self.mutate_selected_nodes(nodes, SelectionOperation::Set, network_path); self.mutate_selected_nodes(nodes, SelectionOperation::Set, network_path);
} }
pub fn remove_selection_history_step(&mut self, network_path: &[NodeId]) { pub fn remove_selection_history_step(&mut self, network_path: &[NodeId]) {
let network = self.network_mut(&[]).unwrap(); let Some(mut value) = self.metadata_value_mut(MetadataType::SelectionUndoHistory, network_path) else {
let metadata_node_id = Self::metadata_node_id(MetadataType::SelectionUndoHistory, network_path); log::error!("Could not get tagged value in remove_selection_history_step");
let Some(metadata_node) = network.nodes.get_mut(&metadata_node_id) else {
log::error!("Could not get metadata node with id {metadata_node_id} in set_metadata");
return;
};
let Some(metadata_input) = metadata_node.inputs.get_mut(0) else {
log::error!("Could not get metadata input in set_metadata");
return;
};
let Some(mut value) = metadata_input.as_value_mut() else {
log::error!("Could not get tagged value in set_metadata");
return; return;
}; };
let TaggedValue::SelectionHistory(selection_undo_history) = value.deref_mut() else { let TaggedValue::SelectionHistory(selection_undo_history) = value.deref_mut() else {
log::error!("Tagged value should be SelectionUndoHistory in set_metadata"); log::error!("Tagged value should be SelectionUndoHistory in remove_selection_history_step");
return; return;
}; };
selection_undo_history.pop_back(); selection_undo_history.pop_back();
@@ -1718,17 +1728,7 @@ impl NodeNetworkInterface {
SelectionDirection::Forward => (MetadataType::SelectionRedoHistory, MetadataType::SelectionUndoHistory), SelectionDirection::Forward => (MetadataType::SelectionRedoHistory, MetadataType::SelectionUndoHistory),
}; };
let network = self.network_mut(&[]).unwrap(); let Some(mut value) = self.metadata_value_mut(adding_to, network_path) else {
let metadata_node_id = Self::metadata_node_id(adding_to, network_path);
let Some(metadata_node) = network.nodes.get_mut(&metadata_node_id) else {
log::error!("Could not get metadata node with id {metadata_node_id} in selection_step");
return;
};
let Some(metadata_input) = metadata_node.inputs.get_mut(0) else {
log::error!("Could not get metadata input in selection_step");
return;
};
let Some(mut value) = metadata_input.as_value_mut() else {
log::error!("Could not get tagged value in selection_step"); log::error!("Could not get tagged value in selection_step");
return; return;
}; };
@@ -1738,17 +1738,7 @@ impl NodeNetworkInterface {
}; };
if let Some(selection_state) = selection_history.pop_back() { if let Some(selection_state) = selection_history.pop_back() {
drop(value); drop(value);
let network = self.network_mut(&[]).unwrap(); let Some(mut value) = self.metadata_value_mut(removing_from, network_path) else {
let metadata_node_id = Self::metadata_node_id(removing_from, network_path);
let Some(metadata_node) = network.nodes.get_mut(&metadata_node_id) else {
log::error!("Could not get metadata node with id {metadata_node_id} in selection_step");
return;
};
let Some(metadata_input) = metadata_node.inputs.get_mut(0) else {
log::error!("Could not get metadata input in selection_step");
return;
};
let Some(mut value) = metadata_input.as_value_mut() else {
log::error!("Could not get tagged value in selection_step"); log::error!("Could not get tagged value in selection_step");
return; return;
}; };
@@ -1766,23 +1756,23 @@ impl NodeNetworkInterface {
} }
fn try_load_stack_dependents(&mut self, network_path: &[NodeId]) { fn try_load_stack_dependents(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::StackDependents(stack_dependents)) = self.metadata_value(MetadataType::StackDependents, network_path) else {
log::error!("Could not get nested network_metadata in stack_dependents"); log::error!("Could not get nested network_metadata in stack_dependents");
return; return;
}; };
if !network_metadata.transient_metadata.stack_dependents.is_loaded() { if !stack_dependents.is_loaded() {
self.load_stack_dependents(network_path); self.load_stack_dependents(network_path);
} }
} }
fn try_get_stack_dependents(&self, network_path: &[NodeId]) -> Option<&HashMap<NodeId, LayerOwner>> { fn try_get_stack_dependents(&self, network_path: &[NodeId]) -> Option<&HashMap<NodeId, LayerOwner>> {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(stack_dependents) = self.metadata_value(MetadataType::StackDependents, network_path) else {
log::error!("Could not get nested network_metadata in try_get_stack_dependents"); log::error!("Could not get stack_dependents in try_get_stack_dependents");
return None; return None;
}; };
let TransientMetadata::Loaded(stack_dependents) = &network_metadata.transient_metadata.stack_dependents else { let TaggedValue::StackDependents(TransientMetadata::Loaded(stack_dependents)) = stack_dependents else {
log::error!("could not load stack_dependents"); log::error!("Could not get stack_dependents in try_get_stack_dependents");
return None; return None;
}; };
Some(stack_dependents) Some(stack_dependents)
@@ -1928,30 +1918,20 @@ impl NodeNetworkInterface {
} }
} }
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(MetadataType::StackDependents, TaggedValue::StackDependents(TransientMetadata::Loaded(stack_dependents)), network_path);
log::error!("Could not get current network in load_export_ports");
return;
};
network_metadata.transient_metadata.stack_dependents = TransientMetadata::Loaded(stack_dependents);
} }
pub fn unload_stack_dependents(&mut self, network_path: &[NodeId]) { pub fn unload_stack_dependents(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(MetadataType::StackDependents, TaggedValue::StackDependents(TransientMetadata::Unloaded), network_path)
log::error!("Could not get nested network_metadata in unload_stack_dependents");
return;
};
network_metadata.transient_metadata.stack_dependents.unload();
} }
/// Resets all the offsets for nodes with no LayerOwner when the drag ends /// Resets all the offsets for nodes with no LayerOwner when the drag ends
pub fn unload_stack_dependents_y_offset(&mut self, network_path: &[NodeId]) { pub fn unload_stack_dependents_y_offset(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { let Some(mut value) = self.metadata_value_mut(MetadataType::StackDependents, network_path) else {
log::error!("Could not get nested network_metadata in unload_stack_dependents_y_offset"); log::error!("Could not get stack_dependents in unload_stack_dependents_y_offset");
return; return;
}; };
if let TaggedValue::StackDependents(TransientMetadata::Loaded(stack_dependents)) = value.deref_mut() {
if let TransientMetadata::Loaded(stack_dependents) = &mut network_metadata.transient_metadata.stack_dependents {
for layer_owner in stack_dependents.values_mut() { for layer_owner in stack_dependents.values_mut() {
if let LayerOwner::None(offset) = layer_owner { if let LayerOwner::None(offset) = layer_owner {
*offset = 0; *offset = 0;
@@ -1961,22 +1941,18 @@ impl NodeNetworkInterface {
} }
pub fn import_export_ports(&mut self, network_path: &[NodeId]) -> Option<&Ports> { pub fn import_export_ports(&mut self, network_path: &[NodeId]) -> Option<&Ports> {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::ImportExportPorts(import_export_ports)) = self.metadata_value(MetadataType::ImportExportPorts, network_path) else {
log::error!("Could not get nested network_metadata in export_ports"); log::error!("Could not get nested network_metadata in export_ports");
return None; return None;
}; };
if !network_metadata.transient_metadata.import_export_ports.is_loaded() { if !import_export_ports.is_loaded() {
self.load_import_export_ports(network_path); self.load_import_export_ports(network_path);
} }
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::ImportExportPorts(TransientMetadata::Loaded(import_export_ports))) = self.metadata_value(MetadataType::ImportExportPorts, network_path) else {
log::error!("Could not get nested network_metadata in export_ports");
return None;
};
let TransientMetadata::Loaded(ports) = &network_metadata.transient_metadata.import_export_ports else {
log::error!("could not load import ports"); log::error!("could not load import ports");
return None; return None;
}; };
Some(ports) Some(import_export_ports)
} }
pub fn load_import_export_ports(&mut self, network_path: &[NodeId]) { pub fn load_import_export_ports(&mut self, network_path: &[NodeId]) {
@@ -2034,35 +2010,27 @@ impl NodeNetworkInterface {
for output_index in 0..self.number_of_displayed_imports(network_path) { for output_index in 0..self.number_of_displayed_imports(network_path) {
import_export_ports.insert_output_port_at_center(output_index, import_top_left + DVec2::new(0., output_index as f64 * 24.)); import_export_ports.insert_output_port_at_center(output_index, import_top_left + DVec2::new(0., output_index as f64 * 24.));
} }
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(
log::error!("Could not get current network in load_export_ports"); MetadataType::ImportExportPorts,
return; TaggedValue::ImportExportPorts(TransientMetadata::Loaded(import_export_ports)),
}; network_path,
);
network_metadata.transient_metadata.import_export_ports = TransientMetadata::Loaded(import_export_ports);
} }
fn unload_import_export_ports(&mut self, network_path: &[NodeId]) { fn unload_import_export_ports(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(MetadataType::ImportExportPorts, TaggedValue::ImportExportPorts(TransientMetadata::Unloaded), network_path);
log::error!("Could not get nested network_metadata in unload_export_ports");
return;
};
network_metadata.transient_metadata.import_export_ports.unload();
} }
pub fn rounded_network_edge_distance(&mut self, network_path: &[NodeId]) -> Option<&NetworkEdgeDistance> { pub fn rounded_network_edge_distance(&mut self, network_path: &[NodeId]) -> Option<&NetworkEdgeDistance> {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::RoundedNetworkEdgeDistance(rounded_network_edge_distance)) = self.metadata_value(MetadataType::RoundedNetworkEdgeDistance, network_path) else {
log::error!("Could not get nested network_metadata in rounded_network_edge_distance"); log::error!("Could not get nested network_metadata in rounded_network_edge_distance");
return None; return None;
}; };
if !network_metadata.transient_metadata.rounded_network_edge_distance.is_loaded() { if !rounded_network_edge_distance.is_loaded() {
self.load_rounded_network_edge_distance(network_path); self.load_rounded_network_edge_distance(network_path);
} }
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::RoundedNetworkEdgeDistance(TransientMetadata::Loaded(rounded_network_edge_distance))) = self.metadata_value(MetadataType::RoundedNetworkEdgeDistance, network_path)
log::error!("Could not get nested network_metadata in rounded_network_edge_distance"); else {
return None;
};
let TransientMetadata::Loaded(rounded_network_edge_distance) = &network_metadata.transient_metadata.rounded_network_edge_distance else {
log::error!("could not load import rounded_network_edge_distance"); log::error!("could not load import rounded_network_edge_distance");
return None; return None;
}; };
@@ -2101,19 +2069,19 @@ impl NodeNetworkInterface {
exports_to_edge_distance: rounded_viewport_exports_distance, exports_to_edge_distance: rounded_viewport_exports_distance,
imports_to_edge_distance: rounded_viewport_imports_distance, imports_to_edge_distance: rounded_viewport_imports_distance,
}; };
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(
log::error!("Could not get current network in load_export_ports"); MetadataType::RoundedNetworkEdgeDistance,
return; TaggedValue::RoundedNetworkEdgeDistance(TransientMetadata::Loaded(network_edge_distance)),
}; network_path,
network_metadata.transient_metadata.rounded_network_edge_distance = TransientMetadata::Loaded(network_edge_distance); );
} }
fn unload_rounded_network_edge_distance(&mut self, network_path: &[NodeId]) { fn unload_rounded_network_edge_distance(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(
log::error!("Could not get nested network_metadata in unload_export_ports"); MetadataType::RoundedNetworkEdgeDistance,
return; TaggedValue::RoundedNetworkEdgeDistance(TransientMetadata::Unloaded),
}; network_path,
network_metadata.transient_metadata.rounded_network_edge_distance.unload(); );
} }
fn owned_nodes(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&HashSet<NodeId>> { fn owned_nodes(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&HashSet<NodeId>> {
@@ -2128,31 +2096,28 @@ impl NodeNetworkInterface {
} }
pub fn all_nodes_bounding_box(&mut self, network_path: &[NodeId]) -> Option<&[DVec2; 2]> { pub fn all_nodes_bounding_box(&mut self, network_path: &[NodeId]) -> Option<&[DVec2; 2]> {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::AllNodesBoundingBox(all_nodes_bounding_box)) = self.metadata_value(MetadataType::AllNodesBoundingBox, network_path) else {
log::error!("Could not get nested network_metadata in all_nodes_bounding_box"); log::error!("Could not get nested network_metadata in all_nodes_bounding_box");
return None; return None;
}; };
if !all_nodes_bounding_box.is_loaded() {
if !network_metadata.transient_metadata.all_nodes_bounding_box.is_loaded() {
self.load_all_nodes_bounding_box(network_path); self.load_all_nodes_bounding_box(network_path);
} }
let network_metadata = self.network_metadata(network_path)?; let Some(TaggedValue::AllNodesBoundingBox(TransientMetadata::Loaded(all_nodes_bounding_box))) = self.metadata_value(MetadataType::AllNodesBoundingBox, network_path) else {
let TransientMetadata::Loaded(bounding_box) = &network_metadata.transient_metadata.all_nodes_bounding_box else {
log::error!("could not load all nodes bounding box"); log::error!("could not load all nodes bounding box");
return None; return None;
}; };
Some(bounding_box) Some(all_nodes_bounding_box)
} }
pub fn load_all_nodes_bounding_box(&mut self, network_path: &[NodeId]) { pub fn load_all_nodes_bounding_box(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(network) = self.network(network_path) else {
log::error!("Could not get nested network_metadata in load_all_nodes_bounding_box"); log::error!("Could not get nested network_metadata in load_all_nodes_bounding_box");
return; return;
}; };
let nodes = network_metadata.persistent_metadata.node_metadata.keys().copied().collect::<Vec<_>>(); let nodes = network.nodes.keys().copied().collect::<Vec<_>>();
let all_nodes_bounding_box = nodes let all_nodes_bounding_box = nodes
.iter() .iter()
@@ -2163,33 +2128,29 @@ impl NodeNetworkInterface {
.reduce(Quad::combine_bounds) .reduce(Quad::combine_bounds)
.unwrap_or([DVec2::new(0., 0.), DVec2::new(0., 0.)]); .unwrap_or([DVec2::new(0., 0.), DVec2::new(0., 0.)]);
let Some(network_metadata) = self.network_metadata_mut(network_path) else { return }; self.set_metadata(
MetadataType::AllNodesBoundingBox,
network_metadata.transient_metadata.all_nodes_bounding_box = TransientMetadata::Loaded(all_nodes_bounding_box); TaggedValue::AllNodesBoundingBox(TransientMetadata::Loaded(all_nodes_bounding_box)),
network_path,
);
} }
pub fn unload_all_nodes_bounding_box(&mut self, network_path: &[NodeId]) { pub fn unload_all_nodes_bounding_box(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(MetadataType::AllNodesBoundingBox, TaggedValue::AllNodesBoundingBox(TransientMetadata::Unloaded), network_path);
log::error!("Could not get nested network_metadata in unload_all_nodes_bounding_box"); self.set_metadata(MetadataType::ImportExportPorts, TaggedValue::ImportExportPorts(TransientMetadata::Unloaded), network_path);
return;
};
network_metadata.transient_metadata.all_nodes_bounding_box.unload();
network_metadata.transient_metadata.import_export_ports.unload();
} }
pub fn outward_wires(&mut self, network_path: &[NodeId]) -> Option<&HashMap<OutputConnector, Vec<InputConnector>>> { pub fn outward_wires(&mut self, network_path: &[NodeId]) -> Option<&HashMap<OutputConnector, Vec<InputConnector>>> {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(TaggedValue::OutwardWires(outward_wires)) = self.metadata_value(MetadataType::OutwardWires, network_path) else {
log::error!("Could not get nested network_metadata in outward_wires"); log::error!("Could not get nested network_metadata in outward_wires");
return None; return None;
}; };
if !network_metadata.transient_metadata.outward_wires.is_loaded() { if !outward_wires.is_loaded() {
self.load_outward_wires(network_path); self.load_outward_wires(network_path);
} }
let network_metadata = self.network_metadata(network_path)?; let Some(TaggedValue::OutwardWires(TransientMetadata::Loaded(outward_wires))) = self.metadata_value(MetadataType::OutwardWires, network_path) else {
let TransientMetadata::Loaded(outward_wires) = &network_metadata.transient_metadata.outward_wires else {
log::error!("could not load outward wires"); log::error!("could not load outward wires");
return None; return None;
}; };
@@ -2240,17 +2201,11 @@ impl NodeNetworkInterface {
} }
} }
let Some(network_metadata) = self.network_metadata_mut(network_path) else { return }; self.set_metadata(MetadataType::OutwardWires, TaggedValue::OutwardWires(TransientMetadata::Loaded(outward_wires)), network_path);
network_metadata.transient_metadata.outward_wires = TransientMetadata::Loaded(outward_wires);
} }
fn unload_outward_wires(&mut self, network_path: &[NodeId]) { fn unload_outward_wires(&mut self, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_metadata(MetadataType::OutwardWires, TaggedValue::OutwardWires(TransientMetadata::Unloaded), network_path);
log::error!("Could not get nested network_metadata in unload_outward_wires");
return;
};
network_metadata.transient_metadata.outward_wires.unload();
} }
pub fn layer_width(&mut self, node_id: &NodeId, network_path: &[NodeId]) -> Option<u32> { pub fn layer_width(&mut self, node_id: &NodeId, network_path: &[NodeId]) -> Option<u32> {
@@ -3164,9 +3119,11 @@ impl NodeNetworkInterface {
self.unload_outward_wires(network_path); self.unload_outward_wires(network_path);
// Update the outward wires and bounding box for all nodes in the encapsulating network // Update the outward wires and bounding box for all nodes in the encapsulating network
if let Some(encapsulating_network_metadata) = self.encapsulating_network_metadata_mut(network_path) { if network_path.len() > 1 {
encapsulating_network_metadata.transient_metadata.outward_wires.unload(); let mut encapsulating_network_path = network_path.to_vec();
encapsulating_network_metadata.transient_metadata.all_nodes_bounding_box.unload(); encapsulating_network_path.pop();
self.unload_outward_wires(&encapsulating_network_path);
self.unload_all_nodes_bounding_box(&encapsulating_network_path);
} }
// Update the click targets for the encapsulating node, if it exists. There is no encapsulating node if the network is the document network // Update the click targets for the encapsulating node, if it exists. There is no encapsulating node if the network is the document network
@@ -3216,9 +3173,11 @@ impl NodeNetworkInterface {
} }
// Update the internal network import ports and outwards connections (if has a network implementation) // Update the internal network import ports and outwards connections (if has a network implementation)
if let Some(internal_network) = &mut node_metadata.persistent_metadata.network_metadata { if node_metadata.persistent_metadata.network_metadata.is_some() {
internal_network.transient_metadata.import_export_ports.unload(); let mut internal_network_path = network_path.to_vec();
internal_network.transient_metadata.outward_wires.unload(); internal_network_path.push(*node_id);
self.unload_import_export_ports(&internal_network_path);
self.unload_outward_wires(&internal_network_path);
} }
// Update the click targets for the node // Update the click targets for the node
@@ -3545,6 +3504,8 @@ impl NodeNetworkInterface {
}; };
network.nodes.insert(node_id, node_template.document_node); network.nodes.insert(node_id, node_template.document_node);
// TODO: Remove this clone once the later usage is removed
self.insert_all_node_metadata(node_id, node_template.persistent_node_metadata.clone(), network_path);
self.transaction_modified(); self.transaction_modified();
let Some(network_metadata) = self.network_metadata_mut(network_path) else { let Some(network_metadata) = self.network_metadata_mut(network_path) else {
@@ -3635,7 +3596,15 @@ impl NodeNetworkInterface {
TaggedValue::SelectionHistory(persistent_metadata.selection_redo_history), TaggedValue::SelectionHistory(persistent_metadata.selection_redo_history),
network_path, network_path,
); );
// TODO: Add the rest of the network metadata nodes self.insert_node_metadata(MetadataType::StackDependents, TaggedValue::StackDependents(TransientMetadata::Unloaded), network_path);
self.insert_node_metadata(MetadataType::AllNodesBoundingBox, TaggedValue::AllNodesBoundingBox(TransientMetadata::Unloaded), network_path);
self.insert_node_metadata(MetadataType::OutwardWires, TaggedValue::OutwardWires(TransientMetadata::Unloaded), network_path);
self.insert_node_metadata(MetadataType::ImportExportPorts, TaggedValue::ImportExportPorts(TransientMetadata::Unloaded), network_path);
self.insert_node_metadata(
MetadataType::RoundedNetworkEdgeDistance,
TaggedValue::RoundedNetworkEdgeDistance(TransientMetadata::Unloaded),
network_path,
);
for (node_id, node_metadata) in persistent_metadata.node_metadata { for (node_id, node_metadata) in persistent_metadata.node_metadata {
self.insert_all_node_metadata(node_id, node_metadata.persistent_metadata, network_path); self.insert_all_node_metadata(node_id, node_metadata.persistent_metadata, network_path);
@@ -3645,8 +3614,8 @@ impl NodeNetworkInterface {
/// Adds a node for the metadata. TODO: Consider calling this in set_metadata if a metadata node cannot be found. /// Adds a node for the metadata. TODO: Consider calling this in set_metadata if a metadata node cannot be found.
fn insert_node_metadata(&mut self, metadata: MetadataType, tagged_value: TaggedValue, node_path: &[NodeId]) { fn insert_node_metadata(&mut self, metadata: MetadataType, tagged_value: TaggedValue, node_path: &[NodeId]) {
let metadata_node_id = Self::metadata_node_id(metadata, node_path); let metadata_node_id = Self::metadata_node_id(metadata, node_path);
let network = self.network_mut(&[]).unwrap(); log::debug!("Inserting metadata {metadata:?} for node {node_path:?} with id {metadata_node_id}");
log::debug!("Inserting metadata node with id {metadata_node_id}"); let network = self.metadata_network_mut(&[]).unwrap();
network.nodes.insert( network.nodes.insert(
metadata_node_id, metadata_node_id,
DocumentNode { DocumentNode {
@@ -3866,20 +3835,8 @@ impl NodeNetworkInterface {
// } // }
pub fn set_metadata(&mut self, metadata: MetadataType, tagged_value: TaggedValue, node_path: &[NodeId]) { pub fn set_metadata(&mut self, metadata: MetadataType, tagged_value: TaggedValue, node_path: &[NodeId]) {
let network = self.network_mut(&[]).unwrap(); let Some(mut value) = self.metadata_value_mut(metadata, node_path) else {
log::error!("Could not set tagged value {tagged_value:?} for metadata {metadata:?} and node {node_path:?} in set_metadata");
let metadata_node_id = Self::metadata_node_id(metadata, node_path);
let Some(metadata_node) = network.nodes.get_mut(&metadata_node_id) else {
log::error!("Could not get metadata node with id {metadata_node_id} in set_metadata");
return;
};
let Some(metadata_input) = metadata_node.inputs.get_mut(0) else {
log::error!("Could not get metadata input in set_metadata");
return;
};
let Some(mut value) = metadata_input.as_value_mut() else {
log::error!("Could not get tagged value in set_metadata");
return; return;
}; };
*value.deref_mut() = tagged_value; *value.deref_mut() = tagged_value;
@@ -4487,16 +4444,22 @@ impl NodeNetworkInterface {
shifted_nodes.insert(*node_id); shifted_nodes.insert(*node_id);
self.shift_node(node_id, IVec2::new(0, shift_sign), network_path); self.shift_node(node_id, IVec2::new(0, shift_sign), network_path);
let Some(network_metadata) = self.network_metadata_mut(network_path) else { let Some(mut value) = self.metadata_value_mut(MetadataType::StackDependents, network_path) else {
log::error!("Could not get nested network_metadata in export_ports"); log::error!("Could not get stack dependents in shift_selected_nodes");
continue; return;
}; };
if let TransientMetadata::Loaded(stack_dependents) = &mut network_metadata.transient_metadata.stack_dependents { let mut transaction_modified = false;
if let TaggedValue::StackDependents(TransientMetadata::Loaded(stack_dependents)) = value.deref_mut() {
if let Some(LayerOwner::None(offset)) = stack_dependents.get_mut(node_id) { if let Some(LayerOwner::None(offset)) = stack_dependents.get_mut(node_id) {
*offset += shift_sign; *offset += shift_sign;
self.transaction_modified(); transaction_modified = true;
}; };
}; };
drop(value);
if transaction_modified {
self.transaction_modified();
}
// Shift the upstream layer so that it stays in the same place // Shift the upstream layer so that it stays in the same place
if self.is_layer(node_id, network_path) { if self.is_layer(node_id, network_path) {
@@ -4592,11 +4555,11 @@ impl NodeNetworkInterface {
self.shift_node(node_id, IVec2::new(0, shift_sign), network_path); self.shift_node(node_id, IVec2::new(0, shift_sign), network_path);
let Some(network_metadata) = self.network_metadata_mut(network_path) else { let Some(mut stack_dependents_value) = self.metadata_value_mut(MetadataType::StackDependents, network_path) else {
log::error!("Could not get nested network_metadata in export_ports"); log::error!("Could not get nested network_metadata in export_ports");
return; return;
}; };
let TransientMetadata::Loaded(stack_dependents) = &mut network_metadata.transient_metadata.stack_dependents else { let TaggedValue::StackDependents(TransientMetadata::Loaded(stack_dependents)) = stack_dependents_value.deref_mut() else {
log::error!("Stack dependents should be loaded in vertical_shift_with_push"); log::error!("Stack dependents should be loaded in vertical_shift_with_push");
return; return;
}; };
@@ -4607,16 +4570,20 @@ impl NodeNetworkInterface {
&mut default_layer_owner &mut default_layer_owner
}); });
let mut transaction_modified = false;
match layer_owner { match layer_owner {
LayerOwner::None(offset) => { LayerOwner::None(offset) => {
*offset += shift_sign; *offset += shift_sign;
self.transaction_modified(); transaction_modified = true;
} }
LayerOwner::Layer(_) => { LayerOwner::Layer(_) => {
log::error!("Node being shifted with a push should not be owned"); log::error!("Node being shifted with a push should not be owned");
} }
} }
drop(stack_dependents_value);
if transaction_modified {
self.transaction_modified();
}
// Shift the upstream layer so that it stays in the same place // Shift the upstream layer so that it stays in the same place
if self.is_layer(node_id, network_path) { if self.is_layer(node_id, network_path) {
let upstream_layer = { let upstream_layer = {
@@ -5085,91 +5052,6 @@ impl<'a> Iterator for FlowIter<'a> {
} }
} }
#[derive(Debug, Clone)]
pub struct Ports {
input_ports: Vec<(usize, ClickTarget)>,
output_ports: Vec<(usize, ClickTarget)>,
}
impl Default for Ports {
fn default() -> Self {
Self::new()
}
}
impl Ports {
pub fn new() -> Ports {
Ports {
input_ports: Vec::new(),
output_ports: Vec::new(),
}
}
pub fn click_targets(&self) -> impl Iterator<Item = &ClickTarget> {
self.input_ports
.iter()
.map(|(_, click_target)| click_target)
.chain(self.output_ports.iter().map(|(_, click_target)| click_target))
}
pub fn insert_input_port_at_center(&mut self, input_index: usize, center: DVec2) {
let subpath = Subpath::new_ellipse(center - DVec2::new(8., 8.), center + DVec2::new(8., 8.));
self.input_ports.push((input_index, ClickTarget::new(subpath, 0.)));
}
pub fn insert_output_port_at_center(&mut self, output_index: usize, center: DVec2) {
let subpath = Subpath::new_ellipse(center - DVec2::new(8., 8.), center + DVec2::new(8., 8.));
self.output_ports.push((output_index, ClickTarget::new(subpath, 0.)));
}
fn insert_node_input(&mut self, input_index: usize, row_index: usize, node_top_left: DVec2) {
// The center of the click target is always 24 px down from the top left corner of the node
let center = node_top_left + DVec2::new(0., 24. + 24. * row_index as f64);
self.insert_input_port_at_center(input_index, center);
}
fn insert_node_output(&mut self, output_index: usize, row_index: usize, node_top_left: DVec2) {
// The center of the click target is always 24 px down from the top left corner of the node
let center = node_top_left + DVec2::new(5. * 24., 24. + 24. * row_index as f64);
self.insert_output_port_at_center(output_index, center);
}
fn insert_layer_input(&mut self, input_index: usize, node_top_left: DVec2) {
let center = if input_index == 0 {
node_top_left + DVec2::new(2. * 24., 24. * 2. + 8.)
} else {
node_top_left + DVec2::new(0., 24. * 1.)
};
self.insert_input_port_at_center(input_index, center);
}
fn insert_layer_output(&mut self, node_top_left: DVec2) {
// The center of the click target is always 24 px down from the top left corner of the node
let center = node_top_left + DVec2::new(2. * 24., -8.0);
self.insert_output_port_at_center(0, center);
}
pub fn clicked_input_port_from_point(&self, point: DVec2) -> Option<usize> {
self.input_ports.iter().find_map(|(port, click_target)| click_target.intersect_point_no_stroke(point).then_some(*port))
}
pub fn clicked_output_port_from_point(&self, point: DVec2) -> Option<usize> {
self.output_ports.iter().find_map(|(port, click_target)| click_target.intersect_point_no_stroke(point).then_some(*port))
}
pub fn input_port_position(&self, index: usize) -> Option<DVec2> {
self.input_ports
.get(index)
.and_then(|(_, click_target)| click_target.bounding_box().map(|bounds| bounds[0] + DVec2::new(8., 8.)))
}
pub fn output_port_position(&self, index: usize) -> Option<DVec2> {
self.output_ports
.get(index)
.and_then(|(_, click_target)| click_target.bounding_box().map(|bounds| bounds[0] + DVec2::new(8., 8.)))
}
}
/// All fields in NetworkMetadata should automatically be updated by using the network interface API. If a field is none then it should be calculated based on the network state. /// All fields in NetworkMetadata should automatically be updated by using the network interface API. If a field is none then it should be calculated based on the network state.
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)] #[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct NodeNetworkMetadata { pub struct NodeNetworkMetadata {
@@ -5236,25 +5118,6 @@ pub struct NodeNetworkPersistentMetadata {
pub selection_redo_history: VecDeque<Vec<NodeId>>, pub selection_redo_history: VecDeque<Vec<NodeId>>,
} }
/// This is the same as Option, but more clear in the context of having cached metadata either being loaded or unloaded
#[derive(Debug, Default, Clone)]
pub enum TransientMetadata<T> {
Loaded(T),
#[default]
Unloaded,
}
impl<T> TransientMetadata<T> {
/// Set the current transient metadata to unloaded
pub fn unload(&mut self) {
*self = TransientMetadata::Unloaded;
}
pub fn is_loaded(&self) -> bool {
matches!(self, TransientMetadata::Loaded(_))
}
}
/// If some network calculation is too slow to compute for every usage, cache the data here /// If some network calculation is too slow to compute for every usage, cache the data here
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct NodeNetworkTransientMetadata { pub struct NodeNetworkTransientMetadata {
@@ -5275,22 +5138,6 @@ pub struct NodeNetworkTransientMetadata {
pub rounded_network_edge_distance: TransientMetadata<NetworkEdgeDistance>, pub rounded_network_edge_distance: TransientMetadata<NetworkEdgeDistance>,
} }
#[derive(Debug, Clone)]
pub struct NetworkEdgeDistance {
/// The viewport pixel distance distance between the left edge of the node graph and the exports.
pub exports_to_edge_distance: DVec2,
/// The viewport pixel distance between the left edge of the node graph and the imports.
pub imports_to_edge_distance: DVec2,
}
#[derive(Debug, Clone)]
pub enum LayerOwner {
// Used to get the layer that should be shifted when there is a collision.
Layer(NodeId),
// The vertical offset of a node from the start of its shift. Should be reset when the drag ends.
None(i32),
}
/// Utility function for providing a default boolean value to serde. /// Utility function for providing a default boolean value to serde.
#[inline(always)] #[inline(always)]
fn return_true() -> bool { fn return_true() -> bool {
@@ -21,7 +21,7 @@ use std::fmt::Write;
use vello::*; use vello::*;
/// Represents a clickable target for the layer /// Represents a clickable target for the layer
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub struct ClickTarget { pub struct ClickTarget {
subpath: bezier_rs::Subpath<PointId>, subpath: bezier_rs::Subpath<PointId>,
stroke_width: f64, stroke_width: f64,
@@ -38,6 +38,10 @@ impl ClickTarget {
&self.subpath &self.subpath
} }
pub fn stroke_width(&self) -> f64 {
self.stroke_width
}
pub fn bounding_box(&self) -> Option<[DVec2; 2]> { pub fn bounding_box(&self) -> Option<[DVec2; 2]> {
self.bounding_box self.bounding_box
} }
+149 -3
View File
@@ -1,8 +1,10 @@
use crate::document::value::TaggedValue; use crate::document::value::TaggedValue;
use crate::proto::{ConstructionArgs, ProtoNetwork, ProtoNode, ProtoNodeInput}; use crate::proto::{ConstructionArgs, ProtoNetwork, ProtoNode, ProtoNodeInput};
use bezier_rs::Subpath;
use dyn_any::{DynAny, StaticType}; use dyn_any::{DynAny, StaticType};
use graphene_core::memo::MemoHashGuard; use graphene_core::memo::MemoHashGuard;
use graphene_core::renderer::ClickTarget;
pub use graphene_core::uuid::generate_uuid; pub use graphene_core::uuid::generate_uuid;
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type}; use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
@@ -73,7 +75,7 @@ pub enum OldNodeInput {
} }
// TODO: Eventually remove this (probably starting late 2024) // TODO: Eventually remove this (probably starting late 2024)
use serde::Deserialize; use serde::{Deserialize, Serialize};
fn deserialize_inputs<'de, D>(deserializer: D) -> Result<Vec<NodeInput>, D::Error> fn deserialize_inputs<'de, D>(deserializer: D) -> Result<Vec<NodeInput>, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
@@ -1381,7 +1383,7 @@ impl RootNode {
} }
/// Represents an input connector with index based on the [`DocumentNode::inputs`] index, not the visible input index /// Represents an input connector with index based on the [`DocumentNode::inputs`] index, not the visible input index
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type, Hash, DynAny)]
pub enum InputConnector { pub enum InputConnector {
#[serde(rename = "node")] #[serde(rename = "node")]
Node { Node {
@@ -1421,7 +1423,7 @@ impl InputConnector {
} }
/// Represents an output connector /// Represents an output connector
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type, DynAny)]
pub enum OutputConnector { pub enum OutputConnector {
#[serde(rename = "node")] #[serde(rename = "node")]
Node { Node {
@@ -1484,6 +1486,150 @@ impl PTZ {
} }
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Hash, DynAny)]
pub enum LayerOwner {
// Used to get the layer that should be shifted when there is a collision.
Layer(NodeId),
// The vertical offset of a node from the start of its shift. Should be reset when the drag ends.
None(i32),
}
#[derive(Debug, Clone, PartialEq, DynAny, serde::Serialize, serde::Deserialize)]
pub struct Ports {
#[serde(skip)]
input_ports: Vec<(usize, ClickTarget)>,
#[serde(skip)]
output_ports: Vec<(usize, ClickTarget)>,
}
impl Default for Ports {
fn default() -> Self {
Self::new()
}
}
impl Ports {
pub fn new() -> Ports {
Ports {
input_ports: Vec::new(),
output_ports: Vec::new(),
}
}
pub fn input_ports(&self) -> impl Iterator<Item = (usize, &ClickTarget)> {
self.input_ports.iter().map(|(index, click_target)| (*index, click_target))
}
pub fn output_ports(&self) -> impl Iterator<Item = (usize, &ClickTarget)> {
self.output_ports.iter().map(|(index, click_target)| (*index, click_target))
}
pub fn click_targets(&self) -> impl Iterator<Item = &ClickTarget> {
self.input_ports
.iter()
.map(|(_, click_target)| click_target)
.chain(self.output_ports.iter().map(|(_, click_target)| click_target))
}
pub fn insert_input_port_at_center(&mut self, input_index: usize, center: DVec2) {
let subpath = Subpath::new_ellipse(center - DVec2::new(8., 8.), center + DVec2::new(8., 8.));
self.input_ports.push((input_index, ClickTarget::new(subpath, 0.)));
}
pub fn insert_output_port_at_center(&mut self, output_index: usize, center: DVec2) {
let subpath = Subpath::new_ellipse(center - DVec2::new(8., 8.), center + DVec2::new(8., 8.));
self.output_ports.push((output_index, ClickTarget::new(subpath, 0.)));
}
pub fn insert_node_input(&mut self, input_index: usize, row_index: usize, node_top_left: DVec2) {
// The center of the click target is always 24 px down from the top left corner of the node
let center = node_top_left + DVec2::new(0., 24. + 24. * row_index as f64);
self.insert_input_port_at_center(input_index, center);
}
pub fn insert_node_output(&mut self, output_index: usize, row_index: usize, node_top_left: DVec2) {
// The center of the click target is always 24 px down from the top left corner of the node
let center = node_top_left + DVec2::new(5. * 24., 24. + 24. * row_index as f64);
self.insert_output_port_at_center(output_index, center);
}
pub fn insert_layer_input(&mut self, input_index: usize, node_top_left: DVec2) {
let center = if input_index == 0 {
node_top_left + DVec2::new(2. * 24., 24. * 2. + 8.)
} else {
node_top_left + DVec2::new(0., 24. * 1.)
};
self.insert_input_port_at_center(input_index, center);
}
pub fn insert_layer_output(&mut self, node_top_left: DVec2) {
// The center of the click target is always 24 px down from the top left corner of the node
let center = node_top_left + DVec2::new(2. * 24., -8.0);
self.insert_output_port_at_center(0, center);
}
pub fn clicked_input_port_from_point(&self, point: DVec2) -> Option<usize> {
self.input_ports.iter().find_map(|(port, click_target)| click_target.intersect_point_no_stroke(point).then_some(*port))
}
pub fn clicked_output_port_from_point(&self, point: DVec2) -> Option<usize> {
self.output_ports.iter().find_map(|(port, click_target)| click_target.intersect_point_no_stroke(point).then_some(*port))
}
pub fn input_port_position(&self, index: usize) -> Option<DVec2> {
self.input_ports
.get(index)
.and_then(|(_, click_target)| click_target.bounding_box().map(|bounds| bounds[0] + DVec2::new(8., 8.)))
}
pub fn output_port_position(&self, index: usize) -> Option<DVec2> {
self.output_ports
.get(index)
.and_then(|(_, click_target)| click_target.bounding_box().map(|bounds| bounds[0] + DVec2::new(8., 8.)))
}
}
/// This is the same as Option, but more clear in the context of having cached metadata either being loaded or unloaded
#[derive(Debug, Default, Clone, PartialEq, serde::Deserialize, Hash)]
pub enum TransientMetadata<T> {
Loaded(T),
#[default]
Unloaded,
}
unsafe impl<T: 'static> StaticType for TransientMetadata<T> {
type Static = TransientMetadata<T>;
}
// Ensure transient metadata is always serialized as Unloaded
impl<T> Serialize for TransientMetadata<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
// Always serialize as Unloaded
serializer.serialize_unit_variant("TransientMetadata", 1, "Unloaded")
}
}
impl<T> TransientMetadata<T> {
/// Set the current transient metadata to unloaded
pub fn unload(&mut self) {
*self = TransientMetadata::Unloaded;
}
pub fn is_loaded(&self) -> bool {
matches!(self, TransientMetadata::Loaded(_))
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, DynAny)]
pub struct NetworkEdgeDistance {
/// The viewport pixel distance distance between the left edge of the node graph and the exports.
pub exports_to_edge_distance: DVec2,
/// The viewport pixel distance between the left edge of the node graph and the imports.
pub imports_to_edge_distance: DVec2,
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
+106 -2
View File
@@ -1,4 +1,4 @@
use super::DocumentNode; use super::{DocumentNode, TransientMetadata};
use crate::document::NodeId; use crate::document::NodeId;
pub use crate::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod}; pub use crate::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod};
use crate::proto::{Any as DAny, FutureAny}; use crate::proto::{Any as DAny, FutureAny};
@@ -11,7 +11,7 @@ use graphene_core::{Color, MemoHash, Node, Type};
use dyn_any::DynAny; use dyn_any::DynAny;
pub use dyn_any::StaticType; pub use dyn_any::StaticType;
pub use glam::{DAffine2, DVec2, IVec2, UVec2}; pub use glam::{DAffine2, DVec2, IVec2, UVec2};
use std::collections::VecDeque; use std::collections::{HashMap, VecDeque};
use std::fmt::Display; use std::fmt::Display;
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -179,9 +179,16 @@ tagged_value! {
CentroidType(graphene_core::vector::misc::CentroidType), CentroidType(graphene_core::vector::misc::CentroidType),
BooleanOperation(graphene_core::vector::misc::BooleanOperation), BooleanOperation(graphene_core::vector::misc::BooleanOperation),
FontCache(Arc<graphene_core::text::FontCache>), FontCache(Arc<graphene_core::text::FontCache>),
// Persistent Network Metadata
Previewing(crate::document::Previewing), Previewing(crate::document::Previewing),
PTZ(crate::document::PTZ), PTZ(crate::document::PTZ),
SelectionHistory(VecDeque<Vec<NodeId>>), SelectionHistory(VecDeque<Vec<NodeId>>),
// Transient Network Metadata
StackDependents(TransientMetadata<HashMap<NodeId, crate::document::LayerOwner>>),
AllNodesBoundingBox(TransientMetadata<[DVec2; 2]>),
OutwardWires(TransientMetadata<HashMap<crate::document::OutputConnector, Vec<crate::document::InputConnector>>>),
ImportExportPorts(TransientMetadata<crate::document::Ports>),
RoundedNetworkEdgeDistance(TransientMetadata<crate::document::NetworkEdgeDistance>),
} }
impl TaggedValue { impl TaggedValue {
@@ -258,6 +265,10 @@ trait FakeHash {
fn hash<H: core::hash::Hasher>(&self, state: &mut H); fn hash<H: core::hash::Hasher>(&self, state: &mut H);
} }
mod fake_hash { mod fake_hash {
use std::collections::HashMap;
use crate::document::{InputConnector, OutputConnector, Ports, TransientMetadata};
use super::*; use super::*;
impl FakeHash for f64 { impl FakeHash for f64 {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
@@ -274,6 +285,22 @@ mod fake_hash {
self.to_cols_array().iter().for_each(|x| x.to_bits().hash(state)) self.to_cols_array().iter().for_each(|x| x.to_bits().hash(state))
} }
} }
// impl<K: FakeHash, V: FakeHash> FakeHash for HashMap<K, V> {
// fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
// self.iter().for_each(|(k, v)| {
// k.hash(state);
// v.hash(state);
// })
// }
// }
impl<K: Hash, V: Hash> FakeHash for HashMap<K, V> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.iter().for_each(|(k, v)| {
k.hash(state);
v.hash(state);
})
}
}
impl<X: FakeHash> FakeHash for Option<X> { impl<X: FakeHash> FakeHash for Option<X> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
if let Some(x) = self { if let Some(x) = self {
@@ -284,6 +311,16 @@ mod fake_hash {
} }
} }
} }
impl<X: FakeHash> FakeHash for TransientMetadata<X> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
if let TransientMetadata::Loaded(x) = self {
1.hash(state);
x.hash(state);
} else {
0.hash(state);
}
}
}
impl<X: FakeHash> FakeHash for Vec<X> { impl<X: FakeHash> FakeHash for Vec<X> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.len().hash(state); self.len().hash(state);
@@ -308,4 +345,71 @@ mod fake_hash {
self.zoom.hash(state); self.zoom.hash(state);
} }
} }
// impl FakeHash for Option<HashMap<NodeId, crate::document::LayerOwner>> {
// fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
// if let Some(x) = self {
// 1.hash(state);
// x.iter().for_each(|(k, v)| {
// k.hash(state);
// v.hash(state);
// });
// } else {
// 0.hash(state);
// }
// }
// }
// impl FakeHash for HashMap<crate::document::OutputConnector, Vec<crate::document::InputConnector>> {
// fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
// self.iter().for_each(|(k, v)| {
// k.hash(state);
// v.hash(state);
// });
// }
// }
impl FakeHash for OutputConnector {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
match self {
OutputConnector::Node { node_id, output_index } => {
0.hash(state);
node_id.hash(state);
output_index.hash(state);
}
OutputConnector::Import(import_index) => {
1.hash(state);
import_index.hash(state);
}
}
}
}
impl FakeHash for InputConnector {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
match self {
InputConnector::Node { node_id, input_index } => {
0.hash(state);
node_id.hash(state);
input_index.hash(state);
}
InputConnector::Export(export_index) => {
1.hash(state);
export_index.hash(state);
}
}
}
}
impl FakeHash for crate::document::NetworkEdgeDistance {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.exports_to_edge_distance.hash(state);
self.imports_to_edge_distance.hash(state);
}
}
impl FakeHash for Ports {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.input_ports.iter().chain(self.output_ports.iter()).for_each(|(index, click_target)| {
index.hash(state);
click_target.subpath().hash(state);
click_target.stroke_width().hash(state);
click_target.bounding_box().hash(state)
});
}
}
} }