Skip to content
Merged
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
2 changes: 1 addition & 1 deletion demo-artwork/changing-seasons.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/isometric-fountain.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/marbled-mandelbrot.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/painted-dreams.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/parametric-dunescape.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/procedural-string-lights.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/red-dress.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/valley-of-spires.graphite

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions editor/src/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,14 @@ mod test {
println!("-------------------------------------------------");
println!("Failed test due to receiving a DisplayDialogError while loading a Graphite demo file.");
println!();
println!("NOTE:");
println!("Document upgrading isn't performed in tests like when opening in the actual editor.");
println!("You may need to open and re-save a document in the editor to apply its migrations.");
println!();
println!("DisplayDialogError details:");
println!();
println!("Description: {value}");
println!("Description:");
println!("{value}");
println!("-------------------------------------------------");
println!();

Expand Down Expand Up @@ -538,7 +543,9 @@ mod test {
});

// Check if the graph renders
editor.eval_graph().await;
if let Err(e) = editor.eval_graph().await {
print_problem_to_terminal_on_failure(&format!("Failed to evaluate the graph for document '{document_name}':\n{e}"));
}

for response in responses {
// Check for the existence of the file format incompatibility warning dialog after opening the test file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,17 +289,17 @@ impl<'a> ModifyInputsContext<'a> {
log::error!("Node type {} does not exist in ModifyInputsContext::existing_node_id", reference);
return None;
};
// If inserting a path node, insert a flatten vector elements if the type is a graphic group.
// If inserting a path node, insert a Flatten Path if the type is a graphic group.
// TODO: Allow the path node to operate on Graphic Group data by utilizing the reference for each vector data in a group.
if node_definition.identifier == "Path" {
let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type().clone();
if layer_input_type == concrete!(GraphicGroupTable) {
let Some(flatten_vector_elements_definition) = resolve_document_node_type("Flatten Vector Elements") else {
log::error!("Flatten Vector Elements does not exist in ModifyInputsContext::existing_node_id");
let Some(flatten_path_definition) = resolve_document_node_type("Flatten Path") else {
log::error!("Flatten Path does not exist in ModifyInputsContext::existing_node_id");
return None;
};
let node_id = NodeId::new();
self.network_interface.insert_node(node_id, flatten_vector_elements_definition.default_node_template(), &[]);
self.network_interface.insert_node(node_id, flatten_path_definition.default_node_template(), &[]);
self.network_interface.move_node_to_chain_start(&node_id, output_layer, &[]);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3805,6 +3805,15 @@ impl NodeNetworkInterface {
node_metadata.persistent_metadata.network_metadata = metadata.network_metadata;
}

/// Keep metadata in sync with the new implementation if this is used by anything other than the upgrade scripts
pub fn replace_reference_name(&mut self, node_id: &NodeId, network_path: &[NodeId], reference_name: String) {
let Some(node_metadata) = self.node_metadata_mut(node_id, network_path) else {
log::error!("Could not get node metadata in replace_reference_name");
return;
};
node_metadata.persistent_metadata.reference = Some(reference_name);
}

/// Keep metadata in sync with the new implementation if this is used by anything other than the upgrade scripts
pub fn set_manual_compostion(&mut self, node_id: &NodeId, network_path: &[NodeId], manual_composition: Option<Type>) {
let Some(network) = self.network_mut(network_path) else {
Expand Down
19 changes: 18 additions & 1 deletion editor/src/messages/portfolio/portfolio_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
}
};

const REPLACEMENTS: [(&str, &str); 36] = [
const REPLACEMENTS: [(&str, &str); 37] = [
("graphene_core::AddArtboardNode", "graphene_core::graphic_element::AppendArtboardNode"),
("graphene_core::ConstructArtboardNode", "graphene_core::graphic_element::ToArtboardNode"),
("graphene_core::ToGraphicElementNode", "graphene_core::graphic_element::ToElementNode"),
Expand Down Expand Up @@ -507,6 +507,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
("graphene_std::raster::SampleNode", "graphene_std::raster::SampleImageNode"),
("graphene_core::transform::CullNode", "graphene_core::ops::IdentityNode"),
("graphene_std::raster::MaskImageNode", "graphene_std::raster::MaskNode"),
("graphene_core::vector::FlattenVectorElementsNode", "graphene_core::vector::FlattenPathNode"),
];
let mut network = document.network_interface.document_network().clone();
network.generate_node_paths(&[]);
Expand Down Expand Up @@ -946,6 +947,22 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[2].clone(), network_path);
document.network_interface.set_input(&InputConnector::node(*node_id, 2), old_inputs[3].clone(), network_path);
}

if reference == "Flatten Vector Elements" {
let node_definition = resolve_document_node_type("Flatten Path").unwrap();
let new_node_template = node_definition.default_node_template();
let document_node = new_node_template.document_node;
document.network_interface.replace_implementation(node_id, network_path, document_node.implementation.clone());
document
.network_interface
.replace_implementation_metadata(node_id, network_path, new_node_template.persistent_node_metadata);

let old_inputs = document.network_interface.replace_inputs(node_id, document_node.inputs.clone(), network_path);

document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);

document.network_interface.replace_reference_name(node_id, network_path, "Flatten Path".to_string());
}
}

