Instance tables refactor part 5: unwrap GraphicGroup as multi-row Instance<GraphicElement> tables and move up transforms (#2363)

* Just group

* Partly working but without transforms

* Remove Transform/TransformMut from GraphicElement and GraphicGroupTable

* Fix layers and flattening

* Fix transform group handling on the remaining nodes

* Change collect metadata

* Add transform on vector data. TODO: Remove duplicate transform

* Small code tidying-up

* Add concatenate node?

* Remove ignore_modifications which is always false

* Improve transforms

* Mostly fix the nested transform cage angle (except leaf layers and skew)

* WIP attempt to integrate skew

* Fix nesting bounding box

* Avoid setting the transform

* Fix stroke transforms

* Renderer cleanup

* Fix tests for repeated elements not given unique point IDs

* Suppress cargo-deny warning

* Fix upgrade code for graphic group data

* Work around rendering issue in Isometric Fountain

---------

Co-authored-by: Adam <adamgerhant@gmail.com>
Co-authored-by: hypercube <0hypercube@gmail.com>
This commit is contained in:
Keavon Chambers
2025-03-12 01:38:36 -07:00
committed by GitHub
parent d2fc919ba6
commit a696aae044
28 changed files with 856 additions and 930 deletions

View File

@@ -1,4 +1,5 @@
use crate::application_io::TextureFrameTable;
use crate::instances::Instances;
use crate::raster::bbox::AxisAlignedBbox;
use crate::raster::image::ImageFrameTable;
use crate::vector::VectorDataTable;
@@ -90,8 +91,6 @@ pub struct Footprint {
pub resolution: glam::UVec2,
/// Quality of the render, this may be used by caching nodes to decide if the cached render is sufficient
pub quality: RenderQuality,
/// When the transform is set downstream, all upstream modifications have to be ignored
pub ignore_modifications: bool,
}
impl Default for Footprint {
@@ -106,7 +105,6 @@ impl Footprint {
transform: DAffine2::IDENTITY,
resolution: glam::UVec2::new(1920, 1080),
quality: RenderQuality::Full,
ignore_modifications: false,
}
}
pub fn viewport_bounds_in_local_space(&self) -> AxisAlignedBbox {
@@ -156,7 +154,7 @@ impl ApplyTransform for () {
}
#[node_macro::node(category(""))]
async fn transform<T: 'n + TransformMut + 'static>(
async fn transform<T: 'n + 'static>(
ctx: impl Ctx + CloneVarArgs + ExtractAll,
#[implementations(
Context -> VectorDataTable,
@@ -164,39 +162,40 @@ async fn transform<T: 'n + TransformMut + 'static>(
Context -> ImageFrameTable<Color>,
Context -> TextureFrameTable,
)]
transform_target: impl Node<Context<'static>, Output = T>,
transform_target: impl Node<Context<'static>, Output = Instances<T>>,
translate: DVec2,
rotate: f64,
scale: DVec2,
shear: DVec2,
_pivot: DVec2,
) -> T {
let modification = DAffine2::from_scale_angle_translation(scale, rotate, translate) * DAffine2::from_cols_array(&[1., shear.y, shear.x, 1., 0., 0.]);
) -> Instances<T> {
let matrix = DAffine2::from_scale_angle_translation(scale, rotate, translate) * DAffine2::from_cols_array(&[1., shear.y, shear.x, 1., 0., 0.]);
let footprint = ctx.try_footprint().copied();
let mut ctx = OwnedContextImpl::from(ctx);
if let Some(mut footprint) = footprint {
if !footprint.ignore_modifications {
footprint.apply_transform(&modification);
}
footprint.apply_transform(&matrix);
ctx = ctx.with_footprint(footprint);
}
let mut transform_target = transform_target.eval(ctx.into_context()).await;
let data_transform = transform_target.transform_mut();
*data_transform = modification * (*data_transform);
for data_transform in transform_target.instances_mut() {
*data_transform.transform = matrix * *data_transform.transform;
}
transform_target
}
#[node_macro::node(category(""))]
fn replace_transform<Data: TransformMut, TransformInput: Transform>(
fn replace_transform<Data, TransformInput: Transform>(
_: impl Ctx,
#[implementations(VectorDataTable, ImageFrameTable<Color>, GraphicGroupTable)] mut data: Data,
#[implementations(VectorDataTable, ImageFrameTable<Color>, GraphicGroupTable)] mut data: Instances<Data>,
#[implementations(DAffine2)] transform: TransformInput,
) -> Data {
let data_transform = data.transform_mut();
*data_transform = transform.transform();
) -> Instances<Data> {
for data_transform in data.instances_mut() {
*data_transform.transform = transform.transform();
}
data
}