Restructure node crates (#3384)

* Restructure node-graph folder

* Fix wasm compilation

* Move node definitions out of *-types crates

* Cleanup

* Fix warnings

* Fix warnings

* Start adding migrations

* Add migrations and move memo nodes to gcore

* Move nodes/gsvg-render -> rendering

* Replace some hard coded identifiers and fix automatic conversion

* Fix Vec2Value node migration

* Fix formatting

* Add more migrations

* Cleanup features

* Fix core_types::raster import

* Update demo artwork (to make profile ci work)

* Move *-types to node-graph/libraries folder

* Add missing node migrations

* Migrate more nodes

* Remove impure memo node

* More fixes and remove warning

* Migrate context and add a few missing migrations

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2025-11-18 11:21:54 +01:00
committed by GitHub
parent 12453d2e61
commit 57b0b9c7ed
193 changed files with 3871 additions and 2720 deletions

View File

@@ -0,0 +1,23 @@
[package]
name = "transform-nodes"
version = "0.1.0"
edition = "2024"
description = "Transform operation nodes for Graphene"
authors = ["Graphite Authors <contact@graphite.rs>"]
license = "MIT OR Apache-2.0"
[features]
default = ["serde"]
[dependencies]
# Local dependencies
core-types = { workspace = true }
vector-types = { workspace = true }
graphic-types = { workspace = true }
node-macro = { workspace = true }
# Workspace dependencies
glam = { workspace = true }
# Optional workspace dependencies
serde = { workspace = true, optional = true }

View File

@@ -0,0 +1,7 @@
pub mod transform_nodes;
// Re-export for convenience
pub use core_types as gcore;
pub use graphic_types;
pub use transform_nodes::*;
pub use vector_types;

View File

@@ -0,0 +1,106 @@
use core::f64;
use core_types::color::Color;
use core_types::table::Table;
use core_types::transform::{ApplyTransform, Transform};
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, InjectFootprint, ModifyFootprint, OwnedContextImpl};
use glam::{DAffine2, DVec2};
use graphic_types::Graphic;
use graphic_types::Vector;
use graphic_types::raster_types::{CPU, GPU, Raster};
use vector_types::GradientStops;
/// Applies the specified transform to the input value, which may be a graphic type or another transform.
#[node_macro::node(category(""))]
async fn transform<T: ApplyTransform + 'n + 'static>(
ctx: impl Ctx + CloneVarArgs + ExtractAll + ModifyFootprint,
#[implementations(
Context -> DAffine2,
Context -> DVec2,
Context -> Table<Vector>,
Context -> Table<Graphic>,
Context -> Table<Raster<CPU>>,
Context -> Table<Raster<GPU>>,
Context -> Table<Color>,
Context -> Table<GradientStops>,
)]
value: impl Node<Context<'static>, Output = T>,
translation: DVec2,
rotation: f64,
scale: DVec2,
skew: DVec2,
) -> T {
let trs = DAffine2::from_scale_angle_translation(scale, rotation.to_radians(), translation);
let skew = DAffine2::from_cols_array(&[1., skew.y.to_radians().tan(), skew.x.to_radians().tan(), 1., 0., 0.]);
let matrix = trs * skew;
let footprint = ctx.try_footprint().copied();
let mut ctx = OwnedContextImpl::from(ctx);
if let Some(mut footprint) = footprint {
footprint.apply_transform(&matrix);
ctx = ctx.with_footprint(footprint);
}
let mut transform_target = value.eval(ctx.into_context()).await;
transform_target.left_apply_transform(&matrix);
transform_target
}
/// Overwrites the transform of each element in the input table with the specified transform.
#[node_macro::node(category(""))]
fn replace_transform<Data, TransformInput: Transform>(
_: impl Ctx + InjectFootprint,
#[implementations(Table<Vector>, Table<Raster<CPU>>, Table<Graphic>, Table<Color>, Table<GradientStops>)] mut data: Table<Data>,
#[implementations(DAffine2)] transform: TransformInput,
) -> Table<Data> {
for data_transform in data.iter_mut() {
*data_transform.transform = transform.transform();
}
data
}
// TODO: Figure out how this node should behave once #2982 is implemented.
/// Obtains the transform of the first element in the input table, if present.
#[node_macro::node(category("Math: Transform"), path(core_types::vector))]
async fn extract_transform<T>(
_: impl Ctx,
#[implementations(
Table<Graphic>,
Table<Vector>,
Table<Raster<CPU>>,
Table<Raster<GPU>>,
Table<Color>,
Table<GradientStops>,
)]
vector: Table<T>,
) -> DAffine2 {
vector.iter().next().map(|row| *row.transform).unwrap_or_default()
}
/// Produces the inverse of the input transform, which is the transform that undoes the effect of the original transform.
#[node_macro::node(category("Math: Transform"))]
fn invert_transform(_: impl Ctx, transform: DAffine2) -> DAffine2 {
transform.inverse()
}
/// Extracts the translation component from the input transform.
#[node_macro::node(category("Math: Transform"))]
fn decompose_translation(_: impl Ctx, transform: DAffine2) -> DVec2 {
transform.translation
}
/// Extracts the rotation component (in degrees) from the input transform.
/// This, together with the "Decompose Scale" node, also may jointly represent any shear component in the original transform.
#[node_macro::node(category("Math: Transform"))]
fn decompose_rotation(_: impl Ctx, transform: DAffine2) -> f64 {
transform.decompose_rotation().to_degrees()
}
/// Extracts the scale component from the input transform.
/// This, together with the "Decompose Rotation" node, also may jointly represent any shear component in the original transform.
#[node_macro::node(category("Math: Transform"))]
fn decompose_scale(_: impl Ctx, transform: DAffine2) -> DVec2 {
transform.decompose_scale()
}