// TODO: Eventually remove this document upgrade code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ pub fn merge_layers(document: &DocumentMessageHandler, first_layer: LayerNodeIde
delete_children: false,
});

// Add a flatten vector elements node after the merge
// Add a Flatten Path node after the merge
let flatten_node_id = NodeId::new();
let flatten_node = document_node_definitions::resolve_document_node_type("Flatten Vector Elements")
let flatten_node = document_node_definitions::resolve_document_node_type("Flatten Path")
.expect("Failed to create flatten node")
.default_node_template();
responses.add(NodeGraphMessage::InsertNode {
Expand Down
5 changes: 4 additions & 1 deletion editor/src/messages/tool/tool_messages/artboard_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,10 @@ mod test_artboard {
pub use crate::test_utils::test_prelude::*;

async fn get_artboards(editor: &mut EditorTestUtils) -> Vec<graphene_core::Artboard> {
let instrumented = editor.eval_graph().await;
let instrumented = match editor.eval_graph().await {
Ok(instrumented) => instrumented,
Err(e) => panic!("Failed to evaluate graph: {}", e),
};
instrumented.grab_all_input::<graphene_core::append_artboard::ArtboardInput>(&editor.runtime).collect()
}

Expand Down
5 changes: 4 additions & 1 deletion editor/src/messages/tool/tool_messages/ellipse_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,10 @@ mod test_ellipse {
}

async fn get_ellipse(editor: &mut EditorTestUtils) -> Vec<ResolvedEllipse> {
let instrumented = editor.eval_graph().await;
let instrumented = match editor.eval_graph().await {
Ok(instrumented) => instrumented,
Err(e) => panic!("Failed to evaluate graph: {e}"),
};

let document = editor.active_document();
let layers = document.metadata().all_layers();
Expand Down
5 changes: 4 additions & 1 deletion editor/src/messages/tool/tool_messages/fill_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ mod test_fill {
use graphene_std::vector::style::Fill;

async fn get_fills(editor: &mut EditorTestUtils) -> Vec<Fill> {
let instrumented = editor.eval_graph().await;
let instrumented = match editor.eval_graph().await {
Ok(instrumented) => instrumented,
Err(e) => panic!("Failed to evaluate graph: {e}"),
};

instrumented.grab_all_input::<fill::FillInput<Fill>>(&editor.runtime).collect()
}
Expand Down
5 changes: 4 additions & 1 deletion editor/src/messages/tool/tool_messages/gradient_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,10 @@ mod test_gradient {
use super::gradient_space_transform;

async fn get_fills(editor: &mut EditorTestUtils) -> Vec<(Fill, DAffine2)> {
let instrumented = editor.eval_graph().await;
let instrumented = match editor.eval_graph().await {
Ok(instrumented) => instrumented,
Err(e) => panic!("Failed to evaluate graph: {}", e),
};

let document = editor.active_document();
let layers = document.metadata().all_layers();
Expand Down
16 changes: 12 additions & 4 deletions editor/src/messages/tool/tool_messages/spline_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,9 @@ mod test_spline_tool {
editor.handle_message(SplineToolMessage::Confirm).await;

// Evaluate the graph to ensure everything is processed
editor.eval_graph().await;
if let Err(e) = editor.eval_graph().await {
panic!("Graph evaluation failed: {}", e);
}

// Get the layer and vector data
let document = editor.active_document();
Expand Down Expand Up @@ -708,7 +710,9 @@ mod test_spline_tool {
editor.handle_message(SplineToolMessage::Confirm).await;

// Evaluating the graph to ensure everything is processed
editor.eval_graph().await;
if let Err(e) = editor.eval_graph().await {
panic!("Graph evaluation failed: {}", e);
}

// Get the layer and vector data
let document = editor.active_document();
Expand Down Expand Up @@ -744,7 +748,9 @@ mod test_spline_tool {
editor.handle_message(SplineToolMessage::Confirm).await;

// Evaluating the graph to ensure everything is processed
editor.eval_graph().await;
if let Err(e) = editor.eval_graph().await {
panic!("Graph evaluation failed: {}", e);
}

// Get the layer and vector data
let document = editor.active_document();
Expand Down Expand Up @@ -781,7 +787,9 @@ mod test_spline_tool {
editor.click_tool(ToolType::Spline, MouseKeys::LEFT, DVec2::new(150.0, 100.0), ModifierKeys::empty()).await;

editor.handle_message(SplineToolMessage::Confirm).await;
editor.eval_graph().await;
if let Err(e) = editor.eval_graph().await {
panic!("Graph evaluation failed: {}", e);
}

// Get the layer and vector data
let document = editor.active_document();
Expand Down
25 changes: 16 additions & 9 deletions editor/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,35 @@ impl EditorTestUtils {
Self { editor, runtime }
}

pub fn eval_graph<'a>(&'a mut self) -> impl std::future::Future<Output = Instrumented> + 'a {
pub fn eval_graph<'a>(&'a mut self) -> impl std::future::Future<Output = Result<Instrumented, String>> + 'a {
// An inner function is required since async functions in traits are a bit weird
async fn run<'a>(editor: &'a mut Editor, runtime: &'a mut NodeRuntime) -> Instrumented {
async fn run<'a>(editor: &'a mut Editor, runtime: &'a mut NodeRuntime) -> Result<Instrumented, String> {
let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler;
let exector = &mut portfolio.executor;
let document = portfolio.documents.get_mut(&portfolio.active_document_id.unwrap()).unwrap();

let instrumented = exector.update_node_graph_instrumented(document).expect("update_node_graph_instrumented failed");
let instrumented = match exector.update_node_graph_instrumented(document) {
Ok(instrumented) => instrumented,
Err(e) => return Err(format!("update_node_graph_instrumented failed\n\n{e}")),
};

let viewport_resolution = glam::UVec2::ONE;
exector
.submit_current_node_graph_evaluation(document, viewport_resolution, Default::default())
.expect("submit_current_node_graph_evaluation failed");
if let Err(e) = exector.submit_current_node_graph_evaluation(document, viewport_resolution, Default::default()) {
return Err(format!("submit_current_node_graph_evaluation failed\n\n{e}"));
}
runtime.run().await;

let mut messages = VecDeque::new();
editor.poll_node_graph_evaluation(&mut messages).expect("Graph should render");
if let Err(e) = editor.poll_node_graph_evaluation(&mut messages) {
return Err(format!("Graph should render\n\n{e}"));
}
let frontend_messages = messages.into_iter().flat_map(|message| editor.handle_message(message));

for message in frontend_messages {
message.check_node_graph_error();
}

instrumented
Ok(instrumented)
}

run(&mut self.editor, &mut self.runtime)
Expand All @@ -69,7 +74,9 @@ impl EditorTestUtils {
self.editor.handle_message(message);

// Required to process any buffered messages
self.eval_graph().await;
if let Err(e) = self.eval_graph().await {
panic!("Failed to evaluate graph: {e}");
}
}

pub async fn new_document(&mut self) {
Expand Down
43 changes: 43 additions & 0 deletions node-graph/gcore/src/graphic_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,49 @@ async fn flatten_group(_: impl Ctx, group: GraphicGroupTable, fully_flatten: boo
output
}

#[node_macro::node(category("General"))]
async fn flatten_vector(_: impl Ctx, group: GraphicGroupTable) -> VectorDataTable {
// TODO: Avoid mutable reference, instead return a new GraphicGroupTable?
fn flatten_group(output_group_table: &mut VectorDataTable, current_group_table: GraphicGroupTable) {
for current_instance in current_group_table.instance_ref_iter() {
let current_element = current_instance.instance.clone();
let reference = *current_instance.source_node_id;

match current_element {
// If we're allowed to recurse, flatten any GraphicGroups we encounter
GraphicElement::GraphicGroup(mut current_element) => {
// Apply the parent group's transform to all child elements
for graphic_element in current_element.instance_mut_iter() {
*graphic_element.transform = *current_instance.transform * *graphic_element.transform;
}

flatten_group(output_group_table, current_element);
}
// Handle any leaf elements we encounter, which can be either non-GraphicGroup elements or GraphicGroups that we don't want to flatten
GraphicElement::VectorData(vector_instance) => {
for current_element in vector_instance.instance_ref_iter() {
output_group_table.push(Instance {
instance: current_element.instance.clone(),
transform: *current_instance.transform * *current_element.transform,
alpha_blending: AlphaBlending {
opacity: current_instance.alpha_blending.opacity * current_element.alpha_blending.opacity,
blend_mode: current_element.alpha_blending.blend_mode,
},
source_node_id: reference,
});
}
}
_ => {}
}
}
}

let mut output = VectorDataTable::default();
flatten_group(&mut output, group);

output
}

#[node_macro::node(category(""))]
async fn to_artboard<Data: Into<GraphicGroupTable> + 'n>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,
Expand Down
4 changes: 4 additions & 0 deletions node-graph/gcore/src/graphic_element/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,10 @@ impl GraphicElementRendered for RasterDataTable<Color> {
let subpath = Subpath::new_rect(DVec2::ZERO, DVec2::ONE);
click_targets.push(ClickTarget::new(subpath, 0.));
}

fn to_graphic_element(&self) -> GraphicElement {
GraphicElement::RasterData(self.clone())
}
}

impl GraphicElementRendered for GraphicElement {
Expand Down
7 changes: 7 additions & 0 deletions node-graph/gcore/src/instances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ impl<T> Instances<T> {
self.source_node_id.push(instance.source_node_id);
}

pub fn extend(&mut self, instances: Instances<T>) {
self.instance.extend(instances.instance);
self.transform.extend(instances.transform);
self.alpha_blending.extend(instances.alpha_blending);
self.source_node_id.extend(instances.source_node_id);
}

pub fn instance_iter(self) -> impl DoubleEndedIterator<Item = Instance<T>> {
self.instance
.into_iter()
Expand Down
18 changes: 16 additions & 2 deletions node-graph/gcore/src/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,26 @@ async fn switch<T, C: Send + 'n + Clone>(
condition: bool,
#[expose]
#[implementations(
Context -> String, Context -> bool, Context -> f64, Context -> u32, Context -> u64, Context -> DVec2, Context -> VectorDataTable, Context -> DAffine2,
Context -> String,
Context -> bool,
Context -> f64,
Context -> u32,
Context -> u64,
Context -> DVec2,
Context -> VectorDataTable,
Context -> DAffine2,
)]
if_true: impl Node<C, Output = T>,
#[expose]
#[implementations(
Context -> String, Context -> bool, Context -> f64, Context -> u32, Context -> u64, Context -> DVec2, Context -> VectorDataTable, Context -> DAffine2,
Context -> String,
Context -> bool,
Context -> f64,
Context -> u32,
Context -> u64,
Context -> DVec2,
Context -> VectorDataTable,
Context -> DAffine2,
)]
if_false: impl Node<C, Output = T>,
) -> T {
Expand Down
Loading
Loading