mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-23 00:58:11 +08:00
Instance tables refactor part 6: unwrap VectorData and ImageFrame from single-row to multi-row tables (#2684)
* Start refactoring the boolean operations code * Switch to iterators in the boolean operations code * Make boolean operations work on rows of a table, not Vecs of single-row tables * Remove more .transform() * Simplify brush code * Attempt to remove .transform() by using Instance<Image<Color>> in brush code, but a regression is introduced * Improve blend_image_closure * Simplify * Remove leading underscore from type arguments * Remove .transform() from ImageFrameTable<P> and fix Mask node behavior on stencils not fully overlapping its target image * Remove more .one_instance_ref() * Fully remove .one_instance_ref() and improve the 'Combine Channels' node robustness * Fully remove .once_instance_mut() * Fix tests * Remove .one_empty_image() * Make Instances<T>::default() return an empty table for images, but still not yet vector --------- Co-authored-by: hypercube <0hypercube@gmail.com>
This commit is contained in:
co-authored by
hypercube
parent
76ecdc8f1b
commit
cb4289169d
@@ -1,10 +1,5 @@
|
||||
use crate::application_io::TextureFrameTable;
|
||||
use crate::raster::Pixel;
|
||||
use crate::raster::image::{Image, ImageFrameTable};
|
||||
use crate::transform::{Transform, TransformMut};
|
||||
use crate::AlphaBlending;
|
||||
use crate::uuid::NodeId;
|
||||
use crate::vector::VectorDataTable;
|
||||
use crate::{AlphaBlending, GraphicElement, RasterFrame};
|
||||
use dyn_any::StaticType;
|
||||
use glam::DAffine2;
|
||||
use std::hash::Hash;
|
||||
@@ -47,26 +42,6 @@ impl<T> Instances<T> {
|
||||
self.source_node_id.push(instance.source_node_id);
|
||||
}
|
||||
|
||||
pub fn one_instance_ref(&self) -> InstanceRef<T> {
|
||||
InstanceRef {
|
||||
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())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn one_instance_mut(&mut self) -> InstanceMut<T> {
|
||||
let length = self.instance.len();
|
||||
|
||||
InstanceMut {
|
||||
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 instance_iter(self) -> impl DoubleEndedIterator<Item = Instance<T>> {
|
||||
self.instance
|
||||
.into_iter()
|
||||
@@ -81,7 +56,7 @@ impl<T> Instances<T> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn instance_ref_iter(&self) -> impl DoubleEndedIterator<Item = InstanceRef<T>> {
|
||||
pub fn instance_ref_iter(&self) -> impl DoubleEndedIterator<Item = InstanceRef<T>> + Clone {
|
||||
self.instance
|
||||
.iter()
|
||||
.zip(self.transform.iter())
|
||||
@@ -146,11 +121,8 @@ impl<T> Instances<T> {
|
||||
|
||||
impl<T: Default + Hash + 'static> Default for Instances<T> {
|
||||
fn default() -> Self {
|
||||
// TODO: Remove once all types have been converted to tables
|
||||
let converted_to_tables = [TypeId::of::<crate::Artboard>(), TypeId::of::<crate::GraphicElement>()];
|
||||
|
||||
use core::any::TypeId;
|
||||
if converted_to_tables.contains(&TypeId::of::<T>()) {
|
||||
if TypeId::of::<T>() != TypeId::of::<crate::vector::VectorData>() {
|
||||
// TODO: Remove the 'static trait bound when this special casing is removed by making all types return empty
|
||||
Self::empty()
|
||||
} else {
|
||||
@@ -188,7 +160,7 @@ fn one_source_node_id_default() -> Vec<Option<NodeId>> {
|
||||
vec![None]
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct InstanceRef<'a, T> {
|
||||
pub instance: &'a T,
|
||||
pub transform: &'a DAffine2,
|
||||
@@ -196,6 +168,20 @@ pub struct InstanceRef<'a, T> {
|
||||
pub source_node_id: &'a Option<NodeId>,
|
||||
}
|
||||
|
||||
impl<T> InstanceRef<'_, T> {
|
||||
pub fn to_instance_cloned(self) -> Instance<T>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Instance {
|
||||
instance: self.instance.clone(),
|
||||
transform: *self.transform,
|
||||
alpha_blending: *self.alpha_blending,
|
||||
source_node_id: *self.source_node_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstanceMut<'a, T> {
|
||||
pub instance: &'a mut T,
|
||||
@@ -204,7 +190,7 @@ pub struct InstanceMut<'a, T> {
|
||||
pub source_node_id: &'a mut Option<NodeId>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Instance<T> {
|
||||
pub instance: T,
|
||||
pub transform: DAffine2,
|
||||
@@ -224,64 +210,31 @@ impl<T> Instance<T> {
|
||||
source_node_id: self.source_node_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VECTOR DATA TABLE
|
||||
impl Transform for VectorDataTable {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.one_instance_ref().transform
|
||||
pub fn to_instance_ref(&self) -> InstanceRef<T> {
|
||||
InstanceRef {
|
||||
instance: &self.instance,
|
||||
transform: &self.transform,
|
||||
alpha_blending: &self.alpha_blending,
|
||||
source_node_id: &self.source_node_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TransformMut for VectorDataTable {
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
self.one_instance_mut().transform
|
||||
}
|
||||
}
|
||||
|
||||
// TEXTURE FRAME TABLE
|
||||
impl Transform for TextureFrameTable {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.one_instance_ref().transform
|
||||
pub fn to_instance_mut(&mut self) -> InstanceMut<T> {
|
||||
InstanceMut {
|
||||
instance: &mut self.instance,
|
||||
transform: &mut self.transform,
|
||||
alpha_blending: &mut self.alpha_blending,
|
||||
source_node_id: &mut self.source_node_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TransformMut for TextureFrameTable {
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
self.one_instance_mut().transform
|
||||
}
|
||||
}
|
||||
|
||||
// IMAGE FRAME TABLE
|
||||
impl<P: Pixel> Transform for ImageFrameTable<P>
|
||||
where
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.one_instance_ref().transform
|
||||
}
|
||||
}
|
||||
impl<P: Pixel> TransformMut for ImageFrameTable<P>
|
||||
where
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
self.one_instance_mut().transform
|
||||
}
|
||||
}
|
||||
|
||||
// RASTER FRAME
|
||||
impl Transform for RasterFrame {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
match self {
|
||||
RasterFrame::ImageFrame(image_frame) => image_frame.transform(),
|
||||
RasterFrame::TextureFrame(texture_frame) => texture_frame.transform(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TransformMut for RasterFrame {
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
match self {
|
||||
RasterFrame::ImageFrame(image_frame) => image_frame.transform_mut(),
|
||||
RasterFrame::TextureFrame(texture_frame) => texture_frame.transform_mut(),
|
||||
pub fn to_table(self) -> Instances<T> {
|
||||
Instances {
|
||||
instance: vec![self.instance],
|
||||
transform: vec![self.transform],
|
||||
alpha_blending: vec![self.alpha_blending],
|
||||
source_node_id: vec![self.source_node_id],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user