-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathuse_everywhere_ui.js
292 lines (250 loc) · 10.9 KB
/
use_everywhere_ui.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
import { Logger, get_real_node, get_group_node, get_all_nodes_within } from "./use_everywhere_utilities.js";
import { ComfyWidgets } from "../../scripts/widgets.js";
import { app } from "../../scripts/app.js";
function nodes_in_my_group(node_id) {
const nodes_in = new Set();
app.graph._groups.forEach((group) => {
group.recomputeInsideNodes();
if (group._nodes?.find((node) => { return (node.id===node_id) } )) {
group._nodes.forEach((node) => { nodes_in.add(node.id) } )
}
});
return [...nodes_in];
}
function nodes_not_in_my_group(node_id) {
const nid = nodes_in_my_group(node_id);
const nodes_not_in = [];
app.graph._nodes.forEach((node) => {
if (!nid.includes(node.id)) nodes_not_in.push(node.id);
});
return nodes_not_in;
}
function nodes_in_groups_matching(regex, already_limited_to) {
const nodes_in = new Set();
app.graph._groups.forEach((group) => {
if (regex.test(group.title)) {
group.recomputeInsideNodes();
group._nodes.forEach((node) => {
if (!already_limited_to || already_limited_to.contains(node.id)) {
nodes_in.add(node.id)
}
} );
}
});
return [...nodes_in];
}
function nodes_my_color(node_id, already_limited_to) {
const nodes_in = new Set();
const color = get_real_node(node_id).color;
if (already_limited_to) {
already_limited_to.forEach((nid) => {
if (get_real_node(nid).color==color) nodes_in.add(nid)
})
} else {
app.graph._nodes.forEach((node) => {
if (node.color==color) nodes_in.add(node.id)
})
}
return [...nodes_in];
}
function nodes_not_my_color(node_id, already_limited_to) {
const nodes_in = new Set();
const color = get_real_node(node_id).color;
if (already_limited_to) {
already_limited_to.forEach((nid) => {
if (get_real_node(nid).color!=color) nodes_in.add(nid)
})
} else {
app.graph._nodes.forEach((node) => {
if (node.color!=color) nodes_in.add(node.id)
})
}
return [...nodes_in];
}
function indicate_restriction(ctx, title_height) {
ctx.save();
ctx.lineWidth = 2;
ctx.strokeStyle = "#6F6";
ctx.beginPath();
ctx.roundRect(5,5-title_height,20,20,8);
ctx.stroke();
ctx.restore();
}
function displayMessage(id, message) {
const node = get_real_node(id);
if (!node) return;
var w = node.widgets?.find((w) => w.name === "display_text_widget");
if (app.ui.settings.getSettingValue('AE.details', false) || w) {
if (!w) {
w = ComfyWidgets["STRING"](this, "display_text_widget", ["STRING", { multiline: true }], app).widget;
w.inputEl.readOnly = true;
w.inputEl.style.opacity = 0.6;
w.inputEl.style.fontSize = "9pt";
}
w.value = message;
this.onResize?.(this.size);
}
}
function update_input_label(node, slot, app) {
if (node.input_type[slot]) {
node.inputs[slot].name = node.input_type[slot];
node.inputs[slot].color_on = app.canvas.default_connection_color_byType[node.input_type[slot]];
} else {
node.inputs[slot].name = "anything";
node.inputs[slot].color_on = undefined;
}
}
class LinkRenderController {
static _instance;
static instance(tga) {
if (!this._instance) this._instance = new LinkRenderController();
if (tga && !this._instance.the_graph_analyser) this._instance.the_graph_analyser = tga;
return this._instance
}
constructor() {
this.the_graph_analyser = null;
this.periodically_mark_link_list_outdated();
}
ue_list = undefined; // a UseEverythingList; undefined when outdated
ue_list_reloading = false; // true when a reload has been requested but not completed
// memory reuse
slot_pos1 = new Float32Array(2); //to reuse
slot_pos2 = new Float32Array(2); //to reuse
mark_link_list_outdated() {
if (this.ue_list) {
this.ue_list = undefined;
this.request_link_list_update();
Logger.log(Logger.INFORMATION, "link_list marked outdated");
} else {
Logger.log(Logger.INFORMATION, "link_list was already outdated");
}
}
periodically_mark_link_list_outdated() {
this.mark_link_list_outdated();
setTimeout(this.periodically_mark_link_list_outdated.bind(this), 1000);
}
// callback when the_graph_analyser finishes - store the result and note reloading is false
reload_resolve = function (value) {
this.ue_list_reloading=false;
this.ue_list = value;
Logger.log(Logger.INFORMATION, "link list update completed");
Logger.log_call(Logger.DETAIL, this.ue_list.print_all);
}.bind(this)
// callback for when the_graph_analyser fails - note reloading is false and log
reload_reject = function(reason) {
this.ue_list_reloading=false;
Logger.log(Logger.ERROR, "link list update failed");
Logger.log_error(Logger.ERROR, reason);
}.bind(this)
// request an update to the ue_list.
request_link_list_update() {
if (this.ue_list_reloading) return; // already doing it
this.ue_list_reloading = true; // stop any more requests
this.the_graph_analyser.analyse_graph().then(this.reload_resolve, this.reload_reject); // an async call is a promise; pass it two callbacks
Logger.log(Logger.INFORMATION, "link list update started");
}
highlight_ue_connections(node, ctx) {
if (!app.ui.settings.getSettingValue('AE.highlight', true)) return;
//if (this._ue_links_visible) return;
if (!this.list_ready()) return;
this.ue_list.all_connected_inputs(node).forEach((ue_connection) => {
if (!ue_connection.control_node) { // control node deleted...
this.mark_link_list_outdated();
return;
}
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.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();
ctx.restore();
});
}
list_ready() {
if (!this.the_graph_analyser) return false;
if (this.ue_list===undefined) this.request_link_list_update();
return !this.ue_list_reloading
}
node_in_ueconnection(ue_connection, id) {
return (get_group_node(ue_connection.control_node.id).id == id || get_group_node(ue_connection.sending_to.id).id == id)
}
any_node_in_ueconnection(ue_connection, list_of_nodes) {
return (Object.values(list_of_nodes).find((node) => (this.node_in_ueconnection(ue_connection, node.id))))?true:false;
}
render_all_ue_links(ctx) {
if (!this.list_ready()) return;
ctx.save();
const orig_hqr = app.canvas.highquality_render;
app.canvas.highquality_render = false;
const mode = app.ui.settings.getSettingValue('AE.showlinks', 0);
const animate = app.ui.settings.getSettingValue('AE.animate', 3);
if (animate==2 || animate==3) this.animate_step(ctx);
var any_links_shown = false;
this.ue_list.all_ue_connections().forEach((ue_connection) => {
var show = false;
if (mode==4) show = true;
if ( (mode==2 || mode==3) && app.canvas.node_over && this.node_in_ueconnection(ue_connection, app.canvas.node_over.id) ) show = true;
if ( (mode==1 || mode==3) && this.any_node_in_ueconnection(ue_connection, app.canvas.selected_nodes)) show = true;
if ( show ) {
this._render_ue_link(ue_connection, ctx, animate);
any_links_shown = true;
}
});
if (animate>0) {
/*
If no links were shown, wait 200ms.
If links were shown without dots, wait 100ms.
If links were shown with dots, wait 30ms.
*/
const timeout = any_links_shown ? ((animate%2 == 1) ? 30 : 100) : 200;
setTimeout( app.graph.change.bind(app.graph), timeout );
}
app.canvas.highquality_render = orig_hqr;
ctx.restore();
}
_render_ue_link(ue_connection, ctx, animate) {
const node = get_real_node(ue_connection.sending_to.id);
/* this is the end node; get the position of the input */
var pos2 = node.getConnectionPos(true, ue_connection.input_index, this.slot_pos1);
/* get the position of the *input* that is being echoed - except for the Seed Anywhere node,
which is displayed with an output: the class records control_node_input_index as -ve (-1 => 0, -2 => 1...) */
const input_source = (ue_connection.control_node_input_index >= 0);
const source_index = input_source ? ue_connection.control_node_input_index : -1-ue_connection.control_node_input_index;
const pos1 = get_group_node(ue_connection.control_node.id).getConnectionPos(input_source, source_index, this.slot_pos2);
/* get the direction that we start and end */
const delta_x = pos2[0] - pos1[0];
const delta_y = pos2[1] - pos1[1];
const end_direction = LiteGraph.LEFT; // always end going into an input
const sta_direction = ((Math.abs(delta_y) > Math.abs(delta_x))) ?
((delta_y>0) ? LiteGraph.DOWN : LiteGraph.UP) :
((input_source && delta_x<0) ? LiteGraph.LEFT : LiteGraph.RIGHT)
var color = LGraphCanvas.link_type_colors[ue_connection.type];
if (color=="") color = "white";
ctx.shadowColor = color;
app.canvas.renderLink(ctx, pos1, pos2, undefined, true, animate%2, color, sta_direction, end_direction, undefined);
}
animate_step(ctx) {
const max_blur = 8;
const speed = 0.75;
var f = (LiteGraph.getTime()*0.001*speed) % 1;
const step = Math.ceil(f*2*max_blur) % (2*max_blur);
ctx.shadowBlur = (step<max_blur) ? step + 4 : 3 + 2*max_blur - step;
}
}
export {displayMessage, update_input_label, nodes_in_my_group, nodes_not_in_my_group, nodes_in_groups_matching, nodes_my_color, nodes_not_my_color, indicate_restriction}
export{ LinkRenderController}