From 46639c0d77143d66e6ee11a789ba1cf55787bb1c Mon Sep 17 00:00:00 2001 From: daine Date: Thu, 26 Apr 2018 12:42:08 +0200 Subject: [PATCH] update build/ --- build/litegraph.js | 4332 +++++++++++++++++++++++--------------------- src/litegraph.js | 4 +- 2 files changed, 2303 insertions(+), 2033 deletions(-) diff --git a/build/litegraph.js b/build/litegraph.js index 6b8e80cce9..4f314d8a07 100644 --- a/build/litegraph.js +++ b/build/litegraph.js @@ -1,3 +1,5 @@ +//packer version + (function(global){ // ************************************************************* // LiteGraph CLASS ******* @@ -2807,6 +2809,12 @@ function LGraphCanvas( canvas, graph, options ) this.title_text_font = "bold 14px Arial"; this.inner_text_font = "normal 12px Arial"; this.default_link_color = "#AAC"; + this.default_connection_color = { + input_off: "#AAC", + input_on: "#7F7", + output_off: "#AAC", + output_on: "#7F7", + }; this.highquality_render = true; this.editor_alpha = 1; //used for transition @@ -2824,6 +2832,7 @@ function LGraphCanvas( canvas, graph, options ) this.dragging_rectangle = null; this.always_render_background = false; + this.render_canvas_border = true; this.render_connections_shadows = false; //too much cpu this.render_connections_border = true; this.render_curved_connections = true; @@ -4537,8 +4546,10 @@ LGraphCanvas.prototype.drawBackCanvas = function() //ctx.fillRect( this.visible_area[0] + 10, this.visible_area[1] + 10, this.visible_area[2] - 20, this.visible_area[3] - 20); //bg - ctx.strokeStyle = "#235"; - ctx.strokeRect(0,0,canvas.width,canvas.height); + if (this.render_canvas_border) { + ctx.strokeStyle = "#235"; + ctx.strokeRect(0,0,canvas.width,canvas.height); + } if(this.render_connections_shadows) { @@ -4690,7 +4701,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if ( this.connecting_node && LiteGraph.isValidConnection( slot.type && out_slot.type ) ) ctx.globalAlpha = 0.4 * editor_alpha; - ctx.fillStyle = slot.link != null ? "#7F7" : "#AAA"; + ctx.fillStyle = slot.link != null ? this.default_connection_color.input_on : this.default_connection_color.input_off; var pos = node.getConnectionPos(true,i); pos[0] -= node.pos[0]; @@ -4734,7 +4745,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) pos[0] -= node.pos[0]; pos[1] -= node.pos[1]; - ctx.fillStyle = slot.links && slot.links.length ? "#7F7" : "#AAA"; + ctx.fillStyle = slot.links && slot.links.length ? this.default_connection_color.output_on : this.default_connection_color.output_off; ctx.beginPath(); //ctx.rect( node.size[0] - 14,i*14,10,10); @@ -6462,489 +6473,489 @@ if( typeof(window) != "undefined" && !window["requestAnimationFrame"] ) if(typeof(exports) != "undefined") exports.LiteGraph = this.LiteGraph; - -//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); - -//Watch a value in the editor -function Pass() -{ - this.addInput("in",0); - this.addOutput("out",0); - this.size = [40,20]; -} - -Pass.title = "Pass"; -Pass.desc = "Allows to connect different types"; - -Pass.prototype.onExecute = function() -{ - this.setOutputData( 0, this.getInputData(0) ); -} - -LiteGraph.registerNodeType("basic/pass", Pass); - - -//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); + +//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); + +//Watch a value in the editor +function Pass() +{ + this.addInput("in",0); + this.addOutput("out",0); + this.size = [40,20]; +} + +Pass.title = "Pass"; +Pass.desc = "Allows to connect different types"; + +Pass.prototype.onExecute = function() +{ + this.setOutputData( 0, this.getInputData(0) ); +} + +LiteGraph.registerNodeType("basic/pass", Pass); + + +//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); //event related nodes (function(global){ var LiteGraph = global.LiteGraph; @@ -7094,787 +7105,787 @@ DelayEvent.prototype.onGetInputs = function() LiteGraph.registerNodeType("events/delay", DelayEvent ); -})(this); -//widgets -(function(global){ -var LiteGraph = global.LiteGraph; - - /* Button ****************/ - - function WidgetButton() - { - this.addOutput( "clicked", LiteGraph.EVENT ); - this.addProperty( "text","" ); - this.addProperty( "font","40px Arial" ); - this.addProperty( "message", "" ); - this.size = [64,84]; - } - - WidgetButton.title = "Button"; - WidgetButton.desc = "Triggers an event"; - - WidgetButton.prototype.onDrawForeground = function(ctx) - { - if(this.flags.collapsed) - return; - - //ctx.font = "40px Arial"; - //ctx.textAlign = "center"; - ctx.fillStyle = "black"; - ctx.fillRect(1,1,this.size[0] - 3, this.size[1] - 3); - ctx.fillStyle = "#AAF"; - ctx.fillRect(0,0,this.size[0] - 3, this.size[1] - 3); - ctx.fillStyle = this.clicked ? "white" : (this.mouseOver ? "#668" : "#334"); - ctx.fillRect(1,1,this.size[0] - 4, this.size[1] - 4); - - if( this.properties.text || this.properties.text === 0 ) - { - ctx.textAlign = "center"; - ctx.fillStyle = this.clicked ? "black" : "white"; - if( this.properties.font ) - ctx.font = this.properties.font; - ctx.fillText(this.properties.text, this.size[0] * 0.5, this.size[1] * 0.85 ); - ctx.textAlign = "left"; - } - } - - WidgetButton.prototype.onMouseDown = function(e, local_pos) - { - if(local_pos[0] > 1 && local_pos[1] > 1 && local_pos[0] < (this.size[0] - 2) && local_pos[1] < (this.size[1] - 2) ) - { - this.clicked = true; - this.trigger( "clicked", this.properties.message ); - return true; - } - } - - WidgetButton.prototype.onMouseUp = function(e) - { - this.clicked = false; - } - - - LiteGraph.registerNodeType("widget/button", WidgetButton ); - - /* Knob ****************/ - - function WidgetKnob() - { - this.addOutput("",'number'); - this.size = [64,84]; - this.properties = {min:0,max:1,value:0.5,wcolor:"#7AF",size:50}; - } - - WidgetKnob.title = "Knob"; - WidgetKnob.desc = "Circular controller"; - WidgetKnob.widgets = [{name:"increase",text:"+",type:"minibutton"},{name:"decrease",text:"-",type:"minibutton"}]; - - - WidgetKnob.prototype.onAdded = function() - { - this.value = (this.properties["value"] - this.properties["min"]) / (this.properties["max"] - this.properties["min"]); - - this.imgbg = this.loadImage("imgs/knob_bg.png"); - this.imgfg = this.loadImage("imgs/knob_fg.png"); - } - - WidgetKnob.prototype.onDrawImageKnob = function(ctx) - { - if(!this.imgfg || !this.imgfg.width) return; - - var d = this.imgbg.width*0.5; - var scale = this.size[0] / this.imgfg.width; - - ctx.save(); - ctx.translate(0,20); - ctx.scale(scale,scale); - ctx.drawImage(this.imgbg,0,0); - //ctx.drawImage(this.imgfg,0,20); - - ctx.translate(d,d); - ctx.rotate(this.value * (Math.PI*2) * 6/8 + Math.PI * 10/8); - //ctx.rotate(this.value * (Math.PI*2)); - ctx.translate(-d,-d); - ctx.drawImage(this.imgfg,0,0); - - ctx.restore(); - - 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) - { - if(!this.imgfg || !this.imgfg.width) return; - - //circle around - ctx.lineWidth = 1; - ctx.strokeStyle= this.mouseOver ? "#FFF" : "#AAA"; - ctx.fillStyle="#000"; - ctx.beginPath(); - ctx.arc(this.size[0] * 0.5,this.size[1] * 0.5 + 10,this.properties.size * 0.5,0,Math.PI*2,true); - ctx.stroke(); - - if(this.value > 0) - { - ctx.strokeStyle=this.properties["wcolor"]; - ctx.lineWidth = (this.properties.size * 0.2); - ctx.beginPath(); - ctx.arc(this.size[0] * 0.5,this.size[1] * 0.5 + 10,this.properties.size * 0.35,Math.PI * -0.5 + Math.PI*2 * this.value,Math.PI * -0.5,true); - ctx.stroke(); - ctx.lineWidth = 1; - } - - ctx.font = (this.properties.size * 0.2) + "px Arial"; - ctx.fillStyle="#AAA"; - ctx.textAlign = "center"; - - var str = this.properties["value"]; - if(typeof(str) == 'number') - str = str.toFixed(2); - - ctx.fillText(str,this.size[0] * 0.5,this.size[1]*0.65); - ctx.textAlign = "left"; - } - - WidgetKnob.prototype.onDrawForeground = function(ctx) - { - this.onDrawImageKnob(ctx); - } - - WidgetKnob.prototype.onExecute = function() - { - this.setOutputData(0, this.properties["value"] ); - - this.boxcolor = LiteGraph.colorToString([this.value,this.value,this.value]); - } - - WidgetKnob.prototype.onMouseDown = function(e) - { - if(!this.imgfg || !this.imgfg.width) return; - - //this.center = [this.imgbg.width * 0.5, this.imgbg.height * 0.5 + 20]; - //this.radius = this.imgbg.width * 0.5; - this.center = [this.size[0] * 0.5, this.size[1] * 0.5 + 20]; - this.radius = this.size[0] * 0.5; - - if(e.canvasY - this.pos[1] < 20 || LiteGraph.distance([e.canvasX,e.canvasY],[this.pos[0] + this.center[0],this.pos[1] + this.center[1]]) > this.radius) - return false; - - this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; - this.captureInput(true); - - /* - var tmp = this.localToScreenSpace(0,0); - this.trace(tmp[0] + "," + tmp[1]); */ - return true; - } - - WidgetKnob.prototype.onMouseMove = function(e) - { - if(!this.oldmouse) return; - - var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; - - var v = this.value; - v -= (m[1] - this.oldmouse[1]) * 0.01; - if(v > 1.0) v = 1.0; - else if(v < 0.0) v = 0.0; - - this.value = v; - this.properties["value"] = this.properties["min"] + (this.properties["max"] - this.properties["min"]) * this.value; - - this.oldmouse = m; - this.setDirtyCanvas(true); - } - - WidgetKnob.prototype.onMouseUp = function(e) - { - if(this.oldmouse) - { - this.oldmouse = null; - this.captureInput(false); - } - } - - WidgetKnob.prototype.onMouseLeave = function(e) - { - //this.oldmouse = null; - } - - WidgetKnob.prototype.onWidget = function(e,widget) - { - if(widget.name=="increase") - this.onPropertyChanged("size", this.properties.size + 10); - else if(widget.name=="decrease") - this.onPropertyChanged("size", this.properties.size - 10); - } - - WidgetKnob.prototype.onPropertyChanged = function(name,value) - { - if(name=="wcolor") - this.properties[name] = value; - else if(name=="size") - { - value = parseInt(value); - this.properties[name] = value; - this.size = [value+4,value+24]; - this.setDirtyCanvas(true,true); - } - else if(name=="min" || name=="max" || name=="value") - { - this.properties[name] = parseFloat(value); - } - else - return false; - return true; - } - - LiteGraph.registerNodeType("widget/knob", WidgetKnob); - - //Widget H SLIDER - function WidgetHSlider() - { - this.size = [160,26]; - this.addOutput("",'number'); - this.properties = {wcolor:"#7AF",min:0,max:1,value:0.5}; - } - - WidgetHSlider.title = "H.Slider"; - WidgetHSlider.desc = "Linear slider controller"; - - WidgetHSlider.prototype.onAdded = function() - { - this.value = 0.5; - this.imgfg = this.loadImage("imgs/slider_fg.png"); - } - - WidgetHSlider.prototype.onDrawVectorial = function(ctx) - { - if(!this.imgfg || !this.imgfg.width) return; - - //border - ctx.lineWidth = 1; - ctx.strokeStyle= this.mouseOver ? "#FFF" : "#AAA"; - ctx.fillStyle="#000"; - ctx.beginPath(); - ctx.rect(2,0,this.size[0]-4,20); - ctx.stroke(); - - ctx.fillStyle=this.properties["wcolor"]; - ctx.beginPath(); - ctx.rect(2+(this.size[0]-4-20)*this.value,0, 20,20); - ctx.fill(); - } - - WidgetHSlider.prototype.onDrawImage = function(ctx) - { - if(!this.imgfg || !this.imgfg.width) - return; - - //border - ctx.lineWidth = 1; - ctx.fillStyle="#000"; - ctx.fillRect(2,9,this.size[0]-4,2); - - ctx.strokeStyle= "#333"; - ctx.beginPath(); - ctx.moveTo(2,9); - ctx.lineTo(this.size[0]-4,9); - ctx.stroke(); - - ctx.strokeStyle= "#AAA"; - ctx.beginPath(); - ctx.moveTo(2,11); - ctx.lineTo(this.size[0]-4,11); - ctx.stroke(); - - ctx.drawImage(this.imgfg, 2+(this.size[0]-4)*this.value - this.imgfg.width*0.5,-this.imgfg.height*0.5 + 10); - }, - - WidgetHSlider.prototype.onDrawForeground = function(ctx) - { - this.onDrawImage(ctx); - } - - WidgetHSlider.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 = LiteGraph.colorToString([this.value,this.value,this.value]); - } - - WidgetHSlider.prototype.onMouseDown = function(e) - { - if(e.canvasY - this.pos[1] < 0) - return false; - - this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; - this.captureInput(true); - return true; - } - - WidgetHSlider.prototype.onMouseMove = function(e) - { - if(!this.oldmouse) return; - - var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; - - var v = this.value; - var delta = (m[0] - this.oldmouse[0]); - v += delta / this.size[0]; - if(v > 1.0) v = 1.0; - else if(v < 0.0) v = 0.0; - - this.value = v; - - this.oldmouse = m; - this.setDirtyCanvas(true); - } - - WidgetHSlider.prototype.onMouseUp = function(e) - { - this.oldmouse = null; - this.captureInput(false); - } - - WidgetHSlider.prototype.onMouseLeave = function(e) - { - //this.oldmouse = null; - } - - WidgetHSlider.prototype.onPropertyChanged = function(name,value) - { - if(name=="wcolor") - this.properties[name] = value; - else - return false; - return true; - } - - LiteGraph.registerNodeType("widget/hslider", WidgetHSlider ); - - - function WidgetProgress() - { - this.size = [160,26]; - this.addInput("",'number'); - this.properties = {min:0,max:1,value:0,wcolor:"#AAF"}; - } - - WidgetProgress.title = "Progress"; - WidgetProgress.desc = "Shows data in linear progress"; - - WidgetProgress.prototype.onExecute = function() - { - var v = this.getInputData(0); - if( v != undefined ) - this.properties["value"] = v; - } - - WidgetProgress.prototype.onDrawForeground = function(ctx) - { - //border - ctx.lineWidth = 1; - ctx.fillStyle=this.properties.wcolor; - var v = (this.properties.value - this.properties.min) / (this.properties.max - this.properties.min); - v = Math.min(1,v); - v = Math.max(0,v); - ctx.fillRect(2,2,(this.size[0]-4)*v,this.size[1]-4); - } - - LiteGraph.registerNodeType("widget/progress", WidgetProgress); - - - /* - LiteGraph.registerNodeType("widget/kpad",{ - title: "KPad", - desc: "bidimensional slider", - size: [200,200], - outputs: [["x",'number'],["y",'number']], - properties:{x:0,y:0,borderColor:"#333",bgcolorTop:"#444",bgcolorBottom:"#000",shadowSize:1, borderRadius:2}, - - createGradient: function(ctx) - { - this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]); - this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]); - this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]); - }, - - onDrawBackground: function(ctx) - { - if(!this.lineargradient) - this.createGradient(ctx); - - ctx.lineWidth = 1; - ctx.strokeStyle = this.properties["borderColor"]; - //ctx.fillStyle = "#ebebeb"; - ctx.fillStyle = this.lineargradient; - - ctx.shadowColor = "#000"; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - ctx.shadowBlur = this.properties["shadowSize"]; - ctx.roundRect(0,0,this.size[0],this.size[1],this.properties["shadowSize"]); - ctx.fill(); - ctx.shadowColor = "rgba(0,0,0,0)"; - ctx.stroke(); - - ctx.fillStyle = "#A00"; - ctx.fillRect(this.size[0] * this.properties["x"] - 5, this.size[1] * this.properties["y"] - 5,10,10); - }, - - onWidget: function(e,widget) - { - if(widget.name == "update") - { - this.lineargradient = null; - this.setDirtyCanvas(true); - } - }, - - onExecute: function() - { - this.setOutputData(0, this.properties["x"] ); - this.setOutputData(1, this.properties["y"] ); - }, - - onMouseDown: function(e) - { - if(e.canvasY - this.pos[1] < 0) - return false; - - this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; - this.captureInput(true); - return true; - }, - - onMouseMove: function(e) - { - if(!this.oldmouse) return; - - var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; - - this.properties.x = m[0] / this.size[0]; - this.properties.y = m[1] / this.size[1]; - - if(this.properties.x > 1.0) this.properties.x = 1.0; - else if(this.properties.x < 0.0) this.properties.x = 0.0; - - if(this.properties.y > 1.0) this.properties.y = 1.0; - else if(this.properties.y < 0.0) this.properties.y = 0.0; - - this.oldmouse = m; - this.setDirtyCanvas(true); - }, - - onMouseUp: function(e) - { - if(this.oldmouse) - { - this.oldmouse = null; - this.captureInput(false); - } - }, - - onMouseLeave: function(e) - { - //this.oldmouse = null; - } - }); - - - - LiteGraph.registerNodeType("widget/button", { - title: "Button", - desc: "A send command button", - - widgets: [{name:"test",text:"Test Button",type:"button"}], - size: [100,40], - properties:{text:"clickme",command:"",color:"#7AF",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",fontsize:"16"}, - outputs:[["M","module"]], - - createGradient: function(ctx) - { - this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]); - this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]); - this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]); - }, - - drawVectorShape: function(ctx) - { - ctx.fillStyle = this.mouseOver ? this.properties["color"] : "#AAA"; - - if(this.clicking) - ctx.fillStyle = "#FFF"; - - ctx.strokeStyle = "#AAA"; - ctx.roundRect(5,5,this.size[0] - 10,this.size[1] - 10,4); - ctx.stroke(); - - if(this.mouseOver) - ctx.fill(); - - //ctx.fillRect(5,20,this.size[0] - 10,this.size[1] - 30); - - ctx.fillStyle = this.mouseOver ? "#000" : "#AAA"; - ctx.font = "bold " + this.properties["fontsize"] + "px Criticized,Tahoma"; - ctx.textAlign = "center"; - ctx.fillText(this.properties["text"],this.size[0]*0.5,this.size[1]*0.5 + 0.5*parseInt(this.properties["fontsize"])); - ctx.textAlign = "left"; - }, - - drawBevelShape: function(ctx) - { - ctx.shadowColor = "#000"; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - ctx.shadowBlur = this.properties["shadowSize"]; - - if(!this.lineargradient) - this.createGradient(ctx); - - ctx.fillStyle = this.mouseOver ? this.properties["color"] : this.lineargradient; - if(this.clicking) - ctx.fillStyle = "#444"; - - ctx.strokeStyle = "#FFF"; - ctx.roundRect(5,5,this.size[0] - 10,this.size[1] - 10,4); - ctx.fill(); - ctx.shadowColor = "rgba(0,0,0,0)"; - ctx.stroke(); - - ctx.fillStyle = this.mouseOver ? "#000" : "#444"; - ctx.font = "bold " + this.properties["fontsize"] + "px Century Gothic"; - ctx.textAlign = "center"; - ctx.fillText(this.properties["text"],this.size[0]*0.5,this.size[1]*0.5 + 0.40*parseInt(this.properties["fontsize"])); - ctx.textAlign = "left"; - }, - - onDrawForeground: function(ctx) - { - this.drawBevelShape(ctx); - }, - - clickButton: function() - { - var module = this.getOutputModule(0); - if(this.properties["command"] && this.properties["command"] != "") - { - if (! module.executeAction(this.properties["command"]) ) - this.trace("Error executing action in other module"); - } - else if(module && module.onTrigger) - { - module.onTrigger(); - } - }, - - onMouseDown: function(e) - { - if(e.canvasY - this.pos[1] < 2) - return false; - this.clickButton(); - this.clicking = true; - return true; - }, - - onMouseUp: function(e) - { - this.clicking = false; - }, - - onExecute: function() - { - }, - - onWidget: function(e,widget) - { - if(widget.name == "test") - { - this.clickButton(); - } - }, - - onPropertyChanged: function(name,value) - { - this.properties[name] = value; - return true; - } - }); - */ - - - function WidgetText() - { - this.addInputs("",0); - this.properties = { value:"...",font:"Arial", fontsize:18, color:"#AAA", align:"left", glowSize:0, decimals:1 }; - } - - WidgetText.title = "Text"; - WidgetText.desc = "Shows the input value"; - WidgetText.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}]; - - WidgetText.prototype.onDrawForeground = function(ctx) - { - //ctx.fillStyle="#000"; - //ctx.fillRect(0,0,100,60); - ctx.fillStyle = this.properties["color"]; - var v = this.properties["value"]; - - if(this.properties["glowSize"]) - { - ctx.shadowColor = this.properties["color"]; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - ctx.shadowBlur = this.properties["glowSize"]; - } - else - ctx.shadowColor = "transparent"; - - var fontsize = this.properties["fontsize"]; - - ctx.textAlign = this.properties["align"]; - ctx.font = fontsize.toString() + "px " + this.properties["font"]; - this.str = typeof(v) == 'number' ? v.toFixed(this.properties["decimals"]) : v; - - if( typeof(this.str) == 'string') - { - var lines = this.str.split("\\n"); - for(var i in lines) - ctx.fillText(lines[i],this.properties["align"] == "left" ? 15 : this.size[0] - 15, fontsize * -0.15 + fontsize * (parseInt(i)+1) ); - } - - ctx.shadowColor = "transparent"; - this.last_ctx = ctx; - ctx.textAlign = "left"; - } - - WidgetText.prototype.onExecute = function() - { - var v = this.getInputData(0); - if(v != null) - this.properties["value"] = v; - //this.setDirtyCanvas(true); - } - - WidgetText.prototype.resize = function() - { - if(!this.last_ctx) return; - - var lines = this.str.split("\\n"); - this.last_ctx.font = this.properties["fontsize"] + "px " + this.properties["font"]; - var max = 0; - for(var i in lines) - { - var w = this.last_ctx.measureText(lines[i]).width; - if(max < w) max = w; - } - this.size[0] = max + 20; - this.size[1] = 4 + lines.length * this.properties["fontsize"]; - - this.setDirtyCanvas(true); - } - - WidgetText.prototype.onWidget = function(e,widget) - { - if(widget.name == "resize") - this.resize(); - else if (widget.name == "led_text") - { - this.properties["font"] = "Digital"; - this.properties["glowSize"] = 4; - this.setDirtyCanvas(true); - } - else if (widget.name == "normal_text") - { - this.properties["font"] = "Arial"; - this.setDirtyCanvas(true); - } - } - - WidgetText.prototype.onPropertyChanged = function(name,value) - { - this.properties[name] = value; - this.str = typeof(value) == 'number' ? value.toFixed(3) : value; - //this.resize(); - return true; - } - - LiteGraph.registerNodeType("widget/text", WidgetText ); - - - function WidgetPanel() - { - this.size = [200,100]; - this.properties = {borderColor:"#ffffff",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",shadowSize:2, borderRadius:3}; - } - - WidgetPanel.title = "Panel"; - WidgetPanel.desc = "Non interactive panel"; - WidgetPanel.widgets = [{name:"update",text:"Update",type:"button"}]; - - - WidgetPanel.prototype.createGradient = function(ctx) - { - if(this.properties["bgcolorTop"] == "" || this.properties["bgcolorBottom"] == "") - { - this.lineargradient = 0; - return; - } - - this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]); - this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]); - this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]); - } - - WidgetPanel.prototype.onDrawForeground = function(ctx) - { - if(this.lineargradient == null) - this.createGradient(ctx); - - if(!this.lineargradient) - return; - - ctx.lineWidth = 1; - ctx.strokeStyle = this.properties["borderColor"]; - //ctx.fillStyle = "#ebebeb"; - ctx.fillStyle = this.lineargradient; - - if(this.properties["shadowSize"]) - { - ctx.shadowColor = "#000"; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - ctx.shadowBlur = this.properties["shadowSize"]; - } - else - ctx.shadowColor = "transparent"; - - ctx.roundRect(0,0,this.size[0]-1,this.size[1]-1,this.properties["shadowSize"]); - ctx.fill(); - ctx.shadowColor = "transparent"; - ctx.stroke(); - } - - WidgetPanel.prototype.onWidget = function(e,widget) - { - if(widget.name == "update") - { - this.lineargradient = null; - this.setDirtyCanvas(true); - } - } - - LiteGraph.registerNodeType("widget/panel", WidgetPanel ); - -})(this); +})(this); +//widgets +(function(global){ +var LiteGraph = global.LiteGraph; + + /* Button ****************/ + + function WidgetButton() + { + this.addOutput( "clicked", LiteGraph.EVENT ); + this.addProperty( "text","" ); + this.addProperty( "font","40px Arial" ); + this.addProperty( "message", "" ); + this.size = [64,84]; + } + + WidgetButton.title = "Button"; + WidgetButton.desc = "Triggers an event"; + + WidgetButton.prototype.onDrawForeground = function(ctx) + { + if(this.flags.collapsed) + return; + + //ctx.font = "40px Arial"; + //ctx.textAlign = "center"; + ctx.fillStyle = "black"; + ctx.fillRect(1,1,this.size[0] - 3, this.size[1] - 3); + ctx.fillStyle = "#AAF"; + ctx.fillRect(0,0,this.size[0] - 3, this.size[1] - 3); + ctx.fillStyle = this.clicked ? "white" : (this.mouseOver ? "#668" : "#334"); + ctx.fillRect(1,1,this.size[0] - 4, this.size[1] - 4); + + if( this.properties.text || this.properties.text === 0 ) + { + ctx.textAlign = "center"; + ctx.fillStyle = this.clicked ? "black" : "white"; + if( this.properties.font ) + ctx.font = this.properties.font; + ctx.fillText(this.properties.text, this.size[0] * 0.5, this.size[1] * 0.85 ); + ctx.textAlign = "left"; + } + } + + WidgetButton.prototype.onMouseDown = function(e, local_pos) + { + if(local_pos[0] > 1 && local_pos[1] > 1 && local_pos[0] < (this.size[0] - 2) && local_pos[1] < (this.size[1] - 2) ) + { + this.clicked = true; + this.trigger( "clicked", this.properties.message ); + return true; + } + } + + WidgetButton.prototype.onMouseUp = function(e) + { + this.clicked = false; + } + + + LiteGraph.registerNodeType("widget/button", WidgetButton ); + + /* Knob ****************/ + + function WidgetKnob() + { + this.addOutput("",'number'); + this.size = [64,84]; + this.properties = {min:0,max:1,value:0.5,wcolor:"#7AF",size:50}; + } + + WidgetKnob.title = "Knob"; + WidgetKnob.desc = "Circular controller"; + WidgetKnob.widgets = [{name:"increase",text:"+",type:"minibutton"},{name:"decrease",text:"-",type:"minibutton"}]; + + + WidgetKnob.prototype.onAdded = function() + { + this.value = (this.properties["value"] - this.properties["min"]) / (this.properties["max"] - this.properties["min"]); + + this.imgbg = this.loadImage("imgs/knob_bg.png"); + this.imgfg = this.loadImage("imgs/knob_fg.png"); + } + + WidgetKnob.prototype.onDrawImageKnob = function(ctx) + { + if(!this.imgfg || !this.imgfg.width) return; + + var d = this.imgbg.width*0.5; + var scale = this.size[0] / this.imgfg.width; + + ctx.save(); + ctx.translate(0,20); + ctx.scale(scale,scale); + ctx.drawImage(this.imgbg,0,0); + //ctx.drawImage(this.imgfg,0,20); + + ctx.translate(d,d); + ctx.rotate(this.value * (Math.PI*2) * 6/8 + Math.PI * 10/8); + //ctx.rotate(this.value * (Math.PI*2)); + ctx.translate(-d,-d); + ctx.drawImage(this.imgfg,0,0); + + ctx.restore(); + + 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) + { + if(!this.imgfg || !this.imgfg.width) return; + + //circle around + ctx.lineWidth = 1; + ctx.strokeStyle= this.mouseOver ? "#FFF" : "#AAA"; + ctx.fillStyle="#000"; + ctx.beginPath(); + ctx.arc(this.size[0] * 0.5,this.size[1] * 0.5 + 10,this.properties.size * 0.5,0,Math.PI*2,true); + ctx.stroke(); + + if(this.value > 0) + { + ctx.strokeStyle=this.properties["wcolor"]; + ctx.lineWidth = (this.properties.size * 0.2); + ctx.beginPath(); + ctx.arc(this.size[0] * 0.5,this.size[1] * 0.5 + 10,this.properties.size * 0.35,Math.PI * -0.5 + Math.PI*2 * this.value,Math.PI * -0.5,true); + ctx.stroke(); + ctx.lineWidth = 1; + } + + ctx.font = (this.properties.size * 0.2) + "px Arial"; + ctx.fillStyle="#AAA"; + ctx.textAlign = "center"; + + var str = this.properties["value"]; + if(typeof(str) == 'number') + str = str.toFixed(2); + + ctx.fillText(str,this.size[0] * 0.5,this.size[1]*0.65); + ctx.textAlign = "left"; + } + + WidgetKnob.prototype.onDrawForeground = function(ctx) + { + this.onDrawImageKnob(ctx); + } + + WidgetKnob.prototype.onExecute = function() + { + this.setOutputData(0, this.properties["value"] ); + + this.boxcolor = LiteGraph.colorToString([this.value,this.value,this.value]); + } + + WidgetKnob.prototype.onMouseDown = function(e) + { + if(!this.imgfg || !this.imgfg.width) return; + + //this.center = [this.imgbg.width * 0.5, this.imgbg.height * 0.5 + 20]; + //this.radius = this.imgbg.width * 0.5; + this.center = [this.size[0] * 0.5, this.size[1] * 0.5 + 20]; + this.radius = this.size[0] * 0.5; + + if(e.canvasY - this.pos[1] < 20 || LiteGraph.distance([e.canvasX,e.canvasY],[this.pos[0] + this.center[0],this.pos[1] + this.center[1]]) > this.radius) + return false; + + this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; + this.captureInput(true); + + /* + var tmp = this.localToScreenSpace(0,0); + this.trace(tmp[0] + "," + tmp[1]); */ + return true; + } + + WidgetKnob.prototype.onMouseMove = function(e) + { + if(!this.oldmouse) return; + + var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; + + var v = this.value; + v -= (m[1] - this.oldmouse[1]) * 0.01; + if(v > 1.0) v = 1.0; + else if(v < 0.0) v = 0.0; + + this.value = v; + this.properties["value"] = this.properties["min"] + (this.properties["max"] - this.properties["min"]) * this.value; + + this.oldmouse = m; + this.setDirtyCanvas(true); + } + + WidgetKnob.prototype.onMouseUp = function(e) + { + if(this.oldmouse) + { + this.oldmouse = null; + this.captureInput(false); + } + } + + WidgetKnob.prototype.onMouseLeave = function(e) + { + //this.oldmouse = null; + } + + WidgetKnob.prototype.onWidget = function(e,widget) + { + if(widget.name=="increase") + this.onPropertyChanged("size", this.properties.size + 10); + else if(widget.name=="decrease") + this.onPropertyChanged("size", this.properties.size - 10); + } + + WidgetKnob.prototype.onPropertyChanged = function(name,value) + { + if(name=="wcolor") + this.properties[name] = value; + else if(name=="size") + { + value = parseInt(value); + this.properties[name] = value; + this.size = [value+4,value+24]; + this.setDirtyCanvas(true,true); + } + else if(name=="min" || name=="max" || name=="value") + { + this.properties[name] = parseFloat(value); + } + else + return false; + return true; + } + + LiteGraph.registerNodeType("widget/knob", WidgetKnob); + + //Widget H SLIDER + function WidgetHSlider() + { + this.size = [160,26]; + this.addOutput("",'number'); + this.properties = {wcolor:"#7AF",min:0,max:1,value:0.5}; + } + + WidgetHSlider.title = "H.Slider"; + WidgetHSlider.desc = "Linear slider controller"; + + WidgetHSlider.prototype.onAdded = function() + { + this.value = 0.5; + this.imgfg = this.loadImage("imgs/slider_fg.png"); + } + + WidgetHSlider.prototype.onDrawVectorial = function(ctx) + { + if(!this.imgfg || !this.imgfg.width) return; + + //border + ctx.lineWidth = 1; + ctx.strokeStyle= this.mouseOver ? "#FFF" : "#AAA"; + ctx.fillStyle="#000"; + ctx.beginPath(); + ctx.rect(2,0,this.size[0]-4,20); + ctx.stroke(); + + ctx.fillStyle=this.properties["wcolor"]; + ctx.beginPath(); + ctx.rect(2+(this.size[0]-4-20)*this.value,0, 20,20); + ctx.fill(); + } + + WidgetHSlider.prototype.onDrawImage = function(ctx) + { + if(!this.imgfg || !this.imgfg.width) + return; + + //border + ctx.lineWidth = 1; + ctx.fillStyle="#000"; + ctx.fillRect(2,9,this.size[0]-4,2); + + ctx.strokeStyle= "#333"; + ctx.beginPath(); + ctx.moveTo(2,9); + ctx.lineTo(this.size[0]-4,9); + ctx.stroke(); + + ctx.strokeStyle= "#AAA"; + ctx.beginPath(); + ctx.moveTo(2,11); + ctx.lineTo(this.size[0]-4,11); + ctx.stroke(); + + ctx.drawImage(this.imgfg, 2+(this.size[0]-4)*this.value - this.imgfg.width*0.5,-this.imgfg.height*0.5 + 10); + }, + + WidgetHSlider.prototype.onDrawForeground = function(ctx) + { + this.onDrawImage(ctx); + } + + WidgetHSlider.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 = LiteGraph.colorToString([this.value,this.value,this.value]); + } + + WidgetHSlider.prototype.onMouseDown = function(e) + { + if(e.canvasY - this.pos[1] < 0) + return false; + + this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; + this.captureInput(true); + return true; + } + + WidgetHSlider.prototype.onMouseMove = function(e) + { + if(!this.oldmouse) return; + + var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; + + var v = this.value; + var delta = (m[0] - this.oldmouse[0]); + v += delta / this.size[0]; + if(v > 1.0) v = 1.0; + else if(v < 0.0) v = 0.0; + + this.value = v; + + this.oldmouse = m; + this.setDirtyCanvas(true); + } + + WidgetHSlider.prototype.onMouseUp = function(e) + { + this.oldmouse = null; + this.captureInput(false); + } + + WidgetHSlider.prototype.onMouseLeave = function(e) + { + //this.oldmouse = null; + } + + WidgetHSlider.prototype.onPropertyChanged = function(name,value) + { + if(name=="wcolor") + this.properties[name] = value; + else + return false; + return true; + } + + LiteGraph.registerNodeType("widget/hslider", WidgetHSlider ); + + + function WidgetProgress() + { + this.size = [160,26]; + this.addInput("",'number'); + this.properties = {min:0,max:1,value:0,wcolor:"#AAF"}; + } + + WidgetProgress.title = "Progress"; + WidgetProgress.desc = "Shows data in linear progress"; + + WidgetProgress.prototype.onExecute = function() + { + var v = this.getInputData(0); + if( v != undefined ) + this.properties["value"] = v; + } + + WidgetProgress.prototype.onDrawForeground = function(ctx) + { + //border + ctx.lineWidth = 1; + ctx.fillStyle=this.properties.wcolor; + var v = (this.properties.value - this.properties.min) / (this.properties.max - this.properties.min); + v = Math.min(1,v); + v = Math.max(0,v); + ctx.fillRect(2,2,(this.size[0]-4)*v,this.size[1]-4); + } + + LiteGraph.registerNodeType("widget/progress", WidgetProgress); + + + /* + LiteGraph.registerNodeType("widget/kpad",{ + title: "KPad", + desc: "bidimensional slider", + size: [200,200], + outputs: [["x",'number'],["y",'number']], + properties:{x:0,y:0,borderColor:"#333",bgcolorTop:"#444",bgcolorBottom:"#000",shadowSize:1, borderRadius:2}, + + createGradient: function(ctx) + { + this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]); + this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]); + this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]); + }, + + onDrawBackground: function(ctx) + { + if(!this.lineargradient) + this.createGradient(ctx); + + ctx.lineWidth = 1; + ctx.strokeStyle = this.properties["borderColor"]; + //ctx.fillStyle = "#ebebeb"; + ctx.fillStyle = this.lineargradient; + + ctx.shadowColor = "#000"; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + ctx.shadowBlur = this.properties["shadowSize"]; + ctx.roundRect(0,0,this.size[0],this.size[1],this.properties["shadowSize"]); + ctx.fill(); + ctx.shadowColor = "rgba(0,0,0,0)"; + ctx.stroke(); + + ctx.fillStyle = "#A00"; + ctx.fillRect(this.size[0] * this.properties["x"] - 5, this.size[1] * this.properties["y"] - 5,10,10); + }, + + onWidget: function(e,widget) + { + if(widget.name == "update") + { + this.lineargradient = null; + this.setDirtyCanvas(true); + } + }, + + onExecute: function() + { + this.setOutputData(0, this.properties["x"] ); + this.setOutputData(1, this.properties["y"] ); + }, + + onMouseDown: function(e) + { + if(e.canvasY - this.pos[1] < 0) + return false; + + this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; + this.captureInput(true); + return true; + }, + + onMouseMove: function(e) + { + if(!this.oldmouse) return; + + var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ]; + + this.properties.x = m[0] / this.size[0]; + this.properties.y = m[1] / this.size[1]; + + if(this.properties.x > 1.0) this.properties.x = 1.0; + else if(this.properties.x < 0.0) this.properties.x = 0.0; + + if(this.properties.y > 1.0) this.properties.y = 1.0; + else if(this.properties.y < 0.0) this.properties.y = 0.0; + + this.oldmouse = m; + this.setDirtyCanvas(true); + }, + + onMouseUp: function(e) + { + if(this.oldmouse) + { + this.oldmouse = null; + this.captureInput(false); + } + }, + + onMouseLeave: function(e) + { + //this.oldmouse = null; + } + }); + + + + LiteGraph.registerNodeType("widget/button", { + title: "Button", + desc: "A send command button", + + widgets: [{name:"test",text:"Test Button",type:"button"}], + size: [100,40], + properties:{text:"clickme",command:"",color:"#7AF",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",fontsize:"16"}, + outputs:[["M","module"]], + + createGradient: function(ctx) + { + this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]); + this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]); + this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]); + }, + + drawVectorShape: function(ctx) + { + ctx.fillStyle = this.mouseOver ? this.properties["color"] : "#AAA"; + + if(this.clicking) + ctx.fillStyle = "#FFF"; + + ctx.strokeStyle = "#AAA"; + ctx.roundRect(5,5,this.size[0] - 10,this.size[1] - 10,4); + ctx.stroke(); + + if(this.mouseOver) + ctx.fill(); + + //ctx.fillRect(5,20,this.size[0] - 10,this.size[1] - 30); + + ctx.fillStyle = this.mouseOver ? "#000" : "#AAA"; + ctx.font = "bold " + this.properties["fontsize"] + "px Criticized,Tahoma"; + ctx.textAlign = "center"; + ctx.fillText(this.properties["text"],this.size[0]*0.5,this.size[1]*0.5 + 0.5*parseInt(this.properties["fontsize"])); + ctx.textAlign = "left"; + }, + + drawBevelShape: function(ctx) + { + ctx.shadowColor = "#000"; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + ctx.shadowBlur = this.properties["shadowSize"]; + + if(!this.lineargradient) + this.createGradient(ctx); + + ctx.fillStyle = this.mouseOver ? this.properties["color"] : this.lineargradient; + if(this.clicking) + ctx.fillStyle = "#444"; + + ctx.strokeStyle = "#FFF"; + ctx.roundRect(5,5,this.size[0] - 10,this.size[1] - 10,4); + ctx.fill(); + ctx.shadowColor = "rgba(0,0,0,0)"; + ctx.stroke(); + + ctx.fillStyle = this.mouseOver ? "#000" : "#444"; + ctx.font = "bold " + this.properties["fontsize"] + "px Century Gothic"; + ctx.textAlign = "center"; + ctx.fillText(this.properties["text"],this.size[0]*0.5,this.size[1]*0.5 + 0.40*parseInt(this.properties["fontsize"])); + ctx.textAlign = "left"; + }, + + onDrawForeground: function(ctx) + { + this.drawBevelShape(ctx); + }, + + clickButton: function() + { + var module = this.getOutputModule(0); + if(this.properties["command"] && this.properties["command"] != "") + { + if (! module.executeAction(this.properties["command"]) ) + this.trace("Error executing action in other module"); + } + else if(module && module.onTrigger) + { + module.onTrigger(); + } + }, + + onMouseDown: function(e) + { + if(e.canvasY - this.pos[1] < 2) + return false; + this.clickButton(); + this.clicking = true; + return true; + }, + + onMouseUp: function(e) + { + this.clicking = false; + }, + + onExecute: function() + { + }, + + onWidget: function(e,widget) + { + if(widget.name == "test") + { + this.clickButton(); + } + }, + + onPropertyChanged: function(name,value) + { + this.properties[name] = value; + return true; + } + }); + */ + + + function WidgetText() + { + this.addInputs("",0); + this.properties = { value:"...",font:"Arial", fontsize:18, color:"#AAA", align:"left", glowSize:0, decimals:1 }; + } + + WidgetText.title = "Text"; + WidgetText.desc = "Shows the input value"; + WidgetText.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}]; + + WidgetText.prototype.onDrawForeground = function(ctx) + { + //ctx.fillStyle="#000"; + //ctx.fillRect(0,0,100,60); + ctx.fillStyle = this.properties["color"]; + var v = this.properties["value"]; + + if(this.properties["glowSize"]) + { + ctx.shadowColor = this.properties["color"]; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + ctx.shadowBlur = this.properties["glowSize"]; + } + else + ctx.shadowColor = "transparent"; + + var fontsize = this.properties["fontsize"]; + + ctx.textAlign = this.properties["align"]; + ctx.font = fontsize.toString() + "px " + this.properties["font"]; + this.str = typeof(v) == 'number' ? v.toFixed(this.properties["decimals"]) : v; + + if( typeof(this.str) == 'string') + { + var lines = this.str.split("\\n"); + for(var i in lines) + ctx.fillText(lines[i],this.properties["align"] == "left" ? 15 : this.size[0] - 15, fontsize * -0.15 + fontsize * (parseInt(i)+1) ); + } + + ctx.shadowColor = "transparent"; + this.last_ctx = ctx; + ctx.textAlign = "left"; + } + + WidgetText.prototype.onExecute = function() + { + var v = this.getInputData(0); + if(v != null) + this.properties["value"] = v; + //this.setDirtyCanvas(true); + } + + WidgetText.prototype.resize = function() + { + if(!this.last_ctx) return; + + var lines = this.str.split("\\n"); + this.last_ctx.font = this.properties["fontsize"] + "px " + this.properties["font"]; + var max = 0; + for(var i in lines) + { + var w = this.last_ctx.measureText(lines[i]).width; + if(max < w) max = w; + } + this.size[0] = max + 20; + this.size[1] = 4 + lines.length * this.properties["fontsize"]; + + this.setDirtyCanvas(true); + } + + WidgetText.prototype.onWidget = function(e,widget) + { + if(widget.name == "resize") + this.resize(); + else if (widget.name == "led_text") + { + this.properties["font"] = "Digital"; + this.properties["glowSize"] = 4; + this.setDirtyCanvas(true); + } + else if (widget.name == "normal_text") + { + this.properties["font"] = "Arial"; + this.setDirtyCanvas(true); + } + } + + WidgetText.prototype.onPropertyChanged = function(name,value) + { + this.properties[name] = value; + this.str = typeof(value) == 'number' ? value.toFixed(3) : value; + //this.resize(); + return true; + } + + LiteGraph.registerNodeType("widget/text", WidgetText ); + + + function WidgetPanel() + { + this.size = [200,100]; + this.properties = {borderColor:"#ffffff",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",shadowSize:2, borderRadius:3}; + } + + WidgetPanel.title = "Panel"; + WidgetPanel.desc = "Non interactive panel"; + WidgetPanel.widgets = [{name:"update",text:"Update",type:"button"}]; + + + WidgetPanel.prototype.createGradient = function(ctx) + { + if(this.properties["bgcolorTop"] == "" || this.properties["bgcolorBottom"] == "") + { + this.lineargradient = 0; + return; + } + + this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]); + this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]); + this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]); + } + + WidgetPanel.prototype.onDrawForeground = function(ctx) + { + if(this.lineargradient == null) + this.createGradient(ctx); + + if(!this.lineargradient) + return; + + ctx.lineWidth = 1; + ctx.strokeStyle = this.properties["borderColor"]; + //ctx.fillStyle = "#ebebeb"; + ctx.fillStyle = this.lineargradient; + + if(this.properties["shadowSize"]) + { + ctx.shadowColor = "#000"; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + ctx.shadowBlur = this.properties["shadowSize"]; + } + else + ctx.shadowColor = "transparent"; + + ctx.roundRect(0,0,this.size[0]-1,this.size[1]-1,this.properties["shadowSize"]); + ctx.fill(); + ctx.shadowColor = "transparent"; + ctx.stroke(); + } + + WidgetPanel.prototype.onWidget = function(e,widget) + { + if(widget.name == "update") + { + this.lineargradient = null; + this.setDirtyCanvas(true); + } + } + + LiteGraph.registerNodeType("widget/panel", WidgetPanel ); + +})(this); (function(global){ var LiteGraph = global.LiteGraph; @@ -8078,7 +8089,7 @@ GamepadInput.prototype.onGetOutputs = function() { LiteGraph.registerNodeType("input/gamepad", GamepadInput ); -})(this); +})(this); (function(global){ var LiteGraph = global.LiteGraph; @@ -9120,764 +9131,764 @@ if(global.glMatrix) } //glMatrix -})(this); -(function(global){ -var LiteGraph = global.LiteGraph; - -function Selector() -{ - this.addInput("sel","boolean"); - this.addOutput("value","number"); - this.properties = { A:0, B:1 }; - this.size = [60,20]; -} - -Selector.title = "Selector"; -Selector.desc = "outputs A if selector is true, B if selector is false"; - -Selector.prototype.onExecute = function() -{ - var cond = this.getInputData(0); - if(cond === undefined) - return; - - for(var i = 1; i < this.inputs.length; i++) - { - var input = this.inputs[i]; - var v = this.getInputData(i); - if(v === undefined) - continue; - this.properties[input.name] = v; - } - - var A = this.properties.A; - var B = this.properties.B; - this.setOutputData(0, cond ? A : B ); -} - -Selector.prototype.onGetInputs = function() { - return [["A",0],["B",0]]; -} - -LiteGraph.registerNodeType("logic/selector", Selector); - -})(this); -(function(global){ -var LiteGraph = global.LiteGraph; - -function GraphicsImage() -{ - this.inputs = []; - this.addOutput("frame","image"); - this.properties = {"url":""}; -} - -GraphicsImage.title = "Image"; -GraphicsImage.desc = "Image loader"; -GraphicsImage.widgets = [{name:"load",text:"Load",type:"button"}]; - -GraphicsImage.supported_extensions = ["jpg","jpeg","png","gif"]; - -GraphicsImage.prototype.onAdded = function() -{ - if(this.properties["url"] != "" && this.img == null) - { - this.loadImage( this.properties["url"] ); - } -} - -GraphicsImage.prototype.onDrawBackground = function(ctx) -{ - if(this.img && this.size[0] > 5 && this.size[1] > 5) - ctx.drawImage(this.img, 0,0,this.size[0],this.size[1]); -} - - -GraphicsImage.prototype.onExecute = function() -{ - if(!this.img) - this.boxcolor = "#000"; - if(this.img && this.img.width) - this.setOutputData(0,this.img); - else - this.setOutputData(0,null); - if(this.img && this.img.dirty) - this.img.dirty = false; -} - -GraphicsImage.prototype.onPropertyChanged = function(name,value) -{ - this.properties[name] = value; - if (name == "url" && value != "") - this.loadImage(value); - - return true; -} - -GraphicsImage.prototype.loadImage = function( url, callback ) -{ - if(url == "") - { - this.img = null; - return; - } - - this.img = document.createElement("img"); - - if(url.substr(0,7) == "http://") - { - if(LiteGraph.proxy) //proxy external files - url = LiteGraph.proxy + url.substr(7); - } - - this.img.src = url; - this.boxcolor = "#F95"; - var that = this; - this.img.onload = function() - { - if(callback) - callback(this); - that.trace("Image loaded, size: " + that.img.width + "x" + that.img.height ); - this.dirty = true; - that.boxcolor = "#9F9"; - that.setDirtyCanvas(true); - } -} - -GraphicsImage.prototype.onWidget = function(e,widget) -{ - if(widget.name == "load") - { - this.loadImage(this.properties["url"]); - } -} - -GraphicsImage.prototype.onDropFile = function(file) -{ - var that = this; - if(this._url) - URL.revokeObjectURL( this._url ); - this._url = URL.createObjectURL( file ); - this.properties.url = this._url; - this.loadImage( this._url, function(img){ - that.size[1] = (img.height / img.width) * that.size[0]; - }); -} - -LiteGraph.registerNodeType("graphics/image", GraphicsImage); - - - -function ColorPalette() -{ - this.addInput("f","number"); - this.addOutput("Color","color"); - this.properties = {colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"}; - -} - -ColorPalette.title = "Palette"; -ColorPalette.desc = "Generates a color"; - -ColorPalette.prototype.onExecute = function() -{ - var c = []; - - if (this.properties.colorA != null) - c.push( hex2num( this.properties.colorA ) ); - if (this.properties.colorB != null) - c.push( hex2num( this.properties.colorB ) ); - if (this.properties.colorC != null) - c.push( hex2num( this.properties.colorC ) ); - if (this.properties.colorD != null) - c.push( hex2num( this.properties.colorD ) ); - - var f = this.getInputData(0); - if(f == null) f = 0.5; - if (f > 1.0) - f = 1.0; - else if (f < 0.0) - f = 0.0; - - if(c.length == 0) - return; - - var result = [0,0,0]; - if(f == 0) - result = c[0]; - else if(f == 1) - result = c[ c.length - 1]; - else - { - var pos = (c.length - 1)* f; - var c1 = c[ Math.floor(pos) ]; - var c2 = c[ Math.floor(pos)+1 ]; - var t = pos - Math.floor(pos); - result[0] = c1[0] * (1-t) + c2[0] * (t); - result[1] = c1[1] * (1-t) + c2[1] * (t); - result[2] = c1[2] * (1-t) + c2[2] * (t); - } - - /* - c[0] = 1.0 - Math.abs( Math.sin( 0.1 * reModular.getTime() * Math.PI) ); - c[1] = Math.abs( Math.sin( 0.07 * reModular.getTime() * Math.PI) ); - c[2] = Math.abs( Math.sin( 0.01 * reModular.getTime() * Math.PI) ); - */ - - for(var i in result) - result[i] /= 255; - - this.boxcolor = colorToString(result); - this.setOutputData(0, result); -} - - -LiteGraph.registerNodeType("color/palette", ColorPalette ); - - -function ImageFrame() -{ - this.addInput("","image"); - this.size = [200,200]; -} - -ImageFrame.title = "Frame"; -ImageFrame.desc = "Frame viewerew"; -ImageFrame.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}]; - - -ImageFrame.prototype.onDrawBackground = function(ctx) -{ - if(this.frame) - ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]); -} - -ImageFrame.prototype.onExecute = function() -{ - this.frame = this.getInputData(0); - this.setDirtyCanvas(true); -} - -ImageFrame.prototype.onWidget = function(e,widget) -{ - if(widget.name == "resize" && this.frame) - { - var width = this.frame.width; - var height = this.frame.height; - - if(!width && this.frame.videoWidth != null ) - { - width = this.frame.videoWidth; - height = this.frame.videoHeight; - } - - if(width && height) - this.size = [width, height]; - this.setDirtyCanvas(true,true); - } - else if(widget.name == "view") - this.show(); -} - -ImageFrame.prototype.show = function() -{ - //var str = this.canvas.toDataURL("image/png"); - if(showElement && this.frame) - showElement(this.frame); -} - - -LiteGraph.registerNodeType("graphics/frame", ImageFrame ); - - - -/* -LiteGraph.registerNodeType("visualization/graph", { - desc: "Shows a graph of the inputs", - - inputs: [["",0],["",0],["",0],["",0]], - size: [200,200], - properties: {min:-1,max:1,bgColor:"#000"}, - onDrawBackground: function(ctx) - { - var colors = ["#FFF","#FAA","#AFA","#AAF"]; - - if(this.properties.bgColor != null && this.properties.bgColor != "") - { - ctx.fillStyle="#000"; - ctx.fillRect(2,2,this.size[0] - 4, this.size[1]-4); - } - - if(this.data) - { - var min = this.properties["min"]; - var max = this.properties["max"]; - - for(var i in this.data) - { - var data = this.data[i]; - if(!data) continue; - - if(this.getInputInfo(i) == null) continue; - - ctx.strokeStyle = colors[i]; - ctx.beginPath(); - - var d = data.length / this.size[0]; - for(var j = 0; j < data.length; j += d) - { - var value = data[ Math.floor(j) ]; - value = (value - min) / (max - min); - if (value > 1.0) value = 1.0; - else if(value < 0) value = 0; - - if(j == 0) - ctx.moveTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); - else - ctx.lineTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); - } - - ctx.stroke(); - } - } - - //ctx.restore(); - }, - - onExecute: function() - { - if(!this.data) this.data = []; - - for(var i in this.inputs) - { - var value = this.getInputData(i); - - if(typeof(value) == "number") - { - value = value ? value : 0; - if(!this.data[i]) - this.data[i] = []; - this.data[i].push(value); - - if(this.data[i].length > (this.size[1] - 4)) - this.data[i] = this.data[i].slice(1,this.data[i].length); - } - else - this.data[i] = value; - } - - if(this.data.length) - this.setDirtyCanvas(true); - } - }); -*/ - -function ImageFade() -{ - this.addInputs([["img1","image"],["img2","image"],["fade","number"]]); - this.addOutput("","image"); - this.properties = {fade:0.5,width:512,height:512}; -} - -ImageFade.title = "Image fade"; -ImageFade.desc = "Fades between images"; -ImageFade.widgets = [{name:"resizeA",text:"Resize to A",type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}]; - -ImageFade.prototype.onAdded = function() -{ - this.createCanvas(); - var ctx = this.canvas.getContext("2d"); - ctx.fillStyle = "#000"; - ctx.fillRect(0,0,this.properties["width"],this.properties["height"]); -} - -ImageFade.prototype.createCanvas = function() -{ - this.canvas = document.createElement("canvas"); - this.canvas.width = this.properties["width"]; - this.canvas.height = this.properties["height"]; -} - -ImageFade.prototype.onExecute = function() -{ - var ctx = this.canvas.getContext("2d"); - this.canvas.width = this.canvas.width; - - var A = this.getInputData(0); - if (A != null) - { - ctx.drawImage(A,0,0,this.canvas.width, this.canvas.height); - } - - var fade = this.getInputData(2); - if(fade == null) - fade = this.properties["fade"]; - else - this.properties["fade"] = fade; - - ctx.globalAlpha = fade; - var B = this.getInputData(1); - if (B != null) - { - ctx.drawImage(B,0,0,this.canvas.width, this.canvas.height); - } - ctx.globalAlpha = 1.0; - - this.setOutputData(0,this.canvas); - this.setDirtyCanvas(true); -} - -LiteGraph.registerNodeType("graphics/imagefade", ImageFade); - - - -function ImageCrop() -{ - this.addInput("","image"); - this.addOutput("","image"); - this.properties = {width:256,height:256,x:0,y:0,scale:1.0 }; - this.size = [50,20]; -} - -ImageCrop.title = "Crop"; -ImageCrop.desc = "Crop Image"; - -ImageCrop.prototype.onAdded = function() -{ - this.createCanvas(); -} - -ImageCrop.prototype.createCanvas = function() -{ - this.canvas = document.createElement("canvas"); - this.canvas.width = this.properties["width"]; - this.canvas.height = this.properties["height"]; -} - -ImageCrop.prototype.onExecute = function() -{ - var input = this.getInputData(0); - if(!input) - return; - - if(input.width) - { - var ctx = this.canvas.getContext("2d"); - - ctx.drawImage(input, -this.properties["x"],-this.properties["y"], input.width * this.properties["scale"], input.height * this.properties["scale"]); - this.setOutputData(0,this.canvas); - } - else - this.setOutputData(0,null); -} - -ImageCrop.prototype.onDrawBackground = function(ctx) -{ - if(this.flags.collapsed) - return; - if(this.canvas) - ctx.drawImage( this.canvas, 0,0,this.canvas.width,this.canvas.height, 0,0, this.size[0], this.size[1] ); -} - -ImageCrop.prototype.onPropertyChanged = function(name,value) -{ - this.properties[name] = value; - - if(name == "scale") - { - this.properties[name] = parseFloat(value); - if(this.properties[name] == 0) - { - this.trace("Error in scale"); - this.properties[name] = 1.0; - } - } - else - this.properties[name] = parseInt(value); - - this.createCanvas(); - - return true; -} - -LiteGraph.registerNodeType("graphics/cropImage", ImageCrop ); - - -function ImageVideo() -{ - this.addInput("t","number"); - this.addOutputs([["frame","image"],["t","number"],["d","number"]]); - this.properties = {"url":""}; -} - -ImageVideo.title = "Video"; -ImageVideo.desc = "Video playback"; -ImageVideo.widgets = [{name:"play",text:"PLAY",type:"minibutton"},{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}]; - -ImageVideo.prototype.onExecute = function() -{ - if(!this.properties.url) - return; - - if(this.properties.url != this._video_url) - this.loadVideo(this.properties.url); - - if(!this._video || this._video.width == 0) - return; - - var t = this.getInputData(0); - if(t && t >= 0 && t <= 1.0) - { - this._video.currentTime = t * this._video.duration; - this._video.pause(); - } - - this._video.dirty = true; - this.setOutputData(0,this._video); - this.setOutputData(1,this._video.currentTime); - this.setOutputData(2,this._video.duration); - this.setDirtyCanvas(true); -} - -ImageVideo.prototype.onStart = function() -{ - this.play(); -} - -ImageVideo.prototype.onStop = function() -{ - this.stop(); -} - -ImageVideo.prototype.loadVideo = function(url) -{ - this._video_url = url; - - this._video = document.createElement("video"); - this._video.src = url; - this._video.type = "type=video/mp4"; - - this._video.muted = true; - this._video.autoplay = true; - - var that = this; - this._video.addEventListener("loadedmetadata",function(e) { - //onload - that.trace("Duration: " + this.duration + " seconds"); - that.trace("Size: " + this.videoWidth + "," + this.videoHeight); - that.setDirtyCanvas(true); - this.width = this.videoWidth; - this.height = this.videoHeight; - }); - this._video.addEventListener("progress",function(e) { - //onload - //that.trace("loading..."); - }); - this._video.addEventListener("error",function(e) { - console.log("Error loading video: " + this.src); - that.trace("Error loading video: " + this.src); - if (this.error) { - switch (this.error.code) { - case this.error.MEDIA_ERR_ABORTED: - that.trace("You stopped the video."); - break; - case this.error.MEDIA_ERR_NETWORK: - that.trace("Network error - please try again later."); - break; - case this.error.MEDIA_ERR_DECODE: - that.trace("Video is broken.."); - break; - case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED: - that.trace("Sorry, your browser can't play this video."); - break; - } - } - }); - - this._video.addEventListener("ended",function(e) { - that.trace("Ended."); - this.play(); //loop - }); - - //document.body.appendChild(this.video); -} - -ImageVideo.prototype.onPropertyChanged = function(name,value) -{ - this.properties[name] = value; - if (name == "url" && value != "") - this.loadVideo(value); - - return true; -} - -ImageVideo.prototype.play = function() -{ - if(this._video) - this._video.play(); -} - -ImageVideo.prototype.playPause = function() -{ - if(!this._video) - return; - if(this._video.paused) - this.play(); - else - this.pause(); -} - -ImageVideo.prototype.stop = function() -{ - if(!this._video) - return; - this._video.pause(); - this._video.currentTime = 0; -} - -ImageVideo.prototype.pause = function() -{ - if(!this._video) - return; - this.trace("Video paused"); - this._video.pause(); -} - -ImageVideo.prototype.onWidget = function(e,widget) -{ - /* - if(widget.name == "demo") - { - this.loadVideo(); - } - else if(widget.name == "play") - { - if(this._video) - this.playPause(); - } - if(widget.name == "stop") - { - this.stop(); - } - else if(widget.name == "mute") - { - if(this._video) - this._video.muted = !this._video.muted; - } - */ -} - -LiteGraph.registerNodeType("graphics/video", ImageVideo ); - - -// Texture Webcam ***************************************** -function ImageWebcam() -{ - this.addOutput("Webcam","image"); - this.properties = {}; -} - -ImageWebcam.title = "Webcam"; -ImageWebcam.desc = "Webcam image"; - - -ImageWebcam.prototype.openStream = function() -{ - //Vendor prefixes hell - navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); - window.URL = window.URL || window.webkitURL; - - if (!navigator.getUserMedia) { - //console.log('getUserMedia() is not supported in your browser, use chrome and enable WebRTC from about://flags'); - return; - } - - this._waiting_confirmation = true; - - // Not showing vendor prefixes. - navigator.getUserMedia({video: true}, this.streamReady.bind(this), onFailSoHard); - - var that = this; - function onFailSoHard(e) { - console.log('Webcam rejected', e); - that._webcam_stream = false; - that.box_color = "red"; - }; -} - -ImageWebcam.prototype.onRemoved = function() -{ - if(this._webcam_stream) - { - this._webcam_stream.stop(); - this._webcam_stream = null; - this._video = null; - } -} - -ImageWebcam.prototype.streamReady = function(localMediaStream) -{ - this._webcam_stream = localMediaStream; - //this._waiting_confirmation = false; - - var video = this._video; - if(!video) - { - video = document.createElement("video"); - video.autoplay = true; - video.src = window.URL.createObjectURL(localMediaStream); - this._video = video; - //document.body.appendChild( video ); //debug - //when video info is loaded (size and so) - video.onloadedmetadata = function(e) { - // Ready to go. Do some stuff. - console.log(e); - }; - } -}, - -ImageWebcam.prototype.onExecute = function() -{ - if(this._webcam_stream == null && !this._waiting_confirmation) - this.openStream(); - - if(!this._video || !this._video.videoWidth) return; - - this._video.width = this._video.videoWidth; - this._video.height = this._video.videoHeight; - this.setOutputData(0, this._video); -} - -ImageWebcam.prototype.getExtraMenuOptions = function(graphcanvas) -{ - var that = this; - var txt = !that.properties.show ? "Show Frame" : "Hide Frame"; - return [ {content: txt, callback: - function() { - that.properties.show = !that.properties.show; - } - }]; -} - -ImageWebcam.prototype.onDrawBackground = function(ctx) -{ - if(this.flags.collapsed || this.size[1] <= 20 || !this.properties.show) - return; - - if(!this._video) - return; - - //render to graph canvas - ctx.save(); - ctx.drawImage(this._video, 0, 0, this.size[0], this.size[1]); - ctx.restore(); -} - -LiteGraph.registerNodeType("graphics/webcam", ImageWebcam ); - - -})(this); - +})(this); +(function(global){ +var LiteGraph = global.LiteGraph; + +function Selector() +{ + this.addInput("sel","boolean"); + this.addOutput("value","number"); + this.properties = { A:0, B:1 }; + this.size = [60,20]; +} + +Selector.title = "Selector"; +Selector.desc = "outputs A if selector is true, B if selector is false"; + +Selector.prototype.onExecute = function() +{ + var cond = this.getInputData(0); + if(cond === undefined) + return; + + for(var i = 1; i < this.inputs.length; i++) + { + var input = this.inputs[i]; + var v = this.getInputData(i); + if(v === undefined) + continue; + this.properties[input.name] = v; + } + + var A = this.properties.A; + var B = this.properties.B; + this.setOutputData(0, cond ? A : B ); +} + +Selector.prototype.onGetInputs = function() { + return [["A",0],["B",0]]; +} + +LiteGraph.registerNodeType("logic/selector", Selector); + +})(this); +(function(global){ +var LiteGraph = global.LiteGraph; + +function GraphicsImage() +{ + this.inputs = []; + this.addOutput("frame","image"); + this.properties = {"url":""}; +} + +GraphicsImage.title = "Image"; +GraphicsImage.desc = "Image loader"; +GraphicsImage.widgets = [{name:"load",text:"Load",type:"button"}]; + +GraphicsImage.supported_extensions = ["jpg","jpeg","png","gif"]; + +GraphicsImage.prototype.onAdded = function() +{ + if(this.properties["url"] != "" && this.img == null) + { + this.loadImage( this.properties["url"] ); + } +} + +GraphicsImage.prototype.onDrawBackground = function(ctx) +{ + if(this.img && this.size[0] > 5 && this.size[1] > 5) + ctx.drawImage(this.img, 0,0,this.size[0],this.size[1]); +} + + +GraphicsImage.prototype.onExecute = function() +{ + if(!this.img) + this.boxcolor = "#000"; + if(this.img && this.img.width) + this.setOutputData(0,this.img); + else + this.setOutputData(0,null); + if(this.img && this.img.dirty) + this.img.dirty = false; +} + +GraphicsImage.prototype.onPropertyChanged = function(name,value) +{ + this.properties[name] = value; + if (name == "url" && value != "") + this.loadImage(value); + + return true; +} + +GraphicsImage.prototype.loadImage = function( url, callback ) +{ + if(url == "") + { + this.img = null; + return; + } + + this.img = document.createElement("img"); + + if(url.substr(0,7) == "http://") + { + if(LiteGraph.proxy) //proxy external files + url = LiteGraph.proxy + url.substr(7); + } + + this.img.src = url; + this.boxcolor = "#F95"; + var that = this; + this.img.onload = function() + { + if(callback) + callback(this); + that.trace("Image loaded, size: " + that.img.width + "x" + that.img.height ); + this.dirty = true; + that.boxcolor = "#9F9"; + that.setDirtyCanvas(true); + } +} + +GraphicsImage.prototype.onWidget = function(e,widget) +{ + if(widget.name == "load") + { + this.loadImage(this.properties["url"]); + } +} + +GraphicsImage.prototype.onDropFile = function(file) +{ + var that = this; + if(this._url) + URL.revokeObjectURL( this._url ); + this._url = URL.createObjectURL( file ); + this.properties.url = this._url; + this.loadImage( this._url, function(img){ + that.size[1] = (img.height / img.width) * that.size[0]; + }); +} + +LiteGraph.registerNodeType("graphics/image", GraphicsImage); + + + +function ColorPalette() +{ + this.addInput("f","number"); + this.addOutput("Color","color"); + this.properties = {colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"}; + +} + +ColorPalette.title = "Palette"; +ColorPalette.desc = "Generates a color"; + +ColorPalette.prototype.onExecute = function() +{ + var c = []; + + if (this.properties.colorA != null) + c.push( hex2num( this.properties.colorA ) ); + if (this.properties.colorB != null) + c.push( hex2num( this.properties.colorB ) ); + if (this.properties.colorC != null) + c.push( hex2num( this.properties.colorC ) ); + if (this.properties.colorD != null) + c.push( hex2num( this.properties.colorD ) ); + + var f = this.getInputData(0); + if(f == null) f = 0.5; + if (f > 1.0) + f = 1.0; + else if (f < 0.0) + f = 0.0; + + if(c.length == 0) + return; + + var result = [0,0,0]; + if(f == 0) + result = c[0]; + else if(f == 1) + result = c[ c.length - 1]; + else + { + var pos = (c.length - 1)* f; + var c1 = c[ Math.floor(pos) ]; + var c2 = c[ Math.floor(pos)+1 ]; + var t = pos - Math.floor(pos); + result[0] = c1[0] * (1-t) + c2[0] * (t); + result[1] = c1[1] * (1-t) + c2[1] * (t); + result[2] = c1[2] * (1-t) + c2[2] * (t); + } + + /* + c[0] = 1.0 - Math.abs( Math.sin( 0.1 * reModular.getTime() * Math.PI) ); + c[1] = Math.abs( Math.sin( 0.07 * reModular.getTime() * Math.PI) ); + c[2] = Math.abs( Math.sin( 0.01 * reModular.getTime() * Math.PI) ); + */ + + for(var i in result) + result[i] /= 255; + + this.boxcolor = colorToString(result); + this.setOutputData(0, result); +} + + +LiteGraph.registerNodeType("color/palette", ColorPalette ); + + +function ImageFrame() +{ + this.addInput("","image"); + this.size = [200,200]; +} + +ImageFrame.title = "Frame"; +ImageFrame.desc = "Frame viewerew"; +ImageFrame.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}]; + + +ImageFrame.prototype.onDrawBackground = function(ctx) +{ + if(this.frame) + ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]); +} + +ImageFrame.prototype.onExecute = function() +{ + this.frame = this.getInputData(0); + this.setDirtyCanvas(true); +} + +ImageFrame.prototype.onWidget = function(e,widget) +{ + if(widget.name == "resize" && this.frame) + { + var width = this.frame.width; + var height = this.frame.height; + + if(!width && this.frame.videoWidth != null ) + { + width = this.frame.videoWidth; + height = this.frame.videoHeight; + } + + if(width && height) + this.size = [width, height]; + this.setDirtyCanvas(true,true); + } + else if(widget.name == "view") + this.show(); +} + +ImageFrame.prototype.show = function() +{ + //var str = this.canvas.toDataURL("image/png"); + if(showElement && this.frame) + showElement(this.frame); +} + + +LiteGraph.registerNodeType("graphics/frame", ImageFrame ); + + + +/* +LiteGraph.registerNodeType("visualization/graph", { + desc: "Shows a graph of the inputs", + + inputs: [["",0],["",0],["",0],["",0]], + size: [200,200], + properties: {min:-1,max:1,bgColor:"#000"}, + onDrawBackground: function(ctx) + { + var colors = ["#FFF","#FAA","#AFA","#AAF"]; + + if(this.properties.bgColor != null && this.properties.bgColor != "") + { + ctx.fillStyle="#000"; + ctx.fillRect(2,2,this.size[0] - 4, this.size[1]-4); + } + + if(this.data) + { + var min = this.properties["min"]; + var max = this.properties["max"]; + + for(var i in this.data) + { + var data = this.data[i]; + if(!data) continue; + + if(this.getInputInfo(i) == null) continue; + + ctx.strokeStyle = colors[i]; + ctx.beginPath(); + + var d = data.length / this.size[0]; + for(var j = 0; j < data.length; j += d) + { + var value = data[ Math.floor(j) ]; + value = (value - min) / (max - min); + if (value > 1.0) value = 1.0; + else if(value < 0) value = 0; + + if(j == 0) + ctx.moveTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); + else + ctx.lineTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); + } + + ctx.stroke(); + } + } + + //ctx.restore(); + }, + + onExecute: function() + { + if(!this.data) this.data = []; + + for(var i in this.inputs) + { + var value = this.getInputData(i); + + if(typeof(value) == "number") + { + value = value ? value : 0; + if(!this.data[i]) + this.data[i] = []; + this.data[i].push(value); + + if(this.data[i].length > (this.size[1] - 4)) + this.data[i] = this.data[i].slice(1,this.data[i].length); + } + else + this.data[i] = value; + } + + if(this.data.length) + this.setDirtyCanvas(true); + } + }); +*/ + +function ImageFade() +{ + this.addInputs([["img1","image"],["img2","image"],["fade","number"]]); + this.addOutput("","image"); + this.properties = {fade:0.5,width:512,height:512}; +} + +ImageFade.title = "Image fade"; +ImageFade.desc = "Fades between images"; +ImageFade.widgets = [{name:"resizeA",text:"Resize to A",type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}]; + +ImageFade.prototype.onAdded = function() +{ + this.createCanvas(); + var ctx = this.canvas.getContext("2d"); + ctx.fillStyle = "#000"; + ctx.fillRect(0,0,this.properties["width"],this.properties["height"]); +} + +ImageFade.prototype.createCanvas = function() +{ + this.canvas = document.createElement("canvas"); + this.canvas.width = this.properties["width"]; + this.canvas.height = this.properties["height"]; +} + +ImageFade.prototype.onExecute = function() +{ + var ctx = this.canvas.getContext("2d"); + this.canvas.width = this.canvas.width; + + var A = this.getInputData(0); + if (A != null) + { + ctx.drawImage(A,0,0,this.canvas.width, this.canvas.height); + } + + var fade = this.getInputData(2); + if(fade == null) + fade = this.properties["fade"]; + else + this.properties["fade"] = fade; + + ctx.globalAlpha = fade; + var B = this.getInputData(1); + if (B != null) + { + ctx.drawImage(B,0,0,this.canvas.width, this.canvas.height); + } + ctx.globalAlpha = 1.0; + + this.setOutputData(0,this.canvas); + this.setDirtyCanvas(true); +} + +LiteGraph.registerNodeType("graphics/imagefade", ImageFade); + + + +function ImageCrop() +{ + this.addInput("","image"); + this.addOutput("","image"); + this.properties = {width:256,height:256,x:0,y:0,scale:1.0 }; + this.size = [50,20]; +} + +ImageCrop.title = "Crop"; +ImageCrop.desc = "Crop Image"; + +ImageCrop.prototype.onAdded = function() +{ + this.createCanvas(); +} + +ImageCrop.prototype.createCanvas = function() +{ + this.canvas = document.createElement("canvas"); + this.canvas.width = this.properties["width"]; + this.canvas.height = this.properties["height"]; +} + +ImageCrop.prototype.onExecute = function() +{ + var input = this.getInputData(0); + if(!input) + return; + + if(input.width) + { + var ctx = this.canvas.getContext("2d"); + + ctx.drawImage(input, -this.properties["x"],-this.properties["y"], input.width * this.properties["scale"], input.height * this.properties["scale"]); + this.setOutputData(0,this.canvas); + } + else + this.setOutputData(0,null); +} + +ImageCrop.prototype.onDrawBackground = function(ctx) +{ + if(this.flags.collapsed) + return; + if(this.canvas) + ctx.drawImage( this.canvas, 0,0,this.canvas.width,this.canvas.height, 0,0, this.size[0], this.size[1] ); +} + +ImageCrop.prototype.onPropertyChanged = function(name,value) +{ + this.properties[name] = value; + + if(name == "scale") + { + this.properties[name] = parseFloat(value); + if(this.properties[name] == 0) + { + this.trace("Error in scale"); + this.properties[name] = 1.0; + } + } + else + this.properties[name] = parseInt(value); + + this.createCanvas(); + + return true; +} + +LiteGraph.registerNodeType("graphics/cropImage", ImageCrop ); + + +function ImageVideo() +{ + this.addInput("t","number"); + this.addOutputs([["frame","image"],["t","number"],["d","number"]]); + this.properties = {"url":""}; +} + +ImageVideo.title = "Video"; +ImageVideo.desc = "Video playback"; +ImageVideo.widgets = [{name:"play",text:"PLAY",type:"minibutton"},{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}]; + +ImageVideo.prototype.onExecute = function() +{ + if(!this.properties.url) + return; + + if(this.properties.url != this._video_url) + this.loadVideo(this.properties.url); + + if(!this._video || this._video.width == 0) + return; + + var t = this.getInputData(0); + if(t && t >= 0 && t <= 1.0) + { + this._video.currentTime = t * this._video.duration; + this._video.pause(); + } + + this._video.dirty = true; + this.setOutputData(0,this._video); + this.setOutputData(1,this._video.currentTime); + this.setOutputData(2,this._video.duration); + this.setDirtyCanvas(true); +} + +ImageVideo.prototype.onStart = function() +{ + this.play(); +} + +ImageVideo.prototype.onStop = function() +{ + this.stop(); +} + +ImageVideo.prototype.loadVideo = function(url) +{ + this._video_url = url; + + this._video = document.createElement("video"); + this._video.src = url; + this._video.type = "type=video/mp4"; + + this._video.muted = true; + this._video.autoplay = true; + + var that = this; + this._video.addEventListener("loadedmetadata",function(e) { + //onload + that.trace("Duration: " + this.duration + " seconds"); + that.trace("Size: " + this.videoWidth + "," + this.videoHeight); + that.setDirtyCanvas(true); + this.width = this.videoWidth; + this.height = this.videoHeight; + }); + this._video.addEventListener("progress",function(e) { + //onload + //that.trace("loading..."); + }); + this._video.addEventListener("error",function(e) { + console.log("Error loading video: " + this.src); + that.trace("Error loading video: " + this.src); + if (this.error) { + switch (this.error.code) { + case this.error.MEDIA_ERR_ABORTED: + that.trace("You stopped the video."); + break; + case this.error.MEDIA_ERR_NETWORK: + that.trace("Network error - please try again later."); + break; + case this.error.MEDIA_ERR_DECODE: + that.trace("Video is broken.."); + break; + case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED: + that.trace("Sorry, your browser can't play this video."); + break; + } + } + }); + + this._video.addEventListener("ended",function(e) { + that.trace("Ended."); + this.play(); //loop + }); + + //document.body.appendChild(this.video); +} + +ImageVideo.prototype.onPropertyChanged = function(name,value) +{ + this.properties[name] = value; + if (name == "url" && value != "") + this.loadVideo(value); + + return true; +} + +ImageVideo.prototype.play = function() +{ + if(this._video) + this._video.play(); +} + +ImageVideo.prototype.playPause = function() +{ + if(!this._video) + return; + if(this._video.paused) + this.play(); + else + this.pause(); +} + +ImageVideo.prototype.stop = function() +{ + if(!this._video) + return; + this._video.pause(); + this._video.currentTime = 0; +} + +ImageVideo.prototype.pause = function() +{ + if(!this._video) + return; + this.trace("Video paused"); + this._video.pause(); +} + +ImageVideo.prototype.onWidget = function(e,widget) +{ + /* + if(widget.name == "demo") + { + this.loadVideo(); + } + else if(widget.name == "play") + { + if(this._video) + this.playPause(); + } + if(widget.name == "stop") + { + this.stop(); + } + else if(widget.name == "mute") + { + if(this._video) + this._video.muted = !this._video.muted; + } + */ +} + +LiteGraph.registerNodeType("graphics/video", ImageVideo ); + + +// Texture Webcam ***************************************** +function ImageWebcam() +{ + this.addOutput("Webcam","image"); + this.properties = {}; +} + +ImageWebcam.title = "Webcam"; +ImageWebcam.desc = "Webcam image"; + + +ImageWebcam.prototype.openStream = function() +{ + //Vendor prefixes hell + navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); + window.URL = window.URL || window.webkitURL; + + if (!navigator.getUserMedia) { + //console.log('getUserMedia() is not supported in your browser, use chrome and enable WebRTC from about://flags'); + return; + } + + this._waiting_confirmation = true; + + // Not showing vendor prefixes. + navigator.getUserMedia({video: true}, this.streamReady.bind(this), onFailSoHard); + + var that = this; + function onFailSoHard(e) { + console.log('Webcam rejected', e); + that._webcam_stream = false; + that.box_color = "red"; + }; +} + +ImageWebcam.prototype.onRemoved = function() +{ + if(this._webcam_stream) + { + this._webcam_stream.stop(); + this._webcam_stream = null; + this._video = null; + } +} + +ImageWebcam.prototype.streamReady = function(localMediaStream) +{ + this._webcam_stream = localMediaStream; + //this._waiting_confirmation = false; + + var video = this._video; + if(!video) + { + video = document.createElement("video"); + video.autoplay = true; + video.src = window.URL.createObjectURL(localMediaStream); + this._video = video; + //document.body.appendChild( video ); //debug + //when video info is loaded (size and so) + video.onloadedmetadata = function(e) { + // Ready to go. Do some stuff. + console.log(e); + }; + } +}, + +ImageWebcam.prototype.onExecute = function() +{ + if(this._webcam_stream == null && !this._waiting_confirmation) + this.openStream(); + + if(!this._video || !this._video.videoWidth) return; + + this._video.width = this._video.videoWidth; + this._video.height = this._video.videoHeight; + this.setOutputData(0, this._video); +} + +ImageWebcam.prototype.getExtraMenuOptions = function(graphcanvas) +{ + var that = this; + var txt = !that.properties.show ? "Show Frame" : "Hide Frame"; + return [ {content: txt, callback: + function() { + that.properties.show = !that.properties.show; + } + }]; +} + +ImageWebcam.prototype.onDrawBackground = function(ctx) +{ + if(this.flags.collapsed || this.size[1] <= 20 || !this.properties.show) + return; + + if(!this._video) + return; + + //render to graph canvas + ctx.save(); + ctx.drawImage(this._video, 0, 0, this.size[0], this.size[1]); + ctx.restore(); +} + +LiteGraph.registerNodeType("graphics/webcam", ImageWebcam ); + + +})(this); + (function(global){ var LiteGraph = global.LiteGraph; @@ -12351,7 +12362,7 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ } //litegl.js defined -})(this); +})(this); (function(global){ var LiteGraph = global.LiteGraph; @@ -12915,7 +12926,7 @@ if(typeof(GL) != "undefined") global.LGraphFXVigneting = LGraphFXVigneting; } -})(this); +})(this); (function( global ) { var LiteGraph = global.LiteGraph; @@ -13623,7 +13634,7 @@ LiteGraph.registerNodeType("midi/cc", LGMIDICC); function now() { return window.performance.now() } -})( this ); +})( this ); (function( global ) { var LiteGraph = global.LiteGraph; @@ -14879,4 +14890,263 @@ LiteGraph.registerNodeType("audio/destination", LGAudioDestination); -})( this ); \ No newline at end of file +})( this ); +//event related nodes +(function(global){ +var LiteGraph = global.LiteGraph; + +function LGWebSocket() +{ + this.size = [60,20]; + this.addInput("send", LiteGraph.ACTION); + this.addOutput("received", LiteGraph.EVENT); + this.addInput("in", 0 ); + this.addOutput("out", 0 ); + this.properties = { + url: "", + room: "lgraph" //allows to filter messages + }; + this._ws = null; + this._last_data = []; +} + +LGWebSocket.title = "WebSocket"; +LGWebSocket.desc = "Send data through a websocket"; + +LGWebSocket.prototype.onPropertyChanged = function(name,value) +{ + if(name == "url") + this.createSocket(); +} + +LGWebSocket.prototype.onExecute = function() +{ + if(!this._ws && this.properties.url) + this.createSocket(); + + if(!this._ws || this._ws.readyState != WebSocket.OPEN ) + return; + + var room = this.properties.room; + + for(var i = 1; i < this.inputs.length; ++i) + { + var data = this.getInputData(i); + if(data != null) + { + var json; + try + { + json = JSON.stringify({ type: 0, room: room, channel: i, data: data }); + } + catch (err) + { + continue; + } + this._ws.send( json ); + } + } + + for(var i = 1; i < this.outputs.length; ++i) + this.setOutputData( i, this._last_data[i] ); +} + +LGWebSocket.prototype.createSocket = function() +{ + var that = this; + var url = this.properties.url; + if( url.substr(0,2) != "ws" ) + url = "ws://" + url; + this._ws = new WebSocket( url ); + this._ws.onopen = function() + { + console.log("ready"); + that.boxcolor = "#8E8"; + } + this._ws.onmessage = function(e) + { + var data = JSON.parse( e.data ); + if( data.room && data.room != this.properties.room ) + return; + if( e.data.type == 1 ) + that.triggerSlot( 0, data ); + else + that._last_data[ e.data.channel || 0 ] = data.data; + } + this._ws.onerror = function(e) + { + console.log("couldnt connect to websocket"); + that.boxcolor = "#E88"; + } + this._ws.onclose = function(e) + { + console.log("connection closed"); + that.boxcolor = "#000"; + } +} + +LGWebSocket.prototype.send = function(data) +{ + if(!this._ws || this._ws.readyState != WebSocket.OPEN ) + return; + this._ws.send( JSON.stringify({ type:1, msg: data }) ); +} + +LGWebSocket.prototype.onAction = function( action, param ) +{ + if(!this._ws || this._ws.readyState != WebSocket.OPEN ) + return; + this._ws.send( { type: 1, room: this.properties.room, action: action, data: param } ); +} + +LGWebSocket.prototype.onGetInputs = function() +{ + return [["in",0]]; +} + +LGWebSocket.prototype.onGetOutputs = function() +{ + return [["out",0]]; +} + +LiteGraph.registerNodeType("network/websocket", LGWebSocket ); + + +//It is like a websocket but using the SillyServer.js server that bounces packets back to all clients connected: +//For more information: https://github.com/jagenjo/SillyServer.js + +function LGSillyClient() +{ + this.size = [60,20]; + this.addInput("send", LiteGraph.ACTION); + this.addOutput("received", LiteGraph.EVENT); + this.addInput("in", 0 ); + this.addOutput("out", 0 ); + this.properties = { + url: "tamats.com:55000", + room: "lgraph", + save_bandwidth: true + }; + + this._server = null; + this.createSocket(); + this._last_input_data = []; + this._last_output_data = []; +} + +LGSillyClient.title = "SillyClient"; +LGSillyClient.desc = "Connects to SillyServer to broadcast messages"; + +LGSillyClient.prototype.onPropertyChanged = function(name,value) +{ + var final_url = (this.properties.url + "/" + this.properties.room); + if(this._server && this._final_url != final_url ) + { + this._server.connect( this.properties.url, this.properties.room ); + this._final_url = final_url; + } +} + +LGSillyClient.prototype.onExecute = function() +{ + if(!this._server || !this._server.is_connected) + return; + + var save_bandwidth = this.properties.save_bandwidth; + + for(var i = 1; i < this.inputs.length; ++i) + { + var data = this.getInputData(i); + if(data != null) + { + if( save_bandwidth && this._last_input_data[i] == data ) + continue; + this._server.sendMessage( { type: 0, channel: i, data: data } ); + this._last_input_data[i] = data; + } + } + + for(var i = 1; i < this.outputs.length; ++i) + this.setOutputData( i, this._last_output_data[i] ); +} + +LGSillyClient.prototype.createSocket = function() +{ + var that = this; + if(typeof(SillyClient) == "undefined") + { + if(!this._error) + console.error("SillyClient node cannot be used, you must include SillyServer.js"); + this._error = true; + return; + } + + this._server = new SillyClient(); + this._server.on_ready = function() + { + console.log("ready"); + that.boxcolor = "#8E8"; + } + this._server.on_message = function(id,msg) + { + var data = null; + try + { + data = JSON.parse( msg ); + } + catch (err) + { + return; + } + + if(data.type == 1) + that.triggerSlot( 0, data ); + else + that._last_output_data[ data.channel || 0 ] = data.data; + } + this._server.on_error = function(e) + { + console.log("couldnt connect to websocket"); + that.boxcolor = "#E88"; + } + this._server.on_close = function(e) + { + console.log("connection closed"); + that.boxcolor = "#000"; + } + + if(this.properties.url && this.properties.room) + { + this._server.connect( this.properties.url, this.properties.room ); + this._final_url = (this.properties.url + "/" + this.properties.room); + } +} + +LGSillyClient.prototype.send = function(data) +{ + if(!this._server || !this._server.is_connected) + return; + this._server.sendMessage( { type:1, data: data } ); +} + +LGSillyClient.prototype.onAction = function( action, param ) +{ + if(!this._server || !this._server.is_connected) + return; + this._server.sendMessage( { type: 1, action: action, data: param } ); +} + +LGSillyClient.prototype.onGetInputs = function() +{ + return [["in",0]]; +} + +LGSillyClient.prototype.onGetOutputs = function() +{ + return [["out",0]]; +} + +LiteGraph.registerNodeType("network/sillyclient", LGSillyClient ); + + +})(this); diff --git a/src/litegraph.js b/src/litegraph.js index 4a437d64bb..d27f36b86e 100755 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -2830,7 +2830,7 @@ function LGraphCanvas( canvas, graph, options ) this.dragging_rectangle = null; this.always_render_background = false; - this.render_canvas_area = true; + this.render_canvas_border = true; this.render_connections_shadows = false; //too much cpu this.render_connections_border = true; this.render_curved_connections = true; @@ -4544,7 +4544,7 @@ LGraphCanvas.prototype.drawBackCanvas = function() //ctx.fillRect( this.visible_area[0] + 10, this.visible_area[1] + 10, this.visible_area[2] - 20, this.visible_area[3] - 20); //bg - if (this.render_canvas_area) { + if (this.render_canvas_border) { ctx.strokeStyle = "#235"; ctx.strokeRect(0,0,canvas.width,canvas.height); }