From 2e9b4a3f77b286d878deed7b4b65f0756f1f8c2e Mon Sep 17 00:00:00 2001 From: tamat Date: Fri, 20 Jun 2014 18:20:11 +0200 Subject: [PATCH] support to subgraphs --- build/litegraph.js | 416 ++++++++++++++++++++++++----- build/litegraph.min.js | 101 +++---- demo/demo.js | 2 +- doc/classes/LGraph.html | 10 +- doc/classes/LGraphCanvas.html | 214 ++++++++++++++- doc/classes/LGraphNode.html | 60 ++--- doc/data.json | 114 +++++--- doc/files/.._src_litegraph.js.html | 293 ++++++++++++++++---- src/litegraph.js | 293 ++++++++++++++++---- src/nodes/base.js | 95 ++++++- src/nodes/interface.js | 16 +- src/nodes/math.js | 12 +- 12 files changed, 1291 insertions(+), 335 deletions(-) diff --git a/build/litegraph.js b/build/litegraph.js index e26094570..0bf2668f4 100644 --- a/build/litegraph.js +++ b/build/litegraph.js @@ -286,7 +286,7 @@ LGraph.prototype.clear = function() this.global_inputs = {}; this.global_outputs = {}; - this.graph = {}; + //this.graph = {}; this.debug = true; this.change(); @@ -761,10 +761,18 @@ LGraph.prototype.getNodeOnPos = function(x,y, nodes_list) return null; } +// ********** GLOBALS ***************** + //Tell this graph has a global input of this type LGraph.prototype.addGlobalInput = function(name, type, value) { - this.global_inputs[name] = { type: type, value: value }; + this.global_inputs[name] = { name: name, type: type, value: value }; + + if(this.onGlobalInputAdded) + this.onGlobalInputAdded(name, type); + + if(this.onGlobalsChange) + this.onGlobalsChange(); } //assign a data to the global input @@ -776,29 +784,117 @@ LGraph.prototype.setGlobalInputData = function(name, data) input.value = data; } +//assign a data to the global input +LGraph.prototype.getGlobalInputData = function(name) +{ + var input = this.global_inputs[name]; + if (!input) + return null; + return input.value; +} + //rename the global input LGraph.prototype.renameGlobalInput = function(old_name, name, data) { + if(!this.global_inputs[old_name]) + return false; + + if(this.global_inputs[name]) + { + console.error("there is already one input with that name"); + return false; + } + + this.global_inputs[name] = this.global_inputs[old_name]; + delete this.global_inputs[old_name]; + + if(this.onGlobalInputRenamed) + this.onGlobalInputRenamed(old_name, name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); +} + +LGraph.prototype.removeGlobalInput = function(name) +{ + if(!this.global_inputs[name]) + return false; + + delete this.global_inputs[name]; + + if(this.onGlobalInputRemoved) + this.onGlobalInputRemoved(name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); + return true; } LGraph.prototype.addGlobalOutput = function(name, type, value) { - this.global_outputs[name] = { type: type, value: value }; + this.global_outputs[name] = { name: name, type: type, value: value }; + + if(this.onGlobalOutputAdded) + this.onGlobalOutputAdded(name, type); + + if(this.onGlobalsChange) + this.onGlobalsChange(); } //assign a data to the global output -LGraph.prototype.setGlobalOutputData = function(name, data) +LGraph.prototype.setGlobalOutputData = function(name, value) { var output = this.global_outputs[ name ]; if (!output) return; - output.value = data; + output.value = value; } +//assign a data to the global input +LGraph.prototype.getGlobalOutputData = function(name) +{ + var output = this.global_outputs[name]; + if (!output) + return null; + return output.value; +} + + //rename the global output LGraph.prototype.renameGlobalOutput = function(old_name, name, data) { + if(!this.global_outputs[old_name]) + return false; + + if(this.global_outputs[name]) + { + console.error("there is already one output with that name"); + return false; + } + + this.global_outputs[name] = this.global_outputs[old_name]; + delete this.global_outputs[old_name]; + + if(this.onGlobalOutputRenamed) + this.onGlobalOutputRenamed(old_name, name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); +} + +LGraph.prototype.removeGlobalOutput = function(name) +{ + if(!this.global_outputs[name]) + return false; + delete this.global_outputs[name]; + + if(this.onGlobalOutputRemoved) + this.onGlobalOutputRemoved(name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); + return true; } @@ -904,7 +1000,7 @@ LGraph.prototype.serialize = function() var data = { - graph: this.graph, +// graph: this.graph, iteration: this.iteration, frame: this.frame, @@ -1040,7 +1136,12 @@ LGraphNode.prototype.configure = function(info) if(info[j] == null) continue; else if (typeof(info[j]) == 'object') //object - this[j] = LiteGraph.cloneObject(info[j], this[j]); + { + if(this[j] && this[j].configure) + this[j].configure( info[j] ); + else + this[j] = LiteGraph.cloneObject(info[j], this[j]); + } else //value this[j] = info[j]; } @@ -1113,6 +1214,36 @@ LGraphNode.prototype.serialize = function() return o; } + +/* Creates a clone of this node */ +LGraphNode.prototype.clone = function() +{ + var node = LiteGraph.createNode(this.type); + + var data = this.serialize(); + delete data["id"]; + node.configure(data); + + /* + node.size = this.size.concat(); + if(this.inputs) + for(var i = 0, l = this.inputs.length; i < l; ++i) + { + if(node.findInputSlot( this.inputs[i].name ) == -1) + node.addInput( this.inputs[i].name, this.inputs[i].type ); + } + + if(this.outputs) + for(var i = 0, l = this.outputs.length; i < l; ++i) + { + if(node.findOutputSlot( this.outputs[i].name ) == -1) + node.addOutput( this.outputs[i].name, this.outputs[i].type ); + } + */ + + return node; +} + //reduced version of objectivize: NOT FINISHED /* LGraphNode.prototype.reducedObjectivize = function() @@ -1291,6 +1422,8 @@ LGraphNode.prototype.addOutput = function(name,type,extra_info) if(!this.outputs) this.outputs = []; this.outputs.push(o); + if(this.onOutputAdded) + this.onOutputAdded(o); this.size = this.computeSize(); } @@ -1312,6 +1445,8 @@ LGraphNode.prototype.addOutputs = function(array) if(!this.outputs) this.outputs = []; this.outputs.push(o); + if(this.onOutputAdded) + this.onOutputAdded(o); } this.size = this.computeSize(); @@ -1327,6 +1462,8 @@ LGraphNode.prototype.removeOutput = function(slot) this.disconnectOutput(slot); this.outputs.splice(slot,1); this.size = this.computeSize(); + if(this.onOutputRemoved) + this.onOutputRemoved(slot); } /** @@ -1346,6 +1483,8 @@ LGraphNode.prototype.addInput = function(name,type,extra_info) if(!this.inputs) this.inputs = []; this.inputs.push(o); this.size = this.computeSize(); + if(this.onInputAdded) + this.onInputAdded(o); } /** @@ -1366,6 +1505,8 @@ LGraphNode.prototype.addInputs = function(array) if(!this.inputs) this.inputs = []; this.inputs.push(o); + if(this.onInputAdded) + this.onInputAdded(o); } this.size = this.computeSize(); @@ -1381,6 +1522,8 @@ LGraphNode.prototype.removeInput = function(slot) this.disconnectInput(slot); this.inputs.splice(slot,1); this.size = this.computeSize(); + if(this.onInputRemoved) + this.onInputRemoved(slot); } /** @@ -1723,29 +1866,6 @@ LGraphNode.prototype.alignToGrid = function() this.pos[1] = LiteGraph.CANVAS_GRID_SIZE * Math.round(this.pos[1] / LiteGraph.CANVAS_GRID_SIZE); } -/* Creates a clone of this node */ -LGraphNode.prototype.clone = function() -{ - var node = LiteGraph.createNode(this.type); - - node.size = this.size.concat(); - if(this.inputs) - for(var i = 0, l = this.inputs.length; i < l; ++i) - { - if(node.findInputSlot( this.inputs[i].name ) == -1) - node.addInput( this.inputs[i].name, this.inputs[i].type ); - } - - if(this.outputs) - for(var i = 0, l = this.outputs.length; i < l; ++i) - { - if(node.findOutputSlot( this.outputs[i].name ) == -1) - node.addOutput( this.outputs[i].name, this.outputs[i].type ); - } - - - return node; -} /* Console output */ LGraphNode.prototype.trace = function(msg) @@ -1968,7 +2088,7 @@ LGraphCanvas.prototype.clear = function() * assigns a graph, you can reasign graphs to the same canvas * * @method setGraph -* @param {LGraph} assigns a graph +* @param {LGraph} graph */ LGraphCanvas.prototype.setGraph = function(graph) { @@ -1992,6 +2112,48 @@ LGraphCanvas.prototype.setGraph = function(graph) this.setDirty(true,true); } +/** +* opens a graph contained inside a node in the current graph +* +* @method openSubgraph +* @param {LGraph} graph +*/ +LGraphCanvas.prototype.openSubgraph = function(graph) +{ + if(!graph) + throw("graph cannot be null"); + + if(this.graph == graph) + throw("graph cannot be the same"); + + this.clear(); + + if(this.graph) + { + if(!this._graph_stack) + this._graph_stack = []; + this._graph_stack.push(this.graph); + } + + graph.attachCanvas(this); + this.setDirty(true,true); +} + +/** +* closes a subgraph contained inside a node +* +* @method closeSubgraph +* @param {LGraph} assigns a graph +*/ +LGraphCanvas.prototype.closeSubgraph = function() +{ + if(!this._graph_stack || this._graph_stack.length == 0) + return; + var graph = this._graph_stack.pop(); + graph.attachCanvas(this); + this.setDirty(true,true); +} + /** * assigns a canvas * @@ -3895,32 +4057,59 @@ LGraphCanvas.node_colors = { LGraphCanvas.prototype.getCanvasMenuOptions = function() { - return [ - {content:"Add Node", is_menu: true, callback: LGraphCanvas.onMenuAdd } - //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } - ]; + var options = null; + if(this.getMenuOptions) + options = this.getMenuOptions(); + else + { + options = [ + {content:"Add Node", is_menu: true, callback: LGraphCanvas.onMenuAdd } + //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } + ]; + + if(this._graph_stack) + options = [{content:"Close subgraph", callback: this.closeSubgraph.bind(this) },null].concat(options); + } + + if(this.getExtraMenuOptions) + { + var extra = this.getExtraMenuOptions(this); + extra.push(null); + options = extra.concat( options ); + } + + return options; } LGraphCanvas.prototype.getNodeMenuOptions = function(node) { - var options = [ - {content:"Inputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeInputs }, - {content:"Outputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeOutputs }, - null, - {content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse }, - {content:"Pin", callback: LGraphCanvas.onMenuNodePin }, - {content:"Colors", is_menu: true, callback: LGraphCanvas.onMenuNodeColors }, - {content:"Shapes", is_menu: true, callback: LGraphCanvas.onMenuNodeShapes }, - null, - {content:"Clone", callback: LGraphCanvas.onMenuNodeClone }, - null, - {content:"Remove", callback: LGraphCanvas.onMenuNodeRemove } - ]; + var options = null; - if( node.clonable == false ) - options[7].disabled = true; - if( node.removable == false ) - options[9].disabled = true; + if(node.getMenuOptions) + options = node.getMenuOptions(this); + else + options = [ + {content:"Inputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeInputs }, + {content:"Outputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeOutputs }, + null, + {content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse }, + {content:"Pin", callback: LGraphCanvas.onMenuNodePin }, + {content:"Colors", is_menu: true, callback: LGraphCanvas.onMenuNodeColors }, + {content:"Shapes", is_menu: true, callback: LGraphCanvas.onMenuNodeShapes }, + null + ]; + + if(node.getExtraMenuOptions) + { + var extra = node.getExtraMenuOptions(this); + extra.push(null); + options = extra.concat( options ); + } + + if( node.clonable !== false ) + options.push({content:"Clone", callback: LGraphCanvas.onMenuNodeClone }); + if( node.removable !== false ) + options.push(null,{content:"Remove", callback: LGraphCanvas.onMenuNodeRemove }); if(node.onGetInputs) { @@ -4273,15 +4462,32 @@ if( !window["requestAnimationFrame"] ) //Input for a subgraph function GlobalInput() { + this.title = "Input"; + + //random name to avoid problems with other outputs when added + var genname = "input_" + (Math.random()*1000).toFixed(); + this.properties = { name: genname, type: "number" }; this.addOutput("value",0); } +GlobalInput.title = "Input"; +GlobalInput.desc = "Input of the graph"; + +GlobalInput.prototype.onAdded = function() +{ + this.graph.addGlobalInput( this.properties.name, this.properties.type ); +} + GlobalInput.prototype.onExecute = function() { - var name = this.title; - //read input - var value = node.graph.global_inputs[name]; - this.setOutputData(0,value); + var name = this.properties.name; + + //read from global input + var data = this.graph.global_inputs[name]; + if(!data) return; + + //put through output + this.setOutputData(0,data.value); } LiteGraph.registerNodeType("graph/input", GlobalInput); @@ -4293,11 +4499,14 @@ function GlobalOutput() this.title = "Output"; //random name to avoid problems with other outputs when added - var genname = "input_" + (Math.random()*1000).toFixed(); + var genname = "output_" + (Math.random()*1000).toFixed(); this.properties = { name: genname, type: "number" }; this.addInput("value","number"); } +GlobalOutput.title = "Ouput"; +GlobalOutput.desc = "Output of the graph"; + GlobalOutput.prototype.onAdded = function() { var name = this.graph.addGlobalOutput( this.properties.name, this.properties.type ); @@ -4305,8 +4514,7 @@ GlobalOutput.prototype.onAdded = function() GlobalOutput.prototype.onExecute = function() { - var value = this.getInputData(0); - this.graph.setGlobalOutputData( this.properties.name, value ); + this.graph.setGlobalOutputData( this.properties.name, this.getInputData(0) ); } LiteGraph.registerNodeType("graph/output", GlobalOutput); @@ -4315,29 +4523,77 @@ LiteGraph.registerNodeType("graph/output", GlobalOutput); //Subgraph: a node that contains a graph function Subgraph() { + var that = this; this.subgraph = new LGraph(); + this.subgraph._subgraph_node = this; + this.subgraph._is_subgraph = true; + this.subgraph.onGlobalInputAdded = this.onSubgraphNewGlobalInput.bind(this); + this.subgraph.onGlobalOutputAdded = this.onSubgraphNewGlobalOutput.bind(this); + this.bgcolor = "#FA3"; } +Subgraph.title = "Subgraph"; +Subgraph.desc = "Graph inside a node"; + +Subgraph.prototype.onSubgraphNewGlobalInput = function(name, type) +{ + this.addInput(name, type); +} + +Subgraph.prototype.onSubgraphNewGlobalOutput = function(name, type) +{ + this.addOutput(name, type); +} + +Subgraph.prototype.getExtraMenuOptions = function(graphcanvas) +{ + var that = this; + return [ {content:"Open", callback: + function() { + graphcanvas.openSubgraph( that.subgraph ); + } + }]; +} + Subgraph.prototype.onExecute = function() { //send inputs to subgraph global inputs - for(var i in this.inputs) - { - var input = this.inputs[i]; + if(this.inputs) + for(var i = 0; i < this.inputs.length; i++) + { + var input = this.inputs[i]; + var value = this.getInputData(i); + this.subgraph.setGlobalInputData( input.name, value ); + } - //this.subgraph.setGlobalInputData( input.name, input.value ); - } + //execute + this.subgraph.runStep(); //send subgraph global outputs to outputs + if(this.outputs) + for(var i = 0; i < this.outputs.length; i++) + { + var output = this.outputs[i]; + var value = this.subgraph.getGlobalOutputData( output.name ); + this.setOutputData(i, value); + } } Subgraph.prototype.configure = function(o) { - LGraph.prototype.configure.call(this, o); - //after configure, ... + LGraphNode.prototype.configure.call(this, o); + //this.subgraph.configure(o.graph); } +Subgraph.prototype.serialize = function() +{ + var data = LGraphNode.prototype.serialize.call(this); + data.subgraph = this.subgraph.serialize(); + return data; +} + + LiteGraph.registerNodeType("graph/subgraph", Subgraph); @@ -4619,8 +4875,8 @@ LiteGraph.registerNodeType("network/network_callback",{ function WidgetKnob() { - this.size = [64,84]; this.addOutput("",'number'); + this.size = [64,84]; this.properties = {min:0,max:1,value:0.5,wcolor:"#7AF",size:50}; } @@ -4658,12 +4914,14 @@ LiteGraph.registerNodeType("network/network_callback",{ ctx.restore(); - ctx.font = "bold 16px Criticized,Tahoma"; - ctx.fillStyle="rgba(100,100,100,0.8)"; - ctx.textAlign = "center"; - - ctx.fillText(this.name.toUpperCase(), this.size[0] * 0.5, 18 ); - ctx.textAlign = "left"; + if(this.title) + { + ctx.font = "bold 16px Criticized,Tahoma"; + ctx.fillStyle="rgba(100,100,100,0.8)"; + ctx.textAlign = "center"; + ctx.fillText(this.title.toUpperCase(), this.size[0] * 0.5, 18 ); + ctx.textAlign = "left"; + } } WidgetKnob.prototype.onDrawVectorKnob = function(ctx) @@ -5377,6 +5635,7 @@ function MathClamp() MathClamp.title = "Clamp"; MathClamp.desc = "Clamp number between min and max"; +MathClamp.filter = "shader"; MathClamp.prototype.onExecute = function() { @@ -5387,6 +5646,14 @@ MathClamp.prototype.onExecute = function() this.setOutputData(0, v ); } +MathClamp.prototype.getCode = function(lang) +{ + var code = ""; + if(this.isInputConnected(0)) + code += "clamp({{0}}," + this.properties.min + "," + this.properties.max + ")"; + return code; +} + LiteGraph.registerNodeType("math/clamp", MathClamp ); @@ -5426,7 +5693,7 @@ MathFloor.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; - this.setOutputData(0, v|1 ); + this.setOutputData(0, Math.floor(v) ); } LiteGraph.registerNodeType("math/floor", MathFloor ); @@ -5620,6 +5887,7 @@ function MathTrigonometry() MathTrigonometry.title = "Trigonometry"; MathTrigonometry.desc = "Sin Cos Tan"; +MathTrigonometry.filter = "shader"; MathTrigonometry.prototype.onExecute = function() { diff --git a/build/litegraph.min.js b/build/litegraph.min.js index a35839456..62b1df1ec 100644 --- a/build/litegraph.min.js +++ b/build/litegraph.min.js @@ -4,7 +4,7 @@ b.type=a;LiteGraph.debug&&console.log("Node registered: "+a);a.split("/");var c= !this.registered_node_types[b].skip_list&&(a[this.registered_node_types[b].category]=1);var c=[];for(b in a)c.push(b);return c},reloadNodes:function(a){var b=document.getElementsByTagName("script"),c=[],d;for(d in b)c.push(b[d]);b=document.getElementsByTagName("head")[0];a=document.location.href+a;for(d in c){var e=c[d].src;if(e&&e.substr(0,a.length)==a)try{LiteGraph.debug&&console.log("Reloading: "+e);var f=document.createElement("script");f.type="text/javascript";f.src=e;b.appendChild(f);b.removeChild(c[d])}catch(g){if(LiteGraph.throw_errors)throw g; LiteGraph.debug&&console.log("Error while reloading "+e)}}LiteGraph.debug&&console.log("Nodes reloaded")},cloneObject:function(a,b){if(null==a)return null;var c=JSON.parse(JSON.stringify(a));if(!b)return c;for(var d in c)b[d]=c[d];return b}};LiteGraph.getTime="undefined"!=typeof performance?function(){return performance.now()}:function(){return Date.now()};function LGraph(){LiteGraph.debug&&console.log("Graph created");this.list_of_graphcanvas=null;this.clear()} LGraph.supported_types=["number","string","boolean"];LGraph.prototype.getSupportedTypes=function(){return this.supported_types||LGraph.supported_types};LGraph.STATUS_STOPPED=1;LGraph.STATUS_RUNNING=2; -LGraph.prototype.clear=function(){this.stop();this.status=LGraph.STATUS_STOPPED;this.last_node_id=0;this._nodes=[];this._nodes_by_id={};this.last_link_id=0;this.links={};this.iteration=0;this.config={};this.fixedtime=this.runningtime=this.globaltime=0;this.elapsed_time=this.fixedtime_lapse=0.01;this.starttime=0;this.global_inputs={};this.global_outputs={};this.graph={};this.debug=!0;this.change();this.sendActionToCanvas("clear")}; +LGraph.prototype.clear=function(){this.stop();this.status=LGraph.STATUS_STOPPED;this.last_node_id=0;this._nodes=[];this._nodes_by_id={};this.last_link_id=0;this.links={};this.iteration=0;this.config={};this.fixedtime=this.runningtime=this.globaltime=0;this.elapsed_time=this.fixedtime_lapse=0.01;this.starttime=0;this.global_inputs={};this.global_outputs={};this.debug=!0;this.change();this.sendActionToCanvas("clear")}; LGraph.prototype.attachCanvas=function(a){if(a.constructor!=LGraphCanvas)throw"attachCanvas expects a LGraphCanvas instance";a.graph&&a.graph!=this&&a.graph.detachCanvas(a);a.graph=this;this.list_of_graphcanvas||(this.list_of_graphcanvas=[]);this.list_of_graphcanvas.push(a)};LGraph.prototype.detachCanvas=function(a){var b=this.list_of_graphcanvas.indexOf(a);-1!=b&&(a.graph=null,this.list_of_graphcanvas.splice(b,1))}; LGraph.prototype.start=function(a){if(this.status!=LGraph.STATUS_RUNNING){this.status=LGraph.STATUS_RUNNING;if(this.onPlayEvent)this.onPlayEvent();this.sendEventToAllNodes("onStart");this.starttime=LiteGraph.getTime();var b=this;this.execution_timer_id=setInterval(function(){b.runStep(1)},a||1)}}; LGraph.prototype.stop=function(){if(this.status!=LGraph.STATUS_STOPPED){this.status=LGraph.STATUS_STOPPED;if(this.onStopEvent)this.onStopEvent();null!=this.execution_timer_id&&clearInterval(this.execution_timer_id);this.execution_timer_id=null;this.sendEventToAllNodes("onStop")}}; @@ -16,24 +16,30 @@ LGraph.prototype.sendEventToAllNodes=function(a,b){var c=this._nodes_in_order?th LGraph.prototype.add=function(a,b){if(a&&(-1==a.id||null==this._nodes_by_id[a.id])){if(this._nodes.length>=LiteGraph.MAX_NUMBER_OF_NODES)throw"LiteGraph: max number of nodes in a graph reached";if(null==a.id||-1==a.id)a.id=this.last_node_id++;a.graph=this;this._nodes.push(a);this._nodes_by_id[a.id]=a;if(a.onAdded)a.onAdded();this.config.align_to_grid&&a.alignToGrid();b||this.updateExecutionOrder();if(this.onNodeAdded)this.onNodeAdded(a);this.setDirtyCanvas(!0);this.change();return a}}; LGraph.prototype.remove=function(a){if(null!=this._nodes_by_id[a.id]&&!a.ignore_remove){if(a.inputs)for(var b=0;ba&&this.pos[1]-cb)return!0;return!1}; LGraphNode.prototype.findInputSlot=function(a){if(!this.inputs)return-1;for(var b=0,c=this.inputs.length;b=this.outputs.length)return LiteGraph.debug&&console.log("Connect: Error, slot number not found"),!1;if(b==this)return!1;if(c.constructor===String){if(c=b.findInputSlot(c),-1==c)return LiteGraph.debug&&console.log("Connect: Error, no slot of name "+c),!1}else if(!b.inputs||c>=b.inputs.length)return LiteGraph.debug&& @@ -45,13 +51,13 @@ LGraphNode.prototype.disconnectInput=function(a){if(a.constructor===String){if(a 0==a.links.length)return!1;for(var c=0,d=a.links.length;cb&&this.inputs[b].pos?[this.pos[0]+this.inputs[b].pos[0],this.pos[1]+this.inputs[b].pos[1]]:!a&&this.outputs.length>b&&this.outputs[b].pos?[this.pos[0]+this.outputs[b].pos[0],this.pos[1]+this.outputs[b].pos[1]]: a?[this.pos[0],this.pos[1]+10+b*LiteGraph.NODE_SLOT_HEIGHT]:[this.pos[0]+this.size[0]+1,this.pos[1]+10+b*LiteGraph.NODE_SLOT_HEIGHT]};LGraphNode.prototype.alignToGrid=function(){this.pos[0]=LiteGraph.CANVAS_GRID_SIZE*Math.round(this.pos[0]/LiteGraph.CANVAS_GRID_SIZE);this.pos[1]=LiteGraph.CANVAS_GRID_SIZE*Math.round(this.pos[1]/LiteGraph.CANVAS_GRID_SIZE)}; -LGraphNode.prototype.clone=function(){var a=LiteGraph.createNode(this.type);a.size=this.size.concat();if(this.inputs)for(var b=0,c=this.inputs.length;bLGraphNode.MAX_CONSOLE&&this.console.shift();this.graph.onNodeTrace(this,a)};LGraphNode.prototype.setDirtyCanvas=function(a,b){this.graph&&this.graph.sendActionToCanvas("setDirty",[a,b])};LGraphNode.prototype.loadImage=function(a){var b=new Image;b.src=LiteGraph.node_images_path+a;b.ready=!1;var c=this;b.onload=function(){this.ready=!0;c.setDirtyCanvas(!0)};return b}; LGraphNode.prototype.executeAction=function(a){if(""==a)return!1;if(-1!=a.indexOf(";")||-1!=a.indexOf("}"))return this.trace("Error: Action contains unsafe characters"),!1;var b=a.split("(")[0];if("function"!=typeof this[b])return this.trace("Error: Action not found on node: "+b),!1;try{b=eval,eval=null,(new Function("with(this) { "+a+"}")).call(this),eval=b}catch(c){return this.trace("Error executing action {"+a+"} :"+c),!1}return!0}; LGraphNode.prototype.captureInput=function(a){if(this.graph&&this.graph.list_of_graphcanvas){var b=this.graph.list_of_graphcanvas,c;for(c in b){var d=b[c];if(a||d.node_capturing_input==this)d.node_capturing_input=a?this:null,this.graph.debug&&console.log(this.title+": Capturing input "+(a?"ON":"OFF"))}}};LGraphNode.prototype.collapse=function(){this.flags.collapsed=this.flags.collapsed?!1:!0;this.setDirtyCanvas(!0,!0)}; LGraphNode.prototype.pin=function(a){this.flags.pinned=void 0===a?!this.flags.pinned:a};LGraphNode.prototype.localToScreen=function(a,b,c){return[(a+this.pos[0])*c.scale+c.offset[0],(b+this.pos[1])*c.scale+c.offset[1]]};function LGraphCanvas(a,b){"string"==typeof a&&(a=document.querySelector(a));if(!a)throw"no canvas found";b&&b.attachCanvas(this);this.setCanvas(a);this.clear();this.startRendering()}LGraphCanvas.link_type_colors={number:"#AAC",node:"#DCA"}; LGraphCanvas.prototype.clear=function(){this.fps=this.render_time=this.last_draw_time=this.frame=0;this.scale=1;this.offset=[0,0];this.selected_nodes={};this.connecting_node=this.node_capturing_input=this.node_over=this.node_dragged=null;this.highquality_render=!0;this.editor_alpha=1;this.pause_rendering=!1;this.dirty_bgcanvas=this.dirty_canvas=this.render_shadows=!0;this.dirty_area=null;this.render_only_selected=!0;this.live_mode=!1;this.allow_dragnodes=this.allow_dragcanvas=this.show_info=!0;this.node_in_panel= null;this.last_mouse=[0,0];this.last_mouseclick=0;this.title_text_font="bold 14px Arial";this.inner_text_font="normal 12px Arial";this.render_connections_shadows=!1;this.render_connection_arrows=this.render_curved_connections=this.render_connections_border=!0;this.connections_width=4;if(this.onClear)this.onClear()};LGraphCanvas.prototype.setGraph=function(a){this.graph!=a&&(this.clear(),!a&&this.graph?this.graph.detachCanvas(this):(a.attachCanvas(this),this.setDirty(!0,!0)))}; +LGraphCanvas.prototype.openSubgraph=function(a){if(!a)throw"graph cannot be null";if(this.graph==a)throw"graph cannot be the same";this.clear();this.graph&&(this._graph_stack||(this._graph_stack=[]),this._graph_stack.push(this.graph));a.attachCanvas(this);this.setDirty(!0,!0)};LGraphCanvas.prototype.closeSubgraph=function(){this._graph_stack&&0!=this._graph_stack.length&&(this._graph_stack.pop().attachCanvas(this),this.setDirty(!0,!0))}; LGraphCanvas.prototype.setCanvas=function(a){var b=this;"string"==typeof a&&(a=document.getElementById(a));if(null==a)throw"Error creating LiteGraph canvas: Canvas not found";if(a!=this.canvas){this.canvas=a;this.canvas.className+=" lgraphcanvas";this.canvas.data=this;this.bgcanvas=null;this.bgcanvas||(this.bgcanvas=document.createElement("canvas"),this.bgcanvas.width=this.canvas.width,this.bgcanvas.height=this.canvas.height);if(null==this.canvas.getContext)throw"This browser doesnt support Canvas"; this.ctx=this.canvas.getContext("2d");this.bgctx=this.bgcanvas.getContext("2d");this._mousemove_callback=this.processMouseMove.bind(this);this._mouseup_callback=this.processMouseUp.bind(this);this.canvas.addEventListener("mousedown",this.processMouseDown.bind(this),!0);this.canvas.addEventListener("mousemove",this._mousemove_callback);this.canvas.addEventListener("contextmenu",function(a){a.preventDefault();return!1});this.canvas.addEventListener("mousewheel",this.processMouseWheel.bind(this),!1); this.canvas.addEventListener("DOMMouseScroll",this.processMouseWheel.bind(this),!1);this.canvas.addEventListener("touchstart",this.touchHandler,!0);this.canvas.addEventListener("touchmove",this.touchHandler,!0);this.canvas.addEventListener("touchend",this.touchHandler,!0);this.canvas.addEventListener("touchcancel",this.touchHandler,!0);this.canvas.addEventListener("keydown",function(a){b.processKeyDown(a)});this.canvas.addEventListener("keyup",function(a){b.processKeyUp(a)})}}; @@ -111,9 +117,10 @@ LGraphCanvas.onMenuNodeOutputs=function(a,b,c){function d(f){if(a){var e=f.value {event:b,callback:d,from:c})}return!1}};LGraphCanvas.onMenuNodeCollapse=function(a){a.flags.collapsed=!a.flags.collapsed;a.setDirtyCanvas(!0,!0)};LGraphCanvas.onMenuNodePin=function(a){a.pin()}; LGraphCanvas.onMenuNodeColors=function(a,b,c){var d=[],e;for(e in LGraphCanvas.node_colors){var f=LGraphCanvas.node_colors[e];d.push({value:e,content:""+e+""})}LiteGraph.createContextualMenu(d,{event:b,callback:function(b){a&&(b=LGraphCanvas.node_colors[b.value])&&(a.color=b.color,a.bgcolor=b.bgcolor,a.setDirtyCanvas(!0))},from:c});return!1}; LGraphCanvas.onMenuNodeShapes=function(a,b){LiteGraph.createContextualMenu(["box","round"],{event:b,callback:function(b){a&&(a.shape=b,a.setDirtyCanvas(!0))}});return!1};LGraphCanvas.onMenuNodeRemove=function(a){!1!=a.removable&&(a.graph.remove(a),a.setDirtyCanvas(!0,!0))};LGraphCanvas.onMenuNodeClone=function(a){if(!1!=a.clonable){var b=a.clone();b&&(b.pos=[a.pos[0]+5,a.pos[1]+5],a.graph.add(b),a.setDirtyCanvas(!0,!0))}}; -LGraphCanvas.node_colors={red:{color:"#FAA",bgcolor:"#A44"},green:{color:"#AFA",bgcolor:"#4A4"},blue:{color:"#AAF",bgcolor:"#44A"},white:{color:"#FFF",bgcolor:"#AAA"}};LGraphCanvas.prototype.getCanvasMenuOptions=function(){return[{content:"Add Node",is_menu:!0,callback:LGraphCanvas.onMenuAdd}]}; -LGraphCanvas.prototype.getNodeMenuOptions=function(a){var b=[{content:"Inputs",is_menu:!0,disabled:!0,callback:LGraphCanvas.onMenuNodeInputs},{content:"Outputs",is_menu:!0,disabled:!0,callback:LGraphCanvas.onMenuNodeOutputs},null,{content:"Collapse",callback:LGraphCanvas.onMenuNodeCollapse},{content:"Pin",callback:LGraphCanvas.onMenuNodePin},{content:"Colors",is_menu:!0,callback:LGraphCanvas.onMenuNodeColors},{content:"Shapes",is_menu:!0,callback:LGraphCanvas.onMenuNodeShapes},null,{content:"Clone", -callback:LGraphCanvas.onMenuNodeClone},null,{content:"Remove",callback:LGraphCanvas.onMenuNodeRemove}];!1==a.clonable&&(b[7].disabled=!0);!1==a.removable&&(b[9].disabled=!0);if(a.onGetInputs){var c=a.onGetInputs();c&&c.length&&(b[0].disabled=!1)}a.onGetOutputs&&(a=a.onGetOutputs())&&a.length&&(b[1].disabled=!1);return b}; +LGraphCanvas.node_colors={red:{color:"#FAA",bgcolor:"#A44"},green:{color:"#AFA",bgcolor:"#4A4"},blue:{color:"#AAF",bgcolor:"#44A"},white:{color:"#FFF",bgcolor:"#AAA"}}; +LGraphCanvas.prototype.getCanvasMenuOptions=function(){var a=null;this.getMenuOptions?a=this.getMenuOptions():(a=[{content:"Add Node",is_menu:!0,callback:LGraphCanvas.onMenuAdd}],this._graph_stack&&(a=[{content:"Close subgraph",callback:this.closeSubgraph.bind(this)},null].concat(a)));if(this.getExtraMenuOptions){var b=this.getExtraMenuOptions(this);b.push(null);a=b.concat(a)}return a}; +LGraphCanvas.prototype.getNodeMenuOptions=function(a){var b=null,b=a.getMenuOptions?a.getMenuOptions(this):[{content:"Inputs",is_menu:!0,disabled:!0,callback:LGraphCanvas.onMenuNodeInputs},{content:"Outputs",is_menu:!0,disabled:!0,callback:LGraphCanvas.onMenuNodeOutputs},null,{content:"Collapse",callback:LGraphCanvas.onMenuNodeCollapse},{content:"Pin",callback:LGraphCanvas.onMenuNodePin},{content:"Colors",is_menu:!0,callback:LGraphCanvas.onMenuNodeColors},{content:"Shapes",is_menu:!0,callback:LGraphCanvas.onMenuNodeShapes}, +null];if(a.getExtraMenuOptions){var c=a.getExtraMenuOptions(this);c.push(null);b=c.concat(b)}!1!==a.clonable&&b.push({content:"Clone",callback:LGraphCanvas.onMenuNodeClone});!1!==a.removable&&b.push(null,{content:"Remove",callback:LGraphCanvas.onMenuNodeRemove});a.onGetInputs&&(c=a.onGetInputs())&&c.length&&(b[0].disabled=!1);a.onGetOutputs&&(a=a.onGetOutputs())&&a.length&&(b[1].disabled=!1);return b}; LGraphCanvas.prototype.processContextualMenu=function(a,b){var c=this,d=this.getCanvasWindow(),e=LiteGraph.createContextualMenu(a?this.getNodeMenuOptions(a):this.getCanvasMenuOptions(),{event:b,callback:function(f,d){if(f&&f.callback)return f.callback(a,d,e,c,b)}},d)}; CanvasRenderingContext2D.prototype.roundRect=function(a,b,c,d,e,f){void 0===e&&(e=5);void 0===f&&(f=e);this.beginPath();this.moveTo(a+e,b);this.lineTo(a+c-e,b);this.quadraticCurveTo(a+c,b,a+c,b+e);this.lineTo(a+c,b+d-f);this.quadraticCurveTo(a+c,b+d,a+c-f,b+d);this.lineTo(a+f,b+d);this.quadraticCurveTo(a,b+d,a,b+d-f);this.lineTo(a,b+e);this.quadraticCurveTo(a,b,a+e,b)};function compareObjects(a,b){for(var c in a)if(a[c]!=b[c])return!1;return!0} function distance(a,b){return Math.sqrt((b[0]-a[0])*(b[0]-a[0])+(b[1]-a[1])*(b[1]-a[1]))}function colorToString(a){return"rgba("+Math.round(255*a[0]).toFixed()+","+Math.round(255*a[1]).toFixed()+","+Math.round(255*a[2]).toFixed()+","+(4==a.length?a[3].toFixed(2):"1.0")+")"}function isInsideRectangle(a,b,c,d,e,f){return ca&&db?!0:!1}function growBounding(a,b,c){ba[2]&&(a[2]=b);ca[3]&&(a[3]=c)} @@ -124,20 +131,23 @@ f.backgroundColor="#444";e.addEventListener("contextmenu",function(a){a.preventD d));e.appendChild(h)}e.addEventListener("mouseover",function(a){this.mouse_inside=!0});e.addEventListener("mouseout",function(a){for(a=a.toElement;a!=this&&a!=c.document;)a=a.parentNode;a!=this&&(this.mouse_inside=!1,this.block_close||this.closeMenu())});c.document.body.appendChild(e);a=e.getClientRects()[0];b.from&&(b.from.block_close=!0);h=b.left||0;g=b.top||0;b.event&&(h=b.event.pageX-10,g=b.event.pageY-10,b.left&&(h=b.left),f=c.document.body.getClientRects()[0],b.from&&(h=b.from.getClientRects()[0], h=h.left+h.width),h>f.width-a.width-10&&(h=f.width-a.width-10),g>f.height-a.height-10&&(g=f.height-a.height-10));e.style.left=h+"px";e.style.top=g+"px";e.closeMenu=function(){b.from&&(b.from.block_close=!1,b.from.mouse_inside||b.from.closeMenu());this.parentNode&&c.document.body.removeChild(this)};return e};LiteGraph.closeAllContextualMenus=function(){var a=document.querySelectorAll(".litecontextualmenu");if(a.length){for(var b=[],c=0;ca.canvasY-this.pos[1]||distance([a.canvasX,a.canvasY],[this.pos[0]+this.center[0],this.pos[1]+this.center[1]])>this.radius)return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0);return!0}};a.prototype.onMouseMove=function(a){if(this.oldmouse){a=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];var b=this.value,b=b-0.01*(a[1]-this.oldmouse[1]);1b&&(b=0);this.value=b;this.properties.value=this.properties.min+(this.properties.max-this.properties.min)* -this.value;this.oldmouse=a;this.setDirtyCanvas(!0)}};a.prototype.onMouseUp=function(a){this.oldmouse&&(this.oldmouse=null,this.captureInput(!1))};a.prototype.onMouseLeave=function(a){};a.prototype.onWidget=function(a,b){if("increase"==b.name)this.onPropertyChange("size",this.properties.size+10);else if("decrease"==b.name)this.onPropertyChange("size",this.properties.size-10)};a.prototype.onPropertyChange=function(a,b){if("wcolor"==a)this.properties[a]=b;else if("size"==a)b=parseInt(b),this.properties[a]= -b,this.size=[b+4,b+24],this.setDirtyCanvas(!0,!0);else if("min"==a||"max"==a||"value"==a)this.properties[a]=parseFloat(b);else return!1;return!0};LiteGraph.registerNodeType("widget/knob",a);b.title="H.Slider";b.desc="Linear slider controller";b.prototype.onInit=function(){this.value=0.5;this.imgfg=this.loadImage("imgs/slider_fg.png")};b.prototype.onDrawVectorial=function(a){this.imgfg&&this.imgfg.width&&(a.lineWidth=1,a.strokeStyle=this.mouseOver?"#FFF":"#AAA",a.fillStyle="#000",a.beginPath(),a.rect(2, -0,this.size[0]-4,20),a.stroke(),a.fillStyle=this.properties.wcolor,a.beginPath(),a.rect(2+(this.size[0]-4-20)*this.value,0,20,20),a.fill())};b.prototype.onDrawImage=function(a){this.imgfg&&this.imgfg.width&&(a.lineWidth=1,a.fillStyle="#000",a.fillRect(2,9,this.size[0]-4,2),a.strokeStyle="#333",a.beginPath(),a.moveTo(2,9),a.lineTo(this.size[0]-4,9),a.stroke(),a.strokeStyle="#AAA",a.beginPath(),a.moveTo(2,11),a.lineTo(this.size[0]-4,11),a.stroke(),a.drawImage(this.imgfg,2+(this.size[0]-4)*this.value- -0.5*this.imgfg.width,0.5*-this.imgfg.height+10))};b.prototype.onDrawForeground=function(a){this.onDrawImage(a)};b.prototype.onExecute=function(){this.properties.value=this.properties.min+(this.properties.max-this.properties.min)*this.value;this.setOutputData(0,this.properties.value);this.boxcolor=colorToString([this.value,this.value,this.value])};b.prototype.onMouseDown=function(a){if(0>a.canvasY-this.pos[1])return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0); +function(a){if(this.imgfg&&this.imgfg.width){var b=0.5*this.imgbg.width,c=this.size[0]/this.imgfg.width;a.save();a.translate(0,20);a.scale(c,c);a.drawImage(this.imgbg,0,0);a.translate(b,b);a.rotate(2*this.value*Math.PI*6/8+10*Math.PI/8);a.translate(-b,-b);a.drawImage(this.imgfg,0,0);a.restore();this.title&&(a.font="bold 16px Criticized,Tahoma",a.fillStyle="rgba(100,100,100,0.8)",a.textAlign="center",a.fillText(this.title.toUpperCase(),0.5*this.size[0],18),a.textAlign="left")}};a.prototype.onDrawVectorKnob= +function(a){if(this.imgfg&&this.imgfg.width){a.lineWidth=1;a.strokeStyle=this.mouseOver?"#FFF":"#AAA";a.fillStyle="#000";a.beginPath();a.arc(0.5*this.size[0],0.5*this.size[1]+10,0.5*this.properties.size,0,2*Math.PI,!0);a.stroke();0a.canvasY-this.pos[1]||distance([a.canvasX,a.canvasY],[this.pos[0]+this.center[0],this.pos[1]+this.center[1]])>this.radius)return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0);return!0}};a.prototype.onMouseMove=function(a){if(this.oldmouse){a=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];var b=this.value,b=b-0.01*(a[1]-this.oldmouse[1]);1b&&(b=0);this.value=b;this.properties.value=this.properties.min+(this.properties.max- +this.properties.min)*this.value;this.oldmouse=a;this.setDirtyCanvas(!0)}};a.prototype.onMouseUp=function(a){this.oldmouse&&(this.oldmouse=null,this.captureInput(!1))};a.prototype.onMouseLeave=function(a){};a.prototype.onWidget=function(a,b){if("increase"==b.name)this.onPropertyChange("size",this.properties.size+10);else if("decrease"==b.name)this.onPropertyChange("size",this.properties.size-10)};a.prototype.onPropertyChange=function(a,b){if("wcolor"==a)this.properties[a]=b;else if("size"==a)b=parseInt(b), +this.properties[a]=b,this.size=[b+4,b+24],this.setDirtyCanvas(!0,!0);else if("min"==a||"max"==a||"value"==a)this.properties[a]=parseFloat(b);else return!1;return!0};LiteGraph.registerNodeType("widget/knob",a);b.title="H.Slider";b.desc="Linear slider controller";b.prototype.onInit=function(){this.value=0.5;this.imgfg=this.loadImage("imgs/slider_fg.png")};b.prototype.onDrawVectorial=function(a){this.imgfg&&this.imgfg.width&&(a.lineWidth=1,a.strokeStyle=this.mouseOver?"#FFF":"#AAA",a.fillStyle="#000", +a.beginPath(),a.rect(2,0,this.size[0]-4,20),a.stroke(),a.fillStyle=this.properties.wcolor,a.beginPath(),a.rect(2+(this.size[0]-4-20)*this.value,0,20,20),a.fill())};b.prototype.onDrawImage=function(a){this.imgfg&&this.imgfg.width&&(a.lineWidth=1,a.fillStyle="#000",a.fillRect(2,9,this.size[0]-4,2),a.strokeStyle="#333",a.beginPath(),a.moveTo(2,9),a.lineTo(this.size[0]-4,9),a.stroke(),a.strokeStyle="#AAA",a.beginPath(),a.moveTo(2,11),a.lineTo(this.size[0]-4,11),a.stroke(),a.drawImage(this.imgfg,2+(this.size[0]- +4)*this.value-0.5*this.imgfg.width,0.5*-this.imgfg.height+10))};b.prototype.onDrawForeground=function(a){this.onDrawImage(a)};b.prototype.onExecute=function(){this.properties.value=this.properties.min+(this.properties.max-this.properties.min)*this.value;this.setOutputData(0,this.properties.value);this.boxcolor=colorToString([this.value,this.value,this.value])};b.prototype.onMouseDown=function(a){if(0>a.canvasY-this.pos[1])return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0); return!0};b.prototype.onMouseMove=function(a){if(this.oldmouse){a=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];var b=this.value,b=b+(a[0]-this.oldmouse[0])/this.size[0];1b&&(b=0);this.value=b;this.oldmouse=a;this.setDirtyCanvas(!0)}};b.prototype.onMouseUp=function(a){this.oldmouse=null;this.captureInput(!1)};b.prototype.onMouseLeave=function(a){};b.prototype.onPropertyChange=function(a,b){if("wcolor"==a)this.properties[a]=b;else return!1;return!0};LiteGraph.registerNodeType("widget/hslider", b);c.title="Progress";c.desc="Shows data in linear progress";c.prototype.onExecute=function(){var a=this.getInputData(0);void 0!=a&&(this.properties.value=a)};c.prototype.onDrawForeground=function(a){a.lineWidth=1;a.fillStyle=this.properties.wcolor;var b=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min),b=Math.min(1,b),b=Math.max(0,b);a.fillRect(2,2,(this.size[0]-4)*b,this.size[1]-4)};LiteGraph.registerNodeType("widget/progress",c);d.title="Text";d.desc="Shows the input value"; d.widgets=[{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}];d.prototype.onDrawForeground=function(a){a.fillStyle=this.properties.color;var b=this.properties.value;this.properties.glowSize?(a.shadowColor=this.properties.color,a.shadowOffsetX=0,a.shadowOffsetY=0,a.shadowBlur=this.properties.glowSize):a.shadowColor="transparent";var c=this.properties.fontsize;a.textAlign=this.properties.align;a.font=c.toString()+ @@ -149,19 +159,20 @@ e.prototype.onWidget=function(a,b){"update"==b.name&&(this.lineargradient=null,t (function(){function a(){this.addOutput("value","number");this.properties={min:0,max:1};this.size=[60,20]}function b(){this.addInput("in","number");this.addOutput("out","number");this.size=[60,20];this.properties={min:0,max:1}}function c(){this.addInput("in","number");this.addOutput("out","number");this.size=[60,20]}function d(){this.addInput("in","number");this.addOutput("out","number");this.size=[60,20]}function e(){this.addInput("in","number");this.addOutput("out","number");this.size=[60,20]}function f(){this.addInput("in", "number",{label:""});this.addOutput("out","number",{label:""});this.size=[60,20];this.properties={factor:1}}function g(){this.addInput("A","number");this.addInput("B","number");this.addOutput("A+B","number");this.properties={A:1,B:1}}function h(){this.addInputs("A","number");this.addInputs("B","number");this.addOutputs("A==B","number");this.addOutputs("A!=B","number");this.properties={A:0,B:0}}function l(){this.addInput("inc","number");this.addOutput("total","number");this.properties={increment:0, value:0}}function n(){this.addInput("v","number");this.addOutput("sin","number");this.properties={amplitude:1,offset:0};this.bgImageUrl="nodes/imgs/icon-sin.png"}a.title="Rand";a.desc="Random number";a.prototype.onExecute=function(){var a=this.properties.min,b=this.properties.max;this._last_v=Math.random()*(b-a)+a;this.setOutputData(0,this._last_v)};a.prototype.onDrawBackground=function(a){this.outputs[0].label=this._last_v?this._last_v.toFixed(3):"?"};LiteGraph.registerNodeType("math/rand",a);b.title= -"Clamp";b.desc="Clamp number between min and max";b.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(a=Math.max(this.properties.min,a),a=Math.min(this.properties.max,a),this.setOutputData(0,a))};LiteGraph.registerNodeType("math/clamp",b);c.title="Abs";c.desc="Absolute";c.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,Math.abs(a))};LiteGraph.registerNodeType("math/abs",c);d.title="Floor";d.desc="Floor number to remove fractional part";d.prototype.onExecute= -function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a|1)};LiteGraph.registerNodeType("math/floor",d);e.title="Frac";e.desc="Returns fractional part";e.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a%1)};LiteGraph.registerNodeType("math/frac",e);f.title="Scale";f.desc="v * factor";f.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a*this.properties.factor)};LiteGraph.registerNodeType("math/scale",f);g.title= -"Operation";g.desc="Easy math operators";g.prototype.setValue=function(a){"string"==typeof a&&(a=parseFloat(a));this.properties.value=a;this.setDirtyCanvas(!0)};g.prototype.onExecute=function(){var a=this.getInputData(0),b=this.getInputData(1);null!=a?this.properties.A=a:a=this.properties.A;null!=b?this.properties.B=b:b=this.properties.B;for(var c=0,d=this.outputs.length;cB":value=a>b;break;case "A=B":value=a>=b}this.setOutputData(c,value)}}};h.prototype.onGetOutputs=function(){return[["A==B","number"],["A!=B","number"],["A>B","number"],["A=B","number"],["A<=B","number"]]};LiteGraph.registerNodeType("math/compare",h);l.title="Accumulate";l.desc="Increments a value every time";l.prototype.onExecute= -function(){var a=this.getInputData(0);this.properties.value=null!==a?this.properties.value+a:this.properties.value+this.properties.increment;this.setOutputData(0,this.properties.value)};LiteGraph.registerNodeType("math/accumulate",l);n.title="Trigonometry";n.desc="Sin Cos Tan";n.prototype.onExecute=function(){var a=this.getInputData(0),b=this.properties.amplitude,c=this.findInputSlot("amplitude");-1!=c&&(b=this.getInputData(c));var d=this.properties.offset,c=this.findInputSlot("offset");-1!=c&&(d= -this.getInputData(c));for(var c=0,e=this.outputs.length;cXYZ", -k.desc="vector 3 to components",k.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]))},LiteGraph.registerNodeType("math3d/vec3-to-xyz",k),k=function(){this.addInputs([["x","number"],["y","number"],["z","number"]]);this.addOutput("vec3","vec3");this.properties={x:0,y:0,z:0}},k.title="XYZ->Vec3",k.desc="components to vector3",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x); -var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);this.setOutputData(0,vec3.fromValues(a,b,c))},LiteGraph.registerNodeType("math3d/xyz-to-vec3",k),k=function(){this.addInputs([["degrees","number"],["axis","vec3"]]);this.addOutput("quat","quat");this.properties={angle:90,axis:vec3.fromValues(0,1,0)}},k.title="Rotation",k.desc="quaternion rotation",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle); -var b=this.getInputData(1);null==b&&(b=this.properties.axis);a=quat.setAxisAngle(quat.create(),b,0.0174532925*a);this.setOutputData(0,a)},LiteGraph.registerNodeType("math3d/rotation",k),k=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},k.title="Rot. Vec3",k.desc="rotate a point",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a): -this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))},LiteGraph.registerNodeType("math3d/rotate_vec3",k),k=function(){this.addInputs([["A","quat"],["B","quat"]]);this.addOutput("A*B","quat")},k.title="Mult. Quat",k.desc="rotate quaternion",k.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(quat.create(),a,b),this.setOutputData(0,a))}},LiteGraph.registerNodeType("math3d/mult-quat",k))})(); +"Clamp";b.desc="Clamp number between min and max";b.filter="shader";b.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(a=Math.max(this.properties.min,a),a=Math.min(this.properties.max,a),this.setOutputData(0,a))};b.prototype.getCode=function(a){a="";this.isInputConnected(0)&&(a+="clamp({{0}},"+this.properties.min+","+this.properties.max+")");return a};LiteGraph.registerNodeType("math/clamp",b);c.title="Abs";c.desc="Absolute";c.prototype.onExecute=function(){var a=this.getInputData(0); +null!=a&&this.setOutputData(0,Math.abs(a))};LiteGraph.registerNodeType("math/abs",c);d.title="Floor";d.desc="Floor number to remove fractional part";d.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,Math.floor(a))};LiteGraph.registerNodeType("math/floor",d);e.title="Frac";e.desc="Returns fractional part";e.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a%1)};LiteGraph.registerNodeType("math/frac",e);f.title="Scale";f.desc= +"v * factor";f.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a*this.properties.factor)};LiteGraph.registerNodeType("math/scale",f);g.title="Operation";g.desc="Easy math operators";g.prototype.setValue=function(a){"string"==typeof a&&(a=parseFloat(a));this.properties.value=a;this.setDirtyCanvas(!0)};g.prototype.onExecute=function(){var a=this.getInputData(0),b=this.getInputData(1);null!=a?this.properties.A=a:a=this.properties.A;null!=b?this.properties.B=b: +b=this.properties.B;for(var c=0,d=this.outputs.length;cB":value=a>b;break;case "A=B":value=a>=b}this.setOutputData(c,value)}}};h.prototype.onGetOutputs=function(){return[["A==B","number"],["A!=B","number"], +["A>B","number"],["A=B","number"],["A<=B","number"]]};LiteGraph.registerNodeType("math/compare",h);l.title="Accumulate";l.desc="Increments a value every time";l.prototype.onExecute=function(){var a=this.getInputData(0);this.properties.value=null!==a?this.properties.value+a:this.properties.value+this.properties.increment;this.setOutputData(0,this.properties.value)};LiteGraph.registerNodeType("math/accumulate",l);n.title="Trigonometry";n.desc="Sin Cos Tan";n.filter="shader";n.prototype.onExecute= +function(){var a=this.getInputData(0),b=this.properties.amplitude,c=this.findInputSlot("amplitude");-1!=c&&(b=this.getInputData(c));var d=this.properties.offset,c=this.findInputSlot("offset");-1!=c&&(d=this.getInputData(c));for(var c=0,e=this.outputs.length;cXYZ",k.desc="vector 3 to components",k.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]))},LiteGraph.registerNodeType("math3d/vec3-to-xyz",k),k=function(){this.addInputs([["x","number"],["y","number"],["z","number"]]);this.addOutput("vec3", +"vec3");this.properties={x:0,y:0,z:0}},k.title="XYZ->Vec3",k.desc="components to vector3",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);this.setOutputData(0,vec3.fromValues(a,b,c))},LiteGraph.registerNodeType("math3d/xyz-to-vec3",k),k=function(){this.addInputs([["degrees","number"],["axis","vec3"]]);this.addOutput("quat","quat");this.properties= +{angle:90,axis:vec3.fromValues(0,1,0)}},k.title="Rotation",k.desc="quaternion rotation",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle);var b=this.getInputData(1);null==b&&(b=this.properties.axis);a=quat.setAxisAngle(quat.create(),b,0.0174532925*a);this.setOutputData(0,a)},LiteGraph.registerNodeType("math3d/rotation",k),k=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},k.title= +"Rot. Vec3",k.desc="rotate a point",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a):this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))},LiteGraph.registerNodeType("math3d/rotate_vec3",k),k=function(){this.addInputs([["A","quat"],["B","quat"]]);this.addOutput("A*B","quat")},k.title="Mult. Quat",k.desc="rotate quaternion",k.prototype.onExecute=function(){var a=this.getInputData(0);if(null!= +a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(quat.create(),a,b),this.setOutputData(0,a))}},LiteGraph.registerNodeType("math3d/mult-quat",k))})(); (function(){function a(){this.addInput("f","number");this.addOutput("Color","color");this.properties={colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"}}function b(){this.addInput("","image");this.size=[200,200]}function c(){this.addInputs([["img1","image"],["img2","image"],["fade","number"]]);this.addInput("","image");this.properties={fade:0.5,width:512,height:512}}function d(){this.inputs=[];this.addOutput("frame","image");this.properties={url:""}}function e(){this.addInput("", "image");this.addOutputs("","image");this.properties={width:256,height:256,x:0,y:0,scale:1};this.size=[50,20]}function f(){this.addInput("t","number");this.addOutputs([["frame","image"],["t","number"],["d","number"]]);this.properties={url:""}}function g(){this.addOutput("Webcam","image");this.properties={}}a.title="Palette";a.desc="Generates a color";a.prototype.onExecute=function(){var a=[];null!=this.properties.colorA&&a.push(hex2num(this.properties.colorA));null!=this.properties.colorB&&a.push(hex2num(this.properties.colorB)); null!=this.properties.colorC&&a.push(hex2num(this.properties.colorC));null!=this.properties.colorD&&a.push(hex2num(this.properties.colorD));var b=this.getInputData(0);null==b&&(b=0.5);1b&&(b=0);if(0!=a.length){var c=[0,0,0];if(0==b)c=a[0];else if(1==b)c=a[a.length-1];else{var d=(a.length-1)*b,b=a[Math.floor(d)],a=a[Math.floor(d)+1],d=d-Math.floor(d);c[0]=b[0]*(1-d)+a[0]*d;c[1]=b[1]*(1-d)+a[1]*d;c[2]=b[2]*(1-d)+a[2]*d}for(var e in c)c[e]/=255;this.boxcolor=colorToString(c);this.setOutputData(0, diff --git a/demo/demo.js b/demo/demo.js index 13c5c314c..500503655 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -45,7 +45,7 @@ function multiConnection() var node_const_A = LiteGraph.createNode("basic/const"); node_const_A.pos = [200,200]; graph.add(node_const_A); - node_const_A.setValue(4); + node_const_A.setValue(4.5); var node_const_B = LiteGraph.createNode("basic/const"); node_const_B.pos = [200,300]; diff --git a/doc/classes/LGraph.html b/doc/classes/LGraph.html index 67608031b..3f2ad8322 100644 --- a/doc/classes/LGraph.html +++ b/doc/classes/LGraph.html @@ -637,7 +637,7 @@ - ../src/litegraph.js:922 + ../src/litegraph.js:1018

@@ -1477,7 +1477,7 @@ if the nodes are using graphical actions

- ../src/litegraph.js:856 + ../src/litegraph.js:952

@@ -1825,7 +1825,7 @@ if the nodes are using graphical actions

- ../src/litegraph.js:889 + ../src/litegraph.js:985

@@ -1910,7 +1910,7 @@ if the nodes are using graphical actions

- ../src/litegraph.js:804 + ../src/litegraph.js:900

@@ -2020,7 +2020,7 @@ can be easily accesed from the outside of the graph

- ../src/litegraph.js:819 + ../src/litegraph.js:915

diff --git a/doc/classes/LGraphCanvas.html b/doc/classes/LGraphCanvas.html index 2d66a2b02..ebb18c716 100644 --- a/doc/classes/LGraphCanvas.html +++ b/doc/classes/LGraphCanvas.html @@ -96,7 +96,7 @@ @@ -163,7 +163,7 @@ - ../src/litegraph.js:2116 + ../src/litegraph.js:2278

@@ -254,6 +254,13 @@ + + +
  • + closeSubgraph + + +
  • @@ -261,6 +268,13 @@ +
  • + +
  • + openSubgraph + + +
  • @@ -339,7 +353,7 @@ - ../src/litegraph.js:1912 + ../src/litegraph.js:2032

    @@ -359,6 +373,95 @@ + + + +
    +

    closeSubgraph

    + + +
    + (
      + +
    • + + assigns + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + ../src/litegraph.js:2141 + +

    + + + + + +
    + +
    +

    closes a subgraph contained inside a node

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + assigns + LGraph + + + + +
      +

      a graph

      + +
      + + +
    • + +
    +
    + + + + +
    @@ -398,7 +501,7 @@ - ../src/litegraph.js:2132 + ../src/litegraph.js:2294

    @@ -432,6 +535,94 @@ + + + +
    +

    openSubgraph

    + + +
    + (
      + +
    • + + graph + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + ../src/litegraph.js:2114 + +

    + + + + + +
    + +
    +

    opens a graph contained inside a node in the current graph

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graph + LGraph + + + + +
      + +
      + + +
    • + +
    +
    + + + + +
    @@ -477,7 +668,7 @@ - ../src/litegraph.js:1994 + ../src/litegraph.js:2156

    @@ -533,7 +724,7 @@
  • - assigns + graph
  • @@ -566,7 +757,7 @@ - ../src/litegraph.js:1966 + ../src/litegraph.js:2086

    @@ -589,15 +780,14 @@
  • - assigns + graph LGraph
    -

    a graph

    - +
    @@ -645,7 +835,7 @@ - ../src/litegraph.js:2144 + ../src/litegraph.js:2306

    @@ -700,7 +890,7 @@ - ../src/litegraph.js:2175 + ../src/litegraph.js:2337

    diff --git a/doc/classes/LGraphNode.html b/doc/classes/LGraphNode.html index 36fc193be..d6790beea 100644 --- a/doc/classes/LGraphNode.html +++ b/doc/classes/LGraphNode.html @@ -96,7 +96,7 @@ @@ -415,7 +415,7 @@ - ../src/litegraph.js:1385 + ../src/litegraph.js:1528

    @@ -563,7 +563,7 @@ - ../src/litegraph.js:1331 + ../src/litegraph.js:1468

    @@ -683,7 +683,7 @@ - ../src/litegraph.js:1350 + ../src/litegraph.js:1489

    @@ -784,7 +784,7 @@ - ../src/litegraph.js:1277 + ../src/litegraph.js:1408

    @@ -904,7 +904,7 @@ - ../src/litegraph.js:1296 + ../src/litegraph.js:1429

    @@ -983,7 +983,7 @@ - ../src/litegraph.js:1842 + ../src/litegraph.js:1962

    @@ -1052,7 +1052,7 @@ - ../src/litegraph.js:1398 + ../src/litegraph.js:1541

    @@ -1144,7 +1144,7 @@ - ../src/litegraph.js:1029 + ../src/litegraph.js:1125

    @@ -1225,7 +1225,7 @@ - ../src/litegraph.js:1478 + ../src/litegraph.js:1621

    @@ -1364,7 +1364,7 @@ - ../src/litegraph.js:1628 + ../src/litegraph.js:1771

    @@ -1477,7 +1477,7 @@ - ../src/litegraph.js:1561 + ../src/litegraph.js:1704

    @@ -1600,7 +1600,7 @@ - ../src/litegraph.js:1448 + ../src/litegraph.js:1591

    @@ -1707,7 +1707,7 @@ - ../src/litegraph.js:1463 + ../src/litegraph.js:1606

    @@ -1804,7 +1804,7 @@ - ../src/litegraph.js:1416 + ../src/litegraph.js:1559

    @@ -1893,7 +1893,7 @@ - ../src/litegraph.js:1685 + ../src/litegraph.js:1828

    @@ -2016,7 +2016,7 @@ - ../src/litegraph.js:1180 + ../src/litegraph.js:1311

    @@ -2122,7 +2122,7 @@ - ../src/litegraph.js:1206 + ../src/litegraph.js:1337

    @@ -2226,7 +2226,7 @@ - ../src/litegraph.js:1221 + ../src/litegraph.js:1352

    @@ -2330,7 +2330,7 @@ - ../src/litegraph.js:1248 + ../src/litegraph.js:1379

    @@ -2420,7 +2420,7 @@ - ../src/litegraph.js:1148 + ../src/litegraph.js:1279

    @@ -2489,7 +2489,7 @@ - ../src/litegraph.js:1194 + ../src/litegraph.js:1325

    @@ -2593,7 +2593,7 @@ - ../src/litegraph.js:1236 + ../src/litegraph.js:1367

    @@ -2703,7 +2703,7 @@ - ../src/litegraph.js:1426 + ../src/litegraph.js:1569

    @@ -2808,7 +2808,7 @@ - ../src/litegraph.js:1855 + ../src/litegraph.js:1975

    @@ -2873,7 +2873,7 @@ - ../src/litegraph.js:1373 + ../src/litegraph.js:1514

    @@ -2961,7 +2961,7 @@ - ../src/litegraph.js:1319 + ../src/litegraph.js:1454

    @@ -3039,7 +3039,7 @@ - ../src/litegraph.js:1075 + ../src/litegraph.js:1176

    @@ -3110,7 +3110,7 @@ - ../src/litegraph.js:1161 + ../src/litegraph.js:1292

    @@ -3203,7 +3203,7 @@ - ../src/litegraph.js:1136 + ../src/litegraph.js:1267

    diff --git a/doc/data.json b/doc/data.json index 4e51b636d..5f149b208 100644 --- a/doc/data.json +++ b/doc/data.json @@ -51,7 +51,7 @@ "plugin_for": [], "extension_for": [], "file": "../src/litegraph.js", - "line": 1000, + "line": 1096, "description": "Base Class for all the node type classes", "params": [ { @@ -70,7 +70,7 @@ "plugin_for": [], "extension_for": [], "file": "../src/litegraph.js", - "line": 2116, + "line": 2278, "description": "marks as dirty the canvas, this way it will be rendered again", "is_constructor": 1, "params": [ @@ -438,7 +438,7 @@ }, { "file": "../src/litegraph.js", - "line": 804, + "line": 900, "description": "Assigns a value to all the nodes that matches this name. This is used to create global variables of the node that\ncan be easily accesed from the outside of the graph", "itemtype": "method", "name": "setInputData", @@ -458,7 +458,7 @@ }, { "file": "../src/litegraph.js", - "line": 819, + "line": 915, "description": "Returns the value of the first node with this name. This is used to access global variables of the graph from the outside", "itemtype": "method", "name": "setInputData", @@ -477,7 +477,7 @@ }, { "file": "../src/litegraph.js", - "line": 856, + "line": 952, "description": "returns if the graph is in live mode", "itemtype": "method", "name": "isLive", @@ -485,7 +485,7 @@ }, { "file": "../src/litegraph.js", - "line": 889, + "line": 985, "description": "Creates a Object containing all the info about this graph, it can be serialized", "itemtype": "method", "name": "serialize", @@ -497,7 +497,7 @@ }, { "file": "../src/litegraph.js", - "line": 922, + "line": 1018, "description": "Configure a graph from a JSON string", "itemtype": "method", "name": "configure", @@ -512,7 +512,7 @@ }, { "file": "../src/litegraph.js", - "line": 1029, + "line": 1125, "description": "configure a node from an object containing the serialized info", "itemtype": "method", "name": "configure", @@ -520,7 +520,7 @@ }, { "file": "../src/litegraph.js", - "line": 1075, + "line": 1176, "description": "serialize the content", "itemtype": "method", "name": "serialize", @@ -528,7 +528,7 @@ }, { "file": "../src/litegraph.js", - "line": 1136, + "line": 1267, "description": "serialize and stringify", "itemtype": "method", "name": "toString", @@ -536,7 +536,7 @@ }, { "file": "../src/litegraph.js", - "line": 1148, + "line": 1279, "description": "get the title string", "itemtype": "method", "name": "getTitle", @@ -544,7 +544,7 @@ }, { "file": "../src/litegraph.js", - "line": 1161, + "line": 1292, "description": "sets the output data", "itemtype": "method", "name": "setOutputData", @@ -564,7 +564,7 @@ }, { "file": "../src/litegraph.js", - "line": 1180, + "line": 1311, "description": "retrieves the input data from one slot", "itemtype": "method", "name": "getInputData", @@ -583,7 +583,7 @@ }, { "file": "../src/litegraph.js", - "line": 1194, + "line": 1325, "description": "tells you if there is a connection in one input slot", "itemtype": "method", "name": "isInputConnected", @@ -602,7 +602,7 @@ }, { "file": "../src/litegraph.js", - "line": 1206, + "line": 1337, "description": "tells you info about an input connection (which node, type, etc)", "itemtype": "method", "name": "getInputInfo", @@ -621,7 +621,7 @@ }, { "file": "../src/litegraph.js", - "line": 1221, + "line": 1352, "description": "tells you info about an output connection (which node, type, etc)", "itemtype": "method", "name": "getOutputInfo", @@ -640,7 +640,7 @@ }, { "file": "../src/litegraph.js", - "line": 1236, + "line": 1367, "description": "tells you if there is a connection in one output slot", "itemtype": "method", "name": "isOutputConnected", @@ -659,7 +659,7 @@ }, { "file": "../src/litegraph.js", - "line": 1248, + "line": 1379, "description": "retrieves all the nodes connected to this output slot", "itemtype": "method", "name": "getOutputNodes", @@ -678,7 +678,7 @@ }, { "file": "../src/litegraph.js", - "line": 1277, + "line": 1408, "description": "add a new output slot to use in this node", "itemtype": "method", "name": "addOutput", @@ -703,7 +703,7 @@ }, { "file": "../src/litegraph.js", - "line": 1296, + "line": 1429, "description": "add a new output slot to use in this node", "itemtype": "method", "name": "addOutputs", @@ -718,7 +718,7 @@ }, { "file": "../src/litegraph.js", - "line": 1319, + "line": 1454, "description": "remove an existing output slot", "itemtype": "method", "name": "removeOutput", @@ -733,7 +733,7 @@ }, { "file": "../src/litegraph.js", - "line": 1331, + "line": 1468, "description": "add a new input slot to use in this node", "itemtype": "method", "name": "addInput", @@ -758,7 +758,7 @@ }, { "file": "../src/litegraph.js", - "line": 1350, + "line": 1489, "description": "add several new input slots in this node", "itemtype": "method", "name": "addInputs", @@ -773,7 +773,7 @@ }, { "file": "../src/litegraph.js", - "line": 1373, + "line": 1514, "description": "remove an existing input slot", "itemtype": "method", "name": "removeInput", @@ -788,7 +788,7 @@ }, { "file": "../src/litegraph.js", - "line": 1385, + "line": 1528, "description": "add an special connection to this node (used for special kinds of graphs)", "itemtype": "method", "name": "addConnection", @@ -818,7 +818,7 @@ }, { "file": "../src/litegraph.js", - "line": 1398, + "line": 1541, "description": "computes the size of a node according to its inputs and output slots", "itemtype": "method", "name": "computeSize", @@ -837,7 +837,7 @@ }, { "file": "../src/litegraph.js", - "line": 1416, + "line": 1559, "description": "returns the bounding of the object, used for rendering purposes", "itemtype": "method", "name": "getBounding", @@ -849,7 +849,7 @@ }, { "file": "../src/litegraph.js", - "line": 1426, + "line": 1569, "description": "checks if a point is inside the shape of a node", "itemtype": "method", "name": "isPointInsideNode", @@ -873,7 +873,7 @@ }, { "file": "../src/litegraph.js", - "line": 1448, + "line": 1591, "description": "returns the input slot with a given name (used for dynamic slots), -1 if not found", "itemtype": "method", "name": "findInputSlot", @@ -892,7 +892,7 @@ }, { "file": "../src/litegraph.js", - "line": 1463, + "line": 1606, "description": "returns the output slot with a given name (used for dynamic slots), -1 if not found", "itemtype": "method", "name": "findOutputSlot", @@ -911,7 +911,7 @@ }, { "file": "../src/litegraph.js", - "line": 1478, + "line": 1621, "description": "connect this node output to the input of another node", "itemtype": "method", "name": "connect", @@ -940,7 +940,7 @@ }, { "file": "../src/litegraph.js", - "line": 1561, + "line": 1704, "description": "disconnect one output to an specific node", "itemtype": "method", "name": "disconnectOutput", @@ -964,7 +964,7 @@ }, { "file": "../src/litegraph.js", - "line": 1628, + "line": 1771, "description": "disconnect one input", "itemtype": "method", "name": "disconnectInput", @@ -983,7 +983,7 @@ }, { "file": "../src/litegraph.js", - "line": 1685, + "line": 1828, "description": "returns the center of a connection point in canvas coords", "itemtype": "method", "name": "getConnectionPos", @@ -1007,7 +1007,7 @@ }, { "file": "../src/litegraph.js", - "line": 1842, + "line": 1962, "description": "Collapse the node to make it smaller on the canvas", "itemtype": "method", "name": "collapse", @@ -1015,7 +1015,7 @@ }, { "file": "../src/litegraph.js", - "line": 1855, + "line": 1975, "description": "Forces the node to do not move or realign on Z", "itemtype": "method", "name": "pin", @@ -1023,7 +1023,7 @@ }, { "file": "../src/litegraph.js", - "line": 1912, + "line": 2032, "description": "clears all the data inside", "itemtype": "method", "name": "clear", @@ -1031,10 +1031,40 @@ }, { "file": "../src/litegraph.js", - "line": 1966, + "line": 2086, "description": "assigns a graph, you can reasign graphs to the same canvas", "itemtype": "method", "name": "setGraph", + "params": [ + { + "name": "graph", + "description": "", + "type": "LGraph" + } + ], + "class": "LGraphCanvas" + }, + { + "file": "../src/litegraph.js", + "line": 2114, + "description": "opens a graph contained inside a node in the current graph", + "itemtype": "method", + "name": "openSubgraph", + "params": [ + { + "name": "graph", + "description": "", + "type": "LGraph" + } + ], + "class": "LGraphCanvas" + }, + { + "file": "../src/litegraph.js", + "line": 2141, + "description": "closes a subgraph contained inside a node", + "itemtype": "method", + "name": "closeSubgraph", "params": [ { "name": "assigns", @@ -1046,7 +1076,7 @@ }, { "file": "../src/litegraph.js", - "line": 1994, + "line": 2156, "description": "assigns a canvas", "itemtype": "method", "name": "setCanvas", @@ -1061,7 +1091,7 @@ }, { "file": "../src/litegraph.js", - "line": 2132, + "line": 2294, "description": "Used to attach the canvas in a popup", "itemtype": "method", "name": "getCanvasWindow", @@ -1073,7 +1103,7 @@ }, { "file": "../src/litegraph.js", - "line": 2144, + "line": 2306, "description": "starts rendering the content of the canvas when needed", "itemtype": "method", "name": "startRendering", @@ -1081,7 +1111,7 @@ }, { "file": "../src/litegraph.js", - "line": 2175, + "line": 2337, "description": "stops rendering the content of the canvas (to save resources)", "itemtype": "method", "name": "stopRendering", diff --git a/doc/files/.._src_litegraph.js.html b/doc/files/.._src_litegraph.js.html index 7c64f139b..1fecedaf9 100644 --- a/doc/files/.._src_litegraph.js.html +++ b/doc/files/.._src_litegraph.js.html @@ -379,7 +379,7 @@ LGraph.prototype.clear = function() this.global_inputs = {}; this.global_outputs = {}; - this.graph = {}; + //this.graph = {}; this.debug = true; this.change(); @@ -854,10 +854,18 @@ LGraph.prototype.getNodeOnPos = function(x,y, nodes_list) return null; } +// ********** GLOBALS ***************** + //Tell this graph has a global input of this type LGraph.prototype.addGlobalInput = function(name, type, value) { - this.global_inputs[name] = { type: type, value: value }; + this.global_inputs[name] = { name: name, type: type, value: value }; + + if(this.onGlobalInputAdded) + this.onGlobalInputAdded(name, type); + + if(this.onGlobalsChange) + this.onGlobalsChange(); } //assign a data to the global input @@ -869,29 +877,117 @@ LGraph.prototype.setGlobalInputData = function(name, data) input.value = data; } +//assign a data to the global input +LGraph.prototype.getGlobalInputData = function(name) +{ + var input = this.global_inputs[name]; + if (!input) + return null; + return input.value; +} + //rename the global input LGraph.prototype.renameGlobalInput = function(old_name, name, data) { + if(!this.global_inputs[old_name]) + return false; + + if(this.global_inputs[name]) + { + console.error("there is already one input with that name"); + return false; + } + + this.global_inputs[name] = this.global_inputs[old_name]; + delete this.global_inputs[old_name]; + + if(this.onGlobalInputRenamed) + this.onGlobalInputRenamed(old_name, name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); +} + +LGraph.prototype.removeGlobalInput = function(name) +{ + if(!this.global_inputs[name]) + return false; + + delete this.global_inputs[name]; + + if(this.onGlobalInputRemoved) + this.onGlobalInputRemoved(name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); + return true; } LGraph.prototype.addGlobalOutput = function(name, type, value) { - this.global_outputs[name] = { type: type, value: value }; + this.global_outputs[name] = { name: name, type: type, value: value }; + + if(this.onGlobalOutputAdded) + this.onGlobalOutputAdded(name, type); + + if(this.onGlobalsChange) + this.onGlobalsChange(); } //assign a data to the global output -LGraph.prototype.setGlobalOutputData = function(name, data) +LGraph.prototype.setGlobalOutputData = function(name, value) { var output = this.global_outputs[ name ]; if (!output) return; - output.value = data; + output.value = value; } +//assign a data to the global input +LGraph.prototype.getGlobalOutputData = function(name) +{ + var output = this.global_outputs[name]; + if (!output) + return null; + return output.value; +} + + //rename the global output LGraph.prototype.renameGlobalOutput = function(old_name, name, data) { + if(!this.global_outputs[old_name]) + return false; + + if(this.global_outputs[name]) + { + console.error("there is already one output with that name"); + return false; + } + + this.global_outputs[name] = this.global_outputs[old_name]; + delete this.global_outputs[old_name]; + + if(this.onGlobalOutputRenamed) + this.onGlobalOutputRenamed(old_name, name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); +} + +LGraph.prototype.removeGlobalOutput = function(name) +{ + if(!this.global_outputs[name]) + return false; + delete this.global_outputs[name]; + + if(this.onGlobalOutputRemoved) + this.onGlobalOutputRemoved(name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); + return true; } @@ -997,7 +1093,7 @@ LGraph.prototype.serialize = function() var data = { - graph: this.graph, +// graph: this.graph, iteration: this.iteration, frame: this.frame, @@ -1133,7 +1229,12 @@ LGraphNode.prototype.configure = function(info) if(info[j] == null) continue; else if (typeof(info[j]) == 'object') //object - this[j] = LiteGraph.cloneObject(info[j], this[j]); + { + if(this[j] && this[j].configure) + this[j].configure( info[j] ); + else + this[j] = LiteGraph.cloneObject(info[j], this[j]); + } else //value this[j] = info[j]; } @@ -1206,6 +1307,36 @@ LGraphNode.prototype.serialize = function() return o; } + +/* Creates a clone of this node */ +LGraphNode.prototype.clone = function() +{ + var node = LiteGraph.createNode(this.type); + + var data = this.serialize(); + delete data["id"]; + node.configure(data); + + /* + node.size = this.size.concat(); + if(this.inputs) + for(var i = 0, l = this.inputs.length; i < l; ++i) + { + if(node.findInputSlot( this.inputs[i].name ) == -1) + node.addInput( this.inputs[i].name, this.inputs[i].type ); + } + + if(this.outputs) + for(var i = 0, l = this.outputs.length; i < l; ++i) + { + if(node.findOutputSlot( this.outputs[i].name ) == -1) + node.addOutput( this.outputs[i].name, this.outputs[i].type ); + } + */ + + return node; +} + //reduced version of objectivize: NOT FINISHED /* LGraphNode.prototype.reducedObjectivize = function() @@ -1384,6 +1515,8 @@ LGraphNode.prototype.addOutput = function(name,type,extra_info) if(!this.outputs) this.outputs = []; this.outputs.push(o); + if(this.onOutputAdded) + this.onOutputAdded(o); this.size = this.computeSize(); } @@ -1405,6 +1538,8 @@ LGraphNode.prototype.addOutputs = function(array) if(!this.outputs) this.outputs = []; this.outputs.push(o); + if(this.onOutputAdded) + this.onOutputAdded(o); } this.size = this.computeSize(); @@ -1420,6 +1555,8 @@ LGraphNode.prototype.removeOutput = function(slot) this.disconnectOutput(slot); this.outputs.splice(slot,1); this.size = this.computeSize(); + if(this.onOutputRemoved) + this.onOutputRemoved(slot); } /** @@ -1439,6 +1576,8 @@ LGraphNode.prototype.addInput = function(name,type,extra_info) if(!this.inputs) this.inputs = []; this.inputs.push(o); this.size = this.computeSize(); + if(this.onInputAdded) + this.onInputAdded(o); } /** @@ -1459,6 +1598,8 @@ LGraphNode.prototype.addInputs = function(array) if(!this.inputs) this.inputs = []; this.inputs.push(o); + if(this.onInputAdded) + this.onInputAdded(o); } this.size = this.computeSize(); @@ -1474,6 +1615,8 @@ LGraphNode.prototype.removeInput = function(slot) this.disconnectInput(slot); this.inputs.splice(slot,1); this.size = this.computeSize(); + if(this.onInputRemoved) + this.onInputRemoved(slot); } /** @@ -1816,29 +1959,6 @@ LGraphNode.prototype.alignToGrid = function() this.pos[1] = LiteGraph.CANVAS_GRID_SIZE * Math.round(this.pos[1] / LiteGraph.CANVAS_GRID_SIZE); } -/* Creates a clone of this node */ -LGraphNode.prototype.clone = function() -{ - var node = LiteGraph.createNode(this.type); - - node.size = this.size.concat(); - if(this.inputs) - for(var i = 0, l = this.inputs.length; i < l; ++i) - { - if(node.findInputSlot( this.inputs[i].name ) == -1) - node.addInput( this.inputs[i].name, this.inputs[i].type ); - } - - if(this.outputs) - for(var i = 0, l = this.outputs.length; i < l; ++i) - { - if(node.findOutputSlot( this.outputs[i].name ) == -1) - node.addOutput( this.outputs[i].name, this.outputs[i].type ); - } - - - return node; -} /* Console output */ LGraphNode.prototype.trace = function(msg) @@ -2061,7 +2181,7 @@ LGraphCanvas.prototype.clear = function() * assigns a graph, you can reasign graphs to the same canvas * * @method setGraph -* @param {LGraph} assigns a graph +* @param {LGraph} graph */ LGraphCanvas.prototype.setGraph = function(graph) { @@ -2085,6 +2205,48 @@ LGraphCanvas.prototype.setGraph = function(graph) this.setDirty(true,true); } +/** +* opens a graph contained inside a node in the current graph +* +* @method openSubgraph +* @param {LGraph} graph +*/ +LGraphCanvas.prototype.openSubgraph = function(graph) +{ + if(!graph) + throw("graph cannot be null"); + + if(this.graph == graph) + throw("graph cannot be the same"); + + this.clear(); + + if(this.graph) + { + if(!this._graph_stack) + this._graph_stack = []; + this._graph_stack.push(this.graph); + } + + graph.attachCanvas(this); + this.setDirty(true,true); +} + +/** +* closes a subgraph contained inside a node +* +* @method closeSubgraph +* @param {LGraph} assigns a graph +*/ +LGraphCanvas.prototype.closeSubgraph = function() +{ + if(!this._graph_stack || this._graph_stack.length == 0) + return; + var graph = this._graph_stack.pop(); + graph.attachCanvas(this); + this.setDirty(true,true); +} + /** * assigns a canvas * @@ -3988,32 +4150,59 @@ LGraphCanvas.node_colors = { LGraphCanvas.prototype.getCanvasMenuOptions = function() { - return [ - {content:"Add Node", is_menu: true, callback: LGraphCanvas.onMenuAdd } - //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } - ]; + var options = null; + if(this.getMenuOptions) + options = this.getMenuOptions(); + else + { + options = [ + {content:"Add Node", is_menu: true, callback: LGraphCanvas.onMenuAdd } + //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } + ]; + + if(this._graph_stack) + options = [{content:"Close subgraph", callback: this.closeSubgraph.bind(this) },null].concat(options); + } + + if(this.getExtraMenuOptions) + { + var extra = this.getExtraMenuOptions(this); + extra.push(null); + options = extra.concat( options ); + } + + return options; } LGraphCanvas.prototype.getNodeMenuOptions = function(node) { - var options = [ - {content:"Inputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeInputs }, - {content:"Outputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeOutputs }, - null, - {content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse }, - {content:"Pin", callback: LGraphCanvas.onMenuNodePin }, - {content:"Colors", is_menu: true, callback: LGraphCanvas.onMenuNodeColors }, - {content:"Shapes", is_menu: true, callback: LGraphCanvas.onMenuNodeShapes }, - null, - {content:"Clone", callback: LGraphCanvas.onMenuNodeClone }, - null, - {content:"Remove", callback: LGraphCanvas.onMenuNodeRemove } - ]; + var options = null; - if( node.clonable == false ) - options[7].disabled = true; - if( node.removable == false ) - options[9].disabled = true; + if(node.getMenuOptions) + options = node.getMenuOptions(this); + else + options = [ + {content:"Inputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeInputs }, + {content:"Outputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeOutputs }, + null, + {content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse }, + {content:"Pin", callback: LGraphCanvas.onMenuNodePin }, + {content:"Colors", is_menu: true, callback: LGraphCanvas.onMenuNodeColors }, + {content:"Shapes", is_menu: true, callback: LGraphCanvas.onMenuNodeShapes }, + null + ]; + + if(node.getExtraMenuOptions) + { + var extra = node.getExtraMenuOptions(this); + extra.push(null); + options = extra.concat( options ); + } + + if( node.clonable !== false ) + options.push({content:"Clone", callback: LGraphCanvas.onMenuNodeClone }); + if( node.removable !== false ) + options.push(null,{content:"Remove", callback: LGraphCanvas.onMenuNodeRemove }); if(node.onGetInputs) { diff --git a/src/litegraph.js b/src/litegraph.js index 02083227c..bd2da5e2f 100644 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -285,7 +285,7 @@ LGraph.prototype.clear = function() this.global_inputs = {}; this.global_outputs = {}; - this.graph = {}; + //this.graph = {}; this.debug = true; this.change(); @@ -760,10 +760,18 @@ LGraph.prototype.getNodeOnPos = function(x,y, nodes_list) return null; } +// ********** GLOBALS ***************** + //Tell this graph has a global input of this type LGraph.prototype.addGlobalInput = function(name, type, value) { - this.global_inputs[name] = { type: type, value: value }; + this.global_inputs[name] = { name: name, type: type, value: value }; + + if(this.onGlobalInputAdded) + this.onGlobalInputAdded(name, type); + + if(this.onGlobalsChange) + this.onGlobalsChange(); } //assign a data to the global input @@ -775,29 +783,117 @@ LGraph.prototype.setGlobalInputData = function(name, data) input.value = data; } +//assign a data to the global input +LGraph.prototype.getGlobalInputData = function(name) +{ + var input = this.global_inputs[name]; + if (!input) + return null; + return input.value; +} + //rename the global input LGraph.prototype.renameGlobalInput = function(old_name, name, data) { + if(!this.global_inputs[old_name]) + return false; + + if(this.global_inputs[name]) + { + console.error("there is already one input with that name"); + return false; + } + + this.global_inputs[name] = this.global_inputs[old_name]; + delete this.global_inputs[old_name]; + + if(this.onGlobalInputRenamed) + this.onGlobalInputRenamed(old_name, name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); +} + +LGraph.prototype.removeGlobalInput = function(name) +{ + if(!this.global_inputs[name]) + return false; + + delete this.global_inputs[name]; + + if(this.onGlobalInputRemoved) + this.onGlobalInputRemoved(name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); + return true; } LGraph.prototype.addGlobalOutput = function(name, type, value) { - this.global_outputs[name] = { type: type, value: value }; + this.global_outputs[name] = { name: name, type: type, value: value }; + + if(this.onGlobalOutputAdded) + this.onGlobalOutputAdded(name, type); + + if(this.onGlobalsChange) + this.onGlobalsChange(); } //assign a data to the global output -LGraph.prototype.setGlobalOutputData = function(name, data) +LGraph.prototype.setGlobalOutputData = function(name, value) { var output = this.global_outputs[ name ]; if (!output) return; - output.value = data; + output.value = value; } +//assign a data to the global input +LGraph.prototype.getGlobalOutputData = function(name) +{ + var output = this.global_outputs[name]; + if (!output) + return null; + return output.value; +} + + //rename the global output LGraph.prototype.renameGlobalOutput = function(old_name, name, data) { + if(!this.global_outputs[old_name]) + return false; + + if(this.global_outputs[name]) + { + console.error("there is already one output with that name"); + return false; + } + + this.global_outputs[name] = this.global_outputs[old_name]; + delete this.global_outputs[old_name]; + + if(this.onGlobalOutputRenamed) + this.onGlobalOutputRenamed(old_name, name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); +} + +LGraph.prototype.removeGlobalOutput = function(name) +{ + if(!this.global_outputs[name]) + return false; + delete this.global_outputs[name]; + + if(this.onGlobalOutputRemoved) + this.onGlobalOutputRemoved(name); + + if(this.onGlobalsChange) + this.onGlobalsChange(); + return true; } @@ -903,7 +999,7 @@ LGraph.prototype.serialize = function() var data = { - graph: this.graph, +// graph: this.graph, iteration: this.iteration, frame: this.frame, @@ -1039,7 +1135,12 @@ LGraphNode.prototype.configure = function(info) if(info[j] == null) continue; else if (typeof(info[j]) == 'object') //object - this[j] = LiteGraph.cloneObject(info[j], this[j]); + { + if(this[j] && this[j].configure) + this[j].configure( info[j] ); + else + this[j] = LiteGraph.cloneObject(info[j], this[j]); + } else //value this[j] = info[j]; } @@ -1112,6 +1213,36 @@ LGraphNode.prototype.serialize = function() return o; } + +/* Creates a clone of this node */ +LGraphNode.prototype.clone = function() +{ + var node = LiteGraph.createNode(this.type); + + var data = this.serialize(); + delete data["id"]; + node.configure(data); + + /* + node.size = this.size.concat(); + if(this.inputs) + for(var i = 0, l = this.inputs.length; i < l; ++i) + { + if(node.findInputSlot( this.inputs[i].name ) == -1) + node.addInput( this.inputs[i].name, this.inputs[i].type ); + } + + if(this.outputs) + for(var i = 0, l = this.outputs.length; i < l; ++i) + { + if(node.findOutputSlot( this.outputs[i].name ) == -1) + node.addOutput( this.outputs[i].name, this.outputs[i].type ); + } + */ + + return node; +} + //reduced version of objectivize: NOT FINISHED /* LGraphNode.prototype.reducedObjectivize = function() @@ -1290,6 +1421,8 @@ LGraphNode.prototype.addOutput = function(name,type,extra_info) if(!this.outputs) this.outputs = []; this.outputs.push(o); + if(this.onOutputAdded) + this.onOutputAdded(o); this.size = this.computeSize(); } @@ -1311,6 +1444,8 @@ LGraphNode.prototype.addOutputs = function(array) if(!this.outputs) this.outputs = []; this.outputs.push(o); + if(this.onOutputAdded) + this.onOutputAdded(o); } this.size = this.computeSize(); @@ -1326,6 +1461,8 @@ LGraphNode.prototype.removeOutput = function(slot) this.disconnectOutput(slot); this.outputs.splice(slot,1); this.size = this.computeSize(); + if(this.onOutputRemoved) + this.onOutputRemoved(slot); } /** @@ -1345,6 +1482,8 @@ LGraphNode.prototype.addInput = function(name,type,extra_info) if(!this.inputs) this.inputs = []; this.inputs.push(o); this.size = this.computeSize(); + if(this.onInputAdded) + this.onInputAdded(o); } /** @@ -1365,6 +1504,8 @@ LGraphNode.prototype.addInputs = function(array) if(!this.inputs) this.inputs = []; this.inputs.push(o); + if(this.onInputAdded) + this.onInputAdded(o); } this.size = this.computeSize(); @@ -1380,6 +1521,8 @@ LGraphNode.prototype.removeInput = function(slot) this.disconnectInput(slot); this.inputs.splice(slot,1); this.size = this.computeSize(); + if(this.onInputRemoved) + this.onInputRemoved(slot); } /** @@ -1722,29 +1865,6 @@ LGraphNode.prototype.alignToGrid = function() this.pos[1] = LiteGraph.CANVAS_GRID_SIZE * Math.round(this.pos[1] / LiteGraph.CANVAS_GRID_SIZE); } -/* Creates a clone of this node */ -LGraphNode.prototype.clone = function() -{ - var node = LiteGraph.createNode(this.type); - - node.size = this.size.concat(); - if(this.inputs) - for(var i = 0, l = this.inputs.length; i < l; ++i) - { - if(node.findInputSlot( this.inputs[i].name ) == -1) - node.addInput( this.inputs[i].name, this.inputs[i].type ); - } - - if(this.outputs) - for(var i = 0, l = this.outputs.length; i < l; ++i) - { - if(node.findOutputSlot( this.outputs[i].name ) == -1) - node.addOutput( this.outputs[i].name, this.outputs[i].type ); - } - - - return node; -} /* Console output */ LGraphNode.prototype.trace = function(msg) @@ -1967,7 +2087,7 @@ LGraphCanvas.prototype.clear = function() * assigns a graph, you can reasign graphs to the same canvas * * @method setGraph -* @param {LGraph} assigns a graph +* @param {LGraph} graph */ LGraphCanvas.prototype.setGraph = function(graph) { @@ -1991,6 +2111,48 @@ LGraphCanvas.prototype.setGraph = function(graph) this.setDirty(true,true); } +/** +* opens a graph contained inside a node in the current graph +* +* @method openSubgraph +* @param {LGraph} graph +*/ +LGraphCanvas.prototype.openSubgraph = function(graph) +{ + if(!graph) + throw("graph cannot be null"); + + if(this.graph == graph) + throw("graph cannot be the same"); + + this.clear(); + + if(this.graph) + { + if(!this._graph_stack) + this._graph_stack = []; + this._graph_stack.push(this.graph); + } + + graph.attachCanvas(this); + this.setDirty(true,true); +} + +/** +* closes a subgraph contained inside a node +* +* @method closeSubgraph +* @param {LGraph} assigns a graph +*/ +LGraphCanvas.prototype.closeSubgraph = function() +{ + if(!this._graph_stack || this._graph_stack.length == 0) + return; + var graph = this._graph_stack.pop(); + graph.attachCanvas(this); + this.setDirty(true,true); +} + /** * assigns a canvas * @@ -3894,32 +4056,59 @@ LGraphCanvas.node_colors = { LGraphCanvas.prototype.getCanvasMenuOptions = function() { - return [ - {content:"Add Node", is_menu: true, callback: LGraphCanvas.onMenuAdd } - //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } - ]; + var options = null; + if(this.getMenuOptions) + options = this.getMenuOptions(); + else + { + options = [ + {content:"Add Node", is_menu: true, callback: LGraphCanvas.onMenuAdd } + //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } + ]; + + if(this._graph_stack) + options = [{content:"Close subgraph", callback: this.closeSubgraph.bind(this) },null].concat(options); + } + + if(this.getExtraMenuOptions) + { + var extra = this.getExtraMenuOptions(this); + extra.push(null); + options = extra.concat( options ); + } + + return options; } LGraphCanvas.prototype.getNodeMenuOptions = function(node) { - var options = [ - {content:"Inputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeInputs }, - {content:"Outputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeOutputs }, - null, - {content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse }, - {content:"Pin", callback: LGraphCanvas.onMenuNodePin }, - {content:"Colors", is_menu: true, callback: LGraphCanvas.onMenuNodeColors }, - {content:"Shapes", is_menu: true, callback: LGraphCanvas.onMenuNodeShapes }, - null, - {content:"Clone", callback: LGraphCanvas.onMenuNodeClone }, - null, - {content:"Remove", callback: LGraphCanvas.onMenuNodeRemove } - ]; + var options = null; - if( node.clonable == false ) - options[7].disabled = true; - if( node.removable == false ) - options[9].disabled = true; + if(node.getMenuOptions) + options = node.getMenuOptions(this); + else + options = [ + {content:"Inputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeInputs }, + {content:"Outputs", is_menu: true, disabled:true, callback: LGraphCanvas.onMenuNodeOutputs }, + null, + {content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse }, + {content:"Pin", callback: LGraphCanvas.onMenuNodePin }, + {content:"Colors", is_menu: true, callback: LGraphCanvas.onMenuNodeColors }, + {content:"Shapes", is_menu: true, callback: LGraphCanvas.onMenuNodeShapes }, + null + ]; + + if(node.getExtraMenuOptions) + { + var extra = node.getExtraMenuOptions(this); + extra.push(null); + options = extra.concat( options ); + } + + if( node.clonable !== false ) + options.push({content:"Clone", callback: LGraphCanvas.onMenuNodeClone }); + if( node.removable !== false ) + options.push(null,{content:"Remove", callback: LGraphCanvas.onMenuNodeRemove }); if(node.onGetInputs) { diff --git a/src/nodes/base.js b/src/nodes/base.js index 49181b5b4..f6104c0b2 100644 --- a/src/nodes/base.js +++ b/src/nodes/base.js @@ -5,15 +5,32 @@ //Input for a subgraph function GlobalInput() { + this.title = "Input"; + + //random name to avoid problems with other outputs when added + var genname = "input_" + (Math.random()*1000).toFixed(); + this.properties = { name: genname, type: "number" }; this.addOutput("value",0); } +GlobalInput.title = "Input"; +GlobalInput.desc = "Input of the graph"; + +GlobalInput.prototype.onAdded = function() +{ + this.graph.addGlobalInput( this.properties.name, this.properties.type ); +} + GlobalInput.prototype.onExecute = function() { - var name = this.title; - //read input - var value = node.graph.global_inputs[name]; - this.setOutputData(0,value); + var name = this.properties.name; + + //read from global input + var data = this.graph.global_inputs[name]; + if(!data) return; + + //put through output + this.setOutputData(0,data.value); } LiteGraph.registerNodeType("graph/input", GlobalInput); @@ -25,11 +42,14 @@ function GlobalOutput() this.title = "Output"; //random name to avoid problems with other outputs when added - var genname = "input_" + (Math.random()*1000).toFixed(); + var genname = "output_" + (Math.random()*1000).toFixed(); this.properties = { name: genname, type: "number" }; this.addInput("value","number"); } +GlobalOutput.title = "Ouput"; +GlobalOutput.desc = "Output of the graph"; + GlobalOutput.prototype.onAdded = function() { var name = this.graph.addGlobalOutput( this.properties.name, this.properties.type ); @@ -37,8 +57,7 @@ GlobalOutput.prototype.onAdded = function() GlobalOutput.prototype.onExecute = function() { - var value = this.getInputData(0); - this.graph.setGlobalOutputData( this.properties.name, value ); + this.graph.setGlobalOutputData( this.properties.name, this.getInputData(0) ); } LiteGraph.registerNodeType("graph/output", GlobalOutput); @@ -47,29 +66,77 @@ LiteGraph.registerNodeType("graph/output", GlobalOutput); //Subgraph: a node that contains a graph function Subgraph() { + var that = this; this.subgraph = new LGraph(); + this.subgraph._subgraph_node = this; + this.subgraph._is_subgraph = true; + this.subgraph.onGlobalInputAdded = this.onSubgraphNewGlobalInput.bind(this); + this.subgraph.onGlobalOutputAdded = this.onSubgraphNewGlobalOutput.bind(this); + this.bgcolor = "#FA3"; } +Subgraph.title = "Subgraph"; +Subgraph.desc = "Graph inside a node"; + +Subgraph.prototype.onSubgraphNewGlobalInput = function(name, type) +{ + this.addInput(name, type); +} + +Subgraph.prototype.onSubgraphNewGlobalOutput = function(name, type) +{ + this.addOutput(name, type); +} + +Subgraph.prototype.getExtraMenuOptions = function(graphcanvas) +{ + var that = this; + return [ {content:"Open", callback: + function() { + graphcanvas.openSubgraph( that.subgraph ); + } + }]; +} + Subgraph.prototype.onExecute = function() { //send inputs to subgraph global inputs - for(var i in this.inputs) - { - var input = this.inputs[i]; + if(this.inputs) + for(var i = 0; i < this.inputs.length; i++) + { + var input = this.inputs[i]; + var value = this.getInputData(i); + this.subgraph.setGlobalInputData( input.name, value ); + } - //this.subgraph.setGlobalInputData( input.name, input.value ); - } + //execute + this.subgraph.runStep(); //send subgraph global outputs to outputs + if(this.outputs) + for(var i = 0; i < this.outputs.length; i++) + { + var output = this.outputs[i]; + var value = this.subgraph.getGlobalOutputData( output.name ); + this.setOutputData(i, value); + } } Subgraph.prototype.configure = function(o) { - LGraph.prototype.configure.call(this, o); - //after configure, ... + LGraphNode.prototype.configure.call(this, o); + //this.subgraph.configure(o.graph); } +Subgraph.prototype.serialize = function() +{ + var data = LGraphNode.prototype.serialize.call(this); + data.subgraph = this.subgraph.serialize(); + return data; +} + + LiteGraph.registerNodeType("graph/subgraph", Subgraph); diff --git a/src/nodes/interface.js b/src/nodes/interface.js index 623c6d09c..1fe0a6e79 100644 --- a/src/nodes/interface.js +++ b/src/nodes/interface.js @@ -3,8 +3,8 @@ function WidgetKnob() { - this.size = [64,84]; this.addOutput("",'number'); + this.size = [64,84]; this.properties = {min:0,max:1,value:0.5,wcolor:"#7AF",size:50}; } @@ -42,12 +42,14 @@ ctx.restore(); - ctx.font = "bold 16px Criticized,Tahoma"; - ctx.fillStyle="rgba(100,100,100,0.8)"; - ctx.textAlign = "center"; - - ctx.fillText(this.name.toUpperCase(), this.size[0] * 0.5, 18 ); - ctx.textAlign = "left"; + if(this.title) + { + ctx.font = "bold 16px Criticized,Tahoma"; + ctx.fillStyle="rgba(100,100,100,0.8)"; + ctx.textAlign = "center"; + ctx.fillText(this.title.toUpperCase(), this.size[0] * 0.5, 18 ); + ctx.textAlign = "left"; + } } WidgetKnob.prototype.onDrawVectorKnob = function(ctx) diff --git a/src/nodes/math.js b/src/nodes/math.js index 6d45045e9..091a5ca4f 100644 --- a/src/nodes/math.js +++ b/src/nodes/math.js @@ -41,6 +41,7 @@ function MathClamp() MathClamp.title = "Clamp"; MathClamp.desc = "Clamp number between min and max"; +MathClamp.filter = "shader"; MathClamp.prototype.onExecute = function() { @@ -51,6 +52,14 @@ MathClamp.prototype.onExecute = function() this.setOutputData(0, v ); } +MathClamp.prototype.getCode = function(lang) +{ + var code = ""; + if(this.isInputConnected(0)) + code += "clamp({{0}}," + this.properties.min + "," + this.properties.max + ")"; + return code; +} + LiteGraph.registerNodeType("math/clamp", MathClamp ); @@ -90,7 +99,7 @@ MathFloor.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; - this.setOutputData(0, v|1 ); + this.setOutputData(0, Math.floor(v) ); } LiteGraph.registerNodeType("math/floor", MathFloor ); @@ -284,6 +293,7 @@ function MathTrigonometry() MathTrigonometry.title = "Trigonometry"; MathTrigonometry.desc = "Sin Cos Tan"; +MathTrigonometry.filter = "shader"; MathTrigonometry.prototype.onExecute = function() {