//basic nodes (function(global){ var LiteGraph = global.LiteGraph; //Constant function Time() { this.addOutput("in ms","number"); this.addOutput("in sec","number"); } Time.title = "Time"; Time.desc = "Time"; Time.prototype.onExecute = function() { this.setOutputData(0, this.graph.globaltime * 1000 ); this.setOutputData(1, this.graph.globaltime ); } LiteGraph.registerNodeType("basic/time", Time); //Subgraph: a node that contains a graph function Subgraph() { var that = this; this.size = [120,60]; //create inner graph this.subgraph = new LGraph(); this.subgraph._subgraph_node = this; this.subgraph._is_subgraph = true; this.subgraph.onGlobalInputAdded = this.onSubgraphNewGlobalInput.bind(this); this.subgraph.onGlobalInputRenamed = this.onSubgraphRenamedGlobalInput.bind(this); this.subgraph.onGlobalInputTypeChanged = this.onSubgraphTypeChangeGlobalInput.bind(this); this.subgraph.onGlobalOutputAdded = this.onSubgraphNewGlobalOutput.bind(this); this.subgraph.onGlobalOutputRenamed = this.onSubgraphRenamedGlobalOutput.bind(this); this.subgraph.onGlobalOutputTypeChanged = this.onSubgraphTypeChangeGlobalOutput.bind(this); this.bgcolor = "#663"; } Subgraph.title = "Subgraph"; Subgraph.desc = "Graph inside a node"; Subgraph.prototype.onSubgraphNewGlobalInput = function(name, type) { //add input to the node this.addInput(name, type); } Subgraph.prototype.onSubgraphRenamedGlobalInput = function(oldname, name) { var slot = this.findInputSlot( oldname ); if(slot == -1) return; var info = this.getInputInfo(slot); info.name = name; } Subgraph.prototype.onSubgraphTypeChangeGlobalInput = function(name, type) { var slot = this.findInputSlot( name ); if(slot == -1) return; var info = this.getInputInfo(slot); info.type = type; } Subgraph.prototype.onSubgraphNewGlobalOutput = function(name, type) { //add output to the node this.addOutput(name, type); } Subgraph.prototype.onSubgraphRenamedGlobalOutput = function(oldname, name) { var slot = this.findOutputSlot( oldname ); if(slot == -1) return; var info = this.getOutputInfo(slot); info.name = name; } Subgraph.prototype.onSubgraphTypeChangeGlobalOutput = function(name, type) { var slot = this.findOutputSlot( name ); if(slot == -1) return; var info = this.getOutputInfo(slot); info.type = 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 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 ); } //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) { 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; } Subgraph.prototype.clone = function() { var node = LiteGraph.createNode(this.type); var data = this.serialize(); delete data["id"]; delete data["inputs"]; delete data["outputs"]; node.configure(data); return node; } LiteGraph.registerNodeType("graph/subgraph", Subgraph ); //Input for a subgraph function GlobalInput() { //random name to avoid problems with other outputs when added var input_name = "input_" + (Math.random()*1000).toFixed(); this.addOutput(input_name, null ); this.properties = { name: input_name, type: null }; var that = this; Object.defineProperty( this.properties, "name", { get: function() { return input_name; }, set: function(v) { if(v == "") return; var info = that.getOutputInfo(0); if(info.name == v) return; info.name = v; if(that.graph) that.graph.renameGlobalInput(input_name, v); input_name = v; }, enumerable: true }); Object.defineProperty( this.properties, "type", { get: function() { return that.outputs[0].type; }, set: function(v) { that.outputs[0].type = v; if(that.graph) that.graph.changeGlobalInputType(input_name, that.outputs[0].type); }, enumerable: true }); } GlobalInput.title = "Input"; GlobalInput.desc = "Input of the graph"; //When added to graph tell the graph this is a new global input GlobalInput.prototype.onAdded = function() { this.graph.addGlobalInput( this.properties.name, this.properties.type ); } GlobalInput.prototype.onExecute = function() { 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); //Output for a subgraph function GlobalOutput() { //random name to avoid problems with other outputs when added var output_name = "output_" + (Math.random()*1000).toFixed(); this.addInput(output_name, null); this.properties = {name: output_name, type: null }; var that = this; Object.defineProperty(this.properties, "name", { get: function() { return output_name; }, set: function(v) { if(v == "") return; var info = that.getInputInfo(0); if(info.name == v) return; info.name = v; if(that.graph) that.graph.renameGlobalOutput(output_name, v); output_name = v; }, enumerable: true }); Object.defineProperty(this.properties, "type", { get: function() { return that.inputs[0].type; }, set: function(v) { that.inputs[0].type = v; if(that.graph) that.graph.changeGlobalInputType( output_name, that.inputs[0].type ); }, enumerable: true }); } GlobalOutput.title = "Ouput"; GlobalOutput.desc = "Output of the graph"; GlobalOutput.prototype.onAdded = function() { var name = this.graph.addGlobalOutput( this.properties.name, this.properties.type ); } GlobalOutput.prototype.onExecute = function() { this.graph.setGlobalOutputData( this.properties.name, this.getInputData(0) ); } LiteGraph.registerNodeType("graph/output", GlobalOutput); //Constant function Constant() { this.addOutput("value","number"); this.addProperty( "value", 1.0 ); this.editable = { property:"value", type:"number" }; } Constant.title = "Const"; Constant.desc = "Constant value"; Constant.prototype.setValue = function(v) { if( typeof(v) == "string") v = parseFloat(v); this.properties["value"] = v; this.setDirtyCanvas(true); }; Constant.prototype.onExecute = function() { this.setOutputData(0, parseFloat( this.properties["value"] ) ); } Constant.prototype.onDrawBackground = function(ctx) { //show the current value this.outputs[0].label = this.properties["value"].toFixed(3); } Constant.prototype.onWidget = function(e,widget) { if(widget.name == "value") this.setValue(widget.value); } LiteGraph.registerNodeType("basic/const", Constant); //Watch a value in the editor function Watch() { this.size = [60,20]; this.addInput("value",0,{label:""}); this.addOutput("value",0,{label:""}); this.addProperty( "value", "" ); } Watch.title = "Watch"; Watch.desc = "Show value of input"; Watch.prototype.onExecute = function() { this.properties.value = this.getInputData(0); this.setOutputData(0, this.properties.value); } Watch.prototype.onDrawBackground = function(ctx) { //show the current value if(this.inputs[0] && this.properties["value"] != null) { if (this.properties["value"].constructor === Number ) this.inputs[0].label = this.properties["value"].toFixed(3); else { var str = this.properties["value"]; if(str && str.length) //convert typed to array str = Array.prototype.slice.call(str).join(","); this.inputs[0].label = str; } } } LiteGraph.registerNodeType("basic/watch", Watch); //Show value inside the debug console function Console() { this.mode = LiteGraph.ON_EVENT; this.size = [60,20]; this.addProperty( "msg", "" ); this.addInput("log", LiteGraph.EVENT); this.addInput("msg",0); } Console.title = "Console"; Console.desc = "Show value inside the console"; Console.prototype.onAction = function(action, param) { if(action == "log") console.log( param ); else if(action == "warn") console.warn( param ); else if(action == "error") console.error( param ); } Console.prototype.onExecute = function() { var msg = this.getInputData(1); if(msg !== null) this.properties.msg = msg; console.log(msg); } Console.prototype.onGetInputs = function() { return [["log",LiteGraph.ACTION],["warn",LiteGraph.ACTION],["error",LiteGraph.ACTION]]; } LiteGraph.registerNodeType("basic/console", Console ); //Show value inside the debug console function NodeScript() { this.size = [60,20]; this.addProperty( "onExecute", "" ); this.addInput("in", ""); this.addInput("in2", ""); this.addOutput("out", ""); this.addOutput("out2", ""); this._func = null; } NodeScript.title = "Script"; NodeScript.desc = "executes a code"; NodeScript.widgets_info = { "onExecute": { type:"code" } }; NodeScript.prototype.onPropertyChanged = function(name,value) { if(name == "onExecute" && LiteGraph.allow_scripts ) { this._func = null; try { this._func = new Function( value ); } catch (err) { console.error("Error parsing script"); console.error(err); } } } NodeScript.prototype.onExecute = function() { if(!this._func) return; try { this._func.call(this); } catch (err) { console.error("Error in script"); console.error(err); } } LiteGraph.registerNodeType("basic/script", NodeScript ); })(this);