Add a Connect Cells option to the 'Grid' node (#4374)

Add a Connect Cells option to the Grid node
This commit is contained in:
Keavon Chambers
2026-07-26 12:15:14 -07:00
committed by Dennis Kobert
parent dd416f8663
commit 5a8fac33fd
3 changed files with 101 additions and 86 deletions

View File

@@ -1901,7 +1901,9 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
let columns = number_widget(ParameterWidgetsInfo::new(node_id, ColumnsInput::INDEX, true, context), NumberInput::default().min(1.));
let rows = number_widget(ParameterWidgetsInfo::new(node_id, RowsInput::INDEX, true, context), NumberInput::default().min(1.));
widgets.extend([LayoutGroup::row(columns), LayoutGroup::row(rows)]);
let connect_cells = bool_widget(ParameterWidgetsInfo::new(node_id, ConnectCellsInput::INDEX, true, context), CheckboxInput::default());
widgets.extend([LayoutGroup::row(columns), LayoutGroup::row(rows), LayoutGroup::row(connect_cells)]);
widgets
}

View File

@@ -2307,33 +2307,36 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
}
}
// Make the "Grid" node, if its input of index 3 is a DVec2 for "angles" instead of a u32 for the "columns" input that now succeeds "angles", move the angle to index 5 (after "columns" and "rows")
// Upgrade the "Grid" node from its six-input layout to the current seven-input layout (which adds a trailing
// "connect_cells" toggle, defaulting to the connected mesh that older grids produced). Legacy documents also placed
// "angles" at index 3 instead of index 5 (after "columns" and "rows"), so we reorder those. Either way, "connect_cells"
// is left at its default from the new node template.
if reference == DefinitionIdentifier::ProtoNode(graphene_std::vector::generator_nodes::grid::IDENTIFIER) && inputs_count == 6 {
let node_definition = resolve_document_node_type(&reference)?;
let mut new_node_template = node_definition.default_node_template();
let mut current_node_template = document.network_interface.create_node_template(node_id, network_path)?;
let mut new_node_template = resolve_document_node_type(&reference)?.default_node_template();
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut new_node_template)?;
let index_3_value = old_inputs.get(3).cloned();
let mut upgraded = false;
// The two six-input layouts differ only in where the DVec2 "angles" and the u32 "columns"/"rows" sit:
// Legacy: [primary, grid_type, spacing, angles (DVec2), columns (u32), rows (u32)]
// Modern: [primary, grid_type, spacing, columns (u32), rows (u32), angles (DVec2)]
// So a DVec2 "angles" at index 3, or a u32 "rows" at index 5, marks the legacy order. Checking both slots classifies
// correctly even when one of them is a wired or imported connection rather than a literal value.
let index_3_is_angles = matches!(old_inputs.get(3), Some(NodeInput::Value { tagged_value, .. }) if matches!(**tagged_value, TaggedValue::DVec2(_)));
let index_5_is_rows = matches!(old_inputs.get(5), Some(NodeInput::Value { tagged_value, .. }) if matches!(**tagged_value, TaggedValue::U32(_)));
let legacy_angles_layout = index_3_is_angles || index_5_is_rows;
if let Some(NodeInput::Value { tagged_value, exposed: _ }) = index_3_value
&& matches!(*tagged_value, TaggedValue::DVec2(_))
{
// Move index 3 to the end
if legacy_angles_layout {
// Old order: [primary, grid_type, spacing, angles, columns, rows]. Move "angles" from index 3 to index 5.
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[4].clone(), network_path);
document.network_interface.set_input(&InputConnector::node(*node_id, 4), old_inputs[5].clone(), network_path);
document.network_interface.set_input(&InputConnector::node(*node_id, 5), old_inputs[3].clone(), network_path);
upgraded = true;
}
if !upgraded {
let _ = document.network_interface.replace_inputs(node_id, network_path, &mut current_node_template);
} else {
// Modern six-input order. Carry each input over to the same index.
for (index, input) in old_inputs.iter().take(6).enumerate() {
document.network_interface.set_input(&InputConnector::node(*node_id, index), input.clone(), network_path);
}
}
}