From 90befbd9bc599e4d1a63adf7fac3ef5bfc382e37 Mon Sep 17 00:00:00 2001 From: 0hypercube <0hypercube@gmail.com> Date: Sat, 25 Feb 2023 11:21:35 +0000 Subject: [PATCH] Add vector data type --- Cargo.lock | 8 +- document-legacy/src/consts.rs | 6 -- document-legacy/src/layers/mod.rs | 9 ++- document-legacy/src/layers/render_data.rs | 22 ++++++ editor/Cargo.toml | 2 - editor/src/application.rs | 25 +----- node-graph/gcore/Cargo.toml | 2 + node-graph/gcore/src/consts.rs | 5 ++ node-graph/gcore/src/lib.rs | 2 + node-graph/gcore/src/raster/color.rs | 2 +- node-graph/gcore/src/uuid.rs | 38 ++++++++++ node-graph/gcore/src/vector/mod.rs | 12 ++- .../gcore/src/vector/style.rs | 76 +++++++++---------- node-graph/gcore/src/vector/vector_data.rs | 12 +++ node-graph/gpu-compiler/Cargo.toml | 1 - node-graph/graph-craft/Cargo.toml | 1 - node-graph/graph-craft/src/document.rs | 15 +--- node-graph/interpreted-executor/Cargo.toml | 1 - node-graph/vulkan-executor/Cargo.toml | 1 - node-graph/wgpu-executor/Cargo.toml | 1 - 20 files changed, 140 insertions(+), 101 deletions(-) create mode 100644 document-legacy/src/layers/render_data.rs create mode 100644 node-graph/gcore/src/consts.rs rename document-legacy/src/layers/style/mod.rs => node-graph/gcore/src/vector/style.rs (93%) create mode 100644 node-graph/gcore/src/vector/vector_data.rs diff --git a/Cargo.lock b/Cargo.lock index e1eb3ede48..4c25face4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1629,7 +1629,6 @@ dependencies = [ "graphene-core", "log", "num-traits", - "rand_chacha 0.3.1", "serde", "specta", ] @@ -1647,8 +1646,10 @@ dependencies = [ "log", "node-macro", "once_cell", + "rand_chacha 0.3.1", "serde", "specta", + "spin 0.9.4", "spirv-std", ] @@ -1738,12 +1739,10 @@ dependencies = [ "kurbo", "log", "once_cell", - "rand_chacha 0.3.1", "remain", "serde", "serde_json", "specta", - "spin 0.9.4", "test-case", "thiserror", ] @@ -2173,7 +2172,6 @@ dependencies = [ "log", "num-traits", "once_cell", - "rand_chacha 0.3.1", "serde", ] @@ -5122,7 +5120,6 @@ dependencies = [ "graphene-core", "log", "num-traits", - "rand_chacha 0.3.1", "serde", "vulkano", ] @@ -5477,7 +5474,6 @@ dependencies = [ "graphene-core", "log", "num-traits", - "rand_chacha 0.3.1", "serde", "spirv", "wgpu", diff --git a/document-legacy/src/consts.rs b/document-legacy/src/consts.rs index 1521cec344..df9c3752d1 100644 --- a/document-legacy/src/consts.rs +++ b/document-legacy/src/consts.rs @@ -1,9 +1,3 @@ -use graphene_core::raster::color::Color; - -// RENDERING -pub const LAYER_OUTLINE_STROKE_COLOR: Color = Color::BLACK; -pub const LAYER_OUTLINE_STROKE_WEIGHT: f64 = 1.; - // BOOLEAN OPERATIONS // Bezier curve intersection algorithm diff --git a/document-legacy/src/layers/mod.rs b/document-legacy/src/layers/mod.rs index 94306fa1aa..abd54f1414 100644 --- a/document-legacy/src/layers/mod.rs +++ b/document-legacy/src/layers/mod.rs @@ -25,6 +25,13 @@ pub mod layer_info; pub mod nodegraph_layer; /// Contains the [ShapeLayer](shape_layer::ShapeLayer) type, a generic SVG element defined using Bezier paths. pub mod shape_layer; -pub mod style; /// Contains the [TextLayer](text_layer::TextLayer) type. pub mod text_layer; + +mod render_data; +pub use render_data::RenderData; + +pub mod style { + pub use super::RenderData; + pub use graphene_core::vector::style::*; +} diff --git a/document-legacy/src/layers/render_data.rs b/document-legacy/src/layers/render_data.rs new file mode 100644 index 0000000000..804303fe41 --- /dev/null +++ b/document-legacy/src/layers/render_data.rs @@ -0,0 +1,22 @@ +use super::style::ViewMode; +use super::text_layer::FontCache; + +use glam::DVec2; + +/// Contains metadata for rendering the document as an svg +#[derive(Debug, Clone, Copy)] +pub struct RenderData<'a> { + pub font_cache: &'a FontCache, + pub view_mode: ViewMode, + pub culling_bounds: Option<[DVec2; 2]>, +} + +impl<'a> RenderData<'a> { + pub fn new(font_cache: &'a FontCache, view_mode: ViewMode, culling_bounds: Option<[DVec2; 2]>) -> Self { + Self { + font_cache, + view_mode, + culling_bounds, + } + } +} diff --git a/editor/Cargo.toml b/editor/Cargo.toml index 361b135052..04684c5379 100644 --- a/editor/Cargo.toml +++ b/editor/Cargo.toml @@ -23,8 +23,6 @@ serde_json = { version = "1.0" } graphite-proc-macros = { path = "../proc-macros" } bezier-rs = { path = "../libraries/bezier-rs" } glam = { version="0.22", features = ["serde"] } -rand_chacha = "0.3.1" -spin = "0.9.2" kurbo = { git = "https://github.com/linebender/kurbo.git", features = [ "serde", ] } diff --git a/editor/src/application.rs b/editor/src/application.rs index 86621321b8..434ebd41ee 100644 --- a/editor/src/application.rs +++ b/editor/src/application.rs @@ -1,15 +1,7 @@ use crate::dispatcher::Dispatcher; use crate::messages::prelude::*; -use rand_chacha::rand_core::{RngCore, SeedableRng}; -use rand_chacha::ChaCha20Rng; -use spin::Mutex; -use std::cell::Cell; - -static RNG: Mutex> = Mutex::new(None); -thread_local! { - pub static UUID_SEED: Cell> = Cell::new(None); -} +pub use graphene_core::uuid::*; // TODO: serialize with serde to save the current editor state pub struct Editor { @@ -39,21 +31,6 @@ impl Default for Editor { } } -pub fn set_uuid_seed(random_seed: u64) { - UUID_SEED.with(|seed| seed.set(Some(random_seed))) -} - -pub fn generate_uuid() -> u64 { - let mut lock = RNG.lock(); - if lock.is_none() { - UUID_SEED.with(|seed| { - let random_seed = seed.get().expect("Random seed not set before editor was initialized"); - *lock = Some(ChaCha20Rng::seed_from_u64(random_seed)); - }) - } - lock.as_mut().map(ChaCha20Rng::next_u64).unwrap() -} - pub fn release_series() -> String { format!("Release Series: {}", env!("GRAPHITE_RELEASE_SERIES")) } diff --git a/node-graph/gcore/Cargo.toml b/node-graph/gcore/Cargo.toml index c8ebf90509..3d1e7daf6f 100644 --- a/node-graph/gcore/Cargo.toml +++ b/node-graph/gcore/Cargo.toml @@ -33,6 +33,8 @@ kurbo = { git = "https://github.com/linebender/kurbo.git", features = [ "serde", ], optional = true } glam = { version = "^0.22", default-features = false, features = ["scalar-math", "libm"]} +rand_chacha = "0.3.1" +spin = "0.9.2" node-macro = {path = "../node-macro"} specta.workspace = true once_cell = { version = "1.17.0", default-features = false } diff --git a/node-graph/gcore/src/consts.rs b/node-graph/gcore/src/consts.rs new file mode 100644 index 0000000000..498ba32dc4 --- /dev/null +++ b/node-graph/gcore/src/consts.rs @@ -0,0 +1,5 @@ +use crate::raster::Color; + +// RENDERING +pub const LAYER_OUTLINE_STROKE_COLOR: Color = Color::BLACK; +pub const LAYER_OUTLINE_STROKE_WEIGHT: f64 = 1.; diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index 92208ddd03..5c18ec8080 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -7,6 +7,7 @@ extern crate alloc; #[cfg(feature = "log")] extern crate log; +pub mod consts; pub mod generic; pub mod ops; pub mod structural; @@ -22,6 +23,7 @@ pub mod raster; pub mod vector; use core::any::TypeId; +pub use raster::Color; // pub trait Node: for<'n> NodeIO<'n> { pub trait Node<'i, Input: 'i>: 'i { diff --git a/node-graph/gcore/src/raster/color.rs b/node-graph/gcore/src/raster/color.rs index 14c8111ac1..9231e8fa4d 100644 --- a/node-graph/gcore/src/raster/color.rs +++ b/node-graph/gcore/src/raster/color.rs @@ -28,7 +28,7 @@ pub struct Color { alpha: f32, } -#[allow(clippy::derive_hash_xor_eq)] +#[allow(clippy::derived_hash_with_manual_eq)] impl Hash for Color { fn hash(&self, state: &mut H) { self.red.to_bits().hash(state); diff --git a/node-graph/gcore/src/uuid.rs b/node-graph/gcore/src/uuid.rs index 6bbfcdd054..b410eb4544 100644 --- a/node-graph/gcore/src/uuid.rs +++ b/node-graph/gcore/src/uuid.rs @@ -40,3 +40,41 @@ mod u64_string { u64::from_str(&s).map_err(serde::de::Error::custom) } } + +mod uuid_generation { + use core::cell::Cell; + use rand_chacha::rand_core::{RngCore, SeedableRng}; + use rand_chacha::ChaCha20Rng; + use spin::Mutex; + + static RNG: Mutex> = Mutex::new(None); + thread_local! { + pub static UUID_SEED: Cell> = Cell::new(None); + } + + pub fn set_uuid_seed(random_seed: u64) { + UUID_SEED.with(|seed| seed.set(Some(random_seed))) + } + + pub fn generate_uuid() -> u64 { + let mut lock = RNG.lock(); + if lock.is_none() { + UUID_SEED.with(|seed| { + let random_seed = seed.get().unwrap_or(42); + *lock = Some(ChaCha20Rng::seed_from_u64(random_seed)); + }) + } + lock.as_mut().map(ChaCha20Rng::next_u64).expect("uuid mutex poisoned") + } +} + +pub use uuid_generation::*; + +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct ManipulatorGroupId(u64); + +impl bezier_rs::Identifier for ManipulatorGroupId { + fn new() -> Self { + Self(generate_uuid()) + } +} diff --git a/node-graph/gcore/src/vector/mod.rs b/node-graph/gcore/src/vector/mod.rs index e93c6ad495..3ac05c9d0f 100644 --- a/node-graph/gcore/src/vector/mod.rs +++ b/node-graph/gcore/src/vector/mod.rs @@ -1,6 +1,16 @@ pub mod consts; pub mod generator_nodes; -pub mod id_vec; pub mod manipulator_group; pub mod manipulator_point; + +pub mod style; +pub use style::PathStyle; + pub mod subpath; +pub use subpath::Subpath; + +mod vector_data; +pub use vector_data::VectorData; + +mod id_vec; +pub use id_vec::IdBackedVec; diff --git a/document-legacy/src/layers/style/mod.rs b/node-graph/gcore/src/vector/style.rs similarity index 93% rename from document-legacy/src/layers/style/mod.rs rename to node-graph/gcore/src/vector/style.rs index c86991dd21..62b245f1fb 100644 --- a/document-legacy/src/layers/style/mod.rs +++ b/node-graph/gcore/src/vector/style.rs @@ -1,9 +1,7 @@ //! Contains stylistic options for SVG elements. -use super::text_layer::FontCache; use crate::consts::{LAYER_OUTLINE_STROKE_COLOR, LAYER_OUTLINE_STROKE_WEIGHT}; - -use graphene_core::raster::color::Color; +use crate::Color; use glam::{DAffine2, DVec2}; use serde::{Deserialize, Serialize}; @@ -21,36 +19,6 @@ fn format_opacity(name: &str, opacity: f32) -> String { } } -/// Represents different ways of rendering an object -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, specta::Type)] -pub enum ViewMode { - /// Render with normal coloration at the current viewport resolution - #[default] - Normal, - /// Render only the outlines of shapes at the current viewport resolution - Outline, - /// Render with normal coloration at the document resolution, showing the pixels when the current viewport resolution is higher - Pixels, -} - -/// Contains metadata for rendering the document as an svg -#[derive(Debug, Clone, Copy)] -pub struct RenderData<'a> { - pub font_cache: &'a FontCache, - pub view_mode: ViewMode, - pub culling_bounds: Option<[DVec2; 2]>, -} - -impl<'a> RenderData<'a> { - pub fn new(font_cache: &'a FontCache, view_mode: ViewMode, culling_bounds: Option<[DVec2; 2]>) -> Self { - Self { - font_cache, - view_mode, - culling_bounds, - } - } -} - #[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, Serialize, Deserialize, specta::Type)] pub enum GradientType { #[default] @@ -62,7 +30,7 @@ pub enum GradientType { /// /// Contains the start and end points, along with the colors at varying points along the length. #[repr(C)] -#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, specta::Type)] +#[derive(Debug, PartialEq, Default, Serialize, Deserialize, specta::Type)] pub struct Gradient { pub start: DVec2, pub end: DVec2, @@ -71,7 +39,6 @@ pub struct Gradient { uuid: u64, pub gradient_type: GradientType, } - impl Gradient { /// Constructs a new gradient with the colors at 0 and 1 specified. pub fn new(start: DVec2, start_color: Color, end: DVec2, end_color: Color, transform: DAffine2, uuid: u64, gradient_type: GradientType) -> Self { @@ -170,6 +137,21 @@ impl Gradient { } } +impl Clone for Gradient { + /// Clones the gradient, with the cloned gradient having the new uuid. + /// If multiple gradients have the same id then only one gradient will be shown in the final svg output. + fn clone(&self) -> Self { + Self { + start: self.start, + end: self.end, + transform: self.transform, + positions: self.positions.clone(), + uuid: crate::uuid::generate_uuid(), + gradient_type: self.gradient_type, + } + } +} + /// Describes the fill of a layer. /// /// Can be None, a solid [Color], a linear [Gradient], a radial [Gradient] or potentially some sort of image or pattern in the future @@ -410,7 +392,7 @@ impl PathStyle { /// /// # Example /// ``` - /// # use graphite_document_legacy::layers::style::{Fill, PathStyle}; + /// # use graphene_core::vector::style::{Fill, PathStyle}; /// # use graphene_core::raster::color::Color; /// let fill = Fill::solid(Color::RED); /// let style = PathStyle::new(None, fill.clone()); @@ -425,7 +407,7 @@ impl PathStyle { /// /// # Example /// ``` - /// # use graphite_document_legacy::layers::style::{Fill, Stroke, PathStyle}; + /// # use graphene_core::vector::style::{Fill, Stroke, PathStyle}; /// # use graphene_core::raster::color::Color; /// let stroke = Stroke::new(Color::GREEN, 42.); /// let style = PathStyle::new(Some(stroke.clone()), Fill::None); @@ -440,7 +422,7 @@ impl PathStyle { /// /// # Example /// ``` - /// # use graphite_document_legacy::layers::style::{Fill, PathStyle}; + /// # use graphene_core::vector::style::{Fill, PathStyle}; /// # use graphene_core::raster::color::Color; /// let mut style = PathStyle::default(); /// @@ -459,7 +441,7 @@ impl PathStyle { /// /// # Example /// ``` - /// # use graphite_document_legacy::layers::style::{Stroke, PathStyle}; + /// # use graphene_core::vector::style::{Stroke, PathStyle}; /// # use graphene_core::raster::color::Color; /// let mut style = PathStyle::default(); /// @@ -478,7 +460,7 @@ impl PathStyle { /// /// # Example /// ``` - /// # use graphite_document_legacy::layers::style::{Fill, PathStyle}; + /// # use graphene_core::vector::style::{Fill, PathStyle}; /// # use graphene_core::raster::color::Color; /// let mut style = PathStyle::new(None, Fill::Solid(Color::RED)); /// @@ -496,7 +478,7 @@ impl PathStyle { /// /// # Example /// ``` - /// # use graphite_document_legacy::layers::style::{Fill, Stroke, PathStyle}; + /// # use graphene_core::vector::style::{Fill, Stroke, PathStyle}; /// # use graphene_core::raster::color::Color; /// let mut style = PathStyle::new(Some(Stroke::new(Color::GREEN, 42.)), Fill::None); /// @@ -524,3 +506,15 @@ impl PathStyle { format!("{}{}", fill_attribute, stroke_attribute) } } + +/// Represents different ways of rendering an object +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, specta::Type)] +pub enum ViewMode { + /// Render with normal coloration at the current viewport resolution + #[default] + Normal, + /// Render only the outlines of shapes at the current viewport resolution + Outline, + /// Render with normal coloration at the document resolution, showing the pixels when the current viewport resolution is higher + Pixels, +} diff --git a/node-graph/gcore/src/vector/vector_data.rs b/node-graph/gcore/src/vector/vector_data.rs new file mode 100644 index 0000000000..cb9a07e448 --- /dev/null +++ b/node-graph/gcore/src/vector/vector_data.rs @@ -0,0 +1,12 @@ +use glam::DAffine2; + +use super::style::PathStyle; +use crate::uuid::ManipulatorGroupId; + +/// [VectorData] is passed between nodes. +/// It contains a list of subpaths (that may be open or closed), a transform and some style information. +pub struct VectorData { + pub subpaths: Vec>, + pub transform: DAffine2, + pub style: PathStyle, +} diff --git a/node-graph/gpu-compiler/Cargo.toml b/node-graph/gpu-compiler/Cargo.toml index a32c92be51..22160289cc 100644 --- a/node-graph/gpu-compiler/Cargo.toml +++ b/node-graph/gpu-compiler/Cargo.toml @@ -16,7 +16,6 @@ graphene-core = { path = "../gcore", features = ["async", "std", "alloc"] } graph-craft = {path = "../graph-craft", features = ["serde"] } dyn-any = { path = "../../libraries/dyn-any", features = ["log-bad-types", "rc", "glam"] } num-traits = "0.2" -rand_chacha = "0.3.1" log = "0.4" serde = { version = "1", features = ["derive", "rc"]} glam = { version = "0.22" } diff --git a/node-graph/graph-craft/Cargo.toml b/node-graph/graph-craft/Cargo.toml index f0caf1fe1b..4f5c99896e 100644 --- a/node-graph/graph-craft/Cargo.toml +++ b/node-graph/graph-craft/Cargo.toml @@ -15,7 +15,6 @@ graphene-core = { path = "../gcore", features = ["std"] } dyn-any = { path = "../../libraries/dyn-any", features = ["log-bad-types", "rc", "glam"] } num-traits = "0.2" dyn-clone = "1.0" -rand_chacha = "0.3.1" log = "0.4" serde = { version = "1", features = ["derive", "rc"], optional = true } glam = { version = "0.22" } diff --git a/node-graph/graph-craft/src/document.rs b/node-graph/graph-craft/src/document.rs index 83ba93299b..bf3d1cdda7 100644 --- a/node-graph/graph-craft/src/document.rs +++ b/node-graph/graph-craft/src/document.rs @@ -4,27 +4,14 @@ use graphene_core::{NodeIdentifier, Type}; use dyn_any::{DynAny, StaticType}; use glam::IVec2; +pub use graphene_core::uuid::generate_uuid; use graphene_core::TypeDescriptor; -use rand_chacha::{ - rand_core::{RngCore, SeedableRng}, - ChaCha20Rng, -}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use std::sync::Mutex; pub mod value; pub type NodeId = u64; -static RNG: Mutex> = Mutex::new(None); - -pub fn generate_uuid() -> u64 { - let mut lock = RNG.lock().expect("uuid mutex poisoned"); - if lock.is_none() { - *lock = Some(ChaCha20Rng::seed_from_u64(0)); - } - lock.as_mut().map(ChaCha20Rng::next_u64).unwrap() -} fn merge_ids(a: u64, b: u64) -> u64 { use std::hash::{Hash, Hasher}; diff --git a/node-graph/interpreted-executor/Cargo.toml b/node-graph/interpreted-executor/Cargo.toml index 3dfad3fc69..27abad1b54 100644 --- a/node-graph/interpreted-executor/Cargo.toml +++ b/node-graph/interpreted-executor/Cargo.toml @@ -20,7 +20,6 @@ dyn-any = { path = "../../libraries/dyn-any", features = ["log-bad-types", "glam num-traits = "0.2" borrow_stack = { path = "../borrow_stack" } dyn-clone = "1.0" -rand_chacha = "0.3.1" log = "0.4" serde = { version = "1", features = ["derive"], optional = true } glam = { version = "0.22" } diff --git a/node-graph/vulkan-executor/Cargo.toml b/node-graph/vulkan-executor/Cargo.toml index 26af1ac696..ff3266526c 100644 --- a/node-graph/vulkan-executor/Cargo.toml +++ b/node-graph/vulkan-executor/Cargo.toml @@ -14,7 +14,6 @@ graphene-core = { path = "../gcore", features = ["async", "std", "alloc", "gpu"] graph-craft = {path = "../graph-craft" } dyn-any = { path = "../../libraries/dyn-any", features = ["log-bad-types", "rc", "glam"] } num-traits = "0.2" -rand_chacha = "0.3.1" log = "0.4" serde = { version = "1", features = ["derive", "rc"], optional = true } glam = { version = "0.22" } diff --git a/node-graph/wgpu-executor/Cargo.toml b/node-graph/wgpu-executor/Cargo.toml index fdda9d1573..02b8046194 100644 --- a/node-graph/wgpu-executor/Cargo.toml +++ b/node-graph/wgpu-executor/Cargo.toml @@ -15,7 +15,6 @@ graph-craft = {path = "../graph-craft" } dyn-any = { path = "../../libraries/dyn-any", features = ["log-bad-types", "rc", "glam"] } future-executor = { path = "../future-executor" } num-traits = "0.2" -rand_chacha = "0.3.1" log = "0.4" serde = { version = "1", features = ["derive", "rc"], optional = true } glam = { version = "0.22" }