ComfyUI/custom_nodes/cg-use-everywhere/js/use_everywhere_settings.js

272 lines
10 KiB
JavaScript

import { app } from "../../scripts/app.js";
import { GraphAnalyser } from "./use_everywhere_graph_analysis.js";
import { LinkRenderController } from "./use_everywhere_ui.js";
import { convert_to_links, remove_all_ues } from "./use_everywhere_apply.js";
import { VERSION } from "./use_everywhere_utilities.js";
import { settingsCache } from "./use_everywhere_cache.js";
import { visible_graph } from "./use_everywhere_subgraph_utils.js";
import { edit_restrictions } from "./ue_properties_editor.js";
import { is_UEnode } from "./use_everywhere_utilities.js";
export const SETTINGS = [
{
id: "Use Everywhere.About",
name: `Version ${VERSION}`,
type: () => {return document.createElement('span')},
},
{
id: "Use Everywhere.Graphics.showlinks",
name: "Show links",
type: "combo",
options: [ {value:0, text:"All off"}, {value:1, text:"Selected nodes"}, {value:2, text:"Mouseover node"}, {value:3, text:"Selected and mouseover nodes"}, {value:4, text:"All on"}],
defaultValue: 3,
onChange: settingsCache.onSettingChange,
},
{
id: "Use Everywhere.Graphics.fuzzlinks",
name: "Statically distinguish UE links",
type: "boolean",
tooltip: "Render UE links, when shown, differently from normal links. Much lower performance cost than animation.",
defaultValue: true,
onChange: settingsCache.onSettingChange,
},
{
id: "Use Everywhere.Graphics.animate",
name: "Animate UE links",
type: "combo",
options: [ {value:0, text:"Off"}, {value:1, text:"Dots"}, {value:2, text:"Pulse"}, {value:3, text:"Both"}, ],
defaultValue: 0,
onChange: settingsCache.onSettingChange,
tooltip: "Animating links may have a negative impact on UI performance. Consider using Statically distinguish UE links instead."
},
{
id: "Use Everywhere.Graphics.stop_animation_when_running",
name: "Turn animation off when workflow is running",
type: "boolean",
defaultValue: true,
onChange: settingsCache.onSettingChange,
},
{
id: "Use Everywhere.Graphics.highlight",
name: "Highlight connected and connectable inputs",
type: "boolean",
defaultValue: true,
onChange: settingsCache.onSettingChange,
},
{
id: "Use Everywhere.Graphics.preserve edit window position",
name: "Save restrictions edit window position",
type: "boolean",
defaultValue: false,
onChange: settingsCache.onSettingChange,
tooltip: "If off, the edit window appears where the mouse is"
},
{
id: "Use Everywhere.Graphics.tooltips",
name: "Show restrictions as tooltip",
type: "boolean",
defaultValue: true,
onChange: settingsCache.onSettingChange,
},
{
id: "Use Everywhere.Options.connect_to_bypassed",
name: "Connect to bypassed nodes",
type: "boolean",
defaultValue: false,
onChange: settingsCache.onSettingChange,
tooltip: "By default UE links are made to the node downstream of bypassed nodes."
},
{
id: "Use Everywhere.Options.checkloops",
name: "Check for loops before submitting",
type: "boolean",
defaultValue: true,
onChange: settingsCache.onSettingChange,
tooltip: "Check to see if UE links have created a loop that wasn't there before"
},
{
id: "Use Everywhere.Options.logging",
name: "Logging",
type: "combo",
options: [ {value:0, text:"Errors Only"}, {value:1, text:"Problems"}, {value:2, text:"Information"}, {value:3, text:"Detail"}, ],
defaultValue: 1,
onChange: settingsCache.onSettingChange,
},
{
id: "Use Everywhere.Options.block_graph_validation",
name: "Block workflow validation",
type: "boolean",
defaultValue: true,
tooltip: "Turn off workflow validation (which tends to replace UE links with real ones)",
onChange: settingsCache.onSettingChange,
},
]
const ui_update_settings = [
"Use Everywhere.Graphics.showlinks",
"Use Everywhere.Graphics.fuzzlinks",
"Use Everywhere.Graphics.animate",
"Use Everywhere.Graphics.stop_animation_when_running",
"Use Everywhere.Graphics.highlight",
]
ui_update_settings.forEach((id) => {
settingsCache.addCallback(id, ()=>{app.graph?.change.bind(app.graph)})
})
function submenu(properties, property, options, e, menu, node) {
const current = properties[property] ? (properties[property]==2 ? 3 : 2 ) : 1;
const submenu = new LiteGraph.ContextMenu(
options,
{ event: e, callback: inner_function, parentMenu: menu, node: node }
);
const current_element = submenu.root.querySelector(`:nth-child(${current})`);
if (current_element) current_element.style.borderLeft = "2px solid #484";
function inner_function(v) {
if (node) {
const choice = Object.values(options).indexOf(v);
properties[property] = choice;
LinkRenderController.instance().mark_link_list_outdated();
}
}
}
function highlight_selected(submenu_root, node, names) {
names.forEach((name, i) => {
const current_element = submenu_root?.querySelector(`:nth-child(${i+1})`);
if (current_element) {
if (node.properties.ue_properties['widget_ue_connectable'][name]) {
current_element.style.borderLeft = "2px solid #484";
} else {
current_element.style.borderLeft = "";
}
} else {
let a;
}
})
}
function widget_ue_submenu(value, options, e, menu, node) {
if (!(node.properties.ue_properties)) node.properties.ue_properties = {}
if (!(node.properties.ue_properties.widget_ue_connectable)) node.properties.ue_properties.widget_ue_connectable = {};
const linkedWidgets = new Set()
node.widgets
.filter(w => w.linkedWidgets)
.forEach((widget) => { widget.linkedWidgets.forEach((lw)=>{linkedWidgets.add(lw)}) });
const names = []
node.widgets
.filter(w => !linkedWidgets.has(w))
.filter(w => !w.hidden)
.filter(w => !w.name?.includes('$$'))
.forEach((widget) => { names.push(widget.name) });
const submenu = new LiteGraph.ContextMenu(
names,
{ event: e, callback: function (v) {
node.properties.ue_properties.widget_ue_connectable[v] = !!!node.properties.ue_properties.widget_ue_connectable[v];
LinkRenderController.instance().mark_link_list_outdated();
highlight_selected(this.parentElement, node, names)
return true; // keep open
},
parentMenu: menu, node:node}
)
highlight_selected(submenu.root, node, names)
}
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;
node_or_node_type.getExtraMenuOptions = function(_, options) {
getExtraMenuOptions?.apply(this, arguments);
if (is_UEnode(this)) {
node_menu_settings(options, this);
} else {
non_ue_menu_settings(options, this);
}
ioio(options,'callback',`menu option on ${this.id}`);
}
node_or_node_type.ue_extra_menu_items_added = true
}
export function non_ue_menu_settings(options, node) {
options.push(null);
options.push(
{
content: node.properties.rejects_ue_links ? "Allow UE Links" : "Reject UE Links",
has_submenu: false,
callback: () => { node.properties.rejects_ue_links = !!!node.properties.rejects_ue_links },
}
)
if (node.widgets?.length) {
options.push(
{
content: "UE Connectable Widgets",
has_submenu: true,
callback: widget_ue_submenu,
}
)
}
options.push(null);
}
export function node_menu_settings(options, node) {
options.push(null);
options.push(
{
content: "Edit restrictions",
callback: edit_restrictions,
}
)
options.push(
{
content: "Convert to real links",
callback: async () => {
const ues = GraphAnalyser.instance().wait_to_analyse_visible_graph();
convert_to_links(ues, node);
visible_graph().remove(node);
}
}
)
options.push(null);
}
export function canvas_menu_settings(options) {
options.push(null); // divider
options.push({
content: (app.ui.settings.getSettingValue('Use Everywhere.Graphics.showlinks')>0) ? "Hide UE links" : "Show UE links",
callback: () => {
const setTo = (app.ui.settings.getSettingValue('Use Everywhere.Graphics.showlinks')>0) ? 0 : 4;
app.ui.settings.setSettingValue('Use Everywhere.Graphics.showlinks', setTo);
app.graph.change();
}
},
{
content: "Convert all UEs to real links",
callback: async () => {
if (window.confirm("This will convert all links created by Use Everywhere to real links, and delete all the Use Everywhere nodes. Is that what you want?")) {
const ues = GraphAnalyser.instance().wait_to_analyse_visible_graph();
LinkRenderController.instance().pause("convert");
try {
convert_to_links(ues, visible_graph());
remove_all_ues(true);
} finally {
app.graph.change();
LinkRenderController.instance().unpause()
}
}
}
});
if (GraphAnalyser.instance().ambiguity_messages.length) {
options.push({
content: "Show UE broadcast clashes",
callback: async () => {
alert(GraphAnalyser.instance().ambiguity_messages.join("\n"))
}
})
}
options.push(null); // divider
}