mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Polish user-created subgraph nodes: imports in the Properties panel; reorder/delete/rename imports/exports (#2105)
* Remove imports/exports * WIP: Autogenerated properties * WIP: Input based properties * WIP: Hashmap based input overrides * Migrate noise pattern node to input properties * Reorder exports * Continue migrating properties * WIP: Improve reorder exports * Automatically populate all input properties for sub networks * Complete reorder import and export * Add widget override to node macro * Migrate assign colors to input based properties * WIP: Full node property override * Node based properties override for proto nodes * Migrate all node properties to be input based * Rename imports/exports * improve UI * Protonode input valid implementations * Valid type list * Small formatting fixes * Polishing small issues * Document upgrade * fix tests * Upgrade noise pattern node * remove console log * Fix upgrade script for Noise Pattern * Improve the Properties panel representation for graphical data * Re-export demo art * Code review * code review improvements * Cleanup for node properties overrides * Reexport demo art * Fix clippy lints --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -146,6 +146,14 @@ pub enum FrontendMessage {
|
||||
UpdateGraphViewOverlay {
|
||||
open: bool,
|
||||
},
|
||||
UpdateImportReorderIndex {
|
||||
#[serde(rename = "importIndex")]
|
||||
index: Option<usize>,
|
||||
},
|
||||
UpdateExportReorderIndex {
|
||||
#[serde(rename = "exportIndex")]
|
||||
index: Option<usize>,
|
||||
},
|
||||
UpdateLayerWidths {
|
||||
#[serde(rename = "layerWidths")]
|
||||
layer_widths: HashMap<NodeId, u32>,
|
||||
|
||||
@@ -194,7 +194,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
||||
}
|
||||
DocumentMessage::PropertiesPanel(message) => {
|
||||
let properties_panel_message_handler_data = PropertiesPanelMessageHandlerData {
|
||||
network_interface: &self.network_interface,
|
||||
network_interface: &mut self.network_interface,
|
||||
selection_network_path: &self.selection_network_path,
|
||||
document_name: self.name.as_str(),
|
||||
executor,
|
||||
@@ -391,6 +391,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
||||
self.selection_network_path.clone_from(&self.breadcrumb_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(DocumentMessage::ZoomCanvasToFitAll);
|
||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
||||
}
|
||||
DocumentMessage::Escape => {
|
||||
if self.node_graph_handler.drag_start.is_some() {
|
||||
@@ -1007,7 +1008,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
||||
}
|
||||
responses.add(PropertiesPanelMessage::Refresh);
|
||||
responses.add(NodeGraphMessage::UpdateLayerPanel);
|
||||
responses.add(NodeGraphMessage::UpdateInSelectedNetwork)
|
||||
responses.add(NodeGraphMessage::UpdateInSelectedNetwork);
|
||||
}
|
||||
DocumentMessage::SetBlendModeForSelectedLayers { blend_mode } => {
|
||||
for layer in self.network_interface.selected_nodes(&[]).unwrap().selected_layers_except_artboards(&self.network_interface) {
|
||||
@@ -1018,6 +1019,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
||||
self.graph_fade_artwork_percentage = percentage;
|
||||
responses.add(FrontendMessage::UpdateGraphFadeArtwork { percentage });
|
||||
}
|
||||
|
||||
DocumentMessage::SetNodePinned { node_id, pinned } => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(NodeGraphMessage::SetPinned { node_id, pinned });
|
||||
@@ -1224,21 +1226,13 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
||||
.navigation_handler
|
||||
.calculate_offset_transform(ipp.viewport_bounds.center(), &network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz);
|
||||
self.network_interface.set_transform(transform, &self.breadcrumb_network_path);
|
||||
let imports = self.network_interface.frontend_imports(&self.breadcrumb_network_path).unwrap_or_default();
|
||||
let exports = self.network_interface.frontend_exports(&self.breadcrumb_network_path).unwrap_or_default();
|
||||
let add_import = self.network_interface.frontend_import_modify(&self.breadcrumb_network_path);
|
||||
let add_export = self.network_interface.frontend_export_modify(&self.breadcrumb_network_path);
|
||||
|
||||
responses.add(DocumentMessage::RenderRulers);
|
||||
responses.add(DocumentMessage::RenderScrollbars);
|
||||
responses.add(NodeGraphMessage::UpdateEdges);
|
||||
responses.add(NodeGraphMessage::UpdateBoxSelection);
|
||||
responses.add(FrontendMessage::UpdateImportsExports {
|
||||
imports,
|
||||
exports,
|
||||
add_import,
|
||||
add_export,
|
||||
});
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
|
||||
responses.add(FrontendMessage::UpdateNodeGraphTransform {
|
||||
transform: Transform {
|
||||
scale: transform.matrix2.x_axis.x,
|
||||
@@ -1465,26 +1459,22 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
|
||||
pub fn deserialize_document(serialized_content: &str) -> Result<Self, EditorError> {
|
||||
let document_message_handler = serde_json::from_str::<OldDocumentMessageHandler>(serialized_content)
|
||||
.map_or_else(
|
||||
|_| serde_json::from_str::<DocumentMessageHandler>(serialized_content),
|
||||
|old_message_handler| {
|
||||
let default_document_message_handler = DocumentMessageHandler {
|
||||
network_interface: NodeNetworkInterface::from_old_network(old_message_handler.network),
|
||||
collapsed: old_message_handler.collapsed,
|
||||
commit_hash: old_message_handler.commit_hash,
|
||||
document_ptz: old_message_handler.document_ptz,
|
||||
document_mode: old_message_handler.document_mode,
|
||||
view_mode: old_message_handler.view_mode,
|
||||
overlays_visible: old_message_handler.overlays_visible,
|
||||
rulers_visible: old_message_handler.rulers_visible,
|
||||
graph_view_overlay_open: old_message_handler.graph_view_overlay_open,
|
||||
snapping_state: old_message_handler.snapping_state,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(default_document_message_handler)
|
||||
},
|
||||
)
|
||||
let document_message_handler = serde_json::from_str::<DocumentMessageHandler>(serialized_content)
|
||||
.or_else(|_| {
|
||||
serde_json::from_str::<OldDocumentMessageHandler>(serialized_content).map(|old_message_handler| DocumentMessageHandler {
|
||||
network_interface: NodeNetworkInterface::from_old_network(old_message_handler.network),
|
||||
collapsed: old_message_handler.collapsed,
|
||||
commit_hash: old_message_handler.commit_hash,
|
||||
document_ptz: old_message_handler.document_ptz,
|
||||
document_mode: old_message_handler.document_mode,
|
||||
view_mode: old_message_handler.view_mode,
|
||||
overlays_visible: old_message_handler.overlays_visible,
|
||||
rulers_visible: old_message_handler.rulers_visible,
|
||||
graph_view_overlay_open: old_message_handler.graph_view_overlay_open,
|
||||
snapping_state: old_message_handler.snapping_state,
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.map_err(|e| EditorError::DocumentDeserialization(e.to_string()))?;
|
||||
Ok(document_message_handler)
|
||||
}
|
||||
@@ -2089,7 +2079,7 @@ impl DocumentMessageHandler {
|
||||
/// Create a network interface with a single export
|
||||
fn default_document_network_interface() -> NodeNetworkInterface {
|
||||
let mut network_interface = NodeNetworkInterface::default();
|
||||
network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "".to_string(), &[]);
|
||||
network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "", &[]);
|
||||
network_interface
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_node_template();
|
||||
let image = resolve_document_node_type("Image")
|
||||
.expect("Image node does not exist")
|
||||
.node_template_input_override([Some(NodeInput::value(TaggedValue::ImageFrame(image_frame), false))]);
|
||||
.node_template_input_override([Some(NodeInput::value(TaggedValue::None, false)), Some(NodeInput::value(TaggedValue::ImageFrame(image_frame), false))]);
|
||||
|
||||
let image_id = NodeId::new();
|
||||
self.network_interface.insert_node(image_id, image, &[]);
|
||||
@@ -256,7 +256,11 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
let mut existing_node_id = None;
|
||||
for upstream_node in upstream.collect::<Vec<_>>() {
|
||||
// Check if this is the node we have been searching for.
|
||||
if self.network_interface.reference(&upstream_node, &[]).is_some_and(|node_reference| node_reference == reference) {
|
||||
if self
|
||||
.network_interface
|
||||
.reference(&upstream_node, &[])
|
||||
.is_some_and(|node_reference| *node_reference == Some(reference.to_string()))
|
||||
{
|
||||
existing_node_id = Some(upstream_node);
|
||||
break;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
use super::utility_types::Direction;
|
||||
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
|
||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeTemplate, OutputConnector};
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::{ImportOrExport, InputConnector, NodeTemplate, OutputConnector};
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
use glam::IVec2;
|
||||
@@ -58,8 +58,7 @@ pub enum NodeGraphMessage {
|
||||
EnterNestedNetwork,
|
||||
DuplicateSelectedNodes,
|
||||
ExposeInput {
|
||||
node_id: NodeId,
|
||||
input_index: usize,
|
||||
input_connector: InputConnector,
|
||||
new_exposed: bool,
|
||||
},
|
||||
InsertNode {
|
||||
@@ -98,6 +97,20 @@ pub enum NodeGraphMessage {
|
||||
shift: Key,
|
||||
},
|
||||
PrintSelectedNodeCoordinates,
|
||||
RemoveImport {
|
||||
import_index: usize,
|
||||
},
|
||||
RemoveExport {
|
||||
export_index: usize,
|
||||
},
|
||||
ReorderImport {
|
||||
start_index: usize,
|
||||
end_index: usize,
|
||||
},
|
||||
ReorderExport {
|
||||
start_index: usize,
|
||||
end_index: usize,
|
||||
},
|
||||
RunDocumentGraph,
|
||||
ForceRunDocumentGraph,
|
||||
SelectedNodesAdd {
|
||||
@@ -153,6 +166,14 @@ pub enum NodeGraphMessage {
|
||||
TogglePreviewImpl {
|
||||
node_id: NodeId,
|
||||
},
|
||||
SetImportExportName {
|
||||
name: String,
|
||||
index: ImportOrExport,
|
||||
},
|
||||
SetImportExportNameImpl {
|
||||
name: String,
|
||||
index: ImportOrExport,
|
||||
},
|
||||
ToggleSelectedAsLayersOrNodes,
|
||||
ToggleSelectedLocked,
|
||||
ToggleLocked {
|
||||
@@ -180,6 +201,7 @@ pub enum NodeGraphMessage {
|
||||
},
|
||||
UpdateEdges,
|
||||
UpdateBoxSelection,
|
||||
UpdateImportsExports,
|
||||
UpdateLayerPanel,
|
||||
UpdateNewNodeGraph,
|
||||
UpdateTypes {
|
||||
|
||||
@@ -71,6 +71,12 @@ pub struct NodeGraphMessageHandler {
|
||||
auto_panning: AutoPanning,
|
||||
/// The node to preview on mouse up if alt-clicked
|
||||
preview_on_mouse_up: Option<NodeId>,
|
||||
// The index of the import that is being moved
|
||||
reordering_import: Option<usize>,
|
||||
// The index of the export that is being moved
|
||||
reordering_export: Option<usize>,
|
||||
// The end index of the moved port
|
||||
end_index: Option<usize>,
|
||||
}
|
||||
|
||||
/// NodeGraphMessageHandler always modifies the network which the selected nodes are in. No GraphOperationMessages should be added here, since those messages will always affect the document network.
|
||||
@@ -99,8 +105,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![new_layer_id] });
|
||||
}
|
||||
NodeGraphMessage::AddImport => network_interface.add_import(graph_craft::document::value::TaggedValue::None, true, -1, String::new(), breadcrumb_network_path),
|
||||
NodeGraphMessage::AddExport => network_interface.add_export(graph_craft::document::value::TaggedValue::None, -1, String::new(), breadcrumb_network_path),
|
||||
NodeGraphMessage::AddImport => {
|
||||
network_interface.add_import(graph_craft::document::value::TaggedValue::None, true, -1, "", breadcrumb_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
}
|
||||
NodeGraphMessage::AddExport => {
|
||||
network_interface.add_export(graph_craft::document::value::TaggedValue::None, -1, "", breadcrumb_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
}
|
||||
NodeGraphMessage::Init => {
|
||||
responses.add(BroadcastMessage::SubscribeEvent {
|
||||
on: BroadcastEvent::SelectionChanged,
|
||||
@@ -298,35 +310,29 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
{
|
||||
return;
|
||||
};
|
||||
let Some(network) = network_interface.network(selection_network_path) else {
|
||||
log::error!("Could not get network in EnterNestedNetwork");
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(node) = network.nodes.get(&node_id) else { return };
|
||||
if let DocumentNodeImplementation::Network(_) = node.implementation {
|
||||
if let Some(DocumentNodeImplementation::Network(_)) = network_interface.implementation(&node_id, selection_network_path) {
|
||||
responses.add(DocumentMessage::EnterNestedNetwork { node_id });
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => {
|
||||
let Some(network) = network_interface.network(selection_network_path) else {
|
||||
NodeGraphMessage::ExposeInput { input_connector, new_exposed } => {
|
||||
let InputConnector::Node { node_id, input_index } = input_connector else {
|
||||
log::error!("Cannot expose/hide export");
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(node) = network.nodes.get(&node_id) else {
|
||||
let Some(node) = network_interface.document_node(&node_id, selection_network_path) else {
|
||||
log::error!("Could not find node {node_id} in NodeGraphMessage::ExposeInput");
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(mut input) = node.inputs.get(input_index).cloned() else {
|
||||
log::error!("Could not find input {input_index} in NodeGraphMessage::ExposeInput");
|
||||
return;
|
||||
};
|
||||
if let NodeInput::Value { exposed, .. } = &mut input {
|
||||
*exposed = new_exposed;
|
||||
} else {
|
||||
// TODO: Should network and node inputs be able to be hidden?
|
||||
log::error!("Could not hide/show input: {:?} since it is not NodeInput::Value", input);
|
||||
} else if !new_exposed {
|
||||
// If hiding an input that is not a value, then disconnect it. This will convert it to a value input.
|
||||
responses.add(NodeGraphMessage::DisconnectInput { input_connector });
|
||||
responses.add(NodeGraphMessage::ExposeInput { input_connector, new_exposed });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -336,6 +342,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
input_connector: InputConnector::node(node_id, input_index),
|
||||
input,
|
||||
});
|
||||
|
||||
responses.add(PropertiesPanelMessage::Refresh);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
}
|
||||
@@ -559,23 +566,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
|
||||
let node_graph_point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click);
|
||||
|
||||
let Some(modify_import_export) = network_interface.modify_import_export(selection_network_path) else {
|
||||
log::error!("Could not get modify import export in PointerDown");
|
||||
return;
|
||||
};
|
||||
|
||||
if modify_import_export.add_export.intersect_point_no_stroke(node_graph_point) {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::AddExport);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
return;
|
||||
} else if modify_import_export.add_import.intersect_point_no_stroke(node_graph_point) {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::AddImport);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
return;
|
||||
}
|
||||
|
||||
if network_interface
|
||||
.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Grip, selection_network_path)
|
||||
.is_some()
|
||||
@@ -651,6 +641,37 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(modify_import_export) = network_interface.modify_import_export(selection_network_path) else {
|
||||
log::error!("Could not get modify import export in PointerDown");
|
||||
return;
|
||||
};
|
||||
|
||||
if modify_import_export.add_import_export.clicked_input_port_from_point(node_graph_point).is_some() {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::AddExport);
|
||||
return;
|
||||
} else if modify_import_export.add_import_export.clicked_output_port_from_point(node_graph_point).is_some() {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::AddImport);
|
||||
return;
|
||||
} else if let Some(remove_import_index) = modify_import_export.remove_imports_exports.clicked_output_port_from_point(node_graph_point) {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::RemoveImport { import_index: remove_import_index });
|
||||
return;
|
||||
} else if let Some(remove_export_index) = modify_import_export.remove_imports_exports.clicked_input_port_from_point(node_graph_point) {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::RemoveExport { export_index: remove_export_index });
|
||||
return;
|
||||
} else if let Some(move_import_index) = modify_import_export.reorder_imports_exports.clicked_output_port_from_point(node_graph_point) {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
self.reordering_import = Some(move_import_index);
|
||||
return;
|
||||
} else if let Some(move_export_index) = modify_import_export.reorder_imports_exports.clicked_input_port_from_point(node_graph_point) {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
self.reordering_export = Some(move_export_index);
|
||||
return;
|
||||
}
|
||||
|
||||
self.selection_before_pointer_down = network_interface
|
||||
.selected_nodes(selection_network_path)
|
||||
.map(|selected_nodes| selected_nodes.selected_nodes().cloned().collect())
|
||||
@@ -881,6 +902,46 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
responses.add(NodeGraphMessage::ShiftSelectedNodesByAmount { graph_delta, rubber_band: true });
|
||||
} else if self.box_selection_start.is_some() {
|
||||
responses.add(NodeGraphMessage::UpdateBoxSelection);
|
||||
} else if self.reordering_import.is_some() {
|
||||
let Some(modify_import_export) = network_interface.modify_import_export(selection_network_path) else {
|
||||
log::error!("Could not get modify import export in PointerUp");
|
||||
return;
|
||||
};
|
||||
// Find the first import that is below the mouse position
|
||||
self.end_index = Some(
|
||||
modify_import_export
|
||||
.reorder_imports_exports
|
||||
.output_ports()
|
||||
.find_map(|(index, click_target)| {
|
||||
let Some(position) = click_target.bounding_box().map(|bbox| (bbox[0].y + bbox[1].y) / 2.) else {
|
||||
log::error!("Could not get bounding box for import: {index}");
|
||||
return None;
|
||||
};
|
||||
(position > point.y).then_some(*index)
|
||||
})
|
||||
.unwrap_or(modify_import_export.reorder_imports_exports.output_ports().count()),
|
||||
);
|
||||
responses.add(FrontendMessage::UpdateImportReorderIndex { index: self.end_index });
|
||||
} else if self.reordering_export.is_some() {
|
||||
let Some(modify_import_export) = network_interface.modify_import_export(selection_network_path) else {
|
||||
log::error!("Could not get modify import export in PointerUp");
|
||||
return;
|
||||
};
|
||||
// Find the first export that is below the mouse position
|
||||
self.end_index = Some(
|
||||
modify_import_export
|
||||
.reorder_imports_exports
|
||||
.input_ports()
|
||||
.find_map(|(index, click_target)| {
|
||||
let Some(position) = click_target.bounding_box().map(|bbox| (bbox[0].y + bbox[1].y) / 2.) else {
|
||||
log::error!("Could not get bounding box for export: {index}");
|
||||
return None;
|
||||
};
|
||||
(position > point.y).then_some(*index)
|
||||
})
|
||||
.unwrap_or(modify_import_export.reorder_imports_exports.input_ports().count()),
|
||||
);
|
||||
responses.add(FrontendMessage::UpdateExportReorderIndex { index: self.end_index });
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::PointerUp => {
|
||||
@@ -1129,15 +1190,34 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
}
|
||||
self.select_if_not_dragged = None;
|
||||
}
|
||||
|
||||
// End of reordering an import
|
||||
else if let (Some(moving_import), Some(end_index)) = (self.reordering_import, self.end_index) {
|
||||
responses.add(NodeGraphMessage::ReorderImport {
|
||||
start_index: moving_import,
|
||||
end_index,
|
||||
});
|
||||
responses.add(DocumentMessage::EndTransaction);
|
||||
}
|
||||
// End of reordering an export
|
||||
else if let (Some(moving_export), Some(end_index)) = (self.reordering_export, self.end_index) {
|
||||
responses.add(NodeGraphMessage::ReorderExport {
|
||||
start_index: moving_export,
|
||||
end_index,
|
||||
});
|
||||
responses.add(DocumentMessage::EndTransaction);
|
||||
}
|
||||
self.drag_start = None;
|
||||
self.begin_dragging = false;
|
||||
self.box_selection_start = None;
|
||||
self.wire_in_progress_from_connector = None;
|
||||
self.wire_in_progress_to_connector = None;
|
||||
self.reordering_export = None;
|
||||
self.reordering_import = None;
|
||||
responses.add(DocumentMessage::EndTransaction);
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
|
||||
responses.add(FrontendMessage::UpdateBox { box_selection: None })
|
||||
responses.add(FrontendMessage::UpdateBox { box_selection: None });
|
||||
responses.add(FrontendMessage::UpdateImportReorderIndex { index: None });
|
||||
responses.add(FrontendMessage::UpdateExportReorderIndex { index: None });
|
||||
}
|
||||
NodeGraphMessage::PointerOutsideViewport { shift } => {
|
||||
if self.drag_start.is_some() || self.box_selection_start.is_some() {
|
||||
@@ -1186,6 +1266,26 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
// }
|
||||
// }
|
||||
}
|
||||
NodeGraphMessage::RemoveImport { import_index: usize } => {
|
||||
network_interface.remove_import(usize, selection_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
NodeGraphMessage::RemoveExport { export_index: usize } => {
|
||||
network_interface.remove_export(usize, selection_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
NodeGraphMessage::ReorderImport { start_index, end_index } => {
|
||||
network_interface.reorder_import(start_index, end_index, selection_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
NodeGraphMessage::ReorderExport { start_index, end_index } => {
|
||||
network_interface.reorder_export(start_index, end_index, selection_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
NodeGraphMessage::RunDocumentGraph => {
|
||||
responses.add(PortfolioMessage::SubmitGraphRender { document_id, ignore_hash: false });
|
||||
}
|
||||
@@ -1230,16 +1330,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
let wires = Self::collect_wires(network_interface, breadcrumb_network_path);
|
||||
let nodes = self.collect_nodes(network_interface, breadcrumb_network_path);
|
||||
let (layer_widths, chain_widths, has_left_input_wire) = network_interface.collect_layer_widths(breadcrumb_network_path);
|
||||
let imports = network_interface.frontend_imports(breadcrumb_network_path).unwrap_or_default();
|
||||
let exports = network_interface.frontend_exports(breadcrumb_network_path).unwrap_or_default();
|
||||
let add_import = network_interface.frontend_import_modify(breadcrumb_network_path);
|
||||
let add_export = network_interface.frontend_export_modify(breadcrumb_network_path);
|
||||
responses.add(FrontendMessage::UpdateImportsExports {
|
||||
imports,
|
||||
exports,
|
||||
add_import,
|
||||
add_export,
|
||||
});
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
responses.add(FrontendMessage::UpdateNodeGraph { nodes, wires });
|
||||
responses.add(FrontendMessage::UpdateLayerWidths {
|
||||
layer_widths,
|
||||
@@ -1253,16 +1344,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
if graph_view_overlay_open {
|
||||
network_interface.set_grid_aligned_edges(DVec2::new(ipp.viewport_bounds.bottom_right.x - ipp.viewport_bounds.top_left.x, 0.), breadcrumb_network_path);
|
||||
// Send the new edges to the frontend
|
||||
let imports = network_interface.frontend_imports(breadcrumb_network_path).unwrap_or_default();
|
||||
let exports = network_interface.frontend_exports(breadcrumb_network_path).unwrap_or_default();
|
||||
let add_import = network_interface.frontend_import_modify(breadcrumb_network_path);
|
||||
let add_export = network_interface.frontend_export_modify(breadcrumb_network_path);
|
||||
responses.add(FrontendMessage::UpdateImportsExports {
|
||||
imports,
|
||||
exports,
|
||||
add_import,
|
||||
add_export,
|
||||
});
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::SetInputValue { node_id, input_index, value } => {
|
||||
@@ -1272,7 +1354,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
input,
|
||||
});
|
||||
responses.add(PropertiesPanelMessage::Refresh);
|
||||
if (!network_interface.reference(&node_id, selection_network_path).is_some_and(|reference| reference == "Imaginate") || input_index == 0)
|
||||
if (!network_interface
|
||||
.reference(&node_id, selection_network_path)
|
||||
.is_some_and(|reference| *reference == Some("Imaginate".to_string()))
|
||||
|| input_index == 0)
|
||||
&& network_interface.connected_to_output(&node_id, selection_network_path)
|
||||
{
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
@@ -1377,6 +1462,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
NodeGraphMessage::SetDisplayNameImpl { node_id, alias } => {
|
||||
network_interface.set_display_name(&node_id, alias, selection_network_path);
|
||||
}
|
||||
NodeGraphMessage::SetImportExportName { name, index } => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(NodeGraphMessage::SetImportExportNameImpl { name, index });
|
||||
responses.add(DocumentMessage::EndTransaction);
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
}
|
||||
NodeGraphMessage::SetImportExportNameImpl { name, index } => network_interface.set_import_export_name(name, index, breadcrumb_network_path),
|
||||
NodeGraphMessage::TogglePreview { node_id } => {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::TogglePreviewImpl { node_id });
|
||||
@@ -1427,13 +1519,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
let node_ids = selected_nodes.selected_nodes().cloned().collect::<Vec<_>>();
|
||||
|
||||
// If any of the selected nodes are pinned, unpin them all. Otherwise, pin them all.
|
||||
let pinned = !node_ids.iter().all(|node_id| {
|
||||
if let Some(node) = network_interface.node_metadata(node_id, breadcrumb_network_path) {
|
||||
node.persistent_metadata.pinned
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
let pinned = !node_ids.iter().all(|node_id| network_interface.is_pinned(node_id, breadcrumb_network_path));
|
||||
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
for node_id in &node_ids {
|
||||
@@ -1442,9 +1528,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids });
|
||||
}
|
||||
NodeGraphMessage::ToggleSelectedVisibility => {
|
||||
let Some(network) = network_interface.network(selection_network_path) else {
|
||||
return;
|
||||
};
|
||||
let Some(selected_nodes) = network_interface.selected_nodes(selection_network_path) else {
|
||||
log::error!("Could not get selected nodes in NodeGraphMessage::ToggleSelectedLocked");
|
||||
return;
|
||||
@@ -1452,7 +1535,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
let node_ids = selected_nodes.selected_nodes().cloned().collect::<Vec<_>>();
|
||||
|
||||
// If any of the selected nodes are hidden, show them all. Otherwise, hide them all.
|
||||
let visible = !node_ids.iter().all(|node_id| network.nodes.get(node_id).is_some_and(|node| node.visible));
|
||||
let visible = !node_ids.iter().all(|node_id| network_interface.is_visible(node_id, selection_network_path));
|
||||
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
for node_id in &node_ids {
|
||||
@@ -1461,16 +1544,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids });
|
||||
}
|
||||
NodeGraphMessage::ToggleVisibility { node_id } => {
|
||||
let Some(network) = network_interface.network(selection_network_path) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(node) = network.nodes.get(&node_id) else {
|
||||
log::error!("Cannot get node {node_id} in NodeGraphMessage::ToggleVisibility");
|
||||
return;
|
||||
};
|
||||
|
||||
let visible = !node.visible;
|
||||
let visible = !network_interface.is_visible(&node_id, selection_network_path);
|
||||
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id, visible });
|
||||
@@ -1552,6 +1626,32 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
responses.add(FrontendMessage::UpdateBox { box_selection })
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::UpdateImportsExports => {
|
||||
let imports = network_interface.frontend_imports(breadcrumb_network_path).unwrap_or_default();
|
||||
let exports = network_interface.frontend_exports(breadcrumb_network_path).unwrap_or_default();
|
||||
let add_import = network_interface
|
||||
.frontend_import_export_modify(
|
||||
|modify_import_export_click_target| modify_import_export_click_target.add_import_export.output_ports().collect::<Vec<_>>(),
|
||||
breadcrumb_network_path,
|
||||
)
|
||||
.into_iter()
|
||||
.next();
|
||||
let add_export = network_interface
|
||||
.frontend_import_export_modify(
|
||||
|modify_import_export_click_target| modify_import_export_click_target.add_import_export.input_ports().collect::<Vec<_>>(),
|
||||
breadcrumb_network_path,
|
||||
)
|
||||
.into_iter()
|
||||
.next();
|
||||
|
||||
responses.add(FrontendMessage::UpdateImportsExports {
|
||||
imports,
|
||||
exports,
|
||||
add_import,
|
||||
add_export,
|
||||
});
|
||||
}
|
||||
|
||||
NodeGraphMessage::UpdateLayerPanel => {
|
||||
Self::update_layer_panel(network_interface, selection_network_path, collapsed, responses);
|
||||
}
|
||||
@@ -1671,14 +1771,7 @@ impl NodeGraphMessageHandler {
|
||||
let has_selection = selected_nodes.has_selected_nodes();
|
||||
let selection_includes_layers = network_interface.selected_nodes(&[]).unwrap().selected_layers(network_interface.document_metadata()).count() > 0;
|
||||
let selection_all_locked = network_interface.selected_nodes(&[]).unwrap().selected_unlocked_layers(network_interface).count() == 0;
|
||||
let selection_all_visible = selected_nodes.selected_nodes().all(|id| {
|
||||
if let Some(node) = network.nodes.get(id) {
|
||||
node.visible
|
||||
} else {
|
||||
error!("Could not get node {id} in update_selection_action_buttons");
|
||||
true
|
||||
}
|
||||
});
|
||||
let selection_all_visible = selected_nodes.selected_nodes().all(|node_id| network_interface.is_visible(node_id, breadcrumb_network_path));
|
||||
|
||||
let mut widgets = vec![
|
||||
PopoverButton::new()
|
||||
@@ -1839,10 +1932,6 @@ impl NodeGraphMessageHandler {
|
||||
/// Collate the properties panel sections for a node graph
|
||||
pub fn collate_properties(context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
// If the selected nodes are in the document network, use the document network. Otherwise, use the nested network
|
||||
let Some(network) = context.network_interface.network(context.selection_network_path) else {
|
||||
warn!("No network in collate_properties");
|
||||
return Vec::new();
|
||||
};
|
||||
let Some(selected_nodes) = context.network_interface.selected_nodes(context.selection_network_path) else {
|
||||
warn!("No selected nodes in collate_properties");
|
||||
return Vec::new();
|
||||
@@ -1868,25 +1957,13 @@ impl NodeGraphMessageHandler {
|
||||
match layers.len() {
|
||||
// If no layers are selected, show properties for all selected nodes
|
||||
0 => {
|
||||
let selected_nodes = nodes
|
||||
.iter()
|
||||
.filter_map(|node_id| {
|
||||
network.nodes.get(node_id).map(|node| {
|
||||
let pinned = if let Some(node) = context.network_interface.node_metadata(node_id, context.selection_network_path) {
|
||||
node.persistent_metadata.pinned
|
||||
} else {
|
||||
error!("Could not get node {node_id} in collate_properties");
|
||||
false
|
||||
};
|
||||
|
||||
node_properties::generate_node_properties(node, *node_id, pinned, context)
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let selected_nodes = nodes.iter().map(|node_id| node_properties::generate_node_properties(*node_id, context)).collect::<Vec<_>>();
|
||||
if !selected_nodes.is_empty() {
|
||||
return selected_nodes;
|
||||
}
|
||||
|
||||
// TODO: Display properties for encapsulating node when no nodes are selected in a nested network
|
||||
// This may require store a separate path for the properties panel
|
||||
let mut properties = vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
@@ -1900,20 +1977,20 @@ impl NodeGraphMessageHandler {
|
||||
],
|
||||
}];
|
||||
|
||||
let Some(network) = context.network_interface.network(context.selection_network_path) else {
|
||||
warn!("No network in collate_properties");
|
||||
return Vec::new();
|
||||
};
|
||||
// And if no nodes are selected, show properties for all pinned nodes
|
||||
let pinned_node_properties = network
|
||||
.nodes
|
||||
.keys()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.iter()
|
||||
.filter_map(|(node_id, node)| {
|
||||
let pinned = if let Some(node) = context.network_interface.node_metadata(node_id, context.selection_network_path) {
|
||||
node.persistent_metadata.pinned
|
||||
} else {
|
||||
error!("Could not get node {node_id} in collate_properties");
|
||||
false
|
||||
};
|
||||
|
||||
if pinned {
|
||||
Some(node_properties::generate_node_properties(node, *node_id, pinned, context))
|
||||
.filter_map(|node_id| {
|
||||
if context.network_interface.is_pinned(node_id, context.selection_network_path) {
|
||||
Some(node_properties::generate_node_properties(*node_id, context))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -1983,17 +2060,9 @@ impl NodeGraphMessageHandler {
|
||||
!context.network_interface.is_layer(node_id, context.selection_network_path)
|
||||
}
|
||||
})
|
||||
.filter_map(|(_, node_id)| network.nodes.get(&node_id).map(|node| (node, node_id)))
|
||||
.map(|(node, node_id)| {
|
||||
let pinned = if let Some(node) = context.network_interface.node_metadata(&node_id, context.selection_network_path) {
|
||||
node.persistent_metadata.pinned
|
||||
} else {
|
||||
error!("Could not get node {node_id} in collate_properties");
|
||||
false
|
||||
};
|
||||
|
||||
node_properties::generate_node_properties(node, node_id, pinned, context)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.iter()
|
||||
.map(|(_, node_id)| node_properties::generate_node_properties(*node_id, context))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
layer_properties.extend(node_properties);
|
||||
@@ -2110,8 +2179,9 @@ impl NodeGraphMessageHandler {
|
||||
let inputs = frontend_inputs_lookup.remove(&node_id).unwrap_or_default();
|
||||
let mut inputs = inputs.into_iter().map(|input| {
|
||||
input.map(|input| FrontendGraphInput {
|
||||
data_type: FrontendGraphDataType::with_type(&input.ty),
|
||||
data_type: FrontendGraphDataType::displayed_type(&input.ty, &input.type_source),
|
||||
resolved_type: Some(format!("{:?} from {:?}", &input.ty, input.type_source)),
|
||||
valid_types: input.valid_types.iter().map(|ty| ty.to_string()).collect(),
|
||||
name: input.name.unwrap_or_else(|| input.ty.nested_type().to_string()),
|
||||
connected_to: input.output_connector,
|
||||
})
|
||||
@@ -2122,8 +2192,8 @@ impl NodeGraphMessageHandler {
|
||||
|
||||
let output_types = network_interface.output_types(&node_id, breadcrumb_network_path);
|
||||
let primary_output_type = output_types.first().cloned().flatten();
|
||||
let frontend_data_type = if let Some((output_type, _)) = &primary_output_type {
|
||||
FrontendGraphDataType::with_type(output_type)
|
||||
let frontend_data_type = if let Some((output_type, type_source)) = &primary_output_type {
|
||||
FrontendGraphDataType::displayed_type(output_type, type_source)
|
||||
} else {
|
||||
FrontendGraphDataType::General
|
||||
};
|
||||
@@ -2144,8 +2214,8 @@ impl NodeGraphMessageHandler {
|
||||
if index == 0 && network_interface.has_primary_output(&node_id, breadcrumb_network_path) {
|
||||
continue;
|
||||
}
|
||||
let frontend_data_type = if let Some((output_type, _)) = &exposed_output {
|
||||
FrontendGraphDataType::with_type(output_type)
|
||||
let frontend_data_type = if let Some((output_type, type_source)) = &exposed_output {
|
||||
FrontendGraphDataType::displayed_type(output_type, type_source)
|
||||
} else {
|
||||
FrontendGraphDataType::General
|
||||
};
|
||||
@@ -2203,7 +2273,7 @@ impl NodeGraphMessageHandler {
|
||||
.node_metadata(&node_id, breadcrumb_network_path)
|
||||
.is_some_and(|node_metadata| node_metadata.persistent_metadata.is_layer()),
|
||||
can_be_layer: can_be_layer_lookup.contains(&node_id),
|
||||
reference: network_interface.reference(&node_id, breadcrumb_network_path),
|
||||
reference: network_interface.reference(&node_id, breadcrumb_network_path).cloned().unwrap_or_default(),
|
||||
display_name: network_interface.frontend_display_name(&node_id, breadcrumb_network_path),
|
||||
primary_input,
|
||||
exposed_inputs,
|
||||
@@ -2273,7 +2343,7 @@ impl NodeGraphMessageHandler {
|
||||
|| (
|
||||
// Check if the last node in the chain has an exposed left input
|
||||
network_interface.upstream_flow_back_from_nodes(vec![node_id], &[], network_interface::FlowType::HorizontalFlow).last().is_some_and(|node_id|
|
||||
network_interface.network(&[]).unwrap().nodes.get(&node_id).map_or_else(||{log::error!("Could not get node {node_id} in update_layer_panel"); false}, |node| {
|
||||
network_interface.document_node(&node_id, &[]).map_or_else(||{log::error!("Could not get node {node_id} in update_layer_panel"); false}, |node| {
|
||||
if network_interface.is_layer(&node_id, &[]) {
|
||||
node.inputs.iter().filter(|input| input.is_exposed_to_frontend(true)).nth(1).is_some_and(|input| input.as_value().is_some())
|
||||
} else {
|
||||
@@ -2284,7 +2354,7 @@ impl NodeGraphMessageHandler {
|
||||
|
||||
let parents_visible = layer.ancestors(network_interface.document_metadata()).filter(|&ancestor| ancestor != layer).all(|layer| {
|
||||
if layer != LayerNodeIdentifier::ROOT_PARENT {
|
||||
network_interface.network(&[]).unwrap().nodes.get(&layer.to_node()).map(|node| node.visible).unwrap_or_default()
|
||||
network_interface.document_node(&layer.to_node(), &[]).map(|node| node.visible).unwrap_or_default()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@@ -2389,6 +2459,7 @@ struct InputLookup {
|
||||
name: Option<String>,
|
||||
ty: Type,
|
||||
type_source: TypeSource,
|
||||
valid_types: Vec<Type>,
|
||||
output_connector: Option<OutputConnector>,
|
||||
}
|
||||
|
||||
@@ -2412,8 +2483,10 @@ fn frontend_inputs_lookup(breadcrumb_network_path: &[NodeId], network_interface:
|
||||
}
|
||||
|
||||
// Get the name from the metadata here (since it also requires a reference to the `network_interface`)
|
||||
let name = network_interface.input_name(&node_id, index, breadcrumb_network_path);
|
||||
|
||||
let name = network_interface
|
||||
.input_name(&node_id, index, breadcrumb_network_path)
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|name| name.to_string());
|
||||
// Get the output connector that feeds into this input (done here as well for simplicity)
|
||||
let connector = OutputConnector::from_input(input);
|
||||
|
||||
@@ -2430,13 +2503,21 @@ fn frontend_inputs_lookup(breadcrumb_network_path: &[NodeId], network_interface:
|
||||
for (index, value) in value.iter_mut().enumerate() {
|
||||
// Skip not exposed inputs for efficiency
|
||||
let Some(value) = value else { continue };
|
||||
|
||||
// Resolve the type (done in a separate loop because it requires a mutable reference to the `network_interface`)
|
||||
let (ty, type_source) = network_interface.input_type(&InputConnector::node(node_id, index), breadcrumb_network_path);
|
||||
value.ty = ty;
|
||||
value.type_source = type_source;
|
||||
}
|
||||
}
|
||||
|
||||
for (&node_id, value) in frontend_inputs_lookup.iter_mut() {
|
||||
for (index, value) in value.iter_mut().enumerate() {
|
||||
// Skip not exposed inputs for efficiency
|
||||
let Some(value) = value else { continue };
|
||||
// Resolve the type (done in a separate loop because it requires a mutable reference to the `network_interface`)
|
||||
value.valid_types = network_interface.valid_input_types(&InputConnector::node(node_id, index), breadcrumb_network_path);
|
||||
}
|
||||
}
|
||||
frontend_inputs_lookup
|
||||
}
|
||||
|
||||
@@ -2462,6 +2543,9 @@ impl Default for NodeGraphMessageHandler {
|
||||
deselect_on_pointer_up: None,
|
||||
auto_panning: Default::default(),
|
||||
preview_on_mouse_up: None,
|
||||
reordering_export: None,
|
||||
reordering_import: None,
|
||||
end_index: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::NodeId;
|
||||
use graphene_core::Type;
|
||||
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, OutputConnector};
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, OutputConnector, TypeSource};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub enum FrontendGraphDataType {
|
||||
@@ -11,12 +11,12 @@ pub enum FrontendGraphDataType {
|
||||
Raster,
|
||||
VectorData,
|
||||
Number,
|
||||
Graphic,
|
||||
Group,
|
||||
Artboard,
|
||||
}
|
||||
|
||||
impl FrontendGraphDataType {
|
||||
pub fn with_type(input: &Type) -> Self {
|
||||
fn with_type(input: &Type) -> Self {
|
||||
match TaggedValue::from_type_or_none(input) {
|
||||
TaggedValue::Image(_) | TaggedValue::ImageFrame(_) => Self::Raster,
|
||||
TaggedValue::Subpaths(_) | TaggedValue::VectorData(_) => Self::VectorData,
|
||||
@@ -30,11 +30,18 @@ impl FrontendGraphDataType {
|
||||
| TaggedValue::F64Array4(_)
|
||||
| TaggedValue::VecF64(_)
|
||||
| TaggedValue::VecDVec2(_) => Self::Number,
|
||||
TaggedValue::GraphicGroup(_) | TaggedValue::GraphicElement(_) => Self::Graphic,
|
||||
TaggedValue::GraphicGroup(_) | TaggedValue::GraphicElement(_) => Self::Group,
|
||||
TaggedValue::ArtboardGroup(_) => Self::Artboard,
|
||||
_ => Self::General,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn displayed_type(input: &Type, type_source: &TypeSource) -> Self {
|
||||
match type_source {
|
||||
TypeSource::Error(_) | TypeSource::RandomProtonodeImplementation => Self::General,
|
||||
_ => Self::with_type(input),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
@@ -44,6 +51,8 @@ pub struct FrontendGraphInput {
|
||||
pub name: String,
|
||||
#[serde(rename = "resolvedType")]
|
||||
pub resolved_type: Option<String>,
|
||||
#[serde(rename = "validTypes")]
|
||||
pub valid_types: Vec<String>,
|
||||
#[serde(rename = "connectedTo")]
|
||||
pub connected_to: Option<OutputConnector>,
|
||||
}
|
||||
@@ -180,6 +189,8 @@ pub struct FrontendClickTargets {
|
||||
pub all_nodes_bounding_box: String,
|
||||
#[serde(rename = "importExportsBoundingBox")]
|
||||
pub import_exports_bounding_box: String,
|
||||
#[serde(rename = "modifyImportExport")]
|
||||
pub modify_import_export: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::messages::portfolio::document::utility_types::network_interface::Node
|
||||
use crate::node_graph_executor::NodeGraphExecutor;
|
||||
|
||||
pub struct PropertiesPanelMessageHandlerData<'a> {
|
||||
pub network_interface: &'a NodeNetworkInterface,
|
||||
pub network_interface: &'a mut NodeNetworkInterface,
|
||||
pub selection_network_path: &'a [NodeId],
|
||||
pub document_name: &'a str,
|
||||
pub executor: &'a mut NodeGraphExecutor,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -384,7 +384,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
document_serialized_content,
|
||||
} => {
|
||||
// It can be helpful to temporarily set `upgrade_from_before_editable_subgraphs` to true if it's desired to upgrade a piece of artwork to use fresh copies of all nodes
|
||||
let upgrade_from_before_editable_subgraphs = document_serialized_content.contains("node_output_index");
|
||||
let replace_implementations_from_definition = document_serialized_content.contains("node_output_index");
|
||||
let upgrade_vector_manipulation_format = document_serialized_content.contains("ManipulatorGroupIds") && !document_name.contains("__DO_NOT_UPGRADE__");
|
||||
let document_name = document_name.replace("__DO_NOT_UPGRADE__", "");
|
||||
|
||||
@@ -409,7 +409,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
// Upgrade all old nodes to support editable subgraphs introduced in #1750
|
||||
if upgrade_from_before_editable_subgraphs {
|
||||
if replace_implementations_from_definition {
|
||||
// This can be used, if uncommented, to upgrade demo artwork with outdated document node internals from their definitions. Delete when it's no longer needed.
|
||||
// Used for upgrading old internal networks for demo artwork nodes. Will reset all node internals for any opened file
|
||||
for node_id in &document
|
||||
@@ -614,6 +614,31 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
.network_interface
|
||||
.set_input(&InputConnector::node(NodeId(0), 1), NodeInput::value(TaggedValue::String(label), false), &[*node_id]);
|
||||
}
|
||||
|
||||
if reference == "Image" && inputs_count == 1 {
|
||||
let node_definition = crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type(reference).unwrap();
|
||||
let new_image_node = node_definition.default_node_template();
|
||||
document.network_interface.replace_implementation(node_id, &[], new_image_node.document_node.implementation);
|
||||
|
||||
// Insert a new empty input for the image
|
||||
document.network_interface.add_import(TaggedValue::None, false, 0, "Empty", &[*node_id]);
|
||||
document.network_interface.set_reference(node_id, &[], Some("Image".to_string()));
|
||||
}
|
||||
|
||||
if reference == "Noise Pattern" && inputs_count == 15 {
|
||||
let node_definition = crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type(reference).unwrap();
|
||||
let new_noise_pattern_node = node_definition.default_node_template();
|
||||
document.network_interface.replace_implementation(node_id, &[], new_noise_pattern_node.document_node.implementation);
|
||||
|
||||
let old_inputs = document.network_interface.replace_inputs(node_id, new_noise_pattern_node.document_node.inputs.clone(), &[]);
|
||||
|
||||
document
|
||||
.network_interface
|
||||
.set_input(&InputConnector::node(*node_id, 0), NodeInput::value(TaggedValue::None, false), &[]);
|
||||
for (i, input) in old_inputs.iter().enumerate() {
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, i + 1), input.clone(), &[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
|
||||
@@ -186,7 +186,7 @@ impl<'a> NodeGraphLayer<'a> {
|
||||
/// Node id of a node if it exists in the layer's primary flow
|
||||
pub fn upstream_node_id_from_name(&self, node_name: &str) -> Option<NodeId> {
|
||||
self.horizontal_layer_flow()
|
||||
.find(|node_id| self.network_interface.reference(node_id, &[]).is_some_and(|reference| reference == node_name))
|
||||
.find(|node_id| self.network_interface.reference(node_id, &[]).is_some_and(|reference| *reference == Some(node_name.to_string())))
|
||||
}
|
||||
|
||||
/// Find all of the inputs of a specific node within the layer's primary flow, up until the next layer is reached.
|
||||
@@ -194,7 +194,7 @@ impl<'a> NodeGraphLayer<'a> {
|
||||
self.horizontal_layer_flow()
|
||||
.skip(1)// Skip self
|
||||
.take_while(|node_id| !self.network_interface.is_layer(node_id,&[]))
|
||||
.find(|node_id| self.network_interface.reference(node_id,&[]).is_some_and(|reference| reference == node_name))
|
||||
.find(|node_id| self.network_interface.reference(node_id,&[]).is_some_and(|reference| *reference == Some(node_name.to_string())))
|
||||
.and_then(|node_id| self.network_interface.network(&[]).unwrap().nodes.get(&node_id).map(|node| &node.inputs))
|
||||
}
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ impl BrushToolData {
|
||||
let Some(reference) = document.network_interface.reference(&node_id, &[]) else {
|
||||
continue;
|
||||
};
|
||||
if reference == "Brush" && node_id != layer.to_node() {
|
||||
if *reference == Some("Brush".to_string()) && node_id != layer.to_node() {
|
||||
let points_input = node.inputs.get(2)?;
|
||||
let Some(TaggedValue::BrushStrokes(strokes)) = points_input.as_value() else {
|
||||
continue;
|
||||
@@ -285,7 +285,7 @@ impl BrushToolData {
|
||||
self.strokes.clone_from(strokes);
|
||||
|
||||
return Some(layer);
|
||||
} else if reference == "Transform" {
|
||||
} else if *reference == Some("Transform".to_string()) {
|
||||
let upstream = document.metadata().upstream_transform(node_id);
|
||||
let pivot = DAffine2::from_translation(upstream.transform_point2(get_current_normalized_pivot(&node.inputs)));
|
||||
self.transform = pivot * get_current_transform(&node.inputs) * pivot.inverse() * self.transform;
|
||||
|
||||
@@ -793,7 +793,10 @@ impl Fsm for PenToolFsmState {
|
||||
(_, PenToolMessage::Redo) => {
|
||||
tool_data.point_index = (tool_data.point_index + 1).min(tool_data.latest_points.len().saturating_sub(1));
|
||||
tool_data.place_anchor(SnapData::new(document, input), transform, input.mouse.position, responses);
|
||||
(tool_data.point_index == 0).then_some(PenToolFsmState::Ready).unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||
match tool_data.point_index {
|
||||
0 => PenToolFsmState::Ready,
|
||||
_ => PenToolFsmState::PlacingAnchor,
|
||||
}
|
||||
}
|
||||
_ => self,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user