Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::messages::portfolio::document::node_graph::utility_types::{ContextMen
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::GroupFolderType;
use crate::messages::portfolio::document::utility_types::network_interface::{
self, FlowType, InputConnector, NodeNetworkInterface, NodeTemplate, NodeTypePersistentMetadata, OutputConnector, Previewing,
self, FlowType, InputConnector, LayerPosition, NodeNetworkInterface, NodePosition, NodeTemplate, NodeTypePersistentMetadata, OutputConnector, Previewing,
};
use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerPanelEntry};
use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle, WirePath, WirePathUpdate, build_vector_wire};
Expand Down Expand Up @@ -763,7 +763,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
network_interface.set_chain_position(&node_id, selection_network_path);
}
NodeGraphMessage::PasteNodes { serialized_nodes } => {
let data = match serde_json::from_str::<Vec<(NodeId, NodeTemplate)>>(&serialized_nodes) {
let mut data = match serde_json::from_str::<Vec<(NodeId, NodeTemplate)>>(&serialized_nodes) {
Ok(d) => d,
Err(e) => {
warn!("Invalid node data {e:?}");
Expand All @@ -774,6 +774,48 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
return;
}

// Get network path of node overlay
let Some(network_metadata) = network_interface.network_metadata(breadcrumb_network_path) else {
log::error!("Could not get network metadata in PasteNodes");
return;
};

let cursor_viewport_location = ipp.mouse.position;
let cursor_to_node_graph = network_metadata
.persistent_metadata
.navigation_metadata
.node_graph_to_viewport
.inverse()
.transform_point2(cursor_viewport_location);

// Sort the selected nodes by the new id so that we know which node was selected first
data.sort_by_key(|a| a.0);

// Get position of the first node selected for copying that has an absolute position. Calculate paste offset from the cursor
// If no nodes with absolute position, then there is no offset from cursor
let copy_position_opt = data.iter().find_map(|(_, template)| match &template.persistent_node_metadata.node_type_metadata {
NodeTypePersistentMetadata::Layer(layer_metadata) => {
if let LayerPosition::Absolute(position) = &layer_metadata.position {
Some(position)
} else {
None
}
}
NodeTypePersistentMetadata::Node(node_metadata) => {
if let NodePosition::Absolute(position) = node_metadata.position() {
Some(position)
} else {
None
}
}
});

let copy_position = copy_position_opt.copied().unwrap_or_default();
let graph_delta = IVec2::new(
((cursor_to_node_graph.x / GRID_SIZE as f64).round()) as i32 - copy_position.x,
((cursor_to_node_graph.y / GRID_SIZE as f64).round()) as i32 - copy_position.y,
);

responses.add(DocumentMessage::AddTransaction);

let new_ids: HashMap<_, _> = data.iter().map(|(id, _)| (*id, NodeId::new())).collect();
Expand All @@ -782,7 +824,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
nodes: data,
new_ids: new_ids.clone(),
});
responses.add(NodeGraphMessage::SelectedNodesSet { nodes })
responses.add(NodeGraphMessage::SelectedNodesSet { nodes });

// Shift nodes based on offset
responses.add(NodeGraphMessage::ShiftSelectedNodesByAmount { graph_delta, rubber_band: true })
}
NodeGraphMessage::PointerDown {
shift_click,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6712,6 +6712,10 @@ impl NodePersistentMetadata {
pub fn new(position: NodePosition) -> Self {
Self { position }
}

pub fn position(&self) -> &NodePosition {
&self.position
}
}

/// A layer can either be position as Absolute or in a Stack
Expand Down