mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Reshape the node catalog: rename the list access nodes, split Text to Vector, reinstate Upload Texture as a proto node, and delete the vestigial debug nodes
This commit is contained in:
committed by
Dennis Kobert
parent
1bac1d694f
commit
ead622b969
@@ -2758,7 +2758,7 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
|
||||
let solidify_stroke_definition = document_node_definitions::resolve_proto_node_type(graphene_std::vector::solidify_stroke::IDENTIFIER).expect("Solidify Stroke node should exist");
|
||||
let index_elements_definition = document_node_definitions::resolve_proto_node_type(graphene_std::graphic::index_elements::IDENTIFIER).expect("Index Elements node should exist");
|
||||
let item_at_index_definition = document_node_definitions::resolve_proto_node_type(graphene_std::graphic::item_at_index::IDENTIFIER).expect("Item at Index node should exist");
|
||||
|
||||
let mut resulting_layers: Vec<NodeId> = Vec::new();
|
||||
|
||||
@@ -2791,7 +2791,7 @@ impl DocumentMessageHandler {
|
||||
if has_fill && has_stroke {
|
||||
let (existing_index, new_index) = (0_f64, 1_f64);
|
||||
|
||||
let existing_index_template = index_elements_definition.node_template_input_override([None, Some(NodeInput::value(TaggedValue::F64(existing_index), false))]);
|
||||
let existing_index_template = item_at_index_definition.node_template_input_override([None, Some(NodeInput::value(TaggedValue::F64(existing_index), false))]);
|
||||
let existing_index_id = NodeId::new();
|
||||
self.network_interface.insert_node(existing_index_id, existing_index_template, &[]);
|
||||
self.network_interface.move_node_to_chain_start(&existing_index_id, layer, &[], false);
|
||||
@@ -2813,7 +2813,7 @@ impl DocumentMessageHandler {
|
||||
self.network_interface.set_display_name(&new_layer_id, original_name, &[]);
|
||||
}
|
||||
|
||||
let new_index_template = index_elements_definition.node_template_input_override([None, Some(NodeInput::value(TaggedValue::F64(new_index), false))]);
|
||||
let new_index_template = item_at_index_definition.node_template_input_override([None, Some(NodeInput::value(TaggedValue::F64(new_index), false))]);
|
||||
let new_index_id = NodeId::new();
|
||||
self.network_interface.insert_node(new_index_id, new_index_template, &[]);
|
||||
self.network_interface.move_node_to_chain_start(&new_index_id, new_layer, &[], false);
|
||||
|
||||
@@ -488,7 +488,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
},
|
||||
// 1: Count Elements (number of subpaths)
|
||||
DocumentNode {
|
||||
implementation: DocumentNodeImplementation::ProtoNode(vector::count_elements::IDENTIFIER),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(vector::list_length::IDENTIFIER),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1289,78 +1289,6 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
),
|
||||
properties: None,
|
||||
},
|
||||
#[cfg(feature = "gpu")]
|
||||
DocumentNodeDefinition {
|
||||
identifier: "Upload Texture",
|
||||
category: "Debug",
|
||||
node_template: NodeTemplate {
|
||||
document_node: DocumentNode {
|
||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
||||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::import(concrete!(List<Raster<CPU>>), 0), NodeInput::scope(platform_application_io::wgpu_executor::IDENTIFIER)],
|
||||
call_argument: generic!(T),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(wgpu_executor::texture_conversion::upload_texture::IDENTIFIER),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
call_argument: generic!(T),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(memo::memoize::IDENTIFIER),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![NodeInput::type_default(descriptor!(List<Raster<CPU>>), true)],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
output_names: vec!["Texture".to_string()],
|
||||
network_metadata: Some(NodeNetworkMetadata {
|
||||
persistent_metadata: NodeNetworkPersistentMetadata {
|
||||
node_metadata: [
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-7, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(7, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed("TODO"),
|
||||
properties: None,
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
identifier: "Extract",
|
||||
category: "",
|
||||
@@ -1407,13 +1335,13 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
// Node 1: extract_element at index 0, extracts the whole match as a bare String (drops the item's start/end/name attributes since the unwrapped String can't carry them)
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::F64(0.), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::extract_element::IDENTIFIER),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::item_at_index::IDENTIFIER),
|
||||
..Default::default()
|
||||
},
|
||||
// Node 2: omit_element at index 0, returns the capture group items as a List<String>, preserving each item's start/end/name attributes
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::F64(0.), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::omit_element::IDENTIFIER),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::remove_at_index::IDENTIFIER),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
|
||||
@@ -93,10 +93,6 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
node: graphene_std::animation::animation_time::IDENTIFIER,
|
||||
aliases: &["graphene_core::animation::AnimationTimeNode"],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::debug::clone::IDENTIFIER,
|
||||
aliases: &["graphene_core::ops::CloneNode"],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::extract_xy::extract_xy::IDENTIFIER,
|
||||
aliases: &["graphene_core::ops::ExtractXyNode"],
|
||||
@@ -112,6 +108,14 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
"graphene_core::transform_nodes::FreezeRealTimeNode",
|
||||
"graphene_core::vector::SubpathSegmentLengthsNode",
|
||||
"core_types::vector::SubpathSegmentLengthsNode",
|
||||
// The deleted debug Option trio degrades to a passthrough of its single input (audit resolution 8)
|
||||
"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::debug::UnwrapOptionNode",
|
||||
],
|
||||
},
|
||||
NodeReplacement {
|
||||
@@ -126,18 +130,6 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
node: graphene_std::animation::real_time::IDENTIFIER,
|
||||
aliases: &["graphene_core::animation::RealTimeNode"],
|
||||
},
|
||||
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_option::IDENTIFIER,
|
||||
aliases: &["graphene_core::ops::UnwrapNode", "graphene_core::debug::UnwrapNode"],
|
||||
},
|
||||
// ================================
|
||||
// graphic
|
||||
// ================================
|
||||
@@ -167,13 +159,19 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
aliases: &["graphene_core::graphic::FlattenVectorNode", "graphene_core::graphic_element::FlattenVectorNode"],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::graphic::index_elements::IDENTIFIER,
|
||||
node: graphene_std::graphic::item_at_index::IDENTIFIER,
|
||||
aliases: &[
|
||||
"graphene_core::graphic_element::IndexNode",
|
||||
"graphene_core::graphic::IndexNode",
|
||||
"graphene_core::graphic::IndexElementsNode",
|
||||
"graphic_nodes::graphic::IndexElementsNode",
|
||||
"graphic_nodes::graphic::ExtractElementNode",
|
||||
],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::graphic::remove_at_index::IDENTIFIER,
|
||||
aliases: &["graphic_nodes::graphic::OmitElementNode"],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::graphic::legacy_layer_extend::IDENTIFIER,
|
||||
aliases: &[
|
||||
@@ -777,7 +775,7 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
aliases: &["graphene_core::vector::ClosePathNode"],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::vector::count_elements::IDENTIFIER,
|
||||
node: graphene_std::vector::list_length::IDENTIFIER,
|
||||
aliases: &["graphene_core::vector::CountElementsNode"],
|
||||
},
|
||||
NodeReplacement {
|
||||
@@ -1876,6 +1874,25 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 5), old_inputs[3].clone(), network_path);
|
||||
}
|
||||
|
||||
// The Text to Vector node's runtime `separate_glyphs` toggle became the dedicated "Text to Vector Glyphs" node, leaving Text to Vector as a plain
|
||||
// string-to-compound-path converter. A 2-input Text to Vector is the old toggled shape: a `true` toggle routes to Text to Vector Glyphs, otherwise
|
||||
// the node stays Text to Vector; either way the toggle input is dropped and the string wire is preserved.
|
||||
if reference == DefinitionIdentifier::ProtoNode(graphene_std::text::text_to_vector::IDENTIFIER) && inputs_count == 2 {
|
||||
let separate_glyphs = matches!(node.inputs.get(1).and_then(|input| input.as_value()), Some(TaggedValue::Bool(true)));
|
||||
let target = if separate_glyphs {
|
||||
graphene_std::text::text_to_vector_glyphs::IDENTIFIER
|
||||
} else {
|
||||
graphene_std::text::text_to_vector::IDENTIFIER
|
||||
};
|
||||
|
||||
let mut node_template = resolve_proto_node_type(target)?.default_node_template();
|
||||
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
|
||||
document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
|
||||
if let Some(string_input) = node.inputs.first() {
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 0), string_input.clone(), network_path);
|
||||
}
|
||||
}
|
||||
|
||||
// Upgrade Text node to include line height and character spacing, which were previously hardcoded to 1, from https://github.com/GraphiteEditor/Graphite/pull/2016
|
||||
if reference == DefinitionIdentifier::ProtoNode(ProtoNodeIdentifier::new("graphene_std::text::TextNode")) && inputs_count == 8 {
|
||||
let mut template: NodeTemplate = legacy_text_node_template()?;
|
||||
@@ -2406,14 +2423,14 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
return None;
|
||||
};
|
||||
|
||||
// Create Count Elements node: counts content `List` items → N
|
||||
let Some(count_elements_def) = resolve_document_node_type(&DefinitionIdentifier::ProtoNode(graphene_std::vector::count_elements::IDENTIFIER)) else {
|
||||
log::error!("Could not get count_elements node from definition when upgrading morph");
|
||||
// Create List Length node: counts content `List` items → N
|
||||
let Some(list_length_def) = resolve_document_node_type(&DefinitionIdentifier::ProtoNode(graphene_std::vector::list_length::IDENTIFIER)) else {
|
||||
log::error!("Could not get list_length node from definition when upgrading morph");
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
||||
return None;
|
||||
};
|
||||
let count_elements_template = count_elements_def.default_node_template();
|
||||
let count_elements_id = NodeId::new();
|
||||
let list_length_template = list_length_def.default_node_template();
|
||||
let list_length_id = NodeId::new();
|
||||
|
||||
// Create Subtract node: N → N-1
|
||||
let Some(subtract_def) = resolve_document_node_type(&DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::subtract::IDENTIFIER)) else {
|
||||
@@ -2435,10 +2452,10 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
let divide_id = NodeId::new();
|
||||
|
||||
// Insert and position nodes
|
||||
document.network_interface.insert_node(count_elements_id, count_elements_template, network_path);
|
||||
document.network_interface.insert_node(list_length_id, list_length_template, network_path);
|
||||
document
|
||||
.network_interface
|
||||
.shift_absolute_node_position(&count_elements_id, morph_position + IVec2::new(-21, 2), network_path);
|
||||
.shift_absolute_node_position(&list_length_id, morph_position + IVec2::new(-21, 2), network_path);
|
||||
|
||||
document.network_interface.insert_node(subtract_id, subtract_template, network_path);
|
||||
document.network_interface.shift_absolute_node_position(&subtract_id, morph_position + IVec2::new(-14, 2), network_path);
|
||||
@@ -2447,12 +2464,12 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
document.network_interface.shift_absolute_node_position(÷_id, morph_position + IVec2::new(-7, 1), network_path);
|
||||
|
||||
// Wire: content source → Count Elements input 0
|
||||
document.network_interface.set_input(&InputConnector::node(count_elements_id, 0), old_inputs[0].clone(), network_path);
|
||||
document.network_interface.set_input(&InputConnector::node(list_length_id, 0), old_inputs[0].clone(), network_path);
|
||||
|
||||
// Wire: Count Elements output → Subtract input 0 (minuend)
|
||||
document
|
||||
.network_interface
|
||||
.set_input(&InputConnector::node(subtract_id, 0), NodeInput::node(count_elements_id, 0), network_path);
|
||||
.set_input(&InputConnector::node(subtract_id, 0), NodeInput::node(list_length_id, 0), network_path);
|
||||
|
||||
// Wire: old progression → Divide input 0 (numerator)
|
||||
document.network_interface.set_input(&InputConnector::node(divide_id, 0), old_inputs[1].clone(), network_path);
|
||||
@@ -2745,6 +2762,31 @@ fn migrate_removed_catalog_definitions(node_id: &NodeId, node: &DocumentNode, ne
|
||||
}
|
||||
}
|
||||
|
||||
// The removed Attach Attribute node (merged into Write Attribute per audit resolution 6) degrades to a passthrough of its
|
||||
// content: its eager whole-list source input cannot be mechanically rewired as Write Attribute's lazy per-item value producer.
|
||||
if let Some(DefinitionIdentifier::ProtoNode(identifier)) = document.network_interface.reference(node_id, network_path)
|
||||
&& identifier.as_str().ends_with("::AttachAttributeNode")
|
||||
{
|
||||
let mut node_template = resolve_proto_node_type(graphene_std::ops::passthrough::IDENTIFIER)?.default_node_template();
|
||||
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
|
||||
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
|
||||
if let Some(content) = old_inputs.first() {
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 0), content.clone(), network_path);
|
||||
}
|
||||
}
|
||||
|
||||
// The Upload Texture node's old wrapper-network form maps onto its proto node form, which draws the executor from scope
|
||||
if let Some(DefinitionIdentifier::Network(name)) = document.network_interface.reference(node_id, network_path)
|
||||
&& name == "Upload Texture"
|
||||
{
|
||||
let mut node_template = resolve_proto_node_type(graphene_std::platform_application_io::upload_texture::IDENTIFIER)?.default_node_template();
|
||||
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
|
||||
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
|
||||
if let Some(content) = old_inputs.first() {
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 0), content.clone(), network_path);
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
@@ -2752,6 +2794,13 @@ fn migrate_removed_catalog_definitions(node_id: &NodeId, node: &DocumentNode, ne
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// The removed-definition blocks above abort silently via `?` if their swap target ever leaves the catalog
|
||||
#[test]
|
||||
fn removed_definition_swap_targets_resolve() {
|
||||
assert!(resolve_proto_node_type(graphene_std::ops::passthrough::IDENTIFIER).is_some());
|
||||
assert!(resolve_proto_node_type(graphene_std::platform_application_io::upload_texture::IDENTIFIER).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_written_attribute_no_longer_resets_the_layer_definitions() {
|
||||
// The node resolves natively again, so a document carrying it keeps
|
||||
|
||||
Reference in New Issue
Block a user