Update to 7.8
7.8
This commit is contained in:
@@ -8,12 +8,39 @@
|
||||
|
||||
Check out [Image Picker](https://github.com/chrisgoringe/cg-image-filter) for another way to make some workflows smoother.
|
||||
|
||||
# What is Anything Everywhere?
|
||||
|
||||
The `Anything Everywhere` node takes one or more inputs and sends the data to other nodes that need it.
|
||||
You can connect as many inputs to an `Anything Everywhere` node as you like, and there are a range of ways
|
||||
to control where the data will be sent.
|
||||
|
||||
Here's the standard ComfyUI template modified to use `AnythingEverywhere`
|
||||
|
||||
|workflow|output image you can drop into Comfy|
|
||||
|-|-|
|
||||
|||
|
||||
|
||||
The `MODEL`, `CLIP`, and `VAE` are automatically broadcast to all the places they are needed.
|
||||
|
||||
Doesn't make much difference in this simple case, but with complex workflows it really does.
|
||||
This is what the default wan 2.2 s2v video workflow looks like:
|
||||
|
||||
|before|after|
|
||||
|-|-|
|
||||
|||
|
||||
|
||||
# Getting started
|
||||
|
||||
Drop [this workflow](docs/UE_example.json) into Comfy, and take a look at how it works.
|
||||
|
||||
# Common Questions
|
||||
|
||||
## How do I get positive and negative conditionings to work?
|
||||
|
||||
Connect both to a single UE node, and then rename the inputs. See [here](https://github.com/chrisgoringe/cg-use-everywhere/issues/317#issuecomment-3663225670).
|
||||
|
||||
Or use node broadcasting, as in the [example workflow](docs/UE_example.json)
|
||||
|
||||
## Why doesn't it work with reroutes / primitives?
|
||||
|
||||
Nodes which dynamically work out their data type are a real problem that isn't worth the complexity to fix. See [here](https://github.com/chrisgoringe/cg-use-everywhere/tree/main#primitives-and-reroutes) for more info.
|
||||
@@ -24,6 +51,12 @@ Yes. See Combo Clone node [here](https://github.com/chrisgoringe/cg-use-everywhe
|
||||
|
||||
# Recent Changes
|
||||
|
||||
## 7.8
|
||||
|
||||
- Added regex match of outputs to the repeated types options
|
||||
- Fixed issues with the new ComfyUI autogrow inputs
|
||||
- Fixed API export to save with real links [389](https://github.com/chrisgoringe/cg-use-everywhere/issues/389)
|
||||
|
||||
## 7.7
|
||||
|
||||
- Added "Apply to unrepeated output" options
|
||||
@@ -37,7 +70,7 @@ Yes. See Combo Clone node [here](https://github.com/chrisgoringe/cg-use-everywhe
|
||||
- Added "Send to Any" option in restrictions
|
||||
|
||||
<details>
|
||||
<summary>Older changes since 7.0</summary>
|
||||
<summary>Older changes</summary>
|
||||
|
||||
## 7.5
|
||||
|
||||
@@ -85,27 +118,6 @@ Bugfixes:
|
||||
|
||||
</details>
|
||||
|
||||
# What is Anything Everywhere?
|
||||
|
||||
The `Anything Everywhere` node takes one or more inputs and sends the data to other nodes that need it.
|
||||
You can connect as many inputs to an `Anything Everywhere` node as you like, and there are a range of ways
|
||||
to control where the data will be sent.
|
||||
|
||||
Here's the standard ComfyUI template modified to use `AnythingEverywhere`
|
||||
|
||||
|workflow|output image you can drop into Comfy|
|
||||
|-|-|
|
||||
|||
|
||||
|
||||
The `MODEL`, `CLIP`, and `VAE` are automatically broadcast to all the places they are needed.
|
||||
|
||||
Doesn't make much difference in this simple case, but with complex workflows it really does.
|
||||
This is what the default wan 2.2 s2v video workflow looks like:
|
||||
|
||||
|before|after|
|
||||
|-|-|
|
||||
|||
|
||||
|
||||
# Any node broadcasting
|
||||
|
||||
<details>
|
||||
@@ -153,6 +165,9 @@ either the name of the input slot on the target node, or the name of the target
|
||||
The `match start` and `match end` options require that the input names match from the start (or end) for the full length of the shorter:
|
||||
so you can match `seed` to `seed` or `noise_seed` by naming the `Anything Everywhere` input `seed` and selecting `Match end of input names`.
|
||||
|
||||
You can also give the output a name which is a regex, and select `Regex match of input names` - so if your output is named `prompt|text` it
|
||||
will match inputs named `prompt` or `text`.
|
||||
|
||||
If `Apply to Unrepeated` is set to `Yes`, the `Repeated Types` rule will be applied to all outputs, whether or not they are repeated.
|
||||
|
||||
`Send To Any`(default 'no') can be used to allow this node to send data to inputs with the `Any` type.
|
||||
@@ -214,13 +229,13 @@ Animation takes quite a lot of processing, so don't use it unless you really nee
|
||||
Any node that is capable of broadcasting data (a UE node, or another node to which broadcasting has been added) is marked with a circle in the top left hand corner.
|
||||
|
||||
If the circle is green, the node has no additional restrictions on where data will be sent;
|
||||
if it is red, it has one or more restrictions (which you can see by hovering your mouse over it, or by editing restrictions
|
||||
if it is yellow, it has one or more restrictions (which you can see by hovering your mouse over it, or by editing restrictions
|
||||
with the option on the right click menu, or by double clicking the node).
|
||||
|
||||
If the node is actually sending data, the circle (red or green) is bold; if the node is capable of sending but is not actually making
|
||||
If the node is actually sending data, the circle (red or yellow) is bold; if the node is capable of sending but is not actually making
|
||||
and connections, it is muted.
|
||||
|
||||

|
||||

|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -242,6 +257,16 @@ here `merged` can broadcast, but isn't, `x` can broadcast and is, and `y` is set
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Conflicts show up in red</summary>
|
||||
|
||||
If two (or more) broadcasters with the same priority could send to the same input, the input will be marked with a red cross.
|
||||
If UE links are being shown all possible links are shown in red. Here two model loaders are broadcasting...
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
# Special Case Nodes
|
||||
|
||||
<details>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
from .use_everywhere import SeedEverywhere, AnythingEverywhere, AnythingSomewhere, AnythingEverywhereTriplet, SimpleString, ComboClone, AnythingEverywherePrompts
|
||||
|
||||
UE_VERSION = "7.7.1"
|
||||
UE_VERSION = "7.8"
|
||||
WEB_DIRECTORY = "./js"
|
||||
__all__ = [ "WEB_DIRECTORY"]
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -32,6 +32,7 @@ export function language_changed(is_now, was_before) {
|
||||
i18n("Match start of input names"),
|
||||
i18n("Match end of input names"),
|
||||
i18n("Inputs matches target node name"),
|
||||
i18n("Regex match of input names"),
|
||||
]
|
||||
|
||||
GROUP_RESTRICTION_OPTIONS = [
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
export const VERSION = "7.7.1"
|
||||
export const VERSION = "7.8"
|
||||
|
||||
class Shared {
|
||||
constructor() {
|
||||
|
||||
@@ -275,6 +275,18 @@ app.registerExtension({
|
||||
return await shared.graphAnalyser.call_function_with_modified_graph( original_graphToPrompt )
|
||||
}
|
||||
|
||||
/*
|
||||
Find the Export as API function and wrap it
|
||||
*/
|
||||
const export_workflow_api = app.extensionManager.command.commands.find((c)=>(c.id=='Comfy.ExportWorkflowAPI'))
|
||||
if (export_workflow_api) {
|
||||
const original = export_workflow_api.function
|
||||
export_workflow_api.function = async function () {
|
||||
await shared.graphAnalyser.call_function_with_modified_graph( ()=>{ original.apply(this, arguments)} )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Modifications to the canvas
|
||||
- listen for set-graph to mark the link list as out of date when we open or close a subgraph
|
||||
|
||||
@@ -38,6 +38,20 @@ function _convert_to_links(ue, added_links, removed_links) {
|
||||
});
|
||||
}
|
||||
|
||||
export function remove_comfyDynamic_autogrow(graph) {
|
||||
graph.nodes.filter((node)=>(node.comfyDynamic?.autogrow)).forEach((node)=>{
|
||||
node.__ue_removed_comfyDynamic_autogrow = node.comfyDynamic.autogrow
|
||||
node.comfyDynamic.autogrow = {}
|
||||
})
|
||||
const restorer = function() {
|
||||
graph.nodes.filter((node)=>(node.__ue_removed_comfyDynamic_autogrow)).forEach((node)=>{
|
||||
node.comfyDynamic.autogrow = node.__ue_removed_comfyDynamic_autogrow
|
||||
node.__ue_removed_comfyDynamic_autogrow = undefined
|
||||
})
|
||||
}
|
||||
return { restorer:restorer }
|
||||
}
|
||||
|
||||
export function convert_to_links(ues, control_node, graph) {
|
||||
if (control_node) {
|
||||
if (!graph) graph = control_node.graph
|
||||
|
||||
@@ -152,10 +152,15 @@ function validity_errors(params) {
|
||||
}
|
||||
|
||||
export class Ambiguity {
|
||||
constructor( data ) {
|
||||
Object.assign(this, data)
|
||||
this.matches = []
|
||||
}
|
||||
/*
|
||||
name : display_name of node
|
||||
id : node.id
|
||||
input : input.name
|
||||
graph : the graph the node is in
|
||||
matches : [
|
||||
{
|
||||
type : m[i].controller.type,
|
||||
@@ -237,16 +242,17 @@ export class UseEverywhereList {
|
||||
if (matches.length>1) {
|
||||
matches.sort((a,b) => b.priority-a.priority);
|
||||
if(matches[0].priority == matches[1].priority) {
|
||||
const msg = new Ambiguity()
|
||||
Object.assign(msg, { name:display_name(node), id:node.id, input:input.name, matches:[] })
|
||||
const msg = new Ambiguity( { name:display_name(node), id:node.id, input:input.name, graph:(node.graph || node.subgraph) } )
|
||||
|
||||
matches.filter((m)=>(m.priority == matches[0].priority)).forEach((m)=>{
|
||||
var ni = node.inputs?.findIndex((i)=>(i==input))
|
||||
if (ni==undefined) ni = node.allSlots?.findIndex((i)=>(i==input))
|
||||
msg.matches.push( {
|
||||
type : m.controller.type,
|
||||
id : m.controller.id,
|
||||
index : m.control_node_input_index,
|
||||
node : node,
|
||||
node_index : node.inputs.findIndex((i)=>(i==input))
|
||||
node_index : ni
|
||||
})
|
||||
})
|
||||
|
||||
@@ -363,6 +369,14 @@ export class UseEverywhereList {
|
||||
return (target_name == input_name)
|
||||
}
|
||||
}
|
||||
if (rule == 4) { // 4 input as regex matches input
|
||||
additional_requirement = (target_input, _) => {
|
||||
const re = new RegExp(input_name)
|
||||
const target_name = target_input.label || target_input.name
|
||||
return re.exec(target_name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.add_ue(node, i, connection.type, [connection.link.origin_id.toString(), connection.link.origin_slot], input_regex, additional_requirement);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UseEverywhereList } from "./use_everywhere_classes.js";
|
||||
import { node_is_live, is_connected, is_UEnode, Logger, Pausable, node_can_broadcast } from "./use_everywhere_utilities.js";
|
||||
import { convert_to_links } from "./use_everywhere_apply.js";
|
||||
import { convert_to_links, remove_comfyDynamic_autogrow } from "./use_everywhere_apply.js";
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { settingsCache } from "./use_everywhere_cache.js";
|
||||
import { is_connectable } from "./use_everywhere_settings.js";
|
||||
@@ -23,6 +23,7 @@ class GraphAnalyser extends Pausable {
|
||||
Logger.log_problem(`modify_graph called but no ues could be obtained for ${graph.id}`)
|
||||
console.trace()
|
||||
}
|
||||
this.mods.push( remove_comfyDynamic_autogrow(graph) )
|
||||
const modifications = convert_to_links( ues, null, graph )
|
||||
this.mods.push( modifications );
|
||||
if (!graph.extra) graph.extra = {}
|
||||
|
||||
+18
-5
@@ -194,13 +194,26 @@ export class LinkRenderController extends Pausable {
|
||||
|
||||
highlight_subgraph_node_connections(subgraph, ctx) {
|
||||
if (!settingsCache.getSettingValue('Use Everywhere.Graphics.highlight')) return;
|
||||
this.ue_list.all_connected_inputs(subgraph.outputNode).forEach((ue_connection)=>{
|
||||
const pos2 = subgraph?.outputNode?.slots[ue_connection.input_index]?.pos;
|
||||
const node = subgraph?.outputNode
|
||||
const ue_connections = this.ue_list.all_connected_inputs(subgraph.outputNode)
|
||||
|
||||
ue_connections.forEach((ue_connection)=>{
|
||||
const pos2 = node.slots[ue_connection.input_index]?.pos;
|
||||
if (pos2) {
|
||||
drawcircle(ctx, pos2, CONNECTED_1, 5, "first", {strokeStyle:LGraphCanvas.link_type_colors[ue_connection.type]})
|
||||
drawcircle(ctx, pos2, CONNECTED_2, 4, "last")
|
||||
}
|
||||
})
|
||||
|
||||
shared.graphAnalyser.ambiguities.filter((ambiguity)=>(ambiguity.id==-20)).forEach((ambiguity)=>{
|
||||
const index = ambiguity.matches[0]?.node_index
|
||||
const pos2 = node.slots[index]?.pos
|
||||
if (pos2) {
|
||||
drawcross(ctx, pos2, AMBIGUITY, 7)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
highlight_ue_connections(node, ctx) {
|
||||
@@ -336,13 +349,13 @@ export class LinkRenderController extends Pausable {
|
||||
|
||||
shared.graphAnalyser.ambiguities.forEach((ambiguity)=>{
|
||||
ambiguity.matches.forEach((m)=>{
|
||||
if (app.canvas.node_over == m.node) {
|
||||
if (app.canvas.node_over == m.node || ambiguity.id==-20 && ambiguity.graph.outputNode?.isPointerOver) {
|
||||
this._render_ue_link(
|
||||
{
|
||||
graph : m.node.graph,
|
||||
graph : ambiguity.graph,
|
||||
sending_to : m.node,
|
||||
input_index : m.node_index,
|
||||
control_node : m.node.graph.getNodeById(m.id),
|
||||
control_node : ambiguity.graph.getNodeById(m.id),
|
||||
control_node_input_index : m.index,
|
||||
type : m.type,
|
||||
}, ctx, 0, "#F00")
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "cg-use-everywhere"
|
||||
description = "A set of nodes that allow data to be 'broadcast' to some or all unconnected inputs. Greatly reduces link spaghetti."
|
||||
version = "7.7.1"
|
||||
version = "7.8"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = [
|
||||
"comfyui-frontend-package>=1.25.0"
|
||||
|
||||
Reference in New Issue
Block a user