diff --git a/css/litegraph.css b/css/litegraph.css
index 51fa4a18f..b32be79bf 100755
--- a/css/litegraph.css
+++ b/css/litegraph.css
@@ -578,3 +578,54 @@
background-color: white;
color: black;
}
+
+.litegraph .dialog {
+ min-height: 0;
+}
+.litegraph .dialog .dialog-content {
+display: block;
+}
+.litegraph .dialog .dialog-content .subgraph_property {
+padding: 5px;
+}
+.litegraph .dialog .dialog-footer {
+margin: 0;
+}
+.litegraph .dialog .dialog-footer .subgraph_property {
+margin-top: 0;
+display: flex;
+align-items: center;
+padding: 5px;
+}
+.litegraph .dialog .dialog-footer .subgraph_property .name {
+flex: 1;
+}
+.litegraph .graphdialog {
+display: flex;
+align-items: center;
+border-radius: 20px;
+padding: 4px 10px;
+position: fixed;
+}
+.litegraph .graphdialog .name {
+padding: 0;
+min-height: 0;
+font-size: 16px;
+vertical-align: middle;
+}
+.litegraph .graphdialog .value {
+font-size: 16px;
+min-height: 0;
+margin: 0 10px;
+padding: 2px 5px;
+}
+.litegraph .graphdialog input[type="checkbox"] {
+width: 16px;
+height: 16px;
+}
+.litegraph .graphdialog button {
+padding: 4px 18px;
+border-radius: 20px;
+cursor: pointer;
+}
+
diff --git a/src/litegraph.js b/src/litegraph.js
index bfacaec94..5b85b2386 100755
--- a/src/litegraph.js
+++ b/src/litegraph.js
@@ -4899,6 +4899,9 @@ LGraphNode.prototype.executeAction = function(action)
this.centerOnNode(subgraph_node);
this.selectNodes([subgraph_node]);
}
+ // when close sub graph back to offset [0, 0] scale 1
+ this.ds.offset = [0, 0]
+ this.ds.scale = 1
};
/**
@@ -7013,92 +7016,154 @@ LGraphNode.prototype.executeAction = function(action)
* draws the panel in the corner that shows subgraph properties
* @method drawSubgraphPanel
**/
- LGraphCanvas.prototype.drawSubgraphPanel = function(ctx) {
- var subgraph = this.graph;
- var subnode = subgraph._subgraph_node;
- if(!subnode)
- {
- console.warn("subgraph without subnode");
- return;
- }
+ LGraphCanvas.prototype.drawSubgraphPanel = function (ctx) {
+ var subgraph = this.graph;
+ var subnode = subgraph._subgraph_node;
+ if (!subnode) {
+ console.warn("subgraph without subnode");
+ return;
+ }
+ this.drawSubgraphPanelLeft(subgraph, subnode, ctx)
+ this.drawSubgraphPanelRight(subgraph, subnode, ctx)
+ }
+ LGraphCanvas.prototype.drawSubgraphPanelLeft = function (subgraph, subnode, ctx) {
+ var num = subnode.inputs ? subnode.inputs.length : 0;
+ var w = 200;
+ var h = Math.floor(LiteGraph.NODE_SLOT_HEIGHT * 1.6);
- var num = subnode.inputs ? subnode.inputs.length : 0;
- var w = 300;
- var h = Math.floor(LiteGraph.NODE_SLOT_HEIGHT * 1.6);
+ ctx.fillStyle = "#111";
+ ctx.globalAlpha = 0.8;
+ ctx.beginPath();
+ ctx.roundRect(10, 10, w, (num + 1) * h + 50, 8);
+ ctx.fill();
+ ctx.globalAlpha = 1;
- ctx.fillStyle = "#111";
- ctx.globalAlpha = 0.8;
- ctx.beginPath();
- ctx.roundRect(10,10,w, (num + 1) * h + 50,8 );
- ctx.fill();
- ctx.globalAlpha = 1;
+ ctx.fillStyle = "#888";
+ ctx.font = "14px Arial";
+ ctx.textAlign = "left";
+ ctx.fillText("Graph Inputs", 20, 34);
+ // var pos = this.mouse;
- ctx.fillStyle = "#888";
- ctx.font = "14px Arial";
- ctx.textAlign = "left";
- ctx.fillText( "Graph Inputs", 20, 34 );
- var pos = this.mouse;
+ if (this.drawButton(w - 20, 20, 20, 20, "X", "#151515")) {
+ this.closeSubgraph();
+ return;
+ }
- if( this.drawButton( w - 20, 20,20,20, "X", "#151515" ) )
- {
- this.closeSubgraph();
- return;
- }
+ var y = 50;
+ ctx.font = "14px Arial";
+ if (subnode.inputs)
+ for (var i = 0; i < subnode.inputs.length; ++i) {
+ var input = subnode.inputs[i];
+ if (input.not_subgraph_input)
+ continue;
- var y = 50;
- ctx.font = "20px Arial";
- if(subnode.inputs)
- for(var i = 0; i < subnode.inputs.length; ++i)
- {
- var input = subnode.inputs[i];
- if(input.not_subgraph_input)
- 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.beginPath();
+ ctx.arc(w - 16, y + h * 0.5, 5, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.fillStyle = "#AAA";
+ ctx.fillText(input.name, 30, y + h * 0.75);
+ // var tw = ctx.measureText(input.name);
+ ctx.fillStyle = "#777";
+ ctx.fillText(input.type, 130, y + h * 0.75);
+ y += h;
+ }
+ //add + button
+ if (this.drawButton(20, y + 2, w - 20, h - 2, "+", "#151515", "#222")) {
+ this.showSubgraphPropertiesDialog(subnode);
+ }
+ }
+ LGraphCanvas.prototype.drawSubgraphPanelRight = function (subgraph, subnode, ctx) {
+ var num = subnode.outputs ? subnode.outputs.length : 0;
+ var canvas_w = this.bgcanvas.width
+ var w = 200;
+ var h = Math.floor(LiteGraph.NODE_SLOT_HEIGHT * 1.6);
- //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 = "#111";
+ ctx.globalAlpha = 0.8;
+ ctx.beginPath();
+ ctx.roundRect(canvas_w - w - 10, 10, w, (num + 1) * h + 50, 8);
+ ctx.fill();
+ ctx.globalAlpha = 1;
- ctx.fillStyle = "#9C9";
- ctx.beginPath();
- ctx.arc(w - 16,y + h * 0.5,5,0,2*Math.PI);
- ctx.fill();
+ ctx.fillStyle = "#888";
+ ctx.font = "14px Arial";
+ ctx.textAlign = "left";
+ var title_text = "Graph Outputs"
+ var tw = ctx.measureText(title_text).width
+ ctx.fillText(title_text, (canvas_w - tw) - 20, 34);
+ // var pos = this.mouse;
+ if (this.drawButton(canvas_w - w, 20, 20, 20, "X", "#151515")) {
+ this.closeSubgraph();
+ return;
+ }
- ctx.fillStyle = "#AAA";
- ctx.fillText( input.name, 50, y + h*0.75 );
- var tw = ctx.measureText( input.name );
- ctx.fillStyle = "#777";
- ctx.fillText( input.type, 50 + tw.width + 10, y + h*0.75 );
-
- y += h;
- }
-
- //add + button
- if( this.drawButton( 20,y+2,w - 20, h - 2, "+", "#151515", "#222" ) )
- {
- this.showSubgraphPropertiesDialog( subnode );
- }
- }
+ var y = 50;
+ ctx.font = "14px Arial";
+ if (subnode.outputs)
+ for (var i = 0; i < subnode.outputs.length; ++i) {
+ var output = subnode.outputs[i];
+ if (output.not_subgraph_input)
+ 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.beginPath();
+ ctx.arc(canvas_w - w + 16, y + h * 0.5, 5, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.fillStyle = "#AAA";
+ ctx.fillText(output.name, canvas_w - w + 30, y + h * 0.75);
+ // var tw = ctx.measureText(input.name);
+ ctx.fillStyle = "#777";
+ ctx.fillText(output.type, canvas_w - w + 130, y + h * 0.75);
+ y += h;
+ }
+ //add + button
+ if (this.drawButton(canvas_w - w, y + 2, w - 20, h - 2, "+", "#151515", "#222")) {
+ this.showSubgraphPropertiesDialogRight(subnode);
+ }
+ }
//Draws a button into the canvas overlay and computes if it was clicked using the immediate gui paradigm
LGraphCanvas.prototype.drawButton = function( x,y,w,h, text, bgcolor, hovercolor, textcolor )
{
@@ -10572,7 +10637,67 @@ LGraphNode.prototype.executeAction = function(action)
this.canvas.parentNode.appendChild(panel);
return panel;
}
+ LGraphCanvas.prototype.showSubgraphPropertiesDialogRight = function (node) {
+ // console.log("showing subgraph properties dialog");
+ var that = this;
+ // old_panel if old_panel is exist close it
+ var old_panel = this.canvas.parentNode.querySelector(".subgraph_dialog");
+ if (old_panel)
+ old_panel.close();
+ // new panel
+ var panel = this.createPanel("Subgraph Outputs", { closable: true, width: 500 });
+ panel.node = node;
+ panel.classList.add("subgraph_dialog");
+
+ function inner_refresh() {
+ panel.clear();
+ //show currents
+ if (node.outputs)
+ for (var i = 0; i < node.outputs.length; ++i) {
+ var input = node.outputs[i];
+ if (input.not_subgraph_output)
+ continue;
+ var html = " ";
+ var elem = panel.addHTML(html, "subgraph_property");
+ elem.dataset["name"] = input.name;
+ elem.dataset["slot"] = i;
+ elem.querySelector(".name").innerText = input.name;
+ elem.querySelector(".type").innerText = input.type;
+ elem.querySelector("button").addEventListener("click", function (e) {
+ node.removeOutput(Number(this.parentNode.dataset["slot"]));
+ inner_refresh();
+ });
+ }
+ }
+
+ //add extra
+ var html = " + NameType";
+ var elem = panel.addHTML(html, "subgraph_property extra", true);
+ elem.querySelector(".name").addEventListener("keydown", function (e) {
+ if (e.keyCode == 13) {
+ addOutput.apply(this)
+ }
+ })
+ elem.querySelector("button").addEventListener("click", function (e) {
+ addOutput.apply(this)
+ });
+ function addOutput() {
+ var elem = this.parentNode;
+ var name = elem.querySelector(".name").value;
+ var type = elem.querySelector(".type").value;
+ if (!name || node.findOutputSlot(name) != -1)
+ return;
+ node.addOutput(name, type);
+ elem.querySelector(".name").value = "";
+ elem.querySelector(".type").value = "";
+ inner_refresh();
+ }
+
+ inner_refresh();
+ this.canvas.parentNode.appendChild(panel);
+ return panel;
+ }
LGraphCanvas.prototype.checkPanels = function()
{
if(!this.canvas)
diff --git a/src/nodes/base.js b/src/nodes/base.js
index 5be256750..abd2b46a1 100755
--- a/src/nodes/base.js
+++ b/src/nodes/base.js
@@ -131,39 +131,63 @@
}
};
- Subgraph.prototype.onDrawBackground = function(ctx, graphcanvas, canvas, pos)
- {
- if(this.flags.collapsed)
- return;
-
- var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5;
-
- //button
- var over = LiteGraph.isInsideRectangle(pos[0],pos[1],this.pos[0],this.pos[1] + y,this.size[0],LiteGraph.NODE_TITLE_HEIGHT);
- ctx.fillStyle = over ? "#555" : "#222";
- ctx.beginPath();
- if (this._shape == LiteGraph.BOX_SHAPE)
- ctx.rect(0, y, this.size[0]+1, LiteGraph.NODE_TITLE_HEIGHT);
- else
- ctx.roundRect( 0, y, this.size[0]+1, LiteGraph.NODE_TITLE_HEIGHT, 0, 8);
- ctx.fill();
-
- //button
- ctx.textAlign = "center";
- ctx.font = "24px Arial";
- ctx.fillStyle = over ? "#DDD" : "#999";
- ctx.fillText( "+", this.size[0] * 0.5, y + 24 );
- }
-
- Subgraph.prototype.onMouseDown = function(e, localpos, graphcanvas)
- {
- var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5;
- if(localpos[1] > y)
- {
- graphcanvas.showSubgraphPropertiesDialog(this);
- }
- }
+ Subgraph.prototype.onDrawBackground = function (ctx, graphcanvas, canvas, pos) {
+ if (this.flags.collapsed)
+ return;
+ var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5;
+ // button
+ var over = LiteGraph.isInsideRectangle(pos[0], pos[1], this.pos[0], this.pos[1] + y, this.size[0], LiteGraph.NODE_TITLE_HEIGHT);
+ let overleft = LiteGraph.isInsideRectangle(pos[0], pos[1], this.pos[0], this.pos[1] + y, this.size[0] / 2, LiteGraph.NODE_TITLE_HEIGHT)
+ ctx.fillStyle = over ? "#555" : "#222";
+ ctx.beginPath();
+ if (this._shape == LiteGraph.BOX_SHAPE) {
+ if (overleft) {
+ ctx.rect(0, y, this.size[0] / 2 + 1, LiteGraph.NODE_TITLE_HEIGHT);
+ } else {
+ ctx.rect(this.size[0] / 2, y, this.size[0] / 2 + 1, LiteGraph.NODE_TITLE_HEIGHT);
+ }
+ }
+ else {
+ if (overleft) {
+ ctx.roundRect(0, y, this.size[0] / 2 + 1, LiteGraph.NODE_TITLE_HEIGHT, 0, 8);
+ } else {
+ ctx.roundRect(this.size[0] / 2, y, this.size[0] / 2 + 1, LiteGraph.NODE_TITLE_HEIGHT, 0, 8);
+ }
+ }
+ if (over) {
+ ctx.fill();
+ } else {
+ ctx.fillRect(0, y, this.size[0] + 1, LiteGraph.NODE_TITLE_HEIGHT);
+ }
+ // button
+ ctx.textAlign = "center";
+ ctx.font = "24px Arial";
+ ctx.fillStyle = over ? "#DDD" : "#999";
+ ctx.fillText("+", this.size[0] * 0.25, y + 24);
+ ctx.fillText("+", this.size[0] * 0.75, y + 24);
+ }
+ // Subgraph.prototype.onMouseDown = function(e, localpos, graphcanvas)
+ // {
+ // var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5;
+ // if(localpos[1] > y)
+ // {
+ // graphcanvas.showSubgraphPropertiesDialog(this);
+ // }
+ // }
+ Subgraph.prototype.onMouseDown = function (e, localpos, graphcanvas) {
+ var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5;
+ console.log(0)
+ if (localpos[1] > y) {
+ if (localpos[0] < this.size[0] / 2) {
+ console.log(1)
+ graphcanvas.showSubgraphPropertiesDialog(this);
+ } else {
+ console.log(2)
+ graphcanvas.showSubgraphPropertiesDialogRight(this);
+ }
+ }
+ }
Subgraph.prototype.computeSize = function()
{
var num_inputs = this.inputs ? this.inputs.length : 0;
@@ -541,48 +565,48 @@
this.properties = {};
var that = this;
- Object.defineProperty(this.properties, "name", {
- get: function() {
- return that.name_in_graph;
- },
- set: function(v) {
- 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, "name", {
+ // get: function() {
+ // return that.name_in_graph;
+ // },
+ // set: function(v) {
+ // 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", {
- get: function() {
- return that.inputs[0].type;
- },
- set: function(v) {
- if (v == "action" || v == "event") {
- v = LiteGraph.ACTION;
- }
- if (!LiteGraph.isValidConnection(that.inputs[0].type,v))
- that.disconnectInput(0);
- that.inputs[0].type = v;
- if (that.name_in_graph) {
- //already added
- that.graph.changeOutputType(
- that.name_in_graph,
- that.inputs[0].type
- );
- }
- that.type_widget.value = v || "";
- },
- enumerable: true
- });
+ // Object.defineProperty(this.properties, "type", {
+ // get: function() {
+ // return that.inputs[0].type;
+ // },
+ // set: function(v) {
+ // if (v == "action" || v == "event") {
+ // v = LiteGraph.ACTION;
+ // }
+ // if (!LiteGraph.isValidConnection(that.inputs[0].type,v))
+ // that.disconnectInput(0);
+ // that.inputs[0].type = v;
+ // if (that.name_in_graph) {
+ // //already added
+ // that.graph.changeOutputType(
+ // that.name_in_graph,
+ // 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");
@@ -593,6 +617,50 @@
GraphOutput.title = "Output";
GraphOutput.desc = "Output of the graph";
+ GraphOutput.prototype.onPropertyChanged = function (name, v) {
+ if (name == "name") {
+ if (v == "" || v == this.name_in_graph || v == "enabled") {
+ return false;
+ }
+ if (this.graph) {
+ if (this.name_in_graph) {
+ //already added
+ this.graph.renameOutput(this.name_in_graph, v);
+ } else {
+ this.graph.addOutput(v, this.properties.type);
+ }
+ } //what if not?!
+ this.name_widget.value = v;
+ this.name_in_graph = v;
+ }
+ else if (name == "type") {
+ this.updateType();
+ }
+ else if (name == "value") {
+ }
+ }
+
+
+ GraphOutput.prototype.updateType = function () {
+ var type = this.properties.type;
+ if (this.type_widget)
+ this.type_widget.value = type;
+
+ //update output
+ if (this.inputs[0].type != type) {
+ if (!LiteGraph.isValidConnection(this.inputs[0].type, type))
+ this.disconnectInput(0);
+ this.inputs[0].type = type;
+ }
+
+ //update graph
+ if (this.graph && this.name_in_graph) {
+ this.graph.changeOutputType(this.name_in_graph, type);
+ }
+ }
+
+
+
GraphOutput.prototype.onExecute = function() {
this._value = this.getInputData(0);
this.graph.setOutputData(this.properties.name, this._value);