use core_types::list::{Item, List}; use core_types::transform::TransformMut; use core_types::{ATTR_BACKGROUND, ATTR_CLIP, ATTR_DIMENSIONS, ATTR_LOCATION, CloneVarArgs, Color, Context, Ctx, ExtractAll, OwnedContextImpl}; use glam::{DAffine2, DVec2}; use graphic_types::graphic::{Graphic, IntoGraphicList}; use graphic_types::{Artboard, Vector}; use raster_types::{CPU, GPU, Raster}; use vector_types::Gradient; /// Constructs a single-element `Artboard[]` with the given content and metadata stored as row attributes. #[node_macro::node(category(""))] pub async fn create_artboard( ctx: impl ExtractAll + CloneVarArgs + Ctx, /// Graphics to include within the artboard. #[implementations( Context -> List, Context -> List, Context -> List, Context -> List>, Context -> List>, Context -> List, Context -> List, Context -> Item, // TODO: Remove this )] content: impl Node, Output = T>, /// Coordinate of the top-left corner of the artboard within the document. location: Item, /// Width and height of the artboard within the document. dimensions: Item, /// Color of the artboard background. background: Item, /// Whether to cut off the contained content that extends outside the artboard, or keep it visible. #[default(true)] clip: Item, ) -> Item { let (location, dimensions, clip) = (location.into_element(), dimensions.into_element(), clip.into_element()); let footprint = ctx.try_footprint().copied(); let mut new_ctx = OwnedContextImpl::from(ctx); if let Some(mut footprint) = footprint { footprint.translate(location); new_ctx = new_ctx.with_footprint(footprint); } let content = content.eval(new_ctx.into_context()).await.into_graphic_list(); // 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.into_element(); // Name is not stored here, it's resolved live from the parent layer's display name Item::new_from_element(Artboard::new(content)) .with_attribute(ATTR_LOCATION, normalized_location) .with_attribute(ATTR_DIMENSIONS, normalized_dimensions) .with_attribute(ATTR_BACKGROUND, background) .with_attribute(ATTR_CLIP, clip) }