@@ -24,6 +24,12 @@ Yes. See Combo Clone node [here](https://github.com/chrisgoringe/cg-use-everywhe
|
||||
|
||||
# Recent Changes
|
||||
|
||||
## 7.7
|
||||
|
||||
- Added "Apply to unrepeated output" options
|
||||
- Cleaned up restrictions dialog
|
||||
- Internal refactoring to conform to ComfyUI changes
|
||||
|
||||
## 7.6
|
||||
|
||||
- Added visual indicators to subgraph nodes
|
||||
@@ -31,7 +37,7 @@ Yes. See Combo Clone node [here](https://github.com/chrisgoringe/cg-use-everywhe
|
||||
- Added "Send to Any" option in restrictions
|
||||
|
||||
<details>
|
||||
<summary>Changes since 7.0</summary>
|
||||
<summary>Older changes since 7.0</summary>
|
||||
|
||||
## 7.5
|
||||
|
||||
@@ -140,10 +146,6 @@ The node will only send data to another node if the regex matches the receiving
|
||||
|
||||
The Group and Colour restrictions will constrain the node to only send to nodes in (or not in) the same group, and of the same (or different) colour.
|
||||
|
||||
If you select multiple restrictions, all must be satisfied for the node to send.
|
||||
|
||||
If any restrictions are applied, the `Anything Everywhere` node gets a green circle in the top left hand corner, and a tooltip if you hover the mouse over it (as long as Show Links is not set to None).
|
||||
|
||||
`Repeated Types` determines behaviour when more than one input of the same type is connected to an `Anything Everywhere` node.
|
||||
In this case an additional constraint is used to disambiguate which inputs match
|
||||
by comparing the name of the input slot on the `Anything Everywhere` node with
|
||||
@@ -151,8 +153,16 @@ 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`.
|
||||
|
||||
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.
|
||||
|
||||
`Priority` is used to resolve conflicts between multiple sending nodes. It has a default value (which generally follows the rule that the more restrictive the rules, the higher the priority), but you can override that value.
|
||||
|
||||
If you select multiple restrictions, all must be satisfied for the node to send.
|
||||
|
||||
If any restrictions are applied, the `Anything Everywhere` node gets a green circle in the top left hand corner, and a tooltip if you hover the mouse over it (as long as Show Links is not set to None).
|
||||
|
||||
You can rename input slots by right-clicking on the input dot - but you can't rename widget inputs - this is a limitation imposed by ComfyUI ([discussion](https://github.com/Comfy-Org/ComfyUI_frontend/issues/3654)). The work-around is to rename the target node (or use multiple `Anything Everywhere` nodes with other constraints, especially color matching).
|
||||
|
||||
</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.6.2"
|
||||
UE_VERSION = "7.7"
|
||||
WEB_DIRECTORY = "./js"
|
||||
__all__ = [ "WEB_DIRECTORY"]
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 85 KiB |
+1
-1
@@ -1,4 +1,4 @@
|
||||
export const VERSION = "7.6.2"
|
||||
export const VERSION = "7.7"
|
||||
|
||||
class Shared {
|
||||
constructor() {
|
||||
|
||||
@@ -32,32 +32,49 @@
|
||||
background-color: rgb(45 24 24 / 80%);
|
||||
}
|
||||
|
||||
.ue_properties_table {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ue_editor_header {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background-color: rgb(45 24 24 / 80%);
|
||||
background-size: 100% 14px;
|
||||
background-image: repeating-linear-gradient(0deg, #636363, black 1px, rgb(45 24 24 / 80%) 1px, rgb(45 24 24 / 80%) 2px);
|
||||
padding-top: 4px;
|
||||
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background-color: rgb(45 24 24 / 80%);
|
||||
background-size: 100% 14px;
|
||||
background-image: repeating-linear-gradient(0deg, #636363, black 1px, rgb(45 24 24 / 80%) 1px, rgb(45 24 24 / 80%) 2px);
|
||||
padding-top: 4px;
|
||||
border-bottom: thin dashed #ddd;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.ue_editor_body {
|
||||
padding: 0px 4px;
|
||||
.ue_properties_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.ue_editor_body th {
|
||||
|
||||
.break_below {
|
||||
border-bottom: thin dashed #ddd;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
span.ue_properties_title {
|
||||
text-align: right;
|
||||
flex-grow: 1;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.ue_editor_body th::after {
|
||||
|
||||
.ue_properties_title::after {
|
||||
content: ':';
|
||||
}
|
||||
|
||||
.ue_editor_body td {
|
||||
select {
|
||||
width: 100%;
|
||||
}
|
||||
.ue_properties_cell {
|
||||
flex-grow: 0;
|
||||
width: 250px
|
||||
}
|
||||
|
||||
|
||||
.ue_editor_footer {
|
||||
margin: 8px;
|
||||
border: thin solid white;
|
||||
@@ -67,7 +84,7 @@
|
||||
|
||||
.regex_input_container {
|
||||
display: flex;
|
||||
width: 250px;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
input {
|
||||
flex-grow: 1;
|
||||
|
||||
@@ -71,6 +71,7 @@ const DEFAULT_PROPERTIES = {
|
||||
group_regex_invert : false,
|
||||
priority : undefined,
|
||||
repeated_type_rule : 0,
|
||||
apply_to_unrepeated : 0,
|
||||
string_to_combo : 0,
|
||||
send_to_any : 0
|
||||
}
|
||||
|
||||
@@ -23,16 +23,19 @@ export function edit_restrictions(a,b,c,d, node) { // a,b,c,d parameters are ign
|
||||
}
|
||||
|
||||
function add_row(table, header) {
|
||||
const row = document.createElement('tr')
|
||||
const row = document.createElement('div')
|
||||
row.className = 'ue_properties_row'
|
||||
table.appendChild(row)
|
||||
const header_elem = document.createElement('th')
|
||||
const header_elem = document.createElement('span')
|
||||
header_elem.className = 'ue_properties_title'
|
||||
header_elem.innerText = header
|
||||
row.appendChild(header_elem)
|
||||
return row
|
||||
}
|
||||
|
||||
function add_cell(row, cell) {
|
||||
const td = document.createElement('td')
|
||||
const td = document.createElement('span')
|
||||
td.className = 'ue_properties_cell'
|
||||
row.appendChild(td)
|
||||
td.appendChild(cell)
|
||||
}
|
||||
@@ -52,7 +55,8 @@ function changed(node, property, value) {
|
||||
}
|
||||
|
||||
function create_editor_html(node) {
|
||||
const table = document.createElement('table')
|
||||
const table = document.createElement('div')
|
||||
table.className = 'ue_properties_table'
|
||||
|
||||
for (var i=0; i<=2; i++) {
|
||||
const name = REGEXES[i]
|
||||
@@ -74,6 +78,8 @@ function create_editor_html(node) {
|
||||
create_element('input', contents, {type:'text', value:node.properties.ue_properties[`${name}_regex`] || ''}).
|
||||
addEventListener('input', (e)=>{ changed(node, `${name}_regex`, e.target.value)})
|
||||
|
||||
if (i==2) { row.classList.add('break_below') }
|
||||
|
||||
add_cell(row,contents)
|
||||
}
|
||||
|
||||
@@ -86,24 +92,32 @@ function create_editor_html(node) {
|
||||
const col_select = document.createElement('select')
|
||||
add_cell(col_row,col_select)
|
||||
add_select_options(node, col_select, COLOR_RESTRICTION_OPTIONS, `color_restricted` )
|
||||
col_row.classList.add('break_below')
|
||||
|
||||
const repeated_type_row = add_row(table, i18n("Repeated Types"))
|
||||
const repeated_type_select = document.createElement('select')
|
||||
add_cell(repeated_type_row,repeated_type_select)
|
||||
add_select_options(node, repeated_type_select, REPEATED_TYPE_OPTIONS, `repeated_type_rule`)
|
||||
|
||||
const apply_to_unrepeated_row = add_row(table, i18n("Apply to Unrepeated"))
|
||||
const apply_to_unrepeated_select = document.createElement('select')
|
||||
add_cell(apply_to_unrepeated_row, apply_to_unrepeated_select)
|
||||
add_select_options(node, apply_to_unrepeated_select, ["no", "yes"], `apply_to_unrepeated`)
|
||||
apply_to_unrepeated_row.classList.add('break_below')
|
||||
|
||||
if (node.inputs.find((i)=>(i.type=="STRING"))) {
|
||||
const send_to_combos_row = add_row(table, i18n("String to Combos"))
|
||||
const send_to_combos_select = document.createElement('select')
|
||||
add_cell(send_to_combos_row, send_to_combos_select)
|
||||
add_select_options(node, send_to_combos_select, ["no", "yes"], `string_to_combo`)
|
||||
send_to_combos_row.classList.add('break_below')
|
||||
}
|
||||
|
||||
const send_to_any_row = add_row(table, i18n("Send to Any"))
|
||||
const send_to_any_select = document.createElement('select')
|
||||
add_cell(send_to_any_row, send_to_any_select)
|
||||
add_select_options(node, send_to_any_select, ["no", "yes"], `send_to_any`)
|
||||
send_to_any_row.classList.add('break_below')
|
||||
|
||||
const priority_row = add_row(table, i18n("Priority"))
|
||||
const priority_edit = document.createElement("input")
|
||||
@@ -116,6 +130,7 @@ function create_editor_html(node) {
|
||||
priority_edit.id = 'priority_value'
|
||||
if (!node.properties.ue_properties.priority) priority_edit.style.opacity = 0.5
|
||||
add_cell(priority_row,priority_edit)
|
||||
priority_row.classList.add('break_below')
|
||||
|
||||
return table
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ function _convert_graph_to_links(graph, ues, control_node_id) {
|
||||
const links_out_of_subgraph = new Set()
|
||||
const problem_links = new Set()
|
||||
|
||||
const new_subgraph_node = graph._nodes_by_id[graph.last_node_id];
|
||||
const new_subgraph_node = graph.getNodeById(graph.last_node_id);
|
||||
const new_subgraph = new_subgraph_node?.subgraph;
|
||||
|
||||
added_links.forEach(added_link => {
|
||||
@@ -96,7 +96,7 @@ function _convert_graph_to_links(graph, ues, control_node_id) {
|
||||
|
||||
links_out_of_subgraph.forEach((llink)=>{
|
||||
const control_node_id = llink.control_node?.id
|
||||
const control_node_in_graph = graph._nodes_by_id[control_node_id]
|
||||
const control_node_in_graph = graph.getNodeById(control_node_id)
|
||||
if (control_node_in_graph) {
|
||||
// the control node is outside, so we should disconnect anything else that is connected to the same output of the subgraph node
|
||||
new_subgraph_node.outputs[new_subgraph.links[llink.id].target_slot].links.forEach((link_id)=>{
|
||||
@@ -121,7 +121,7 @@ function _convert_graph_to_links(graph, ues, control_node_id) {
|
||||
}
|
||||
|
||||
removed_links.forEach(llink => {
|
||||
graph._nodes_by_id[llink.origin_id].connect(llink.origin_slot, graph._nodes_by_id[llink.target_id], llink.target_slot)
|
||||
graph.getNodeById(llink.origin_id).connect(llink.origin_slot, graph.getNodeById(llink.target_id), llink.target_slot)
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -334,7 +334,7 @@ export class UseEverywhereList {
|
||||
if (connection.link && check_if_able_to_broadcast(node,i)) {
|
||||
const input_regex = undefined
|
||||
var additional_requirement = null
|
||||
if (duplicated_broadcasted_types.has(connection.type)) {
|
||||
if (duplicated_broadcasted_types.has(connection.type) || node.properties.ue_properties.apply_to_unrepeated) {
|
||||
const input_name = possible.label || possible.name
|
||||
const rule = node.properties.ue_properties?.repeated_type_rule || 0
|
||||
if (rule == 0) { // 0 is exact match of input name
|
||||
|
||||
@@ -40,7 +40,7 @@ export function fix_new_subgraph_node(node) {
|
||||
subgraph.inputNode.slots.forEach((slot, i)=>{
|
||||
slot.linkIds.forEach((lid) => {
|
||||
const link = subgraph.links[lid]
|
||||
const target = subgraph._nodes_by_id[link.target_id]
|
||||
const target = subgraph.getNodeById(link.target_id)
|
||||
const slot_name = target.inputs[link.target_slot].name
|
||||
const ue_connectable = target.properties.ue_properties.widget_ue_connectable[slot_name]
|
||||
if (ue_connectable) {
|
||||
@@ -58,29 +58,6 @@ export function fix_new_subgraph_node(node) {
|
||||
}
|
||||
}
|
||||
|
||||
function fix_subgraph_widgets(node) {
|
||||
return
|
||||
// some code for Issue 390 - fixing widgets on subgraph nodes - which doesn't work yet
|
||||
const graph = node.subgraph
|
||||
const widgets = node.widgets
|
||||
if (!graph) return
|
||||
shared.graphAnalyser.analyse_graph(graph, true)
|
||||
node.inputs.forEach((input,slot)=>{
|
||||
if (!input.widget) {
|
||||
const connected_widgets = graph.extra['ue_links'].
|
||||
filter((uel)=>(uel.upstream=="-10" && uel.upstream_slot==slot)).
|
||||
map((uel)=>graph._nodes_by_id[uel.downstream]?.inputs[uel.downstream_slot]?.widget).
|
||||
filter((w)=>(w))
|
||||
if (connected_widgets.length>0) {
|
||||
const new_widget = node.addWidget()
|
||||
input._widget = new_widget
|
||||
input.widget = {name:new_widget.name}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
ue_callbacks.register_allnode_callback('afterConfigureGraph', fix_subgraph_widgets, true )
|
||||
|
||||
class WrappedIONode {
|
||||
constructor(io_node) {
|
||||
this.io_node = io_node;
|
||||
|
||||
@@ -169,7 +169,7 @@ export class LinkRenderController extends Pausable {
|
||||
disable_all_connected_widgets( ) {
|
||||
this.widgets_disabled = []
|
||||
app.canvas.graph.extra['ue_links']?.forEach((uel) => {
|
||||
const node = app.canvas.graph._nodes_by_id[uel.downstream]
|
||||
const node = app.canvas.graph.getNodeById(uel.downstream)
|
||||
if (node) {
|
||||
const name = node.inputs[uel.downstream_slot]?.name;
|
||||
if (name) {
|
||||
@@ -337,7 +337,7 @@ export class LinkRenderController extends Pausable {
|
||||
graph : m.node.graph,
|
||||
sending_to : m.node,
|
||||
input_index : m.node_index,
|
||||
control_node : m.node.graph._nodes_by_id[m.id],
|
||||
control_node : m.node.graph.getNodeById(m.id),
|
||||
control_node_input_index : m.index,
|
||||
type : m.type,
|
||||
}, ctx, 0, "#F00")
|
||||
@@ -388,7 +388,7 @@ export class LinkRenderController extends Pausable {
|
||||
/* this is the end node; get the position of the input */
|
||||
var pos2 = node.getConnectionPos(true, ue_connection.input_index, this.slot_pos1);
|
||||
|
||||
const control_node = graph._nodes_by_id[ue_connection.control_node.id]
|
||||
const control_node = graph.getNodeById(ue_connection.control_node.id)
|
||||
if (!control_node) {
|
||||
Logger.problem(`Couldn't find position for UE link ${ue_connection}.`,null,true)
|
||||
return;
|
||||
|
||||
@@ -48,7 +48,7 @@ export function get_real_node(node_id, 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];
|
||||
return graph.getNodeById(nid);
|
||||
}
|
||||
|
||||
export class Logger {
|
||||
|
||||
+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.6.2"
|
||||
version = "7.7"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = [
|
||||
"comfyui-frontend-package>=1.25.0"
|
||||
|
||||
Reference in New Issue
Block a user