mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Instance tables refactor part 4: replace ArtboardGroups with multi-row Instances<Artboard> (#2265)
* Clean up dyn_any usages * Migrate ArtboardGroup to ArtboardGroupTable (not yet flattened) * Reorder graphical data imports * Flatten and remove ArtboardGroup in favor of ArtboardGroupTable * Fix test
This commit is contained in:
@@ -49,6 +49,7 @@ impl TransformMut for SurfaceFrame {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl StaticType for SurfaceFrame {
|
||||
type Static = SurfaceFrame;
|
||||
}
|
||||
@@ -90,6 +91,7 @@ impl PartialEq for ImageTexture {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl StaticType for ImageTexture {
|
||||
type Static = ImageTexture;
|
||||
}
|
||||
@@ -128,6 +130,7 @@ impl<S: Size> Size for SurfaceHandle<S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<T: 'static> StaticType for SurfaceHandle<T> {
|
||||
type Static = SurfaceHandle<T>;
|
||||
}
|
||||
@@ -138,6 +141,7 @@ pub struct SurfaceHandleFrame<Surface> {
|
||||
pub transform: DAffine2,
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<T: 'static> StaticType for SurfaceHandleFrame<T> {
|
||||
type Static = SurfaceHandleFrame<T>;
|
||||
}
|
||||
@@ -317,6 +321,7 @@ impl<T> Debug for EditorApi<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<T: StaticTypeSized> StaticType for EditorApi<T> {
|
||||
type Static = EditorApi<T::Static>;
|
||||
}
|
||||
|
||||
@@ -238,6 +238,12 @@ pub struct Artboard {
|
||||
pub clip: bool,
|
||||
}
|
||||
|
||||
impl Default for Artboard {
|
||||
fn default() -> Self {
|
||||
Self::new(IVec2::ZERO, IVec2::new(1920, 1080))
|
||||
}
|
||||
}
|
||||
|
||||
impl Artboard {
|
||||
pub fn new(location: IVec2, dimensions: IVec2) -> Self {
|
||||
Self {
|
||||
@@ -251,23 +257,38 @@ impl Artboard {
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains multiple artboards.
|
||||
#[derive(Clone, Default, Debug, Hash, PartialEq, DynAny)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ArtboardGroup {
|
||||
pub artboards: Vec<(Artboard, Option<NodeId>)>,
|
||||
}
|
||||
// TODO: Eventually remove this migration document upgrade code
|
||||
pub fn migrate_artboard_group<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<ArtboardGroupTable, D::Error> {
|
||||
use serde::Deserialize;
|
||||
|
||||
impl ArtboardGroup {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
#[derive(Clone, Default, Debug, Hash, PartialEq, DynAny)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ArtboardGroup {
|
||||
pub artboards: Vec<(Artboard, Option<NodeId>)>,
|
||||
}
|
||||
|
||||
fn append_artboard(&mut self, artboard: Artboard, node_id: Option<NodeId>) {
|
||||
self.artboards.push((artboard, node_id));
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum EitherFormat {
|
||||
ArtboardGroup(ArtboardGroup),
|
||||
ArtboardGroupTable(ArtboardGroupTable),
|
||||
}
|
||||
|
||||
Ok(match EitherFormat::deserialize(deserializer)? {
|
||||
EitherFormat::ArtboardGroup(artboard_group) => {
|
||||
let mut table = ArtboardGroupTable::empty();
|
||||
for (artboard, source_node_id) in artboard_group.artboards {
|
||||
table.push(artboard);
|
||||
*table.instances_mut().last().unwrap().source_node_id = source_node_id;
|
||||
}
|
||||
table
|
||||
}
|
||||
EitherFormat::ArtboardGroupTable(artboard_group_table) => artboard_group_table,
|
||||
})
|
||||
}
|
||||
|
||||
pub type ArtboardGroupTable = Instances<Artboard>;
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
async fn layer(_: impl Ctx, stack: GraphicGroupTable, mut element: GraphicElement, node_path: Vec<NodeId>) -> GraphicGroupTable {
|
||||
let mut stack = stack;
|
||||
@@ -385,15 +406,13 @@ async fn to_artboard<Data: Into<GraphicGroupTable> + 'n>(
|
||||
}
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
async fn append_artboard(_ctx: impl Ctx, mut artboards: ArtboardGroup, artboard: Artboard, node_path: Vec<NodeId>) -> ArtboardGroup {
|
||||
// let mut artboards = artboards.eval(ctx.clone()).await;
|
||||
// let artboard = artboard.eval(ctx).await;
|
||||
// let foot = ctx.footprint();
|
||||
// log::debug!("{:?}", foot);
|
||||
async fn append_artboard(_ctx: impl Ctx, mut artboards: ArtboardGroupTable, artboard: Artboard, node_path: Vec<NodeId>) -> ArtboardGroupTable {
|
||||
// Get the penultimate element of the node path, or None if the path is too short.
|
||||
// This is used to get the ID of the user-facing "Artboard" node (which encapsulates this internal "Append Artboard" node).
|
||||
let encapsulating_node_id = node_path.get(node_path.len().wrapping_sub(2)).copied();
|
||||
artboards.append_artboard(artboard, encapsulating_node_id);
|
||||
|
||||
artboards.push(artboard);
|
||||
*artboards.instances_mut().last().unwrap().source_node_id = encapsulating_node_id;
|
||||
|
||||
artboards
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::transform::{Footprint, Transform};
|
||||
use crate::uuid::{generate_uuid, NodeId};
|
||||
use crate::vector::style::{Fill, Stroke, ViewMode};
|
||||
use crate::vector::{PointId, VectorDataTable};
|
||||
use crate::{Artboard, ArtboardGroup, Color, GraphicElement, GraphicGroupTable, RasterFrame};
|
||||
use crate::{Artboard, ArtboardGroupTable, Color, GraphicElement, GraphicGroupTable, RasterFrame};
|
||||
|
||||
use bezier_rs::Subpath;
|
||||
use dyn_any::DynAny;
|
||||
@@ -790,38 +790,38 @@ impl GraphicElementRendered for Artboard {
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphicElementRendered for ArtboardGroup {
|
||||
impl GraphicElementRendered for ArtboardGroupTable {
|
||||
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
|
||||
for (artboard, _) in &self.artboards {
|
||||
artboard.render_svg(render, render_params);
|
||||
for artboard in self.instances() {
|
||||
artboard.instance.render_svg(render, render_params);
|
||||
}
|
||||
}
|
||||
|
||||
fn bounding_box(&self, transform: DAffine2) -> Option<[DVec2; 2]> {
|
||||
self.artboards.iter().filter_map(|(element, _)| element.bounding_box(transform)).reduce(Quad::combine_bounds)
|
||||
self.instances().filter_map(|instance| instance.instance.bounding_box(transform)).reduce(Quad::combine_bounds)
|
||||
}
|
||||
|
||||
fn collect_metadata(&self, metadata: &mut RenderMetadata, footprint: Footprint, _element_id: Option<NodeId>) {
|
||||
for (artboard, element_id) in &self.artboards {
|
||||
artboard.collect_metadata(metadata, footprint, *element_id);
|
||||
for instance in self.instances() {
|
||||
instance.instance.collect_metadata(metadata, footprint, *instance.source_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_upstream_click_targets(&self, click_targets: &mut Vec<ClickTarget>) {
|
||||
for (artboard, _) in &self.artboards {
|
||||
artboard.add_upstream_click_targets(click_targets);
|
||||
for instance in self.instances() {
|
||||
instance.instance.add_upstream_click_targets(click_targets);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "vello")]
|
||||
fn render_to_vello(&self, scene: &mut Scene, transform: DAffine2, context: &mut RenderContext) {
|
||||
for (artboard, _) in &self.artboards {
|
||||
artboard.render_to_vello(scene, transform, context)
|
||||
for instance in self.instances() {
|
||||
instance.instance.render_to_vello(scene, transform, context)
|
||||
}
|
||||
}
|
||||
|
||||
fn contains_artboard(&self) -> bool {
|
||||
!self.artboards.is_empty()
|
||||
self.instances().count() > 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@ use crate::application_io::{ImageTexture, TextureFrameTable};
|
||||
use crate::raster::image::{Image, ImageFrameTable};
|
||||
use crate::raster::Pixel;
|
||||
use crate::transform::{Transform, TransformMut};
|
||||
use crate::uuid::NodeId;
|
||||
use crate::vector::{InstanceId, VectorData, VectorDataTable};
|
||||
use crate::{AlphaBlending, GraphicElement, GraphicGroup, GraphicGroupTable, RasterFrame};
|
||||
|
||||
use dyn_any::StaticType;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
use std::hash::Hash;
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Instances<T>
|
||||
where
|
||||
T: Into<GraphicElement> + StaticType + 'static,
|
||||
{
|
||||
pub struct Instances<T> {
|
||||
id: Vec<InstanceId>,
|
||||
#[serde(alias = "instances")]
|
||||
instance: Vec<T>,
|
||||
@@ -21,15 +20,44 @@ where
|
||||
transform: Vec<DAffine2>,
|
||||
#[serde(default = "one_alpha_blending_default")]
|
||||
alpha_blending: Vec<AlphaBlending>,
|
||||
#[serde(default = "one_source_node_id_default")]
|
||||
source_node_id: Vec<Option<NodeId>>,
|
||||
}
|
||||
|
||||
impl<T: Into<GraphicElement> + StaticType + 'static> Instances<T> {
|
||||
impl<T> Instances<T> {
|
||||
pub fn new(instance: T) -> Self {
|
||||
Self {
|
||||
id: vec![InstanceId::generate()],
|
||||
instance: vec![instance],
|
||||
transform: vec![DAffine2::IDENTITY],
|
||||
alpha_blending: vec![AlphaBlending::default()],
|
||||
source_node_id: vec![None],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
id: Vec::new(),
|
||||
instance: Vec::new(),
|
||||
transform: Vec::new(),
|
||||
alpha_blending: Vec::new(),
|
||||
source_node_id: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, instance: T) -> InstanceMut<T> {
|
||||
self.id.push(InstanceId::generate());
|
||||
self.instance.push(instance);
|
||||
self.transform.push(DAffine2::IDENTITY);
|
||||
self.alpha_blending.push(AlphaBlending::default());
|
||||
self.source_node_id.push(None);
|
||||
|
||||
InstanceMut {
|
||||
id: self.id.last_mut().expect("Shouldn't be empty"),
|
||||
instance: self.instance.last_mut().expect("Shouldn't be empty"),
|
||||
transform: self.transform.last_mut().expect("Shouldn't be empty"),
|
||||
alpha_blending: self.alpha_blending.last_mut().expect("Shouldn't be empty"),
|
||||
source_node_id: self.source_node_id.last_mut().expect("Shouldn't be empty"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +67,7 @@ impl<T: Into<GraphicElement> + StaticType + 'static> Instances<T> {
|
||||
instance: self.instance.first().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", self.instance.len())),
|
||||
transform: self.transform.first().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", self.instance.len())),
|
||||
alpha_blending: self.alpha_blending.first().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", self.instance.len())),
|
||||
source_node_id: self.source_node_id.first().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", self.instance.len())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,47 +79,52 @@ impl<T: Into<GraphicElement> + StaticType + 'static> Instances<T> {
|
||||
instance: self.instance.first_mut().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", length)),
|
||||
transform: self.transform.first_mut().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", length)),
|
||||
alpha_blending: self.alpha_blending.first_mut().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", length)),
|
||||
source_node_id: self.source_node_id.first_mut().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED, FOUND {}", length)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instances(&self) -> impl Iterator<Item = Instance<T>> {
|
||||
assert!(self.instance.len() == 1, "ONE INSTANCE EXPECTED, FOUND {} (instances)", self.instance.len());
|
||||
// assert!(self.instance.len() == 1, "ONE INSTANCE EXPECTED, FOUND {} (instances)", self.instance.len());
|
||||
self.id
|
||||
.iter()
|
||||
.zip(self.instance.iter())
|
||||
.zip(self.transform.iter())
|
||||
.zip(self.alpha_blending.iter())
|
||||
.map(|(((id, instance), transform), alpha_blending)| Instance {
|
||||
.zip(self.source_node_id.iter())
|
||||
.map(|((((id, instance), transform), alpha_blending), source_node_id)| Instance {
|
||||
id,
|
||||
instance,
|
||||
transform,
|
||||
alpha_blending,
|
||||
source_node_id,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn instances_mut(&mut self) -> impl Iterator<Item = InstanceMut<T>> {
|
||||
assert!(self.instance.len() == 1, "ONE INSTANCE EXPECTED, FOUND {} (instances_mut)", self.instance.len());
|
||||
// assert!(self.instance.len() == 1, "ONE INSTANCE EXPECTED, FOUND {} (instances_mut)", self.instance.len());
|
||||
self.id
|
||||
.iter_mut()
|
||||
.zip(self.instance.iter_mut())
|
||||
.zip(self.transform.iter_mut())
|
||||
.zip(self.alpha_blending.iter_mut())
|
||||
.map(|(((id, instance), transform), alpha_blending)| InstanceMut {
|
||||
.zip(self.source_node_id.iter_mut())
|
||||
.map(|((((id, instance), transform), alpha_blending), source_node_id)| InstanceMut {
|
||||
id,
|
||||
instance,
|
||||
transform,
|
||||
alpha_blending,
|
||||
source_node_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<GraphicElement> + Default + Hash + StaticType + 'static> Default for Instances<T> {
|
||||
impl<T: Default + Hash> Default for Instances<T> {
|
||||
fn default() -> Self {
|
||||
Self::new(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<GraphicElement> + Hash + StaticType + 'static> core::hash::Hash for Instances<T> {
|
||||
impl<T: Hash> core::hash::Hash for Instances<T> {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state);
|
||||
for instance in &self.instance {
|
||||
@@ -99,13 +133,14 @@ impl<T: Into<GraphicElement> + Hash + StaticType + 'static> core::hash::Hash for
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<GraphicElement> + PartialEq + StaticType + 'static> PartialEq for Instances<T> {
|
||||
impl<T: PartialEq> PartialEq for Instances<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id && self.instance.len() == other.instance.len() && { self.instance.iter().zip(other.instance.iter()).all(|(a, b)| a == b) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Into<GraphicElement> + StaticType + 'static> dyn_any::StaticType for Instances<T> {
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<T: StaticType + 'static> StaticType for Instances<T> {
|
||||
type Static = Instances<T>;
|
||||
}
|
||||
|
||||
@@ -115,6 +150,9 @@ fn one_daffine2_default() -> Vec<DAffine2> {
|
||||
fn one_alpha_blending_default() -> Vec<AlphaBlending> {
|
||||
vec![AlphaBlending::default()]
|
||||
}
|
||||
fn one_source_node_id_default() -> Vec<Option<NodeId>> {
|
||||
vec![None]
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Instance<'a, T> {
|
||||
@@ -122,6 +160,7 @@ pub struct Instance<'a, T> {
|
||||
pub instance: &'a T,
|
||||
pub transform: &'a DAffine2,
|
||||
pub alpha_blending: &'a AlphaBlending,
|
||||
pub source_node_id: &'a Option<NodeId>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct InstanceMut<'a, T> {
|
||||
@@ -129,6 +168,7 @@ pub struct InstanceMut<'a, T> {
|
||||
pub instance: &'a mut T,
|
||||
pub transform: &'a mut DAffine2,
|
||||
pub alpha_blending: &'a mut AlphaBlending,
|
||||
pub source_node_id: &'a mut Option<NodeId>,
|
||||
}
|
||||
|
||||
// GRAPHIC ELEMENT
|
||||
@@ -235,8 +275,6 @@ impl<P: Pixel> TransformMut for InstanceMut<'_, Image<P>> {
|
||||
// IMAGE FRAME TABLE
|
||||
impl<P: Pixel> Transform for ImageFrameTable<P>
|
||||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn transform(&self) -> DAffine2 {
|
||||
@@ -245,8 +283,6 @@ where
|
||||
}
|
||||
impl<P: Pixel> TransformMut for ImageFrameTable<P>
|
||||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
|
||||
@@ -51,6 +51,8 @@ pub mod registry;
|
||||
|
||||
pub use context::*;
|
||||
use core::any::TypeId;
|
||||
use core::pin::Pin;
|
||||
pub use dyn_any::{StaticTypeSized, WasmNotSend, WasmNotSync};
|
||||
pub use memo::MemoHash;
|
||||
pub use raster::Color;
|
||||
pub use types::Cow;
|
||||
@@ -148,10 +150,6 @@ impl<'i, I: 'i, O: 'i, N: Node<'i, I, Output = O> + ?Sized> Node<'i, I> for allo
|
||||
}
|
||||
}
|
||||
|
||||
use dyn_any::StaticTypeSized;
|
||||
|
||||
use core::pin::Pin;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'i, I, O: 'i> Node<'i, I> for Pin<Box<dyn Node<'i, I, Output = O> + 'i>> {
|
||||
type Output = O;
|
||||
@@ -172,5 +170,3 @@ pub use crate::application_io::{SurfaceFrame, SurfaceId};
|
||||
pub type WasmSurfaceHandle = application_io::SurfaceHandle<web_sys::HtmlCanvasElement>;
|
||||
#[cfg(feature = "wasm")]
|
||||
pub type WasmSurfaceHandleFrame = application_io::SurfaceHandleFrame<web_sys::HtmlCanvasElement>;
|
||||
|
||||
pub use dyn_any::{WasmNotSend, WasmNotSync};
|
||||
|
||||
@@ -734,8 +734,6 @@ impl Adjust<Color> for GradientStops {
|
||||
}
|
||||
impl<P: Pixel> Adjust<P> for ImageFrameTable<P>
|
||||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn adjust(&mut self, map_fn: impl Fn(&P) -> P) {
|
||||
@@ -1382,8 +1380,6 @@ impl MultiplyAlpha for GraphicGroupTable {
|
||||
}
|
||||
impl<P: Pixel> MultiplyAlpha for ImageFrameTable<P>
|
||||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn multiply_alpha(&mut self, factor: f64) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use dyn_any::DynAny;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
|
||||
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
|
||||
|
||||
@@ -4,8 +4,9 @@ use crate::vector::brush_stroke::BrushStroke;
|
||||
use crate::vector::brush_stroke::BrushStyle;
|
||||
use crate::Color;
|
||||
|
||||
use core::hash::Hash;
|
||||
use dyn_any::DynAny;
|
||||
|
||||
use core::hash::Hash;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
@@ -57,7 +58,7 @@ impl BrushCacheImpl {
|
||||
background = core::mem::take(&mut self.blended_image);
|
||||
|
||||
// Check if the first non-blended stroke is an extension of the last one.
|
||||
let mut first_stroke_texture = ImageFrameTable::empty();
|
||||
let mut first_stroke_texture = ImageFrameTable::one_empty_image();
|
||||
let mut first_stroke_point_skip = 0;
|
||||
let strokes = input[num_blended_strokes..].to_vec();
|
||||
if !strokes.is_empty() && self.prev_input.len() > num_blended_strokes {
|
||||
|
||||
@@ -176,6 +176,7 @@ pub struct ValueMapperNode<C> {
|
||||
lut: Vec<C>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<C: StaticTypeSized> StaticType for ValueMapperNode<C> {
|
||||
type Static = ValueMapperNode<C::Static>;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use super::discrete_srgb::float_to_srgb_u8;
|
||||
use super::Color;
|
||||
use crate::{instances::Instances, transform::TransformMut};
|
||||
use crate::{AlphaBlending, GraphicElement};
|
||||
use crate::instances::Instances;
|
||||
use crate::transform::TransformMut;
|
||||
use crate::AlphaBlending;
|
||||
use crate::GraphicElement;
|
||||
use alloc::vec::Vec;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use dyn_any::StaticType;
|
||||
@@ -68,6 +70,7 @@ impl<P: Pixel + Debug> Debug for Image<P> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<P> StaticType for Image<P>
|
||||
where
|
||||
P: dyn_any::StaticTypeSized + Pixel,
|
||||
@@ -235,6 +238,8 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl<P> StaticType for ImageFrame<P>
|
||||
where
|
||||
P: dyn_any::StaticTypeSized + Pixel,
|
||||
@@ -279,7 +284,7 @@ pub type ImageFrameTable<P> = Instances<Image<P>>;
|
||||
|
||||
/// Construct a 0x0 image frame table. This is useful because ImageFrameTable::default() will return a 1x1 image frame table.
|
||||
impl ImageFrameTable<Color> {
|
||||
pub fn empty() -> Self {
|
||||
pub fn one_empty_image() -> Self {
|
||||
let mut result = Self::new(Image::default());
|
||||
*result.transform_mut() = DAffine2::ZERO;
|
||||
result
|
||||
@@ -302,8 +307,7 @@ impl<P: Debug + Copy + Pixel> Sample for Image<P> {
|
||||
|
||||
impl<P> Sample for ImageFrameTable<P>
|
||||
where
|
||||
P: Debug + Copy + Pixel + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
P: Debug + Copy + Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
type Pixel = P;
|
||||
@@ -323,8 +327,7 @@ where
|
||||
|
||||
impl<P> Bitmap for ImageFrameTable<P>
|
||||
where
|
||||
P: Copy + Pixel + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
P: Copy + Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
type Pixel = P;
|
||||
@@ -350,8 +353,7 @@ where
|
||||
|
||||
impl<P> BitmapMut for ImageFrameTable<P>
|
||||
where
|
||||
P: Copy + Pixel + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
P: Copy + Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn get_pixel_mut(&mut self, x: u32, y: u32) -> Option<&mut Self::Pixel> {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::transform::Footprint;
|
||||
use crate::{NodeIO, NodeIOTypes, Type};
|
||||
use crate::{Node, NodeIO, NodeIOTypes, Type, WasmNotSend};
|
||||
|
||||
use dyn_any::DynAny;
|
||||
use dyn_any::{DynAny, StaticType};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::pin::Pin;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
@@ -153,11 +154,6 @@ impl NodeContainer {
|
||||
}
|
||||
}
|
||||
|
||||
use crate::Node;
|
||||
use crate::WasmNotSend;
|
||||
use dyn_any::StaticType;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Boxes the input and downcasts the output.
|
||||
/// Wraps around a node taking Box<dyn DynAny> and returning Box<dyn DynAny>
|
||||
#[derive(Clone)]
|
||||
@@ -166,7 +162,11 @@ pub struct DowncastBothNode<I, O> {
|
||||
_i: PhantomData<I>,
|
||||
_o: PhantomData<O>,
|
||||
}
|
||||
impl<'input, O: 'input + StaticType + WasmNotSend, I: 'input + StaticType + WasmNotSend> Node<'input, I> for DowncastBothNode<I, O> {
|
||||
impl<'input, O, I> Node<'input, I> for DowncastBothNode<I, O>
|
||||
where
|
||||
O: 'input + StaticType + WasmNotSend,
|
||||
I: 'input + StaticType + WasmNotSend,
|
||||
{
|
||||
type Output = DynFuture<'input, O>;
|
||||
#[inline]
|
||||
fn eval(&'input self, input: I) -> Self::Output {
|
||||
@@ -234,9 +234,11 @@ pub struct DynAnyNode<I, O, Node> {
|
||||
_o: PhantomData<O>,
|
||||
}
|
||||
|
||||
impl<'input, _I: 'input + StaticType + WasmNotSend, _O: 'input + StaticType + WasmNotSend, N: 'input> Node<'input, Any<'input>> for DynAnyNode<_I, _O, N>
|
||||
impl<'input, _I, _O, N> Node<'input, Any<'input>> for DynAnyNode<_I, _O, N>
|
||||
where
|
||||
N: Node<'input, _I, Output = DynFuture<'input, _O>>,
|
||||
_I: 'input + dyn_any::StaticType + WasmNotSend,
|
||||
_O: 'input + dyn_any::StaticType + WasmNotSend,
|
||||
N: 'input + Node<'input, _I, Output = DynFuture<'input, _O>>,
|
||||
{
|
||||
type Output = FutureAny<'input>;
|
||||
#[inline]
|
||||
@@ -275,9 +277,11 @@ where
|
||||
self.node.serialize()
|
||||
}
|
||||
}
|
||||
impl<'input, _I: 'input + StaticType, _O: 'input + StaticType, N: 'input> DynAnyNode<_I, _O, N>
|
||||
impl<'input, _I, _O, N> DynAnyNode<_I, _O, N>
|
||||
where
|
||||
N: Node<'input, _I, Output = DynFuture<'input, _O>>,
|
||||
_I: 'input + dyn_any::StaticType,
|
||||
_O: 'input + dyn_any::StaticType,
|
||||
N: 'input + Node<'input, _I, Output = DynFuture<'input, _O>>,
|
||||
{
|
||||
pub const fn new(node: N) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::application_io::TextureFrameTable;
|
||||
use crate::raster::bbox::AxisAlignedBbox;
|
||||
use crate::raster::image::ImageFrameTable;
|
||||
use crate::vector::VectorDataTable;
|
||||
use crate::{Artboard, ArtboardGroup, CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicGroupTable, OwnedContextImpl};
|
||||
use crate::{Artboard, ArtboardGroupTable, CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicGroupTable, OwnedContextImpl};
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
|
||||
@@ -132,7 +132,7 @@ impl From<()> for Footprint {
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Debug"))]
|
||||
fn cull<T>(_: impl Ctx, #[implementations(VectorDataTable, GraphicGroupTable, Artboard, ImageFrameTable<Color>, ArtboardGroup)] data: T) -> T {
|
||||
fn cull<T>(_: impl Ctx, #[implementations(VectorDataTable, GraphicGroupTable, Artboard, ImageFrameTable<Color>, ArtboardGroupTable)] data: T) -> T {
|
||||
data
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ use core::any::TypeId;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub use alloc::borrow::Cow;
|
||||
use dyn_any::StaticType;
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::borrow::Cow;
|
||||
|
||||
@@ -220,7 +219,8 @@ impl Default for Type {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl StaticType for Type {
|
||||
#[cfg(feature = "dyn-any")]
|
||||
unsafe impl dyn_any::StaticType for Type {
|
||||
type Static = Self;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ impl Type {
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn new<T: StaticType + Sized>() -> Self {
|
||||
pub fn new<T: dyn_any::StaticType + Sized>() -> Self {
|
||||
Self::Concrete(TypeDescriptor {
|
||||
id: Some(TypeId::of::<T::Static>()),
|
||||
name: Cow::Borrowed(core::any::type_name::<T::Static>()),
|
||||
@@ -278,6 +278,7 @@ impl Type {
|
||||
align: core::mem::align_of::<T>(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<usize> {
|
||||
match self {
|
||||
Self::Generic(_) => None,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use dyn_any::DynAny;
|
||||
pub use uuid_generation::*;
|
||||
|
||||
use dyn_any::DynAny;
|
||||
|
||||
#[derive(Clone, Copy, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct Uuid(
|
||||
#[serde(with = "u64_string")]
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::raster::BlendMode;
|
||||
use crate::Color;
|
||||
|
||||
use dyn_any::DynAny;
|
||||
|
||||
use glam::DVec2;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::renderer::format_transform_matrix;
|
||||
use crate::Color;
|
||||
|
||||
use dyn_any::DynAny;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
use std::fmt::{self, Display, Write};
|
||||
|
||||
|
||||
@@ -670,6 +670,7 @@ async fn subpath_segment_lengths(_: impl Ctx, vector_data: VectorDataTable) -> V
|
||||
|
||||
#[node_macro::node(name("Spline"), category("Vector"), path(graphene_core::vector))]
|
||||
async fn spline(_: impl Ctx, mut vector_data: VectorDataTable) -> VectorDataTable {
|
||||
let original_transform = vector_data.transform();
|
||||
let vector_data = vector_data.one_instance_mut().instance;
|
||||
|
||||
// Exit early if there are no points to generate splines from.
|
||||
@@ -707,7 +708,9 @@ async fn spline(_: impl Ctx, mut vector_data: VectorDataTable) -> VectorDataTabl
|
||||
}
|
||||
vector_data.segment_domain = segment_domain;
|
||||
|
||||
VectorDataTable::new(vector_data.clone())
|
||||
let mut result = VectorDataTable::new(vector_data.clone());
|
||||
*result.transform_mut() = original_transform;
|
||||
result
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
|
||||
|
||||
Reference in New Issue
Block a user