Replace the Artboard struct with a Table<Table<Graphic>> shape (#4077)

* Replace the Artboard struct with a Table<Table<Graphic>> shape

* Remove the never-functional, seemingly unneeded migrate_type_descriptor_names due to typo

* Allow negative artboard sizes
This commit is contained in:
Keavon Chambers
2026-04-28 22:58:33 -07:00
committed by GitHub
parent 0847d7b0ab
commit ba63c26c62
27 changed files with 350 additions and 442 deletions
+29 -25
View File
@@ -1,13 +1,19 @@
use core_types::{CloneVarArgs, Color, Context, Ctx, ExtractAll, OwnedContextImpl, table::Table, transform::TransformMut};
use glam::{DAffine2, DVec2, IVec2};
use core_types::{
ATTR_BACKGROUND, ATTR_CLIP, ATTR_DIMENSIONS, ATTR_LOCATION, CloneVarArgs, Color, Context, Ctx, ExtractAll, OwnedContextImpl,
table::{Table, TableRow},
transform::TransformMut,
};
use glam::{DAffine2, DVec2};
use graphic_types::{
Artboard, Vector,
Vector,
graphic::{Graphic, IntoGraphicTable},
};
use raster_types::{CPU, GPU, Raster};
use vector_types::GradientStops;
/// Constructs a new single-item `Table<Artboard>` with the chosen properties.
/// Constructs a new single-item `Table<Table<Graphic>>` (an artboard table) where the row's element is
/// the artboard's content and the metadata (label, location, dimensions, background, clip) is stored as
/// per-row attributes.
#[node_macro::node(category(""))]
pub async fn create_artboard<T: IntoGraphicTable + 'n>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,
@@ -22,42 +28,40 @@ pub async fn create_artboard<T: IntoGraphicTable + 'n>(
Context -> DAffine2,
)]
content: impl Node<Context<'static>, Output = T>,
/// Name of the artboard, shown in parts of the editor.
label: String,
/// Coordinate of the top-left corner of the artboard within the document.
location: DVec2,
/// Width and height of the artboard within the document. Only integers are valid.
/// Width and height of the artboard within the document.
dimensions: DVec2,
/// Color of the artboard background. Only positive integers are valid.
/// Color of the artboard background.
background: Table<Color>,
/// Whether to cut off the contained content that extends outside the artboard, or keep it visible.
#[default(true)]
clip: bool,
) -> Table<Artboard> {
let location = location.as_ivec2();
) -> Table<Table<Graphic>> {
let footprint = ctx.try_footprint().copied();
let mut new_ctx = OwnedContextImpl::from(ctx);
if let Some(mut footprint) = footprint {
footprint.translate(location.as_dvec2());
footprint.translate(location);
new_ctx = new_ctx.with_footprint(footprint);
}
let content = content.eval(new_ctx.into_context()).await.into_graphic_table();
let dimensions = dimensions.as_ivec2().max(IVec2::ONE);
let location = location.min(location + dimensions);
let dimensions = dimensions.abs();
// Normalize so `location` is the top-left corner and `dimensions` are positive (allowing negative input
// dimensions to represent dragging from the opposite corner). Compute the corner using the raw signed
// dimensions before clamping, otherwise negative inputs collapse to the original corner instead of inverting.
let normalized_location = location.min(location + dimensions);
let normalized_dimensions = dimensions.abs().max(DVec2::ONE);
let background = background.element(0).copied().unwrap_or(Color::WHITE);
Table::new_from_element(Artboard {
content,
label,
location,
dimensions,
background,
clip,
})
// The artboard's user-visible name is its parent layer's display name; not stored as an attribute here so
// it can't go stale. The data panel resolves it live from the row's `editor:layer_path` NodeId via the network
// interface, so renaming the layer reflects everywhere on the next refresh.
Table::new_from_row(
TableRow::new_from_element(content)
.with_attribute(ATTR_LOCATION, normalized_location)
.with_attribute(ATTR_DIMENSIONS, normalized_dimensions)
.with_attribute(ATTR_BACKGROUND, background)
.with_attribute(ATTR_CLIP, clip),
)
}