mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-23 04:40:15 +08:00
Update litegraph
This commit is contained in:
parent
d1813201cc
commit
32fe4dc411
@ -91,6 +91,8 @@
|
|||||||
AUTOHIDE_TITLE: 3,
|
AUTOHIDE_TITLE: 3,
|
||||||
VERTICAL_LAYOUT: "vertical", // arrange nodes vertically
|
VERTICAL_LAYOUT: "vertical", // arrange nodes vertically
|
||||||
|
|
||||||
|
BASE_SLOT_TYPES: ["*", "array", "object", "number", "string", "enum", "boolean", "table"],
|
||||||
|
|
||||||
proxy: null, //used to redirect calls
|
proxy: null, //used to redirect calls
|
||||||
node_images_path: "",
|
node_images_path: "",
|
||||||
|
|
||||||
@ -148,6 +150,9 @@
|
|||||||
// use this if you must have node IDs that are unique across all graphs and subgraphs.
|
// use this if you must have node IDs that are unique across all graphs and subgraphs.
|
||||||
use_uuids: false,
|
use_uuids: false,
|
||||||
|
|
||||||
|
// use a combo widget for selecting graph input/output types instead of a text box
|
||||||
|
graph_inputs_outputs_use_combo_widget: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a node class so it can be listed when the user wants to create a new one
|
* Register a node class so it can be listed when the user wants to create a new one
|
||||||
* @method registerNodeType
|
* @method registerNodeType
|
||||||
@ -614,6 +619,40 @@
|
|||||||
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,a=>(a^Math.random()*16>>a/4).toString(16));
|
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,a=>(a^Math.random()*16>>a/4).toString(16));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getSlotTypeName: function(type) {
|
||||||
|
if (type === LiteGraph.EVENT || type === LiteGraph.ACTION) {
|
||||||
|
return "event"
|
||||||
|
}
|
||||||
|
else if (type === LiteGraph.DEFAULT) {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
},
|
||||||
|
|
||||||
|
getSlotTypesIn: function() {
|
||||||
|
let result = []
|
||||||
|
result = result.concat(LiteGraph.BASE_SLOT_TYPES)
|
||||||
|
result = result.concat([LiteGraph.EVENT])
|
||||||
|
result = result.concat(LiteGraph.slot_types_in)
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
||||||
|
getSlotTypesInFormatted: function() {
|
||||||
|
return LiteGraph.getSlotTypesIn().map(LiteGraph.getSlotTypeName);
|
||||||
|
},
|
||||||
|
|
||||||
|
getSlotTypesOut: function() {
|
||||||
|
let result = []
|
||||||
|
result = result.concat(LiteGraph.BASE_SLOT_TYPES)
|
||||||
|
result = result.concat([LiteGraph.EVENT])
|
||||||
|
result = result.concat(LiteGraph.slot_types_out)
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
||||||
|
getSlotTypesOutFormatted: function() {
|
||||||
|
return LiteGraph.getSlotTypesOut().map(LiteGraph.getSlotTypeName);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the types of two slots are compatible (taking into account wildcards, etc)
|
* Returns if the types of two slots are compatible (taking into account wildcards, etc)
|
||||||
* @method isValidConnection
|
* @method isValidConnection
|
||||||
@ -886,6 +925,10 @@
|
|||||||
this.list_of_graphcanvas = [];
|
this.list_of_graphcanvas = [];
|
||||||
}
|
}
|
||||||
this.list_of_graphcanvas.push(graphcanvas);
|
this.list_of_graphcanvas.push(graphcanvas);
|
||||||
|
|
||||||
|
if (graphcanvas.onGraphAttached) {
|
||||||
|
graphcanvas.onGraphAttached(this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -904,6 +947,10 @@
|
|||||||
}
|
}
|
||||||
graphcanvas.graph = null;
|
graphcanvas.graph = null;
|
||||||
this.list_of_graphcanvas.splice(pos, 1);
|
this.list_of_graphcanvas.splice(pos, 1);
|
||||||
|
|
||||||
|
if (graphcanvas.onGraphDetached) {
|
||||||
|
graphcanvas.onGraphDetached(this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5470,10 +5517,32 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
if (!this._graph_stack) {
|
if (!this._graph_stack) {
|
||||||
this._graph_stack = [];
|
this._graph_stack = [];
|
||||||
}
|
}
|
||||||
this._graph_stack.push(this.graph);
|
const offset = [this.ds.offset[0], this.ds.offset[1]]
|
||||||
|
this._graph_stack.push({ graph: this.graph, offset, scale: this.ds.scale });
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.attachCanvas(this);
|
graph.attachCanvas(this);
|
||||||
|
|
||||||
|
const offset = [0, 0]
|
||||||
|
|
||||||
|
if (graph._nodes.length > 0) {
|
||||||
|
let min_x = Number.MAX_SAFE_INTEGER;
|
||||||
|
let max_x = 0;
|
||||||
|
let min_y = Number.MAX_SAFE_INTEGER;
|
||||||
|
let max_y = 0;
|
||||||
|
for (const node of graph._nodes) {
|
||||||
|
min_x = Math.min(node.pos[0], min_x);
|
||||||
|
max_x = Math.max(node.pos[0] + node.size[0], max_x);
|
||||||
|
min_y = Math.min(node.pos[1], min_y);
|
||||||
|
max_y = Math.max(node.pos[1] + node.size[1], max_y);
|
||||||
|
}
|
||||||
|
offset[0] = -(min_x + (max_x - min_x) / 2) + this.canvas.width / 2;
|
||||||
|
offset[1] = -(min_y + (max_y - min_y) / 2) + this.canvas.height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ds.offset = offset;
|
||||||
|
this.ds.scale = 1
|
||||||
|
|
||||||
this.checkPanels();
|
this.checkPanels();
|
||||||
this.setDirty(true, true);
|
this.setDirty(true, true);
|
||||||
};
|
};
|
||||||
@ -5488,8 +5557,8 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
if (!this._graph_stack || this._graph_stack.length == 0) {
|
if (!this._graph_stack || this._graph_stack.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var subgraph_node = this.graph._subgraph_node;
|
const subgraph_node = this.graph._subgraph_node;
|
||||||
var graph = this._graph_stack.pop();
|
const { graph, offset, scale } = this._graph_stack.pop();
|
||||||
this.selected_nodes = {};
|
this.selected_nodes = {};
|
||||||
this.highlighted_links = {};
|
this.highlighted_links = {};
|
||||||
graph.attachCanvas(this);
|
graph.attachCanvas(this);
|
||||||
@ -5498,9 +5567,14 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
this.centerOnNode(subgraph_node);
|
this.centerOnNode(subgraph_node);
|
||||||
this.selectNodes([subgraph_node]);
|
this.selectNodes([subgraph_node]);
|
||||||
}
|
}
|
||||||
// when close sub graph back to offset [0, 0] scale 1
|
this.ds.offset = offset
|
||||||
this.ds.offset = [0, 0]
|
this.ds.scale = scale
|
||||||
this.ds.scale = 1
|
};
|
||||||
|
|
||||||
|
LGraphCanvas.prototype.closeAllSubgraphs = function() {
|
||||||
|
while (this._graph_stack && this._graph_stack.length > 0) {
|
||||||
|
this.closeSubgraph();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7366,6 +7440,10 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
if (this.onShowNodePanel) {
|
if (this.onShowNodePanel) {
|
||||||
this.onShowNodePanel(n);
|
this.onShowNodePanel(n);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.showShowNodePanel(n);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.onNodeDblClicked) {
|
if (this.onNodeDblClicked) {
|
||||||
this.onNodeDblClicked(n);
|
this.onNodeDblClicked(n);
|
||||||
@ -8053,27 +8131,6 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
if (input.not_subgraph_input)
|
if (input.not_subgraph_input)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//input button clicked
|
|
||||||
if (this.drawButton(20, y + 2, w - 20, h - 2)) {
|
|
||||||
var type = subnode.constructor.input_node_type || "graph/input";
|
|
||||||
this.graph.beforeChange();
|
|
||||||
var newnode = LiteGraph.createNode(type);
|
|
||||||
if (newnode) {
|
|
||||||
subgraph.add(newnode);
|
|
||||||
this.block_click = false;
|
|
||||||
this.last_click_position = null;
|
|
||||||
this.selectNodes([newnode]);
|
|
||||||
this.node_dragged = newnode;
|
|
||||||
this.dragging_canvas = false;
|
|
||||||
newnode.setProperty("name", input.name);
|
|
||||||
newnode.setProperty("type", input.type);
|
|
||||||
this.node_dragged.pos[0] = this.graph_mouse[0] - 5;
|
|
||||||
this.node_dragged.pos[1] = this.graph_mouse[1] - 5;
|
|
||||||
this.graph.afterChange();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
console.error("graph input node not found:", type);
|
|
||||||
}
|
|
||||||
ctx.fillStyle = "#9C9";
|
ctx.fillStyle = "#9C9";
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(w - 16, y + h * 0.5, 5, 0, 2 * Math.PI);
|
ctx.arc(w - 16, y + h * 0.5, 5, 0, 2 * Math.PI);
|
||||||
@ -8123,27 +8180,6 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
if (output.not_subgraph_input)
|
if (output.not_subgraph_input)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//output button clicked
|
|
||||||
if (this.drawButton(canvas_w - w, y + 2, w - 20, h - 2)) {
|
|
||||||
var type = subnode.constructor.output_node_type || "graph/output";
|
|
||||||
this.graph.beforeChange();
|
|
||||||
var newnode = LiteGraph.createNode(type);
|
|
||||||
if (newnode) {
|
|
||||||
subgraph.add(newnode);
|
|
||||||
this.block_click = false;
|
|
||||||
this.last_click_position = null;
|
|
||||||
this.selectNodes([newnode]);
|
|
||||||
this.node_dragged = newnode;
|
|
||||||
this.dragging_canvas = false;
|
|
||||||
newnode.setProperty("name", output.name);
|
|
||||||
newnode.setProperty("type", output.type);
|
|
||||||
this.node_dragged.pos[0] = this.graph_mouse[0] - 5;
|
|
||||||
this.node_dragged.pos[1] = this.graph_mouse[1] - 5;
|
|
||||||
this.graph.afterChange();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
console.error("graph input node not found:", type);
|
|
||||||
}
|
|
||||||
ctx.fillStyle = "#9C9";
|
ctx.fillStyle = "#9C9";
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(canvas_w - w + 16, y + h * 0.5, 5, 0, 2 * Math.PI);
|
ctx.arc(canvas_w - w + 16, y + h * 0.5, 5, 0, 2 * Math.PI);
|
||||||
@ -8272,8 +8308,9 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
//show subgraph stack header
|
//show subgraph stack header
|
||||||
if (this._graph_stack && this._graph_stack.length) {
|
if (this._graph_stack && this._graph_stack.length) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
var parent_graph = this._graph_stack[this._graph_stack.length - 1];
|
const top_entry = this._graph_stack[this._graph_stack.length - 1];
|
||||||
var subgraph_node = this.graph._subgraph_node;
|
const parent_graph = top_entry.graph;
|
||||||
|
const subgraph_node = this.graph._subgraph_node;
|
||||||
ctx.strokeStyle = subgraph_node.bgcolor;
|
ctx.strokeStyle = subgraph_node.bgcolor;
|
||||||
ctx.lineWidth = 10;
|
ctx.lineWidth = 10;
|
||||||
ctx.strokeRect(1, 1, canvas.width - 2, canvas.height - 2);
|
ctx.strokeRect(1, 1, canvas.width - 2, canvas.height - 2);
|
||||||
@ -12694,31 +12731,74 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
elem.querySelector(".name").innerText = input.name;
|
elem.querySelector(".name").innerText = input.name;
|
||||||
elem.querySelector(".type").innerText = input.type;
|
elem.querySelector(".type").innerText = input.type;
|
||||||
elem.querySelector("button").addEventListener("click",function(e){
|
elem.querySelector("button").addEventListener("click",function(e){
|
||||||
node.removeInput( Number( this.parentNode.dataset["slot"] ) );
|
const inputName = this.parentNode.dataset["name"]
|
||||||
|
node.removeGraphInput(inputName);
|
||||||
inner_refresh();
|
inner_refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
node.graph.setDirtyCanvas(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add extra
|
//add extra
|
||||||
var html = " + <span class='label'>Name</span><input class='name'/><span class='label'>Type</span><input class='type'></input><button>+</button>";
|
var html = `
|
||||||
var elem = panel.addHTML(html,"subgraph_property extra", true);
|
+
|
||||||
elem.querySelector("button").addEventListener("click", function(e){
|
<span class='label'>Name</span>
|
||||||
var elem = this.parentNode;
|
<input class='name'/>
|
||||||
var name = elem.querySelector(".name").value;
|
<span class='label'>Type</span>
|
||||||
var type = elem.querySelector(".type").value;
|
<select class='type'></select>
|
||||||
if(!name || node.findInputSlot(name) != -1)
|
<button>+</button>`;
|
||||||
return;
|
var elem = panel.addHTML(html, "subgraph_property extra", true);
|
||||||
node.addInput(name,type);
|
const nameInput = elem.querySelector(".name");
|
||||||
elem.querySelector(".name").value = "";
|
const typeInput = elem.querySelector(".type");
|
||||||
elem.querySelector(".type").value = "";
|
const addButton = elem.querySelector("button");
|
||||||
inner_refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
inner_refresh();
|
for (const inType of LiteGraph.getSlotTypesIn()) {
|
||||||
this.canvas.parentNode.appendChild(panel);
|
var opt = document.createElement('option');
|
||||||
return panel;
|
opt.value = inType
|
||||||
|
opt.innerHTML = LiteGraph.getSlotTypeName(inType)
|
||||||
|
typeInput.appendChild(opt);
|
||||||
|
if (inType === "*") {
|
||||||
|
opt.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addInput = () => {
|
||||||
|
const name = nameInput.value;
|
||||||
|
let type = typeInput.value;
|
||||||
|
if (type === "-1")
|
||||||
|
type = BuiltInSlotType.EVENT;
|
||||||
|
|
||||||
|
if (!name || node.findInputSlot(name) != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.addGraphInputNode(node, name, type)
|
||||||
|
nameInput.value = "";
|
||||||
|
typeInput.value = "";
|
||||||
|
inner_refresh();
|
||||||
|
nameInput.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkSubmit = (e) => {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
addInput()
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
else if (e.keyCode == 27) {
|
||||||
|
panel.close();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addButton.addEventListener("click", addInput);
|
||||||
|
nameInput.addEventListener("keydown", checkSubmit);
|
||||||
|
typeInput.addEventListener("keydown", checkSubmit);
|
||||||
|
|
||||||
|
inner_refresh();
|
||||||
|
this.canvas.parentNode.appendChild(panel);
|
||||||
|
nameInput.focus();
|
||||||
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
LGraphCanvas.prototype.showSubgraphPropertiesDialogRight = function (node) {
|
LGraphCanvas.prototype.showSubgraphPropertiesDialogRight = function (node) {
|
||||||
|
|
||||||
// console.log("showing subgraph properties dialog");
|
// console.log("showing subgraph properties dialog");
|
||||||
@ -12747,52 +12827,158 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
elem.querySelector(".name").innerText = input.name;
|
elem.querySelector(".name").innerText = input.name;
|
||||||
elem.querySelector(".type").innerText = input.type;
|
elem.querySelector(".type").innerText = input.type;
|
||||||
elem.querySelector("button").addEventListener("click", function (e) {
|
elem.querySelector("button").addEventListener("click", function (e) {
|
||||||
node.removeOutput(Number(this.parentNode.dataset["slot"]));
|
const outputName = this.parentNode.dataset["name"]
|
||||||
|
node.removeGraphOutput(outputName);
|
||||||
inner_refresh();
|
inner_refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
node.graph.setDirtyCanvas(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add extra
|
//add extra
|
||||||
var html = " + <span class='label'>Name</span><input class='name'/><span class='label'>Type</span><input class='type'></input><button>+</button>";
|
var html = `
|
||||||
|
+
|
||||||
|
<span class='label'>Name</span>
|
||||||
|
<input class='name'/>
|
||||||
|
<span class='label'>Type</span>
|
||||||
|
<select class='type'></select>
|
||||||
|
<button>+</button>`;
|
||||||
var elem = panel.addHTML(html, "subgraph_property extra", true);
|
var elem = panel.addHTML(html, "subgraph_property extra", true);
|
||||||
elem.querySelector(".name").addEventListener("keydown", function (e) {
|
const nameInput = elem.querySelector(".name");
|
||||||
if (e.keyCode == 13) {
|
const typeInput = elem.querySelector(".type");
|
||||||
addOutput.apply(this)
|
const addButton = elem.querySelector("button");
|
||||||
|
|
||||||
|
for (const outType of LiteGraph.getSlotTypesOut()) {
|
||||||
|
var opt = document.createElement('option');
|
||||||
|
opt.value = outType
|
||||||
|
opt.innerHTML = LiteGraph.getSlotTypeName(outType)
|
||||||
|
typeInput.appendChild(opt);
|
||||||
|
if (outType === "*") {
|
||||||
|
opt.selected = true;
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
elem.querySelector("button").addEventListener("click", function (e) {
|
|
||||||
addOutput.apply(this)
|
const addOutput = () => {
|
||||||
});
|
const name = nameInput.value;
|
||||||
function addOutput() {
|
let type = typeInput.value;
|
||||||
var elem = this.parentNode;
|
if (type === "-1")
|
||||||
var name = elem.querySelector(".name").value;
|
type = BuiltInSlotType.EVENT;
|
||||||
var type = elem.querySelector(".type").value;
|
|
||||||
if (!name || node.findOutputSlot(name) != -1)
|
if (!name || node.findOutputSlot(name) != -1)
|
||||||
return;
|
return;
|
||||||
node.addOutput(name, type);
|
|
||||||
elem.querySelector(".name").value = "";
|
this.addGraphOutputNode(node, name, type)
|
||||||
elem.querySelector(".type").value = "";
|
nameInput.value = "";
|
||||||
|
typeInput.value = "";
|
||||||
inner_refresh();
|
inner_refresh();
|
||||||
|
nameInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkSubmit = (e) => {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
addOutput()
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
else if (e.keyCode == 27) {
|
||||||
|
panel.close();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addButton.addEventListener("click", addOutput);
|
||||||
|
nameInput.addEventListener("keydown", checkSubmit);
|
||||||
|
typeInput.addEventListener("keydown", checkSubmit);
|
||||||
|
|
||||||
inner_refresh();
|
inner_refresh();
|
||||||
this.canvas.parentNode.appendChild(panel);
|
this.canvas.parentNode.appendChild(panel);
|
||||||
|
nameInput.focus();
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LGraphCanvas.prototype.addGraphInputNode = function(subgraphNode, name, type) {
|
||||||
|
// Check if there's already an input
|
||||||
|
const existing = this.graph.findNodesByType("graph/input")
|
||||||
|
.find(node => node.properties.name === name)
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
this.selectNodes([existing])
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// graph input node must have a non-empty type
|
||||||
|
if (!type || type === "")
|
||||||
|
type = "*"
|
||||||
|
|
||||||
|
const pos = [
|
||||||
|
(this.canvas.width * 0.25) / this.ds.scale - this.ds.offset[0],
|
||||||
|
(this.canvas.height * 0.5) / this.ds.scale - this.ds.offset[1]
|
||||||
|
]
|
||||||
|
|
||||||
|
this.graph.beforeChange();
|
||||||
|
const pair = subgraphNode.addGraphInput(name, type, pos);
|
||||||
|
if (pair) {
|
||||||
|
const newnode = pair.innerNode;
|
||||||
|
this.selectNodes([newnode]);
|
||||||
|
this.graph.afterChange();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("graph input node not found:", type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LGraphCanvas.prototype.addGraphOutputNode = function(subgraphNode, name, type) {
|
||||||
|
// Check if there's already an output
|
||||||
|
const existing = this.graph.findNodesByType("graph/output")
|
||||||
|
.find(node => node.properties.name === name)
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
this.selectNodes([existing])
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// graph output node must have a non-empty type
|
||||||
|
if (!type || type === "")
|
||||||
|
type = "*"
|
||||||
|
|
||||||
|
const pos = [
|
||||||
|
(this.canvas.width * 0.75) / this.ds.scale - this.ds.offset[0],
|
||||||
|
(this.canvas.height * 0.5) / this.ds.scale - this.ds.offset[1]
|
||||||
|
]
|
||||||
|
|
||||||
|
this.graph.beforeChange();
|
||||||
|
const pair = subgraphNode.addGraphOutput(name, type, pos);
|
||||||
|
if (pair) {
|
||||||
|
const newnode = pair.innerNode;
|
||||||
|
this.selectNodes([newnode]);
|
||||||
|
this.graph.afterChange();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("graph input node not found:", type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LGraphCanvas.prototype.checkPanels = function()
|
LGraphCanvas.prototype.checkPanels = function()
|
||||||
{
|
{
|
||||||
if(!this.canvas)
|
if (!this.canvas)
|
||||||
return;
|
return;
|
||||||
var panels = this.canvas.parentNode.querySelectorAll(".litegraph.dialog");
|
|
||||||
for(var i = 0; i < panels.length; ++i)
|
var panels = this.canvas.parentNode.querySelectorAll(".litegraph.dialog");
|
||||||
{
|
for (var i = 0; i < panels.length; ++i) {
|
||||||
var panel = panels[i];
|
var panel = panels[i]
|
||||||
if( !panel.node )
|
if (!panel.node)
|
||||||
continue;
|
continue;
|
||||||
if( !panel.node.graph || panel.graph != this.graph )
|
if (!panel.node.graph)
|
||||||
panel.close();
|
panel.close();
|
||||||
}
|
|
||||||
|
if (panel.node.graph != this.graph) {
|
||||||
|
if (panel.node.type === "graph/subgraph" && this.graph._is_subgraph && this.graph === panel.node.subgraph) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panel.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LGraphCanvas.onMenuNodeCollapse = function(value, options, e, menu, node) {
|
LGraphCanvas.onMenuNodeCollapse = function(value, options, e, menu, node) {
|
||||||
@ -13132,10 +13318,6 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
has_submenu: true,
|
has_submenu: true,
|
||||||
callback: LGraphCanvas.onShowMenuNodeProperties
|
callback: LGraphCanvas.onShowMenuNodeProperties
|
||||||
},
|
},
|
||||||
{
|
|
||||||
content: "Properties Panel",
|
|
||||||
callback: function(item, options, e, menu, node) { LGraphCanvas.active_canvas.showShowNodePanel(node) }
|
|
||||||
},
|
|
||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
content: "Title",
|
content: "Title",
|
||||||
@ -14774,6 +14956,158 @@ if (typeof exports != "undefined") {
|
|||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Subgraph.prototype.getValidGraphInputName = function(baseName)
|
||||||
|
{
|
||||||
|
baseName = baseName ||"newInput"
|
||||||
|
let name = baseName
|
||||||
|
let existing = this.getInnerGraphInput(name)
|
||||||
|
let i = 1;
|
||||||
|
while (existing != null) {
|
||||||
|
name = `${baseName}_${i++}`
|
||||||
|
existing = this.getInnerGraphInput(name)
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.getValidGraphOutputName = function(baseName)
|
||||||
|
{
|
||||||
|
baseName = baseName || "newOutput"
|
||||||
|
let name = baseName
|
||||||
|
let existing = this.getInnerGraphOutput(name)
|
||||||
|
let i = 1;
|
||||||
|
while (existing != null) {
|
||||||
|
name = `${baseName}_${i++}`
|
||||||
|
existing = this.getInnerGraphOutput(name)
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.getInnerGraphInput = function(outerInputName) {
|
||||||
|
const graphInput = this.subgraph._nodes.find(n => {
|
||||||
|
return n.type === "graph/input"
|
||||||
|
&& n.properties.name === outerInputName
|
||||||
|
})
|
||||||
|
|
||||||
|
return graphInput || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.getInnerGraphOutput = function(outerOutputName) {
|
||||||
|
const graphOutput = this.subgraph._nodes.find(n => {
|
||||||
|
return n.type === "graph/output"
|
||||||
|
&& n.properties.name === outerOutputName
|
||||||
|
})
|
||||||
|
|
||||||
|
return graphOutput || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.addGraphInput = function(name, type, pos) {
|
||||||
|
name = this.getValidGraphInputName(name)
|
||||||
|
|
||||||
|
const innerNode = LiteGraph.createNode("graph/input");
|
||||||
|
if (innerNode == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
let outerType = type;
|
||||||
|
|
||||||
|
// console.debug("[Subgraph] addGraphInput", name, type, outerType, pos)
|
||||||
|
|
||||||
|
// These will run onPropertyChanged.
|
||||||
|
innerNode.setProperty("name", name)
|
||||||
|
innerNode.setProperty("type", type)
|
||||||
|
|
||||||
|
this.subgraph.add(innerNode);
|
||||||
|
const nodeSize = innerNode.computeSize();
|
||||||
|
if (pos)
|
||||||
|
innerNode.pos = [pos[0] - nodeSize[0] * 0.5, pos[1] - nodeSize[1] * 0.5];
|
||||||
|
|
||||||
|
// The following call will add an input slot to this node automatically from onSubgraphNewInput.
|
||||||
|
this.subgraph.addInput(name, outerType, null);
|
||||||
|
|
||||||
|
const outerInputIndex = this.inputs.length - 1;
|
||||||
|
const outerInput = this.inputs[outerInputIndex]
|
||||||
|
|
||||||
|
return { innerNode, outerInput, outerInputIndex }
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.addGraphOutput = function(name, type, pos) {
|
||||||
|
name = this.getValidGraphOutputName(name)
|
||||||
|
|
||||||
|
const innerNode = LiteGraph.createNode("graph/output");
|
||||||
|
if (innerNode == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
let outerType = type;
|
||||||
|
|
||||||
|
// console.debug("[Subgraph] addGraphOutput", name, type, outerType, pos)
|
||||||
|
|
||||||
|
// These will run onPropertyChanged.
|
||||||
|
innerNode.setProperty("name", name)
|
||||||
|
innerNode.setProperty("type", type)
|
||||||
|
|
||||||
|
this.subgraph.add(innerNode);
|
||||||
|
const nodeSize = innerNode.computeSize();
|
||||||
|
if (pos)
|
||||||
|
innerNode.pos = [pos[0], pos[1] - nodeSize[1] * 0.5];
|
||||||
|
|
||||||
|
// The following call will add an output slot to this node automatically from onSubgraphNewOutput.
|
||||||
|
this.subgraph.addOutput(name, outerType, null);
|
||||||
|
|
||||||
|
const outerOutputIndex = this.outputs.length - 1;
|
||||||
|
const outerOutput = this.outputs[outerOutputIndex]
|
||||||
|
|
||||||
|
return { innerNode, outerOutput, outerOutputIndex }
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.removeGraphInput = function(inputName) {
|
||||||
|
const inputSlot = this.findInputSlot(inputName);
|
||||||
|
if (inputSlot == null) {
|
||||||
|
console.error("[Subgraph] No input in slot!", inputName)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const innerNodes = this.subgraph.findNodesByType("graph/input").filter(n => n.properties.name === inputName);
|
||||||
|
|
||||||
|
if (innerNodes.length > 0) {
|
||||||
|
// Removing the nodes will also trigger removeInput from subgraph hooks
|
||||||
|
for (const node of innerNodes) {
|
||||||
|
this.subgraph.remove(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn("[Subgraph] No GraphInputs found on input removal", inputName)
|
||||||
|
|
||||||
|
// remove the input ourselves since no subgraph hook was triggered
|
||||||
|
const index = this.findInputSlot(inputName)
|
||||||
|
if (index !== -1)
|
||||||
|
this.removeInput(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Subgraph.prototype.removeGraphOutput = function(outputName) {
|
||||||
|
const outputSlot = this.findOutputSlot(outputName);
|
||||||
|
if (outputSlot == null) {
|
||||||
|
console.error("[Subgraph] No output in slot!", outputName)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const innerNodes = this.subgraph.findNodesByType("graph/output").filter(n => n.properties.name === outputName);
|
||||||
|
|
||||||
|
if (innerNodes.length > 0) {
|
||||||
|
// Removing the nodes will also trigger removeOutput from subgraph hooks
|
||||||
|
for (const node of innerNodes) {
|
||||||
|
this.subgraph.remove(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn("[Subgraph] No GraphOutputs found on output removal", outputName)
|
||||||
|
|
||||||
|
// remove the output ourselves since no subgraph hook was triggered
|
||||||
|
const index = this.findOutputSlot(outputName)
|
||||||
|
if (index !== -1)
|
||||||
|
this.removeOutput(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Subgraph.prototype.buildFromNodes = function(nodes)
|
Subgraph.prototype.buildFromNodes = function(nodes)
|
||||||
{
|
{
|
||||||
//clear all?
|
//clear all?
|
||||||
@ -14869,6 +15203,7 @@ if (typeof exports != "undefined") {
|
|||||||
//Input for a subgraph
|
//Input for a subgraph
|
||||||
function GraphInput() {
|
function GraphInput() {
|
||||||
this.addOutput("", "number");
|
this.addOutput("", "number");
|
||||||
|
this.clonable = false;
|
||||||
|
|
||||||
this.name_in_graph = "";
|
this.name_in_graph = "";
|
||||||
this.properties = {
|
this.properties = {
|
||||||
@ -14883,28 +15218,33 @@ if (typeof exports != "undefined") {
|
|||||||
"text",
|
"text",
|
||||||
"Name",
|
"Name",
|
||||||
this.properties.name,
|
this.properties.name,
|
||||||
function(v) {
|
this.setName.bind(this),
|
||||||
if (!v) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
that.setProperty("name",v);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.type_widget = this.addWidget(
|
|
||||||
"text",
|
|
||||||
"Type",
|
|
||||||
this.properties.type,
|
|
||||||
function(v) {
|
|
||||||
that.setProperty("type",v);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (LiteGraph.graph_inputs_outputs_use_combo_widget) {
|
||||||
|
this.type_widget = this.addWidget(
|
||||||
|
"combo",
|
||||||
|
"Type",
|
||||||
|
LiteGraph.getSlotTypeName(this.properties.type),
|
||||||
|
this.setType.bind(this),
|
||||||
|
{ values: LiteGraph.getSlotTypesInFormatted }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.type_widget = this.addWidget(
|
||||||
|
"text",
|
||||||
|
"Type",
|
||||||
|
LiteGraph.getSlotTypeName(this.properties.type),
|
||||||
|
this.setType.bind(this),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.value_widget = this.addWidget(
|
this.value_widget = this.addWidget(
|
||||||
"number",
|
"number",
|
||||||
"Value",
|
"Value",
|
||||||
this.properties.value,
|
this.properties.value,
|
||||||
function(v) {
|
function(v) {
|
||||||
that.setProperty("value",v);
|
that.setProperty("value", v);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -14916,15 +15256,45 @@ if (typeof exports != "undefined") {
|
|||||||
GraphInput.desc = "Input of the graph";
|
GraphInput.desc = "Input of the graph";
|
||||||
|
|
||||||
GraphInput.prototype.onConfigure = function()
|
GraphInput.prototype.onConfigure = function()
|
||||||
|
|
||||||
{
|
{
|
||||||
this.updateType();
|
this.updateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphInput.prototype.setName = function(v)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (v == null || v === this.properties.name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const subgraph = this.graph._subgraph_node
|
||||||
|
if (!subgraph)
|
||||||
|
return;
|
||||||
|
v = subgraph.getValidGraphInputName(v);
|
||||||
|
this.setProperty("name", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphInput.prototype.setType = function(v)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (!v) {
|
||||||
|
v = "*"
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = v;
|
||||||
|
if (v === "-1" || v === "event")
|
||||||
|
type = LiteGraph.EVENT
|
||||||
|
else if (v === "0")
|
||||||
|
type = "*"
|
||||||
|
|
||||||
|
this.setProperty("type", type);
|
||||||
|
}
|
||||||
|
|
||||||
//ensures the type in the node output and the type in the associated graph input are the same
|
//ensures the type in the node output and the type in the associated graph input are the same
|
||||||
GraphInput.prototype.updateType = function()
|
GraphInput.prototype.updateType = function()
|
||||||
{
|
{
|
||||||
var type = this.properties.type;
|
var type = this.properties.type;
|
||||||
this.type_widget.value = type;
|
this.type_widget.value = LiteGraph.getSlotTypeName(type);
|
||||||
|
|
||||||
//update output
|
//update output
|
||||||
if(this.outputs[0].type != type)
|
if(this.outputs[0].type != type)
|
||||||
@ -15029,56 +15399,37 @@ if (typeof exports != "undefined") {
|
|||||||
//Output for a subgraph
|
//Output for a subgraph
|
||||||
function GraphOutput() {
|
function GraphOutput() {
|
||||||
this.addInput("", "");
|
this.addInput("", "");
|
||||||
|
this.clonable = false;
|
||||||
|
|
||||||
this.name_in_graph = "";
|
this.name_in_graph = "";
|
||||||
this.properties = { name: "", type: "" };
|
this.properties = { name: "", type: "" };
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
// Object.defineProperty(this.properties, "name", {
|
this.name_widget = this.addWidget(
|
||||||
// get: function() {
|
"text",
|
||||||
// return that.name_in_graph;
|
"Name",
|
||||||
// },
|
this.properties.name,
|
||||||
// set: function(v) {
|
this.setName.bind(this)
|
||||||
// if (v == "" || v == that.name_in_graph) {
|
);
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (that.name_in_graph) {
|
|
||||||
// //already added
|
|
||||||
// that.graph.renameOutput(that.name_in_graph, v);
|
|
||||||
// } else {
|
|
||||||
// that.graph.addOutput(v, that.properties.type);
|
|
||||||
// }
|
|
||||||
// that.name_widget.value = v;
|
|
||||||
// that.name_in_graph = v;
|
|
||||||
// },
|
|
||||||
// enumerable: true
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Object.defineProperty(this.properties, "type", {
|
if (LiteGraph.graph_inputs_outputs_use_combo_widget) {
|
||||||
// get: function() {
|
this.type_widget = this.addWidget(
|
||||||
// return that.inputs[0].type;
|
"combo",
|
||||||
// },
|
"Type",
|
||||||
// set: function(v) {
|
LiteGraph.getSlotTypeName(this.properties.type),
|
||||||
// if (v == "action" || v == "event") {
|
this.setType.bind(this),
|
||||||
// v = LiteGraph.ACTION;
|
{ values: LiteGraph.getSlotTypesOutFormatted }
|
||||||
// }
|
);
|
||||||
// if (!LiteGraph.isValidConnection(that.inputs[0].type,v))
|
}
|
||||||
// that.disconnectInput(0);
|
else {
|
||||||
// that.inputs[0].type = v;
|
this.type_widget = this.addWidget(
|
||||||
// if (that.name_in_graph) {
|
"text",
|
||||||
// //already added
|
"Type",
|
||||||
// that.graph.changeOutputType(
|
LiteGraph.getSlotTypeName(this.properties.type),
|
||||||
// that.name_in_graph,
|
this.setType.bind(this),
|
||||||
// that.inputs[0].type
|
);
|
||||||
// );
|
}
|
||||||
// }
|
|
||||||
// that.type_widget.value = v || "";
|
|
||||||
// },
|
|
||||||
// enumerable: true
|
|
||||||
// });
|
|
||||||
|
|
||||||
this.name_widget = this.addWidget("text","Name",this.properties.name,"name");
|
|
||||||
this.type_widget = this.addWidget("text","Type",this.properties.type,"type");
|
|
||||||
this.widgets_up = true;
|
this.widgets_up = true;
|
||||||
this.size = [180, 60];
|
this.size = [180, 60];
|
||||||
}
|
}
|
||||||
@ -15086,6 +15437,31 @@ if (typeof exports != "undefined") {
|
|||||||
GraphOutput.title = "Output";
|
GraphOutput.title = "Output";
|
||||||
GraphOutput.desc = "Output of the graph";
|
GraphOutput.desc = "Output of the graph";
|
||||||
|
|
||||||
|
GraphOutput.prototype.setName = function (v) {
|
||||||
|
if (v == null || v === this.properties.name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const subgraph = this.graph._subgraph_node
|
||||||
|
if (!subgraph)
|
||||||
|
return;
|
||||||
|
v = subgraph.getValidGraphOutputName(v);
|
||||||
|
this.setProperty("name", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphOutput.prototype.setType = function (v) {
|
||||||
|
if (!v) {
|
||||||
|
v = "*"
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = v;
|
||||||
|
if (v === "-1" || v === "event")
|
||||||
|
type = LiteGraph.EVENT
|
||||||
|
else if (v === "0")
|
||||||
|
type = "*"
|
||||||
|
|
||||||
|
this.setProperty("type", type);
|
||||||
|
}
|
||||||
|
|
||||||
GraphOutput.prototype.onPropertyChanged = function (name, v) {
|
GraphOutput.prototype.onPropertyChanged = function (name, v) {
|
||||||
if (name == "name") {
|
if (name == "name") {
|
||||||
if (v == "" || v == this.name_in_graph || v == "enabled") {
|
if (v == "" || v == this.name_in_graph || v == "enabled") {
|
||||||
@ -15112,7 +15488,7 @@ if (typeof exports != "undefined") {
|
|||||||
GraphOutput.prototype.updateType = function () {
|
GraphOutput.prototype.updateType = function () {
|
||||||
var type = this.properties.type;
|
var type = this.properties.type;
|
||||||
if (this.type_widget)
|
if (this.type_widget)
|
||||||
this.type_widget.value = type;
|
this.type_widget.value = LiteGraph.getSlotTypeName(type);
|
||||||
|
|
||||||
//update output
|
//update output
|
||||||
if (this.inputs[0].type != type) {
|
if (this.inputs[0].type != type) {
|
||||||
|
|||||||
@ -438,13 +438,20 @@
|
|||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.litegraph .subgraph_property > select.type {
|
||||||
|
margin-right: 20px;
|
||||||
|
padding-left: 4px;
|
||||||
|
background-color: black;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.litegraph .subgraph_property span.label {
|
.litegraph .subgraph_property span.label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.litegraph .subgraph_property input {
|
.litegraph .subgraph_property input, .litegraph .subgraph_property select {
|
||||||
width: 140px;
|
width: 140px;
|
||||||
color: #999;
|
color: #999;
|
||||||
background-color: #1A1A1A;
|
background-color: #1A1A1A;
|
||||||
@ -468,7 +475,7 @@
|
|||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.litegraph .subgraph_property.extra input {
|
.litegraph .subgraph_property.extra input, .litegraph .subgraph_property.extra select {
|
||||||
background-color: #111;
|
background-color: #111;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,7 @@ export class ComfyApp {
|
|||||||
*/
|
*/
|
||||||
this.nodePreviewImages = {};
|
this.nodePreviewImages = {};
|
||||||
|
|
||||||
|
/**
|
||||||
* Stores `true` for nodes that are executing (the node or its parent subgraphs)
|
* Stores `true` for nodes that are executing (the node or its parent subgraphs)
|
||||||
* @type {Set<string>}
|
* @type {Set<string>}
|
||||||
*/
|
*/
|
||||||
@ -828,6 +829,25 @@ export class ComfyApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies widgets when graph is changed
|
||||||
|
*/
|
||||||
|
#addCanvasAttachDetachHandlers() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
LGraphCanvas.prototype.onGraphAttached = function(graph) {
|
||||||
|
if (node.onGraphAttached)
|
||||||
|
node.onGraphAttached()
|
||||||
|
}
|
||||||
|
|
||||||
|
LGraphCanvas.prototype.onGraphDetached = function(graph) {
|
||||||
|
for (const node of graph._nodes) {
|
||||||
|
if (node.onGraphDetached)
|
||||||
|
node.onGraphDetached()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws node highlights (executing, drag drop) and progress bar
|
* Draws node highlights (executing, drag drop) and progress bar
|
||||||
*/
|
*/
|
||||||
@ -1034,6 +1054,7 @@ export class ComfyApp {
|
|||||||
*/
|
*/
|
||||||
async setup() {
|
async setup() {
|
||||||
LiteGraph.use_uuids = true;
|
LiteGraph.use_uuids = true;
|
||||||
|
LiteGraph.graph_inputs_outputs_use_combo_widget = true;
|
||||||
LiteGraph.registered_node_types["graph/input"].skip_list = true;
|
LiteGraph.registered_node_types["graph/input"].skip_list = true;
|
||||||
LiteGraph.registered_node_types["graph/output"].skip_list = true;
|
LiteGraph.registered_node_types["graph/output"].skip_list = true;
|
||||||
|
|
||||||
|
|||||||
@ -179,6 +179,7 @@ function addMultilineWidget(node, name, opts, app) {
|
|||||||
};
|
};
|
||||||
widget.inputEl = document.createElement("textarea");
|
widget.inputEl = document.createElement("textarea");
|
||||||
widget.inputEl.className = "comfy-multiline-input";
|
widget.inputEl.className = "comfy-multiline-input";
|
||||||
|
widget.inputEl.style.display = "none";
|
||||||
widget.inputEl.value = opts.defaultVal;
|
widget.inputEl.value = opts.defaultVal;
|
||||||
widget.inputEl.placeholder = opts.placeholder || "";
|
widget.inputEl.placeholder = opts.placeholder || "";
|
||||||
document.addEventListener("mousedown", function (event) {
|
document.addEventListener("mousedown", function (event) {
|
||||||
@ -216,6 +217,14 @@ function addMultilineWidget(node, name, opts, app) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
node.onGraphAttached = function() {
|
||||||
|
widget.inputEl.style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
node.onGraphDetached = function() {
|
||||||
|
widget.inputEl.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
widget.onRemove = () => {
|
widget.onRemove = () => {
|
||||||
widget.inputEl?.remove();
|
widget.inputEl?.remove();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user