Migrate demo artwork and fix all failing CI tests (#1459)

* Initial work on fixing tests

* Fix formatting

* Remove dead code to satisfy rustc warnings

* Insert into an artboard

* Load updated artwork in editor

* Remove popup when importing image

* Fix up demo art

* Change transform app[lication method

* Reduce number of enums called BlendMode

* Finalize the demo artwork upgrade

* Code review pass

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2023-11-19 23:06:21 -08:00
committed by Keavon Chambers
co-authored by Keavon Chambers
parent 719c96ecd8
commit 8a1cf3ad5d
40 changed files with 1238 additions and 477 deletions
+46 -9
View File
@@ -1,6 +1,6 @@
use glam::{DAffine2, DVec2};
use graphene_core::renderer::ClickTarget;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64;
use graph_craft::document::{DocumentNode, NodeId, NodeNetwork};
@@ -12,6 +12,8 @@ pub struct DocumentMetadata {
transforms: HashMap<LayerNodeIdentifier, DAffine2>,
upstream_transforms: HashMap<NodeId, DAffine2>,
structure: HashMap<LayerNodeIdentifier, NodeRelations>,
artboards: HashSet<LayerNodeIdentifier>,
folders: HashSet<LayerNodeIdentifier>,
click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>,
selected_nodes: Vec<NodeId>,
/// Transform from document space to viewport space.
@@ -25,6 +27,8 @@ impl Default for DocumentMetadata {
upstream_transforms: HashMap::new(),
click_targets: HashMap::new(),
structure: HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]),
artboards: HashSet::new(),
folders: HashSet::new(),
selected_nodes: Vec::new(),
document_to_viewport: DAffine2::IDENTITY,
}
@@ -67,12 +71,12 @@ impl DocumentMetadata {
!self.selected_nodes.is_empty()
}
/// Access the [`NodeRelations`] of a layer
/// Access the [`NodeRelations`] of a layer.
fn get_relations(&self, node_identifier: LayerNodeIdentifier) -> Option<&NodeRelations> {
self.structure.get(&node_identifier)
}
/// Mutably access the [`NodeRelations`] of a layer
/// Mutably access the [`NodeRelations`] of a layer.
fn get_structure_mut(&mut self, node_identifier: LayerNodeIdentifier) -> &mut NodeRelations {
self.structure.entry(node_identifier).or_default()
}
@@ -92,25 +96,41 @@ impl DocumentMetadata {
sorted_layers
}
/// Ancestor that is shared by all layers and that is deepest (more nested). May be the root layer.
pub fn deepest_common_ancestor(&self, layers: impl Iterator<Item = LayerNodeIdentifier>) -> LayerNodeIdentifier {
/// Ancestor that is shared by all layers and that is deepest (more nested). Default may be the root.
pub fn deepest_common_ancestor(&self, layers: impl Iterator<Item = LayerNodeIdentifier>) -> Option<LayerNodeIdentifier> {
layers
.map(|layer| {
let mut layer_path = layer.ancestors(self).skip(1).collect::<Vec<_>>();
let mut layer_path = layer.ancestors(self).collect::<Vec<_>>();
layer_path.reverse();
if !self.folders.contains(&layer) {
layer_path.pop();
}
layer_path
})
.reduce(|mut a, b| {
a.truncate(a.iter().zip(b.iter()).position(|(&a, &b)| a != b).unwrap_or_else(|| a.len().min(b.len())));
a
})
.and_then(|path| path.last().copied())
.unwrap_or(LayerNodeIdentifier::ROOT)
.and_then(|layer| layer.last().copied())
}
pub fn active_artboard(&self) -> LayerNodeIdentifier {
self.artboards.iter().next().copied().unwrap_or(LayerNodeIdentifier::ROOT)
}
pub fn is_folder(&self, layer: LayerNodeIdentifier) -> bool {
self.folders.contains(&layer)
}
pub fn is_artboard(&self, layer: LayerNodeIdentifier) -> bool {
self.artboards.contains(&layer)
}
/// Filter out non folder layers
pub fn folders<'a>(&'a self, layers: impl Iterator<Item = LayerNodeIdentifier> + 'a) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
layers.filter(|layer| layer.has_children(self))
layers.filter(|layer| self.folders.contains(layer))
}
/// Folders sorted from most nested to least nested
@@ -146,6 +166,8 @@ impl DocumentMetadata {
/// Loads the structure of layer nodes from a node graph.
pub fn load_structure(&mut self, graph: &NodeNetwork) {
self.structure = HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]);
self.folders = HashSet::new();
self.artboards = HashSet::new();
let id = graph.outputs[0].node_id;
let Some(output_node) = graph.nodes.get(&id) else {
@@ -166,6 +188,13 @@ impl DocumentMetadata {
if let Some((child_node, child_id)) = first_child_layer(graph, current_node) {
stack.push((child_node, child_id, current_identifier));
}
if is_artboard(current_identifier, graph) {
self.artboards.insert(current_identifier);
}
if is_folder(current_identifier, graph) {
self.folders.insert(current_identifier);
}
}
current = sibling_below(graph, current_node);
@@ -210,6 +239,14 @@ fn is_artboard(layer: LayerNodeIdentifier, network: &NodeNetwork) -> bool {
network.primary_flow_from_node(Some(layer.to_node())).any(|(node, _)| node.name == "Artboard")
}
fn is_folder(layer: LayerNodeIdentifier, network: &NodeNetwork) -> bool {
network.nodes.get(&layer.to_node()).and_then(|node| node.inputs.first()).is_some_and(|input| input.as_node().is_none())
|| network
.primary_flow_from_node(Some(layer.to_node()))
.skip(1)
.any(|(node, _)| node.name == "Artboard" || node.name == "Layer")
}
// click targets
impl DocumentMetadata {
/// Update the cached click targets of the layers