Improve node macro and add more diagnostics (#1999)

* Improve node macro ergonomics

* Fix type error in stub import

* Fix wasm nodes

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-09-21 21:57:45 +02:00
committed by GitHub
parent 3eb98c6d6d
commit cd4124a596
15 changed files with 358 additions and 122 deletions

View File

@@ -234,8 +234,8 @@ impl ArtboardGroup {
#[node_macro::node(category(""))]
async fn layer<F: 'n + Copy + Send>(
#[implementations((), Footprint)] footprint: F,
#[implementations(((), GraphicGroup), (Footprint, GraphicGroup))] stack: impl Node<F, Output = GraphicGroup>,
#[implementations(((), GraphicElement), (Footprint, GraphicElement))] graphic_element: impl Node<F, Output = GraphicElement>,
#[implementations(() -> GraphicGroup, Footprint -> GraphicGroup)] stack: impl Node<F, Output = GraphicGroup>,
#[implementations(() -> GraphicElement, Footprint -> GraphicElement)] graphic_element: impl Node<F, Output = GraphicElement>,
node_path: Vec<NodeId>,
) -> GraphicGroup {
let mut element = graphic_element.eval(footprint).await;
@@ -257,15 +257,15 @@ async fn layer<F: 'n + Copy + Send>(
async fn to_element<F: 'n + Send, Data: Into<GraphicElement> + 'n>(
#[implementations((), (), (), (), Footprint)] footprint: F,
#[implementations(
((), VectorData),
((), ImageFrame<Color>),
((), GraphicGroup),
((), TextureFrame),
(Footprint, VectorData),
(Footprint, ImageFrame<Color>),
(Footprint, GraphicGroup),
(Footprint, TextureFrame),
)]
() -> VectorData,
() -> ImageFrame<Color>,
() -> GraphicGroup,
() -> TextureFrame,
Footprint -> VectorData,
Footprint -> ImageFrame<Color>,
Footprint -> GraphicGroup,
Footprint -> TextureFrame,
)]
data: impl Node<F, Output = Data>,
) -> GraphicElement {
data.eval(footprint).await.into()
@@ -275,14 +275,14 @@ async fn to_element<F: 'n + Send, Data: Into<GraphicElement> + 'n>(
async fn to_group<F: 'n + Send, Data: Into<GraphicGroup> + 'n>(
#[implementations((), (), (), (), Footprint)] footprint: F,
#[implementations(
((), VectorData),
((), ImageFrame<Color>),
((), GraphicGroup),
((), TextureFrame),
(Footprint, VectorData),
(Footprint, ImageFrame<Color>),
(Footprint, GraphicGroup),
(Footprint, TextureFrame),
() -> VectorData,
() -> ImageFrame<Color>,
() -> GraphicGroup,
() -> TextureFrame,
Footprint -> VectorData,
Footprint -> ImageFrame<Color>,
Footprint -> GraphicGroup,
Footprint -> TextureFrame,
)]
element: impl Node<F, Output = Data>,
) -> GraphicGroup {
@@ -292,7 +292,7 @@ async fn to_group<F: 'n + Send, Data: Into<GraphicGroup> + 'n>(
#[node_macro::node(category(""))]
async fn to_artboard<F: 'n + Copy + Send + ApplyTransform>(
#[implementations((), Footprint)] mut footprint: F,
#[implementations(((), GraphicGroup), (Footprint, GraphicGroup))] contents: impl Node<F, Output = GraphicGroup>,
#[implementations(() -> GraphicGroup, Footprint -> GraphicGroup)] contents: impl Node<F, Output = GraphicGroup>,
label: String,
location: IVec2,
dimensions: IVec2,
@@ -314,8 +314,8 @@ async fn to_artboard<F: 'n + Copy + Send + ApplyTransform>(
#[node_macro::node(category(""))]
async fn append_artboard<F: 'n + Copy + Send>(
#[implementations((), Footprint)] footprint: F,
#[implementations(((), ArtboardGroup), (Footprint, ArtboardGroup))] artboards: impl Node<F, Output = ArtboardGroup>,
#[implementations(((), Artboard), (Footprint, Artboard))] artboard: impl Node<F, Output = Artboard>,
#[implementations(() -> ArtboardGroup, Footprint -> ArtboardGroup)] artboards: impl Node<F, Output = ArtboardGroup>,
#[implementations(() -> Artboard, Footprint -> Artboard)] artboard: impl Node<F, Output = Artboard>,
node_path: Vec<NodeId>,
) -> ArtboardGroup {
let artboard = artboard.eval(footprint).await;

View File

@@ -310,7 +310,7 @@ impl SetBlendMode for ImageFrame<Color> {
#[node_macro::node(category("Style"))]
async fn blend_mode<T: SetBlendMode>(
footprint: Footprint,
#[implementations((Footprint, crate::vector::VectorData), (Footprint, crate::GraphicGroup), (Footprint, ImageFrame<Color>))] value: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> crate::vector::VectorData, Footprint -> crate::GraphicGroup, Footprint -> ImageFrame<Color>)] value: impl Node<Footprint, Output = T>,
blend_mode: BlendMode,
) -> T {
let mut value = value.eval(footprint).await;
@@ -321,7 +321,7 @@ async fn blend_mode<T: SetBlendMode>(
#[node_macro::node(category("Style"))]
async fn opacity<T: MultiplyAlpha>(
footprint: Footprint,
#[implementations((Footprint, crate::vector::VectorData), (Footprint, crate::GraphicGroup), (Footprint, ImageFrame<Color>))] value: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> crate::vector::VectorData, Footprint -> crate::GraphicGroup, Footprint -> ImageFrame<Color>)] value: impl Node<Footprint, Output = T>,
#[default(100.)] factor: Percentage,
) -> T {
let mut value = value.eval(footprint).await;

View File

@@ -271,7 +271,7 @@ impl From<BlendMode> for vello::peniko::Mix {
#[node_macro::node(category("Raster: Adjustment"))] // Unique to Graphite
async fn luminance<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
luminance_calc: LuminanceCalculation,
) -> T {
let mut input = input.eval(footprint).await;
@@ -291,7 +291,7 @@ async fn luminance<T: Adjust<Color>>(
#[node_macro::node(category("Raster"))]
async fn extract_channel<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
channel: RedGreenBlueAlpha,
) -> T {
let mut input = input.eval(footprint).await;
@@ -308,7 +308,7 @@ async fn extract_channel<T: Adjust<Color>>(
}
#[node_macro::node(category("Raster"))]
async fn make_opaque<T: Adjust<Color>>(footprint: Footprint, #[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>) -> T {
async fn make_opaque<T: Adjust<Color>>(footprint: Footprint, #[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>) -> T {
let mut input = input.eval(footprint).await;
input.adjust(|color| {
if color.a() == 0. {
@@ -323,7 +323,7 @@ async fn make_opaque<T: Adjust<Color>>(footprint: Footprint, #[implementations((
#[node_macro::node(category("Raster: Adjustment"))]
async fn levels<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] image: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
#[default(0.)] shadows: Percentage,
#[default(50.)] midtones: Percentage,
#[default(100.)] highlights: Percentage,
@@ -381,7 +381,7 @@ async fn levels<T: Adjust<Color>>(
#[node_macro::node(name("Black & White"), category("Raster: Adjustment"))]
async fn black_and_white<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] image: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
#[default(000000ff)] tint: Color,
#[default(40.)]
#[range((-200., 300.))]
@@ -446,7 +446,7 @@ async fn black_and_white<T: Adjust<Color>>(
#[node_macro::node(name("Hue/Saturation"), category("Raster: Adjustment"))]
async fn hue_saturation<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
hue_shift: Angle,
saturation_shift: SignedPercentage,
lightness_shift: SignedPercentage,
@@ -472,7 +472,7 @@ async fn hue_saturation<T: Adjust<Color>>(
}
#[node_macro::node(category("Raster: Adjustment"))]
async fn invert<T: Adjust<Color>>(footprint: Footprint, #[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>) -> T {
async fn invert<T: Adjust<Color>>(footprint: Footprint, #[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>) -> T {
let mut input = input.eval(footprint).await;
input.adjust(|color| {
let color = color.to_gamma_srgb();
@@ -487,7 +487,7 @@ async fn invert<T: Adjust<Color>>(footprint: Footprint, #[implementations((Footp
#[node_macro::node(category("Raster: Adjustment"))]
async fn threshold<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] image: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
#[default(50.)] min_luminance: Percentage,
#[default(100.)] max_luminance: Percentage,
luminance_calc: LuminanceCalculation,
@@ -574,22 +574,22 @@ impl Blend<Color> for GradientStops {
async fn blend<F: 'n + Copy + Send, T: Blend<Color> + Send>(
#[implementations((), (), (), Footprint)] footprint: F,
#[implementations(
((), Color),
((), ImageFrame<Color>),
((), GradientStops),
(Footprint, Color),
(Footprint, ImageFrame<Color>),
(Footprint, GradientStops),
() -> Color,
() -> ImageFrame<Color>,
() -> GradientStops,
Footprint -> Color,
Footprint -> ImageFrame<Color>,
Footprint -> GradientStops,
)]
over: impl Node<F, Output = T>,
#[expose]
#[implementations(
((), Color),
((), ImageFrame<Color>),
((), GradientStops),
(Footprint, Color),
(Footprint, ImageFrame<Color>),
(Footprint, GradientStops),
() -> Color,
() -> ImageFrame<Color>,
() -> GradientStops,
Footprint -> Color,
Footprint -> ImageFrame<Color>,
Footprint -> GradientStops,
)]
under: impl Node<F, Output = T>,
blend_mode: BlendMode,
@@ -693,12 +693,12 @@ pub fn blend_colors(foreground: Color, background: Color, blend_mode: BlendMode,
async fn gradient_map<F: 'n + Copy + Send, T: Adjust<Color>>(
#[implementations((), (), (), Footprint)] footprint: F,
#[implementations(
((), Color),
((), ImageFrame<Color>),
((), GradientStops),
(Footprint, Color),
(Footprint, ImageFrame<Color>),
(Footprint, GradientStops),
() -> Color,
() -> ImageFrame<Color>,
() -> GradientStops,
Footprint -> Color,
Footprint -> ImageFrame<Color>,
Footprint -> GradientStops,
)]
image: impl Node<F, Output = T>,
gradient: GradientStops,
@@ -720,7 +720,7 @@ async fn gradient_map<F: 'n + Copy + Send, T: Adjust<Color>>(
#[node_macro::node(category("Raster: Adjustment"))]
async fn vibrance<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] image: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
vibrance: SignedPercentage,
) -> T {
let mut input = image.eval(footprint).await;
@@ -1003,7 +1003,7 @@ impl DomainWarpType {
#[node_macro::node(category("Raster: Adjustment"))]
async fn channel_mixer<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] image: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
monochrome: bool,
#[default(40.)]
@@ -1145,7 +1145,7 @@ impl core::fmt::Display for SelectiveColorChoice {
#[node_macro::node(category("Raster: Adjustment"))]
async fn selective_color<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] image: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
mode: RelativeAbsolute,
#[name("(Reds) Cyan")] r_c: f64,
#[name("(Reds) Magenta")] r_m: f64,
@@ -1293,7 +1293,7 @@ impl<P: Pixel> MultiplyAlpha for ImageFrame<P> {
#[node_macro::node(category("Raster: Adjustment"))]
async fn posterize<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
#[default(4)]
#[min(2.)]
levels: u32,
@@ -1317,7 +1317,7 @@ async fn posterize<T: Adjust<Color>>(
#[node_macro::node(category("Raster: Adjustment"))]
async fn exposure<T: Adjust<Color>>(
footprint: Footprint,
#[implementations((Footprint, Color), (Footprint, ImageFrame<Color>))] input: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
exposure: f64,
offset: f64,
#[default(1.)]
@@ -1387,12 +1387,12 @@ fn generate_curves<C: Channel + super::Linear>(_: (), curve: Curve, #[implementa
async fn color_overlay<F: 'n + Copy + Send, T: Adjust<Color>>(
#[implementations((), (), (), Footprint)] footprint: F,
#[implementations(
((), Color),
((), ImageFrame<Color>),
((), GradientStops),
(Footprint, Color),
(Footprint, ImageFrame<Color>),
(Footprint, GradientStops),
() -> Color,
() -> ImageFrame<Color>,
() -> GradientStops,
Footprint -> Color,
Footprint -> ImageFrame<Color>,
Footprint -> GradientStops,
)]
image: impl Node<F, Output = T>,
#[default(000000ff)] color: Color,

View File

@@ -220,12 +220,12 @@ impl ApplyTransform for () {
async fn transform<I: Into<Footprint> + ApplyTransform + 'n + Clone + Send + Sync, T: TransformMut + 'n>(
#[implementations(Footprint, Footprint, Footprint, (), (), ())] mut input: I,
#[implementations(
(Footprint, VectorData),
(Footprint, GraphicGroup),
(Footprint, ImageFrame<crate::Color>),
((), VectorData),
((), GraphicGroup),
((), ImageFrame<crate::Color>),
Footprint -> VectorData,
Footprint -> GraphicGroup,
Footprint -> ImageFrame<crate::Color>,
() -> VectorData,
() -> GraphicGroup,
() -> ImageFrame<crate::Color>,
)]
transform_target: impl Node<I, Output = T>,
translate: DVec2,

View File

@@ -426,7 +426,7 @@ use crate::transform::Footprint;
#[node_macro::node(category(""))]
async fn path_modify<F: 'n + Send + Sync + Clone>(
#[implementations((), Footprint)] input: F,
#[implementations(((), VectorData), (Footprint, VectorData))] vector_data: impl Node<F, Output = VectorData>,
#[implementations(() -> VectorData, Footprint -> VectorData)] vector_data: impl Node<F, Output = VectorData>,
modification: Box<VectorModification>,
) -> VectorData {
let mut vector_data = vector_data.eval(input).await;

View File

@@ -29,7 +29,7 @@ impl VectorIterMut for VectorData {
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
async fn assign_colors<T: VectorIterMut>(
footprint: Footprint,
#[implementations((Footprint, GraphicGroup), (Footprint, VectorData))] vector_group: impl Node<Footprint, Output = T>,
#[implementations(Footprint -> GraphicGroup, Footprint -> VectorData)] vector_group: impl Node<Footprint, Output = T>,
#[default(true)] fill: bool,
stroke: bool,
gradient: GradientStops,
@@ -177,7 +177,7 @@ async fn circular_repeat(
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
async fn bounding_box<F: 'n + Copy + Send>(
#[implementations((), Footprint)] footprint: F,
#[implementations(((), VectorData), (Footprint, VectorData))] vector_data: impl Node<F, Output = VectorData>,
#[implementations(() -> VectorData, Footprint -> VectorData)] vector_data: impl Node<F, Output = VectorData>,
) -> VectorData {
let vector_data = vector_data.eval(footprint).await;
@@ -253,7 +253,7 @@ async fn copy_to_points<I: GraphicElementRendered + Default + ConcatElement + Tr
footprint: Footprint,
points: impl Node<Footprint, Output = VectorData>,
#[expose]
#[implementations((Footprint, VectorData), (Footprint, GraphicGroup))]
#[implementations(Footprint -> VectorData, Footprint -> GraphicGroup)]
instance: impl Node<Footprint, Output = I>,
#[default(1)] random_scale_min: f64,
#[default(1)] random_scale_max: f64,
@@ -387,7 +387,7 @@ async fn sample_points(
#[node_macro::node(category(""), path(graphene_core::vector))]
async fn poisson_disk_points<F: 'n + Copy + Send>(
#[implementations((), Footprint)] footprint: F,
#[implementations(((), VectorData), (Footprint, VectorData))] vector_data: impl Node<F, Output = VectorData>,
#[implementations(() -> VectorData, Footprint -> VectorData)] vector_data: impl Node<F, Output = VectorData>,
#[default(10.)]
#[min(0.01)]
separation_disk_diameter: f64,