From d581319ee8272db06d4cd029acf09682f813b399 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 27 Jun 2025 12:30:12 +0200 Subject: [PATCH] Prep `gcore` splitup 2: Vector extension traits (#2759) * extension trait for `MergeByDistance::merge_by_distance_*` * extension trait for `VectorData::append_bezpath` * extension trait for `HandleId::set_relative_position` * remove unreferenced rust files --- .../document/utility_types/transformation.rs | 2 +- .../tool/common_functionality/shape_editor.rs | 2 +- .../common_functionality/utility_functions.rs | 2 +- .../messages/tool/tool_messages/path_tool.rs | 2 +- .../gcore/src/raster/image/base64_serde.rs | 0 .../vector/algorithms/merge_by_distance.rs | 11 ++-- node-graph/gcore/src/vector/algorithms/mod.rs | 6 +-- node-graph/gcore/src/vector/mod.rs | 2 +- node-graph/gcore/src/vector/vector_data.rs | 15 ------ .../src/vector/vector_data/modification.rs | 27 ++++++++++ node-graph/gcore/src/vector/vector_nodes.rs | 3 +- node-graph/gstd/src/cache.rs | 51 ------------------- node-graph/gstd/src/value.rs | 45 ---------------- node-graph/gstd/src/vector.rs | 1 + 14 files changed, 46 insertions(+), 123 deletions(-) delete mode 100644 node-graph/gcore/src/raster/image/base64_serde.rs delete mode 100644 node-graph/gstd/src/cache.rs delete mode 100644 node-graph/gstd/src/value.rs diff --git a/editor/src/messages/portfolio/document/utility_types/transformation.rs b/editor/src/messages/portfolio/document/utility_types/transformation.rs index 4970433e7..a8aff3805 100644 --- a/editor/src/messages/portfolio/document/utility_types/transformation.rs +++ b/editor/src/messages/portfolio/document/utility_types/transformation.rs @@ -9,8 +9,8 @@ use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::utility_types::ToolType; use glam::{DAffine2, DMat2, DVec2}; use graphene_std::renderer::Quad; -use graphene_std::vector::ManipulatorPointId; use graphene_std::vector::VectorModificationType; +use graphene_std::vector::{HandleExt, ManipulatorPointId}; use graphene_std::vector::{HandleId, PointId}; use std::collections::{HashMap, VecDeque}; use std::f64::consts::PI; diff --git a/editor/src/messages/tool/common_functionality/shape_editor.rs b/editor/src/messages/tool/common_functionality/shape_editor.rs index 218c53c6c..c1f7e99f0 100644 --- a/editor/src/messages/tool/common_functionality/shape_editor.rs +++ b/editor/src/messages/tool/common_functionality/shape_editor.rs @@ -12,7 +12,7 @@ use crate::messages::tool::common_functionality::utility_functions::is_visible_p use crate::messages::tool::tool_messages::path_tool::{PathOverlayMode, PointSelectState}; use bezier_rs::{Bezier, BezierHandles, Subpath, TValue}; use glam::{DAffine2, DVec2}; -use graphene_std::vector::{HandleId, SegmentId}; +use graphene_std::vector::{HandleExt, HandleId, SegmentId}; use graphene_std::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType}; #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/editor/src/messages/tool/common_functionality/utility_functions.rs b/editor/src/messages/tool/common_functionality/utility_functions.rs index c6974d500..abe84224a 100644 --- a/editor/src/messages/tool/common_functionality/utility_functions.rs +++ b/editor/src/messages/tool/common_functionality/utility_functions.rs @@ -12,7 +12,7 @@ use bezier_rs::Bezier; use glam::{DAffine2, DVec2}; use graphene_std::renderer::Quad; use graphene_std::text::{FontCache, load_face}; -use graphene_std::vector::{HandleId, ManipulatorPointId, PointId, SegmentId, VectorData, VectorModificationType}; +use graphene_std::vector::{HandleExt, HandleId, ManipulatorPointId, PointId, SegmentId, VectorData, VectorModificationType}; /// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable. pub fn should_extend( diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 395d6a432..51c1fa579 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -18,7 +18,7 @@ use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandi use crate::messages::tool::common_functionality::utility_functions::{calculate_segment_angle, find_two_param_best_approximate}; use bezier_rs::{Bezier, TValue}; use graphene_std::renderer::Quad; -use graphene_std::vector::{HandleId, NoHashBuilder, SegmentId, VectorData}; +use graphene_std::vector::{HandleExt, HandleId, NoHashBuilder, SegmentId, VectorData}; use graphene_std::vector::{ManipulatorPointId, PointId, VectorModificationType}; use std::vec; diff --git a/node-graph/gcore/src/raster/image/base64_serde.rs b/node-graph/gcore/src/raster/image/base64_serde.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/node-graph/gcore/src/vector/algorithms/merge_by_distance.rs b/node-graph/gcore/src/vector/algorithms/merge_by_distance.rs index 4d598f5fd..7cd5adc4c 100644 --- a/node-graph/gcore/src/vector/algorithms/merge_by_distance.rs +++ b/node-graph/gcore/src/vector/algorithms/merge_by_distance.rs @@ -3,9 +3,14 @@ use glam::{DAffine2, DVec2}; use petgraph::prelude::UnGraphMap; use rustc_hash::FxHashSet; -impl VectorData { +pub trait MergeByDistanceExt { /// Collapse all points with edges shorter than the specified distance - pub fn merge_by_distance_topological(&mut self, distance: f64) { + fn merge_by_distance_topological(&mut self, distance: f64); + fn merge_by_distance_spatial(&mut self, transform: DAffine2, distance: f64); +} + +impl MergeByDistanceExt for VectorData { + fn merge_by_distance_topological(&mut self, distance: f64) { // Treat self as an undirected graph let indices = VectorDataIndex::build_from(self); @@ -95,7 +100,7 @@ impl VectorData { self.point_domain.retain(&mut self.segment_domain, |id| !points_to_delete.contains(id)); } - pub fn merge_by_distance_spatial(&mut self, transform: DAffine2, distance: f64) { + fn merge_by_distance_spatial(&mut self, transform: DAffine2, distance: f64) { let point_count = self.point_domain.positions().len(); // Find min x and y for grid cell normalization diff --git a/node-graph/gcore/src/vector/algorithms/mod.rs b/node-graph/gcore/src/vector/algorithms/mod.rs index 40b76fcd4..ed44f2559 100644 --- a/node-graph/gcore/src/vector/algorithms/mod.rs +++ b/node-graph/gcore/src/vector/algorithms/mod.rs @@ -1,6 +1,6 @@ pub mod bezpath_algorithms; -mod instance; -mod merge_by_distance; +pub mod instance; +pub mod merge_by_distance; pub mod offset_subpath; -mod poisson_disk; +pub mod poisson_disk; pub mod spline; diff --git a/node-graph/gcore/src/vector/mod.rs b/node-graph/gcore/src/vector/mod.rs index 5293e88f8..e54620307 100644 --- a/node-graph/gcore/src/vector/mod.rs +++ b/node-graph/gcore/src/vector/mod.rs @@ -1,4 +1,4 @@ -mod algorithms; +pub mod algorithms; pub mod brush_stroke; pub mod click_target; pub mod generator_nodes; diff --git a/node-graph/gcore/src/vector/vector_data.rs b/node-graph/gcore/src/vector/vector_data.rs index 6b442926f..7a596058d 100644 --- a/node-graph/gcore/src/vector/vector_data.rs +++ b/node-graph/gcore/src/vector/vector_data.rs @@ -186,11 +186,6 @@ impl VectorData { self.point_domain.push(id, point.position); } - /// Appends a Kurbo BezPath to the vector data. - pub fn append_bezpath(&mut self, bezpath: kurbo::BezPath) { - AppendBezpath::append_bezpath(self, bezpath); - } - /// Construct some new vector data from a single subpath with an identity transform and black fill. pub fn from_subpath(subpath: impl Borrow>) -> Self { Self::from_subpaths([subpath], false) @@ -637,16 +632,6 @@ impl HandleId { handle_position.map(|pos| (pos - anchor_position).length()).unwrap_or(f64::MAX) } - /// Set the handle's position relative to the anchor which is the start anchor for the primary handle and end anchor for the end handle. - #[must_use] - pub fn set_relative_position(self, relative_position: DVec2) -> VectorModificationType { - let Self { ty, segment } = self; - match ty { - HandleType::Primary => VectorModificationType::SetPrimaryHandle { segment, relative_position }, - HandleType::End => VectorModificationType::SetEndHandle { segment, relative_position }, - } - } - /// Convert an end handle to the primary handle and a primary handle to an end handle. Note that the new handle may not exist (e.g. for a quadratic bézier). #[must_use] pub fn opposite(self) -> Self { diff --git a/node-graph/gcore/src/vector/vector_data/modification.rs b/node-graph/gcore/src/vector/vector_data/modification.rs index 15ed28b63..0f06c643a 100644 --- a/node-graph/gcore/src/vector/vector_data/modification.rs +++ b/node-graph/gcore/src/vector/vector_data/modification.rs @@ -634,6 +634,33 @@ impl<'a> AppendBezpath<'a> { } } +pub trait VectorDataExt { + /// Appends a Kurbo BezPath to the vector data. + fn append_bezpath(&mut self, bezpath: BezPath); +} + +impl VectorDataExt for VectorData { + fn append_bezpath(&mut self, bezpath: BezPath) { + AppendBezpath::append_bezpath(self, bezpath); + } +} + +pub trait HandleExt { + /// Set the handle's position relative to the anchor which is the start anchor for the primary handle and end anchor for the end handle. + #[must_use] + fn set_relative_position(self, relative_position: DVec2) -> VectorModificationType; +} + +impl HandleExt for HandleId { + fn set_relative_position(self, relative_position: DVec2) -> VectorModificationType { + let Self { ty, segment } = self; + match ty { + HandleType::Primary => VectorModificationType::SetPrimaryHandle { segment, relative_position }, + HandleType::End => VectorModificationType::SetEndHandle { segment, relative_position }, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs index c2c3fdbd3..877e2bc4f 100644 --- a/node-graph/gcore/src/vector/vector_nodes.rs +++ b/node-graph/gcore/src/vector/vector_nodes.rs @@ -3,12 +3,13 @@ use super::algorithms::offset_subpath::offset_subpath; use super::algorithms::spline::{solve_spline_first_handle_closed, solve_spline_first_handle_open}; use super::misc::{CentroidType, point_to_dvec2}; use super::style::{Fill, Gradient, GradientStops, Stroke}; -use super::{PointId, SegmentDomain, SegmentId, StrokeId, VectorData, VectorDataTable}; +use super::{PointId, SegmentDomain, SegmentId, StrokeId, VectorData, VectorDataExt, VectorDataTable}; use crate::instances::{Instance, InstanceMut, Instances}; use crate::raster_types::{CPU, GPU, RasterDataTable}; use crate::registry::types::{Angle, Fraction, IntegerCount, Length, Multiplier, Percentage, PixelLength, PixelSize, SeedValue}; use crate::renderer::GraphicElementRendered; use crate::transform::{Footprint, ReferencePoint, Transform}; +use crate::vector::algorithms::merge_by_distance::MergeByDistanceExt; use crate::vector::misc::{MergeByDistanceAlgorithm, PointSpacingType}; use crate::vector::style::{PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; use crate::vector::{FillId, PointDomain, RegionId}; diff --git a/node-graph/gstd/src/cache.rs b/node-graph/gstd/src/cache.rs deleted file mode 100644 index 2a3bbe27d..000000000 --- a/node-graph/gstd/src/cache.rs +++ /dev/null @@ -1,51 +0,0 @@ -use parking_lot::RawRwLock; -use std::any::Any; -use std::borrow::Borrow; -use std::cell::RefCell; -use std::collections::hash_map::DefaultHasher; -use std::collections::HashMap; -use std::hash::{Hash, Hasher}; -use std::iter::{self, Sum}; -use std::marker::PhantomData; -use storage_map::{StorageMap, StorageMapGuard}; - -/// Caches the output of a given Node and acts as a proxy -/// Automatically resets if it receives different input -pub struct SmartCacheNode<'n, 'c, NODE: Node + 'c> { - node: &'n NODE, - map: StorageMap>>, -} -impl<'n: 'c, 'c, NODE: Node + 'c> Node for SmartCacheNode<'n, 'c, NODE> -where - for<'a> NODE::Input<'a>: Hash, -{ - type Input<'a> - = NODE::Input<'a> - where - Self: 'a, - 'c: 'a; - type Output<'a> - = StorageMapGuard<'a, RawRwLock, CacheNode<'n, 'c, NODE>> - where - Self: 'a, - 'c: 'a; - fn eval<'a, I: Borrow>>(&'a self, input: I) -> Self::Output<'a> { - let mut hasher = DefaultHasher::new(); - input.borrow().hash(&mut hasher); - let hash = hasher.finish(); - - self.map.get_or_create_with(&hash, || { - trace!("Creating new cache node"); - CacheNode::new(self.node) - }) - } -} - -impl<'n, 'c, NODE: Node> SmartCacheNode<'n, 'c, NODE> { - pub fn clear(&'n mut self) { - self.map = StorageMap::default(); - } - pub fn new(node: &'n NODE) -> SmartCacheNode<'n, 'c, NODE> { - SmartCacheNode { node, map: StorageMap::default() } - } -} diff --git a/node-graph/gstd/src/value.rs b/node-graph/gstd/src/value.rs deleted file mode 100644 index 8fdf5f34e..000000000 --- a/node-graph/gstd/src/value.rs +++ /dev/null @@ -1,45 +0,0 @@ -use core::marker::PhantomData; -pub use graphene_core::value::*; -use graphene_core::Node; -use dyn_any::DynAny; - -pub struct AnyRefNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>); - -impl<'n, N: Node<'n, Output = &'n O>, O: DynAny<'n> + 'n> Node<'n> for AnyRefNode<'n, N> { - fn eval(&'n self) -> &'n (dyn DynAny<'n>) { - let value: &O = self.0.eval(); - value - } -} -impl<'n, N: Node<'n, Output = &'n O>, O: 'n + ?Sized> AnyRefNode<'n, N> { - pub fn new(n: N) -> AnyRefNode<'n, N> { - AnyRefNode(n, PhantomData) - } -} - -pub struct StorageNode<'n>(&'n dyn Node<'n, Output = &'n dyn DynAny<'n>>); - -impl<'n> Node<'n> for StorageNode<'n> { - fn eval(&'n self) -> &'n (dyn DynAny<'n>) { - self.0.eval() - } -} -impl<'n> StorageNode<'n> { - pub fn new>>(n: &'n N) -> StorageNode<'n> { - StorageNode(n) - } -} - -#[derive(Default)] -pub struct AnyValueNode<'n, T>(T, PhantomData<&'n ()>); -impl<'n, T: 'n + DynAny<'n>> Node<'n> for AnyValueNode<'n, T> { - fn eval(&'n self) -> &'n dyn DynAny<'n> { - &self.0 - } -} - -impl<'n, T> AnyValueNode<'n, T> { - pub const fn new(value: T) -> AnyValueNode<'n, T> { - AnyValueNode(value, PhantomData) - } -} diff --git a/node-graph/gstd/src/vector.rs b/node-graph/gstd/src/vector.rs index 8b82d23dd..754f62df7 100644 --- a/node-graph/gstd/src/vector.rs +++ b/node-graph/gstd/src/vector.rs @@ -1,6 +1,7 @@ use bezier_rs::{ManipulatorGroup, Subpath}; use glam::{DAffine2, DVec2}; use graphene_core::instances::{Instance, InstanceRef}; +use graphene_core::vector::algorithms::merge_by_distance::MergeByDistanceExt; use graphene_core::vector::misc::BooleanOperation; use graphene_core::vector::style::Fill; pub use graphene_core::vector::*;