Make Copy to Points and (Circular) Repeat and nodes output group data, and add flattening nodes (#2011)

* Output group from repeat, add flatten vector elements

* Fix tests

* Fix demo artwork

* Output group from copy to points, add repeat for graphic groups, fix editor freeze on render fail

* Restore painted dreams

* WIP: Fix demo artwork

* Fix demo artwork, add ungroup node

* Incorrect scaling

* fix test

* Fix demo art

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
adamgerhant
2024-10-14 12:39:28 -07:00
committed by GitHub
parent b028bbb8cc
commit e09f5ecaec
14 changed files with 346 additions and 158 deletions

View File

@@ -239,18 +239,28 @@ impl<'a> ModifyInputsContext<'a> {
// Gets the node id of a node with a specific reference that is upstream from the layer node, and creates it if it does not exist
pub fn existing_node_id(&mut self, reference: &'static str) -> Option<NodeId> {
// Start from the layer node or export
let node_id = self.get_output_layer().map_or(Vec::new(), |output_layer| vec![output_layer.to_node()]);
let output_layer = self.get_output_layer()?;
let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type();
let upstream = self.network_interface.upstream_flow_back_from_nodes(node_id, &[], network_interface::FlowType::HorizontalFlow);
let is_traversal_start = |node_id: NodeId| {
self.layer_node.map(|layer| layer.to_node()) == Some(node_id) || self.network_interface.network(&[]).unwrap().exports.iter().any(|export| export.as_node() == Some(node_id))
};
let upstream = self
.network_interface
.upstream_flow_back_from_nodes(vec![output_layer.to_node()], &[], network_interface::FlowType::HorizontalFlow);
// Take until another layer node is found (but not the first layer node)
let existing_node_id = upstream
.take_while(|node_id| is_traversal_start(*node_id) || !self.network_interface.is_layer(node_id, &[]))
.find(|node_id| self.network_interface.reference(node_id, &[]).is_some_and(|node_reference| node_reference == reference));
let mut existing_node_id = None;
for upstream_node in upstream.collect::<Vec<_>>() {
let upstream_node_input_type = self.network_interface.input_type(&InputConnector::node(upstream_node, 0), &[]).0.nested_type();
let is_traversal_start = |node_id: NodeId| {
self.layer_node.map(|layer| layer.to_node()) == Some(node_id) || self.network_interface.network(&[]).unwrap().exports.iter().any(|export| export.as_node() == Some(node_id))
};
if !is_traversal_start(upstream_node) && (self.network_interface.is_layer(&upstream_node, &[]) || upstream_node_input_type != layer_input_type) {
break;
}
if self.network_interface.reference(&upstream_node, &[]).is_some_and(|node_reference| node_reference == reference) {
existing_node_id = Some(upstream_node);
break;
}
}
// Create a new node if the node does not exist and update its inputs
existing_node_id.or_else(|| {

View File

@@ -752,8 +752,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
return;
};
responses.add(DocumentMessage::EndTransaction);
if let Some(preview_node) = self.preview_on_mouse_up {
responses.add(NodeGraphMessage::TogglePreview { node_id: preview_node });
self.preview_on_mouse_up = None;
@@ -992,6 +990,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
self.box_selection_start = None;
self.wire_in_progress_from_connector = None;
self.wire_in_progress_to_connector = None;
responses.add(DocumentMessage::EndTransaction);
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
responses.add(FrontendMessage::UpdateBox { box_selection: None })
}

View File

@@ -3603,7 +3603,7 @@ impl NodeNetworkInterface {
};
// Check whether the being-deleted node's first (primary) input is a node
let mut reconnect_to_input = network.nodes.get(node_id).and_then(|node| {
let reconnect_to_input = network.nodes.get(node_id).and_then(|node| {
node.inputs
.iter()
.find(|input| input.is_exposed_to_frontend(network_path.is_empty()))
@@ -3625,15 +3625,22 @@ impl NodeNetworkInterface {
let mut reconnect_node = None;
// Don't reconnect if the upstream node is a layer and there are multiple downstream inputs to reconnect
let multiple_disconnect_and_upstream_is_layer = downstream_inputs_to_disconnect.len() > 1
&& reconnect_to_input
.as_ref()
.is_some_and(|upstream_input| upstream_input.as_node().map_or(false, |node_id| self.is_layer(&node_id, network_path)));
for downstream_input in &downstream_inputs_to_disconnect {
self.disconnect_input(downstream_input, network_path);
// Prevent reconnecting export to import until https://github.com/GraphiteEditor/Graphite/issues/1762 is solved
if !(matches!(reconnect_to_input, Some(NodeInput::Network { .. })) && matches!(downstream_input, InputConnector::Export(_))) {
if let Some(reconnect_input) = reconnect_to_input.take() {
// Get the reconnect node position only if it is in a stack
if let Some(reconnect_input) = &reconnect_to_input {
reconnect_node = reconnect_input.as_node().and_then(|node_id| if self.is_stack(&node_id, network_path) { Some(node_id) } else { None });
self.disconnect_input(&InputConnector::node(*node_id, 0), network_path);
self.set_input(downstream_input, reconnect_input, network_path);
if !multiple_disconnect_and_upstream_is_layer {
self.set_input(downstream_input, reconnect_input.clone(), network_path);
}
}
}
}

View File

@@ -963,6 +963,7 @@ impl PortfolioMessageHandler {
/text>"#
// It's a mystery why the `/text>` tag above needs to be missing its `<`, but when it exists it prints the `<` character in the text. However this works with it removed.
.to_string();
responses.add(Message::EndBuffer(graphene_std::renderer::RenderMetadata::default()));
responses.add(FrontendMessage::UpdateDocumentArtwork { svg: error });
}
result

View File

@@ -15,7 +15,7 @@ use graphene_core::renderer::{RenderSvgSegmentList, SvgSegment};
use graphene_core::text::FontCache;
use graphene_core::transform::Footprint;
use graphene_core::vector::style::ViewMode;
use graphene_std::renderer::format_transform_matrix;
use graphene_std::renderer::{format_transform_matrix, RenderMetadata};
use graphene_std::vector::VectorData;
use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi};
use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta};
@@ -630,6 +630,7 @@ impl NodeGraphExecutor {
}
fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, transform: DAffine2, responses: &mut VecDeque<Message>) -> Result<(), String> {
let mut render_output_metadata = RenderMetadata::default();
match node_graph_output {
TaggedValue::RenderOutput(render_output) => {
match render_output.data {
@@ -651,10 +652,7 @@ impl NodeGraphExecutor {
}
}
responses.add(Message::EndBuffer(render_output.metadata));
responses.add(DocumentMessage::RenderScrollbars);
responses.add(DocumentMessage::RenderRulers);
responses.add(OverlaysMessage::Draw);
render_output_metadata = render_output.metadata;
}
TaggedValue::Bool(render_object) => Self::debug_render(render_object, transform, responses),
TaggedValue::String(render_object) => Self::debug_render(render_object, transform, responses),
@@ -669,6 +667,10 @@ impl NodeGraphExecutor {
return Err(format!("Invalid node graph output type: {node_graph_output:#?}"));
}
};
responses.add(Message::EndBuffer(render_output_metadata));
responses.add(DocumentMessage::RenderScrollbars);
responses.add(DocumentMessage::RenderRulers);
responses.add(OverlaysMessage::Draw);
Ok(())
}
}