This commit is contained in:
@@ -15,6 +15,10 @@ If upgrading from before version 7, see the end of this document for the major c
|
||||
<details>
|
||||
<summary>Changes since 7.0</summary>
|
||||
|
||||
## 7.5
|
||||
|
||||
- Added per-output granularity to any-node broadcasting
|
||||
|
||||
## 7.4
|
||||
|
||||
- Added broadcasting from [any node](#any-node-broadcasting)
|
||||
@@ -84,6 +88,11 @@ When broadcasting, the node acts like all its outputs were connected to a single
|
||||
|This...|...does the same as this|
|
||||
|-|-|
|
||||
|||
|
||||
|
||||
From `7.5`, the outputs that will broadcast can also be set (like inputs):
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
# Where will the data be sent?
|
||||
@@ -180,7 +189,7 @@ and connections, it is muted.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Inputs have a subtle visual clue</summary>
|
||||
<summary>Inputs and outputs have a subtle visual clue</summary>
|
||||
|
||||
The state of inputs is also represented visually: a black ring and a glow on the input dot indicates it is connectable.
|
||||
In the image below, `positive` has been set to not accept UE inputs, `steps` has been set to accept them, and `model` has a UE connection.
|
||||
@@ -190,6 +199,12 @@ In the image below, `positive` has been set to not accept UE inputs, `steps` has
|
||||
If a widget is getting data from a UE connection, it is grayed out, like `steps` below:
|
||||
|
||||

|
||||
|
||||
Similarly, if a node has had broadcasting added to it, the outputs that can broadcast are shown:
|
||||
here `merged` can broadcast, but isn't, `x` can broadcast and is, and `y` is set to not broadcast.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
# Special Case Nodes
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
@@ -1,5 +1,6 @@
|
||||
import { i18n_functional, i18n_functional_regex } from "./i18n.js";
|
||||
import { default_priority } from "./ue_properties.js";
|
||||
import { is_able_to_broadcast } from "./use_everywhere_settings.js";
|
||||
import { connection_from_output_as_input, visible_graph } from "./use_everywhere_subgraph_utils.js";
|
||||
import { nodes_in_my_group, nodes_not_in_my_group, nodes_my_color, nodes_not_my_color, nodes_in_groups_matching } from "./use_everywhere_ui.js";
|
||||
import { Logger, node_is_live, get_real_node, get_connection } from "./use_everywhere_utilities.js";
|
||||
@@ -160,10 +161,6 @@ function validity_errors(params) {
|
||||
export class UseEverywhereList {
|
||||
constructor() { this.ues = []; this.unmatched_inputs = []; }
|
||||
|
||||
node_sending_anywhere(node) {
|
||||
return this.ues.find((ue)=>(ue.controller?.id==node.id && ue.sending_to?.length>0)) ? true : false;
|
||||
}
|
||||
|
||||
differs_from(another_uel) {
|
||||
if (!another_uel || !another_uel.ues || !this.ues) return true;
|
||||
if (this.ues.length != another_uel.ues.length) return true;
|
||||
@@ -258,6 +255,18 @@ export class UseEverywhereList {
|
||||
return ue_connections;
|
||||
}
|
||||
|
||||
node_sending_anywhere(node) {
|
||||
return this.ues.find((ue)=>(ue.controller?.id==node.id && ue.sending_to?.length>0)) ? true : false;
|
||||
}
|
||||
|
||||
all_sending_slots(for_node) {
|
||||
const sending_slots = new Set()
|
||||
this.ues.filter((ue)=>(ue.controller.id == for_node.id) && (ue.sending_to.length>0)).forEach((ue) => {
|
||||
sending_slots.add(ue.control_node_input_index)
|
||||
});
|
||||
return sending_slots;
|
||||
}
|
||||
|
||||
all_ue_connections() {
|
||||
const ue_connections = [];
|
||||
this.ues.forEach((ue) => {
|
||||
@@ -283,19 +292,25 @@ export class UseEverywhereList {
|
||||
|
||||
var the_possibles
|
||||
var connection_finder
|
||||
var check_if_able_to_broadcast
|
||||
if (node.properties.ue_convert) {
|
||||
the_possibles = node.outputs
|
||||
connection_finder = connection_from_output_as_input
|
||||
check_if_able_to_broadcast = (node, i) => {
|
||||
const name = node.outputs[i].name
|
||||
return is_able_to_broadcast(node, name)
|
||||
}
|
||||
} else {
|
||||
the_possibles = node.inputs
|
||||
connection_finder = get_connection
|
||||
check_if_able_to_broadcast = ()=>{true}
|
||||
}
|
||||
|
||||
const broadcasted_types = new Set()
|
||||
const duplicated_broadcasted_types = new Set()
|
||||
for (var i=0; i<the_possibles.length; i++) {
|
||||
const connection = connection_finder(node, i);
|
||||
if (connection.link) {
|
||||
if (connection.link && check_if_able_to_broadcast(node,i)) {
|
||||
if (broadcasted_types.has(connection.type)) duplicated_broadcasted_types.add(connection.type)
|
||||
broadcasted_types.add(connection.type)
|
||||
}
|
||||
@@ -303,7 +318,7 @@ export class UseEverywhereList {
|
||||
|
||||
the_possibles.forEach((possible, i) => {
|
||||
const connection = connection_finder(node, i);
|
||||
if (connection.link) {
|
||||
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)) {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { node_is_live, is_connected, is_UEnode, Logger, Pausable } from "./use_e
|
||||
import { convert_to_links } from "./use_everywhere_apply.js";
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { settingsCache } from "./use_everywhere_cache.js";
|
||||
import { visible_graph } from "./use_everywhere_subgraph_utils.js";
|
||||
import { is_connectable } from "./use_everywhere_settings.js";
|
||||
import { for_all_graphs } from "./recursive_callbacks.js";
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ function show_connectable(submenu_root, node) {
|
||||
export function is_connectable(node, input_name){
|
||||
const input = node.inputs.find(i => i.name==input_name);
|
||||
if (!input) {
|
||||
Logger.log_error(`Can't find input ${label} on node ${node.title}`);
|
||||
Logger.log_error(`Can't find input ${input_name} on node ${node.title}`);
|
||||
return false;
|
||||
}
|
||||
if (input.widget) {
|
||||
@@ -172,6 +172,50 @@ function widget_ue_submenu(value, options, e, menu, node) {
|
||||
show_connectable(submenu.root, node)
|
||||
}
|
||||
|
||||
function show_broadcasting(submenu_root, node) {
|
||||
node.outputs.forEach((input, i) => {
|
||||
const current_element = submenu_root?.querySelector(`:nth-child(${i+1})`);
|
||||
if (current_element) current_element.style.borderLeft = (is_able_to_broadcast(node,input.name)) ? "2px solid #484" : "";
|
||||
})
|
||||
}
|
||||
|
||||
export function is_able_to_broadcast(node, output_name) {
|
||||
if (!node.properties.ue_convert) return false
|
||||
const output = node.outputs.find(i => i.name==output_name);
|
||||
if (!output) {
|
||||
Logger.log_error(`Can't find output ${output_name} on node ${node.title}`);
|
||||
return false;
|
||||
}
|
||||
return ! (node.properties?.ue_properties?.output_not_broadcasting?.[output_name])
|
||||
}
|
||||
|
||||
function toggle_broadcasting(node, output_name){
|
||||
const p = node.properties.ue_properties
|
||||
p.output_not_broadcasting[output_name] = !!!p.output_not_broadcasting[output_name]
|
||||
}
|
||||
|
||||
function output_ue_submenu(value, options, e, menu, node) {
|
||||
if (!(node.properties.ue_properties)) node.properties.ue_properties = {}
|
||||
if (!(node.properties.ue_properties.output_not_broadcasting)) node.properties.ue_properties.output_not_broadcasting = {};
|
||||
|
||||
const label_to_name = {}
|
||||
node.outputs.forEach((output) => {label_to_name[output.label || output.name] = output.name})
|
||||
const submenu = new LiteGraph.ContextMenu(
|
||||
Object.keys(label_to_name),
|
||||
{ event: e, callback: function (label) {
|
||||
const name = label_to_name[label];
|
||||
toggle_broadcasting(node, name);
|
||||
shared.linkRenderController.mark_link_list_outdated();
|
||||
show_broadcasting(this.parentElement, node)
|
||||
return true; // keep open
|
||||
},
|
||||
parentMenu: menu, node:node}
|
||||
)
|
||||
show_broadcasting(submenu.root, node)
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function add_extra_menu_items(node_or_node_type, ioio) {
|
||||
if (node_or_node_type.ue_extra_menu_items_added) return
|
||||
const getExtraMenuOptions = node_or_node_type.getExtraMenuOptions;
|
||||
@@ -244,9 +288,18 @@ function non_ue_menu_settings(options, node) {
|
||||
{
|
||||
content: node.properties.ue_convert ? "Remove UE broadcasting" : "Add UE broadcasting",
|
||||
has_submenu: false,
|
||||
callback: () => { node.properties.ue_convert = !!!node.properties.ue_convert },
|
||||
callback: () => { node.properties.ue_convert = !!!node.properties.ue_convert },
|
||||
}
|
||||
)
|
||||
if (node.properties.ue_convert) {
|
||||
options.push(
|
||||
{
|
||||
content: "Broadcasting Outputs",
|
||||
has_submenu: true,
|
||||
callback: output_ue_submenu,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function remove_ue_nodes(graph) {
|
||||
|
||||
+75
-37
@@ -3,7 +3,7 @@ import { app } from "../../scripts/app.js";
|
||||
import { settingsCache } from "./use_everywhere_cache.js";
|
||||
import { in_visible_graph, visible_graph } from "./use_everywhere_subgraph_utils.js";
|
||||
import { maybe_show_tooltip } from "./tooltip_window.js";
|
||||
import { is_connectable } from "./use_everywhere_settings.js";
|
||||
import { is_able_to_broadcast, is_connectable } from "./use_everywhere_settings.js";
|
||||
import { shared } from "./shared.js";
|
||||
import { any_restrictions } from "./ue_properties.js";
|
||||
|
||||
@@ -204,6 +204,8 @@ export class LinkRenderController extends Pausable {
|
||||
this.pause('highlight_ue_connections')
|
||||
if (!this._list_ready()) return;
|
||||
|
||||
// get all the inputs that can be connected and aren't
|
||||
// connected with a 'real' link
|
||||
const unconnected_connectable_names = new Set(node.inputs
|
||||
.filter((input)=>is_connectable(node,input.name))
|
||||
.filter((input)=>(!input.link))
|
||||
@@ -216,49 +218,35 @@ export class LinkRenderController extends Pausable {
|
||||
|
||||
const name_sent_to = node.inputs[ue_connection.input_index].name;
|
||||
unconnected_connectable_names.delete(name_sent_to); // remove the name from the list of connectables
|
||||
var pos2 = node.getConnectionPos(true, ue_connection.input_index, this.slot_pos1);
|
||||
pos2[0] -= node.pos[0];
|
||||
pos2[1] -= node.pos[1];
|
||||
ctx.save();
|
||||
ctx.lineWidth = 1;
|
||||
var radius=5
|
||||
ctx.strokeStyle = LGraphCanvas.link_type_colors[ue_connection.type];
|
||||
ctx.shadowColor = "white";
|
||||
ctx.shadowBlur = 10;
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.shadowOffsetY = 0;
|
||||
ctx.beginPath();
|
||||
ctx.roundRect(pos2[0]-radius,pos2[1]-radius,2*radius,2*radius,radius);
|
||||
ctx.stroke();
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.shadowBlur = 0;
|
||||
radius = radius - 1;
|
||||
ctx.roundRect(pos2[0]-radius,pos2[1]-radius,2*radius,2*radius,radius);
|
||||
ctx.stroke();
|
||||
const pos2 = this._relative_connection_pos(node, true, ue_connection.input_index);
|
||||
|
||||
ctx.restore();
|
||||
circle(ctx, pos2, {...CONNECTED_1, strokeStyle:LGraphCanvas.link_type_colors[ue_connection.type]})
|
||||
circle(ctx, pos2, {...CONNECTED_2})
|
||||
});
|
||||
}
|
||||
|
||||
unconnected_connectable_names.forEach((name) => {
|
||||
const index = node.inputs.findIndex((i) => i.name == name);
|
||||
var pos2 = node.getConnectionPos(true, index, this.slot_pos1);
|
||||
pos2[0] -= node.pos[0];
|
||||
pos2[1] -= node.pos[1];
|
||||
ctx.save();
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.shadowColor = "green";
|
||||
ctx.shadowBlur = 10;
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.shadowOffsetY = 0;
|
||||
var radius = 3;
|
||||
ctx.beginPath();
|
||||
ctx.roundRect(pos2[0]-radius,pos2[1]-radius,2*radius,2*radius,radius);
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
const pos2 = this._relative_connection_pos(node, true, index);
|
||||
circle(ctx, pos2, {...UNCONNECTED_CONNECTABLE})
|
||||
})
|
||||
|
||||
if (node.properties.ue_convert) {
|
||||
const sending_slots = this.ue_list.all_sending_slots(node)
|
||||
|
||||
node.outputs.forEach((output,i) => {
|
||||
if (is_able_to_broadcast(node, output.name)) {
|
||||
const pos2 = this._relative_connection_pos(node, false, i);
|
||||
if (sending_slots.has(i)) {
|
||||
circle(ctx, pos2, {...CONNECTED_1, strokeStyle:LGraphCanvas.link_type_colors[node.outputs[i].type]})
|
||||
circle(ctx, pos2, {...CONNECTED_2})
|
||||
} else {
|
||||
circle(ctx, pos2, {...UNCONNECTED_CONNECTABLE})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.log_error(e);
|
||||
} finally {
|
||||
@@ -266,6 +254,13 @@ export class LinkRenderController extends Pausable {
|
||||
}
|
||||
}
|
||||
|
||||
_relative_connection_pos(node, input, slot) {
|
||||
var pos2 = node.getConnectionPos(input, slot, this.slot_pos1);
|
||||
pos2[0] -= node.pos[0];
|
||||
pos2[1] -= node.pos[1];
|
||||
return pos2
|
||||
}
|
||||
|
||||
_list_ready() {
|
||||
if (!shared.graphAnalyser) return false; // we don't have the analyser yet (still loading)
|
||||
if (!this.ue_list) {
|
||||
@@ -422,6 +417,49 @@ export class LinkRenderController extends Pausable {
|
||||
}
|
||||
}
|
||||
|
||||
const UNCONNECTED_CONNECTABLE = {
|
||||
radius : 3,
|
||||
strokeStyle : "black",
|
||||
shadowColor : "green",
|
||||
shadowBlur : 10,
|
||||
shadowOffsetX : 0,
|
||||
shadowOffsetY : 0,
|
||||
}
|
||||
|
||||
const CONNECTED_1 = {
|
||||
radius:5,
|
||||
first_last:"first",
|
||||
lineWidth:1,
|
||||
shadowColor : "white",
|
||||
shadowBlur : 10,
|
||||
shadowOffsetX : 0,
|
||||
shadowOffsetY : 0,
|
||||
}
|
||||
|
||||
const CONNECTED_2 = {
|
||||
radius:4,
|
||||
first_last:"last",
|
||||
shadowBlur : 0,
|
||||
strokeStyle : "black",
|
||||
}
|
||||
|
||||
function circle(ctx, position, properties) {
|
||||
const p = {...properties}
|
||||
|
||||
const radius = p.radius
|
||||
const first_last = p.first_last
|
||||
delete p.radius
|
||||
delete p.first_last
|
||||
|
||||
if (!first_last || first_last=='first') ctx.save()
|
||||
Object.assign(ctx, p)
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.roundRect(position[0]-radius,position[1]-radius,2*radius,2*radius,radius);
|
||||
ctx.stroke();
|
||||
if (!first_last || first_last=='last') ctx.restore()
|
||||
}
|
||||
|
||||
function modify(c) {
|
||||
if (c.length==4) return c + "6"
|
||||
if (c.length==7) return c + "66"
|
||||
|
||||
Reference in New Issue
Block a user