Fix more flaws with 'Transform' node rad-to-deg migration; make 'Tangent on Path' also use degrees by default

This commit is contained in:
Keavon Chambers 2025-09-18 14:05:35 -07:00
parent 3fe7c477e9
commit 7e3ab78ea4
12 changed files with 69 additions and 46 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1341,6 +1341,13 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
persistent_metadata: DocumentNodePersistentMetadata {
display_name: "Transform".to_string(),
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(7, 0)),
input_metadata: vec![
("Value", "TODO").into(),
("Translation", "TODO").into(),
("Rotation", "TODO").into(),
("Scale", "TODO").into(),
("Skew", "TODO").into(),
],
..Default::default()
},
..Default::default()

View File

@ -1002,10 +1002,7 @@ impl NodeNetworkInterface {
.outward_wires(network_path)
.and_then(|outward_wires| outward_wires.get(output_connector))
.cloned()
.unwrap_or_else(|| {
log::error!("Could not get {output_connector:?} in outward wires");
Vec::new()
})
.unwrap_or_default()
.iter()
.map(|input| match input {
InputConnector::Node { node_id, input_index } => {
@ -6470,7 +6467,7 @@ pub struct NodeNetworkTransientMetadata {
pub stack_dependents: TransientMetadata<HashMap<NodeId, LayerOwner>>,
/// Cache for the bounding box around all nodes in node graph space.
pub all_nodes_bounding_box: TransientMetadata<[DVec2; 2]>,
/// Cache bounding box for all "groups of nodes", which will be used to prevent overlapping nodes
// /// Cache bounding box for all "groups of nodes", which will be used to prevent overlapping nodes
// node_group_bounding_box: Vec<(Subpath<ManipulatorGroupId>, Vec<Nodes>)>,
/// Cache for all outward wire connections
pub outward_wires: TransientMetadata<HashMap<OutputConnector, Vec<InputConnector>>>,

View File

@ -784,6 +784,22 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
.set_input(&InputConnector::node(*node_id, 1), NodeInput::value(TaggedValue::Bool(true), false), network_path);
}
// Upgrade the 'Tangent on Path' node to include a boolean input for whether the output should be in radians, which was previously the only option but is now not the default
if (reference == "Tangent on Path") && inputs_count == 4 {
let mut node_template = resolve_document_node_type(reference)?.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)?;
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
document.network_interface.set_input(&InputConnector::node(*node_id, 2), old_inputs[2].clone(), network_path);
document.network_interface.set_input(&InputConnector::node(*node_id, 3), old_inputs[3].clone(), network_path);
document
.network_interface
.set_input(&InputConnector::node(*node_id, 4), NodeInput::value(TaggedValue::Bool(true), false), network_path);
}
// Upgrade the Modulo node to include a boolean input for whether the output should be always positive, which was previously not an option
if reference == "Modulo" && inputs_count == 2 {
let mut node_template = resolve_document_node_type(reference)?.default_node_template();
@ -1054,6 +1070,30 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
// Migrate the Transform node to use degrees instead of radians
if reference == "Transform" && node.inputs.get(6).is_none() {
let mut node_template = resolve_document_node_type("Transform")?.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)?;
// Value
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
// Translation
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
// Rotation
document.network_interface.set_input(&InputConnector::node(*node_id, 2), old_inputs[2].clone(), network_path);
// Scale
document.network_interface.set_input(&InputConnector::node(*node_id, 3), old_inputs[3].clone(), network_path);
// Skew
document.network_interface.set_input(&InputConnector::node(*node_id, 4), old_inputs[4].clone(), network_path);
// Origin Offset
document
.network_interface
.set_input(&InputConnector::node(*node_id, 5), NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false), network_path);
// Scale Appearance
document
.network_interface
.set_input(&InputConnector::node(*node_id, 6), NodeInput::value(TaggedValue::Bool(true), false), network_path);
// Migrate rotation from radians to degrees
match node.inputs.get(2)? {
NodeInput::Value { tagged_value, exposed } => {
@ -1099,31 +1139,6 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
let new_input = NodeInput::value(TaggedValue::DVec2(new_value), *exposed);
document.network_interface.set_input(&InputConnector::node(*node_id, 4), new_input, network_path);
}
if document
.network_interface
.node_metadata(node_id, network_path)
.map(|x| x.persistent_metadata.input_metadata.len() > 5)
.unwrap_or_default()
{
// Remove the possible existence of the old "Pivot" hidden value input that was removed in #2730
let nested_transform_network = [network_path, &[*node_id]].concat();
if node.inputs.get(5).is_some() {
document.network_interface.remove_import(5, &nested_transform_network);
}
// Add the Origin Offset parameter as a hidden input, which will be given actual functionality in the future but is currently used as a marker to detect not-yet-upgraded Transform nodes
document
.network_interface
.add_import(TaggedValue::DVec2(DVec2::ZERO), false, 5, "Origin Offset", "", &nested_transform_network);
document.network_interface.set_input_override(node_id, 5, Some("hidden".to_string()), network_path); // Hide it while we're not yet using it
// Add the Scale Appearance parameter as a hidden input, which will be given actual functionality in the future but is currently used as a marker to detect not-yet-upgraded Transform nodes
document
.network_interface
.add_import(TaggedValue::Bool(true), false, 6, "Scale Appearance", "", &nested_transform_network);
document.network_interface.set_input_override(node_id, 6, Some("hidden".to_string()), network_path); // Hide it while we're not yet using it
}
}
// Add context features to nodes that don't have them (fine-grained context caching migration)

View File

@ -1211,10 +1211,10 @@ async fn position_on_path(
let euclidian = !parameterized_distance;
let mut bezpaths = content
.into_iter()
.iter()
.flat_map(|vector| {
let transform = vector.transform;
vector.element.stroke_bezpath_iter().map(|bezpath| (bezpath, transform)).collect::<Vec<_>>()
let transform = *vector.transform;
vector.element.stroke_bezpath_iter().map(move |bezpath| (bezpath, transform))
})
.collect::<Vec<_>>();
let bezpath_count = bezpaths.len() as f64;
@ -1246,14 +1246,16 @@ async fn tangent_on_path(
reverse: bool,
/// Traverse the path using each segment's Bézier curve parameterization instead of the Euclidean distance. Faster to compute but doesn't respect actual distances.
parameterized_distance: bool,
/// Whether the resulting angle should be given in as radians instead of degrees.
radians: bool,
) -> f64 {
let euclidian = !parameterized_distance;
let mut bezpaths = content
.into_iter()
.iter()
.flat_map(|vector| {
let transform = vector.transform;
vector.element.stroke_bezpath_iter().map(|bezpath| (bezpath, transform)).collect::<Vec<_>>()
let transform = *vector.transform;
vector.element.stroke_bezpath_iter().map(move |bezpath| (bezpath, transform))
})
.collect::<Vec<_>>();
let bezpath_count = bezpaths.len() as f64;
@ -1261,7 +1263,7 @@ async fn tangent_on_path(
let progress = if reverse { bezpath_count - progress } else { progress };
let index = if progress >= bezpath_count { (bezpath_count - 1.) as usize } else { progress as usize };
bezpaths.get_mut(index).map_or(0., |(bezpath, transform)| {
let angle = bezpaths.get_mut(index).map_or(0., |(bezpath, transform)| {
let t = if progress == bezpath_count { 1. } else { progress.fract() };
let t_value = |t: f64| if euclidian { TValue::Euclidean(t) } else { TValue::Parametric(t) };
@ -1277,7 +1279,9 @@ async fn tangent_on_path(
}
-tangent.angle_to(if reverse { -DVec2::X } else { DVec2::X })
})
});
if radians { angle } else { angle.to_degrees() }
}
#[node_macro::node(category(""), path(graphene_core::vector))]