753 lines
31 KiB
JavaScript
753 lines
31 KiB
JavaScript
import { app } from "/scripts/app.js";
|
|
import { api } from "/scripts/api.js";
|
|
import { debounce } from "./debounce.js"
|
|
|
|
app.registerExtension({
|
|
name: "Comfy.EasyApi.Setting",
|
|
async setup(app) {
|
|
this.add_history_setting(app);
|
|
// plugins are loaded before the manager, cannot be patched with Python hooks on Windows.
|
|
const systemStats = await api.getSystemStats();
|
|
if (systemStats.system.os !== 'nt') {
|
|
this.add_github_clone_mirror_setting(app);
|
|
}
|
|
this.add_github_mirror_setting(app);
|
|
this.add_rawgithub_mirror_setting(app);
|
|
this.add_huggingface_mirror_setting(app);
|
|
|
|
const ctxMenu = LiteGraph.ContextMenu;
|
|
const replace = () => {
|
|
LiteGraph.ContextMenu = function (values, options) {
|
|
options = options || {};
|
|
options.autoopen = true;
|
|
return ctxMenu.call(this, values, options);
|
|
};
|
|
LiteGraph.ContextMenu.prototype = ctxMenu.prototype;
|
|
};
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.ContextMenu.autoopen",
|
|
name: "[EasyApi] Auto Open Sub Menu",
|
|
type: "boolean",
|
|
defaultValue: false,
|
|
onChange(value) {
|
|
if (value) {
|
|
replace(value);
|
|
} else {
|
|
LiteGraph.ContextMenu = ctxMenu;
|
|
}
|
|
},
|
|
});
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.Search.fuzzy",
|
|
name: "[EasyApi] Fuzzy Search",
|
|
type: "boolean",
|
|
defaultValue: false,
|
|
onChange(value) {
|
|
LiteGraph.search_fuzzy_match = value;
|
|
},
|
|
});
|
|
},
|
|
add_history_setting: function (app) {
|
|
const changeFun = debounce((n, o) => api.fetchApi("/easyapi/history/size", {
|
|
method: 'POST',
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
maxSize: n
|
|
})
|
|
}), 1000, false)
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.SizeOfHistory",
|
|
name: "[EasyApi] Maximum History Size",
|
|
defaultValue: 10000,
|
|
type: "slider",
|
|
attrs: {
|
|
min: 1,
|
|
max: 10000,
|
|
step: 1,
|
|
},
|
|
onChange: (newVal, oldVal) => {
|
|
changeFun.apply(null, [newVal, oldVal])
|
|
}
|
|
});
|
|
},
|
|
add_github_clone_mirror_setting: function (app) {
|
|
const changeFun = debounce((n, o) => api.fetchApi("/easyapi/settings/clone_github_mirror", {
|
|
method: 'POST',
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
clone_github_mirror: n
|
|
})
|
|
}), 1000, false)
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.MirrorSet.github.clone",
|
|
name: "[EasyApi] Github Clone Mirror",
|
|
defaultValue: "None",
|
|
tooltip: "Will replace host github.com. Suitable of git clone from github.com. On Windows platforms, it is not valid for ComfyUI manager.",
|
|
type: "combo",
|
|
options: [
|
|
{
|
|
value: "None",
|
|
text: "None"
|
|
},
|
|
{
|
|
value: "hub.gitmirror.com/https://github.com",
|
|
text: "gitmirror.com"
|
|
},
|
|
{
|
|
value: "ghp.ci/https://github.com",
|
|
text: "ghp.ci"
|
|
},
|
|
{
|
|
value: "mirror.ghproxy.com/https://github.com",
|
|
text: "mirror.ghproxy.com"
|
|
},
|
|
{
|
|
value: "ghproxy.net/https://github.com",
|
|
text: "ghproxy.net"
|
|
},
|
|
{
|
|
value: "ghproxy.org/https://github.com",
|
|
text: "ghproxy.org"
|
|
},
|
|
{
|
|
value: "gh-proxy.com/https://github.com",
|
|
text: "gh-proxy.com"
|
|
},
|
|
{
|
|
value: "gh.ddlc.top/https://github.com",
|
|
text: "gh.ddlc.top"
|
|
},
|
|
{
|
|
value: "mirrors.chenby.cn/https://github.com",
|
|
text: "mirrors.chenby.cn"
|
|
},
|
|
{
|
|
value: "521github.com/extdomains/github.com",
|
|
text: "521github.com"
|
|
},
|
|
{
|
|
value: "github.moeyy.xyz/https://github.com",
|
|
text: "github.moeyy.xyz"
|
|
}
|
|
],
|
|
|
|
onChange: (newVal, oldVal) => {
|
|
changeFun.apply(null, [newVal, oldVal])
|
|
}
|
|
});
|
|
},
|
|
add_github_mirror_setting: function (app) {
|
|
const changeFun = debounce((n, o) => api.fetchApi("/easyapi/settings/github_mirror", {
|
|
method: 'POST',
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
github_mirror: n
|
|
})
|
|
}), 1000, false)
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.MirrorSet.github",
|
|
name: "[EasyApi] Github Mirror",
|
|
defaultValue: "None",
|
|
tooltip: "Will replace host github.com. Suitable of downloading some models from github.com.",
|
|
type: "combo",
|
|
options: [
|
|
{
|
|
value: "None",
|
|
text: "None"
|
|
},
|
|
{
|
|
value: "hub.gitmirror.com/https://github.com",
|
|
text: "gitmirror.com"
|
|
},
|
|
{
|
|
value: "ghp.ci/https://github.com",
|
|
text: "ghp.ci"
|
|
},
|
|
{
|
|
value: "mirror.ghproxy.com/https://github.com",
|
|
text: "mirror.ghproxy.com"
|
|
},
|
|
{
|
|
value: "ghproxy.net/https://github.com",
|
|
text: "ghproxy.net"
|
|
},
|
|
{
|
|
value: "ghproxy.org/https://github.com",
|
|
text: "ghproxy.org"
|
|
},
|
|
{
|
|
value: "gh-proxy.com/https://github.com",
|
|
text: "gh-proxy.com"
|
|
},
|
|
{
|
|
value: "gh.ddlc.top/https://github.com",
|
|
text: "gh.ddlc.top"
|
|
},
|
|
{
|
|
value: "mirrors.chenby.cn/https://github.com",
|
|
text: "mirrors.chenby.cn"
|
|
},
|
|
{
|
|
value: "521github.com/extdomains/github.com",
|
|
text: "521github.com"
|
|
},
|
|
{
|
|
value: "github.moeyy.xyz/https://github.com",
|
|
text: "github.moeyy.xyz"
|
|
}
|
|
],
|
|
|
|
onChange: (newVal, oldVal) => {
|
|
changeFun.apply(null, [newVal, oldVal])
|
|
}
|
|
});
|
|
},
|
|
add_rawgithub_mirror_setting: function (app) {
|
|
const changeFun = debounce((n, o) => api.fetchApi("/easyapi/settings/rawgithub_mirror", {
|
|
method: 'POST',
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
rawgithub_mirror: n
|
|
})
|
|
}), 1000, false)
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.MirrorSet.rawgithub",
|
|
name: "[EasyApi] RawGithub Mirror",
|
|
defaultValue: "None",
|
|
tooltip: "Will replace host raw.githubusercontent.com",
|
|
type: "combo",
|
|
options: [
|
|
{
|
|
value: "None",
|
|
text: "None"
|
|
},
|
|
{
|
|
value: "raw.gitmirror.com",
|
|
text: "gitmirror.com"
|
|
},
|
|
{
|
|
value: "ghp.ci/https://raw.githubusercontent.com",
|
|
text: "ghp.ci"
|
|
},
|
|
{
|
|
value: "mirror.ghproxy.com/https://raw.githubusercontent.com",
|
|
text: "mirror.ghproxy.com"
|
|
},
|
|
{
|
|
value: "ghproxy.net/https://raw.githubusercontent.com",
|
|
text: "ghproxy.net"
|
|
},
|
|
{
|
|
value: "ghproxy.org/https://raw.githubusercontent.com",
|
|
text: "ghproxy.org"
|
|
},
|
|
{
|
|
value: "gh-proxy.com/https://raw.githubusercontent.com",
|
|
text: "gh-proxy.com"
|
|
},
|
|
{
|
|
value: "mirrors.chenby.cn/https://raw.githubusercontent.com",
|
|
text: "mirrors.chenby.cn"
|
|
},
|
|
{
|
|
value: "gh.ddlc.top/https://raw.githubusercontent.com",
|
|
text: "gh.ddlc.top"
|
|
},
|
|
{
|
|
value: "521github.com/extdomains/raw.githubusercontent.com",
|
|
text: "521github.com"
|
|
},
|
|
{
|
|
value: "github.moeyy.xyz/https://raw.githubusercontent.com",
|
|
text: "github.moeyy.xyz"
|
|
}
|
|
],
|
|
|
|
onChange: (newVal, oldVal) => {
|
|
changeFun.apply(null, [newVal, oldVal])
|
|
}
|
|
});
|
|
},
|
|
add_huggingface_mirror_setting: function (app) {
|
|
const changeFun = debounce((n, o) => api.fetchApi("/easyapi/settings/huggingface_mirror", {
|
|
method: 'POST',
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
huggingface_mirror: n
|
|
})
|
|
}), 1000, false)
|
|
app.ui.settings.addSetting({
|
|
id: "Easyapi.MirrorSet.huggingface",
|
|
name: "[EasyApi] Huggingface Mirror",
|
|
tooltip: "Will replace host huggingface.co",
|
|
defaultValue: "None",
|
|
type: "combo",
|
|
options: [
|
|
{
|
|
value: "None",
|
|
text: "None"
|
|
},
|
|
{
|
|
value: "hf-mirror.com",
|
|
text: "hf-mirror.com"
|
|
},
|
|
// {
|
|
// value: "gitee.com/hf-models",
|
|
// text: "gitee.com"
|
|
// }
|
|
],
|
|
|
|
onChange: (newVal, oldVal) => {
|
|
changeFun.apply(null, [newVal, oldVal])
|
|
}
|
|
});
|
|
},
|
|
})
|
|
|
|
app.registerExtension({
|
|
name: "Comfy.EasyApi.Search",
|
|
async init(app) {
|
|
function fuzzy_match_filter(inputStr, str, matchedPos) {
|
|
matchedPos = matchedPos || [];
|
|
let splitStr = inputStr.split("");
|
|
let j = splitStr.shift()
|
|
for (let i in str) {
|
|
if (str[i] == j) {
|
|
matchedPos.push(i)
|
|
if (splitStr.length == 0) {
|
|
return true;
|
|
}
|
|
j = splitStr.shift()
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function highlight_keywords(oldText, recordPos) {
|
|
let newText = "";
|
|
let pos = recordPos.shift();
|
|
let split = oldText.split("")
|
|
for (let j in split) {
|
|
let c = oldText[j];
|
|
if (j == pos) {
|
|
newText += "<span style='color: red'>" + c + "</span>";
|
|
if (recordPos.length > 0) {
|
|
pos = recordPos.shift();
|
|
} else {
|
|
newText += oldText.slice(parseInt(j) + 1);
|
|
break;
|
|
}
|
|
} else {
|
|
newText += c;
|
|
}
|
|
}
|
|
return newText;
|
|
}
|
|
|
|
let oldOnSearchBox = app.canvas.onSearchBox
|
|
let oldShowSearchBox = LGraphCanvas.prototype.showSearchBox
|
|
LGraphCanvas.prototype.showSearchBox = function(event, options) {
|
|
let that = this;
|
|
// copy from oldShowSearBox
|
|
let def_options = { slot_from: null
|
|
,node_from: null
|
|
,node_to: null
|
|
,do_type_filter: LiteGraph.search_filter_enabled
|
|
,type_filter_in: false // these are default: pass to set initially set values
|
|
,type_filter_out: false
|
|
,show_general_if_none_on_typefilter: true
|
|
,show_general_after_typefiltered: true
|
|
,hide_on_mouse_leave: LiteGraph.search_hide_on_mouse_leave
|
|
,show_all_if_empty: true
|
|
,show_all_on_open: LiteGraph.search_show_all_on_open
|
|
,search_fuzzy_match: LiteGraph.search_fuzzy_match || false // easyapi custom setting
|
|
};
|
|
options = Object.assign(def_options, options || {});
|
|
if (!options.search_fuzzy_match) {
|
|
app.canvas.onSearchBox = oldOnSearchBox;
|
|
return oldShowSearchBox?.apply(this, [event, options]);
|
|
}
|
|
let dialog = oldShowSearchBox?.apply(this, [event, options])
|
|
|
|
app.canvas.onSearchBox = function (helper, inputStr, graphcanvas) {
|
|
// let options = {}
|
|
var c = 0;
|
|
let str = inputStr.toLowerCase();
|
|
var filter = graphcanvas.filter || graphcanvas.graph.filter;
|
|
|
|
// filter by type preprocess
|
|
if (options.do_type_filter && that.search_box) {
|
|
var sIn = that.search_box.querySelector(".slot_in_type_filter");
|
|
var sOut = that.search_box.querySelector(".slot_out_type_filter");
|
|
} else {
|
|
var sIn = false;
|
|
var sOut = false;
|
|
}
|
|
|
|
let filtered = [];
|
|
|
|
//extras
|
|
for (var i in LiteGraph.searchbox_extras) {
|
|
var extra = LiteGraph.searchbox_extras[i];
|
|
if ((!options.show_all_if_empty || str) && !fuzzy_match_filter(str, extra.desc)) {
|
|
continue;
|
|
}
|
|
var ctor = LiteGraph.registered_node_types[ extra.type ];
|
|
if( ctor && ctor.filter != filter )
|
|
continue;
|
|
if( ! inner_test_filter(extra.type) )
|
|
continue;
|
|
// addResult( extra.desc, "searchbox_extra" );
|
|
filtered.push(extra.desc)
|
|
if ( LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
let temp_filtered = []
|
|
if (Array.prototype.filter) { //filter supported
|
|
var keys = Object.keys( LiteGraph.registered_node_types ); //types
|
|
temp_filtered = keys.filter( inner_test_filter );
|
|
} else {
|
|
temp_filtered = [];
|
|
for (var i in LiteGraph.registered_node_types) {
|
|
if( inner_test_filter(i) )
|
|
temp_filtered.push(i);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < temp_filtered.length; i++) {
|
|
// addResult(filtered[i]);
|
|
filtered.push(temp_filtered[i]);
|
|
if ( LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// add general type if filtering
|
|
/*if (options.show_general_after_typefiltered
|
|
&& (sIn.value || sOut.value)
|
|
){
|
|
let filtered_extra = [];
|
|
for (var i in LiteGraph.registered_node_types) {
|
|
if( inner_test_filter(i, {inTypeOverride: sIn&&sIn.value?"*":false, outTypeOverride: sOut&&sOut.value?"*":false}) )
|
|
filtered_extra.push(i);
|
|
}
|
|
for (var i = 0; i < filtered_extra.length; i++) {
|
|
// addResult(filtered_extra[i], "generic_type");
|
|
filtered.push(filtered_extra[i]);
|
|
if (LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit) {
|
|
break;
|
|
}
|
|
}
|
|
}*/
|
|
|
|
// check il filtering gave no results
|
|
if ((sIn.value || sOut.value) &&
|
|
( (helper.childNodes.length == 0 && options.show_general_if_none_on_typefilter) )
|
|
){
|
|
var filtered_extra = [];
|
|
for (var i in LiteGraph.registered_node_types) {
|
|
if( inner_test_filter(i, {skipFilter: true}) )
|
|
filtered_extra.push(i);
|
|
}
|
|
for (var i = 0; i < filtered_extra.length; i++) {
|
|
// addResult(filtered_extra[i], "not_in_filter");
|
|
filtered.push(filtered_extra[i]);
|
|
if ( LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function inner_test_filter( type, optsIn )
|
|
{
|
|
var optsIn = optsIn || {};
|
|
var optsDef = { skipFilter: false
|
|
,inTypeOverride: false
|
|
,outTypeOverride: false
|
|
};
|
|
var opts = Object.assign(optsDef,optsIn);
|
|
var ctor = LiteGraph.registered_node_types[ type ];
|
|
if(filter && ctor.filter != filter )
|
|
return false;
|
|
if ((!options.show_all_if_empty || str) && !fuzzy_match_filter(str, type.toLowerCase()) && (!ctor.title || !fuzzy_match_filter(str, ctor.title.toLowerCase())))
|
|
return false;
|
|
|
|
// filter by slot IN, OUT types
|
|
if(options.do_type_filter && !opts.skipFilter){
|
|
var sType = type;
|
|
|
|
var sV = sIn.value;
|
|
if (opts.inTypeOverride!==false) sV = opts.inTypeOverride;
|
|
//if (sV.toLowerCase() == "_event_") sV = LiteGraph.EVENT; // -1
|
|
|
|
if(sIn && sV){
|
|
//console.log("will check filter against "+sV);
|
|
if (LiteGraph.registered_slot_in_types[sV] && LiteGraph.registered_slot_in_types[sV].nodes){ // type is stored
|
|
//console.debug("check "+sType+" in "+LiteGraph.registered_slot_in_types[sV].nodes);
|
|
var doesInc = LiteGraph.registered_slot_in_types[sV].nodes.includes(sType);
|
|
if (doesInc!==false){
|
|
//console.log(sType+" HAS "+sV);
|
|
}else{
|
|
/*console.debug(LiteGraph.registered_slot_in_types[sV]);
|
|
console.log(+" DONT includes "+type);*/
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
var sV = sOut.value;
|
|
if (opts.outTypeOverride!==false) sV = opts.outTypeOverride;
|
|
//if (sV.toLowerCase() == "_event_") sV = LiteGraph.EVENT; // -1
|
|
|
|
if(sOut && sV){
|
|
//console.log("search will check filter against "+sV);
|
|
if (LiteGraph.registered_slot_out_types[sV] && LiteGraph.registered_slot_out_types[sV].nodes){ // type is stored
|
|
//console.debug("check "+sType+" in "+LiteGraph.registered_slot_out_types[sV].nodes);
|
|
var doesInc = LiteGraph.registered_slot_out_types[sV].nodes.includes(sType);
|
|
if (doesInc!==false){
|
|
//console.log(sType+" HAS "+sV);
|
|
}else{
|
|
/*console.debug(LiteGraph.registered_slot_out_types[sV]);
|
|
console.log(+" DONT includes "+type);*/
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (helper.dataset["observer"] != "true") {
|
|
helper.dataset["observer"] = "true";
|
|
let observConfig = { attributes: false, childList: true };
|
|
let observer = new MutationObserver(mutations => {
|
|
for (let i = 0; i < mutations.length; i++) {
|
|
let mutationRecord = mutations[i];
|
|
let searchWord = helper.parentNode.querySelector("input").value;
|
|
if (searchWord.trim().length == 0) {
|
|
break;
|
|
}
|
|
for (let item of mutationRecord.addedNodes) {
|
|
if (!item.dataset["fuzzy"] && decodeURIComponent(item.dataset["type"]) in LiteGraph.registered_node_types) {
|
|
item.dataset["fuzzy"] = "true";
|
|
let type = decodeURIComponent(item.dataset["type"])
|
|
let newDom = document.createElement("span");
|
|
let recordPos = []
|
|
if (fuzzy_match_filter(searchWord, type.toLowerCase(), recordPos)) {
|
|
let oldDom = item.firstChild.nextSibling;
|
|
let oldText = oldDom.textContent;
|
|
let newText = highlight_keywords(oldText, recordPos);
|
|
oldDom.innerHTML = newText;
|
|
} else {
|
|
recordPos = []
|
|
let node = LiteGraph.registered_node_types[type];
|
|
if (node.title && fuzzy_match_filter(searchWord, node.title.toLowerCase(), recordPos)) {
|
|
let oldDom = item.firstChild;
|
|
let oldText = oldDom.textContent;
|
|
let newText = highlight_keywords(oldText, recordPos);
|
|
newDom.innerHTML = newText;
|
|
item.replaceChild(newDom, oldDom);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
observer.observe(helper, observConfig);
|
|
let oldClose = helper.parentNode.close;
|
|
helper.parentNode.close = function () {
|
|
observer.disconnect();
|
|
oldClose?.apply(this, arguments)
|
|
};
|
|
}
|
|
|
|
return filtered;
|
|
};
|
|
return dialog;
|
|
}
|
|
}
|
|
})
|
|
|
|
function removeOutSoltAndLink(node, out_slot_i) {
|
|
let outNodes = node.getOutputNodes(out_slot_i);
|
|
if (!!node.getOutputNodes(out_slot_i)) {
|
|
outNodes.forEach(outNode => {
|
|
node.disconnectOutput(out_slot_i, outNode.id);
|
|
})
|
|
}
|
|
node.removeOutput(out_slot_i);
|
|
}
|
|
|
|
|
|
let filter_node_type = ['ForEachOpen', 'ForEachClose']
|
|
let output_fixed_num_for_filter_node_type = [3, 0]
|
|
|
|
app.registerExtension({
|
|
name: "Comfy.EasyApi.ForNode",
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
|
|
if (filter_node_type.indexOf(nodeData.name) > -1) {
|
|
let input_name = "initial_value";
|
|
let output_name = "value";
|
|
let fixed_head_input_names = ["flow_control"];
|
|
let fixed_tail_input_names = ["total"];
|
|
// 比py代码中定义少1,因为不含initial_value0
|
|
let max_number_of_inputs = 19;
|
|
let out_fixed_num = output_fixed_num_for_filter_node_type[filter_node_type.indexOf(nodeData.name)];
|
|
|
|
nodeType.prototype.onConnectionsChange = function (type, index, connected, link_info) {
|
|
if(!link_info)
|
|
return;
|
|
|
|
if(type == 2) {
|
|
// connect output
|
|
if (link_info.origin_slot >= out_fixed_num){
|
|
let fixed_head_solts = this.inputs.filter(x => fixed_head_input_names.indexOf(x.name) > -1);
|
|
let fixed_head_solt_count = fixed_head_solts ? fixed_head_solts.length : 0;
|
|
// 设置输入类型
|
|
let input_slot = link_info.origin_slot - out_fixed_num + fixed_head_solt_count
|
|
if (connected) {
|
|
let output_type = app.graph._nodes_by_id[link_info.target_id]?.inputs[link_info.target_slot]?.type
|
|
if(!this.inputs[input_slot]?.link && output_type !== "*") {
|
|
// 输入节点无连接
|
|
this.setOutputDataType(link_info.origin_slot, output_type)
|
|
this.inputs[input_slot].type = output_type
|
|
}
|
|
} else {
|
|
if(!this.inputs[input_slot]?.link && this.inputs[input_slot]?.type !== "*") {
|
|
this.setOutputDataType(link_info.origin_slot, "*")
|
|
if (input_slot < this.inputs.length) {
|
|
this.inputs[input_slot].type = "*";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (filter_node_type.indexOf(nodeData.name) > -1 && app.graph._nodes_by_id[link_info.origin_id].type == 'Reroute')
|
|
this.disconnectInput(link_info.target_slot);
|
|
|
|
// connect input
|
|
if (fixed_tail_input_names.indexOf(this.inputs[index].name) > -1 || fixed_head_input_names.indexOf(this.inputs[index].name) > -1)
|
|
return;
|
|
|
|
if (this.inputs[0].type == '*') {
|
|
const node = app.graph.getNodeById(link_info.origin_id);
|
|
let origin_type = node.outputs[link_info.origin_slot].type;
|
|
|
|
if (origin_type == '*') {
|
|
this.disconnectInput(link_info.target_slot);
|
|
return;
|
|
}
|
|
}
|
|
|
|
let fixed_head_solts = this.inputs.filter(x => fixed_head_input_names.indexOf(x.name) > -1);
|
|
let fixed_head_solt_count = fixed_head_solts ? fixed_head_solts.length : 0;
|
|
|
|
// let fixed_tail_solts = this.inputs.filter(x => fixed_tail_input_names.indexOf(x.name) > -1);
|
|
// let fixed_tail_solt_count = fixed_tail_solts ? fixed_tail_solts.length : 0;
|
|
// let converted_count = fixed_head_solt_count + fixed_tail_solt_count;
|
|
|
|
// 设置类型
|
|
if (connected) {
|
|
let input_type = app.graph._nodes_by_id[link_info.origin_id]?.outputs[link_info.origin_slot]?.type
|
|
if (!!input_type) {
|
|
this.inputs[link_info.target_slot].type = input_type
|
|
this.setOutputDataType(link_info.target_slot - fixed_head_solt_count + out_fixed_num, input_type)
|
|
}
|
|
} else {
|
|
let out_slot = link_info.target_slot - fixed_head_solt_count + out_fixed_num
|
|
if ((!this.outputs[out_slot]?.links || this.outputs[out_slot]?.links?.length == 0) && this.inputs[link_info.target_slot]?.type !== "*") {
|
|
this.inputs[link_info.target_slot].type = "*"
|
|
this.setOutputDataType(out_slot, "*")
|
|
}
|
|
}
|
|
|
|
// 给所有动态输入编号
|
|
let slot_i = 0;
|
|
for (let i = 0; i < this.inputs.length; i++) {
|
|
let input_i = this.inputs[i];
|
|
if (fixed_tail_input_names.indexOf(input_i.name) < 0 && fixed_head_input_names.indexOf(input_i.name) < 0) {
|
|
input_i.name = `${input_name}${slot_i + 1}`;
|
|
slot_i++;
|
|
}
|
|
}
|
|
|
|
if (connected && index == (fixed_head_solt_count + slot_i - 1)) {
|
|
if (max_number_of_inputs == slot_i) {
|
|
return;
|
|
}
|
|
slot_i++;
|
|
this.addInput(`${input_name}${slot_i}`, "*");
|
|
this.addOutput(`${output_name}${slot_i}`, "*");
|
|
}
|
|
|
|
// 最后面未连接的只保留一个
|
|
for (let i = fixed_head_solt_count + slot_i - 1; i >= 1; i--) {
|
|
let input_i_1 = this.inputs[i - 1];
|
|
let input_i = this.inputs[i];
|
|
if (fixed_head_input_names.indexOf(input_i_1.name) < 0 && !input_i_1.link && !input_i.link) {
|
|
// 删除最后一个输入插槽
|
|
this.removeInput(i);
|
|
// 对应输出有连线,断开连线
|
|
let out_slot_i = out_fixed_num + i - fixed_head_solt_count;
|
|
removeOutSoltAndLink(this, out_slot_i);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
let that = this;
|
|
// 找到所有 name 属性为 fixed_tail_input_name 的元素的索引
|
|
const indicesToMove = this.inputs.reduce((acc, item, index) => {
|
|
if (fixed_tail_input_names.indexOf(item.name) > -1) {
|
|
acc.push(index);
|
|
}
|
|
return acc;
|
|
}, []);
|
|
|
|
// 从原数组中移除这些元素
|
|
const elementsToMove = indicesToMove.map(index => that.inputs.splice(index, 1)).flat();
|
|
|
|
// 将这些元素添加到数组末尾
|
|
elementsToMove.forEach(element => that.inputs.push(element));
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
async nodeCreated(node, app) {
|
|
// Fires every time a node is constructed
|
|
// You can modify widgets/add handlers/etc here
|
|
if (filter_node_type.indexOf(node.title) > -1) {
|
|
let out_fixed_num = output_fixed_num_for_filter_node_type[filter_node_type.indexOf(node.title)];
|
|
if (node.id == -1) {
|
|
let input_name = "initial_value";
|
|
for (let i = node.inputs.length - 1; i >= 0; i--) {
|
|
let index = node.inputs[i].name.indexOf(input_name);
|
|
if (index == 0) {
|
|
let num = parseInt(node.inputs[i].name.replace(input_name, ""))
|
|
if (num > 1) {
|
|
node.removeInput(i)
|
|
}
|
|
}
|
|
}
|
|
for (let i = node.outputs.length - 1; i > out_fixed_num; i--) {
|
|
removeOutSoltAndLink(node, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}) |