mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
Fix broken SVG importing and crash when exporting (#1953)
* Fix importing SVG and crash when exporting * Code improvements, prevent entering network after drag
This commit is contained in:
parent
fb7d5970b3
commit
19541c9684
12 changed files with 88 additions and 116 deletions
|
|
@ -246,6 +246,7 @@ fn usvg_transform(c: usvg::Transform) -> DAffine2 {
|
|||
|
||||
fn import_usvg_node(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node, transform: DAffine2, id: NodeId, parent: LayerNodeIdentifier, insert_index: usize) {
|
||||
let layer = modify_inputs.create_layer(id);
|
||||
modify_inputs.network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
|
||||
modify_inputs.layer_node = Some(layer);
|
||||
match node {
|
||||
usvg::Node::Group(group) => {
|
||||
|
|
@ -259,8 +260,6 @@ fn import_usvg_node(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node,
|
|||
let bounds = subpaths.iter().filter_map(|subpath| subpath.bounding_box()).reduce(Quad::combine_bounds).unwrap_or_default();
|
||||
modify_inputs.insert_vector_data(subpaths, layer);
|
||||
|
||||
modify_inputs.network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
|
||||
|
||||
if let Some(transform_node_id) = modify_inputs.existing_node_id("Transform") {
|
||||
transform_utils::update_transform(modify_inputs.network_interface, &transform_node_id, transform * usvg_transform(node.abs_transform()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,12 @@ pub struct NodeGraphMessageHandler {
|
|||
pub node_graph_errors: GraphErrors,
|
||||
has_selection: bool,
|
||||
widgets: [LayoutGroup; 2],
|
||||
/// The start position when dragging nodes
|
||||
pub drag_start: Option<DragStart>,
|
||||
/// Used to add a transaction for the first node move when dragging.
|
||||
begin_dragging: bool,
|
||||
/// Used to prevent entering a nested network if the node is dragged after double clicking
|
||||
drag_occurred: bool,
|
||||
/// Stored in node graph coordinates
|
||||
box_selection_start: Option<DVec2>,
|
||||
/// Restore the selection before box selection if it is aborted
|
||||
|
|
@ -238,10 +241,18 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
|||
});
|
||||
}
|
||||
NodeGraphMessage::EnterNestedNetwork => {
|
||||
// Do not enter the nested network if the node was dragged
|
||||
if self.drag_occurred {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(node_id) = network_interface.node_from_click(ipp.mouse.position, selection_network_path) else {
|
||||
return;
|
||||
};
|
||||
if network_interface.visibility_from_click(ipp.mouse.position, selection_network_path).is_some() {
|
||||
if network_interface
|
||||
.layer_click_target_from_click(ipp.mouse.position, network_interface::LayerClickTargetTypes::Visibility, selection_network_path)
|
||||
.is_some()
|
||||
{
|
||||
return;
|
||||
};
|
||||
let Some(network) = network_interface.network(selection_network_path) else {
|
||||
|
|
@ -337,7 +348,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
|||
|
||||
let node_graph_point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click);
|
||||
|
||||
if network_interface.grip_from_click(click, selection_network_path).is_some() {
|
||||
if network_interface
|
||||
.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Grip, selection_network_path)
|
||||
.is_some()
|
||||
{
|
||||
self.shift_without_push = true;
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +465,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
|||
}
|
||||
|
||||
// Toggle visibility of clicked node and return
|
||||
if let Some(clicked_visibility) = network_interface.visibility_from_click(click, selection_network_path) {
|
||||
if let Some(clicked_visibility) = network_interface.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Visibility, selection_network_path) {
|
||||
responses.add(NodeGraphMessage::ToggleVisibility { node_id: clicked_visibility });
|
||||
return;
|
||||
}
|
||||
|
|
@ -538,6 +552,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
|||
|
||||
self.drag_start = Some(drag_start);
|
||||
self.begin_dragging = true;
|
||||
self.drag_occurred = false;
|
||||
}
|
||||
|
||||
// Update the selection if it was modified
|
||||
|
|
@ -646,6 +661,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
|||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: Some(wire_path) });
|
||||
}
|
||||
} else if let Some(drag_start) = &mut self.drag_start {
|
||||
self.drag_occurred = true;
|
||||
if self.begin_dragging {
|
||||
self.begin_dragging = false;
|
||||
if ipp.keyboard.get(crate::messages::tool::tool_messages::tool_prelude::Key::Alt as usize) {
|
||||
|
|
@ -1991,6 +2007,7 @@ impl Default for NodeGraphMessageHandler {
|
|||
widgets: [LayoutGroup::Row { widgets: Vec::new() }, LayoutGroup::Row { widgets: right_side_widgets }],
|
||||
drag_start: None,
|
||||
begin_dragging: false,
|
||||
drag_occurred: false,
|
||||
shift_without_push: false,
|
||||
box_selection_start: None,
|
||||
selection_before_pointer_down: Vec::new(),
|
||||
|
|
@ -2015,6 +2032,7 @@ impl PartialEq for NodeGraphMessageHandler {
|
|||
&& self.widgets == other.widgets
|
||||
&& self.drag_start == other.drag_start
|
||||
&& self.begin_dragging == other.begin_dragging
|
||||
&& self.drag_occurred == other.drag_occurred
|
||||
&& self.box_selection_start == other.box_selection_start
|
||||
&& self.initial_disconnecting == other.initial_disconnecting
|
||||
&& self.select_if_not_dragged == other.select_if_not_dragged
|
||||
|
|
|
|||
|
|
@ -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.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
//let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
|
||||
|
|
@ -64,7 +64,7 @@ pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut Shape
|
|||
|
||||
pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext) {
|
||||
for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
//let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
use super::network_interface::NodeNetworkInterface;
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::NodeId;
|
||||
use graphene_core::renderer::ClickTarget;
|
||||
use graphene_core::renderer::Quad;
|
||||
|
|
@ -59,24 +56,6 @@ impl DocumentMetadata {
|
|||
self.click_targets.get(&layer)
|
||||
}
|
||||
|
||||
// TODO: Move into network interface so that it does not have to be passed as an argument
|
||||
/// Get vector data after the modification is applied
|
||||
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<VectorData> {
|
||||
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, network_interface);
|
||||
|
||||
if let Some(vector_data) = graph_layer.upstream_node_id_from_name("Path").and_then(|node| self.vector_modify.get(&node)) {
|
||||
let mut modified = vector_data.clone();
|
||||
if let Some(TaggedValue::VectorModification(modification)) = graph_layer.find_input("Path", 1) {
|
||||
modification.apply(&mut modified);
|
||||
}
|
||||
return Some(modified);
|
||||
}
|
||||
self.click_targets
|
||||
.get(&layer)
|
||||
.map(|click| click.iter().map(ClickTarget::subpath))
|
||||
.map(|subpaths| VectorData::from_subpaths(subpaths, true))
|
||||
}
|
||||
|
||||
/// Access the [`NodeRelations`] of a layer.
|
||||
fn get_relations(&self, node_identifier: LayerNodeIdentifier) -> Option<&NodeRelations> {
|
||||
self.structure.get(&node_identifier)
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@ use super::nodes::SelectedNodes;
|
|||
use crate::consts::{EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP, EXPORTS_TO_TOP_EDGE_PIXEL_GAP, GRID_SIZE, IMPORTS_TO_LEFT_EDGE_PIXEL_GAP, IMPORTS_TO_TOP_EDGE_PIXEL_GAP};
|
||||
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
|
||||
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets, FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput};
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
|
||||
use bezier_rs::Subpath;
|
||||
use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork};
|
||||
use graph_craft::{concrete, Type};
|
||||
use graphene_std::renderer::{ClickTarget, Quad};
|
||||
use graphene_std::vector::{PointId, VectorModificationType};
|
||||
use graphene_std::vector::{PointId, VectorData, VectorModificationType};
|
||||
use interpreted_executor::{dynamic_executor::ResolvedDocumentNodeTypes, node_registry::NODE_REGISTRY};
|
||||
|
||||
use glam::{DAffine2, DVec2, IVec2};
|
||||
|
|
@ -455,7 +456,6 @@ impl NodeNetworkInterface {
|
|||
/// Get the [`Type`] for any InputConnector
|
||||
pub fn input_type(&self, input_connector: &InputConnector, network_path: &[NodeId]) -> Type {
|
||||
// TODO: If the input_connector is a NodeInput::Value, return the type of the tagged value
|
||||
// TODO: Store types for all document nodes, not just the compiled proto nodes, which currently skips isolated nodes
|
||||
let node_type_from_compiled_network = if let Some(node_id) = input_connector.node_id() {
|
||||
let Some(current_network) = self.network(network_path) else {
|
||||
log::error!("Could not get current network in input_type");
|
||||
|
|
@ -689,8 +689,6 @@ impl NodeNetworkInterface {
|
|||
let mut import_metadata = None;
|
||||
|
||||
if !network_path.is_empty() {
|
||||
// TODO: https://github.com/GraphiteEditor/Graphite/issues/1767
|
||||
// TODO: Non exposed inputs are not added to the inputs_source_map, fix `pub fn document_node_types(&self) -> ResolvedDocumentNodeTypes`
|
||||
let mut encapsulating_path = network_path.to_vec();
|
||||
let encapsulating_node_id = encapsulating_path.pop().unwrap();
|
||||
|
||||
|
|
@ -1091,15 +1089,6 @@ impl NodeNetworkInterface {
|
|||
.is_some_and(|reference| reference == "Artboard" && self.connected_to_output(node_id, &[]))
|
||||
}
|
||||
|
||||
pub fn parent_artboard(&self, layer: LayerNodeIdentifier) -> Option<LayerNodeIdentifier> {
|
||||
let ancestors: Vec<_> = layer.ancestors(self.document_metadata()).collect();
|
||||
match ancestors.as_slice() {
|
||||
[_, second_last, _last] if self.is_artboard(&second_last.to_node(), &[]) => Some(*second_last),
|
||||
[_, last] if self.is_artboard(&last.to_node(), &[]) => Some(*last),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_artboards(&self) -> HashSet<LayerNodeIdentifier> {
|
||||
self.network_metadata(&[])
|
||||
.unwrap()
|
||||
|
|
@ -1146,7 +1135,10 @@ impl NodeNetworkInterface {
|
|||
.filter(|layer| include_artboards || !self.is_artboard(&layer.to_node(), &[]))
|
||||
.filter_map(|layer| {
|
||||
if !self.is_artboard(&layer.to_node(), &[]) {
|
||||
if let Some(artboard_node_identifier) = self.parent_artboard(layer) {
|
||||
if let Some(artboard_node_identifier) = layer
|
||||
.ancestors(self.document_metadata())
|
||||
.find(|ancestor| *ancestor != LayerNodeIdentifier::ROOT_PARENT && self.is_artboard(&ancestor.to_node(), &[]))
|
||||
{
|
||||
let artboard = self.network(&[]).unwrap().nodes.get(&artboard_node_identifier.to_node());
|
||||
let clip_input = artboard.unwrap().inputs.get(5).unwrap();
|
||||
if let NodeInput::Value { tagged_value, .. } = clip_input {
|
||||
|
|
@ -1637,7 +1629,7 @@ impl NodeNetworkInterface {
|
|||
}
|
||||
|
||||
let mut stack_dependents = HashMap::new();
|
||||
|
||||
let mut owned_sole_dependents = HashSet::new();
|
||||
// Loop through all layers below the stack_tops, and set sole dependents upstream from that layer to be owned by that layer. Ensure LayerOwner is kept in sync.
|
||||
for stack_top in &stack_tops {
|
||||
for upstream_stack_layer in self
|
||||
|
|
@ -1652,6 +1644,7 @@ impl NodeNetworkInterface {
|
|||
let mut new_owned_nodes = HashSet::new();
|
||||
for layer_sole_dependent in &self.upstream_nodes_below_layer(&upstream_layer, network_path) {
|
||||
stack_dependents.insert(*layer_sole_dependent, LayerOwner::Layer(upstream_layer));
|
||||
owned_sole_dependents.insert(*layer_sole_dependent);
|
||||
new_owned_nodes.insert(*layer_sole_dependent);
|
||||
}
|
||||
let Some(layer_node) = self.node_metadata_mut(&upstream_layer, network_path) else {
|
||||
|
|
@ -1716,8 +1709,7 @@ impl NodeNetworkInterface {
|
|||
}
|
||||
|
||||
for sole_dependent in sole_dependents {
|
||||
// TODO: Use a temporary hashmap to store added nodes rather than looping though
|
||||
if stack_dependents.iter().all(|owned_sole_dependent| *owned_sole_dependent.0 != sole_dependent) {
|
||||
if !owned_sole_dependents.contains(&sole_dependent) {
|
||||
stack_dependents.insert(sole_dependent, LayerOwner::None(0));
|
||||
}
|
||||
}
|
||||
|
|
@ -2520,7 +2512,7 @@ impl NodeNetworkInterface {
|
|||
.or_else(|| clicked_nodes.into_iter().next())
|
||||
}
|
||||
|
||||
pub fn visibility_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<NodeId> {
|
||||
pub fn layer_click_target_from_click(&mut self, click: DVec2, click_target_type: LayerClickTargetTypes, network_path: &[NodeId]) -> Option<NodeId> {
|
||||
let Some(network_metadata) = self.network_metadata(network_path) else {
|
||||
log::error!("Could not get nested network_metadata in visibility_from_click");
|
||||
return None;
|
||||
|
|
@ -2538,35 +2530,10 @@ impl NodeNetworkInterface {
|
|||
.filter_map(|node_id| {
|
||||
self.node_click_targets(node_id, network_path).and_then(|transient_node_metadata| {
|
||||
if let NodeTypeClickTargets::Layer(layer) = &transient_node_metadata.node_type_metadata {
|
||||
layer.visibility_click_target.intersect_point_no_stroke(point).then_some(*node_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
.next()
|
||||
}
|
||||
|
||||
// TODO: Combine grip_from_click and visibility_from_click into a single function
|
||||
pub fn grip_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<NodeId> {
|
||||
let Some(network_metadata) = self.network_metadata(network_path) else {
|
||||
log::error!("Could not get nested network_metadata in visibility_from_click");
|
||||
return None;
|
||||
};
|
||||
let Some(network) = self.network(network_path) else {
|
||||
log::error!("Could not get nested network in visibility_from_click");
|
||||
return None;
|
||||
};
|
||||
|
||||
let point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click);
|
||||
let node_ids: Vec<_> = network.nodes.keys().copied().collect();
|
||||
|
||||
node_ids
|
||||
.iter()
|
||||
.filter_map(|node_id| {
|
||||
self.node_click_targets(node_id, network_path).and_then(|transient_node_metadata| {
|
||||
if let NodeTypeClickTargets::Layer(layer) = &transient_node_metadata.node_type_metadata {
|
||||
layer.grip_click_target.intersect_point_no_stroke(point).then_some(*node_id)
|
||||
match click_target_type {
|
||||
LayerClickTargetTypes::Visibility => layer.visibility_click_target.intersect_point_no_stroke(point).then_some(*node_id),
|
||||
LayerClickTargetTypes::Grip => layer.grip_click_target.intersect_point_no_stroke(point).then_some(*node_id),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -2732,6 +2699,23 @@ impl NodeNetworkInterface {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<VectorData> {
|
||||
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, self);
|
||||
|
||||
if let Some(vector_data) = graph_layer.upstream_node_id_from_name("Path").and_then(|node| self.document_metadata.vector_modify.get(&node)) {
|
||||
let mut modified = vector_data.clone();
|
||||
if let Some(TaggedValue::VectorModification(modification)) = graph_layer.find_input("Path", 1) {
|
||||
modification.apply(&mut modified);
|
||||
}
|
||||
return Some(modified);
|
||||
}
|
||||
self.document_metadata
|
||||
.click_targets
|
||||
.get(&layer)
|
||||
.map(|click| click.iter().map(ClickTarget::subpath))
|
||||
.map(|subpaths| VectorData::from_subpaths(subpaths, true))
|
||||
}
|
||||
|
||||
/// Loads the structure of layer nodes from a node graph.
|
||||
pub fn load_structure(&mut self) {
|
||||
self.document_metadata.structure = HashMap::from_iter([(LayerNodeIdentifier::ROOT_PARENT, NodeRelations::default())]);
|
||||
|
|
@ -3168,7 +3152,6 @@ impl NodeNetworkInterface {
|
|||
return;
|
||||
};
|
||||
match &downstream_node_metadata.persistent_metadata.node_type_metadata {
|
||||
// TODO: Layout system
|
||||
NodeTypePersistentMetadata::Layer(_) => {
|
||||
// If the layer feeds into the bottom input of layer, set its position to stack at its previous y position
|
||||
if *input_index == 0 {
|
||||
|
|
@ -3365,7 +3348,7 @@ impl NodeNetworkInterface {
|
|||
transient_metadata: DocumentNodeTransientMetadata::default(),
|
||||
};
|
||||
network_metadata.persistent_metadata.node_metadata.insert(node_id, node_metadata);
|
||||
// TODO: Update the bounding box around all nodes instead of unloading all data
|
||||
|
||||
self.unload_all_nodes_bounding_box(network_path);
|
||||
self.unload_node_click_targets(&node_id, network_path)
|
||||
}
|
||||
|
|
@ -3448,7 +3431,7 @@ impl NodeNetworkInterface {
|
|||
log::error!("Could not get nested network in delete_nodes");
|
||||
continue;
|
||||
};
|
||||
// TODO: Ensure node to delete is fully disconnected from the network
|
||||
|
||||
network.nodes.remove(delete_node_id);
|
||||
self.transaction_modified();
|
||||
|
||||
|
|
@ -4697,7 +4680,6 @@ impl NodeNetworkInterface {
|
|||
match post_node_input {
|
||||
// Move to the bottom of the stack
|
||||
NodeInput::Value { .. } | NodeInput::Scope(_) | NodeInput::Inline(_) | NodeInput::Reflection(_) => {
|
||||
// TODO: Calculate height of bottom layer by getting height of upstream nodes instead of setting to 3
|
||||
let offset = after_move_post_layer_position - previous_layer_position + IVec2::new(0, 3 + height_above_layer);
|
||||
self.shift_absolute_node_position(&layer.to_node(), offset, network_path);
|
||||
self.create_wire(&OutputConnector::node(layer.to_node(), 0), &post_node, network_path);
|
||||
|
|
@ -4844,7 +4826,6 @@ impl InputConnector {
|
|||
}
|
||||
|
||||
/// Represents an output connector
|
||||
/// TODO: Layer could also be a variant, since the output index is always one. Layer(NodeId)
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub enum OutputConnector {
|
||||
#[serde(rename = "node")]
|
||||
|
|
@ -5246,7 +5227,6 @@ pub enum NodePosition {
|
|||
Absolute(IVec2),
|
||||
// In a chain the position is based on the number of nodes to the first layer node
|
||||
Chain,
|
||||
// TODO: Add position for relative to a layer
|
||||
}
|
||||
|
||||
/// Cached metadata that should be calculated when creating a node, and should be recalculated when modifying a node property that affects one of the cached fields.
|
||||
|
|
@ -5303,6 +5283,12 @@ pub struct LayerClickTargets {
|
|||
// preview_click_target: ClickTarget,
|
||||
}
|
||||
|
||||
pub enum LayerClickTargetTypes {
|
||||
Visibility,
|
||||
Grip,
|
||||
// Preview,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct NavigationMetadata {
|
||||
/// The current pan, and zoom state of the viewport's view of the node graph.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl OriginalTransforms {
|
|||
if path_map.contains_key(&layer) {
|
||||
continue;
|
||||
}
|
||||
let Some(vector_data) = network_interface.document_metadata().compute_modified_vector(layer, network_interface) else {
|
||||
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
let Some(selected_points) = shape_editor.selected_points_in_layer(layer) else {
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ impl ShapeState {
|
|||
let mut offset = mouse_delta;
|
||||
let mut best_snapped = SnappedPoint::infinite_snap(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
for (layer, state) in &self.selected_shape_state {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(*layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(*layer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ impl ShapeState {
|
|||
}
|
||||
|
||||
if let Some((layer, manipulator_point_id)) = self.find_nearest_point_indices(network_interface, mouse_position, select_threshold) {
|
||||
let vector_data = network_interface.document_metadata().compute_modified_vector(layer, network_interface)?;
|
||||
let vector_data = network_interface.compute_modified_vector(layer)?;
|
||||
let point_position = manipulator_point_id.get_position(&vector_data)?;
|
||||
|
||||
let selected_shape_state = self.selected_shape_state.get(&layer)?;
|
||||
|
|
@ -278,7 +278,7 @@ impl ShapeState {
|
|||
|
||||
/// Selects all anchors connected to the selected subpath, and deselects all handles, for the given layer.
|
||||
pub fn select_connected_anchors(&mut self, document: &DocumentMessageHandler, layer: LayerNodeIdentifier, mouse: DVec2) {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
return;
|
||||
};
|
||||
let to_viewport = document.metadata().transform_to_viewport(layer);
|
||||
|
|
@ -326,7 +326,7 @@ impl ShapeState {
|
|||
|
||||
/// Internal helper function that selects all anchors, and deselects all handles, for a layer given its [`LayerNodeIdentifier`] and [`SelectedLayerState`].
|
||||
fn select_all_anchors_in_layer_with_state(document: &DocumentMessageHandler, layer: LayerNodeIdentifier, state: &mut SelectedLayerState) {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -425,7 +425,7 @@ impl ShapeState {
|
|||
layer: LayerNodeIdentifier,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Option<()> {
|
||||
let vector_data = network_interface.document_metadata().compute_modified_vector(layer, network_interface)?;
|
||||
let vector_data = network_interface.compute_modified_vector(layer)?;
|
||||
let transform = network_interface.document_metadata().transform_to_document(layer).inverse();
|
||||
let position = transform.transform_point2(new_position);
|
||||
let current_position = point.get_position(&vector_data)?;
|
||||
|
|
@ -459,7 +459,7 @@ impl ShapeState {
|
|||
let mut points_colinear_status = self
|
||||
.selected_shape_state
|
||||
.iter()
|
||||
.map(|(&layer, selection_state)| (network_interface.document_metadata().compute_modified_vector(layer, network_interface), selection_state))
|
||||
.map(|(&layer, selection_state)| (network_interface.compute_modified_vector(layer), selection_state))
|
||||
.flat_map(|(data, selection_state)| selection_state.selected_points.iter().map(move |&point| data.as_ref().map_or(false, |data| data.colinear(point))));
|
||||
|
||||
let Some(first_is_colinear) = points_colinear_status.next() else { return ManipulatorAngle::Mixed };
|
||||
|
|
@ -537,7 +537,7 @@ impl ShapeState {
|
|||
let mut skip_set = HashSet::new();
|
||||
|
||||
for (&layer, layer_state) in self.selected_shape_state.iter() {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
let transform = document.metadata().transform_to_document(layer);
|
||||
|
|
@ -612,7 +612,7 @@ impl ShapeState {
|
|||
/// Move the selected points by dragging the mouse.
|
||||
pub fn move_selected_points(&self, handle_lengths: Option<OpposingHandleLengths>, document: &DocumentMessageHandler, delta: DVec2, equidistant: bool, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
let opposing_handles = handle_lengths.as_ref().and_then(|handle_lengths| handle_lengths.get(&layer));
|
||||
|
|
@ -673,7 +673,7 @@ impl ShapeState {
|
|||
self.selected_shape_state
|
||||
.iter()
|
||||
.filter_map(|(&layer, state)| {
|
||||
let vector_data = document.metadata().compute_modified_vector(layer, &document.network_interface)?;
|
||||
let vector_data = document.network_interface.compute_modified_vector(layer)?;
|
||||
let transform = document.metadata().transform_to_document(layer);
|
||||
let opposing_handle_lengths = vector_data
|
||||
.colinear_manipulators
|
||||
|
|
@ -739,7 +739,7 @@ impl ShapeState {
|
|||
pub fn delete_selected_points(&self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let mut missing_anchors = HashMap::new();
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -830,7 +830,7 @@ impl ShapeState {
|
|||
|
||||
pub fn break_path_at_selected_point(&self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -876,7 +876,7 @@ impl ShapeState {
|
|||
/// Delete point(s) and adjacent segments.
|
||||
pub fn delete_point_and_break_path(&self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -899,7 +899,7 @@ impl ShapeState {
|
|||
/// Disable colinear handles colinear.
|
||||
pub fn disable_colinear_handles_state_on_selected(&self, network_interface: &NodeNetworkInterface, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let Some(vector_data) = network_interface.document_metadata().compute_modified_vector(layer, network_interface) else {
|
||||
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -949,7 +949,7 @@ impl ShapeState {
|
|||
let mut closest_distance_squared: f64 = f64::MAX;
|
||||
let mut manipulator_point = None;
|
||||
|
||||
let vector_data = network_interface.document_metadata().compute_modified_vector(layer, network_interface)?;
|
||||
let vector_data = network_interface.compute_modified_vector(layer)?;
|
||||
let viewspace = network_interface.document_metadata().transform_to_viewport(layer);
|
||||
|
||||
// Handles
|
||||
|
|
@ -994,7 +994,7 @@ impl ShapeState {
|
|||
let mut closest = None;
|
||||
let mut closest_distance_squared: f64 = tolerance * tolerance;
|
||||
|
||||
let vector_data = network_interface.document_metadata().compute_modified_vector(layer, network_interface)?;
|
||||
let vector_data = network_interface.compute_modified_vector(layer)?;
|
||||
|
||||
for (segment, mut bezier, start, end) in vector_data.segment_bezier_iter() {
|
||||
let t = bezier.project(layer_pos);
|
||||
|
|
@ -1054,7 +1054,7 @@ impl ShapeState {
|
|||
/// This can can be activated by double clicking on an anchor with the Path tool.
|
||||
pub fn flip_smooth_sharp(&self, network_interface: &NodeNetworkInterface, target: glam::DVec2, tolerance: f64, responses: &mut VecDeque<Message>) -> bool {
|
||||
let mut process_layer = |layer| {
|
||||
let vector_data = network_interface.document_metadata().compute_modified_vector(layer, network_interface)?;
|
||||
let vector_data = network_interface.compute_modified_vector(layer)?;
|
||||
let transform_to_screenspace = network_interface.document_metadata().transform_to_viewport(layer);
|
||||
|
||||
let mut result = None;
|
||||
|
|
@ -1137,7 +1137,7 @@ impl ShapeState {
|
|||
state.clear_points()
|
||||
}
|
||||
|
||||
let vector_data = network_interface.document_metadata().compute_modified_vector(layer, network_interface);
|
||||
let vector_data = network_interface.compute_modified_vector(layer);
|
||||
let Some(vector_data) = vector_data else { continue };
|
||||
let transform = network_interface.document_metadata().transform_to_viewport(layer);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub fn should_extend(document: &DocumentMessageHandler, goal: DVec2, tolerance:
|
|||
for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) {
|
||||
let viewspace = document.metadata().transform_to_viewport(layer);
|
||||
|
||||
let vector_data = document.metadata().compute_modified_vector(layer, &document.network_interface)?;
|
||||
let vector_data = document.network_interface.compute_modified_vector(layer)?;
|
||||
for id in vector_data.single_connected_points() {
|
||||
let Some(point) = vector_data.point_domain.position_from_id(id) else { continue };
|
||||
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ impl PathToolData {
|
|||
let mut manipulators = HashMap::with_hasher(NoHashBuilder);
|
||||
let mut unselected = Vec::new();
|
||||
for (&layer, state) in &shape_editor.selected_shape_state {
|
||||
let Some(vector_data) = document.metadata().compute_modified_vector(layer, &document.network_interface) else {
|
||||
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
|
||||
continue;
|
||||
};
|
||||
let transform = document.metadata().transform_to_document(layer);
|
||||
|
|
@ -807,7 +807,7 @@ fn get_selection_status(network_interface: &NodeNetworkInterface, shape_state: &
|
|||
let Some(layer) = selection_layers.find(|(_, v)| *v > 0).map(|(k, _)| k) else {
|
||||
return SelectionStatus::None;
|
||||
};
|
||||
let Some(vector_data) = network_interface.document_metadata().compute_modified_vector(layer, network_interface) else {
|
||||
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
|
||||
return SelectionStatus::None;
|
||||
};
|
||||
let Some(&point) = shape_state.selected_points().next() else {
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ impl PenToolData {
|
|||
// Get close path
|
||||
let mut end = None;
|
||||
let layer = self.layer?;
|
||||
let vector_data = document.metadata().compute_modified_vector(layer, &document.network_interface)?;
|
||||
let vector_data = document.network_interface.compute_modified_vector(layer)?;
|
||||
let start = self.latest_point()?.id;
|
||||
let transform = document.metadata().document_to_viewport * transform;
|
||||
for id in vector_data.single_connected_points().filter(|&point| point != start) {
|
||||
|
|
|
|||
|
|
@ -1163,7 +1163,7 @@ impl Fsm for SelectToolFsmState {
|
|||
}
|
||||
|
||||
fn not_artboard(document: &DocumentMessageHandler) -> impl Fn(&LayerNodeIdentifier) -> bool + '_ {
|
||||
|&layer| !document.network_interface.is_artboard(&layer.to_node(), &[])
|
||||
|&layer| layer != LayerNodeIdentifier::ROOT_PARENT && !document.network_interface.is_artboard(&layer.to_node(), &[])
|
||||
}
|
||||
|
||||
fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) {
|
||||
|
|
@ -1173,14 +1173,7 @@ fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec
|
|||
.filter(not_artboard(document))
|
||||
.find(|&ancestor| document.network_interface.selected_nodes(&[]).unwrap().selected_layers_contains(ancestor, document.metadata()));
|
||||
|
||||
let new_selected = ancestor.unwrap_or_else(|| {
|
||||
layer
|
||||
.ancestors(document.metadata())
|
||||
.filter(not_artboard(document))
|
||||
.filter(|ancestor| *ancestor != LayerNodeIdentifier::ROOT_PARENT)
|
||||
.last()
|
||||
.unwrap_or(layer)
|
||||
});
|
||||
let new_selected = ancestor.unwrap_or_else(|| layer.ancestors(document.metadata()).filter(not_artboard(document)).last().unwrap_or(layer));
|
||||
tool_data.layers_dragging.retain(|layer| !layer.ancestors(document.metadata()).any(|ancestor| ancestor == new_selected));
|
||||
tool_data.layers_dragging.push(new_selected);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,10 +70,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
|
|||
}
|
||||
|
||||
if using_path_tool {
|
||||
if let Some(vector_data) = selected_layers
|
||||
.first()
|
||||
.and_then(|&layer| document.metadata().compute_modified_vector(layer, &document.network_interface))
|
||||
{
|
||||
if let Some(vector_data) = selected_layers.first().and_then(|&layer| document.network_interface.compute_modified_vector(layer)) {
|
||||
*selected.original_transforms = OriginalTransforms::default();
|
||||
let viewspace = document.metadata().transform_to_viewport(selected_layers[0]);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue