mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-30 09:47:22 +00:00
Move selected node list from DocumentMetadata to the document (#1565)
This commit is contained in:
parent
aab0fcf84c
commit
78a1bb17cd
27 changed files with 511 additions and 465 deletions
|
@ -306,8 +306,8 @@ mod test {
|
|||
});
|
||||
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
|
||||
|
||||
let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(layers_before_copy.len(), 3);
|
||||
assert_eq!(layers_after_copy.len(), 4);
|
||||
|
@ -329,7 +329,7 @@ mod test {
|
|||
let mut editor = create_editor_with_three_layers();
|
||||
|
||||
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
|
||||
let shape_id = document_before_copy.document_metadata.all_layers().nth(1).unwrap();
|
||||
let shape_id = document_before_copy.metadata.all_layers().nth(1).unwrap();
|
||||
|
||||
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![shape_id.to_node()] });
|
||||
editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::Internal });
|
||||
|
@ -341,8 +341,8 @@ mod test {
|
|||
|
||||
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
|
||||
|
||||
let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(layers_before_copy.len(), 3);
|
||||
assert_eq!(layers_after_copy.len(), 4);
|
||||
|
@ -384,8 +384,8 @@ mod test {
|
|||
|
||||
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
|
||||
|
||||
let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
let [original_folder, original_freehand, original_line, original_ellipse, original_polygon, original_rect] = layers_before_copy[..] else {
|
||||
panic!("Layers before incorrect");
|
||||
};
|
||||
|
@ -413,7 +413,7 @@ mod test {
|
|||
let mut editor = create_editor_with_three_layers();
|
||||
|
||||
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
|
||||
let mut layers = document_before_copy.document_metadata.all_layers();
|
||||
let mut layers = document_before_copy.metadata.all_layers();
|
||||
let rect_id = layers.next().expect("rectangle");
|
||||
let shape_id = layers.next().expect("shape");
|
||||
let ellipse_id = layers.next().expect("ellipse");
|
||||
|
@ -437,8 +437,8 @@ mod test {
|
|||
|
||||
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
|
||||
|
||||
let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(layers_before_copy.len(), 3);
|
||||
assert_eq!(layers_after_copy.len(), 6);
|
||||
|
|
|
@ -75,7 +75,7 @@ impl MessageHandler<DialogMessage, DialogData<'_>> for DialogMessageHandler {
|
|||
if let Some(document) = portfolio.active_document() {
|
||||
let mut index = 0;
|
||||
let artboards = document
|
||||
.document_metadata
|
||||
.metadata
|
||||
.all_layers()
|
||||
.filter(|&layer| is_layer_fed_by_node_of_name(layer, &document.network, "Artboard"))
|
||||
.map(|layer| {
|
||||
|
@ -92,7 +92,7 @@ impl MessageHandler<DialogMessage, DialogData<'_>> for DialogMessageHandler {
|
|||
self.export_dialog = ExportDialogMessageHandler {
|
||||
scale_factor: 1.,
|
||||
artboards,
|
||||
has_selection: document.metadata().selected_layers().next().is_some(),
|
||||
has_selection: document.selected_nodes.selected_layers(document.metadata()).next().is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
self.export_dialog.send_dialog_to_frontend(responses);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon};
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::node_graph::{FrontendNode, FrontendNodeLink, FrontendNodeType};
|
||||
use crate::messages::portfolio::document::utility_types::layer_panel::{JsRawBuffer, LayerPanelEntry, RawBuffer};
|
||||
use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer};
|
||||
use crate::messages::prelude::*;
|
||||
use crate::messages::tool::utility_types::HintData;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
110
editor/src/messages/portfolio/document/utility_types/nodes.rs
Normal file
110
editor/src/messages/portfolio/document/utility_types/nodes.rs
Normal file
|
@ -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>);
|
|
@ -163,7 +163,10 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
|||
};
|
||||
|
||||
let copy_val = |buffer: &mut Vec<CopyBufferEntry>| {
|
||||
for layer_path in active_document.metadata().shallowest_unique_layers(active_document.metadata().selected_layers()) {
|
||||
for layer_path in active_document
|
||||
.metadata()
|
||||
.shallowest_unique_layers(active_document.selected_nodes.selected_layers(active_document.metadata()))
|
||||
{
|
||||
let Some(layer) = layer_path.last().copied() else {
|
||||
continue;
|
||||
};
|
||||
|
@ -184,7 +187,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
|||
.collect(),
|
||||
)
|
||||
.collect(),
|
||||
selected: active_document.metadata().selected_layers_contains(layer),
|
||||
selected: active_document.selected_nodes.selected_layers_contains(layer, active_document.metadata()),
|
||||
collapsed: false,
|
||||
});
|
||||
}
|
||||
|
@ -526,7 +529,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
|||
);
|
||||
|
||||
if let Some(document) = self.active_document() {
|
||||
if document.metadata().selected_layers().next().is_some() {
|
||||
if document.selected_nodes.selected_layers(document.metadata()).next().is_some() {
|
||||
let select = actions!(PortfolioMessageDiscriminant;
|
||||
Copy,
|
||||
Cut,
|
||||
|
|
|
@ -45,7 +45,7 @@ impl Pivot {
|
|||
|
||||
/// Recomputes the pivot position and transform.
|
||||
fn recalculate_pivot(&mut self, document: &DocumentMessageHandler) {
|
||||
let mut layers = document.selected_visible_layers();
|
||||
let mut layers = document.selected_nodes.selected_visible_layers(document.network(), document.metadata());
|
||||
let Some(first) = layers.next() else {
|
||||
// If no layers are selected then we revert things back to default
|
||||
self.normalized_pivot = DVec2::splat(0.5);
|
||||
|
@ -65,8 +65,9 @@ impl Pivot {
|
|||
} else {
|
||||
// If more than one layer is selected we use the AABB with the mean of the pivots
|
||||
let xy_summation = document
|
||||
.selected_visible_layers()
|
||||
.map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.network, &document.document_metadata))
|
||||
.selected_nodes
|
||||
.selected_visible_layers(document.network(), document.metadata())
|
||||
.map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.network, &document.metadata))
|
||||
.reduce(|a, b| a + b)
|
||||
.unwrap_or_default();
|
||||
|
||||
|
@ -100,7 +101,7 @@ impl Pivot {
|
|||
|
||||
/// Sets the viewport position of the pivot for all selected layers.
|
||||
pub fn set_viewport_position(&self, position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
for layer in document.selected_visible_layers() {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
let transform = Self::get_layer_pivot_transform(layer, document);
|
||||
let pivot = transform.inverse().transform_point2(position);
|
||||
// Only update the pivot when computed position is finite. Infinite can happen when scale is 0.
|
||||
|
|
|
@ -266,10 +266,10 @@ impl BrushToolData {
|
|||
fn load_existing_strokes(&mut self, document: &DocumentMessageHandler) -> Option<LayerNodeIdentifier> {
|
||||
self.transform = DAffine2::IDENTITY;
|
||||
|
||||
if document.metadata().selected_layers().count() != 1 {
|
||||
if document.selected_nodes.selected_layers(document.metadata()).count() != 1 {
|
||||
return None;
|
||||
}
|
||||
let Some(layer) = document.metadata().selected_layers().next() else {
|
||||
let Some(layer) = document.selected_nodes.selected_layers(document.metadata()).next() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ impl Fsm for GradientToolFsmState {
|
|||
(_, GradientToolMessage::Overlays(mut overlay_context)) => {
|
||||
let selected = tool_data.selected_gradient.as_ref();
|
||||
|
||||
for layer in document.selected_visible_layers() {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
let Some(gradient) = get_gradient(layer, &document.network) else { continue };
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
let dragging = selected.filter(|selected| selected.layer == layer).map(|selected| selected.dragging);
|
||||
|
@ -366,7 +366,7 @@ impl Fsm for GradientToolFsmState {
|
|||
self
|
||||
}
|
||||
(_, GradientToolMessage::InsertStop) => {
|
||||
for layer in document.selected_visible_layers() {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
let Some(mut gradient) = get_gradient(layer, &document.network) else { continue };
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
|
||||
|
@ -407,7 +407,7 @@ impl Fsm for GradientToolFsmState {
|
|||
let tolerance = (MANIPULATOR_GROUP_MARKER_SIZE * 2.).powi(2);
|
||||
|
||||
let mut dragging = false;
|
||||
for layer in document.selected_visible_layers() {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
let Some(gradient) = get_gradient(layer, &document.network) else { continue };
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
|
||||
|
@ -448,7 +448,7 @@ impl Fsm for GradientToolFsmState {
|
|||
|
||||
// Apply the gradient to the selected layer
|
||||
if let Some(layer) = selected_layer {
|
||||
if !document.metadata().selected_layers_contains(layer) {
|
||||
if !document.selected_nodes.selected_layers_contains(layer, document.metadata()) {
|
||||
let nodes = vec![layer.to_node()];
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes });
|
||||
|
|
|
@ -223,7 +223,7 @@ impl PathToolData {
|
|||
let _selected_layers = shape_editor.selected_layers().cloned().collect::<Vec<_>>();
|
||||
|
||||
// Select the first point within the threshold (in pixels)
|
||||
if let Some(selected_points) = shape_editor.select_point(&document.network, &document.document_metadata, input.mouse.position, SELECTION_THRESHOLD, shift) {
|
||||
if let Some(selected_points) = shape_editor.select_point(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD, shift) {
|
||||
self.start_dragging_point(selected_points, input, document, responses);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
|
@ -298,7 +298,7 @@ impl PathToolData {
|
|||
|
||||
// Move the selected points with the mouse
|
||||
let snapped_position = self.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
shape_editor.move_selected_points(&document.network, &document.document_metadata, snapped_position - self.previous_mouse_position, shift, responses);
|
||||
shape_editor.move_selected_points(&document.network, &document.metadata, snapped_position - self.previous_mouse_position, shift, responses);
|
||||
self.previous_mouse_position = snapped_position;
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ impl Fsm for PathToolFsmState {
|
|||
match (self, event) {
|
||||
(_, PathToolMessage::SelectionChanged) => {
|
||||
// Set the newly targeted layers to visible
|
||||
let target_layers = document.metadata().selected_layers().collect();
|
||||
let target_layers = document.selected_nodes.selected_layers(document.metadata()).collect();
|
||||
shape_editor.set_selected_layers(target_layers);
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
@ -362,12 +362,7 @@ impl Fsm for PathToolFsmState {
|
|||
if tool_data.drag_start_pos == tool_data.previous_mouse_position {
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![] });
|
||||
} else {
|
||||
shape_editor.select_all_in_quad(
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
[tool_data.drag_start_pos, tool_data.previous_mouse_position],
|
||||
!shift_pressed,
|
||||
);
|
||||
shape_editor.select_all_in_quad(&document.network, &document.metadata, [tool_data.drag_start_pos, tool_data.previous_mouse_position], !shift_pressed);
|
||||
}
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
|
@ -381,12 +376,7 @@ impl Fsm for PathToolFsmState {
|
|||
if tool_data.drag_start_pos == tool_data.previous_mouse_position {
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![] });
|
||||
} else {
|
||||
shape_editor.select_all_in_quad(
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
[tool_data.drag_start_pos, tool_data.previous_mouse_position],
|
||||
!shift_pressed,
|
||||
);
|
||||
shape_editor.select_all_in_quad(&document.network, &document.metadata, [tool_data.drag_start_pos, tool_data.previous_mouse_position], !shift_pressed);
|
||||
}
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||
|
@ -398,16 +388,16 @@ impl Fsm for PathToolFsmState {
|
|||
let shift_pressed = input.keyboard.get(shift_mirror_distance as usize);
|
||||
|
||||
let nearest_point = shape_editor
|
||||
.find_nearest_point_indices(&document.network, &document.document_metadata, input.mouse.position, SELECTION_THRESHOLD)
|
||||
.find_nearest_point_indices(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD)
|
||||
.map(|(_, nearest_point)| nearest_point);
|
||||
|
||||
shape_editor.delete_selected_handles_with_zero_length(&document.network, &document.document_metadata, &tool_data.opposing_handle_lengths, responses);
|
||||
shape_editor.delete_selected_handles_with_zero_length(&document.network, &document.metadata, &tool_data.opposing_handle_lengths, responses);
|
||||
|
||||
if tool_data.drag_start_pos.distance(input.mouse.position) <= DRAG_THRESHOLD && !shift_pressed {
|
||||
let clicked_selected = shape_editor.selected_points().any(|&point| nearest_point == Some(point));
|
||||
if clicked_selected {
|
||||
shape_editor.deselect_all();
|
||||
shape_editor.select_point(&document.network, &document.document_metadata, input.mouse.position, SELECTION_THRESHOLD, false);
|
||||
shape_editor.select_point(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD, false);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
}
|
||||
}
|
||||
|
@ -428,9 +418,9 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
(_, PathToolMessage::InsertPoint) => {
|
||||
// First we try and flip the sharpness (if they have clicked on an anchor)
|
||||
if !shape_editor.flip_sharp(&document.network, &document.document_metadata, input.mouse.position, SELECTION_TOLERANCE, responses) {
|
||||
if !shape_editor.flip_sharp(&document.network, &document.metadata, input.mouse.position, SELECTION_TOLERANCE, responses) {
|
||||
// If not, then we try and split the path that may have been clicked upon
|
||||
shape_editor.split(&document.network, &document.document_metadata, input.mouse.position, SELECTION_TOLERANCE, responses);
|
||||
shape_editor.split(&document.network, &document.metadata, input.mouse.position, SELECTION_TOLERANCE, responses);
|
||||
}
|
||||
|
||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||
|
@ -443,7 +433,7 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
(_, PathToolMessage::PointerMove { .. }) => self,
|
||||
(_, PathToolMessage::NudgeSelectedPoints { delta_x, delta_y }) => {
|
||||
shape_editor.move_selected_points(&document.network, &document.document_metadata, (delta_x, delta_y).into(), true, responses);
|
||||
shape_editor.move_selected_points(&document.network, &document.metadata, (delta_x, delta_y).into(), true, responses);
|
||||
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
|
@ -454,18 +444,18 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
(_, PathToolMessage::SelectedPointXChanged { new_x }) => {
|
||||
if let Some(&SingleSelectedPoint { coordinates, id, layer, .. }) = tool_data.selection_status.as_one() {
|
||||
shape_editor.reposition_control_point(&id, responses, &document.network, &document.document_metadata, DVec2::new(new_x, coordinates.y), layer);
|
||||
shape_editor.reposition_control_point(&id, responses, &document.network, &document.metadata, DVec2::new(new_x, coordinates.y), layer);
|
||||
}
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(_, PathToolMessage::SelectedPointYChanged { new_y }) => {
|
||||
if let Some(&SingleSelectedPoint { coordinates, id, layer, .. }) = tool_data.selection_status.as_one() {
|
||||
shape_editor.reposition_control_point(&id, responses, &document.network, &document.document_metadata, DVec2::new(coordinates.x, new_y), layer);
|
||||
shape_editor.reposition_control_point(&id, responses, &document.network, &document.metadata, DVec2::new(coordinates.x, new_y), layer);
|
||||
}
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(_, PathToolMessage::SelectedPointUpdated) => {
|
||||
tool_data.selection_status = get_selection_status(&document.network, &document.document_metadata, shape_editor);
|
||||
tool_data.selection_status = get_selection_status(&document.network, &document.metadata, shape_editor);
|
||||
self
|
||||
}
|
||||
(_, PathToolMessage::ManipulatorAngleMakeSmooth) => {
|
||||
|
|
|
@ -720,7 +720,7 @@ fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64)
|
|||
let mut best = None;
|
||||
let mut best_distance_squared = tolerance * tolerance;
|
||||
|
||||
for layer in document.metadata().selected_layers() {
|
||||
for layer in document.selected_nodes.selected_layers(document.metadata()) {
|
||||
let viewspace = document.metadata().transform_to_viewport(layer);
|
||||
|
||||
let subpaths = get_subpaths(layer, &document.network)?;
|
||||
|
|
|
@ -381,27 +381,32 @@ impl Fsm for SelectToolFsmState {
|
|||
};
|
||||
match (self, event) {
|
||||
(_, SelectToolMessage::Overlays(mut overlay_context)) => {
|
||||
let selected_layers_count = document.metadata().selected_layers().count();
|
||||
let selected_layers_count = document.selected_nodes.selected_layers(document.metadata()).count();
|
||||
tool_data.selected_layers_changed = selected_layers_count != tool_data.selected_layers_count;
|
||||
tool_data.selected_layers_count = selected_layers_count;
|
||||
|
||||
// Outline selected layers
|
||||
for layer in document.selected_visible_layers() {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
overlay_context.outline(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer));
|
||||
}
|
||||
|
||||
// Get the layer the user is hovering over
|
||||
let click = document.click(input.mouse.position, &document.network);
|
||||
let not_selected_click = click.filter(|&hovered_layer| !document.metadata().selected_layers_contains(hovered_layer));
|
||||
let not_selected_click = click.filter(|&hovered_layer| !document.selected_nodes.selected_layers_contains(hovered_layer, document.metadata()));
|
||||
if let Some(layer) = not_selected_click {
|
||||
overlay_context.outline(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer));
|
||||
}
|
||||
|
||||
// Update bounds
|
||||
let transform = document.selected_visible_layers().next().map(|layer| document.metadata().transform_to_viewport(layer));
|
||||
let transform = document
|
||||
.selected_nodes
|
||||
.selected_visible_layers(document.network(), document.metadata())
|
||||
.next()
|
||||
.map(|layer| document.metadata().transform_to_viewport(layer));
|
||||
let transform = transform.unwrap_or(DAffine2::IDENTITY);
|
||||
let bounds = document
|
||||
.selected_visible_layers()
|
||||
.selected_nodes
|
||||
.selected_visible_layers(document.network(), document.metadata())
|
||||
.filter_map(|layer| {
|
||||
document
|
||||
.metadata()
|
||||
|
@ -462,7 +467,7 @@ impl Fsm for SelectToolFsmState {
|
|||
.map(|bounding_box| bounding_box.check_rotate(input.mouse.position))
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut selected: Vec<_> = document.selected_visible_layers().collect();
|
||||
let mut selected: Vec<_> = document.selected_nodes.selected_visible_layers(document.network(), document.metadata()).collect();
|
||||
let intersection = document.click(input.mouse.position, &document.network);
|
||||
|
||||
// If the user is dragging the bounding box bounds, go into ResizingBounds mode.
|
||||
|
@ -491,7 +496,7 @@ impl Fsm for SelectToolFsmState {
|
|||
&tool_data.layers_dragging,
|
||||
responses,
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
&document.metadata,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
);
|
||||
|
@ -510,7 +515,7 @@ impl Fsm for SelectToolFsmState {
|
|||
&selected,
|
||||
responses,
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
&document.metadata,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
);
|
||||
|
@ -630,7 +635,7 @@ impl Fsm for SelectToolFsmState {
|
|||
selected,
|
||||
responses,
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
&document.metadata,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
);
|
||||
|
@ -665,7 +670,7 @@ impl Fsm for SelectToolFsmState {
|
|||
&tool_data.layers_dragging,
|
||||
responses,
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
&document.metadata,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
);
|
||||
|
@ -723,7 +728,11 @@ impl Fsm for SelectToolFsmState {
|
|||
let intersection = document.intersect_quad(quad, &document.network);
|
||||
|
||||
if let Some(path) = intersection.last() {
|
||||
let replacement_selected_layers: Vec<_> = document.metadata().selected_layers().filter(|&layer| !path.starts_with(layer, document.metadata())).collect();
|
||||
let replacement_selected_layers: Vec<_> = document
|
||||
.selected_nodes
|
||||
.selected_layers(document.metadata())
|
||||
.filter(|&layer| !path.starts_with(layer, document.metadata()))
|
||||
.collect();
|
||||
|
||||
tool_data.layers_dragging.clear();
|
||||
tool_data.layers_dragging.extend(replacement_selected_layers.iter());
|
||||
|
@ -791,7 +800,7 @@ impl Fsm for SelectToolFsmState {
|
|||
(SelectToolFsmState::DrawingBox, SelectToolMessage::DragStop { .. } | SelectToolMessage::Enter) => {
|
||||
let quad = tool_data.selection_quad();
|
||||
let new_selected: HashSet<_> = document.intersect_quad(quad, &document.network).collect();
|
||||
let current_selected: HashSet<_> = document.metadata().selected_layers().collect();
|
||||
let current_selected: HashSet<_> = document.selected_nodes.selected_layers(document.metadata()).collect();
|
||||
if new_selected != current_selected {
|
||||
tool_data.layers_dragging = new_selected.into_iter().collect();
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
@ -804,7 +813,7 @@ impl Fsm for SelectToolFsmState {
|
|||
SelectToolFsmState::Ready
|
||||
}
|
||||
(SelectToolFsmState::Ready, SelectToolMessage::Enter) => {
|
||||
let mut selected_layers = document.metadata().selected_layers();
|
||||
let mut selected_layers = document.selected_nodes.selected_layers(document.metadata());
|
||||
|
||||
if let Some(layer) = selected_layers.next() {
|
||||
// Check that only one layer is selected
|
||||
|
@ -832,7 +841,7 @@ impl Fsm for SelectToolFsmState {
|
|||
&tool_data.layers_dragging,
|
||||
responses,
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
&document.metadata,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
);
|
||||
|
@ -908,7 +917,9 @@ impl Fsm for SelectToolFsmState {
|
|||
|
||||
fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) {
|
||||
let layer = selected[0];
|
||||
let ancestor = layer.ancestors(document.metadata()).find(|&ancestor| document.metadata().selected_layers_contains(ancestor));
|
||||
let ancestor = layer
|
||||
.ancestors(document.metadata())
|
||||
.find(|&ancestor| document.selected_nodes.selected_layers_contains(ancestor, document.metadata()));
|
||||
|
||||
let new_selected = ancestor.unwrap_or_else(|| layer.child_of_root(document.metadata()));
|
||||
|
||||
|
@ -932,15 +943,16 @@ fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, mut selected: Ve
|
|||
}
|
||||
|
||||
fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
|
||||
if document.metadata().selected_layers_contains(layer) {
|
||||
if document.selected_nodes.selected_layers_contains(layer, document.metadata()) {
|
||||
responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Path });
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(new_selected) = layer
|
||||
.ancestors(document.metadata())
|
||||
.find(|ancestor| ancestor.parent(document.metadata()).is_some_and(|parent| document.metadata().selected_layers_contains(parent)))
|
||||
else {
|
||||
let Some(new_selected) = layer.ancestors(document.metadata()).find(|ancestor| {
|
||||
ancestor
|
||||
.parent(document.metadata())
|
||||
.is_some_and(|parent| document.selected_nodes.selected_layers_contains(parent, document.metadata()))
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -344,9 +344,9 @@ impl TextToolData {
|
|||
}
|
||||
|
||||
fn can_edit_selected(document: &DocumentMessageHandler) -> Option<LayerNodeIdentifier> {
|
||||
let mut selected_layers = document.metadata().selected_layers();
|
||||
|
||||
let mut selected_layers = document.selected_nodes.selected_layers(document.metadata());
|
||||
let layer = selected_layers.next()?;
|
||||
|
||||
// Check that only one layer is selected
|
||||
if selected_layers.next().is_some() {
|
||||
return None;
|
||||
|
@ -392,7 +392,7 @@ impl Fsm for TextToolFsmState {
|
|||
TextToolFsmState::Editing
|
||||
}
|
||||
(_, TextToolMessage::Overlays(mut overlay_context)) => {
|
||||
for layer in document.metadata().selected_layers() {
|
||||
for layer in document.selected_nodes.selected_layers(document.metadata()) {
|
||||
let Some((text, font, font_size)) = graph_modification_utils::get_text(layer, &document.network) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
@ -48,7 +48,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
|
|||
|
||||
let using_path_tool = tool_data.active_tool_type == ToolType::Path;
|
||||
|
||||
let selected_layers = document.metadata().selected_layers().collect::<Vec<_>>();
|
||||
let selected_layers = document.selected_nodes.selected_layers(document.metadata()).collect::<Vec<_>>();
|
||||
|
||||
let mut selected = Selected::new(
|
||||
&mut self.original_transforms,
|
||||
|
@ -56,7 +56,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
|
|||
&selected_layers,
|
||||
responses,
|
||||
&document.network,
|
||||
&document.document_metadata,
|
||||
&document.metadata,
|
||||
Some(shape_editor),
|
||||
&tool_data.active_tool_type,
|
||||
);
|
||||
|
@ -222,7 +222,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
|
|||
self.mouse_position = input.mouse.position;
|
||||
}
|
||||
SelectionChanged => {
|
||||
let target_layers = document.metadata().selected_layers().collect();
|
||||
let target_layers = document.selected_nodes.selected_layers(document.metadata()).collect();
|
||||
shape_editor.set_selected_layers(target_layers);
|
||||
}
|
||||
TypeBackspace => self.transform_operation.grs_typed(self.typing.type_backspace(), &mut selected, self.snap),
|
||||
|
|
|
@ -449,7 +449,7 @@ impl NodeGraphExecutor {
|
|||
|
||||
let render_config = RenderConfig {
|
||||
viewport: Footprint {
|
||||
transform: document.document_metadata.document_to_viewport,
|
||||
transform: document.metadata.document_to_viewport,
|
||||
resolution: viewport_resolution,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -477,7 +477,9 @@ impl NodeGraphExecutor {
|
|||
// Calculate the bounding box of the region to be exported
|
||||
let bounds = match export_config.bounds {
|
||||
ExportBounds::AllArtwork => document.metadata().document_bounds_document_space(!export_config.transparent_background),
|
||||
ExportBounds::Selection => document.metadata().selected_bounds_document_space(!export_config.transparent_background),
|
||||
ExportBounds::Selection => document
|
||||
.metadata()
|
||||
.selected_bounds_document_space(!export_config.transparent_background, document.metadata(), &document.selected_nodes),
|
||||
ExportBounds::Artboard(id) => document.metadata().bounding_box_document(id),
|
||||
}
|
||||
.ok_or_else(|| "No bounding box".to_string())?;
|
||||
|
@ -558,8 +560,8 @@ impl NodeGraphExecutor {
|
|||
|
||||
let node_graph_output = result.map_err(|e| format!("Node graph evaluation failed: {e:?}"))?;
|
||||
|
||||
document.document_metadata.update_transforms(new_upstream_transforms);
|
||||
document.document_metadata.update_click_targets(new_click_targets);
|
||||
document.metadata.update_transforms(new_upstream_transforms);
|
||||
document.metadata.update_click_targets(new_click_targets);
|
||||
|
||||
let execution_context = self.futures.remove(&execution_id).ok_or_else(|| "Invalid generation ID".to_string())?;
|
||||
if let Some(export_config) = execution_context.export_config {
|
||||
|
|
|
@ -13,7 +13,7 @@ use fern::colors::{Color, ColoredLevelConfig};
|
|||
// use http::{Response, StatusCode};
|
||||
use std::cell::RefCell;
|
||||
// use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
// use std::sync::Arc;
|
||||
// use std::sync::Mutex;
|
||||
|
||||
thread_local! {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue