mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-23 05:08:12 +08:00
* Allow using any graphics type for fill * Adapt gradient/fill property panels and tools to handle List<T> * Make the initial gradient transform covers the target's bounding box * Introduce AnyGraphicListDyn to avoid combinatorial explosion * Allow using any graphics type for stroke paint * Add FIll node migration * Add `for_each_vector_list_mut` instead of `set_paint_attribute` * Adapt paint flow to read and write attributes instead of legacy Fill/Stroke.color * Fix responsibilities of paint related node input setters * Fix Morph by storing List<Graphic> for attributes rather than the concrete types Store fill/stroke paints as List<Graphic> so Color/Gradient transitions do not hit set_attribute_value_dyn's type-mismatch fallback to default paint. * Preserve paint attributes in vector editing ops * Enhance the clarity between direct and chained fill gradients * Update demo arts * Consolidate Fill node gradient appearance inputs * Fix after the cubic review * Revert "Consolidate Fill node gradient appearance inputs" This reverts commit 9622feb20196e2c4da99e98ca95dcc2e34c2c98e. * Replace AnyGraphicListDyn with generic paint connectors on the Fill and Stroke nodes * Canonicalize paint attribute storage to List<Graphic> with a single write helper * Fix Solidify Stroke missing fills stored in the legacy style * Fix Solidify Stroke producing invisible strokes for legacy-only stroke colors * Fix the initial gradient transform ignoring the bounding box's vertical extent * Step paint at the morph midpoint instead of dropping it for unmixable pairings * Remove migration-stage comments * Clarify the initial gradient transform helper's doc and name * Correct the bake_paint_transforms doc and prune dead tolerance arms * Delete the unused Gradient::lerp * Fix a comment typo * Thread network paths through the legacy gradient bake so nested fills migrate * Restore the legacy fill fallback in Expand Fill and Stroke * Read gradient stops from the node's own input in the Fill properties panel * Use the transform input constant instead of a hardcoded index * Remove the unreachable wired color fallback in the Fill properties solid branch * Narrow the fill overlay redraw check to actual fill inputs * Coalesce the fill setter's graph runs into a single dispatch * Position the Gradient Value node inserted for gradient stops * Bake backup gradient placement during migration * Persist pending gradient bakes so unfinished migrations retry on reopen * Migrate the backup gradient's type and spread method * Harden the gradient-migration pass against document switches and stale bakes * Keep the Fill properties UI for layerless and nested Fill nodes * Leave a wired gradient transform input connected instead of overwriting it * Refuse to start a gradient chain ahead of existing layer content * Decode a Fill node's gradient through one shared reader * Nudge a degenerate bounding box so the Fill gradient transform stays invertible * Broadcast Fill and Stroke paint with a single attribute-column pass * Fix Morph stepping the target's stroke in near the source instead of the target * Tidy conventions: clippy get_first, comment periods, sentence-case test messages * Reattach the gradient orientation doc to its function * Re-save demo artwork --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
61 lines
2.5 KiB
Rust
61 lines
2.5 KiB
Rust
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::GradientStops;
|
|
|
|
/// Constructs a single-element `Artboard[]` with the given content and metadata stored as row attributes.
|
|
#[node_macro::node(category(""))]
|
|
pub async fn create_artboard<T: IntoGraphicList>(
|
|
ctx: impl ExtractAll + CloneVarArgs + Ctx,
|
|
/// Graphics to include within the artboard.
|
|
#[implementations(
|
|
Context -> List<Graphic>,
|
|
Context -> List<Vector>,
|
|
Context -> List<String>,
|
|
Context -> List<Raster<CPU>>,
|
|
Context -> List<Raster<GPU>>,
|
|
Context -> List<Color>,
|
|
Context -> List<GradientStops>,
|
|
Context -> DAffine2,
|
|
)]
|
|
content: impl Node<Context<'static>, Output = T>,
|
|
/// Coordinate of the top-left corner of the artboard within the document.
|
|
location: DVec2,
|
|
/// Width and height of the artboard within the document.
|
|
dimensions: DVec2,
|
|
/// Color of the artboard background.
|
|
background: List<Color>,
|
|
/// Whether to cut off the contained content that extends outside the artboard, or keep it visible.
|
|
#[default(true)]
|
|
clip: bool,
|
|
) -> List<Artboard> {
|
|
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.element(0).copied().unwrap_or(Color::WHITE);
|
|
|
|
// Name is not stored here, it's resolved live from the parent layer's display name
|
|
List::new_from_item(
|
|
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),
|
|
)
|
|
}
|