diff --git a/js/use_everywhere_apply.js b/js/use_everywhere_apply.js index 8a1413e..d984a53 100644 --- a/js/use_everywhere_apply.js +++ b/js/use_everywhere_apply.js @@ -12,11 +12,17 @@ function _convert_to_links(ue, added_links, removed_links) { const input_node_id = st.node.id; const input_node = get_real_node(input_node_id, ue.graph); const input_index = st.input_index; - if (input_node.inputs[input_index].link) { // why would this be happening? + if (input_node.inputs?.[input_index].link) { // why would this be happening? const llink = ue.graph.links[input_node.inputs[input_index].link] if (llink) removed_links.push( {...llink} ) } - const new_link = output_node.connect(output_index, input_node, input_index); + var new_link + if (input_node.io_node) { + new_link = input_node.io_node.slots[input_index].connect(output_node.outputs[output_index], output_node); + } else { + new_link = output_node.connect(output_index, input_node, input_index); + } + if (!new_link) console.error("Failed to connect nodes: " + `${output_node_id}[${output_index}] -> ` + diff --git a/js/use_everywhere_classes.js b/js/use_everywhere_classes.js index df1104a..983fe5b 100644 --- a/js/use_everywhere_classes.js +++ b/js/use_everywhere_classes.js @@ -8,7 +8,9 @@ import { Logger, node_is_live, get_real_node, get_connection } from "./use_every export function display_name(node) { if (node?.title) return node.title; if (node?.type) return node.type; - if (node?.properties['Node name for S&R']) return node.properties['Node name for S&R']; + if (node?.properties?.['Node name for S&R']) return node.properties['Node name for S&R']; + if (node?.id==-20) return "subgraph output node"; + if (node?.id==-10) return "subgraph input node"; return "un-nameable node"; } @@ -96,7 +98,7 @@ class UseEverywhere { if (this.output[0] == node.id) return false; if (this.restrict_to && !this.restrict_to.includes(node.id)) return false; const input_label = input.label || input.localized_name || input.name; - const node_label = node.title ? node.title : (node.properties['Node name for S&R'] ? node.properties['Node name for S&R'] : node.type); + const node_label = display_name(node) // node.title ? node.title : (node.properties['Node name for S&R'] ? node.properties['Node name for S&R'] : node.type); if (this.title_regex) { if ( this.title_regex.regex.test(node_label) == this.title_regex.invert ) return false; } @@ -129,8 +131,14 @@ class UseEverywhere { return true; } note_sending_to(node, input) { - const input_index = node.inputs.findIndex((n) => n.name==input.name); - this.sending_to.push({node:node, input:input, input_index:input_index}) + var input_index + if (node.inputs) input_index = node.inputs.findIndex((n) => n.name==input.name); + else if (node.slots) input_index = node.slots.findIndex((n) => n.name==input.name); + if (input_index===undefined) { + Logger.log_problem(`UseEverywhere.note_sending_to could not find input index for node ${node.id} input ${input.name}`); + } else { + this.sending_to.push({node:node, input:input, input_index:input_index}) + } } describe_sending(){ var description = " Linked to:"; diff --git a/js/use_everywhere_graph_analysis.js b/js/use_everywhere_graph_analysis.js index b2339cb..fb541f1 100644 --- a/js/use_everywhere_graph_analysis.js +++ b/js/use_everywhere_graph_analysis.js @@ -63,6 +63,18 @@ class GraphAnalyser extends Pausable { analyse_graph(graph, ignore_pause) { if (this.paused() && !ignore_pause) return null + /* work around known bug in ComfyUI front end that doesn't clean up the linkIds + https://github.com/Comfy-Org/ComfyUI_frontend/issues/5673#issuecomment-3314310014 + */ + if (graph.inputNode) { + graph.inputNode.slots.forEach((slot)=>{ + slot.linkIds = slot.linkIds.filter((lid)=>{ return graph.links[lid] !== undefined }) + }) + graph.outputNode.slots.forEach((slot)=>{ + slot.linkIds = slot.linkIds.filter((lid)=>{ return graph.links[lid] !== undefined }) + }) + } + this.ambiguity_messages = []; const treat_bypassed_as_live = settingsCache.getSettingValue("Use Everywhere.Options.connect_to_bypassed") || this.connect_to_bypassed const live_nodes = graph.nodes.filter((node) => node_is_live(node, treat_bypassed_as_live)) @@ -85,6 +97,12 @@ class GraphAnalyser extends Pausable { } }) + if (graph.outputNode) { + graph.outputNode.slots.filter((slot)=>(slot.linkIds.length==0)).forEach((slot,index)=>{ + connectable.push({node:graph.outputNode, input:slot, index}); + } + )} + // see if we can connect them const links_added = new Set(); connectable.forEach(({node, input, index}) => { diff --git a/js/use_everywhere_subgraph_utils.js b/js/use_everywhere_subgraph_utils.js index cde3e78..3a8d593 100644 --- a/js/use_everywhere_subgraph_utils.js +++ b/js/use_everywhere_subgraph_utils.js @@ -7,7 +7,9 @@ export function visible_graph() { return app.canvas.graph } export function in_visible_graph(node) { try { - return node.graph.id == app.canvas.graph.id + if (node.graph) return node.graph.id == app.canvas.graph.id + else if (node.subgraph) return node.subgraph.id == app.canvas.graph.id + else Logger.log_problem(`in_visible_graph: ${node.id} has no graph or subgraph`) } catch (e) { Logger.log_error(e) return false @@ -79,21 +81,29 @@ function fix_subgraph_widgets(node) { } ue_callbacks.register_allnode_callback('afterConfigureGraph', fix_subgraph_widgets, true ) -class WrappedInputNode { - constructor(subgraph_input_node) { - this.subgraph_input_node = subgraph_input_node; - this.graph = subgraph_input_node.subgraph; +class WrappedIONode { + constructor(io_node) { + this.io_node = io_node; + this.graph = io_node.subgraph; } connect(output_index, input_node, input_index) { this.graph.last_link_id += 1 - this.graph.links[this.graph.last_link_id] = new LLink(this.graph.last_link_id, this.subgraph_input_node.slots[output_index].type, -10, output_index, input_node.id, input_index) + this.graph.links[this.graph.last_link_id] = new LLink(this.graph.last_link_id, this.io_node.slots[output_index].type, -10, output_index, input_node.id, input_index) input_node.inputs[input_index].link = this.graph.last_link_id; - this.subgraph_input_node.slots[output_index].linkIds.push(this.graph.last_link_id) + this.io_node.slots[output_index].linkIds.push(this.graph.last_link_id) return this.graph.links[this.graph.last_link_id] } + getConnectionPos(is_input, slot_number) { + if (is_input) { + return [...this.io_node.slots[slot_number].pos] + } else { + Logger.log_problem("WrappedIONode.getConnectionPos called for output - not supported"); + } + } + } -export function wrap_input(subgraph_input_node) { - return new WrappedInputNode(subgraph_input_node); +export function wrap_input(io_node) { + return new WrappedIONode(io_node); } \ No newline at end of file diff --git a/js/use_everywhere_ui.js b/js/use_everywhere_ui.js index 341f752..bbd3d3b 100644 --- a/js/use_everywhere_ui.js +++ b/js/use_everywhere_ui.js @@ -187,7 +187,7 @@ export class LinkRenderController extends Pausable { Logger.log_error(e); } } else { - Logger.log_problem(`In disable_all_connected_widgets, couldn't find downstream node ${uel.downstream}`) + if (uel.downstream >= 0) Logger.log_problem(`In disable_all_connected_widgets, couldn't find downstream node ${uel.downstream}`) } }) } else { @@ -409,7 +409,7 @@ export class LinkRenderController extends Pausable { } } catch (e) { - Logger.log_problem(`Couldn't render UE link ${ue_connection}. That's ok if something just got deleted.`); + Logger.log_error(e, `Couldn't render UE link ${ue_connection}. That's ok if something just got deleted.`); } } diff --git a/js/use_everywhere_utilities.js b/js/use_everywhere_utilities.js index c160406..9520e26 100644 --- a/js/use_everywhere_utilities.js +++ b/js/use_everywhere_utilities.js @@ -46,6 +46,7 @@ export function get_real_node(node_id, graph) { if (!graph) graph = visible_graph() const nid = node_id.toString(); if (nid==-10) return wrap_input(graph.inputNode); // special case for subgraph input + if (nid==-20) return wrap_input(graph.outputNode); // special case for subgraph input return graph._nodes_by_id[nid]; }