Remove the whole document-legacy crate (#1524)

Remove the whole document-legacy crate

Closes #1520
This commit is contained in:
Keavon Chambers
2023-12-20 05:45:54 -08:00
committed by GitHub
parent dcd38f2e4c
commit 92203f3576
62 changed files with 1287 additions and 1214 deletions
@@ -1,8 +1,8 @@
use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::prelude::*;
use bezier_rs::{ManipulatorGroup, Subpath};
use document_legacy::{document::Document, document_metadata::LayerNodeIdentifier};
use graph_craft::document::{value::TaggedValue, DocumentNode, NodeId, NodeInput, NodeNetwork};
use graphene_core::raster::{BlendMode, ImageFrame};
use graphene_core::text::Font;
@@ -48,8 +48,8 @@ pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<Manip
}
/// Locate the subpaths from the shape nodes of a particular layer
pub fn get_subpaths(layer: LayerNodeIdentifier, document: &Document) -> Option<&Vec<Subpath<ManipulatorGroupId>>> {
if let TaggedValue::Subpaths(subpaths) = NodeGraphLayer::new(layer, document)?.find_input("Shape", 0)? {
pub fn get_subpaths(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<&Vec<Subpath<ManipulatorGroupId>>> {
if let TaggedValue::Subpaths(subpaths) = NodeGraphLayer::new(layer, document_network)?.find_input("Shape", 0)? {
Some(subpaths)
} else {
None
@@ -57,23 +57,23 @@ pub fn get_subpaths(layer: LayerNodeIdentifier, document: &Document) -> Option<&
}
/// Locate the final pivot from the transform (TODO: decide how the pivot should actually work)
pub fn get_pivot(layer: LayerNodeIdentifier, document: &Document) -> Option<DVec2> {
if let TaggedValue::DVec2(pivot) = NodeGraphLayer::new(layer, document)?.find_input("Transform", 5)? {
pub fn get_pivot(layer: LayerNodeIdentifier, network: &NodeNetwork) -> Option<DVec2> {
if let TaggedValue::DVec2(pivot) = NodeGraphLayer::new(layer, network)?.find_input("Transform", 5)? {
Some(*pivot)
} else {
None
}
}
pub fn get_viewport_pivot(layer: LayerNodeIdentifier, document: &Document) -> DVec2 {
let [min, max] = document.metadata.nonzero_bounding_box(layer);
let pivot = get_pivot(layer, document).unwrap_or(DVec2::splat(0.5));
document.metadata.transform_to_viewport(layer).transform_point2(min + (max - min) * pivot)
pub fn get_viewport_pivot(layer: LayerNodeIdentifier, document_network: &NodeNetwork, document_metadata: &DocumentMetadata) -> DVec2 {
let [min, max] = document_metadata.nonzero_bounding_box(layer);
let pivot = get_pivot(layer, document_network).unwrap_or(DVec2::splat(0.5));
document_metadata.transform_to_viewport(layer).transform_point2(min + (max - min) * pivot)
}
/// Get the currently mirrored handles for a particular layer from the shape node
pub fn get_mirror_handles(layer: LayerNodeIdentifier, document: &Document) -> Option<&Vec<ManipulatorGroupId>> {
if let TaggedValue::ManipulatorGroupIds(mirror_handles) = NodeGraphLayer::new(layer, document)?.find_input("Shape", 1)? {
pub fn get_mirror_handles(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<&Vec<ManipulatorGroupId>> {
if let TaggedValue::ManipulatorGroupIds(mirror_handles) = NodeGraphLayer::new(layer, document_network)?.find_input("Shape", 1)? {
Some(mirror_handles)
} else {
None
@@ -81,8 +81,8 @@ pub fn get_mirror_handles(layer: LayerNodeIdentifier, document: &Document) -> Op
}
/// Get the current gradient of a layer from the closest Fill node
pub fn get_gradient(layer: LayerNodeIdentifier, document: &Document) -> Option<Gradient> {
let inputs = NodeGraphLayer::new(layer, document)?.find_node_inputs("Fill")?;
pub fn get_gradient(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<Gradient> {
let inputs = NodeGraphLayer::new(layer, document_network)?.find_node_inputs("Fill")?;
let TaggedValue::FillType(FillType::Gradient) = inputs.get(1)?.as_value()? else {
return None;
};
@@ -111,8 +111,8 @@ pub fn get_gradient(layer: LayerNodeIdentifier, document: &Document) -> Option<G
}
/// Get the current fill of a layer from the closest Fill node
pub fn get_fill_color(layer: LayerNodeIdentifier, document: &Document) -> Option<Color> {
let inputs = NodeGraphLayer::new(layer, document)?.find_node_inputs("Fill")?;
pub fn get_fill_color(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<Color> {
let inputs = NodeGraphLayer::new(layer, document_network)?.find_node_inputs("Fill")?;
let TaggedValue::Color(color) = inputs.get(2)?.as_value()? else {
return None;
};
@@ -120,8 +120,8 @@ pub fn get_fill_color(layer: LayerNodeIdentifier, document: &Document) -> Option
}
/// Get the current blend mode of a layer from the closest Blend Mode node
pub fn get_blend_mode(layer: LayerNodeIdentifier, document: &Document) -> Option<BlendMode> {
let inputs = NodeGraphLayer::new(layer, document)?.find_node_inputs("Blend Mode")?;
pub fn get_blend_mode(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<BlendMode> {
let inputs = NodeGraphLayer::new(layer, document_network)?.find_node_inputs("Blend Mode")?;
let TaggedValue::BlendMode(blend_mode) = inputs.get(1)?.as_value()? else {
return None;
};
@@ -135,25 +135,25 @@ pub fn get_blend_mode(layer: LayerNodeIdentifier, document: &Document) -> Option
/// - Already factored into the pixel alpha channel of an image
/// - The default value of 100% if no Opacity node is present, but this function returns None in that case
/// With those limitations in mind, the intention of this function is to show just the value already present in an upstream Opacity node so that value can be directly edited.
pub fn get_opacity(layer: LayerNodeIdentifier, document: &Document) -> Option<f32> {
let inputs = NodeGraphLayer::new(layer, document)?.find_node_inputs("Opacity")?;
pub fn get_opacity(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<f32> {
let inputs = NodeGraphLayer::new(layer, document_network)?.find_node_inputs("Opacity")?;
let TaggedValue::F32(opacity) = inputs.get(1)?.as_value()? else {
return None;
};
Some(*opacity)
}
pub fn get_fill_id(layer: LayerNodeIdentifier, document: &Document) -> Option<NodeId> {
NodeGraphLayer::new(layer, document)?.node_id("Fill")
pub fn get_fill_id(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<NodeId> {
NodeGraphLayer::new(layer, document_network)?.node_id("Fill")
}
pub fn get_text_id(layer: LayerNodeIdentifier, document: &Document) -> Option<NodeId> {
NodeGraphLayer::new(layer, document)?.node_id("Text")
pub fn get_text_id(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<NodeId> {
NodeGraphLayer::new(layer, document_network)?.node_id("Text")
}
/// Gets properties from the Text node
pub fn get_text(layer: LayerNodeIdentifier, document: &Document) -> Option<(&String, &Font, f64)> {
let inputs = NodeGraphLayer::new(layer, document)?.find_node_inputs("Text")?;
pub fn get_text(layer: LayerNodeIdentifier, document_network: &NodeNetwork) -> Option<(&String, &Font, f64)> {
let inputs = NodeGraphLayer::new(layer, document_network)?.find_node_inputs("Text")?;
let NodeInput::Value {
tagged_value: TaggedValue::String(text),
..
@@ -182,8 +182,8 @@ pub fn get_text(layer: LayerNodeIdentifier, document: &Document) -> Option<(&Str
}
/// Checks if a specified layer uses an upstream node matching the given name.
pub fn is_layer_fed_by_node_of_name(layer: LayerNodeIdentifier, document: &Document, node_name: &str) -> bool {
NodeGraphLayer::new(layer, document).is_some_and(|layer| layer.find_node_inputs(node_name).is_some())
pub fn is_layer_fed_by_node_of_name(layer: LayerNodeIdentifier, document_network: &NodeNetwork, node_name: &str) -> bool {
NodeGraphLayer::new(layer, document_network).is_some_and(|layer| layer.find_node_inputs(node_name).is_some())
}
/// Convert subpaths to an iterator of manipulator groups
@@ -205,12 +205,11 @@ pub struct NodeGraphLayer<'a> {
impl<'a> NodeGraphLayer<'a> {
/// Get the layer node from the document
pub fn new(layer: LayerNodeIdentifier, document: &'a document_legacy::document::Document) -> Option<Self> {
let node_graph = &document.document_network;
let outwards_links = document.document_network.collect_outwards_links();
pub fn new(layer: LayerNodeIdentifier, network: &'a NodeNetwork) -> Option<Self> {
let outwards_links = network.collect_outwards_links();
Some(Self {
node_graph,
node_graph: network,
_outwards_links: outwards_links,
layer_node: layer.to_node(),
})
@@ -4,10 +4,9 @@ use super::graph_modification_utils;
use crate::consts::PIVOT_OUTER;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*;
use document_legacy::document_metadata::LayerNodeIdentifier;
use glam::{DAffine2, DVec2};
use std::collections::VecDeque;
@@ -46,7 +45,7 @@ impl Pivot {
/// Recomputes the pivot position and transform.
fn recalculate_pivot(&mut self, document: &DocumentMessageHandler) {
let mut layers = document.document_legacy.selected_visible_layers();
let mut layers = document.selected_visible_layers();
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);
@@ -59,22 +58,21 @@ impl Pivot {
// If just one layer is selected we can use its inner transform (as it accounts for rotation)
if selected_layers_count == 1 {
let normalized_pivot = graph_modification_utils::get_pivot(first, &document.document_legacy).unwrap_or(DVec2::splat(0.5));
let normalized_pivot = graph_modification_utils::get_pivot(first, &document.network).unwrap_or(DVec2::splat(0.5));
self.normalized_pivot = normalized_pivot;
self.transform_from_normalized = Self::get_layer_pivot_transform(first, document);
self.pivot = Some(self.transform_from_normalized.transform_point2(normalized_pivot));
} else {
// If more than one layer is selected we use the AABB with the mean of the pivots
let xy_summation = document
.document_legacy
.selected_visible_layers()
.map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.document_legacy))
.map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.network, &document.metadata))
.reduce(|a, b| a + b)
.unwrap_or_default();
let pivot = xy_summation / selected_layers_count as f64;
self.pivot = Some(pivot);
let [min, max] = document.document_legacy.selected_visible_layers_bounding_box_viewport().unwrap_or([DVec2::ZERO, DVec2::ONE]);
let [min, max] = document.selected_visible_layers_bounding_box_viewport().unwrap_or([DVec2::ZERO, DVec2::ONE]);
self.normalized_pivot = (pivot - min) / (max - min);
self.transform_from_normalized = DAffine2::from_translation(min) * DAffine2::from_scale(max - min);
@@ -102,7 +100,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.document_legacy.selected_visible_layers() {
for layer in document.selected_visible_layers() {
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.
@@ -1,10 +1,9 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::document_metadata::LayerNodeIdentifier;
use glam::{DAffine2, DVec2, Vec2Swizzles};
#[derive(Clone, Debug, Default)]
@@ -1,12 +1,12 @@
use super::graph_modification_utils;
use crate::consts::DRAG_THRESHOLD;
use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils::{get_manipulator_from_id, get_manipulator_groups, get_mirror_handles, get_subpaths};
use bezier_rs::{Bezier, ManipulatorGroup, TValue};
use document_legacy::document::Document;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graph_craft::document::NodeNetwork;
use graphene_core::uuid::ManipulatorGroupId;
use graphene_core::vector::{ManipulatorPointId, SelectedType};
@@ -66,15 +66,22 @@ pub type OpposingHandleLengths = HashMap<LayerNodeIdentifier, HashMap<Manipulato
impl ShapeState {
/// Select the first point within the selection threshold.
/// Returns a tuple of the points if found and the offset, or `None` otherwise.
pub fn select_point(&mut self, document: &Document, mouse_position: DVec2, select_threshold: f64, add_to_selection: bool) -> Option<SelectedPointsInfo> {
pub fn select_point(
&mut self,
document_network: &NodeNetwork,
document_metadata: &DocumentMetadata,
mouse_position: DVec2,
select_threshold: f64,
add_to_selection: bool,
) -> Option<SelectedPointsInfo> {
if self.selected_shape_state.is_empty() {
return None;
}
if let Some((layer, manipulator_point_id)) = self.find_nearest_point_indices(document, mouse_position, select_threshold) {
if let Some((layer, manipulator_point_id)) = self.find_nearest_point_indices(document_network, document_metadata, mouse_position, select_threshold) {
trace!("Selecting... manipulator point: {manipulator_point_id:?}");
let subpaths = get_subpaths(layer, document)?;
let subpaths = get_subpaths(layer, document_network)?;
let manipulator_group = get_manipulator_groups(subpaths).find(|group| group.id == manipulator_point_id.group)?;
let point_position = manipulator_point_id.manipulator_type.get_position(manipulator_group)?;
@@ -96,7 +103,7 @@ impl ShapeState {
selected_shape_state.select_point(manipulator_point_id);
// Offset to snap the selected point to the cursor
let offset = mouse_position - document.metadata.transform_to_viewport(layer).transform_point2(point_position);
let offset = mouse_position - document_metadata.transform_to_viewport(layer).transform_point2(point_position);
let points = self
.selected_shape_state
@@ -115,9 +122,9 @@ impl ShapeState {
None
}
pub fn select_all_points(&mut self, document: &Document) {
pub fn select_all_points(&mut self, document_network: &NodeNetwork) {
for (layer, state) in self.selected_shape_state.iter_mut() {
let Some(subpaths) = get_subpaths(*layer, document) else { return };
let Some(subpaths) = get_subpaths(*layer, document_network) else { return };
for manipulator in get_manipulator_groups(subpaths) {
state.select_point(ManipulatorPointId::new(manipulator.id, SelectedType::Anchor));
for selected_type in &[SelectedType::InHandle, SelectedType::OutHandle] {
@@ -148,13 +155,13 @@ impl ShapeState {
}
/// A mutable iterator of all the manipulators, regardless of selection.
pub fn manipulator_groups<'a>(&'a self, document: &'a Document) -> impl Iterator<Item = &'a ManipulatorGroup<ManipulatorGroupId>> {
self.iter(document).flat_map(|subpaths| get_manipulator_groups(subpaths))
pub fn manipulator_groups<'a>(&'a self, document_network: &'a NodeNetwork) -> impl Iterator<Item = &'a ManipulatorGroup<ManipulatorGroupId>> {
self.iter(document_network).flat_map(|subpaths| get_manipulator_groups(subpaths))
}
// Sets the selected points to all points for the corresponding intersection
pub fn select_all_anchors(&mut self, document: &Document, layer: LayerNodeIdentifier) {
let Some(subpaths) = get_subpaths(layer, document) else { return };
pub fn select_all_anchors(&mut self, document_network: &NodeNetwork, layer: LayerNodeIdentifier) {
let Some(subpaths) = get_subpaths(layer, document_network) else { return };
let Some(state) = self.selected_shape_state.get_mut(&layer) else { return };
for manipulator in get_manipulator_groups(subpaths) {
state.select_point(ManipulatorPointId::new(manipulator.id, SelectedType::Anchor))
@@ -168,9 +175,17 @@ impl ShapeState {
/// Moves a control point to a `new_position` in document space.
/// Returns `Some(())` if successful and `None` otherwise.
pub fn reposition_control_point(&self, point: &ManipulatorPointId, responses: &mut VecDeque<Message>, document: &Document, new_position: DVec2, layer: LayerNodeIdentifier) -> Option<()> {
let subpaths = get_subpaths(layer, document)?;
let transform = document.metadata.transform_to_viewport(layer).inverse();
pub fn reposition_control_point(
&self,
point: &ManipulatorPointId,
responses: &mut VecDeque<Message>,
document_network: &NodeNetwork,
document_metadata: &DocumentMetadata,
new_position: DVec2,
layer: LayerNodeIdentifier,
) -> Option<()> {
let subpaths = get_subpaths(layer, document_network)?;
let transform = document_metadata.transform_to_viewport(layer).inverse();
let position = transform.transform_point2(new_position);
let group = graph_modification_utils::get_manipulator_from_id(subpaths, point.group)?;
let delta = position - point.manipulator_type.get_position(group)?;
@@ -203,12 +218,12 @@ impl ShapeState {
// Iterates over the selected manipulator groups, returning whether they have mixed, sharp, or smooth angles.
// If there are no points selected this function returns mixed.
pub fn selected_manipulator_angles(&self, document: &Document) -> ManipulatorAngle {
pub fn selected_manipulator_angles(&self, document_network: &NodeNetwork) -> ManipulatorAngle {
// This iterator contains a bool indicating whether or not every selected point has a smooth manipulator angle.
let mut point_smoothness_status = self
.selected_shape_state
.iter()
.filter_map(|(&layer, selection_state)| Some((graph_modification_utils::get_mirror_handles(layer, document)?, selection_state)))
.filter_map(|(&layer, selection_state)| Some((graph_modification_utils::get_mirror_handles(layer, document_network)?, selection_state)))
.flat_map(|(mirror, selection_state)| selection_state.selected_points.iter().map(|selected_point| mirror.contains(&selected_point.group)));
let Some(first_is_smooth) = point_smoothness_status.next() else { return ManipulatorAngle::Mixed };
@@ -291,11 +306,11 @@ impl ShapeState {
}
/// Smooths the set of selected control points, assuming that the selected set is homogeneously sharp.
pub fn smooth_selected_groups(&self, responses: &mut VecDeque<Message>, document: &Document) -> Option<()> {
pub fn smooth_selected_groups(&self, responses: &mut VecDeque<Message>, document_network: &NodeNetwork) -> Option<()> {
let mut skip_set = HashSet::new();
for (&layer, layer_state) in self.selected_shape_state.iter() {
let subpaths = get_subpaths(layer, document)?;
let subpaths = get_subpaths(layer, document_network)?;
for point in layer_state.selected_points.iter() {
if skip_set.contains(&point.group) {
@@ -357,12 +372,12 @@ impl ShapeState {
}
/// Move the selected points by dragging the mouse.
pub fn move_selected_points(&self, document: &Document, delta: DVec2, mirror_distance: bool, responses: &mut VecDeque<Message>) {
pub fn move_selected_points(&self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, delta: DVec2, mirror_distance: bool, responses: &mut VecDeque<Message>) {
for (&layer, state) in &self.selected_shape_state {
let Some(subpaths) = get_subpaths(layer, document) else { continue };
let Some(mirror_angle) = get_mirror_handles(layer, document) else { continue };
let Some(subpaths) = get_subpaths(layer, document_network) else { continue };
let Some(mirror_angle) = get_mirror_handles(layer, document_network) else { continue };
let transform = document.metadata.transform_to_viewport(layer);
let transform = document_metadata.transform_to_viewport(layer);
let delta = transform.inverse().transform_vector2(delta);
for &point in state.selected_points.iter() {
@@ -423,14 +438,20 @@ impl ShapeState {
}
/// Delete selected and mirrored handles with zero length when the drag stops.
pub fn delete_selected_handles_with_zero_length(&self, document: &Document, opposing_handle_lengths: &Option<OpposingHandleLengths>, responses: &mut VecDeque<Message>) {
pub fn delete_selected_handles_with_zero_length(
&self,
document_network: &NodeNetwork,
document_metadata: &DocumentMetadata,
opposing_handle_lengths: &Option<OpposingHandleLengths>,
responses: &mut VecDeque<Message>,
) {
for (&layer, state) in &self.selected_shape_state {
let Some(subpaths) = get_subpaths(layer, document) else { continue };
let Some(mirror_angle) = get_mirror_handles(layer, document) else { continue };
let Some(subpaths) = get_subpaths(layer, document_network) else { continue };
let Some(mirror_angle) = get_mirror_handles(layer, document_network) else { continue };
let opposing_handle_lengths = opposing_handle_lengths.as_ref().and_then(|lengths| lengths.get(&layer));
let transform = document.metadata.transform_to_viewport(layer);
let transform = document_metadata.transform_to_viewport(layer);
for &point in state.selected_points.iter() {
let anchor = ManipulatorPointId::new(point.group, SelectedType::Anchor);
@@ -472,11 +493,11 @@ impl ShapeState {
}
/// The opposing handle lengths.
pub fn opposing_handle_lengths(&self, document: &Document) -> OpposingHandleLengths {
pub fn opposing_handle_lengths(&self, document_network: &NodeNetwork) -> OpposingHandleLengths {
self.selected_shape_state
.iter()
.filter_map(|(&layer, state)| {
let subpaths = get_subpaths(layer, document)?;
let subpaths = get_subpaths(layer, document_network)?;
let opposing_handle_lengths = subpaths
.iter()
.flat_map(|subpath| {
@@ -514,10 +535,10 @@ impl ShapeState {
}
/// Reset the opposing handle lengths.
pub fn reset_opposing_handle_lengths(&self, document: &Document, opposing_handle_lengths: &OpposingHandleLengths, responses: &mut VecDeque<Message>) {
pub fn reset_opposing_handle_lengths(&self, document_network: &NodeNetwork, opposing_handle_lengths: &OpposingHandleLengths, responses: &mut VecDeque<Message>) {
for (&layer, state) in &self.selected_shape_state {
let Some(subpaths) = get_subpaths(layer, document) else { continue };
let Some(mirror_angle) = get_mirror_handles(layer, document) else { continue };
let Some(subpaths) = get_subpaths(layer, document_network) else { continue };
let Some(mirror_angle) = get_mirror_handles(layer, document_network) else { continue };
let Some(opposing_handle_lengths) = opposing_handle_lengths.get(&layer) else { continue };
for subpath in subpaths {
@@ -610,12 +631,18 @@ impl ShapeState {
}
/// Iterate over the shapes.
pub fn iter<'a>(&'a self, document: &'a Document) -> impl Iterator<Item = &'a Vec<bezier_rs::Subpath<ManipulatorGroupId>>> + 'a {
self.selected_shape_state.keys().filter_map(|&layer| get_subpaths(layer, document))
pub fn iter<'a>(&'a self, document_network: &'a NodeNetwork) -> impl Iterator<Item = &'a Vec<bezier_rs::Subpath<ManipulatorGroupId>>> + 'a {
self.selected_shape_state.keys().filter_map(|&layer| get_subpaths(layer, document_network))
}
/// Find a [ManipulatorPoint] that is within the selection threshold and return the layer path, an index to the [ManipulatorGroup], and an enum index for [ManipulatorPoint].
pub fn find_nearest_point_indices(&mut self, document: &Document, mouse_position: DVec2, select_threshold: f64) -> Option<(LayerNodeIdentifier, ManipulatorPointId)> {
pub fn find_nearest_point_indices(
&mut self,
document_network: &NodeNetwork,
document_metadata: &DocumentMetadata,
mouse_position: DVec2,
select_threshold: f64,
) -> Option<(LayerNodeIdentifier, ManipulatorPointId)> {
if self.selected_shape_state.is_empty() {
return None;
}
@@ -623,7 +650,7 @@ impl ShapeState {
let select_threshold_squared = select_threshold * select_threshold;
// Find the closest control point among all elements of shapes_to_modify
for &layer in self.selected_shape_state.keys() {
if let Some((manipulator_point_id, distance_squared)) = Self::closest_point_in_layer(document, layer, mouse_position) {
if let Some((manipulator_point_id, distance_squared)) = Self::closest_point_in_layer(document_network, document_metadata, layer, mouse_position) {
// Choose the first point under the threshold
if distance_squared < select_threshold_squared {
trace!("Selecting... manipulator point: {manipulator_point_id:?}");
@@ -639,12 +666,12 @@ impl ShapeState {
/// Find the closest manipulator, manipulator point, and distance so we can select path elements.
/// Brute force comparison to determine which manipulator (handle or anchor) we want to select taking O(n) time.
/// Return value is an `Option` of the tuple representing `(ManipulatorPointId, distance squared)`.
fn closest_point_in_layer(document: &Document, layer: LayerNodeIdentifier, pos: glam::DVec2) -> Option<(ManipulatorPointId, f64)> {
fn closest_point_in_layer(document_network: &NodeNetwork, document_metadata: &DocumentMetadata, layer: LayerNodeIdentifier, pos: glam::DVec2) -> Option<(ManipulatorPointId, f64)> {
let mut closest_distance_squared: f64 = f64::MAX;
let mut result = None;
let subpaths = get_subpaths(layer, document)?;
let viewspace = document.metadata.transform_to_viewport(layer);
let subpaths = get_subpaths(layer, document_network)?;
let viewspace = document_metadata.transform_to_viewport(layer);
for manipulator in get_manipulator_groups(subpaths) {
let (selected, distance_squared) = SelectedType::closest_widget(manipulator, viewspace, pos, crate::consts::HIDE_HANDLE_DISTANCE);
@@ -658,15 +685,22 @@ impl ShapeState {
}
/// Find the `t` value along the path segment we have clicked upon, together with that segment ID.
fn closest_segment(&self, document: &Document, layer: LayerNodeIdentifier, position: glam::DVec2, tolerance: f64) -> Option<(ManipulatorGroupId, ManipulatorGroupId, Bezier, f64)> {
let transform = document.metadata.transform_to_viewport(layer);
fn closest_segment(
&self,
document_network: &NodeNetwork,
document_metadata: &DocumentMetadata,
layer: LayerNodeIdentifier,
position: glam::DVec2,
tolerance: f64,
) -> Option<(ManipulatorGroupId, ManipulatorGroupId, Bezier, f64)> {
let transform = document_metadata.transform_to_viewport(layer);
let layer_pos = transform.inverse().transform_point2(position);
let projection_options = bezier_rs::ProjectionOptions { lut_size: 5, ..Default::default() };
let mut result = None;
let mut closest_distance_squared: f64 = tolerance * tolerance;
let subpaths = get_subpaths(layer, document)?;
let subpaths = get_subpaths(layer, document_network)?;
for subpath in subpaths {
for (manipulator_index, bezier) in subpath.iter().enumerate() {
@@ -689,9 +723,9 @@ impl ShapeState {
}
/// Handles the splitting of a curve to insert new points (which can be activated by double clicking on a curve with the Path tool).
pub fn split(&self, document: &Document, position: glam::DVec2, tolerance: f64, responses: &mut VecDeque<Message>) {
pub fn split(&self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, position: glam::DVec2, tolerance: f64, responses: &mut VecDeque<Message>) {
for &layer in self.selected_layers() {
if let Some((start, end, bezier, t)) = self.closest_segment(document, layer, position, tolerance) {
if let Some((start, end, bezier, t)) = self.closest_segment(document_network, document_metadata, layer, position, tolerance) {
let [first, second] = bezier.split(TValue::Parametric(t));
// Adjust the first manipulator group's out handle
@@ -726,11 +760,11 @@ impl ShapeState {
}
/// Handles the flipping between sharp corner and smooth (which can be activated by double clicking on an anchor with the Path tool).
pub fn flip_sharp(&self, document: &Document, position: glam::DVec2, tolerance: f64, responses: &mut VecDeque<Message>) -> bool {
pub fn flip_sharp(&self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, position: glam::DVec2, tolerance: f64, responses: &mut VecDeque<Message>) -> bool {
let mut process_layer = |layer| {
let subpaths = get_subpaths(layer, document)?;
let subpaths = get_subpaths(layer, document_network)?;
let transform_to_screenspace = document.metadata.transform_to_viewport(layer);
let transform_to_screenspace = document_metadata.transform_to_viewport(layer);
let mut result = None;
let mut closest_distance_squared = tolerance * tolerance;
@@ -751,7 +785,7 @@ impl ShapeState {
let subpath = &subpaths[subpath_index];
// Check by comparing the handle positions to the anchor if this maniuplator group is a point
// Check by comparing the handle positions to the anchor if this manipulator group is a point
let already_sharp = match (manipulator.in_handle, manipulator.out_handle) {
(Some(in_handle), Some(out_handle)) => anchor_position.abs_diff_eq(in_handle, 1e-10) && anchor_position.abs_diff_eq(out_handle, 1e-10),
(Some(handle), None) | (None, Some(handle)) => anchor_position.abs_diff_eq(handle, 1e-10),
@@ -790,15 +824,15 @@ impl ShapeState {
false
}
pub fn select_all_in_quad(&mut self, document: &Document, quad: [DVec2; 2], clear_selection: bool) {
pub fn select_all_in_quad(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, quad: [DVec2; 2], clear_selection: bool) {
for (&layer, state) in &mut self.selected_shape_state {
if clear_selection {
state.clear_points()
}
let Some(subpaths) = get_subpaths(layer, document) else { continue };
let Some(subpaths) = get_subpaths(layer, document_network) else { continue };
let transform = document.metadata.transform_to_viewport(layer);
let transform = document_metadata.transform_to_viewport(layer);
for manipulator_group in get_manipulator_groups(subpaths) {
for selected_type in [SelectedType::Anchor, SelectedType::InHandle, SelectedType::OutHandle] {
@@ -1,9 +1,8 @@
use super::shape_editor::ManipulatorPointInfo;
use crate::consts::{SNAP_AXIS_TOLERANCE, SNAP_POINT_TOLERANCE};
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use document_legacy::document::LayerId;
use glam::DVec2;
/// Handles snapping and snap overlays
@@ -1,12 +1,11 @@
use super::tool_prelude::*;
use crate::application::generate_uuid;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::tool::common_functionality::transformation_cage::*;
use document_legacy::document_metadata::LayerNodeIdentifier;
use glam::{IVec2, Vec2Swizzles};
#[derive(Default)]
@@ -132,9 +131,8 @@ impl ArtboardToolData {
responses.add(DocumentMessage::StartTransaction);
let mut intersections = document
.document_legacy
.click_xray(input.mouse.position)
.filter(|&layer| is_layer_fed_by_node_of_name(layer, &document.document_legacy, "Artboard"));
.filter(|&layer| is_layer_fed_by_node_of_name(layer, &document.network, "Artboard"));
responses.add(BroadcastEvent::DocumentIsDirty);
if let Some(intersection) = intersections.next() {
@@ -1,9 +1,9 @@
use super::tool_prelude::*;
use crate::messages::portfolio::document::node_graph::resolve_document_node_type;
use crate::messages::portfolio::document::node_graph::transform_utils::{get_current_normalized_pivot, get_current_transform};
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use document_legacy::document_metadata::LayerNodeIdentifier;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNodeMetadata, NodeInput};
use graphene_core::raster::BlendMode;
@@ -69,7 +69,7 @@ impl Fsm for FillToolFsmState {
let ToolMessage::Fill(event) = event else {
return self;
};
let Some(layer_identifier) = document.document_legacy.click(input.mouse.position, &document.document_legacy.document_network) else {
let Some(layer_identifier) = document.click(input.mouse.position, &document.network) else {
return self;
};
let layer = layer_identifier.to_path();
@@ -1,9 +1,9 @@
use super::tool_prelude::*;
use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color;
@@ -2,10 +2,10 @@ use super::tool_prelude::*;
use crate::application::generate_uuid;
use crate::consts::{LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD};
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::graph_modification_utils::get_gradient;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graphene_core::raster::color::Color;
use graphene_core::vector::style::{Fill, Gradient, GradientType};
@@ -170,7 +170,7 @@ impl SelectedGradient {
inner_gradient.transform = gradient_space_transform(inner_gradient.layer, document);
// Clear if no longer a gradient
let Some(gradient) = get_gradient(inner_gradient.layer, &document.document_legacy) else {
let Some(gradient) = get_gradient(inner_gradient.layer, &document.network) else {
responses.add(ToolMessage::RefreshToolOptions);
*gradient = None;
return;
@@ -296,8 +296,8 @@ impl Fsm for GradientToolFsmState {
(_, GradientToolMessage::Overlays(mut overlay_context)) => {
let selected = tool_data.selected_gradient.as_ref();
for layer in document.document_legacy.selected_visible_layers() {
let Some(gradient) = get_gradient(layer, &document.document_legacy) else { continue };
for layer in document.selected_visible_layers() {
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,8 +366,8 @@ impl Fsm for GradientToolFsmState {
self
}
(_, GradientToolMessage::InsertStop) => {
for layer in document.document_legacy.selected_visible_layers() {
let Some(mut gradient) = get_gradient(layer, &document.document_legacy) else { continue };
for layer in document.selected_visible_layers() {
let Some(mut gradient) = get_gradient(layer, &document.network) else { continue };
let transform = gradient_space_transform(layer, document);
let mouse = input.mouse.position;
@@ -407,8 +407,8 @@ impl Fsm for GradientToolFsmState {
let tolerance = (MANIPULATOR_GROUP_MARKER_SIZE * 2.).powi(2);
let mut dragging = false;
for layer in document.document_legacy.selected_visible_layers() {
let Some(gradient) = get_gradient(layer, &document.document_legacy) else { continue };
for layer in document.selected_visible_layers() {
let Some(gradient) = get_gradient(layer, &document.network) else { continue };
let transform = gradient_space_transform(layer, document);
// Check for dragging step
@@ -444,7 +444,7 @@ impl Fsm for GradientToolFsmState {
document.backup_nonmut(responses);
GradientToolFsmState::Drawing
} else {
let selected_layer = document.document_legacy.click(input.mouse.position, &document.document_legacy.document_network);
let selected_layer = document.click(input.mouse.position, &document.network);
// Apply the gradient to the selected layer
if let Some(layer) = selected_layer {
@@ -457,7 +457,7 @@ impl Fsm for GradientToolFsmState {
responses.add(DocumentMessage::StartTransaction);
// Use the already existing gradient if it exists
let gradient = if let Some(gradient) = get_gradient(layer, &document.document_legacy) {
let gradient = if let Some(gradient) = get_gradient(layer, &document.network) {
gradient.clone()
} else {
// Generate a new gradient
@@ -1,9 +1,8 @@
use super::tool_prelude::*;
use crate::messages::portfolio::document::node_graph::{self, IMAGINATE_NODE};
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::resize::Resize;
use document_legacy::document_metadata::LayerNodeIdentifier;
use serde::{Deserialize, Serialize};
#[derive(Default)]
@@ -1,10 +1,10 @@
use super::tool_prelude::*;
use crate::consts::LINE_ROTATE_SNAP_ANGLE;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::Stroke;
use graphene_core::Color;
@@ -2,12 +2,12 @@ use super::tool_prelude::*;
use crate::consts::{DRAG_THRESHOLD, SELECTION_THRESHOLD, SELECTION_TOLERANCE};
use crate::messages::portfolio::document::overlays::utility_functions::path_overlays;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::tool::common_functionality::graph_modification_utils::{get_manipulator_from_id, get_mirror_handles, get_subpaths};
use crate::messages::tool::common_functionality::shape_editor::{ManipulatorAngle, ManipulatorPointInfo, OpposingHandleLengths, SelectedPointsInfo, ShapeState};
use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::document::Document;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graph_craft::document::NodeNetwork;
use graphene_core::renderer::Quad;
use graphene_core::vector::{ManipulatorPointId, SelectedType};
@@ -223,14 +223,14 @@ 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.document_legacy, 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);
PathToolFsmState::Dragging
}
// We didn't find a point nearby, so consider selecting the nearest shape instead
else if let Some(layer) = document.document_legacy.click(input.mouse.position, &document.document_legacy.document_network) {
else if let Some(layer) = document.click(input.mouse.position, &document.network) {
if shift {
responses.add(NodeGraphMessage::SelectedNodesAdd { nodes: vec![layer.to_node()] });
} else {
@@ -238,7 +238,7 @@ impl PathToolData {
}
self.drag_start_pos = input.mouse.position;
self.previous_mouse_position = input.mouse.position;
shape_editor.select_all_anchors(&document.document_legacy, layer);
shape_editor.select_all_anchors(&document.network, layer);
PathToolFsmState::Dragging
} else {
@@ -292,16 +292,16 @@ impl PathToolData {
if shift {
if self.opposing_handle_lengths.is_none() {
self.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(&document.document_legacy));
self.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(&document.network));
}
} else if let Some(opposing_handle_lengths) = &self.opposing_handle_lengths {
shape_editor.reset_opposing_handle_lengths(&document.document_legacy, opposing_handle_lengths, responses);
shape_editor.reset_opposing_handle_lengths(&document.network, opposing_handle_lengths, responses);
self.opposing_handle_lengths = None;
}
// 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.document_legacy, 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;
}
}
@@ -365,7 +365,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.document_legacy, [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);
@@ -379,7 +379,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.document_legacy, [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);
@@ -391,16 +391,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.document_legacy, 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.document_legacy, &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.document_legacy, input.mouse.position, SELECTION_THRESHOLD, false);
shape_editor.select_point(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD, false);
responses.add(OverlaysMessage::Draw);
}
}
@@ -421,9 +421,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.document_legacy, 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.document_legacy, input.mouse.position, SELECTION_TOLERANCE, responses);
shape_editor.split(&document.network, &document.metadata, input.mouse.position, SELECTION_TOLERANCE, responses);
}
responses.add(PathToolMessage::SelectedPointUpdated);
@@ -436,35 +436,35 @@ impl Fsm for PathToolFsmState {
}
(_, PathToolMessage::PointerMove { .. }) => self,
(_, PathToolMessage::NudgeSelectedPoints { delta_x, delta_y }) => {
shape_editor.move_selected_points(&document.document_legacy, (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
}
(_, PathToolMessage::SelectAllPoints) => {
shape_editor.select_all_points(&document.document_legacy);
shape_editor.select_all_points(&document.network);
responses.add(OverlaysMessage::Draw);
PathToolFsmState::Ready
}
(_, 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.document_legacy, 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.document_legacy, 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.document_legacy, shape_editor);
tool_data.selection_status = get_selection_status(&document.network, &document.metadata, shape_editor);
self
}
(_, PathToolMessage::ManipulatorAngleMakeSmooth) => {
responses.add(DocumentMessage::StartTransaction);
shape_editor.set_handle_mirroring_on_selected(true, responses);
shape_editor.smooth_selected_groups(responses, &document.document_legacy);
shape_editor.smooth_selected_groups(responses, &document.network);
responses.add(DocumentMessage::CommitTransaction);
PathToolFsmState::Ready
}
@@ -549,7 +549,7 @@ struct SingleSelectedPoint {
/// Sets the cumulative description of the selected points: if `None` are selected, if `One` is selected, or if `Multiple` are selected.
/// Applies to any selected points, whether they are anchors or handles; and whether they are from a single shape or across multiple shapes.
fn get_selection_status(document: &Document, shape_state: &mut ShapeState) -> SelectionStatus {
fn get_selection_status(document_network: &NodeNetwork, document_metadata: &DocumentMetadata, shape_state: &mut ShapeState) -> SelectionStatus {
let mut selection_layers = shape_state.selected_shape_state.iter().map(|(k, v)| (*k, v.selected_points_count()));
let total_selected_points = selection_layers.clone().map(|(_, v)| v).sum::<usize>();
@@ -559,10 +559,10 @@ fn get_selection_status(document: &Document, shape_state: &mut ShapeState) -> Se
return SelectionStatus::None;
};
let Some(subpaths) = get_subpaths(layer, document) else {
let Some(subpaths) = get_subpaths(layer, document_network) else {
return SelectionStatus::None;
};
let Some(mirror) = get_mirror_handles(layer, document) else {
let Some(mirror) = get_mirror_handles(layer, document_network) else {
return SelectionStatus::None;
};
let Some(point) = shape_state.selected_points().next() else {
@@ -579,7 +579,7 @@ fn get_selection_status(document: &Document, shape_state: &mut ShapeState) -> Se
let manipulator_angle = if mirror.contains(&point.group) { ManipulatorAngle::Smooth } else { ManipulatorAngle::Sharp };
return SelectionStatus::One(SingleSelectedPoint {
coordinates: document.metadata.transform_to_document(layer).transform_point2(local_position),
coordinates: document_metadata.transform_to_document(layer).transform_point2(local_position),
layer,
id: *point,
manipulator_angle,
@@ -589,7 +589,7 @@ fn get_selection_status(document: &Document, shape_state: &mut ShapeState) -> Se
// Check to see if multiple manipulator groups are selected
if total_selected_points > 1 {
return SelectionStatus::Multiple(MultipleSelectedPoints {
manipulator_angle: shape_state.selected_manipulator_angles(document),
manipulator_angle: shape_state.selected_manipulator_angles(document_network),
});
}
@@ -3,12 +3,12 @@ use crate::consts::LINE_ROTATE_SNAP_ANGLE;
use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::portfolio::document::overlays::utility_functions::path_overlays;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::graph_modification_utils::get_subpaths;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graphene_core::uuid::{generate_uuid, ManipulatorGroupId};
use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::vector::{ManipulatorPointId, SelectedType};
@@ -217,7 +217,7 @@ impl PenToolData {
self.subpath_index = subpath_index;
// Stop the handles on the first point from mirroring
let Some(subpaths) = get_subpaths(layer, &document.document_legacy) else {
let Some(subpaths) = get_subpaths(layer, &document.network) else {
return;
};
let manipulator_groups = subpaths[subpath_index].manipulator_groups();
@@ -277,7 +277,7 @@ impl PenToolData {
fn check_break(&mut self, document: &DocumentMessageHandler, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<()> {
// Get subpath
let layer = self.layer?;
let subpath = &get_subpaths(layer, &document.document_legacy)?[self.subpath_index];
let subpath = &get_subpaths(layer, &document.network)?[self.subpath_index];
// Get the last manipulator group and the one previous to that
let mut manipulator_groups = subpath.manipulator_groups().iter();
@@ -323,7 +323,7 @@ impl PenToolData {
fn finish_placing_handle(&mut self, document: &DocumentMessageHandler, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
// Get subpath
let layer = self.layer?;
let subpath = &get_subpaths(layer, &document.document_legacy)?[self.subpath_index];
let subpath = &get_subpaths(layer, &document.network)?[self.subpath_index];
// Get the last manipulator group and the one previous to that
let mut manipulator_groups = subpath.manipulator_groups().iter();
@@ -395,7 +395,7 @@ impl PenToolData {
fn drag_handle(&mut self, document: &DocumentMessageHandler, transform: DAffine2, mouse: DVec2, modifiers: ModifierState, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
// Get subpath
let subpath = &get_subpaths(self.layer?, &document.document_legacy)?[self.subpath_index];
let subpath = &get_subpaths(self.layer?, &document.network)?[self.subpath_index];
// Get the last manipulator group
let manipulator_groups = subpath.manipulator_groups();
@@ -448,7 +448,7 @@ impl PenToolData {
fn place_anchor(&mut self, document: &DocumentMessageHandler, transform: DAffine2, mouse: DVec2, modifiers: ModifierState, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
// Get subpath
let layer = self.layer?;
let subpath = &get_subpaths(layer, &document.document_legacy)?[self.subpath_index];
let subpath = &get_subpaths(layer, &document.network)?[self.subpath_index];
// Get the last manipulator group and the one previous to that
let mut manipulator_groups = subpath.manipulator_groups().iter();
@@ -492,7 +492,7 @@ impl PenToolData {
fn finish_transaction(&mut self, fsm: PenToolFsmState, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) -> Option<DocumentMessage> {
// Get subpath
let subpath = &get_subpaths(self.layer?, &document.document_legacy)?[self.subpath_index];
let subpath = &get_subpaths(self.layer?, &document.network)?[self.subpath_index];
// Abort if only one manipulator group has been placed
if fsm == PenToolFsmState::PlacingAnchor && subpath.len() < 3 {
@@ -724,7 +724,7 @@ fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64)
for layer in document.metadata().selected_layers() {
let viewspace = document.metadata().transform_to_viewport(layer);
let subpaths = get_subpaths(layer, &document.document_legacy)?;
let subpaths = get_subpaths(layer, &document.network)?;
for (subpath_index, subpath) in subpaths.iter().enumerate() {
if subpath.closed() {
continue;
@@ -4,6 +4,7 @@ use super::tool_prelude::*;
use crate::consts::{ROTATE_SNAP_ANGLE, SELECTION_TOLERANCE};
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis};
use crate::messages::portfolio::document::utility_types::transformation::Selected;
use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name;
@@ -11,8 +12,7 @@ use crate::messages::tool::common_functionality::pivot::Pivot;
use crate::messages::tool::common_functionality::snapping::{self, SnapManager};
use crate::messages::tool::common_functionality::transformation_cage::*;
use document_legacy::document::Document;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graph_craft::document::NodeNetwork;
use graphene_core::renderer::Quad;
use std::fmt;
@@ -394,22 +394,21 @@ impl Fsm for SelectToolFsmState {
tool_data.selected_layers_count = selected_layers_count;
// Outline selected layers
for layer in document.document_legacy.selected_visible_layers() {
for layer in document.selected_visible_layers() {
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.document_legacy.click(input.mouse.position, &document.document_legacy.document_network);
let click = document.click(input.mouse.position, &document.network);
let not_selected_click = click.filter(|&hovered_layer| !document.metadata().selected_layers_contains(hovered_layer));
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.document_legacy.selected_visible_layers().next().map(|layer| document.metadata().transform_to_viewport(layer));
let transform = document.selected_visible_layers().next().map(|layer| document.metadata().transform_to_viewport(layer));
let transform = transform.unwrap_or(DAffine2::IDENTITY);
let bounds = document
.document_legacy
.selected_visible_layers()
.filter_map(|layer| {
document
@@ -440,10 +439,10 @@ impl Fsm for SelectToolFsmState {
}
(_, SelectToolMessage::EditLayer) => {
// Edit the clicked layer
if let Some(intersect) = document.document_legacy.click(input.mouse.position, &document.document_legacy.document_network) {
if let Some(intersect) = document.click(input.mouse.position, &document.network) {
match tool_data.nested_selection_behavior {
NestedSelectionBehavior::Shallowest => edit_layer_shallowest_manipulation(document, intersect, responses),
NestedSelectionBehavior::Deepest => edit_layer_deepest_manipulation(intersect, &document.document_legacy, responses),
NestedSelectionBehavior::Deepest => edit_layer_deepest_manipulation(intersect, &document.network, responses),
}
}
@@ -471,8 +470,8 @@ impl Fsm for SelectToolFsmState {
.map(|bounding_box| bounding_box.check_rotate(input.mouse.position))
.unwrap_or_default();
let mut selected: Vec<_> = document.document_legacy.selected_visible_layers().collect();
let intersection = document.document_legacy.click(input.mouse.position, &document.document_legacy.document_network);
let mut selected: Vec<_> = document.selected_visible_layers().collect();
let intersection = document.click(input.mouse.position, &document.network);
// If the user is dragging the bounding box bounds, go into ResizingBounds mode.
// If the user is dragging the rotate trigger, go into RotatingBounds mode.
@@ -502,16 +501,16 @@ impl Fsm for SelectToolFsmState {
tool_data.layers_dragging = selected;
if let Some(bounds) = &mut tool_data.bounding_box_manager {
let document = &document.document_legacy;
bounds.original_bound_transform = bounds.transform;
tool_data.layers_dragging.retain(|layer| document.document_network.nodes.contains_key(&layer.to_node()));
tool_data.layers_dragging.retain(|layer| document.network.nodes.contains_key(&layer.to_node()));
let mut selected = Selected::new(
&mut bounds.original_transforms,
&mut bounds.center_of_transformation,
&tool_data.layers_dragging,
responses,
document,
&document.network,
&document.metadata,
None,
&ToolType::Select,
);
@@ -529,7 +528,8 @@ impl Fsm for SelectToolFsmState {
&mut bounds.center_of_transformation,
&selected,
responses,
&document.document_legacy,
&document.network,
&document.metadata,
None,
&ToolType::Select,
);
@@ -639,7 +639,16 @@ impl Fsm for SelectToolFsmState {
tool_data.layers_dragging.retain(|layer| document.network().nodes.contains_key(&layer.to_node()));
let selected = &tool_data.layers_dragging;
let mut selected = Selected::new(&mut bounds.original_transforms, &mut pivot, selected, responses, &document.document_legacy, None, &ToolType::Select);
let mut selected = Selected::new(
&mut bounds.original_transforms,
&mut pivot,
selected,
responses,
&document.network,
&document.metadata,
None,
&ToolType::Select,
);
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse());
}
@@ -670,7 +679,8 @@ impl Fsm for SelectToolFsmState {
&mut bounds.center_of_transformation,
&tool_data.layers_dragging,
responses,
&document.document_legacy,
&document.network,
&document.metadata,
None,
&ToolType::Select,
);
@@ -725,7 +735,7 @@ impl Fsm for SelectToolFsmState {
// Deselect layer if not snap dragging
if !tool_data.has_dragged && input.keyboard.key(remove_from_selection) && tool_data.layer_selected_on_start.is_none() {
let quad = tool_data.selection_quad();
let intersection = document.document_legacy.intersect_quad(quad, &document.document_legacy.document_network);
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();
@@ -795,7 +805,7 @@ impl Fsm for SelectToolFsmState {
}
(SelectToolFsmState::DrawingBox, SelectToolMessage::DragStop { .. } | SelectToolMessage::Enter) => {
let quad = tool_data.selection_quad();
let new_selected: HashSet<_> = document.document_legacy.intersect_quad(quad, &document.document_legacy.document_network).collect();
let new_selected: HashSet<_> = document.intersect_quad(quad, &document.network).collect();
let current_selected: HashSet<_> = document.metadata().selected_layers().collect();
if new_selected != current_selected {
tool_data.layers_dragging = new_selected.into_iter().collect();
@@ -813,7 +823,7 @@ impl Fsm for SelectToolFsmState {
if let Some(layer) = selected_layers.next() {
// Check that only one layer is selected
if selected_layers.next().is_none() && is_layer_fed_by_node_of_name(layer, &document.document_legacy, "Text") {
if selected_layers.next().is_none() && is_layer_fed_by_node_of_name(layer, &document.network, "Text") {
responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Text });
responses.add(TextToolMessage::EditSelected);
}
@@ -836,7 +846,8 @@ impl Fsm for SelectToolFsmState {
&mut bounding_box_overlays.opposite_pivot,
&tool_data.layers_dragging,
responses,
&document.document_legacy,
&document.network,
&document.metadata,
None,
&ToolType::Select,
);
@@ -951,11 +962,11 @@ fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, layer:
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![new_selected.to_node()] });
}
fn edit_layer_deepest_manipulation(layer: LayerNodeIdentifier, document: &Document, responses: &mut VecDeque<Message>) {
if is_layer_fed_by_node_of_name(layer, document, "Text") {
fn edit_layer_deepest_manipulation(layer: LayerNodeIdentifier, document_network: &NodeNetwork, responses: &mut VecDeque<Message>) {
if is_layer_fed_by_node_of_name(layer, document_network, "Text") {
responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Text });
responses.add(TextToolMessage::EditSelected);
} else if is_layer_fed_by_node_of_name(layer, document, "Shape") {
} else if is_layer_fed_by_node_of_name(layer, document_network, "Shape") {
responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Path });
}
}
@@ -1,11 +1,11 @@
use super::tool_prelude::*;
use crate::consts::DRAG_THRESHOLD;
use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::document_metadata::LayerNodeIdentifier;
use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color;
@@ -3,10 +3,10 @@
use super::tool_prelude::*;
use crate::application::generate_uuid;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils::{self, is_layer_fed_by_node_of_name};
use document_legacy::document_metadata::LayerNodeIdentifier;
use graph_craft::document::value::TaggedValue;
use graphene_core::renderer::Quad;
use graphene_core::text::{load_face, Font, FontCache};
@@ -225,7 +225,7 @@ struct TextToolData {
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.document_legacy) {
if let Some(node_id) = graph_modification_utils::get_fill_id(self.layer, &document.network) {
responses.add(NodeGraphMessage::SetHidden { node_id, hidden: editable });
}
@@ -245,8 +245,8 @@ impl TextToolData {
fn load_layer_text_node(&mut self, document: &DocumentMessageHandler) -> Option<()> {
let transform = document.metadata().transform_to_viewport(self.layer);
let color = graph_modification_utils::get_fill_color(self.layer, &document.document_legacy).unwrap_or(Color::BLACK);
let (text, font, font_size) = graph_modification_utils::get_text(self.layer, &document.document_legacy)?;
let color = graph_modification_utils::get_fill_color(self.layer, &document.network).unwrap_or(Color::BLACK);
let (text, font, font_size) = graph_modification_utils::get_text(self.layer, &document.network)?;
self.editing_text = Some(EditingText {
text: text.clone(),
font: font.clone(),
@@ -276,9 +276,8 @@ impl TextToolData {
fn interact(&mut self, state: TextToolFsmState, mouse: DVec2, document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque<Message>) -> TextToolFsmState {
// Check if the user has selected an existing text layer
if let Some(clicked_text_layer_path) = document
.document_legacy
.click(mouse, document.network())
.filter(|&layer| is_layer_fed_by_node_of_name(layer, &document.document_legacy, "Text"))
.filter(|&layer| is_layer_fed_by_node_of_name(layer, &document.network, "Text"))
{
self.start_editing_layer(clicked_text_layer_path, state, document, font_cache, responses);
@@ -350,7 +349,7 @@ fn can_edit_selected(document: &DocumentMessageHandler) -> Option<LayerNodeIdent
return None;
}
if !is_layer_fed_by_node_of_name(layer, &document.document_legacy, "Text") {
if !is_layer_fed_by_node_of_name(layer, &document.network, "Text") {
return None;
}
@@ -391,7 +390,7 @@ impl Fsm for TextToolFsmState {
}
(_, TextToolMessage::Overlays(mut overlay_context)) => {
for layer in document.metadata().selected_layers() {
let Some((text, font, font_size)) = graph_modification_utils::get_text(layer, &document.document_legacy) else {
let Some((text, font, font_size)) = graph_modification_utils::get_text(layer, &document.network) else {
continue;
};
let buzz_face = font_cache.get(font).map(|data| load_face(data));
@@ -439,7 +438,7 @@ impl Fsm for TextToolFsmState {
tool_data.fix_text_bounds(&new_text, document, font_cache, responses);
responses.add(NodeGraphMessage::SetQualifiedInputValue {
layer_path: Vec::new(),
node_path: vec![graph_modification_utils::get_text_id(tool_data.layer, &document.document_legacy).unwrap()],
node_path: vec![graph_modification_utils::get_text_id(tool_data.layer, &document.network).unwrap()],
input_index: 1,
value: TaggedValue::String(new_text),
});
@@ -55,7 +55,8 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
&mut self.pivot,
&selected_layers,
responses,
&document.document_legacy,
&document.network,
&document.metadata,
Some(shape_editor),
&tool_data.active_tool_type,
);
@@ -67,7 +68,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
}
if using_path_tool {
if let Some(subpaths) = selected_layers.first().and_then(|&layer| graph_modification_utils::get_subpaths(layer, &document.document_legacy)) {
if let Some(subpaths) = selected_layers.first().and_then(|&layer| graph_modification_utils::get_subpaths(layer, &document.network)) {
*selected.original_transforms = OriginalTransforms::default();
let viewspace = document.metadata().transform_to_viewport(selected_layers[0]);
-29
View File
@@ -599,32 +599,3 @@ impl HintInfo {
self
}
}
#[cfg(test)]
mod tool_crash_on_layer_delete_tests {
use crate::application::{set_uuid_seed, Editor};
use crate::messages::portfolio::document::DocumentMessage;
use crate::messages::tool::utility_types::ToolType;
use crate::test_utils::EditorTestUtils;
use test_case::test_case;
#[test_case(ToolType::Pen; "while using Pen tool")]
#[test_case(ToolType::Freehand; "while using Freehand tool")]
#[test_case(ToolType::Spline; "while using Spline tool")]
#[test_case(ToolType::Line; "while using Line tool")]
#[test_case(ToolType::Rectangle; "while using Rectangle tool")]
#[test_case(ToolType::Ellipse; "while using Ellipse tool")]
#[test_case(ToolType::Polygon; "while using Polygon tool")]
#[test_case(ToolType::Path; "while using Path tool")]
fn should_not_crash_when_layer_is_deleted(tool: ToolType) {
set_uuid_seed(0);
let mut test_editor = Editor::new();
test_editor.select_tool(tool);
test_editor.lmb_mousedown(0.0, 0.0);
test_editor.move_mouse(100.0, 100.0);
test_editor.handle_message(DocumentMessage::DeleteSelectedLayers);
}
}