Polish user-created subgraph nodes: imports in the Properties panel; reorder/delete/rename imports/exports (#2105)

* Remove imports/exports

* WIP: Autogenerated properties

* WIP: Input based properties

* WIP: Hashmap based input overrides

* Migrate noise pattern node to input properties

* Reorder exports

* Continue migrating properties

* WIP: Improve reorder exports

* Automatically populate all input properties for sub networks

* Complete reorder import and export

* Add widget override to node macro

* Migrate assign colors to input based properties

* WIP: Full node property override

* Node based properties override for proto nodes

* Migrate all node properties to be input based

* Rename imports/exports

* improve UI

* Protonode input valid implementations

* Valid type list

* Small formatting fixes

* Polishing small issues

* Document upgrade

* fix tests

* Upgrade noise pattern node

* remove console log

* Fix upgrade script for Noise Pattern

* Improve the Properties panel representation for graphical data

* Re-export demo art

* Code review

* code review improvements

* Cleanup for node properties overrides

* Reexport demo art

* Fix clippy lints

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Adam Gerhant 2025-01-20 21:13:14 -08:00 committed by GitHub
parent ad68b1e5c8
commit eec0ef761c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 3660 additions and 2006 deletions

View file

@ -37,7 +37,7 @@ impl ValueProvider for MathNodeContext {
}
/// Calculates a mathematical expression with input values "A" and "B"
#[node_macro::node(category("Math"))]
#[node_macro::node(category("General"), properties("math_properties"))]
fn math<U: num_traits::float::Float>(
_: (),
/// The value of "A" when calculating the expression

View file

@ -1185,7 +1185,7 @@ impl DomainWarpType {
// Aims for interoperable compatibility with:
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27mixr%27%20%3D%20Channel%20Mixer
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Lab%20color%20only-,Channel%20Mixer,-Key%20is%20%27mixr
#[node_macro::node(category("Raster: Adjustment"))]
#[node_macro::node(category("Raster: Adjustment"), properties("channel_mixer_properties"))]
async fn channel_mixer<F: 'n + Send, T: Adjust<Color>>(
#[implementations(
(),
@ -1555,7 +1555,7 @@ async fn posterize<F: 'n + Send, T: Adjust<Color>>(
//
// Algorithm based on:
// https://geraldbakker.nl/psnumbers/exposure.html
#[node_macro::node(category("Raster: Adjustment"))]
#[node_macro::node(category("Raster: Adjustment"), properties("exposure_properties"))]
async fn exposure<F: 'n + Send, T: Adjust<Color>>(
#[implementations(
(),
@ -1683,7 +1683,13 @@ mod index_node {
use crate::raster::{Color, ImageFrame};
#[node_macro::node(category(""))]
pub fn index<T: Default + Clone>(_: (), #[implementations(Vec<ImageFrame<Color>>, Vec<Color>)] input: Vec<T>, index: u32) -> T {
pub fn index<T: Default + Clone>(
_: (),
#[implementations(Vec<ImageFrame<Color>>, Vec<Color>)]
#[widget(ParsedWidgetOverride::Hidden)]
input: Vec<T>,
index: u32,
) -> T {
if (index as usize) < input.len() {
input[index as usize].clone()
} else {

View file

@ -29,27 +29,39 @@ pub mod types {
pub type Resolution = glam::UVec2;
}
// Translation struct between macro and definition
#[derive(Clone)]
pub struct NodeMetadata {
pub display_name: &'static str,
pub category: Option<&'static str>,
pub fields: Vec<FieldMetadata>,
pub description: &'static str,
pub properties: Option<&'static str>,
}
// Translation struct between macro and definition
#[derive(Clone, Debug)]
pub struct FieldMetadata {
pub name: &'static str,
pub description: &'static str,
pub exposed: bool,
pub value_source: ValueSource,
pub widget_override: RegistryWidgetOverride,
pub value_source: RegistryValueSource,
pub number_min: Option<f64>,
pub number_max: Option<f64>,
pub number_mode_range: Option<(f64, f64)>,
}
#[derive(Clone, Debug)]
pub enum ValueSource {
pub enum RegistryWidgetOverride {
None,
Hidden,
String(&'static str),
Custom(&'static str),
}
#[derive(Clone, Debug)]
pub enum RegistryValueSource {
None,
Default(&'static str),
Scope(&'static str),

View file

@ -55,7 +55,7 @@ fn ellipse<F: 'n + Send>(#[implementations((), Footprint)] _footprint: F, _prima
ellipse
}
#[node_macro::node(category("Vector: Shape"))]
#[node_macro::node(category("Vector: Shape"), properties("rectangle_properties"))]
fn rectangle<F: 'n + Send, T: CornerRadius>(
#[implementations((), Footprint)] _footprint: F,
_primary: (),

View file

@ -50,14 +50,15 @@ async fn assign_colors<F: 'n + Send, T: VectorIterMut>(
Footprint -> GraphicGroup,
Footprint -> VectorData,
)]
#[widget(ParsedWidgetOverride::Hidden)]
vector_group: impl Node<F, Output = T>,
#[default(true)] fill: bool,
stroke: bool,
gradient: GradientStops,
#[widget(ParsedWidgetOverride::Custom = "assign_colors_gradient")] gradient: GradientStops,
reverse: bool,
randomize: bool,
seed: SeedValue,
repeat_every: u32,
#[widget(ParsedWidgetOverride::Custom = "assign_colors_randomize")] randomize: bool,
#[widget(ParsedWidgetOverride::Custom = "assign_colors_seed")] seed: SeedValue,
#[widget(ParsedWidgetOverride::Custom = "assign_colors_repeat_every")] repeat_every: u32,
) -> T {
let mut input = vector_group.eval(footprint).await;
let length = input.vector_iter_mut().count();
@ -89,7 +90,7 @@ async fn assign_colors<F: 'n + Send, T: VectorIterMut>(
input
}
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector), properties("fill_properties"))]
async fn fill<F: 'n + Send, FillTy: Into<Fill> + 'n + Send, TargetTy: VectorIterMut + 'n + Send>(
#[implementations(
(),
@ -161,7 +162,7 @@ async fn fill<F: 'n + Send, FillTy: Into<Fill> + 'n + Send, TargetTy: VectorIter
target
}
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector), properties("stroke_properties"))]
async fn stroke<F: 'n + Send, ColorTy: Into<Option<Color>> + 'n + Send, TargetTy: VectorIterMut + 'n + Send>(
#[implementations(
(),
@ -430,7 +431,7 @@ async fn bounding_box<F: 'n + Send>(
result
}
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
#[node_macro::node(category("Vector"), path(graphene_core::vector), properties("offset_path_properties"))]
async fn offset_path<F: 'n + Send>(
#[implementations(
(),