Preserve placeholder connections when resolving to multiple clips - #277
Preserve placeholder connections when resolving to multiple clips#277jakubjezek001 wants to merge 9 commits into
Conversation
When multiple clips are loaded without explicit "Input"/"Output" nodes, fall back to the last connectable node to preserve upstream/downstream connections. Also improve docstring formatting.
|
closed by accindent |
There was a problem hiding this comment.
Pull request overview
Improves Nuke Loader Placeholder behavior when it resolves to multiple clips by attempting to preserve the original node-graph connections (upstream/downstream) instead of leaving all loaded nodes disconnected.
Changes:
- Updates
_set_loaded_connectionsto add fallback logic whenget_group_io_nodes()can’t find explicitly named “Input”/“Output” nodes for multi-clip loads. - Adjusts the method docstring/comment formatting for clarity.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…olved-connected-nodes
moonyuet
left a comment
There was a problem hiding this comment.
Works well for the load placeholder with clip loader
https://github.com/user-attachments/assets/aa609a5c-7613-4eb4-bce5-e86ef6556be6
It also works with load geo(input and output nodes).
Recording.2026-06-26.200953.mp4
|
What's the status here? @jakubjezek001 |
…olved-connected-nodes
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…olved-connected-nodes
| if input_node is None: | ||
| input_candidates = [ | ||
| n for n in connectable if n.maxInputs() > 0] | ||
| input_node = ( | ||
| input_candidates[0] if input_candidates else None) | ||
|
|
||
| if output_node is None: | ||
| output_candidates = [ | ||
| n for n in connectable if n.maxOutputs() > 0] | ||
| output_node = ( | ||
| output_candidates[0] if output_candidates else None) |
There was a problem hiding this comment.
If you load a group that has say 5 nodes, and they are connected in one stream, like A-B-C-D-E. The input would be A, the output would be E. Right?
In this logic here, the input and output would be A - because it allows more inputs and outputs than zero and has the first name (sorted). I'm still confused by this logic.
It should really be that we prefer nodes that are at the start of the graph, e.g. have no inputs but do have outputs. (so they must be somewhere at the start of it) The same goes for outputs, it must be a node that preferably has no output connections (within the loaded nodes), allows to have outputs and if there are two nodes for which this is true prefer the one that does have input connections. So that if for whatever reason you load a group that has a separate floating node C, we'd still take the one at the end of a stream of nodes:
A-B
C
☝️ pick B?
Or what's the reasoning you're after @jakubjezek001 ?
There was a problem hiding this comment.
before it was not connecting any node by mistake. So if placeholder was connected and was resolving in multiple loadable containers - before it would not connect anything at all. But now after the fix it will connect at least single loaded node.
Try it and will see.
There was a problem hiding this comment.
It may work consistently for a single node, but not for a graph of nodes as I'm trying to explain. If we're solving just the single node case - then the logic should consider it's only a single node. Then no need for the sorting and iterating. Then just:
if len(nodes) == 1:
node = nodes[0]
if node.maxInputs() > 0:
input_node = node
if node.maxOutputs() > 0:
output_node = node
Right?
There was a problem hiding this comment.
Do you mean this?
| if input_node is None: | |
| input_candidates = [ | |
| n for n in connectable if n.maxInputs() > 0] | |
| input_node = ( | |
| input_candidates[0] if input_candidates else None) | |
| if output_node is None: | |
| output_candidates = [ | |
| n for n in connectable if n.maxOutputs() > 0] | |
| output_node = ( | |
| output_candidates[0] if output_candidates else None) | |
| if len(connectable) == 1: | |
| node = connectable[0] | |
| if node.maxInputs() > 0: | |
| input_node = node | |
| if node.maxOutputs() > 0: | |
| output_node = node | |
There was a problem hiding this comment.
The way I understand this can load and handle a group of nodes. These nodes, can have their own connections between themselves already.
Like:
A-B-C.
The logic we're defining here is to describe which of these nodes can act as input or output to the rest of the graph
as we've them loaded. Like, what are the inputs and outputs of this group. The B here should never be a viable candidate (or at least, it's the most unlikely one), since it's neither an input or an output of that graph because it is already connected to other inputs and outputs within the group node itself.
maxInputs and maxOutputs if I understand correctly define how many input connections and output connections the nodes may have. Which for B will both be >0 because it has both an input and output connection.
The most viable candidate in this example is:
- A is the input node, because it's at the start of the group (has no incoming connections)
- C is the output node, because it's at the end of the group (has no outgoing connections)
So it's really:
group_nodes.sort(lambda node: node.name()) # sort by something consistent
input_node = None
output_node = None
for node in group_nodes:
if input_node is None:
if has_inputs_within_group(node):
continue
if not can_have_inputs(node):
input_node = node
if output_node is None:
if has_outputs_within_group(node):
continue
if not can_have_outputs(node):
continue
output_node = nodeThis is a stupidly overly simplified example.
Or I am completely misinterpreting what we're solving?
There was a problem hiding this comment.
It seems to me there is misunderstanding here. If I understand it correctly this is solution for reconnecting a nodes which are resolved from placeholder. If the placeholder is connected to upstream connection Input or downstream connection Output then we need to replicate it at first found resolved node, and this is usually single node with single or multiple connectable Inputs or singular Output. There might be multiple of those nodes, since the placehoders rules might be lose and multiple containers might be loaded in the scene - but only single one can be replicating its related placehoder's connection.
There was a problem hiding this comment.
Or are we @BigRoy talking about the same thing but in different way?
There was a problem hiding this comment.
- There is a single placeholder node, from which we transfer the input and output connections to the "loaded group"
- We transfer these to the "assumed input" and "assumed output" node in the loaded group.
This number 2) is what we're computing here. From all the nodes we loaded (of a single load!) give me which node represents the first input node and which the output node so that we can transfer the connections from step 1).
The loaded group of nodes, may have any amount of nodes and connections.
From that loaded group - we must search for the node that we THINK is the input and the output; and that's where I'm describing there's a flaw in the logic.
We must exclude nodes that in the loaded group already have internal connections, because in a loaded group that has:
- A-B-C
Then B must never be what we assume is the input or output node.
We may trigger this across multiple loaded groups, yes. But the logic as I understand it here is about finding the input and output of the group of ONE loaded container.
|
What's the state for this? I tested with #277 (comment), it still works fine. It doesn't work for the loader when we are using the viewer as output. (So did the initial commit.) |
…olved-connected-nodes
…olved-connected-nodes
Changelog Description
When a Loader Placeholder resolves to multiple clips without explicit "Input"/"Output" nodes, the system now preserves the original upstream and downstream connections by falling back to the last connectable node. Previously, placeholders resolving to multiple items would disconnect from the node graph, leaving all loaded clips floating. This fix ensures the first resolved item maintains the placeholder's original connections while additional items remain unconnected as intended.
The change addresses the root cause where
get_group_io_nodes()returnsNonefor both input/output when multiple clips lack specifically named IO nodes. The fallback logic identifies connectable nodes (those with available inputs or outputs) and uses the last one to maintain graph connectivity.Additional info
The fix modifies the
_set_loaded_connectionsmethod in the placeholder loader to include fallback logic when IO nodes are unavailable:maxInputs() > 0ormaxOutputs() > 0Testing notes:
Dependency
Close #109
AY-7741