Move selected node list from DocumentMetadata to the document (#1565)

This commit is contained in:
Keavon Chambers
2024-01-13 04:52:47 -08:00
parent aab0fcf84c
commit 78a1bb17cd
27 changed files with 511 additions and 465 deletions
@@ -1,15 +1,16 @@
use super::utility_types::error::EditorError;
use super::utility_types::misc::{SnappingOptions, SnappingState};
use super::utility_types::nodes::{CollapsedLayers, SelectedNodes};
use crate::application::{generate_uuid, GRAPHITE_GIT_COMMIT_HASH};
use crate::consts::{ASYMPTOTIC_EFFECT, DEFAULT_DOCUMENT_NAME, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING};
use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::NodeGraphHandlerData;
use crate::messages::portfolio::document::node_graph::{GraphOperationHandlerData, NodeGraphHandlerData};
use crate::messages::portfolio::document::properties_panel::utility_types::PropertiesPanelMessageHandlerData;
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::portfolio::document::utility_types::document_metadata::{is_artboard, DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::layer_panel::RawBuffer;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, DocumentMode, FlipAxis, PTZ};
use crate::messages::portfolio::document::utility_types::nodes::RawBuffer;
use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils::{get_blend_mode, get_opacity};
@@ -48,6 +49,10 @@ pub struct DocumentMessageHandler {
// ============================================
#[serde(default = "default_network")]
pub network: NodeNetwork,
#[serde(default = "default_selected_nodes")]
pub selected_nodes: SelectedNodes,
#[serde(default = "default_collapsed")]
pub collapsed: CollapsedLayers,
#[serde(default = "default_name")]
pub name: String,
#[serde(default = "default_commit_hash")]
@@ -62,8 +67,6 @@ pub struct DocumentMessageHandler {
overlays_visible: bool,
#[serde(default = "default_rulers_visible")]
pub rulers_visible: bool,
#[serde(default = "default_collapsed")]
pub collapsed: Vec<LayerNodeIdentifier>,
// =============================================
// Fields omitted from the saved document format
// =============================================
@@ -85,7 +88,7 @@ pub struct DocumentMessageHandler {
#[serde(skip)]
layer_range_selection_reference: Option<LayerNodeIdentifier>,
#[serde(skip)]
pub document_metadata: DocumentMetadata,
pub metadata: DocumentMetadata,
}
impl Default for DocumentMessageHandler {
@@ -102,6 +105,8 @@ impl Default for DocumentMessageHandler {
// Fields that are saved in the document format
// ============================================
network: root_network(),
selected_nodes: SelectedNodes::default(),
collapsed: CollapsedLayers::default(),
name: DEFAULT_DOCUMENT_NAME.to_string(),
commit_hash: GRAPHITE_GIT_COMMIT_HASH.to_string(),
navigation: PTZ::default(),
@@ -109,7 +114,6 @@ impl Default for DocumentMessageHandler {
view_mode: ViewMode::default(),
overlays_visible: true,
rulers_visible: true,
collapsed: Vec::new(),
// =============================================
// Fields omitted from the saved document format
// =============================================
@@ -121,7 +125,7 @@ impl Default for DocumentMessageHandler {
graph_view_overlay_open: false,
snapping_state: SnappingState::default(),
layer_range_selection_reference: None,
document_metadata: Default::default(),
metadata: Default::default(),
}
}
}
@@ -131,6 +135,14 @@ fn default_network() -> NodeNetwork {
DocumentMessageHandler::default().network
}
#[inline(always)]
fn default_selected_nodes() -> SelectedNodes {
DocumentMessageHandler::default().selected_nodes
}
#[inline(always)]
fn default_collapsed() -> CollapsedLayers {
DocumentMessageHandler::default().collapsed
}
#[inline(always)]
fn default_name() -> String {
DocumentMessageHandler::default().name
}
@@ -158,10 +170,6 @@ fn default_overlays_visible() -> bool {
fn default_rulers_visible() -> bool {
DocumentMessageHandler::default().rulers_visible
}
#[inline(always)]
fn default_collapsed() -> Vec<LayerNodeIdentifier> {
DocumentMessageHandler::default().collapsed
}
fn root_network() -> NodeNetwork {
{
@@ -245,13 +253,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
self.navigation_handler.process_message(
message,
responses,
(
&self.document_metadata,
document_bounds,
ipp,
self.selected_visible_layers_bounding_box_viewport(),
&mut self.navigation,
),
(&self.metadata, document_bounds, ipp, self.selected_visible_layers_bounding_box_viewport(), &mut self.navigation),
);
}
#[remain::unsorted]
@@ -265,7 +267,8 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
executor,
document_name: self.name.as_str(),
document_network: &self.network,
document_metadata: &mut self.document_metadata,
document_metadata: &mut self.metadata,
selected_nodes: &self.selected_nodes,
};
self.properties_panel_message_handler
.process_message(message, responses, (persistent_data, properties_panel_message_handler_data));
@@ -277,7 +280,8 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses,
NodeGraphHandlerData {
document_network: &mut self.network,
document_metadata: &mut self.document_metadata,
document_metadata: &mut self.metadata,
selected_nodes: &mut self.selected_nodes,
document_id,
document_name: self.name.as_str(),
collapsed: &mut self.collapsed,
@@ -287,7 +291,17 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
);
}
#[remain::unsorted]
GraphOperation(message) => GraphOperationMessageHandler.process_message(message, responses, (&mut self.network, &mut self.document_metadata, &mut self.collapsed, &mut self.node_graph_handler)),
GraphOperation(message) => GraphOperationMessageHandler.process_message(
message,
responses,
GraphOperationHandlerData {
document_network: &mut self.network,
document_metadata: &mut self.metadata,
selected_nodes: &mut self.selected_nodes,
collapsed: &mut self.collapsed,
node_graph: &mut self.node_graph_handler,
},
),
// Messages
AbortTransaction => {
@@ -312,7 +326,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
AlignAggregate::Max => combined_box[1],
AlignAggregate::Center => (combined_box[0] + combined_box[1]) / 2.,
};
for layer in self.metadata().selected_layers() {
for layer in self.selected_nodes.selected_layers(self.metadata()) {
let Some(bbox) = self.metadata().bounding_box_viewport(layer) else {
continue;
};
@@ -366,7 +380,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
self.backup(responses);
responses.add_front(BroadcastEvent::SelectionChanged);
for path in self.metadata().shallowest_unique_layers(self.metadata().selected_layers()) {
for path in self.metadata().shallowest_unique_layers(self.selected_nodes.selected_layers(self.metadata())) {
responses.add_front(DocumentMessage::DeleteLayer { id: path.last().unwrap().to_node() });
}
@@ -381,7 +395,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
DocumentStructureChanged => {
self.update_layers_panel_options_bar_widgets(responses);
self.document_metadata.load_structure(&self.network);
self.metadata.load_structure(&self.network, &mut self.selected_nodes);
let data_buffer: RawBuffer = self.serialize_root();
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer });
}
@@ -402,7 +416,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
if let Some([min, max]) = self.selected_visible_layers_bounding_box_viewport() {
let center = (max + min) / 2.;
let bbox_trans = DAffine2::from_translation(-center);
for layer in self.metadata().selected_layers() {
for layer in self.selected_nodes.selected_layers(self.metadata()) {
responses.add(GraphOperationMessage::TransformChange {
layer,
transform: DAffine2::from_scale(scale),
@@ -426,7 +440,10 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
}
GroupSelectedLayers => {
// TODO: Add code that changes the insert index of the new folder based on the selected layer
let parent = self.metadata().deepest_common_ancestor(self.metadata().selected_layers(), true).unwrap_or(LayerNodeIdentifier::ROOT);
let parent = self
.metadata()
.deepest_common_ancestor(self.selected_nodes.selected_layers(self.metadata()), true)
.unwrap_or(LayerNodeIdentifier::ROOT);
let folder_id = NodeId(generate_uuid());
@@ -467,7 +484,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
}
}
MoveSelectedLayersTo { parent, insert_index } => {
let selected_layers = self.metadata().selected_layers().collect::<Vec<_>>();
let selected_layers = self.selected_nodes.selected_layers(self.metadata()).collect::<Vec<_>>();
// Disallow trying to insert into self
if selected_layers.iter().any(|&layer| parent.ancestors(self.metadata()).any(|ancestor| ancestor == layer)) {
@@ -495,7 +512,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
let opposite_corner = ipp.keyboard.key(resize_opposite_corner);
let delta = DVec2::new(delta_x, delta_y);
for layer in self.metadata().selected_layers() {
for layer in self.selected_nodes.selected_layers(self.metadata()) {
// Nudge translation
if !ipp.keyboard.key(resize) {
responses.add(GraphOperationMessage::TransformChange {
@@ -506,7 +523,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
});
}
// Nudge resize
else if let Some([existing_top_left, existing_bottom_right]) = self.document_metadata.bounding_box_document(layer) {
else if let Some([existing_top_left, existing_bottom_right]) = self.metadata.bounding_box_document(layer) {
let size = existing_bottom_right - existing_top_left;
let new_size = size + if opposite_corner { -delta } else { delta };
let enlargement_factor = new_size / size;
@@ -636,8 +653,10 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
})
}
SelectAllLayers => {
let all = self.metadata().all_layers_except_artboards().map(|layer| layer.to_node()).collect();
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: all });
let metadata = self.metadata();
let all_layers_except_artboards = metadata.all_layers().filter(move |&layer| !metadata.is_artboard(layer));
let nodes = all_layers_except_artboards.map(|layer| layer.to_node()).collect();
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: nodes });
}
SelectedLayersLower => {
responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: 1 });
@@ -674,7 +693,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
} else {
if ctrl {
// Toggle selection when holding ctrl
if self.metadata().selected_layers_contains(layer) {
if self.selected_nodes.selected_layers_contains(layer, self.metadata()) {
responses.add_front(NodeGraphMessage::SelectedNodesRemove { nodes: vec![id] });
} else {
responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] });
@@ -700,7 +719,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
}
SetBlendModeForSelectedLayers { blend_mode } => {
self.backup(responses);
for layer in self.metadata().selected_layers_except_artboards() {
for layer in self.selected_nodes.selected_layers_except_artboards(self.metadata()) {
responses.add(GraphOperationMessage::BlendModeSet { layer, blend_mode });
}
}
@@ -708,7 +727,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
self.backup(responses);
let opacity = opacity.clamp(0., 1.) as f32;
for layer in self.metadata().selected_layers_except_artboards() {
for layer in self.selected_nodes.selected_layers_except_artboards(self.metadata()) {
responses.add(GraphOperationMessage::OpacitySet { layer, opacity });
}
}
@@ -742,10 +761,10 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
StartTransaction => self.backup(responses),
ToggleLayerExpansion { id } => {
let layer = LayerNodeIdentifier::new(id, self.network());
if self.collapsed.contains(&layer) {
self.collapsed.retain(|&collapsed_layer| collapsed_layer != layer);
if self.collapsed.0.contains(&layer) {
self.collapsed.0.retain(|&collapsed_layer| collapsed_layer != layer);
} else {
self.collapsed.push(layer);
self.collapsed.0.push(layer);
}
responses.add(NodeGraphMessage::RunDocumentGraph);
}
@@ -761,7 +780,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
UngroupSelectedLayers => {
responses.add(DocumentMessage::StartTransaction);
let folder_paths = self.metadata().folders_sorted_by_most_nested(self.metadata().selected_layers());
let folder_paths = self.metadata().folders_sorted_by_most_nested(self.selected_nodes.selected_layers(self.metadata()));
for folder in folder_paths {
// Select all the children of the folder
@@ -784,7 +803,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add(DocumentMessage::CommitTransaction);
}
UpdateDocumentTransform { transform } => {
self.document_metadata.document_to_viewport = transform;
self.metadata.document_to_viewport = transform;
responses.add(DocumentMessage::RenderRulers);
responses.add(DocumentMessage::RenderScrollbars);
responses.add(NodeGraphMessage::RunDocumentGraph);
@@ -810,44 +829,28 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
}
impl DocumentMessageHandler {
pub fn layer_visible(&self, layer: LayerNodeIdentifier) -> bool {
!layer.ancestors(&self.document_metadata).any(|layer| self.network.disabled.contains(&layer.to_node()))
}
pub fn selected_visible_layers(&self) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.document_metadata.selected_layers().filter(|&layer| self.layer_visible(layer))
}
/// Runs an intersection test with all layers and a viewport space quad
pub fn intersect_quad<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, network: &'a NodeNetwork) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
let document_quad = self.document_metadata.document_to_viewport.inverse() * viewport_quad;
self.document_metadata
let document_quad = self.metadata.document_to_viewport.inverse() * viewport_quad;
self.metadata
.root()
.decendants(&self.document_metadata)
.filter(|&layer| self.layer_visible(layer))
.decendants(&self.metadata)
.filter(|&layer| self.selected_nodes.layer_visible(layer, &self.network(), &self.metadata()))
.filter(|&layer| !is_artboard(layer, network))
.filter_map(|layer| self.document_metadata.click_target(layer).map(|targets| (layer, targets)))
.filter(move |(layer, target)| {
target
.iter()
.any(move |target| target.intersect_rectangle(document_quad, self.document_metadata.transform_to_document(*layer)))
})
.filter_map(|layer| self.metadata.click_target(layer).map(|targets| (layer, targets)))
.filter(move |(layer, target)| target.iter().any(move |target| target.intersect_rectangle(document_quad, self.metadata.transform_to_document(*layer))))
.map(|(layer, _)| layer)
}
/// Find all of the layers that were clicked on from a viewport space location
pub fn click_xray(&self, viewport_location: DVec2) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
let point = self.document_metadata.document_to_viewport.inverse().transform_point2(viewport_location);
self.document_metadata
let point = self.metadata.document_to_viewport.inverse().transform_point2(viewport_location);
self.metadata
.root()
.decendants(&self.document_metadata)
.filter(|&layer| self.layer_visible(layer))
.filter_map(|layer| self.document_metadata.click_target(layer).map(|targets| (layer, targets)))
.filter(move |(layer, target)| {
target
.iter()
.any(|target: &ClickTarget| target.intersect_point(point, self.document_metadata.transform_to_document(*layer)))
})
.decendants(&self.metadata)
.filter(|&layer| self.selected_nodes.layer_visible(layer, &self.network(), &self.metadata()))
.filter_map(|layer| self.metadata.click_target(layer).map(|targets| (layer, targets)))
.filter(move |(layer, target)| target.iter().any(|target: &ClickTarget| target.intersect_point(point, self.metadata.transform_to_document(*layer))))
.map(|(layer, _)| layer)
}
@@ -858,8 +861,9 @@ impl DocumentMessageHandler {
/// Get the combined bounding box of the click targets of the selected visible layers in viewport space
pub fn selected_visible_layers_bounding_box_viewport(&self) -> Option<[DVec2; 2]> {
self.selected_visible_layers()
.filter_map(|layer| self.document_metadata.bounding_box_viewport(layer))
self.selected_nodes
.selected_visible_layers(&self.network(), &self.metadata())
.filter_map(|layer| self.metadata.bounding_box_viewport(layer))
.reduce(graphene_core::renderer::Quad::combine_bounds)
}
@@ -868,7 +872,7 @@ impl DocumentMessageHandler {
}
pub fn metadata(&self) -> &DocumentMetadata {
&self.document_metadata
&self.metadata
}
pub fn serialize_document(&self) -> String {
@@ -884,7 +888,7 @@ impl DocumentMessageHandler {
pub fn with_name(name: String, ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> Self {
let mut document = Self { name, ..Self::default() };
let transform = document.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.size() / 2., DVec2::ZERO, 0., 1.);
document.document_metadata.document_to_viewport = transform;
document.metadata.document_to_viewport = transform;
responses.add(DocumentMessage::UpdateDocumentTransform { transform });
document
@@ -909,7 +913,7 @@ impl DocumentMessageHandler {
for layer_node in folder.children(self.metadata()) {
data_section.push(layer_node.to_node().0);
space += 1;
if layer_node.has_children(self.metadata()) && !self.collapsed.contains(&layer_node) {
if layer_node.has_children(self.metadata()) && !self.collapsed.0.contains(&layer_node) {
path.push(layer_node);
// TODO: Skip if folder is not expanded.
@@ -1066,7 +1070,7 @@ impl DocumentMessageHandler {
pub fn new_layer_parent(&self) -> LayerNodeIdentifier {
self.metadata()
.deepest_common_ancestor(self.metadata().selected_layers(), false)
.deepest_common_ancestor(self.selected_nodes.selected_layers(self.metadata()), false)
.unwrap_or_else(|| self.metadata().active_artboard())
}
@@ -1278,7 +1282,7 @@ impl DocumentMessageHandler {
pub fn update_layers_panel_options_bar_widgets(&self, responses: &mut VecDeque<Message>) {
// Get an iterator over the selected layers (excluding artboards which don't have an opacity or blend mode).
let selected_layers_except_artboards = self.metadata().selected_layers_except_artboards();
let selected_layers_except_artboards = self.selected_nodes.selected_layers_except_artboards(self.metadata());
// Look up the current opacity and blend mode of the selected layers (if any), and split the iterator into the first tuple and the rest.
let mut opacity_and_blend_mode = selected_layers_except_artboards.map(|layer| (get_opacity(layer, &self.network).unwrap_or(100.), get_blend_mode(layer, &self.network).unwrap_or_default()));
@@ -1372,7 +1376,7 @@ impl DocumentMessageHandler {
pub fn selected_layers_reorder(&mut self, relative_index_offset: isize, responses: &mut VecDeque<Message>) {
self.backup(responses);
let mut selected_layers = self.metadata().selected_layers();
let mut selected_layers = self.selected_nodes.selected_layers(self.metadata());
let first_or_last_selected_layer = match relative_index_offset.signum() {
-1 => selected_layers.next(),
@@ -1429,7 +1433,7 @@ impl DocumentMessageHandler {
common.extend(escape);
}
if self.metadata().selected_layers().next().is_some() {
if self.selected_nodes.selected_layers(self.metadata()).next().is_some() {
let select = actions!(DocumentMessageDiscriminant;
DeleteSelectedLayers,
DuplicateSelectedLayers,
@@ -54,7 +54,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
&mut self,
message: NavigationMessage,
responses: &mut VecDeque<Message>,
(document_metadata, document_bounds, ipp, selection_bounds, ptz): (&DocumentMetadata, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>, &mut PTZ),
(metadata, document_bounds, ipp, selection_bounds, ptz): (&DocumentMetadata, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>, &mut PTZ),
) {
use NavigationMessage::*;
@@ -73,8 +73,8 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
bounds: [pos1, pos2],
prevent_zoom_past_100,
} => {
let v1 = document_metadata.document_to_viewport.inverse().transform_point2(DVec2::ZERO);
let v2 = document_metadata.document_to_viewport.inverse().transform_point2(ipp.viewport_bounds.size());
let v1 = metadata.document_to_viewport.inverse().transform_point2(DVec2::ZERO);
let v2 = metadata.document_to_viewport.inverse().transform_point2(ipp.viewport_bounds.size());
let center = v1.lerp(v2, 0.5) - pos1.lerp(pos2, 0.5);
let size = (pos2 - pos1) / (v2 - v1);
@@ -96,7 +96,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
}
FitViewportToSelection => {
if let Some(bounds) = selection_bounds {
let transform = document_metadata.document_to_viewport.inverse();
let transform = metadata.document_to_viewport.inverse();
responses.add(FitViewportToBounds {
bounds: [transform.transform_point2(bounds[0]), transform.transform_point2(bounds[1])],
prevent_zoom_past_100: false,
@@ -257,7 +257,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
responses.add(TransformCanvasEnd { abort_transform });
}
TranslateCanvas { delta } => {
let transformed_delta = document_metadata.document_to_viewport.inverse().transform_vector2(delta);
let transformed_delta = metadata.document_to_viewport.inverse().transform_vector2(delta);
ptz.pan += transformed_delta;
responses.add(BroadcastEvent::CanvasTransformed);
@@ -275,7 +275,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
self.transform_operation = TransformOperation::Pan { pre_commit_pan: ptz.pan };
}
TranslateCanvasByViewportFraction { delta } => {
let transformed_delta = document_metadata.document_to_viewport.inverse().transform_vector2(delta * ipp.viewport_bounds.size());
let transformed_delta = metadata.document_to_viewport.inverse().transform_vector2(delta * ipp.viewport_bounds.size());
ptz.pan += transformed_delta;
responses.add(BroadcastEvent::DocumentIsDirty);
@@ -1,5 +1,6 @@
use super::{resolve_document_node_type, VectorDataModification};
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, SelectedNodes};
use crate::messages::prelude::*;
use bezier_rs::Subpath;
@@ -509,7 +510,7 @@ impl<'a> ModifyInputsContext<'a> {
});
}
fn delete_layer(&mut self, id: NodeId) {
fn delete_layer(&mut self, id: NodeId, selected_nodes: &mut SelectedNodes) {
let Some(node) = self.document_network.nodes.get(&id) else {
warn!("Deleting layer node that does not exist");
return;
@@ -558,20 +559,31 @@ impl<'a> ModifyInputsContext<'a> {
}
}
self.document_metadata.retain_selected_nodes(|id| !delete_nodes.contains(id));
selected_nodes.retain_selected_nodes(|id| !delete_nodes.contains(id));
self.responses.add(BroadcastEvent::SelectionChanged);
self.responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetadata, &mut Vec<LayerNodeIdentifier>, &mut NodeGraphMessageHandler)> for GraphOperationMessageHandler {
fn process_message(
&mut self,
message: GraphOperationMessage,
responses: &mut VecDeque<Message>,
(document_network, document_metadata, collapsed, node_graph): (&mut NodeNetwork, &mut DocumentMetadata, &mut Vec<LayerNodeIdentifier>, &mut NodeGraphMessageHandler),
) {
pub struct GraphOperationHandlerData<'a> {
pub document_network: &'a mut NodeNetwork,
pub document_metadata: &'a mut DocumentMetadata,
pub selected_nodes: &'a mut SelectedNodes,
pub collapsed: &'a mut CollapsedLayers,
pub node_graph: &'a mut NodeGraphMessageHandler,
}
impl MessageHandler<GraphOperationMessage, GraphOperationHandlerData<'_>> for GraphOperationMessageHandler {
fn process_message(&mut self, message: GraphOperationMessage, responses: &mut VecDeque<Message>, data: GraphOperationHandlerData) {
let GraphOperationHandlerData {
document_network,
document_metadata,
selected_nodes,
collapsed,
node_graph,
} = data;
match message {
GraphOperationMessage::FillSet { layer, fill } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
@@ -645,7 +657,7 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
if let Some(layer) = modify_inputs.create_layer(id, modify_inputs.document_network.original_outputs()[0].node_id, 0, 0) {
modify_inputs.insert_artboard(artboard, layer);
}
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
GraphOperationMessage::NewBitmapLayer {
id,
@@ -698,14 +710,14 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
modify_inputs.responses.add(NodeGraphMessage::RunDocumentGraph);
}
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
GraphOperationMessage::NewVectorLayer { id, subpaths, parent, insert_index } => {
let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses);
if let Some(layer) = modify_inputs.create_layer_with_insert_index(id, insert_index, parent) {
modify_inputs.insert_vector_data(subpaths, layer);
}
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
GraphOperationMessage::NewTextLayer {
id,
@@ -719,7 +731,7 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
if let Some(layer) = modify_inputs.create_layer_with_insert_index(id, insert_index, parent) {
modify_inputs.insert_text(text, font, size, layer);
}
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
GraphOperationMessage::ResizeArtboard { id, location, dimensions } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(id, document_network, document_metadata, node_graph, responses) {
@@ -728,18 +740,18 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
}
GraphOperationMessage::DeleteLayer { id } => {
let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses);
modify_inputs.delete_layer(id);
load_network_structure(document_network, document_metadata, collapsed);
modify_inputs.delete_layer(id, selected_nodes);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
GraphOperationMessage::ClearArtboards => {
let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses);
let layer_nodes = modify_inputs.document_network.nodes.iter().filter(|(_, node)| node.is_layer()).map(|(id, _)| *id).collect::<Vec<_>>();
for layer in layer_nodes {
if modify_inputs.document_network.upstream_flow_back_from_nodes(vec![layer], true).any(|(node, _id)| node.is_artboard()) {
modify_inputs.delete_layer(layer);
modify_inputs.delete_layer(layer, selected_nodes);
}
}
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
}
}
@@ -749,7 +761,7 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
}
}
pub fn load_network_structure(document_network: &NodeNetwork, document_metadata: &mut DocumentMetadata, collapsed: &mut Vec<LayerNodeIdentifier>) {
document_metadata.load_structure(document_network);
collapsed.retain(|&layer| document_metadata.layer_exists(layer));
pub fn load_network_structure(document_network: &NodeNetwork, document_metadata: &mut DocumentMetadata, selected_nodes: &mut SelectedNodes, collapsed: &mut CollapsedLayers) {
document_metadata.load_structure(document_network, selected_nodes);
collapsed.0.retain(|&layer| document_metadata.layer_exists(layer));
}
@@ -52,11 +52,11 @@ pub struct LayerBounds {
impl LayerBounds {
/// Extract the layer bounds and their transform for a layer.
pub fn new(document_metadata: &DocumentMetadata, layer: LayerNodeIdentifier) -> Self {
pub fn new(metadata: &DocumentMetadata, layer: LayerNodeIdentifier) -> Self {
Self {
bounds: document_metadata.nonzero_bounding_box(layer),
bounds: metadata.nonzero_bounding_box(layer),
bounds_transform: DAffine2::IDENTITY,
layer_transform: document_metadata.transform_to_document(layer),
layer_transform: metadata.transform_to_document(layer),
}
}
@@ -4,7 +4,7 @@ use crate::application::generate_uuid;
use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::layer_panel::{LayerClassification, LayerPanelEntry};
use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerClassification, LayerPanelEntry, SelectedNodes};
use crate::messages::prelude::*;
use graph_craft::document::value::TaggedValue;
@@ -174,20 +174,20 @@ impl NodeGraphMessageHandler {
}
/// Updates the buttons for disable and preview
fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, responses: &mut VecDeque<Message>) {
fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque<Message>) {
if let Some(network) = document_network.nested_network(&self.network) {
let mut widgets = Vec::new();
// Don't allow disabling input or output nodes
let mut selected_nodes = document_metadata.selected_nodes().filter(|&&id| !network.inputs.contains(&id) && !network.original_outputs_contain(id));
let mut selection = selected_nodes.selected_nodes().filter(|&&id| !network.inputs.contains(&id) && !network.original_outputs_contain(id));
// If there is at least one other selected node then show the hide or show button
if selected_nodes.next().is_some() {
if selection.next().is_some() {
// Check if any of the selected nodes are disabled
let is_hidden = document_metadata.selected_nodes().any(|id| network.disabled.contains(id));
let is_hidden = selected_nodes.selected_nodes().any(|id| network.disabled.contains(id));
// Check if multiple nodes are selected
let multiple_nodes = selected_nodes.next().is_some();
let multiple_nodes = selection.next().is_some();
// Generate the enable or disable button accordingly
let (hide_show_label, hide_show_icon) = if is_hidden { ("Make Visible", "EyeHidden") } else { ("Make Hidden", "EyeVisible") };
@@ -203,8 +203,8 @@ impl NodeGraphMessageHandler {
}
// If only one node is selected then show the preview or stop previewing button
let mut selected_nodes = document_metadata.selected_nodes();
if let (Some(&node_id), None) = (selected_nodes.next(), selected_nodes.next()) {
let mut selection = selected_nodes.selected_nodes();
if let (Some(&node_id), None) = (selection.next(), selection.next()) {
// Is this node the current output
let is_output = network.outputs_contain(node_id);
@@ -225,7 +225,7 @@ impl NodeGraphMessageHandler {
}
/// Collate the properties panel sections for a node graph
pub fn collate_properties(&self, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
pub fn collate_properties(&self, context: &mut NodePropertiesContext, selected_nodes: &SelectedNodes) -> Vec<LayoutGroup> {
let mut network = context.network;
for segment in &self.network {
@@ -239,7 +239,7 @@ impl NodeGraphMessageHandler {
// First, we filter all the selections into layers and nodes
let (mut layers, mut nodes) = (Vec::new(), Vec::new());
for node_id in context.metadata.selected_nodes() {
for node_id in selected_nodes.selected_nodes() {
if let Some(layer_or_node) = network.nodes.get(node_id) {
if layer_or_node.is_layer() {
layers.push(*node_id);
@@ -278,8 +278,16 @@ impl NodeGraphMessageHandler {
}
}
fn send_graph(&self, network: &NodeNetwork, graph_view_overlay_open: bool, document_metadata: &mut DocumentMetadata, collapsed: &Vec<LayerNodeIdentifier>, responses: &mut VecDeque<Message>) {
document_metadata.load_structure(&network);
fn send_graph(
&self,
network: &NodeNetwork,
graph_view_overlay_open: bool,
metadata: &mut DocumentMetadata,
selected_nodes: &mut SelectedNodes,
collapsed: &CollapsedLayers,
responses: &mut VecDeque<Message>,
) {
metadata.load_structure(network, selected_nodes);
let links = network
.nodes
@@ -371,9 +379,9 @@ impl NodeGraphMessageHandler {
if node.is_layer() {
let layer = LayerNodeIdentifier::new(node_id, network);
let layer_classification = {
if document_metadata.is_artboard(layer) {
if metadata.is_artboard(layer) {
LayerClassification::Artboard
} else if document_metadata.is_folder(layer) {
} else if metadata.is_folder(layer) {
LayerClassification::Folder
} else {
LayerClassification::Layer
@@ -391,9 +399,9 @@ impl NodeGraphMessageHandler {
let data = LayerPanelEntry {
id: node_id,
layer_classification,
expanded: layer.has_children(document_metadata) && !collapsed.contains(&layer),
depth: layer.ancestors(document_metadata).count() - 1,
parent_id: layer.parent(document_metadata).map(|parent| parent.to_node()),
expanded: layer.has_children(metadata) && !collapsed.0.contains(&layer),
depth: layer.ancestors(metadata).count() - 1,
parent_id: layer.parent(metadata).map(|parent| parent.to_node()),
// TODO: Remove and take this from the graph data in the frontend similar to thumbnail?
name: network.nodes.get(&node_id).map(|node| node.alias.clone()).unwrap_or_default(),
// TODO: Remove and take this from the graph data in the frontend similar to thumbnail?
@@ -413,10 +421,10 @@ impl NodeGraphMessageHandler {
}
/// Updates the frontend's selection state in line with the backend
fn update_selected(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, responses: &mut VecDeque<Message>) {
self.update_selection_action_buttons(document_network, document_metadata, responses);
fn update_selected(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque<Message>) {
self.update_selection_action_buttons(document_network, selected_nodes, responses);
responses.add(FrontendMessage::UpdateNodeGraphSelection {
selected: document_metadata.selected_nodes_ref().clone(),
selected: selected_nodes.selected_nodes_ref().clone(),
});
}
@@ -487,7 +495,7 @@ impl NodeGraphMessageHandler {
}
/// Tries to remove a node from the network, returning true on success.
fn remove_node(&mut self, document_network: &mut NodeNetwork, document_metadata: &mut DocumentMetadata, node_id: NodeId, responses: &mut VecDeque<Message>, reconnect: bool) -> bool {
fn remove_node(&mut self, document_network: &mut NodeNetwork, selected_nodes: &mut SelectedNodes, node_id: NodeId, responses: &mut VecDeque<Message>, reconnect: bool) -> bool {
let Some(network) = document_network.nested_network_mut(&self.network) else {
return false;
};
@@ -495,7 +503,7 @@ impl NodeGraphMessageHandler {
return false;
}
network.nodes.remove(&node_id);
document_metadata.retain_selected_nodes(|&id| id != node_id);
selected_nodes.retain_selected_nodes(|&id| id != node_id);
responses.add(BroadcastEvent::SelectionChanged);
true
}
@@ -521,9 +529,10 @@ impl NodeGraphMessageHandler {
pub struct NodeGraphHandlerData<'a> {
pub document_network: &'a mut NodeNetwork,
pub document_metadata: &'a mut DocumentMetadata,
pub selected_nodes: &'a mut SelectedNodes,
pub document_id: DocumentId,
pub document_name: &'a str,
pub collapsed: &'a mut Vec<LayerNodeIdentifier>,
pub collapsed: &'a mut CollapsedLayers,
pub input: &'a InputPreprocessorMessageHandler,
pub graph_view_overlay_open: bool,
}
@@ -533,6 +542,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let NodeGraphHandlerData {
document_network,
document_metadata,
selected_nodes,
document_id,
collapsed,
graph_view_overlay_open,
@@ -545,14 +555,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
on: BroadcastEvent::SelectionChanged,
send: Box::new(NodeGraphMessage::SelectedNodesUpdated.into()),
});
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
NodeGraphMessage::SelectedNodesUpdated => {
self.update_selection_action_buttons(document_network, document_metadata, responses);
self.update_selected(document_network, document_metadata, responses);
if document_metadata.selected_layers().count() <= 1 {
self.update_selection_action_buttons(document_network, selected_nodes, responses);
self.update_selected(document_network, selected_nodes, responses);
if selected_nodes.selected_layers(document_metadata).count() <= 1 {
responses.add(DocumentMessage::SetRangeSelectionLayer {
new_layer: document_metadata.selected_layers().next(),
new_layer: selected_nodes.selected_layers(document_metadata).next(),
});
}
responses.add(NodeGraphMessage::RunDocumentGraph);
@@ -594,7 +604,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
};
// Collect the selected nodes
let new_ids = &document_metadata.selected_nodes().copied().enumerate().map(|(new, old)| (old, NodeId(new as u64))).collect();
let new_ids = &selected_nodes.selected_nodes().copied().enumerate().map(|(new, old)| (old, NodeId(new as u64))).collect();
let copied_nodes: Vec<_> = Self::copy_nodes(network, new_ids).collect();
// Prefix to show that this is nodes
@@ -627,18 +637,18 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::DeleteSelectedNodes { reconnect: true });
}
NodeGraphMessage::DeleteNode { node_id, reconnect } => {
self.remove_node(document_network, document_metadata, node_id, responses, reconnect);
self.remove_node(document_network, selected_nodes, node_id, responses, reconnect);
}
NodeGraphMessage::DeleteSelectedNodes { reconnect } => {
responses.add(DocumentMessage::StartTransaction);
for node_id in document_metadata.selected_nodes().copied() {
for node_id in selected_nodes.selected_nodes().copied() {
responses.add(NodeGraphMessage::DeleteNode { node_id, reconnect });
}
if let Some(network) = document_network.nested_network(&self.network) {
// Only generate node graph if one of the selected nodes is connected to the output
if document_metadata.selected_nodes().any(|&node_id| network.connected_to_output(node_id)) {
if selected_nodes.selected_nodes().any(|&node_id| network.connected_to_output(node_id)) {
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
@@ -679,24 +689,24 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
}
if let Some(network) = document_network.nested_network(&self.network) {
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
}
self.update_selected(document_network, document_metadata, responses);
self.update_selected(document_network, selected_nodes, responses);
}
NodeGraphMessage::DuplicateSelectedNodes => {
if let Some(network) = document_network.nested_network(&self.network) {
responses.add(DocumentMessage::StartTransaction);
let new_ids = &document_metadata.selected_nodes().map(|&id| (id, NodeId(generate_uuid()))).collect();
let new_ids = &selected_nodes.selected_nodes().map(|&id| (id, NodeId(generate_uuid()))).collect();
document_metadata.clear_selected_nodes();
selected_nodes.clear_selected_nodes();
responses.add(BroadcastEvent::SelectionChanged);
// Copy the selected nodes
let copied_nodes = Self::copy_nodes(network, new_ids).collect::<Vec<_>>();
// Select the new nodes
document_metadata.add_selected_nodes(copied_nodes.iter().map(|(node_id, _)| *node_id));
selected_nodes.add_selected_nodes(copied_nodes.iter().map(|(node_id, _)| *node_id));
responses.add(BroadcastEvent::SelectionChanged);
for (node_id, mut document_node) in copied_nodes {
@@ -707,20 +717,20 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::InsertNode { node_id, document_node });
}
self.update_selected(document_network, document_metadata, responses);
self.update_selected(document_network, selected_nodes, responses);
}
}
NodeGraphMessage::ExitNestedNetwork { depth_of_nesting } => {
document_metadata.clear_selected_nodes();
selected_nodes.clear_selected_nodes();
responses.add(BroadcastEvent::SelectionChanged);
for _ in 0..depth_of_nesting {
self.network.pop();
}
if let Some(network) = document_network.nested_network(&self.network) {
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
}
self.update_selected(document_network, document_metadata, responses);
self.update_selected(document_network, selected_nodes, responses);
}
NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => {
let Some(network) = document_network.nested_network(&self.network) else {
@@ -761,12 +771,12 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
return;
};
for node_id in document_metadata.selected_nodes() {
for node_id in selected_nodes.selected_nodes() {
if let Some(node) = network.nodes.get_mut(node_id) {
node.metadata.position += IVec2::new(displacement_x, displacement_y)
}
}
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
}
NodeGraphMessage::PasteNodes { serialized_nodes } => {
let Some(network) = document_network.nested_network(&self.network) else {
@@ -817,21 +827,21 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(PortfolioMessage::SubmitGraphRender { document_id });
}
NodeGraphMessage::SelectedNodesAdd { nodes } => {
document_metadata.add_selected_nodes(nodes);
selected_nodes.add_selected_nodes(nodes);
responses.add(BroadcastEvent::SelectionChanged);
}
NodeGraphMessage::SelectedNodesRemove { nodes } => {
document_metadata.retain_selected_nodes(|node| !nodes.contains(node));
selected_nodes.retain_selected_nodes(|node| !nodes.contains(node));
responses.add(BroadcastEvent::SelectionChanged);
}
NodeGraphMessage::SelectedNodesSet { nodes } => {
document_metadata.set_selected_nodes(nodes);
selected_nodes.set_selected_nodes(nodes);
responses.add(BroadcastEvent::SelectionChanged);
responses.add(PropertiesPanelMessage::Refresh);
}
NodeGraphMessage::SendGraph => {
if let Some(network) = document_network.nested_network(&self.network) {
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
}
}
NodeGraphMessage::SetInputValue { node_id, input_index, value } => {
@@ -858,7 +868,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let structure_changed = node_input.as_node().is_some() || input.as_node().is_some();
*node_input = input;
if structure_changed {
load_network_structure(document_network, document_metadata, collapsed);
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
}
}
}
@@ -932,14 +942,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
}
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
}
NodeGraphMessage::ToggleSelectedHidden => {
if let Some(network) = document_network.nested_network(&self.network) {
responses.add(DocumentMessage::StartTransaction);
let new_hidden = !document_metadata.selected_nodes().any(|id| network.disabled.contains(id));
for &node_id in document_metadata.selected_nodes() {
let new_hidden = !selected_nodes.selected_nodes().any(|id| network.disabled.contains(id));
for &node_id in selected_nodes.selected_nodes() {
responses.add(NodeGraphMessage::SetHidden { node_id, hidden: new_hidden });
}
}
@@ -963,7 +973,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
self.update_selection_action_buttons(document_network, document_metadata, responses);
self.update_selection_action_buttons(document_network, selected_nodes, responses);
}
NodeGraphMessage::SetName { node_id, name } => {
responses.add(DocumentMessage::StartTransaction);
@@ -974,7 +984,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let Some(node) = network.nodes.get_mut(&node_id) {
node.alias = name;
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
}
}
}
@@ -995,28 +1005,28 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
}
self.update_selection_action_buttons(document_network, document_metadata, responses);
self.update_selection_action_buttons(document_network, selected_nodes, responses);
responses.add(NodeGraphMessage::RunDocumentGraph);
}
NodeGraphMessage::UpdateNewNodeGraph => {
if let Some(network) = document_network.nested_network(&self.network) {
document_metadata.clear_selected_nodes();
selected_nodes.clear_selected_nodes();
responses.add(BroadcastEvent::SelectionChanged);
self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses);
self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses);
let node_types = document_node_types::collect_node_types();
responses.add(FrontendMessage::UpdateNodeTypes { node_types });
}
self.update_selected(document_network, document_metadata, responses);
self.update_selected(document_network, selected_nodes, responses);
}
NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors } => {
self.resolved_types = resolved_types;
self.node_graph_errors = node_graph_errors;
}
}
self.has_selection = document_metadata.has_selected_nodes();
self.has_selection = selected_nodes.has_selected_nodes();
}
fn actions(&self) -> ActionList {
@@ -2919,7 +2919,7 @@ impl DocumentNodeDefinition {
}
/// Converts the [DocumentNodeDefinition] type to a [DocumentNode], based on the inputs from the graph (which must be the correct length) and the metadata
pub fn to_document_node(&self, inputs: impl IntoIterator<Item = NodeInput>, document_metadata: DocumentNodeMetadata) -> DocumentNode {
pub fn to_document_node(&self, inputs: impl IntoIterator<Item = NodeInput>, metadata: DocumentNodeMetadata) -> DocumentNode {
let inputs: Vec<_> = inputs.into_iter().collect();
assert_eq!(inputs.len(), self.inputs.len(), "Inputs passed from the graph must be equal to the number required");
DocumentNode {
@@ -2927,7 +2927,7 @@ impl DocumentNodeDefinition {
inputs,
has_primary_output: self.has_primary_output,
implementation: self.generate_implementation(),
metadata: document_metadata,
metadata,
manual_composition: self.manual_composition.clone(),
..Default::default()
}
@@ -2935,10 +2935,10 @@ impl DocumentNodeDefinition {
/// Converts the [DocumentNodeDefinition] type to a [DocumentNode], using the provided `input_override` and falling back to the default inputs.
/// `input_override` does not have to be the correct length.
pub fn to_document_node_default_inputs(&self, input_override: impl IntoIterator<Item = Option<NodeInput>>, document_metadata: DocumentNodeMetadata) -> DocumentNode {
pub fn to_document_node_default_inputs(&self, input_override: impl IntoIterator<Item = Option<NodeInput>>, metadata: DocumentNodeMetadata) -> DocumentNode {
let mut input_override = input_override.into_iter();
let inputs = self.inputs.iter().map(|default| input_override.next().unwrap_or_default().unwrap_or_else(|| default.default.clone()));
self.to_document_node(inputs, document_metadata)
self.to_document_node(inputs, metadata)
}
/// Converts the [DocumentNodeDefinition] type to a [DocumentNode], completely default
@@ -25,7 +25,7 @@ pub fn overlay_canvas_context() -> web_sys::CanvasRenderingContext2d {
}
pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext) {
for layer in document.metadata().selected_layers() {
for layer in document.selected_nodes.selected_layers(document.metadata()) {
let Some(subpaths) = get_subpaths(layer, &document.network) else { continue };
let transform = document.metadata().transform_to_viewport(layer);
let selected = shape_editor.selected_shape_state.get(&layer);
@@ -15,10 +15,10 @@ impl<'a> MessageHandler<PropertiesPanelMessage, (&PersistentData, PropertiesPane
let PropertiesPanelMessageHandlerData {
node_graph_message_handler,
executor,
document_network,
document_metadata,
document_network: network,
document_metadata: metadata,
selected_nodes,
document_name,
..
} = data;
match message {
@@ -38,11 +38,11 @@ impl<'a> MessageHandler<PropertiesPanelMessage, (&PersistentData, PropertiesPane
responses,
nested_path: &node_graph_message_handler.network,
executor,
network: document_network,
metadata: document_metadata,
network,
metadata,
};
let properties_sections = node_graph_message_handler.collate_properties(&mut context);
let properties_sections = node_graph_message_handler.collate_properties(&mut context, selected_nodes);
let options_bar = vec![LayoutGroup::Row {
widgets: vec![
@@ -1,4 +1,5 @@
use crate::messages::portfolio::document::utility_types::document_metadata::DocumentMetadata;
use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes;
use crate::messages::prelude::NodeGraphMessageHandler;
use crate::node_graph_executor::NodeGraphExecutor;
@@ -8,6 +9,7 @@ pub struct PropertiesPanelMessageHandlerData<'a> {
pub document_name: &'a str,
pub document_network: &'a NodeNetwork,
pub document_metadata: &'a mut DocumentMetadata,
pub selected_nodes: &'a SelectedNodes,
pub node_graph_message_handler: &'a NodeGraphMessageHandler,
pub executor: &'a mut NodeGraphExecutor,
}
@@ -1,3 +1,5 @@
use super::nodes::SelectedNodes;
use graph_craft::document::{DocumentNode, NodeId, NodeNetwork};
use graphene_core::renderer::ClickTarget;
use graphene_core::renderer::Quad;
@@ -19,7 +21,6 @@ pub struct DocumentMetadata {
artboards: HashSet<LayerNodeIdentifier>,
folders: HashSet<LayerNodeIdentifier>,
click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>,
selected_nodes: Vec<NodeId>,
/// Transform from document space to viewport space.
pub document_to_viewport: DAffine2,
}
@@ -32,7 +33,6 @@ impl Default for DocumentMetadata {
structure: HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]),
artboards: HashSet::new(),
folders: HashSet::new(),
selected_nodes: Vec::new(),
document_to_viewport: DAffine2::IDENTITY,
}
}
@@ -52,34 +52,6 @@ impl DocumentMetadata {
self.root().decendants(self)
}
pub fn all_layers_except_artboards(&self) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.all_layers().filter(move |layer| !self.artboards.contains(layer))
}
pub fn selected_layers(&self) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.all_layers().filter(|layer| self.selected_nodes.contains(&layer.to_node()))
}
pub fn selected_layers_except_artboards(&self) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.selected_layers().filter(move |layer| !self.artboards.contains(layer))
}
pub fn selected_layers_contains(&self, layer: LayerNodeIdentifier) -> bool {
self.selected_layers().any(|selected| selected == layer)
}
pub fn selected_nodes(&self) -> core::slice::Iter<'_, NodeId> {
self.selected_nodes.iter()
}
pub fn selected_nodes_ref(&self) -> &Vec<NodeId> {
&self.selected_nodes
}
pub fn has_selected_nodes(&self) -> bool {
!self.selected_nodes.is_empty()
}
pub fn layer_exists(&self, layer: LayerNodeIdentifier) -> bool {
self.structure.contains_key(&layer)
}
@@ -146,14 +118,9 @@ impl DocumentMetadata {
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| self.folders.contains(layer))
}
/// Folders sorted from most nested to least nested
pub fn folders_sorted_by_most_nested(&self, layers: impl Iterator<Item = LayerNodeIdentifier>) -> Vec<LayerNodeIdentifier> {
let mut folders: Vec<_> = self.folders(layers).collect();
let mut folders: Vec<_> = layers.filter(|layer| self.folders.contains(layer)).collect();
folders.sort_by_cached_key(|a| std::cmp::Reverse(a.ancestors(self).count()));
folders
}
@@ -164,24 +131,8 @@ impl DocumentMetadata {
// ==============================================
impl DocumentMetadata {
pub fn retain_selected_nodes(&mut self, f: impl FnMut(&NodeId) -> bool) {
self.selected_nodes.retain(f);
}
pub fn set_selected_nodes(&mut self, new: Vec<NodeId>) {
self.selected_nodes = new;
}
pub fn add_selected_nodes(&mut self, iter: impl IntoIterator<Item = NodeId>) {
self.selected_nodes.extend(iter);
}
pub fn clear_selected_nodes(&mut self) {
self.set_selected_nodes(Vec::new());
}
/// Loads the structure of layer nodes from a node graph.
pub fn load_structure(&mut self, graph: &NodeNetwork) {
pub fn load_structure(&mut self, graph: &NodeNetwork, selected_nodes: &mut SelectedNodes) {
fn first_child_layer<'a>(graph: &'a NodeNetwork, node: &DocumentNode) -> Option<(&'a DocumentNode, NodeId)> {
graph.upstream_flow_back_from_nodes(vec![node.inputs[0].as_node()?], true).find(|(node, _)| node.is_layer())
}
@@ -224,7 +175,7 @@ impl DocumentMetadata {
}
}
self.selected_nodes.retain(|node| graph.nodes.contains_key(node));
selected_nodes.0.retain(|node| graph.nodes.contains_key(node));
self.upstream_transforms.retain(|node, _| graph.nodes.contains_key(node));
self.click_targets.retain(|layer, _| self.structure.contains_key(layer));
}
@@ -328,8 +279,9 @@ impl DocumentMetadata {
}
/// Calculates the selected layer bounds in document space
pub fn selected_bounds_document_space(&self, include_artboards: bool) -> Option<[DVec2; 2]> {
self.selected_layers()
pub fn selected_bounds_document_space(&self, include_artboards: bool, metadata: &DocumentMetadata, selected_nodes: &SelectedNodes) -> Option<[DVec2; 2]> {
selected_nodes
.selected_layers(metadata)
.filter(|&layer| include_artboards || !self.is_artboard(layer))
.filter_map(|layer| self.bounding_box_document(layer))
.reduce(Quad::combine_bounds)
@@ -388,109 +340,109 @@ impl LayerNodeIdentifier {
}
/// Access the parent layer if possible
pub fn parent(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.parent)
pub fn parent(self, metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
metadata.get_relations(self).and_then(|relations| relations.parent)
}
/// Access the previous sibling of this layer (up the Layers panel)
pub fn previous_sibling(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.previous_sibling)
pub fn previous_sibling(self, metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
metadata.get_relations(self).and_then(|relations| relations.previous_sibling)
}
/// Access the next sibling of this layer (down the Layers panel)
pub fn next_sibling(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.next_sibling)
pub fn next_sibling(self, metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
metadata.get_relations(self).and_then(|relations| relations.next_sibling)
}
/// Access the first child of this layer (top most in Layers panel)
pub fn first_child(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.first_child)
pub fn first_child(self, metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
metadata.get_relations(self).and_then(|relations| relations.first_child)
}
/// Access the last child of this layer (bottom most in Layers panel)
pub fn last_child(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.last_child)
pub fn last_child(self, metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
metadata.get_relations(self).and_then(|relations| relations.last_child)
}
/// Does the layer have children?
pub fn has_children(self, document_metadata: &DocumentMetadata) -> bool {
self.first_child(document_metadata).is_some()
pub fn has_children(self, metadata: &DocumentMetadata) -> bool {
self.first_child(metadata).is_some()
}
/// Iterator over all direct children (excluding self and recursive children)
pub fn children(self, document_metadata: &DocumentMetadata) -> AxisIter {
pub fn children(self, metadata: &DocumentMetadata) -> AxisIter {
AxisIter {
layer_node: self.first_child(document_metadata),
layer_node: self.first_child(metadata),
next_node: Self::next_sibling,
document_metadata,
metadata,
}
}
/// All ancestors of this layer, including self, going to the document root
pub fn ancestors(self, document_metadata: &DocumentMetadata) -> AxisIter {
pub fn ancestors(self, metadata: &DocumentMetadata) -> AxisIter {
AxisIter {
layer_node: Some(self),
next_node: Self::parent,
document_metadata,
metadata,
}
}
/// Iterator through all the last children, starting from self
pub fn last_children(self, document_metadata: &DocumentMetadata) -> AxisIter {
pub fn last_children(self, metadata: &DocumentMetadata) -> AxisIter {
AxisIter {
layer_node: Some(self),
next_node: Self::last_child,
document_metadata,
metadata,
}
}
/// Iterator through all decendants, including recursive children (not including self)
pub fn decendants(self, document_metadata: &DocumentMetadata) -> DecendantsIter {
pub fn decendants(self, metadata: &DocumentMetadata) -> DecendantsIter {
DecendantsIter {
front: self.first_child(document_metadata),
back: self.last_child(document_metadata).and_then(|child| child.last_children(document_metadata).last()),
document_metadata,
front: self.first_child(metadata),
back: self.last_child(metadata).and_then(|child| child.last_children(metadata).last()),
metadata,
}
}
/// Add a child towards the top of the Layers panel
pub fn push_front_child(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
let parent = document_metadata.get_structure_mut(self);
pub fn push_front_child(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer");
let parent = metadata.get_structure_mut(self);
let old_first_child = parent.first_child.replace(new);
parent.last_child.get_or_insert(new);
if let Some(old_first_child) = old_first_child {
document_metadata.get_structure_mut(old_first_child).previous_sibling = Some(new);
metadata.get_structure_mut(old_first_child).previous_sibling = Some(new);
}
document_metadata.get_structure_mut(new).next_sibling = old_first_child;
document_metadata.get_structure_mut(new).parent = Some(self);
metadata.get_structure_mut(new).next_sibling = old_first_child;
metadata.get_structure_mut(new).parent = Some(self);
}
/// Add a child towards the bottom of the Layers panel
pub fn push_child(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
let parent = document_metadata.get_structure_mut(self);
pub fn push_child(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer");
let parent = metadata.get_structure_mut(self);
let old_last_child = parent.last_child.replace(new);
parent.first_child.get_or_insert(new);
if let Some(old_last_child) = old_last_child {
document_metadata.get_structure_mut(old_last_child).next_sibling = Some(new);
metadata.get_structure_mut(old_last_child).next_sibling = Some(new);
}
document_metadata.get_structure_mut(new).previous_sibling = old_last_child;
document_metadata.get_structure_mut(new).parent = Some(self);
metadata.get_structure_mut(new).previous_sibling = old_last_child;
metadata.get_structure_mut(new).parent = Some(self);
}
/// Add sibling above in the Layers panel
pub fn add_before(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
document_metadata.get_structure_mut(new).next_sibling = Some(self);
document_metadata.get_structure_mut(new).parent = self.parent(document_metadata);
let old_previous_sibling = document_metadata.get_structure_mut(self).previous_sibling.replace(new);
pub fn add_before(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer");
metadata.get_structure_mut(new).next_sibling = Some(self);
metadata.get_structure_mut(new).parent = self.parent(metadata);
let old_previous_sibling = metadata.get_structure_mut(self).previous_sibling.replace(new);
if let Some(old_previous_sibling) = old_previous_sibling {
document_metadata.get_structure_mut(old_previous_sibling).next_sibling = Some(new);
document_metadata.get_structure_mut(new).previous_sibling = Some(old_previous_sibling);
metadata.get_structure_mut(old_previous_sibling).next_sibling = Some(new);
metadata.get_structure_mut(new).previous_sibling = Some(old_previous_sibling);
} else if let Some(structure) = self
.parent(document_metadata)
.map(|parent| document_metadata.get_structure_mut(parent))
.parent(metadata)
.map(|parent| metadata.get_structure_mut(parent))
.filter(|structure| structure.first_child == Some(self))
{
structure.first_child = Some(new);
@@ -498,17 +450,17 @@ impl LayerNodeIdentifier {
}
/// Add sibling below in the Layers panel
pub fn add_after(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
document_metadata.get_structure_mut(new).previous_sibling = Some(self);
document_metadata.get_structure_mut(new).parent = self.parent(document_metadata);
let old_next_sibling = document_metadata.get_structure_mut(self).next_sibling.replace(new);
pub fn add_after(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer");
metadata.get_structure_mut(new).previous_sibling = Some(self);
metadata.get_structure_mut(new).parent = self.parent(metadata);
let old_next_sibling = metadata.get_structure_mut(self).next_sibling.replace(new);
if let Some(old_next_sibling) = old_next_sibling {
document_metadata.get_structure_mut(old_next_sibling).previous_sibling = Some(new);
document_metadata.get_structure_mut(new).next_sibling = Some(old_next_sibling);
metadata.get_structure_mut(old_next_sibling).previous_sibling = Some(new);
metadata.get_structure_mut(new).next_sibling = Some(old_next_sibling);
} else if let Some(structure) = self
.parent(document_metadata)
.map(|parent| document_metadata.get_structure_mut(parent))
.parent(metadata)
.map(|parent| metadata.get_structure_mut(parent))
.filter(|structure| structure.last_child == Some(self))
{
structure.last_child = Some(new);
@@ -516,18 +468,18 @@ impl LayerNodeIdentifier {
}
/// Delete layer and all children
pub fn delete(self, document_metadata: &mut DocumentMetadata) {
let previous_sibling = self.previous_sibling(document_metadata);
let next_sibling = self.next_sibling(document_metadata);
pub fn delete(self, metadata: &mut DocumentMetadata) {
let previous_sibling = self.previous_sibling(metadata);
let next_sibling = self.next_sibling(metadata);
if let Some(previous_sibling) = previous_sibling.map(|node| document_metadata.get_structure_mut(node)) {
if let Some(previous_sibling) = previous_sibling.map(|node| metadata.get_structure_mut(node)) {
previous_sibling.next_sibling = next_sibling;
}
if let Some(next_sibling) = next_sibling.map(|node| document_metadata.get_structure_mut(node)) {
if let Some(next_sibling) = next_sibling.map(|node| metadata.get_structure_mut(node)) {
next_sibling.previous_sibling = previous_sibling;
}
let mut parent = self.parent(document_metadata).map(|parent| document_metadata.get_structure_mut(parent));
let mut parent = self.parent(metadata).map(|parent| metadata.get_structure_mut(parent));
if let Some(structure) = parent.as_mut().filter(|structure| structure.first_child == Some(self)) {
structure.first_child = next_sibling;
}
@@ -536,22 +488,22 @@ impl LayerNodeIdentifier {
}
let mut delete = vec![self];
delete.extend(self.decendants(document_metadata));
delete.extend(self.decendants(metadata));
for node in delete {
document_metadata.structure.remove(&node);
metadata.structure.remove(&node);
}
}
pub fn exists(&self, document_metadata: &DocumentMetadata) -> bool {
document_metadata.get_relations(*self).is_some()
pub fn exists(&self, metadata: &DocumentMetadata) -> bool {
metadata.get_relations(*self).is_some()
}
pub fn starts_with(&self, other: Self, document_metadata: &DocumentMetadata) -> bool {
self.ancestors(document_metadata).any(|parent| parent == other)
pub fn starts_with(&self, other: Self, metadata: &DocumentMetadata) -> bool {
self.ancestors(metadata).any(|parent| parent == other)
}
pub fn child_of_root(&self, document_metadata: &DocumentMetadata) -> Self {
self.ancestors(document_metadata)
pub fn child_of_root(&self, metadata: &DocumentMetadata) -> Self {
self.ancestors(metadata)
.filter(|&layer| layer != LayerNodeIdentifier::ROOT)
.last()
.expect("There should be a layer before the root")
@@ -567,7 +519,7 @@ impl LayerNodeIdentifier {
pub struct AxisIter<'a> {
pub layer_node: Option<LayerNodeIdentifier>,
pub next_node: fn(LayerNodeIdentifier, &DocumentMetadata) -> Option<LayerNodeIdentifier>,
pub document_metadata: &'a DocumentMetadata,
pub metadata: &'a DocumentMetadata,
}
impl<'a> Iterator for AxisIter<'a> {
@@ -575,7 +527,7 @@ impl<'a> Iterator for AxisIter<'a> {
fn next(&mut self) -> Option<Self::Item> {
let layer_node = self.layer_node.take();
self.layer_node = layer_node.and_then(|node| (self.next_node)(node, self.document_metadata));
self.layer_node = layer_node.and_then(|node| (self.next_node)(node, self.metadata));
layer_node
}
}
@@ -588,7 +540,7 @@ impl<'a> Iterator for AxisIter<'a> {
pub struct DecendantsIter<'a> {
front: Option<LayerNodeIdentifier>,
back: Option<LayerNodeIdentifier>,
document_metadata: &'a DocumentMetadata,
metadata: &'a DocumentMetadata,
}
impl<'a> Iterator for DecendantsIter<'a> {
@@ -602,8 +554,8 @@ impl<'a> Iterator for DecendantsIter<'a> {
let layer_node = self.front.take();
if let Some(layer_node) = layer_node {
self.front = layer_node
.first_child(self.document_metadata)
.or_else(|| layer_node.ancestors(self.document_metadata).find_map(|ancestor| ancestor.next_sibling(self.document_metadata)));
.first_child(self.metadata)
.or_else(|| layer_node.ancestors(self.metadata).find_map(|ancestor| ancestor.next_sibling(self.metadata)));
}
layer_node
}
@@ -618,9 +570,9 @@ impl<'a> DoubleEndedIterator for DecendantsIter<'a> {
let layer_node = self.back.take();
if let Some(layer_node) = layer_node {
self.back = layer_node
.previous_sibling(self.document_metadata)
.and_then(|sibling| sibling.last_children(self.document_metadata).last())
.or_else(|| layer_node.parent(self.document_metadata));
.previous_sibling(self.metadata)
.and_then(|sibling| sibling.last_children(self.metadata).last())
.or_else(|| layer_node.parent(self.metadata));
}
layer_node
@@ -659,47 +611,47 @@ pub fn is_folder(layer: LayerNodeIdentifier, network: &NodeNetwork) -> bool {
#[test]
fn test_tree() {
let mut document_metadata = DocumentMetadata::default();
let root = document_metadata.root();
let document_metadata = &mut document_metadata;
root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(3)));
assert_eq!(root.children(document_metadata).collect::<Vec<_>>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]);
root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(6)));
assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![NodeId(3), NodeId(6)]);
assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![NodeId(3), NodeId(6)]);
LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(4)));
LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(2)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(5)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(9)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(8)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(7)));
root.push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(1)));
let mut metadata = DocumentMetadata::default();
let root = metadata.root();
let metadata = &mut metadata;
root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(3)));
assert_eq!(root.children(metadata).collect::<Vec<_>>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]);
root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(6)));
assert_eq!(root.children(metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![NodeId(3), NodeId(6)]);
assert_eq!(root.decendants(metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![NodeId(3), NodeId(6)]);
LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(4)));
LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(2)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(5)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(9)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(8)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(7)));
root.push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(1)));
assert_eq!(
root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
root.children(metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(9)]
);
assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
root.decendants(metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(7), NodeId(8), NodeId(9)]
);
assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(),
root.decendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(),
vec![NodeId(9), NodeId(8), NodeId(7), NodeId(6), NodeId(5), NodeId(4), NodeId(3), NodeId(2), NodeId(1)]
);
assert!(root.children(document_metadata).all(|child| child.parent(document_metadata) == Some(root)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(document_metadata);
LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(document_metadata);
LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(10)));
assert!(root.children(metadata).all(|child| child.parent(metadata) == Some(root)));
LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(metadata);
LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(metadata);
LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(10)));
assert_eq!(
root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
root.children(metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9)]
);
assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
root.decendants(metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9), NodeId(10)]
);
assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(),
root.decendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(),
vec![NodeId(10), NodeId(9), NodeId(5), NodeId(4), NodeId(3), NodeId(2)]
);
}
@@ -1,52 +0,0 @@
use graph_craft::document::NodeId;
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub struct RawBuffer(Vec<u8>);
impl From<&[u64]> for RawBuffer {
fn from(iter: &[u64]) -> Self {
let v_from_raw: Vec<u8> = iter.iter().flat_map(|x| x.to_ne_bytes()).collect();
Self(v_from_raw)
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, specta::Type)]
pub struct JsRawBuffer(Vec<u8>);
impl From<RawBuffer> for JsRawBuffer {
fn from(buffer: RawBuffer) -> Self {
Self(buffer.0)
}
}
impl Serialize for JsRawBuffer {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buffer = serializer.serialize_struct("Buffer", 2)?;
buffer.serialize_field("pointer", &(self.0.as_ptr() as usize))?;
buffer.serialize_field("length", &(self.0.len()))?;
buffer.end()
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub enum LayerClassification {
#[default]
Folder,
Artboard,
Layer,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub struct LayerPanelEntry {
pub id: NodeId,
pub name: String,
pub tooltip: String,
#[serde(rename = "layerClassification")]
pub layer_classification: LayerClassification,
pub expanded: bool,
pub disabled: bool,
#[serde(rename = "parentId")]
pub parent_id: Option<NodeId>,
pub depth: usize,
}
@@ -1,6 +1,6 @@
pub mod clipboards;
pub mod document_metadata;
pub mod error;
pub mod layer_panel;
pub mod misc;
pub mod nodes;
pub mod transformation;
@@ -0,0 +1,110 @@
use graph_craft::document::{NodeId, NodeNetwork};
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize};
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub struct RawBuffer(Vec<u8>);
impl From<&[u64]> for RawBuffer {
fn from(iter: &[u64]) -> Self {
let v_from_raw: Vec<u8> = iter.iter().flat_map(|x| x.to_ne_bytes()).collect();
Self(v_from_raw)
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, specta::Type)]
pub struct JsRawBuffer(Vec<u8>);
impl From<RawBuffer> for JsRawBuffer {
fn from(buffer: RawBuffer) -> Self {
Self(buffer.0)
}
}
impl Serialize for JsRawBuffer {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buffer = serializer.serialize_struct("Buffer", 2)?;
buffer.serialize_field("pointer", &(self.0.as_ptr() as usize))?;
buffer.serialize_field("length", &(self.0.len()))?;
buffer.end()
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub enum LayerClassification {
#[default]
Folder,
Artboard,
Layer,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub struct LayerPanelEntry {
pub id: NodeId,
pub name: String,
pub tooltip: String,
#[serde(rename = "layerClassification")]
pub layer_classification: LayerClassification,
pub expanded: bool,
pub disabled: bool,
#[serde(rename = "parentId")]
pub parent_id: Option<NodeId>,
pub depth: usize,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub struct SelectedNodes(pub Vec<NodeId>);
impl SelectedNodes {
pub fn layer_visible(&self, layer: LayerNodeIdentifier, network: &NodeNetwork, metadata: &DocumentMetadata) -> bool {
!layer.ancestors(metadata).any(|layer| network.disabled.contains(&layer.to_node()))
}
pub fn selected_visible_layers<'a>(&'a self, network: &'a NodeNetwork, metadata: &'a DocumentMetadata) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.selected_layers(metadata).filter(move |&layer| self.layer_visible(layer, network, metadata))
}
pub fn selected_layers<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
metadata.all_layers().filter(|layer| self.0.contains(&layer.to_node()))
}
pub fn selected_layers_except_artboards<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.selected_layers(metadata).filter(move |&layer| !metadata.is_artboard(layer))
}
pub fn selected_layers_contains(&self, layer: LayerNodeIdentifier, metadata: &DocumentMetadata) -> bool {
self.selected_layers(metadata).any(|selected| selected == layer)
}
pub fn selected_nodes(&self) -> core::slice::Iter<'_, NodeId> {
self.0.iter()
}
pub fn selected_nodes_ref(&self) -> &Vec<NodeId> {
&self.0
}
pub fn has_selected_nodes(&self) -> bool {
!self.0.is_empty()
}
pub fn retain_selected_nodes(&mut self, f: impl FnMut(&NodeId) -> bool) {
self.0.retain(f);
}
pub fn set_selected_nodes(&mut self, new: Vec<NodeId>) {
self.0 = new;
}
pub fn add_selected_nodes(&mut self, iter: impl IntoIterator<Item = NodeId>) {
self.0.extend(iter);
}
pub fn clear_selected_nodes(&mut self) {
self.set_selected_nodes(Vec::new());
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
pub struct CollapsedLayers(pub Vec<LayerNodeIdentifier>);