mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 08:58:13 +08:00
Remove the whole document-legacy crate (#1524)
Remove the whole document-legacy crate Closes #1520
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user