Refactor node migration to be less susceptible to forgetting outdated strings (#2853)
Some checks failed
Editor: Dev & CI / build (push) Has been cancelled
Editor: Dev & CI / cargo-deny (push) Has been cancelled

* migration: make document migration use ProtoNodeIdentifier

* migration: NodeReplacement struct for better formatting

* migration: test for duplicates and fix them
This commit is contained in:
Firestar99 2025-07-11 02:40:54 +02:00 committed by GitHub
parent 912e6f61a9
commit 4c75ddf936
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 459 additions and 148 deletions

View file

@ -9,6 +9,7 @@ use bezier_rs::Subpath;
use glam::IVec2;
use graph_craft::document::DocumentNode;
use graph_craft::document::{DocumentNodeImplementation, NodeInput, value::TaggedValue};
use graphene_std::ProtoNodeIdentifier;
use graphene_std::text::TypesettingConfig;
use graphene_std::uuid::NodeId;
use graphene_std::vector::style::{PaintOrder, StrokeAlign};
@ -20,156 +21,440 @@ const TEXT_REPLACEMENTS: &[(&str, &str)] = &[
("graphene_core::vector::vector_nodes::SubpathSegmentLengthsNode", "graphene_core::vector::SubpathSegmentLengthsNode"),
];
const REPLACEMENTS: &[(&str, &str)] = &[
("graphene_core::AddArtboardNode", "graphene_core::graphic_element::AppendArtboardNode"),
("graphene_core::ConstructArtboardNode", "graphene_core::graphic_element::ToArtboardNode"),
("graphene_core::ToGraphicElementNode", "graphene_core::graphic_element::ToElementNode"),
("graphene_core::ToGraphicGroupNode", "graphene_core::graphic_element::ToGroupNode"),
pub struct NodeReplacement<'a> {
node: ProtoNodeIdentifier,
aliases: &'a [&'a str],
}
const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
// graphic element
NodeReplacement {
node: graphene_std::graphic_element::append_artboard::IDENTIFIER,
aliases: &["graphene_core::AddArtboardNode"],
},
NodeReplacement {
node: graphene_std::graphic_element::to_artboard::IDENTIFIER,
aliases: &["graphene_core::ConstructArtboardNode"],
},
NodeReplacement {
node: graphene_std::graphic_element::to_element::IDENTIFIER,
aliases: &["graphene_core::ToGraphicElementNode"],
},
NodeReplacement {
node: graphene_std::graphic_element::to_group::IDENTIFIER,
aliases: &["graphene_core::ToGraphicGroupNode"],
},
// math_nodes
("graphene_core::ops::MathNode", "graphene_math_nodes::MathNode"),
("graphene_core::ops::AddNode", "graphene_math_nodes::AddNode"),
("graphene_core::ops::SubtractNode", "graphene_math_nodes::SubtractNode"),
("graphene_core::ops::MultiplyNode", "graphene_math_nodes::MultiplyNode"),
("graphene_core::ops::DivideNode", "graphene_math_nodes::DivideNode"),
("graphene_core::ops::ModuloNode", "graphene_math_nodes::ModuloNode"),
("graphene_core::ops::ExponentNode", "graphene_math_nodes::ExponentNode"),
("graphene_core::ops::RootNode", "graphene_math_nodes::RootNode"),
("graphene_core::ops::LogarithmNode", "graphene_math_nodes::LogarithmNode"),
("graphene_core::ops::SineNode", "graphene_math_nodes::SineNode"),
("graphene_core::ops::CosineNode", "graphene_math_nodes::CosineNode"),
("graphene_core::ops::TangentNode", "graphene_math_nodes::TangentNode"),
("graphene_core::ops::SineInverseNode", "graphene_math_nodes::SineInverseNode"),
("graphene_core::ops::CosineInverseNode", "graphene_math_nodes::CosineInverseNode"),
("graphene_core::ops::TangentInverseNode", "graphene_math_nodes::TangentInverseNode"),
("graphene_core::ops::RandomNode", "graphene_math_nodes::RandomNode"),
("graphene_core::ops::ToU32Node", "graphene_math_nodes::ToU32Node"),
("graphene_core::ops::ToU64Node", "graphene_math_nodes::ToU64Node"),
("graphene_core::ops::ToF64Node", "graphene_math_nodes::ToF64Node"),
("graphene_core::ops::RoundNode", "graphene_math_nodes::RoundNode"),
("graphene_core::ops::FloorNode", "graphene_math_nodes::FloorNode"),
("graphene_core::ops::CeilingNode", "graphene_math_nodes::CeilingNode"),
("graphene_core::ops::MinNode", "graphene_math_nodes::MinNode"),
("graphene_core::ops::MaxNode", "graphene_math_nodes::MaxNode"),
("graphene_core::ops::ClampNode", "graphene_math_nodes::ClampNode"),
("graphene_core::ops::EqualsNode", "graphene_math_nodes::EqualsNode"),
("graphene_core::ops::NotEqualsNode", "graphene_math_nodes::NotEqualsNode"),
("graphene_core::ops::LessThanNode", "graphene_math_nodes::LessThanNode"),
("graphene_core::ops::GreaterThanNode", "graphene_math_nodes::GreaterThanNode"),
("graphene_core::ops::LogicalOrNode", "graphene_math_nodes::LogicalOrNode"),
("graphene_core::ops::LogicalAndNode", "graphene_math_nodes::LogicalAndNode"),
("graphene_core::ops::LogicalNotNode", "graphene_math_nodes::LogicalNotNode"),
("graphene_core::ops::BoolValueNode", "graphene_math_nodes::BoolValueNode"),
("graphene_core::ops::NumberValueNode", "graphene_math_nodes::NumberValueNode"),
("graphene_core::ops::PercentageValueNode", "graphene_math_nodes::PercentageValueNode"),
("graphene_core::ops::CoordinateValueNode", "graphene_math_nodes::CoordinateValueNode"),
("graphene_core::ops::ConstructVector2", "graphene_math_nodes::CoordinateValueNode"),
("graphene_core::ops::Vector2ValueNode", "graphene_math_nodes::CoordinateValueNode"),
("graphene_core::ops::ColorValueNode", "graphene_math_nodes::ColorValueNode"),
("graphene_core::ops::GradientValueNode", "graphene_math_nodes::GradientValueNode"),
("graphene_core::ops::SampleGradientNode", "graphene_math_nodes::SampleGradientNode"),
("graphene_core::ops::StringValueNode", "graphene_math_nodes::StringValueNode"),
("graphene_core::ops::DotProductNode", "graphene_math_nodes::DotProductNode"),
NodeReplacement {
node: graphene_std::math_nodes::math::IDENTIFIER,
aliases: &["graphene_core::ops::MathNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::add::IDENTIFIER,
aliases: &["graphene_core::ops::AddNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::subtract::IDENTIFIER,
aliases: &["graphene_core::ops::SubtractNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::multiply::IDENTIFIER,
aliases: &["graphene_core::ops::MultiplyNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::divide::IDENTIFIER,
aliases: &["graphene_core::ops::DivideNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::modulo::IDENTIFIER,
aliases: &["graphene_core::ops::ModuloNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::exponent::IDENTIFIER,
aliases: &["graphene_core::ops::ExponentNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::root::IDENTIFIER,
aliases: &["graphene_core::ops::RootNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::logarithm::IDENTIFIER,
aliases: &["graphene_core::ops::LogarithmNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::sine::IDENTIFIER,
aliases: &["graphene_core::ops::SineNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::cosine::IDENTIFIER,
aliases: &["graphene_core::ops::CosineNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::tangent::IDENTIFIER,
aliases: &["graphene_core::ops::TangentNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::sine_inverse::IDENTIFIER,
aliases: &["graphene_core::ops::SineInverseNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::cosine_inverse::IDENTIFIER,
aliases: &["graphene_core::ops::CosineInverseNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::tangent_inverse::IDENTIFIER,
aliases: &["graphene_core::ops::TangentInverseNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::random::IDENTIFIER,
aliases: &["graphene_core::ops::RandomNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::to_u_32::IDENTIFIER,
aliases: &["graphene_core::ops::ToU32Node"],
},
NodeReplacement {
node: graphene_std::math_nodes::to_u_64::IDENTIFIER,
aliases: &["graphene_core::ops::ToU64Node"],
},
NodeReplacement {
node: graphene_std::math_nodes::to_f_64::IDENTIFIER,
aliases: &["graphene_core::ops::ToF64Node"],
},
NodeReplacement {
node: graphene_std::math_nodes::round::IDENTIFIER,
aliases: &["graphene_core::ops::RoundNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::floor::IDENTIFIER,
aliases: &["graphene_core::ops::FloorNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::ceiling::IDENTIFIER,
aliases: &["graphene_core::ops::CeilingNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::min::IDENTIFIER,
aliases: &["graphene_core::ops::MinNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::max::IDENTIFIER,
aliases: &["graphene_core::ops::MaxNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::clamp::IDENTIFIER,
aliases: &["graphene_core::ops::ClampNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::equals::IDENTIFIER,
aliases: &["graphene_core::ops::EqualsNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::not_equals::IDENTIFIER,
aliases: &["graphene_core::ops::NotEqualsNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::less_than::IDENTIFIER,
aliases: &["graphene_core::ops::LessThanNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::greater_than::IDENTIFIER,
aliases: &["graphene_core::ops::GreaterThanNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::logical_or::IDENTIFIER,
aliases: &["graphene_core::ops::LogicalOrNode", "graphene_core::ops::LogicAndNode", "graphene_core::logic::LogicAndNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::logical_and::IDENTIFIER,
aliases: &["graphene_core::ops::LogicalAndNode", "graphene_core::ops::LogicNotNode", "graphene_core::logic::LogicNotNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::logical_not::IDENTIFIER,
aliases: &["graphene_core::ops::LogicalNotNode", "graphene_core::ops::LogicOrNode", "graphene_core::logic::LogicOrNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::bool_value::IDENTIFIER,
aliases: &["graphene_core::ops::BoolValueNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::number_value::IDENTIFIER,
aliases: &["graphene_core::ops::NumberValueNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::percentage_value::IDENTIFIER,
aliases: &["graphene_core::ops::PercentageValueNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::coordinate_value::IDENTIFIER,
aliases: &[
"graphene_core::ops::CoordinateValueNode",
"graphene_core::ops::ConstructVector2",
"graphene_core::ops::Vector2ValueNode",
],
},
NodeReplacement {
node: graphene_std::math_nodes::color_value::IDENTIFIER,
aliases: &["graphene_core::ops::ColorValueNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::gradient_value::IDENTIFIER,
aliases: &["graphene_core::ops::GradientValueNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::sample_gradient::IDENTIFIER,
aliases: &["graphene_core::ops::SampleGradientNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::string_value::IDENTIFIER,
aliases: &["graphene_core::ops::StringValueNode"],
},
NodeReplacement {
node: graphene_std::math_nodes::dot_product::IDENTIFIER,
aliases: &["graphene_core::ops::DotProductNode"],
},
// debug
("graphene_core::ops::SizeOfNode", "graphene_core::debug::SizeOfNode"),
("graphene_core::ops::SomeNode", "graphene_core::debug::SomeNode"),
("graphene_core::ops::UnwrapNode", "graphene_core::debug::UnwrapNode"),
("graphene_core::ops::CloneNode", "graphene_core::debug::CloneNode"),
NodeReplacement {
node: graphene_std::debug::size_of::IDENTIFIER,
aliases: &["graphene_core::ops::SizeOfNode"],
},
NodeReplacement {
node: graphene_std::debug::some::IDENTIFIER,
aliases: &["graphene_core::ops::SomeNode"],
},
NodeReplacement {
node: graphene_std::debug::unwrap::IDENTIFIER,
aliases: &["graphene_core::ops::UnwrapNode"],
},
NodeReplacement {
node: graphene_std::debug::clone::IDENTIFIER,
aliases: &["graphene_core::ops::CloneNode"],
},
// ???
("graphene_core::ops::ExtractXyNode", "graphene_core::extract_xy::ExtractXyNode"),
("graphene_core::logic::LogicAndNode", "graphene_core::ops::LogicAndNode"),
("graphene_core::logic::LogicNotNode", "graphene_core::ops::LogicNotNode"),
("graphene_core::logic::LogicOrNode", "graphene_core::ops::LogicOrNode"),
("graphene_core::raster::BlendModeNode", "graphene_core::blending_nodes::BlendModeNode"),
("graphene_core::raster::OpacityNode", "graphene_core::blending_nodes::OpacityNode"),
("graphene_core::raster::BlendingNode", "graphene_core::blending_nodes::BlendingNode"),
("graphene_core::vector::GenerateHandlesNode", "graphene_core::vector::AutoTangentsNode"),
("graphene_core::vector::RemoveHandlesNode", "graphene_core::vector::AutoTangentsNode"),
NodeReplacement {
node: graphene_std::extract_xy::extract_xy::IDENTIFIER,
aliases: &["graphene_core::ops::ExtractXyNode"],
},
NodeReplacement {
node: graphene_std::blending_nodes::blend_mode::IDENTIFIER,
aliases: &["graphene_core::raster::BlendModeNode"],
},
NodeReplacement {
node: graphene_std::blending_nodes::opacity::IDENTIFIER,
aliases: &["graphene_core::raster::OpacityNode"],
},
NodeReplacement {
node: graphene_std::blending_nodes::blending::IDENTIFIER,
aliases: &["graphene_core::raster::BlendingNode"],
},
NodeReplacement {
node: graphene_std::vector::auto_tangents::IDENTIFIER,
aliases: &["graphene_core::vector::GenerateHandlesNode", "graphene_core::vector::RemoveHandlesNode"],
},
// raster::adjustments
("graphene_core::raster::adjustments::LuminanceNode", "graphene_raster_nodes::adjustments::LuminanceNode"),
("graphene_core::raster::LuminanceNode", "graphene_raster_nodes::adjustments::LuminanceNode"),
("graphene_core::raster::adjustments::ExtractChannelNode", "graphene_raster_nodes::adjustments::ExtractChannelNode"),
("graphene_core::raster::ExtractChannelNode", "graphene_raster_nodes::adjustments::ExtractChannelNode"),
("graphene_core::raster::adjustments::MakeOpaqueNode", "graphene_raster_nodes::adjustments::MakeOpaqueNode"),
("graphene_core::raster::ExtractOpaqueNode", "graphene_raster_nodes::adjustments::MakeOpaqueNode"),
(
"graphene_core::raster::adjustments::BrightnessContrastNode",
"graphene_raster_nodes::adjustments::BrightnessContrastNode",
),
("graphene_core::raster::adjustments::LevelsNode", "graphene_raster_nodes::adjustments::LevelsNode"),
("graphene_core::raster::LevelsNode", "graphene_raster_nodes::adjustments::LevelsNode"),
("graphene_core::raster::adjustments::BlackAndWhiteNode", "graphene_raster_nodes::adjustments::BlackAndWhiteNode"),
("graphene_core::raster::BlackAndWhiteNode", "graphene_raster_nodes::adjustments::BlackAndWhiteNode"),
("graphene_core::raster::adjustments::HueSaturationNode", "graphene_raster_nodes::adjustments::HueSaturationNode"),
("graphene_core::raster::HueSaturationNode", "graphene_raster_nodes::adjustments::HueSaturationNode"),
("graphene_core::raster::adjustments::InvertNode", "graphene_raster_nodes::adjustments::InvertNode"),
("graphene_core::raster::InvertNode", "graphene_raster_nodes::adjustments::InvertNode"),
("graphene_core::raster::InvertRGBNode", "graphene_raster_nodes::adjustments::InvertNode"),
("graphene_core::raster::adjustments::ThresholdNode", "graphene_raster_nodes::adjustments::ThresholdNode"),
("graphene_core::raster::ThresholdNode", "graphene_raster_nodes::adjustments::ThresholdNode"),
("graphene_core::raster::adjustments::BlendNode", "graphene_raster_nodes::adjustments::BlendNode"),
("graphene_core::raster::BlendNode", "graphene_raster_nodes::adjustments::BlendNode"),
("graphene_core::raster::BlendColorPairNode", "graphene_raster_nodes::adjustments::BlendColorPairNode"),
("graphene_core::raster::adjustments::BlendColorsNode", "graphene_raster_nodes::adjustments::BlendColorsNode"),
("graphene_core::raster::BlendColorsNode", "graphene_raster_nodes::adjustments::BlendColorsNode"),
("graphene_core::raster::adjustments::GradientMapNode", "graphene_raster_nodes::adjustments::GradientMapNode"),
("graphene_core::raster::GradientMapNode", "graphene_raster_nodes::adjustments::GradientMapNode"),
("graphene_core::raster::adjustments::VibranceNode", "graphene_raster_nodes::adjustments::VibranceNode"),
("graphene_core::raster::VibranceNode", "graphene_raster_nodes::adjustments::VibranceNode"),
("graphene_core::raster::adjustments::ChannelMixerNode", "graphene_raster_nodes::adjustments::ChannelMixerNode"),
("graphene_core::raster::ChannelMixerNode", "graphene_raster_nodes::adjustments::ChannelMixerNode"),
("graphene_core::raster::adjustments::SelectiveColorNode", "graphene_raster_nodes::adjustments::SelectiveColorNode"),
("graphene_core::raster::adjustments::PosterizeNode", "graphene_raster_nodes::adjustments::PosterizeNode"),
("graphene_core::raster::PosterizeNode", "graphene_raster_nodes::adjustments::PosterizeNode"),
("graphene_core::raster::adjustments::ExposureNode", "graphene_raster_nodes::adjustments::ExposureNode"),
("graphene_core::raster::ExposureNode", "graphene_raster_nodes::adjustments::ExposureNode"),
("graphene_core::raster::adjustments::ColorOverlayNode", "graphene_raster_nodes::adjustments::ColorOverlayNode"),
("graphene_raster_nodes::generate_curves::ColorOverlayNode", "graphene_raster_nodes::adjustments::ColorOverlayNode"),
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::luminance::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::LuminanceNode", "graphene_core::raster::LuminanceNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::extract_channel::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::ExtractChannelNode", "graphene_core::raster::ExtractChannelNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::make_opaque::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::MakeOpaqueNode", "graphene_core::raster::ExtractOpaqueNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::brightness_contrast::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::BrightnessContrastNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::levels::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::LevelsNode", "graphene_core::raster::LevelsNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::black_and_white::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::BlackAndWhiteNode", "graphene_core::raster::BlackAndWhiteNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::hue_saturation::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::HueSaturationNode", "graphene_core::raster::HueSaturationNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::invert::IDENTIFIER,
aliases: &[
"graphene_core::raster::adjustments::InvertNode",
"graphene_core::raster::InvertNode",
"graphene_core::raster::InvertRGBNode",
],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::threshold::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::ThresholdNode", "graphene_core::raster::ThresholdNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::blend::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::BlendNode", "graphene_core::raster::BlendNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::blend_color_pair::IDENTIFIER,
aliases: &["graphene_core::raster::BlendColorPairNode"],
},
// this node doesn't seem to exist?
// (graphene_std::raster_nodes::adjustments::blend_color::IDENTIFIER, &["graphene_core::raster::adjustments::BlendColorsNode","graphene_core::raster::BlendColorsNode"]),
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::gradient_map::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::GradientMapNode", "graphene_core::raster::GradientMapNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::vibrance::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::VibranceNode", "graphene_core::raster::VibranceNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::channel_mixer::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::ChannelMixerNode", "graphene_core::raster::ChannelMixerNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::selective_color::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::SelectiveColorNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::posterize::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::PosterizeNode", "graphene_core::raster::PosterizeNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::exposure::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::ExposureNode", "graphene_core::raster::ExposureNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::adjustments::color_overlay::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::ColorOverlayNode", "graphene_raster_nodes::generate_curves::ColorOverlayNode"],
},
// raster
("graphene_core::raster::adjustments::GenerateCurvesNode", "graphene_raster_nodes::generate_curves::GenerateCurvesNode"),
("graphene_std::dehaze::DehazeNode", "graphene_raster_nodes::dehaze::DehazeNode"),
("graphene_std::filter::BlurNode", "graphene_raster_nodes::filter::BlurNode"),
(
"graphene_std::image_color_palette::ImageColorPaletteNode",
"graphene_raster_nodes::image_color_palette::ImageColorPaletteNode",
),
("graphene_std::raster::SampleImageNode", "graphene_raster_nodes::std_nodes::SampleImageNode"),
("graphene_std::raster::CombineChannelsNode", "graphene_raster_nodes::std_nodes::CombineChannelsNode"),
("graphene_std::raster::MaskNode", "graphene_raster_nodes::std_nodes::MaskNode"),
("graphene_std::raster::ExtendImageToBoundsNode", "graphene_raster_nodes::std_nodes::ExtendImageToBoundsNode"),
("graphene_std::raster::EmptyImageNode", "graphene_raster_nodes::std_nodes::EmptyImageNode"),
("graphene_std::raster::ImageValueNode", "graphene_raster_nodes::std_nodes::ImageValueNode"),
("graphene_std::raster::NoisePatternNode", "graphene_raster_nodes::std_nodes::NoisePatternNode"),
("graphene_std::raster::MandelbrotNode", "graphene_raster_nodes::std_nodes::MandelbrotNode"),
NodeReplacement {
node: graphene_std::raster_nodes::generate_curves::generate_curves::IDENTIFIER,
aliases: &["graphene_core::raster::adjustments::GenerateCurvesNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::dehaze::dehaze::IDENTIFIER,
aliases: &["graphene_std::dehaze::DehazeNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::filter::blur::IDENTIFIER,
aliases: &["graphene_std::filter::BlurNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::image_color_palette::image_color_palette::IDENTIFIER,
aliases: &["graphene_std::image_color_palette::ImageColorPaletteNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::sample_image::IDENTIFIER,
aliases: &["graphene_std::raster::SampleImageNode", "graphene_std::raster::SampleNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::combine_channels::IDENTIFIER,
aliases: &["graphene_std::raster::CombineChannelsNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::mask::IDENTIFIER,
aliases: &["graphene_std::raster::MaskNode", "graphene_std::raster::MaskImageNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::extend_image_to_bounds::IDENTIFIER,
aliases: &["graphene_std::raster::ExtendImageToBoundsNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::empty_image::IDENTIFIER,
aliases: &["graphene_std::raster::EmptyImageNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::image_value::IDENTIFIER,
aliases: &["graphene_std::raster::ImageValueNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::noise_pattern::IDENTIFIER,
aliases: &["graphene_std::raster::NoisePatternNode"],
},
NodeReplacement {
node: graphene_std::raster_nodes::std_nodes::mandelbrot::IDENTIFIER,
aliases: &["graphene_std::raster::MandelbrotNode"],
},
// text
("graphene_core::text::TextGeneratorNode", "graphene_core::text::TextNode"),
NodeReplacement {
node: graphene_std::text::text::IDENTIFIER,
aliases: &["graphene_core::text::TextGeneratorNode"],
},
// transform
("graphene_core::transform::SetTransformNode", "graphene_core::transform_nodes::ReplaceTransformNode"),
("graphene_core::transform::ReplaceTransformNode", "graphene_core::transform_nodes::ReplaceTransformNode"),
("graphene_core::transform::TransformNode", "graphene_core::transform_nodes::TransformNode"),
("graphene_core::transform::BoundlessFootprintNode", "graphene_core::transform_nodes::BoundlessFootprintNode"),
("graphene_core::transform::FreezeRealTimeNode", "graphene_core::transform_nodes::FreezeRealTimeNode"),
NodeReplacement {
node: graphene_std::transform_nodes::replace_transform::IDENTIFIER,
aliases: &["graphene_core::transform::SetTransformNode", "graphene_core::transform::ReplaceTransformNode"],
},
NodeReplacement {
node: graphene_std::transform_nodes::transform::IDENTIFIER,
aliases: &["graphene_core::transform::TransformNode"],
},
NodeReplacement {
node: graphene_std::transform_nodes::boundless_footprint::IDENTIFIER,
aliases: &["graphene_core::transform::BoundlessFootprintNode"],
},
NodeReplacement {
node: graphene_std::transform_nodes::freeze_real_time::IDENTIFIER,
aliases: &["graphene_core::transform::FreezeRealTimeNode"],
},
// ???
("graphene_core::vector::SplinesFromPointsNode", "graphene_core::vector::SplineNode"),
("graphene_core::vector::generator_nodes::EllipseGenerator", "graphene_core::vector::generator_nodes::EllipseNode"),
("graphene_core::vector::generator_nodes::LineGenerator", "graphene_core::vector::generator_nodes::LineNode"),
("graphene_core::vector::generator_nodes::RectangleGenerator", "graphene_core::vector::generator_nodes::RectangleNode"),
(
"graphene_core::vector::generator_nodes::RegularPolygonGenerator",
"graphene_core::vector::generator_nodes::RegularPolygonNode",
),
("graphene_core::vector::generator_nodes::StarGenerator", "graphene_core::vector::generator_nodes::StarNode"),
("graphene_std::executor::BlendGpuImageNode", "graphene_std::gpu_nodes::BlendGpuImageNode"),
("graphene_std::raster::SampleNode", "graphene_std::raster::SampleImageNode"),
("graphene_core::transform::CullNode", "graphene_core::ops::IdentityNode"),
("graphene_std::raster::MaskImageNode", "graphene_std::raster::MaskNode"),
("graphene_core::vector::FlattenVectorElementsNode", "graphene_core::vector::FlattenPathNode"),
("graphene_std::vector::BooleanOperationNode", "graphene_path_bool::BooleanOperationNode"),
NodeReplacement {
node: graphene_std::vector::spline::IDENTIFIER,
aliases: &["graphene_core::vector::SplinesFromPointsNode"],
},
NodeReplacement {
node: graphene_std::vector::generator_nodes::ellipse::IDENTIFIER,
aliases: &["graphene_core::vector::generator_nodes::EllipseGenerator"],
},
NodeReplacement {
node: graphene_std::vector::generator_nodes::line::IDENTIFIER,
aliases: &["graphene_core::vector::generator_nodes::LineGenerator"],
},
NodeReplacement {
node: graphene_std::vector::generator_nodes::rectangle::IDENTIFIER,
aliases: &["graphene_core::vector::generator_nodes::RectangleGenerator"],
},
NodeReplacement {
node: graphene_std::vector::generator_nodes::regular_polygon::IDENTIFIER,
aliases: &["graphene_core::vector::generator_nodes::RegularPolygonGenerator"],
},
NodeReplacement {
node: graphene_std::vector::generator_nodes::star::IDENTIFIER,
aliases: &["graphene_core::vector::generator_nodes::StarGenerator"],
},
NodeReplacement {
node: graphene_std::ops::identity::IDENTIFIER,
aliases: &["graphene_core::transform::CullNode"],
},
NodeReplacement {
node: graphene_std::vector::flatten_path::IDENTIFIER,
aliases: &["graphene_core::vector::FlattenVectorElementsNode"],
},
NodeReplacement {
node: graphene_std::path_bool::boolean_operation::IDENTIFIER,
aliases: &["graphene_std::vector::BooleanOperationNode"],
},
// brush
("graphene_std::brush::BrushStampGeneratorNode", "graphene_brush::brush::BrushStampGeneratorNode"),
("graphene_std::brush::BlitNode", "graphene_brush::brush::BlitNode"),
("graphene_std::brush::BrushNode", "graphene_brush::brush::BrushNode"),
NodeReplacement {
node: graphene_std::brush::brush::brush_stamp_generator::IDENTIFIER,
aliases: &["graphene_std::brush::BrushStampGeneratorNode"],
},
NodeReplacement {
node: graphene_std::brush::brush::blit::IDENTIFIER,
aliases: &["graphene_std::brush::BlitNode"],
},
NodeReplacement {
node: graphene_std::brush::brush::brush::IDENTIFIER,
aliases: &["graphene_std::brush::BrushNode"],
},
];
const REPLACEMENTS: &[(&str, &str)] = &[];
pub fn document_migration_string_preprocessing(document_serialized_content: String) -> String {
TEXT_REPLACEMENTS
.iter()
@ -195,17 +480,26 @@ pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_
let network = document.network_interface.document_network().clone();
// Apply string replacements to each node
// Apply string and node replacements to each node
let mut replacements = HashMap::<&str, ProtoNodeIdentifier>::new();
Iterator::chain(
NODE_REPLACEMENTS.iter().flat_map(|NodeReplacement { node, aliases }| aliases.iter().map(|old| (*old, node.clone()))),
REPLACEMENTS.iter().map(|(old, new)| (*old, ProtoNodeIdentifier::new(new))),
)
.for_each(|(old, new)| {
if replacements.insert(old, new).is_some() {
panic!("Duplicate old name `{old}`");
}
});
for (node_id, node, network_path) in network.recursive_nodes() {
if let DocumentNodeImplementation::ProtoNode(protonode_id) = &node.implementation {
for (old, new) in REPLACEMENTS {
let node_path_without_type_args = protonode_id.name.split('<').next();
let node_path_without_type_args = protonode_id.name.split('<').next();
if let Some(new) = node_path_without_type_args.and_then(|node_path| replacements.get(node_path)) {
let mut default_template = NodeTemplate::default();
default_template.document_node.implementation = DocumentNodeImplementation::ProtoNode(new.to_string().into());
if node_path_without_type_args == Some(old) {
document.network_interface.replace_implementation(node_id, &network_path, &mut default_template);
document.network_interface.set_manual_compostion(node_id, &network_path, Some(graph_craft::Type::Generic("T".into())));
}
default_template.document_node.implementation = DocumentNodeImplementation::ProtoNode(new.clone());
document.network_interface.replace_implementation(node_id, &network_path, &mut default_template);
document.network_interface.set_manual_compostion(node_id, &network_path, Some(graph_craft::Type::Generic("T".into())));
}
}
}
@ -691,3 +985,20 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
Some(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_no_duplicate_node_replacements() {
let mut hashmap = HashMap::<ProtoNodeIdentifier, u32>::new();
NODE_REPLACEMENTS.iter().for_each(|node| {
*hashmap.entry(node.node.clone()).or_default() += 1;
});
let duplicates = hashmap.iter().filter(|(_, count)| **count > 1).map(|(node, _)| &node.name).collect::<Vec<_>>();
if duplicates.len() > 0 {
panic!("Duplicate entries in `NODE_REPLACEMENTS`: {:?}", duplicates);
}
}
}

View file

@ -490,7 +490,7 @@ async fn to_artboard<Data: Into<GraphicGroupTable> + 'n>(
}
#[node_macro::node(category(""))]
async fn append_artboard(_ctx: impl Ctx, mut artboards: ArtboardGroupTable, artboard: Artboard, node_path: Vec<NodeId>) -> ArtboardGroupTable {
pub async fn append_artboard(_ctx: impl Ctx, mut artboards: ArtboardGroupTable, artboard: Artboard, node_path: Vec<NodeId>) -> ArtboardGroupTable {
// Get the penultimate element of the node path, or None if the path is too short.
// This is used to get the ID of the user-facing "Artboard" node (which encapsulates this internal "Append Artboard" node).
let encapsulating_node_id = node_path.get(node_path.len().wrapping_sub(2)).copied();