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/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.

2 changes: 0 additions & 2 deletions editor/src/messages/portfolio/document/document_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,6 @@ pub enum DocumentMessage {
UpdateClickTargets {
click_targets: HashMap<NodeId, Vec<Arc<ClickTarget>>>,
},
// TODO: Eventually remove this document upgrade code
MigrateLegacyGradients,
UpdateOutlines {
outlines: HashMap<NodeId, Vec<Arc<ClickTarget>>>,
},
Expand Down
32 changes: 0 additions & 32 deletions editor/src/messages/portfolio/document/document_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1372,38 +1372,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
.collect();
self.network_interface.update_click_targets(layer_click_targets);
}
// TODO: Eventually remove this document upgrade code
DocumentMessage::MigrateLegacyGradients => {
if self.pending_gradient_migration {
self.pending_gradient_migration = false;

// Read each layer's legacy gradient and compute its absolute form from the now-available local bounds
let layers: Vec<_> = self.metadata().all_layers().collect();
let conversions: Vec<(NodeId, Fill)> = layers
.into_iter()
.filter_map(|layer| {
let gradient = graph_modification_utils::get_gradient(layer, &self.network_interface)?;
if gradient.absolute {
return None;
}
let fill_node_id = graph_modification_utils::get_fill_node_id(layer, &self.network_interface)?;
let bounds = self.metadata().nonzero_bounding_box(layer);
let bounding_box = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
let layer_transform = self.metadata().upstream_transform(layer.to_node());
Some((fill_node_id, Fill::Gradient(gradient.to_absolute(bounding_box, layer_transform))))
})
.collect();

let converted_any = !conversions.is_empty();
for (fill_node_id, fill) in conversions {
self.network_interface
.set_input(&InputConnector::node(fill_node_id, 1), NodeInput::value(TaggedValue::Fill(fill), false), &[]);
}
if converted_any {
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
}
DocumentMessage::UpdateOutlines { outlines } => {
let layer_outlines = outlines
.into_iter()
Expand Down
5 changes: 3 additions & 2 deletions editor/src/messages/portfolio/document_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::messages::portfolio::document::node_graph::document_node_definitions:
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::prelude::DocumentMessageHandler;
use crate::messages::tool::common_functionality::graph_modification_utils;
use glam::{DVec2, IVec2};
use graph_craft::application_io::resource::{DataSource, Resource, ResourceHash, ResourceId};
use graph_craft::descriptor;
Expand Down Expand Up @@ -1121,8 +1122,8 @@ pub fn document_migration_replace_resources_referenced_by_hash(document_serializ
pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_node_definitions_on_open: bool) {
document.network_interface.migrate_path_modify_node();

// Legacy `Fill::Gradient`s are converted to absolute by the deferred migration pass once the first graph run yields geometry bounds
document.pending_gradient_migration = true;
// Legacy `Fill::Gradient`s are converted to absolute by the deferred migration pre-pass that measures each fill's geometry
document.pending_gradient_migration = !graph_modification_utils::legacy_gradient_fill_nodes(&document.network_interface).is_empty();

let network = document.network_interface.document_network().clone();

Expand Down
9 changes: 8 additions & 1 deletion editor/src/messages/portfolio/portfolio_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,13 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
// Use exact physical dimensions from browser (via ResizeObserver's devicePixelContentBoxSize)
let physical_resolution = viewport.size().to_physical().into_dvec2().round().as_uvec2();

// TODO: Eventually remove this document upgrade code
// A freshly-opened document with legacy gradients runs a one-time measurement pre-pass instead of rendering, until every gradient is converted to absolute space
if document.pending_gradient_migration {
Comment thread
Keavon marked this conversation as resolved.
self.executor.drive_gradient_migration(document, document_id, physical_resolution, scale, responses);
return;
}

// TODO: Remove this when we do the SVG rendering with a separate library on desktop, thus avoiding a need for the hole punch.
// TODO: See #3796. There is a second instance of this todo comment and code block (be sure to remove both).
#[cfg(not(target_family = "wasm"))]
Expand Down Expand Up @@ -1999,7 +2006,7 @@ impl PortfolioMessageHandler {
return Err("No active document".to_string());
};

let result = self.executor.poll_node_graph_evaluation(active_document, responses);
let result = self.executor.poll_node_graph_evaluation(active_document, document_id, responses);
if result.is_err() {
let error = r#"
<rect x="50%" y="50%" width="460" height="100" transform="translate(-230 -50)" rx="4" fill="var(--color-warning-yellow)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::messages::portfolio::document::node_graph::document_node_definitions:
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{FlowType, InputConnector, NodeNetworkInterface, NodeTemplate};
use crate::messages::prelude::*;
use glam::DVec2;
use glam::{DAffine2, DVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graph_craft::{ProtoNodeIdentifier, concrete};
Expand Down Expand Up @@ -319,6 +319,60 @@ pub fn get_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI
Some(gradient.clone())
}

// TODO: Eventually remove this document upgrade code
/// The legacy bounding-box-relative gradient (`absolute == false`) in a "Fill" node's active `fill` input, if any.
fn legacy_active_gradient_in_fill_node(fill_node_id: NodeId, network_interface: &NodeNetworkInterface) -> Option<Gradient> {
let node = network_interface.document_network().nodes.get(&fill_node_id)?;
let TaggedValue::Fill(Fill::Gradient(gradient)) = node.inputs.get(graphene_std::vector::fill::FillInput::<Fill>::INDEX)?.as_value()? else {
return None;
};
(!gradient.absolute).then(|| gradient.clone())
}

// TODO: Eventually remove this document upgrade code
/// The legacy bounding-box-relative gradient (`absolute == false`) stashed in a "Fill" node's `_backup_gradient` input, if any.
/// The backup is inert until the fill is toggled back to a gradient, at which point it becomes the active fill, so it needs converting too.
fn legacy_backup_gradient_in_fill_node(fill_node_id: NodeId, network_interface: &NodeNetworkInterface) -> Option<Gradient> {
let node = network_interface.document_network().nodes.get(&fill_node_id)?;
let TaggedValue::FillGradient(gradient) = node.inputs.get(graphene_std::vector::fill::BackupGradientInput::INDEX)?.as_value()? else {
return None;
};
(!gradient.absolute).then(|| gradient.clone())
}

// TODO: Eventually remove this document upgrade code
/// Convert a "Fill" node's legacy gradients (the active `fill` and/or the stashed `_backup_gradient`) to absolute space using
/// the geometry's measured bounding box, writing each back in place. The active fill is written as a `Fill`, the backup as a bare `FillGradient`.
pub fn migrate_fill_node_gradients_to_absolute(fill_node_id: NodeId, network_interface: &mut NodeNetworkInterface, bounding_box: DAffine2, layer_transform: DAffine2) {
if let Some(gradient) = legacy_active_gradient_in_fill_node(fill_node_id, network_interface) {
let absolute = gradient.to_absolute(bounding_box, layer_transform);
let input = InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::<Fill>::INDEX);
network_interface.set_input(&input, NodeInput::value(TaggedValue::Fill(Fill::Gradient(absolute)), false), &[]);
}
if let Some(gradient) = legacy_backup_gradient_in_fill_node(fill_node_id, network_interface) {
let absolute = gradient.to_absolute(bounding_box, layer_transform);
let input = InputConnector::node(fill_node_id, graphene_std::vector::fill::BackupGradientInput::INDEX);
network_interface.set_input(&input, NodeInput::value(TaggedValue::FillGradient(absolute), false), &[]);
}
}

// TODO: Eventually remove this document upgrade code
/// Find every root-network "Fill" node holding a legacy bounding-box-relative gradient, either as its active `fill` or as its `_backup_gradient`.
///
/// Scans the document network structurally instead of walking each layer's primary flow, so it also catches fills on
/// secondary inputs and in hidden, disabled, or orphaned branches. Fills nested inside subgraph node networks are skipped.
pub fn legacy_gradient_fill_nodes(network_interface: &NodeNetworkInterface) -> Vec<NodeId> {
let fill_identifier = DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER);
network_interface
.document_network()
.nodes
.keys()
.copied()
.filter(|node_id| network_interface.reference(node_id, &[]).as_ref() == Some(&fill_identifier))
.filter(|&node_id| legacy_active_gradient_in_fill_node(node_id, network_interface).is_some() || legacy_backup_gradient_in_fill_node(node_id, network_interface).is_some())
.collect()
}

/// Get the gradient stops of a layer, if any.
pub fn get_gradient_stops(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<GradientStops> {
let gradient_value_node = network_interface.document_network().nodes.get(&get_upstream_gradient_value_node_id(layer, network_interface)?)?;
Expand Down
Loading
Loading