mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 21:46:08 +08:00
Merge branch 'master' into lock-layer-feature
This commit is contained in:
@@ -57,7 +57,7 @@ pub fn default_mapping() -> Mapping {
|
||||
entry!(KeyDown(KeyX); modifiers=[Accel], action_dispatch=NodeGraphMessage::Cut),
|
||||
entry!(KeyDown(KeyC); modifiers=[Accel], action_dispatch=NodeGraphMessage::Copy),
|
||||
entry!(KeyDown(KeyD); modifiers=[Accel], action_dispatch=NodeGraphMessage::DuplicateSelectedNodes),
|
||||
entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=NodeGraphMessage::ToggleSelectedHidden),
|
||||
entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=NodeGraphMessage::ToggleSelectedVisibility),
|
||||
//
|
||||
// TransformLayerMessage
|
||||
entry!(KeyDown(Enter); action_dispatch=TransformLayerMessage::ApplyTransformOperation),
|
||||
|
||||
@@ -822,7 +822,7 @@ impl DocumentMessageHandler {
|
||||
self.metadata
|
||||
.root()
|
||||
.descendants(&self.metadata)
|
||||
.filter(|&layer| self.selected_nodes.layer_visible(layer, self.network(), self.metadata()))
|
||||
.filter(|&layer| self.selected_nodes.layer_visible(layer, self.metadata()))
|
||||
.filter(|&layer| !is_artboard(layer, network))
|
||||
.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))))
|
||||
@@ -835,7 +835,7 @@ impl DocumentMessageHandler {
|
||||
self.metadata
|
||||
.root()
|
||||
.descendants(&self.metadata)
|
||||
.filter(|&layer| self.selected_nodes.layer_visible(layer, self.network(), self.metadata()))
|
||||
.filter(|&layer| self.selected_nodes.layer_visible(layer, 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)
|
||||
@@ -849,7 +849,7 @@ 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_nodes
|
||||
.selected_visible_layers(self.network(), self.metadata())
|
||||
.selected_visible_layers(self.metadata())
|
||||
.filter_map(|layer| self.metadata.bounding_box_viewport(layer))
|
||||
.reduce(graphene_core::renderer::Quad::combine_bounds)
|
||||
}
|
||||
@@ -887,13 +887,6 @@ impl DocumentMessageHandler {
|
||||
Ok(document)
|
||||
}
|
||||
|
||||
/// Returns the bounding boxes for all visible layers.
|
||||
pub fn bounding_boxes(&self) -> impl Iterator<Item = [DVec2; 2]> + '_ {
|
||||
// TODO: Remove this function entirely?
|
||||
// self.visible_layers().filter_map(|path| self.document_legacy.viewport_bounding_box(path, font_cache).ok()?)
|
||||
std::iter::empty()
|
||||
}
|
||||
|
||||
/// Called recursively by the entry function [`serialize_root`].
|
||||
fn serialize_structure(&self, folder: LayerNodeIdentifier, structure_section: &mut Vec<u64>, data_section: &mut Vec<u64>, path: &mut Vec<LayerNodeIdentifier>) {
|
||||
let mut space = 0;
|
||||
|
||||
@@ -89,13 +89,13 @@ pub enum NodeGraphMessage {
|
||||
ShiftNode {
|
||||
node_id: NodeId,
|
||||
},
|
||||
ToggleSelectedHidden,
|
||||
ToggleHidden {
|
||||
ToggleSelectedVisibility,
|
||||
ToggleVisibility {
|
||||
node_id: NodeId,
|
||||
},
|
||||
SetHidden {
|
||||
SetVisibility {
|
||||
node_id: NodeId,
|
||||
hidden: bool,
|
||||
visible: bool,
|
||||
},
|
||||
ToggleSelectedLocked,
|
||||
ToggleLocked {
|
||||
|
||||
@@ -59,8 +59,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
load_network_structure(document_network, document_metadata, selected_nodes, collapsed);
|
||||
}
|
||||
NodeGraphMessage::SelectedNodesUpdated => {
|
||||
self.update_selection_action_buttons(document_network, selected_nodes, responses);
|
||||
self.update_selected(document_network, selected_nodes, responses);
|
||||
self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses);
|
||||
self.update_selected(document_network, document_metadata, selected_nodes, responses);
|
||||
if selected_nodes.selected_layers(document_metadata).count() <= 1 {
|
||||
responses.add(DocumentMessage::SetRangeSelectionLayer {
|
||||
new_layer: selected_nodes.selected_layers(document_metadata).next(),
|
||||
@@ -195,7 +195,7 @@ 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, selected_nodes, collapsed, responses);
|
||||
}
|
||||
self.update_selected(document_network, selected_nodes, responses);
|
||||
self.update_selected(document_network, document_metadata, selected_nodes, responses);
|
||||
}
|
||||
NodeGraphMessage::DuplicateSelectedNodes => {
|
||||
if let Some(network) = document_network.nested_network(&self.network) {
|
||||
@@ -221,7 +221,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
responses.add(NodeGraphMessage::InsertNode { node_id, document_node });
|
||||
}
|
||||
|
||||
self.update_selected(document_network, selected_nodes, responses);
|
||||
self.update_selected(document_network, document_metadata, selected_nodes, responses);
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::ExitNestedNetwork { depth_of_nesting } => {
|
||||
@@ -234,7 +234,7 @@ 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, selected_nodes, collapsed, responses);
|
||||
}
|
||||
self.update_selected(document_network, selected_nodes, responses);
|
||||
self.update_selected(document_network, document_metadata, selected_nodes, responses);
|
||||
}
|
||||
NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => {
|
||||
let Some(network) = document_network.nested_network(&self.network) else {
|
||||
@@ -447,36 +447,46 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
|
||||
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);
|
||||
NodeGraphMessage::ToggleSelectedVisibility => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
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 });
|
||||
}
|
||||
// If any of the selected nodes are hidden, show them all. Otherwise, hide them all.
|
||||
let visible = selected_nodes.selected_nodes().all(|&node_id| document_metadata.node_is_visible(node_id));
|
||||
let visible = !visible;
|
||||
|
||||
for &node_id in selected_nodes.selected_nodes() {
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id, visible });
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::ToggleHidden { node_id } => {
|
||||
if let Some(network) = document_network.nested_network(&self.network) {
|
||||
let new_hidden = !network.disabled.contains(&node_id);
|
||||
responses.add(NodeGraphMessage::SetHidden { node_id, hidden: new_hidden });
|
||||
}
|
||||
NodeGraphMessage::ToggleVisibility { node_id } => {
|
||||
let visible = document_metadata.node_is_visible(node_id);
|
||||
let visible = !visible;
|
||||
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id, visible });
|
||||
}
|
||||
NodeGraphMessage::SetHidden { node_id, hidden } => {
|
||||
if let Some(network) = document_network.nested_network_mut(&self.network) {
|
||||
if !hidden {
|
||||
network.disabled.retain(|&id| node_id != id);
|
||||
} else if !network.imports.contains(&node_id) && !network.original_outputs().iter().any(|output| output.node_id == node_id) {
|
||||
network.disabled.push(node_id);
|
||||
}
|
||||
NodeGraphMessage::SetVisibility { node_id, visible } => {
|
||||
(|| {
|
||||
let Some(network) = document_network.nested_network_mut(&self.network) else { return };
|
||||
|
||||
let input_or_output = network.imports.contains(&node_id) || network.original_outputs().iter().any(|output| output.node_id == node_id);
|
||||
let visibility = if visible {
|
||||
true
|
||||
} else if !input_or_output {
|
||||
false
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Set what we determined shall be the visibility of the node
|
||||
let Some(node) = network.nodes.get_mut(&node_id) else { return };
|
||||
node.visible = visibility;
|
||||
|
||||
// Only generate node graph if one of the selected nodes is connected to the output
|
||||
if network.connected_to_output(node_id) {
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
}
|
||||
self.update_selection_action_buttons(document_network, selected_nodes, responses);
|
||||
})();
|
||||
self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses);
|
||||
}
|
||||
NodeGraphMessage::ToggleSelectedLocked => {
|
||||
if let Some(network) = document_network.nested_network(&self.network) {
|
||||
@@ -537,7 +547,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
}
|
||||
}
|
||||
|
||||
self.update_selection_action_buttons(document_network, selected_nodes, responses);
|
||||
self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses);
|
||||
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
@@ -551,7 +561,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
let node_types = document_node_types::collect_node_types();
|
||||
responses.add(FrontendMessage::UpdateNodeTypes { node_types });
|
||||
}
|
||||
self.update_selected(document_network, selected_nodes, responses);
|
||||
self.update_selected(document_network, document_metadata, selected_nodes, responses);
|
||||
}
|
||||
NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors } => {
|
||||
self.resolved_types = resolved_types;
|
||||
@@ -569,7 +579,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||
impl NodeGraphMessageHandler {
|
||||
pub fn actions_with_node_graph_open(&self, graph_open: bool) -> ActionList {
|
||||
if self.has_selection && graph_open {
|
||||
actions!(NodeGraphMessageDiscriminant; DeleteSelectedNodes, Cut, Copy, DuplicateSelectedNodes, ToggleSelectedHidden)
|
||||
actions!(NodeGraphMessageDiscriminant; DeleteSelectedNodes, Cut, Copy, DuplicateSelectedNodes, ToggleSelectedVisibility)
|
||||
} else {
|
||||
actions!(NodeGraphMessageDiscriminant;)
|
||||
}
|
||||
@@ -583,8 +593,8 @@ impl NodeGraphMessageHandler {
|
||||
});
|
||||
}
|
||||
|
||||
/// Updates the buttons for disable, locked and preview
|
||||
fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque<Message>) {
|
||||
/// Updates the buttons for visibility and preview
|
||||
fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, selected_nodes: &SelectedNodes, responses: &mut VecDeque<Message>) {
|
||||
if let Some(network) = document_network.nested_network(&self.network) {
|
||||
let mut widgets = Vec::new();
|
||||
|
||||
@@ -594,19 +604,18 @@ impl NodeGraphMessageHandler {
|
||||
// If there is at least one other selected node then show the hide or show button
|
||||
if selection.next().is_some() {
|
||||
// Check if any of the selected nodes are disabled
|
||||
let is_hidden = selected_nodes.selected_nodes().any(|id| network.disabled.contains(id));
|
||||
let is_locked = selected_nodes.selected_nodes().any(|id| network.locked.contains(id));
|
||||
let all_visible = selected_nodes.selected_nodes().all(|&id| document_metadata.node_is_visible(id));
|
||||
|
||||
// Check if multiple nodes are selected
|
||||
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") };
|
||||
// Generate the visible/hidden button accordingly
|
||||
let (hide_show_label, hide_show_icon) = if all_visible { ("Make Hidden", "EyeVisible") } else { ("Make Visible", "EyeHidden") };
|
||||
let hide_button = TextButton::new(hide_show_label)
|
||||
.icon(Some(hide_show_icon.to_string()))
|
||||
.tooltip(if is_hidden { "Show selected nodes/layers" } else { "Hide selected nodes/layers" }.to_string() + if multiple_nodes { "s" } else { "" })
|
||||
.tooltip_shortcut(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedHidden))
|
||||
.on_update(move |_| NodeGraphMessage::ToggleSelectedHidden.into())
|
||||
.tooltip(if all_visible { "Hide selected nodes/layers" } else { "Show selected nodes/layers" }.to_string() + if multiple_nodes { "s" } else { "" })
|
||||
.tooltip_shortcut(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedVisibility))
|
||||
.on_update(move |_| NodeGraphMessage::ToggleSelectedVisibility.into())
|
||||
.widget_holder();
|
||||
widgets.push(hide_button);
|
||||
|
||||
@@ -784,8 +793,7 @@ impl NodeGraphMessageHandler {
|
||||
exposed_outputs,
|
||||
position: node.metadata.position.into(),
|
||||
previewed: network.outputs_contain(node_id),
|
||||
disabled: network.disabled.contains(&node_id),
|
||||
locked: network.locked.contains(&node_id),
|
||||
visible: node.visible,
|
||||
errors: errors.map(|e| format!("{e:?}")),
|
||||
});
|
||||
}
|
||||
@@ -814,8 +822,7 @@ impl NodeGraphMessageHandler {
|
||||
parent_id: layer.parent(metadata).map(|parent| parent.to_node()),
|
||||
name: network.nodes.get(&node_id).map(|node| node.alias.clone()).unwrap_or_default(),
|
||||
tooltip: if cfg!(debug_assertions) { format!("Layer ID: {node_id}") } else { "".into() },
|
||||
disabled: network.disabled.contains(&node_id),
|
||||
locked: network.locked.contains(&node_id),
|
||||
visible: node.visible,
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateDocumentLayerDetails { data });
|
||||
}
|
||||
@@ -836,8 +843,8 @@ impl NodeGraphMessageHandler {
|
||||
}
|
||||
|
||||
/// Updates the frontend's selection state in line with the backend
|
||||
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);
|
||||
fn update_selected(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, selected_nodes: &SelectedNodes, responses: &mut VecDeque<Message>) {
|
||||
self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses);
|
||||
responses.add(FrontendMessage::UpdateNodeGraphSelection {
|
||||
selected: selected_nodes.selected_nodes_ref().clone(),
|
||||
});
|
||||
|
||||
@@ -84,8 +84,7 @@ pub struct FrontendNode {
|
||||
#[serde(rename = "exposedOutputs")]
|
||||
pub exposed_outputs: Vec<FrontendGraphOutput>,
|
||||
pub position: (i32, i32),
|
||||
pub disabled: bool,
|
||||
pub locked: bool,
|
||||
pub visible: bool,
|
||||
pub previewed: bool,
|
||||
pub errors: Option<String>,
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::collections::HashMap;
|
||||
pub enum Clipboard {
|
||||
Internal,
|
||||
|
||||
_InternalClipboardCount, // Keep this as the last entry in internal clipboards since it is used for counting the number of enum variants
|
||||
_InternalClipboardCount, // Keep this as the last entry of **internal** clipboards since it is used for counting the number of enum variants
|
||||
|
||||
Device,
|
||||
}
|
||||
@@ -19,7 +19,7 @@ pub const INTERNAL_CLIPBOARD_COUNT: u8 = Clipboard::_InternalClipboardCount as u
|
||||
pub struct CopyBufferEntry {
|
||||
pub nodes: HashMap<NodeId, DocumentNode>,
|
||||
pub selected: bool,
|
||||
pub disabled: bool,
|
||||
pub visible: bool,
|
||||
pub collapsed: bool,
|
||||
pub alias: String,
|
||||
}
|
||||
|
||||
@@ -14,12 +14,15 @@ use std::num::NonZeroU64;
|
||||
// DocumentMetadata
|
||||
// ================
|
||||
|
||||
// TODO: To avoid storing a stateful snapshot of some other system's state (which is easily to accidentally get out of sync),
|
||||
// TODO: it might be better to have a system that can query the state of the node network on demand.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DocumentMetadata {
|
||||
upstream_transforms: HashMap<NodeId, (Footprint, DAffine2)>,
|
||||
structure: HashMap<LayerNodeIdentifier, NodeRelations>,
|
||||
artboards: HashSet<LayerNodeIdentifier>,
|
||||
folders: HashSet<LayerNodeIdentifier>,
|
||||
hidden: HashSet<NodeId>,
|
||||
click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>,
|
||||
/// Transform from document space to viewport space.
|
||||
pub document_to_viewport: DAffine2,
|
||||
@@ -29,10 +32,11 @@ impl Default for DocumentMetadata {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
upstream_transforms: HashMap::new(),
|
||||
click_targets: HashMap::new(),
|
||||
structure: HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]),
|
||||
artboards: HashSet::new(),
|
||||
folders: HashSet::new(),
|
||||
hidden: HashSet::new(),
|
||||
click_targets: HashMap::new(),
|
||||
document_to_viewport: DAffine2::IDENTITY,
|
||||
}
|
||||
}
|
||||
@@ -118,6 +122,10 @@ impl DocumentMetadata {
|
||||
self.artboards.contains(&layer)
|
||||
}
|
||||
|
||||
pub fn node_is_visible(&self, layer: NodeId) -> bool {
|
||||
!self.hidden.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<_> = layers.filter(|layer| self.folders.contains(layer)).collect();
|
||||
@@ -138,8 +146,9 @@ impl DocumentMetadata {
|
||||
}
|
||||
|
||||
self.structure = HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]);
|
||||
self.folders = HashSet::new();
|
||||
self.artboards = HashSet::new();
|
||||
self.folders = HashSet::new();
|
||||
self.hidden = HashSet::new();
|
||||
|
||||
let id = graph.exports[0].node_id;
|
||||
let Some(output_node) = graph.nodes.get(&id) else {
|
||||
@@ -150,22 +159,26 @@ impl DocumentMetadata {
|
||||
};
|
||||
let parent = LayerNodeIdentifier::ROOT;
|
||||
let mut stack = vec![(layer_node, node_id, parent)];
|
||||
while let Some((node, id, parent)) = stack.pop() {
|
||||
let mut current = Some((node, id));
|
||||
while let Some(&(current_node, current_id)) = current.as_ref() {
|
||||
let current_identifier = LayerNodeIdentifier::new_unchecked(current_id);
|
||||
if !self.structure.contains_key(¤t_identifier) {
|
||||
parent.push_child(self, current_identifier);
|
||||
while let Some((node, node_id, parent)) = stack.pop() {
|
||||
let mut current = Some((node, node_id));
|
||||
while let Some(&(current_node, current_node_id)) = current.as_ref() {
|
||||
let current_layer_id = LayerNodeIdentifier::new_unchecked(current_node_id);
|
||||
if !self.structure.contains_key(¤t_layer_id) {
|
||||
parent.push_child(self, current_layer_id);
|
||||
|
||||
if let Some((child_node, child_id)) = first_child_layer(graph, current_node) {
|
||||
stack.push((child_node, child_id, current_identifier));
|
||||
stack.push((child_node, child_id, current_layer_id));
|
||||
}
|
||||
|
||||
if is_artboard(current_identifier, graph) {
|
||||
self.artboards.insert(current_identifier);
|
||||
if is_artboard(current_layer_id, graph) {
|
||||
self.artboards.insert(current_layer_id);
|
||||
}
|
||||
if is_folder(current_identifier, graph) {
|
||||
self.folders.insert(current_identifier);
|
||||
if is_folder(current_layer_id, graph) {
|
||||
self.folders.insert(current_layer_id);
|
||||
}
|
||||
|
||||
if !current_node.visible {
|
||||
self.hidden.insert(current_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,9 +545,9 @@ impl<'a> Iterator for AxisIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// ==============
|
||||
// ===============
|
||||
// DescendantsIter
|
||||
// ==============
|
||||
// ===============
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DescendantsIter<'a> {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use graph_craft::document::{NodeId, NodeNetwork};
|
||||
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
|
||||
|
||||
use graph_craft::document::NodeId;
|
||||
|
||||
use serde::ser::SerializeStruct;
|
||||
|
||||
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)]
|
||||
pub struct RawBuffer(Vec<u8>);
|
||||
|
||||
@@ -46,8 +46,7 @@ pub struct LayerPanelEntry {
|
||||
#[serde(rename = "layerClassification")]
|
||||
pub layer_classification: LayerClassification,
|
||||
pub expanded: bool,
|
||||
pub disabled: bool,
|
||||
pub locked: bool,
|
||||
pub visible: bool,
|
||||
#[serde(rename = "parentId")]
|
||||
pub parent_id: Option<NodeId>,
|
||||
pub depth: usize,
|
||||
@@ -57,12 +56,12 @@ pub struct LayerPanelEntry {
|
||||
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 layer_visible(&self, layer: LayerNodeIdentifier, metadata: &DocumentMetadata) -> bool {
|
||||
layer.ancestors(metadata).all(|layer| metadata.node_is_visible(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_visible_layers<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
|
||||
self.selected_layers(metadata).filter(move |&layer| self.layer_visible(layer, metadata))
|
||||
}
|
||||
|
||||
pub fn layer_ulocked(&self, layer: LayerNodeIdentifier, network: &NodeNetwork, metadata: &DocumentMetadata) -> bool {
|
||||
|
||||
@@ -202,7 +202,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
)
|
||||
.collect(),
|
||||
selected: active_document.selected_nodes.selected_layers_contains(layer, active_document.metadata()),
|
||||
disabled: !active_document.selected_nodes.layer_visible(layer, active_document.network(), active_document.metadata()),
|
||||
visible: active_document.selected_nodes.layer_visible(layer, active_document.metadata()),
|
||||
collapsed: false,
|
||||
alias: previous_alias,
|
||||
});
|
||||
@@ -388,8 +388,8 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
if entry.selected {
|
||||
responses.add(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] });
|
||||
}
|
||||
if entry.disabled {
|
||||
responses.add(NodeGraphMessage::SetHidden { node_id: id, hidden: entry.disabled });
|
||||
if !entry.visible {
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id: id, visible: false });
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -419,8 +419,8 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
if entry.selected {
|
||||
responses.add(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] });
|
||||
}
|
||||
if entry.disabled {
|
||||
responses.add(NodeGraphMessage::SetHidden { node_id: id, hidden: entry.disabled });
|
||||
if !entry.visible {
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id: id, visible: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ impl Pivot {
|
||||
|
||||
/// Recomputes the pivot position and transform.
|
||||
fn recalculate_pivot(&mut self, document: &DocumentMessageHandler) {
|
||||
let mut layers = document.selected_nodes.selected_visible_layers(document.network(), document.metadata());
|
||||
let mut layers = document.selected_nodes.selected_visible_layers(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);
|
||||
@@ -66,7 +66,7 @@ impl Pivot {
|
||||
// If more than one layer is selected we use the AABB with the mean of the pivots
|
||||
let xy_summation = document
|
||||
.selected_nodes
|
||||
.selected_visible_layers(document.network(), document.metadata())
|
||||
.selected_visible_layers(document.metadata())
|
||||
.map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.network, &document.metadata))
|
||||
.reduce(|a, b| a + b)
|
||||
.unwrap_or_default();
|
||||
@@ -101,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_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
for layer in document.selected_nodes.selected_visible_layers(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.
|
||||
|
||||
@@ -255,7 +255,7 @@ impl SnapManager {
|
||||
if candidates.len() > 10 {
|
||||
return;
|
||||
}
|
||||
if !document.selected_nodes.layer_visible(layer, &document.network, &document.metadata) {
|
||||
if !document.selected_nodes.layer_visible(layer, &document.metadata) {
|
||||
return;
|
||||
}
|
||||
if snap_data.ignore.contains(&layer) {
|
||||
|
||||
@@ -247,7 +247,7 @@ impl Fsm for GradientToolFsmState {
|
||||
(_, GradientToolMessage::Overlays(mut overlay_context)) => {
|
||||
let selected = tool_data.selected_gradient.as_ref();
|
||||
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
for layer in document.selected_nodes.selected_visible_layers(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);
|
||||
@@ -318,7 +318,7 @@ impl Fsm for GradientToolFsmState {
|
||||
self
|
||||
}
|
||||
(_, GradientToolMessage::InsertStop) => {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.metadata()) {
|
||||
let Some(mut gradient) = get_gradient(layer, &document.network) else { continue };
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
|
||||
@@ -357,7 +357,7 @@ impl Fsm for GradientToolFsmState {
|
||||
let tolerance = (MANIPULATOR_GROUP_MARKER_SIZE * 2.).powi(2);
|
||||
|
||||
let mut dragging = false;
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.metadata()) {
|
||||
let Some(gradient) = get_gradient(layer, &document.network) else { continue };
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
|
||||
|
||||
@@ -391,7 +391,7 @@ impl Fsm for SelectToolFsmState {
|
||||
tool_data.selected_layers_count = selected_layers_count;
|
||||
|
||||
// Outline selected layers
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) {
|
||||
for layer in document.selected_nodes.selected_visible_layers(document.metadata()) {
|
||||
overlay_context.outline(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer));
|
||||
}
|
||||
|
||||
@@ -405,13 +405,13 @@ impl Fsm for SelectToolFsmState {
|
||||
// Update bounds
|
||||
let transform = document
|
||||
.selected_nodes
|
||||
.selected_visible_layers(document.network(), document.metadata())
|
||||
.selected_visible_layers(document.metadata())
|
||||
.next()
|
||||
.map(|layer| document.metadata().transform_to_viewport(layer));
|
||||
let transform = transform.unwrap_or(DAffine2::IDENTITY);
|
||||
let bounds = document
|
||||
.selected_nodes
|
||||
.selected_visible_layers(document.network(), document.metadata())
|
||||
.selected_visible_layers(document.metadata())
|
||||
.filter_map(|layer| {
|
||||
document
|
||||
.metadata()
|
||||
@@ -472,7 +472,7 @@ impl Fsm for SelectToolFsmState {
|
||||
.map(|bounding_box| bounding_box.check_rotate(input.mouse.position))
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut selected: Vec<_> = document.selected_nodes.selected_visible_layers(document.network(), document.metadata()).collect();
|
||||
let mut selected: Vec<_> = document.selected_nodes.selected_visible_layers(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.
|
||||
|
||||
@@ -215,7 +215,7 @@ impl TextToolData {
|
||||
/// Set the editing state of the currently modifying layer
|
||||
fn set_editing(&self, editable: bool, font_cache: &FontCache, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
if let Some(node_id) = graph_modification_utils::get_fill_id(self.layer, &document.network) {
|
||||
responses.add(NodeGraphMessage::SetHidden { node_id, hidden: editable });
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id, visible: !editable });
|
||||
}
|
||||
|
||||
if let Some(editing_text) = self.editing_text.as_ref().filter(|_| editable) {
|
||||
|
||||
@@ -190,7 +190,7 @@ impl NodeRuntime {
|
||||
image_frame: None,
|
||||
};
|
||||
|
||||
// Required to ensure that the appropriate protonodes are reinserted when the Editor API changes.
|
||||
// Required to ensure that the appropriate proto nodes are reinserted when the Editor API changes.
|
||||
let mut graph_input_hash = DefaultHasher::new();
|
||||
editor_api.font_cache.hash(&mut graph_input_hash);
|
||||
let font_hash_code = graph_input_hash.finish();
|
||||
@@ -218,7 +218,7 @@ impl NodeRuntime {
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
assert_ne!(proto_network.nodes.len(), 0, "No protonodes exist?");
|
||||
assert_ne!(proto_network.nodes.len(), 0, "No proto nodes exist?");
|
||||
if let Err(e) = self.executor.update(proto_network).await {
|
||||
self.node_graph_errors = e;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user