From b96e0d6c66055fe8bae2c9624f2593ae5f048518 Mon Sep 17 00:00:00 2001 From: tamat Date: Fri, 8 May 2015 21:06:49 +0200 Subject: [PATCH] fixes in optional outputs --- build/litegraph.js | 621 +++++++++++++++++++++------------------- build/litegraph.min.js | 234 +++++++-------- css/litegraph.css | 12 +- src/litegraph.js | 81 ++++-- src/nodes/base.js | 214 ++------------ src/nodes/gltextures.js | 180 +++++++++--- src/nodes/logic.js | 37 +++ src/nodes/math.js | 108 +++++-- utils/deploy_files.txt | 1 + 9 files changed, 783 insertions(+), 705 deletions(-) create mode 100644 src/nodes/logic.js diff --git a/build/litegraph.js b/build/litegraph.js index d2a4a470a..37e454469 100644 --- a/build/litegraph.js +++ b/build/litegraph.js @@ -34,6 +34,7 @@ var LiteGraph = { debug: false, throw_errors: true, registered_node_types: {}, + Nodes: {}, /** * Register a node class so it can be listed when the user wants to create a new one @@ -64,6 +65,8 @@ var LiteGraph = { base_class.prototype[i] = LGraphNode.prototype[i]; this.registered_node_types[ type ] = base_class; + if(base_class.constructor.name) + this.Nodes[ base_class.constructor.name ] = base_class; }, /** @@ -718,6 +721,21 @@ LGraph.prototype.getNodeById = function(id) return this._nodes_by_id[id]; } +/** +* Returns a list of nodes that matches a class +* @method findNodesByClass +* @param {Class} classObject the class itself (not an string) +* @return {Array} a list with all the nodes of this type +*/ + +LGraph.prototype.findNodesByClass = function(classObject) +{ + var r = []; + for(var i in this._nodes) + if(this._nodes[i].constructor === classObject) + r.push(this._nodes[i]); + return r; +} /** * Returns a list of nodes that matches a type @@ -1316,7 +1334,9 @@ LGraphNode.prototype.getTitle = function() */ LGraphNode.prototype.setOutputData = function(slot,data) { - if(!this.outputs) return; + if(!this.outputs) + return; + if(slot > -1 && slot < this.outputs.length && this.outputs[slot] && this.outputs[slot].links != null) { for(var i = 0; i < this.outputs[slot].links.length; i++) @@ -1328,17 +1348,18 @@ LGraphNode.prototype.setOutputData = function(slot,data) } /** -* retrieves the input data from one slot +* retrieves the input data (data traveling through the connection) from one slot * @method getInputData * @param {number} slot * @return {*} data */ LGraphNode.prototype.getInputData = function(slot) { - if(!this.inputs) return null; + if(!this.inputs) + return; //undefined; if(slot < this.inputs.length && this.inputs[slot].link != null) return this.graph.links[ this.inputs[slot].link ].data; - return null; + return; //undefined; } /** @@ -1349,7 +1370,8 @@ LGraphNode.prototype.getInputData = function(slot) */ LGraphNode.prototype.isInputConnected = function(slot) { - if(!this.inputs) return null; + if(!this.inputs) + return false; return (slot < this.inputs.length && this.inputs[slot].link != null); } @@ -1429,7 +1451,7 @@ LGraphNode.prototype.triggerOutput = function(slot,param) * @method addOutput * @param {string} name * @param {string} type string defining the output type ("vec3","number",...) -* @param {Object} extra_info this can be used to have special properties of an output (special color, position, etc) +* @param {Object} extra_info this can be used to have special properties of an output (label, special color, position, etc) */ LGraphNode.prototype.addOutput = function(name,type,extra_info) { @@ -1488,11 +1510,12 @@ LGraphNode.prototype.removeOutput = function(slot) * add a new input slot to use in this node * @method addInput * @param {string} name -* @param {string} type string defining the input type ("vec3","number",...) +* @param {string} type string defining the input type ("vec3","number",...), it its a generic one use 0 * @param {Object} extra_info this can be used to have special properties of an input (label, color, position, etc) */ LGraphNode.prototype.addInput = function(name,type,extra_info) { + type = type || 0; var o = {name:name,type:type,link:null}; if(extra_info) for(var i in extra_info) @@ -2510,7 +2533,7 @@ LGraphCanvas.prototype.processMouseDown = function(e) var link_pos = n.getConnectionPos(true,i); if( isInsideRectangle(e.canvasX, e.canvasY, link_pos[0] - 10, link_pos[1] - 5, 20,10) ) { - if(input.link) + if(input.link !== null) { n.disconnectInput(i); this.dirty_bgcanvas = true; @@ -2888,6 +2911,7 @@ LGraphCanvas.prototype.processKeyDown = function(e) if(e.keyCode == 46 || e.keyCode == 8) { this.deleteSelectedNodes(); + block_default = true; } //collapse @@ -3184,8 +3208,8 @@ LGraphCanvas.prototype.drawFrontCanvas = function() if(!ctx) //maybe is using webgl... return; - if(ctx.start) - ctx.start(); + if(ctx.start2D) + ctx.start2D(); var canvas = this.canvas; @@ -3299,8 +3323,8 @@ LGraphCanvas.prototype.drawFrontCanvas = function() //this.dirty_area = null; } - if(ctx.finish) //this is a function I use in webgl renderer - ctx.finish(); + if(ctx.finish2D) //this is a function I use in webgl renderer + ctx.finish2D(); this.dirty_canvas = false; } @@ -4058,11 +4082,11 @@ LGraphCanvas.onMenuNodeInputs = function(node, e, prev_menu) var entries = []; for (var i in options) { - var option = options[i]; - var label = option[0]; - if(option[2] && option[2].label) - label = option[2].label; - entries.push({content: label, value: option}); + var entry = options[i]; + var label = entry[0]; + if(entry[2] && entry[2].label) + label = entry[2].label; + entries.push({content: label, value: entry}); } var menu = LiteGraph.createContextualMenu(entries, {event: e, callback: inner_clicked, from: prev_menu}); } @@ -4088,9 +4112,13 @@ LGraphCanvas.onMenuNodeOutputs = function(node, e, prev_menu) var entries = []; for (var i in options) { - if(node.findOutputSlot(options[i][0]) != -1) + var entry = options[i]; + if(node.findOutputSlot(entry[0]) != -1) continue; //skip the ones already on - entries.push({content: options[i][0], value: options[i]}); + var label = entry[0]; + if(entry[2] && entry[2].label) + label = entry[2].label; + entries.push({content: label, value: entry}); } if(entries.length) var menu = LiteGraph.createContextualMenu(entries, {event: e, callback: inner_clicked, from: prev_menu}); @@ -4098,7 +4126,8 @@ LGraphCanvas.onMenuNodeOutputs = function(node, e, prev_menu) function inner_clicked(v) { - if(!node) return; + if(!node) + return; var value = v.value[1]; @@ -4111,7 +4140,7 @@ LGraphCanvas.onMenuNodeOutputs = function(node, e, prev_menu) return false; } else - node.addOutput(v.value[0],v.value[1]); + node.addOutput(v.value[0], v.value[1], v.value[2]); } return false; @@ -4424,7 +4453,7 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) LiteGraph.closeAllContextualMenus(); var root = ref_window.document.createElement("div"); - root.className = "litecontextualmenu litemenubar-panel"; + root.className = "graphcontextualmenu graphmenubar-panel"; this.root = root; var style = root.style; @@ -4446,11 +4475,11 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) { var item = values[i]; var element = ref_window.document.createElement("div"); - element.className = "litemenu-entry"; + element.className = "graphmenu-entry"; if(item == null) { - element.className = "litemenu-entry separator"; + element.className = "graphmenu-entry separator"; root.appendChild(element); continue; } @@ -4533,7 +4562,7 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) if(options.callback) { var ret = options.callback.call(root, this.data, e ); - if( ret != undefined ) close = ret; + if( ret !== undefined ) close = ret; } if(close) @@ -4558,7 +4587,7 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) LiteGraph.closeAllContextualMenus = function() { - var elements = document.querySelectorAll(".litecontextualmenu"); + var elements = document.querySelectorAll(".graphcontextualmenu"); if(!elements.length) return; var result = []; @@ -4954,210 +4983,34 @@ Watch.prototype.onDrawBackground = function(ctx) if (this.properties["value"].constructor === Number ) this.inputs[0].label = this.properties["value"].toFixed(3); else - this.inputs[0].label = this.properties["value"]; + { + var str = this.properties["value"]; + if(str && str.length) //convert typed to array + str = Array.prototype.slice.call(str).join(","); + this.inputs[0].label = str; + } } } LiteGraph.registerNodeType("basic/watch", Watch); +//Show value inside the debug console +function Console() +{ + this.size = [60,20]; + this.addInput("data",0); +} -/* -LiteGraph.registerNodeType("math/sinusoid",{ - title: "Sin", - desc: "Sinusoidal value generator", - bgImageUrl: "nodes/imgs/icon-sin.png", +Console.title = "Console"; +Console.desc = "Show value inside the console"; - inputs: [["f",'number'],["q",'number'],["a",'number'],["t",'number']], - outputs: [["",'number']], - properties: {amplitude:1.0, freq: 1, phase:0}, +Console.prototype.onExecute = function() +{ + console.log( this.getInputData(0) ); +} - onExecute: function() - { - var f = this.getInputData(0); - if(f != null) - this.properties["freq"] = f; - - var q = this.getInputData(1); - if(q != null) - this.properties["phase"] = q; - - var a = this.getInputData(2); - if(a != null) - this.properties["amplitude"] = a; - - var t = this.graph.getFixedTime(); - if(this.getInputData(3) != null) - t = this.getInputData(3); - // t = t/(2*Math.PI); t = (t-Math.floor(t))*(2*Math.PI); - - var v = this.properties["amplitude"] * Math.sin((2*Math.PI) * t * this.properties["freq"] + this.properties["phase"]); - this.setOutputData(0, v ); - }, - - onDragBackground: function(ctx) - { - this.boxcolor = colorToString(v > 0 ? [0.5,0.8,1,0.5] : [0,0,0,0.5]); - this.setDirtyCanvas(true); - }, -}); -*/ - -/* -LiteGraph.registerNodeType("basic/number",{ - title: "Number", - -// System vars ********************************* - -LiteGraph.registerNodeType("session/info",{ - title: "Time", - desc: "Seconds since start", - - outputs: [["secs",'number']], - properties: {scale:1.0}, - onExecute: function() - { - this.setOutputData(0, this.session.getTime() * this.properties.scale); - } -}); - -LiteGraph.registerNodeType("system/fixedtime",{ - title: "F.Time", - desc: "Constant time value", - - outputs: [["secs",'number']], - properties: {scale:1.0}, - onExecute: function() - { - this.setOutputData(0, this.session.getFixedTime() * this.properties.scale); - } -}); - - -LiteGraph.registerNodeType("system/elapsedtime",{ - title: "Elapsed", - desc: "Seconds elapsed since last execution", - - outputs: [["secs",'number']], - properties: {scale:1.0}, - onExecute: function() - { - this.setOutputData(0, this.session.getElapsedTime() * this.properties.scale); - } -}); - -LiteGraph.registerNodeType("system/iterations",{ - title: "Iterations", - desc: "Number of iterations (executions)", - - outputs: [["",'number']], - onExecute: function() - { - this.setOutputData(0, this.session.iterations ); - } -}); - -LiteGraph.registerNodeType("system/trace",{ - desc: "Outputs input to browser's console", - - inputs: [["",0]], - onExecute: function() - { - var data = this.getInputData(0); - if(data) - trace("DATA: "+data); - } -}); - -/* -LiteGraph.registerNodeType("math/not",{ - title: "Not", - desc: "0 -> 1 or 0 -> 1", - inputs: [["A",'number']], - outputs: [["!A",'number']], - size: [60,22], - onExecute: function() - { - var v = this.getInputData(0); - if(v != null) - this.setOutputData(0, v ? 0 : 1); - } -}); - - - -// Nodes for network in and out -LiteGraph.registerNodeType("network/general/network_input",{ - title: "N.Input", - desc: "Network Input", - outputs: [["",0]], - color: "#00ff96", - bgcolor: "#004327", - - setValue: function(v) - { - this.value = v; - }, - - onExecute: function() - { - this.setOutputData(0, this.value); - } -}); - -LiteGraph.registerNodeType("network/general/network_output",{ - title: "N.Output", - desc: "Network output", - inputs: [["",0]], - color: "#a8ff00", - bgcolor: "#293e00", - - properties: {value:null}, - - getValue: function() - { - return this.value; - }, - - onExecute: function() - { - this.value = this.getOutputData(0); - } -}); - -LiteGraph.registerNodeType("network/network_trigger",{ - title: "N.Trigger", - desc: "Network input trigger", - outputs: [["",0]], - color: "#ff9000", - bgcolor: "#522e00", - - onTrigger: function(v) - { - this.triggerOutput(0,v); - }, -}); - -LiteGraph.registerNodeType("network/network_callback",{ - title: "N.Callback", - desc: "Network callback output.", - outputs: [["",0]], - color: "#6A6", - bgcolor: "#363", - - setTrigger: function(func) - { - this.callback = func; - }, - - onTrigger: function(v) - { - if(this.callback) - this.callback(v); - }, -}); - -*/ +LiteGraph.registerNodeType("basic/console", Console ); })(); @@ -5898,6 +5751,16 @@ MathRand.desc = "Random number"; MathRand.prototype.onExecute = function() { + if(this.inputs) + for(var i = 0; 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 min = this.properties.min; var max = this.properties.max; this._last_v = Math.random() * (max-min) + min; @@ -5913,6 +5776,10 @@ MathRand.prototype.onDrawBackground = function(ctx) this.outputs[0].label = "?"; } +MathRand.prototype.onGetInputs = function() { + return [["min","number"],["max","number"]]; +} + LiteGraph.registerNodeType("math/rand", MathRand); //Math clamp @@ -6039,18 +5906,19 @@ function MathOperation() { this.addInput("A","number"); this.addInput("B","number"); - this.addOutput("A+B","number"); - this.properties = {A:1.0, B:1.0}; + this.addOutput("=","number"); + this.properties = {A:1.0, B:1.0, OP:"+"}; } MathOperation.title = "Operation"; MathOperation.desc = "Easy math operators"; +MathOperation["@OP"] = { type:"enum", title: "operation", values:["+","-","*","/","%","^"]}; + MathOperation.prototype.setValue = function(v) { if( typeof(v) == "string") v = parseFloat(v); this.properties["value"] = v; - this.setDirtyCanvas(true); } MathOperation.prototype.onExecute = function() @@ -6067,42 +5935,36 @@ MathOperation.prototype.onExecute = function() else B = this.properties["B"]; - for(var i = 0, l = this.outputs.length; i < l; ++i) + var result = 0; + switch(this.properties.OP) { - var output = this.outputs[i]; - if(!output.links || !output.links.length) - continue; - var value = 0; - switch( output.name ) - { - case "A+B": value = A+B; break; - case "A-B": value = A-B; break; - case "A*B": value = A*B; break; - case "A/B": value = A/B; break; - } - this.setOutputData(i, value ); + case '+': result = A+B; break; + case '-': result = A-B; break; + case '/': result = A/B; break; + case '%': result = A%B; break; + case '^': result = Math.pow(A,B); break; } + this.setOutputData(0, result ); } -MathOperation.prototype.onGetOutputs = function() +MathOperation.prototype.onDrawBackground = function(ctx) { - return [["A-B","number"],["A*B","number"],["A/B","number"]]; + this.outputs[0].label = "A" + this.properties.OP + "B"; } LiteGraph.registerNodeType("math/operation", MathOperation ); - + //Math compare function MathCompare() { - this.addInputs( "A","number" ); - this.addInputs( "B","number" ); - this.addOutputs("A==B","number"); - this.addOutputs("A!=B","number"); + this.addInput( "A","number" ); + this.addInput( "B","number" ); + this.addOutput("A==B","boolean"); + this.addOutput("A!=B","boolean"); this.properties = {A:0,B:0}; } - MathCompare.title = "Compare"; MathCompare.desc = "compares between two values"; @@ -6110,12 +5972,12 @@ MathCompare.prototype.onExecute = function() { var A = this.getInputData(0); var B = this.getInputData(1); - if(A!=null) + if(A !== undefined) this.properties["A"] = A; else A = this.properties["A"]; - if(B!=null) + if(B !== undefined) this.properties["B"] = B; else B = this.properties["B"]; @@ -6140,11 +6002,56 @@ MathCompare.prototype.onExecute = function() MathCompare.prototype.onGetOutputs = function() { - return [["A==B","number"],["A!=B","number"],["A>B","number"],["A=B","number"],["A<=B","number"]]; + return [["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]; } LiteGraph.registerNodeType("math/compare",MathCompare); +function MathCondition() +{ + this.addInput("A","number"); + this.addInput("B","number"); + this.addOutput("out","boolean"); + this.properties = { A:0, B:1, OP:">" }; + this.size = [60,40]; +} + +MathCondition["@OP"] = { type:"enum", title: "operation", values:[">","<","==","!=","<=",">="]}; + +MathCondition.title = "Condition"; +MathCondition.desc = "evaluates condition between A and B"; + +MathCondition.prototype.onExecute = function() +{ + var A = this.getInputData(0); + if(A === undefined) + A = this.properties.A; + else + this.properties.A = A; + + var B = this.getInputData(1); + if(B === undefined) + B = this.properties.B; + else + this.properties.B = B; + + var result = true; + switch(this.properties.OP) + { + case ">": result = A>B; break; + case "<": result = A=": result = A>=B; break; + } + + this.setOutputData(0, result ); +} + +LiteGraph.registerNodeType("math/condition", MathCondition); + + function MathAccumulate() { this.addInput("inc","number"); @@ -6400,6 +6307,44 @@ if(window.glMatrix) } //glMatrix })(); +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); + + (function(){ @@ -7116,7 +7061,6 @@ if(typeof(LiteGraph) != "undefined") LGraphTexture.widgets_info = {"name": { widget:"texture"} }; //REPLACE THIS TO INTEGRATE WITH YOUR FRAMEWORK - LGraphTexture.textures_container = {}; //where to seek for the textures, if not specified it uses gl.textures LGraphTexture.loadTextureCallback = null; //function in charge of loading textures when not present in the container LGraphTexture.image_preview_size = 256; @@ -7137,9 +7081,31 @@ if(typeof(LiteGraph) != "undefined") "default": LGraphTexture.DEFAULT }; + //returns the container where all the loaded textures are stored (overwrite if you have a Resources Manager) + LGraphTexture.getTexturesContainer = function() + { + return gl.textures; + } + + //process the loading of a texture (overwrite if you have a Resources Manager) + LGraphTexture.loadTexture = function(name, options) + { + options = options || {}; + var url = name; + if(url.substr(0,7) == "http://") + { + if(LiteGraph.proxy) //proxy external files + url = LiteGraph.proxy + url.substr(7); + } + + var container = LGraphTexture.getTexturesContainer(); + var tex = container[ name ] = GL.Texture.fromURL(url, options); + return tex; + } + LGraphTexture.getTexture = function(name) { - var container = LGraphTexture.textures_container || gl.textures; + var container = this.getTexturesContainer(); if(!container) throw("Cannot load texture, container of textures not found"); @@ -7147,25 +7113,8 @@ if(typeof(LiteGraph) != "undefined") var tex = container[ name ]; if(!tex && name && name[0] != ":") { - //texture must be loaded - if(LGraphTexture.loadTextureCallback) - { - //calls the method in charge of loading resources (in LiteScene would be ResourcesManager.load) - var loader = LGraphTexture.loadTextureCallback; - if(loader) - loader( name ); - return null; - } - else - { - var url = name; - if(url.substr(0,7) == "http://") - { - if(LiteGraph.proxy) //proxy external files - url = LiteGraph.proxy + url.substr(7); - } - tex = container[ name ] = GL.Texture.fromURL(url, {}); - } + this.loadTexture(name); + return null; } return tex; @@ -7358,7 +7307,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/texture", LGraphTexture ); - window.LGraphTexture = LGraphTexture; //************************** function LGraphTexturePreview() @@ -7397,7 +7345,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/preview", LGraphTexturePreview ); - window.LGraphTexturePreview = LGraphTexturePreview; //************************************** @@ -7417,13 +7364,15 @@ if(typeof(LiteGraph) != "undefined") if(!tex) return; if(this.properties.name) - LGraphTexture.textures_container[ this.properties.name ] = tex; + { + var container = LGraphTexture.getTexturesContainer(); + container[ this.properties.name ] = tex; + } this.setOutputData(0, tex); } LiteGraph.registerNodeType("texture/save", LGraphTextureSave ); - window.LGraphTextureSave = LGraphTextureSave; //**************************************************** @@ -7608,7 +7557,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/operation", LGraphTextureOperation ); - window.LGraphTextureOperation = LGraphTextureOperation; //**************************************************** @@ -7698,7 +7646,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/shader", LGraphTextureShader ); - window.LGraphTextureShader = LGraphTextureShader; // Texture to Viewport ***************************************** function LGraphTextureToViewport() @@ -7802,7 +7749,6 @@ if(typeof(LiteGraph) != "undefined") LiteGraph.registerNodeType("texture/toviewport", LGraphTextureToViewport ); - window.LGraphTextureToViewport = LGraphTextureToViewport; // Texture Copy ***************************************** @@ -7868,7 +7814,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/copy", LGraphTextureCopy ); - window.LGraphTextureCopy = LGraphTextureCopy; // Texture Copy ***************************************** @@ -7880,7 +7825,7 @@ if(typeof(LiteGraph) != "undefined") } LGraphTextureAverage.title = "Average"; - LGraphTextureAverage.desc = "Compute average of a texture and stores it as a texture"; + LGraphTextureAverage.desc = "Compute the total average of a texture and stores it as a 1x1 pixel texture"; LGraphTextureAverage.prototype.onExecute = function() { @@ -7929,7 +7874,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/average", LGraphTextureAverage ); - window.LGraphTextureAverage = LGraphTextureAverage; // Image To Texture ***************************************** function LGraphImageToTexture() @@ -7977,7 +7921,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/imageToTexture", LGraphImageToTexture ); - window.LGraphImageToTexture = LGraphImageToTexture; // Texture LUT ***************************************** @@ -8070,7 +8013,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/LUT", LGraphTextureLUT ); - window.LGraphTextureLUT = LGraphTextureLUT; // Texture Channels ***************************************** function LGraphTextureChannels() @@ -8146,7 +8088,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/textureChannels", LGraphTextureChannels ); - window.LGraphTextureChannels = LGraphTextureChannels; // Texture Channels to Texture ***************************************** @@ -8213,7 +8154,98 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/channelsTexture", LGraphChannelsTexture ); - window.LGraphChannelsTexture = LGraphChannelsTexture; + + // Texture Channels to Texture ***************************************** + function LGraphTextureGradient() + { + this.addInput("A","color"); + this.addInput("B","color"); + this.addOutput("Texture","Texture"); + + this.properties = { angle: 0, scale: 1, A:[0,0,0], B:[1,1,1], texture_size:32 }; + if(!LGraphTextureGradient._shader) + LGraphTextureGradient._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphTextureGradient.pixel_shader ); + + this._uniforms = { u_angle: 0, u_colorA: vec3.create(), u_colorB: vec3.create()}; + } + + LGraphTextureGradient.title = "Gradient"; + LGraphTextureGradient.desc = "Generates a gradient"; + LGraphTextureGradient["@A"] = { type:"color" }; + LGraphTextureGradient["@B"] = { type:"color" }; + LGraphTextureGradient["@texture_size"] = { type:"enum", values:[32,64,128,256,512] }; + + LGraphTextureGradient.prototype.onExecute = function() + { + gl.disable( gl.BLEND ); + gl.disable( gl.DEPTH_TEST ); + + var mesh = GL.Mesh.getScreenQuad(); + var shader = LGraphTextureGradient._shader; + + var A = this.getInputData(0); + if(!A) + A = this.properties.A; + var B = this.getInputData(1); + if(!B) + B = this.properties.B; + + //angle and scale + for(var i = 2; 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 uniforms = this._uniforms; + this._uniforms.u_angle = this.properties.angle * DEG2RAD; + this._uniforms.u_scale = this.properties.scale; + vec3.copy( uniforms.u_colorA, A ); + vec3.copy( uniforms.u_colorB, B ); + + var size = parseInt( this.properties.texture_size ); + if(!this._tex || this._tex.width != size ) + this._tex = new GL.Texture( size, size, { format: gl.RGB, filter: gl.LINEAR }); + + this._tex.drawTo( function() { + shader.uniforms(uniforms).draw(mesh); + }); + this.setOutputData(0, this._tex); + } + + LGraphTextureGradient.prototype.onGetInputs = function() + { + return [["angle","number"],["scale","number"]]; + } + + LGraphTextureGradient.pixel_shader = "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform float u_angle;\n\ + uniform float u_scale;\n\ + uniform vec3 u_colorA;\n\ + uniform vec3 u_colorB;\n\ + \n\ + vec2 rotate(vec2 v, float angle)\n\ + {\n\ + vec2 result;\n\ + float _cos = cos(angle);\n\ + float _sin = sin(angle);\n\ + result.x = v.x * _cos - v.y * _sin;\n\ + result.y = v.x * _sin + v.y * _cos;\n\ + return result;\n\ + }\n\ + void main() {\n\ + float f = (rotate(u_scale * (v_coord - vec2(0.5)), u_angle) + vec2(0.5)).x;\n\ + vec3 color = mix(u_colorA,u_colorB,clamp(f,0.0,1.0));\n\ + gl_FragColor = vec4(color,1.0);\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/gradient", LGraphTextureGradient ); // Texture Mix ***************************************** function LGraphTextureMix() @@ -8281,7 +8313,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/mix", LGraphTextureMix ); - window.LGraphTextureMix = LGraphTextureMix; // Texture Edges detection ***************************************** function LGraphTextureEdges() @@ -8352,7 +8383,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/edges", LGraphTextureEdges ); - window.LGraphTextureEdges = LGraphTextureEdges; // Texture Depth ***************************************** function LGraphTextureDepthRange() @@ -8402,11 +8432,14 @@ if(typeof(LiteGraph) != "undefined") gl.disable( gl.DEPTH_TEST ); var mesh = Mesh.getScreenQuad(); var shader = LGraphTextureDepthRange._shader; + + //TODO: this asumes we have LiteScene, change it var camera = Renderer._current_camera; + var planes = [Renderer._current_camera.near,Renderer._current_camera.far]; this._temp_texture.drawTo( function() { tex.bind(0); - shader.uniforms({u_texture:0, u_distance: distance, u_range: range, u_camera_planes: [Renderer._current_camera.near,Renderer._current_camera.far] }) + shader.uniforms({u_texture:0, u_distance: distance, u_range: range, u_camera_planes: planes }) .draw(mesh); }); @@ -8438,7 +8471,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/depth_range", LGraphTextureDepthRange ); - window.LGraphTextureDepthRange = LGraphTextureDepthRange; // Texture Blur ***************************************** function LGraphTextureBlur() @@ -8552,13 +8584,12 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/blur", LGraphTextureBlur ); - window.LGraphTextureBlur = LGraphTextureBlur; // Texture Webcam ***************************************** function LGraphTextureWebcam() { this.addOutput("Webcam","Texture"); - this.properties = {}; + this.properties = { texture_name: "" }; } LGraphTextureWebcam.title = "Webcam"; @@ -8659,14 +8690,20 @@ if(typeof(LiteGraph) != "undefined") this._temp_texture = new GL.Texture( width, height, { format: gl.RGB, filter: gl.LINEAR }); this._temp_texture.uploadImage( this._video ); + + if(this.properties.texture_name) + { + var container = LGraphTexture.getTexturesContainer(); + container[ this.properties.texture_name ] = this._temp_texture; + } + this.setOutputData(0,this._temp_texture); } LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam ); - window.LGraphTextureWebcam = LGraphTextureWebcam; - + //Cubemap reader function LGraphCubemap() { this.addOutput("Cubemap","Cubemap"); @@ -8726,8 +8763,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/cubemap", LGraphCubemap ); - window.LGraphCubemap = LGraphCubemap; - } //litegl.js defined //Works with Litegl.js to create WebGL nodes diff --git a/build/litegraph.min.js b/build/litegraph.min.js index 17ebb532b..c5d43fe60 100644 --- a/build/litegraph.min.js +++ b/build/litegraph.min.js @@ -1,23 +1,23 @@ -var LiteGraph={NODE_TITLE_HEIGHT:16,NODE_SLOT_HEIGHT:15,NODE_WIDTH:140,NODE_MIN_WIDTH:50,NODE_COLLAPSED_RADIUS:10,NODE_COLLAPSED_WIDTH:80,CANVAS_GRID_SIZE:10,NODE_TITLE_COLOR:"#222",NODE_DEFAULT_COLOR:"#999",NODE_DEFAULT_BGCOLOR:"#444",NODE_DEFAULT_BOXCOLOR:"#AEF",NODE_DEFAULT_SHAPE:"box",MAX_NUMBER_OF_NODES:1E3,DEFAULT_POSITION:[100,100],node_images_path:"",proxy:null,debug:!1,throw_errors:!0,registered_node_types:{},registerNodeType:function(a,b){if(!b.prototype)throw"Cannot register a simple object, it must be a class with a prototype"; -b.type=a;LiteGraph.debug&&console.log("Node registered: "+a);a.split("/");var c=a.lastIndexOf("/");b.category=a.substr(0,c);if(b.prototype)for(var d in LGraphNode.prototype)b.prototype[d]||(b.prototype[d]=LGraphNode.prototype[d]);this.registered_node_types[a]=b},createNode:function(a,b,c){var d=this.registered_node_types[a];if(!d)return LiteGraph.debug&&console.log('GraphNode type "'+a+'" not registered.'),null;b=b||d.title||a;d=new d(name);d.type=a;d.title||(d.title=b);d.properties||(d.properties= -{});d.flags||(d.flags={});d.size||(d.size=d.computeSize());d.pos||(d.pos=LiteGraph.DEFAULT_POSITION.concat());if(c)for(var e in c)d[e]=c[e];return d},getNodeType:function(a){return this.registered_node_types[a]},getNodeTypesInCategory:function(a){var b=[],c;for(c in this.registered_node_types)""==a?null==this.registered_node_types[c].category&&b.push(this.registered_node_types[c]):this.registered_node_types[c].category==a&&b.push(this.registered_node_types[c]);return b},getNodeTypesCategories:function(){var a= -{"":1},b;for(b in this.registered_node_types)this.registered_node_types[b].category&&!this.registered_node_types[b].skip_list&&(a[this.registered_node_types[b].category]=1);var c=[];for(b in a)c.push(b);return c},reloadNodes:function(a){var b=document.getElementsByTagName("script"),c=[],d;for(d in b)c.push(b[d]);b=document.getElementsByTagName("head")[0];a=document.location.href+a;for(d in c){var e=c[d].src;if(e&&e.substr(0,a.length)==a)try{LiteGraph.debug&&console.log("Reloading: "+e);var f=document.createElement("script"); -f.type="text/javascript";f.src=e;b.appendChild(f);b.removeChild(c[d])}catch(g){if(LiteGraph.throw_errors)throw g;LiteGraph.debug&&console.log("Error while reloading "+e)}}LiteGraph.debug&&console.log("Nodes reloaded")},cloneObject:function(a,b){if(null==a)return null;var c=JSON.parse(JSON.stringify(a));if(!b)return c;for(var d in c)b[d]=c[d];return b}};LiteGraph.getTime="undefined"!=typeof performance?function(){return performance.now()}:function(){return Date.now()}; -function LGraph(){LiteGraph.debug&&console.log("Graph created");this.list_of_graphcanvas=null;this.clear()}LGraph.supported_types=["number","string","boolean"];LGraph.prototype.getSupportedTypes=function(){return this.supported_types||LGraph.supported_types};LGraph.STATUS_STOPPED=1;LGraph.STATUS_RUNNING=2; +var LiteGraph={NODE_TITLE_HEIGHT:16,NODE_SLOT_HEIGHT:15,NODE_WIDTH:140,NODE_MIN_WIDTH:50,NODE_COLLAPSED_RADIUS:10,NODE_COLLAPSED_WIDTH:80,CANVAS_GRID_SIZE:10,NODE_TITLE_COLOR:"#222",NODE_DEFAULT_COLOR:"#999",NODE_DEFAULT_BGCOLOR:"#444",NODE_DEFAULT_BOXCOLOR:"#AEF",NODE_DEFAULT_SHAPE:"box",MAX_NUMBER_OF_NODES:1E3,DEFAULT_POSITION:[100,100],node_images_path:"",proxy:null,debug:!1,throw_errors:!0,registered_node_types:{},Nodes:{},registerNodeType:function(a,b){if(!b.prototype)throw"Cannot register a simple object, it must be a class with a prototype"; +b.type=a;LiteGraph.debug&&console.log("Node registered: "+a);a.split("/");var c=a.lastIndexOf("/");b.category=a.substr(0,c);if(b.prototype)for(var d in LGraphNode.prototype)b.prototype[d]||(b.prototype[d]=LGraphNode.prototype[d]);this.registered_node_types[a]=b;b.constructor.name&&(this.Nodes[b.constructor.name]=b)},createNode:function(a,b,c){var d=this.registered_node_types[a];if(!d)return LiteGraph.debug&&console.log('GraphNode type "'+a+'" not registered.'),null;b=b||d.title||a;d=new d(name);d.type= +a;d.title||(d.title=b);d.properties||(d.properties={});d.flags||(d.flags={});d.size||(d.size=d.computeSize());d.pos||(d.pos=LiteGraph.DEFAULT_POSITION.concat());if(c)for(var e in c)d[e]=c[e];return d},getNodeType:function(a){return this.registered_node_types[a]},getNodeTypesInCategory:function(a){var b=[],c;for(c in this.registered_node_types)""==a?null==this.registered_node_types[c].category&&b.push(this.registered_node_types[c]):this.registered_node_types[c].category==a&&b.push(this.registered_node_types[c]); +return b},getNodeTypesCategories:function(){var a={"":1},b;for(b in this.registered_node_types)this.registered_node_types[b].category&&!this.registered_node_types[b].skip_list&&(a[this.registered_node_types[b].category]=1);var c=[];for(b in a)c.push(b);return c},reloadNodes:function(a){var b=document.getElementsByTagName("script"),c=[],d;for(d in b)c.push(b[d]);b=document.getElementsByTagName("head")[0];a=document.location.href+a;for(d in c){var e=c[d].src;if(e&&e.substr(0,a.length)==a)try{LiteGraph.debug&& +console.log("Reloading: "+e);var f=document.createElement("script");f.type="text/javascript";f.src=e;b.appendChild(f);b.removeChild(c[d])}catch(g){if(LiteGraph.throw_errors)throw g;LiteGraph.debug&&console.log("Error while reloading "+e)}}LiteGraph.debug&&console.log("Nodes reloaded")},cloneObject:function(a,b){if(null==a)return null;var c=JSON.parse(JSON.stringify(a));if(!b)return c;for(var d in c)b[d]=c[d];return b}}; +LiteGraph.getTime="undefined"!=typeof performance?function(){return performance.now()}:function(){return Date.now()};function LGraph(){LiteGraph.debug&&console.log("Graph created");this.list_of_graphcanvas=null;this.clear()}LGraph.supported_types=["number","string","boolean"];LGraph.prototype.getSupportedTypes=function(){return this.supported_types||LGraph.supported_types};LGraph.STATUS_STOPPED=1;LGraph.STATUS_RUNNING=2; LGraph.prototype.clear=function(){this.stop();this.status=LGraph.STATUS_STOPPED;this.last_node_id=0;this._nodes=[];this._nodes_by_id={};this.last_link_id=0;this.links={};this.iteration=0;this.config={};this.fixedtime=this.runningtime=this.globaltime=0;this.elapsed_time=this.fixedtime_lapse=0.01;this.starttime=0;this.global_inputs={};this.global_outputs={};this.debug=!0;this.change();this.sendActionToCanvas("clear")}; LGraph.prototype.attachCanvas=function(a){if(a.constructor!=LGraphCanvas)throw"attachCanvas expects a LGraphCanvas instance";a.graph&&a.graph!=this&&a.graph.detachCanvas(a);a.graph=this;this.list_of_graphcanvas||(this.list_of_graphcanvas=[]);this.list_of_graphcanvas.push(a)};LGraph.prototype.detachCanvas=function(a){var b=this.list_of_graphcanvas.indexOf(a);-1!=b&&(a.graph=null,this.list_of_graphcanvas.splice(b,1))}; LGraph.prototype.start=function(a){if(this.status!=LGraph.STATUS_RUNNING){this.status=LGraph.STATUS_RUNNING;if(this.onPlayEvent)this.onPlayEvent();this.sendEventToAllNodes("onStart");this.starttime=LiteGraph.getTime();var b=this;this.execution_timer_id=setInterval(function(){b.runStep(1)},a||1)}}; LGraph.prototype.stop=function(){if(this.status!=LGraph.STATUS_STOPPED){this.status=LGraph.STATUS_STOPPED;if(this.onStopEvent)this.onStopEvent();null!=this.execution_timer_id&&clearInterval(this.execution_timer_id);this.execution_timer_id=null;this.sendEventToAllNodes("onStop")}}; LGraph.prototype.runStep=function(a){a=a||1;var b=LiteGraph.getTime();this.globaltime=0.001*(b-this.starttime);try{for(var c=0;c=LiteGraph.MAX_NUMBER_OF_NODES)throw"LiteGraph: max number of nodes in a graph reached";if(null==a.id||-1==a.id)a.id=this.last_node_id++;a.graph=this;this._nodes.push(a);this._nodes_by_id[a.id]=a;if(a.onAdded)a.onAdded();this.config.align_to_grid&&a.alignToGrid();b||this.updateExecutionOrder();if(this.onNodeAdded)this.onNodeAdded(a);this.setDirtyCanvas(!0);this.change();return a}}; LGraph.prototype.remove=function(a){if(null!=this._nodes_by_id[a.id]&&!a.ignore_remove){if(a.inputs)for(var b=0;b -LiteGraph.getTime()-this.last_mouseclick&&this.selected_nodes[c.id]){if(c.onDblClick)c.onDblClick(a);this.processNodeDblClicked(c);e=!0}c.onMouseDown&&c.onMouseDown(a)?e=!0:this.live_mode&&(e=d=!0);e||(this.allow_dragnodes&&(this.node_dragged=c),this.selected_nodes[c.id]||this.processNodeSelected(c,a));this.dirty_canvas=!0}}else d=!0;d&&this.allow_dragcanvas&&(this.dragging_canvas=!0)}else 2!=a.which&&3==a.which&&this.processContextualMenu(c,a);this.last_mouse[0]=a.localX;this.last_mouse[1]=a.localY; -this.last_mouseclick=LiteGraph.getTime();this.canvas_mouse=[a.canvasX,a.canvasY];this.graph.change();(!b.document.activeElement||"input"!=b.document.activeElement.nodeName.toLowerCase()&&"textarea"!=b.document.activeElement.nodeName.toLowerCase())&&a.preventDefault();a.stopPropagation();return!1}}; +for(e in d)this.processNodeDeselected(d[e])}d=!1;if(c){this.live_mode||c.flags.pinned||this.bringToFront(c);var f=!1;if(!this.connecting_node&&!c.flags.collapsed&&!this.live_mode){if(c.outputs){e=0;for(var g=c.outputs.length;eLiteGraph.getTime()-this.last_mouseclick&&this.selected_nodes[c.id]){if(c.onDblClick)c.onDblClick(a);this.processNodeDblClicked(c);e=!0}c.onMouseDown&&c.onMouseDown(a)?e=!0:this.live_mode&&(e=d=!0);e||(this.allow_dragnodes&&(this.node_dragged=c),this.selected_nodes[c.id]||this.processNodeSelected(c,a));this.dirty_canvas=!0}}else d=!0;d&&this.allow_dragcanvas&&(this.dragging_canvas=!0)}else 2!=a.which&&3==a.which&&this.processContextualMenu(c,a);this.last_mouse[0]=a.localX;this.last_mouse[1]= +a.localY;this.last_mouseclick=LiteGraph.getTime();this.canvas_mouse=[a.canvasX,a.canvasY];this.graph.change();(!b.document.activeElement||"input"!=b.document.activeElement.nodeName.toLowerCase()&&"textarea"!=b.document.activeElement.nodeName.toLowerCase())&&a.preventDefault();a.stopPropagation();return!1}}; LGraphCanvas.prototype.processMouseMove=function(a){if(this.graph){this.adjustMouseEvent(a);var b=[a.localX,a.localY],c=[b[0]-this.last_mouse[0],b[1]-this.last_mouse[1]];this.last_mouse=b;this.canvas_mouse=[a.canvasX,a.canvasY];if(this.dragging_canvas)this.offset[0]+=c[0]/this.scale,this.offset[1]+=c[1]/this.scale,this.dirty_bgcanvas=this.dirty_canvas=!0;else{this.connecting_node&&(this.dirty_canvas=!0);var b=this.graph.getNodeOnPos(a.canvasX,a.canvasY,this.visible_nodes),d;for(d in this.graph._nodes)if(this.graph._nodes[d].mouseOver&& b!=this.graph._nodes[d]){this.graph._nodes[d].mouseOver=!1;if(this.node_over&&this.node_over.onMouseLeave)this.node_over.onMouseLeave(a);this.node_over=null;this.dirty_canvas=!0}if(b){if(!b.mouseOver&&(b.mouseOver=!0,this.node_over=b,this.dirty_canvas=!0,b.onMouseEnter))b.onMouseEnter(a);if(b.onMouseMove)b.onMouseMove(a);if(this.connecting_node){var e=this._highlight_input||[0,0],f=this.isOverNodeInput(b,a.canvasX,a.canvasY,e);-1!=f&&b.inputs[f]?(f=b.inputs[f].type,f!=this.connecting_output.type&& f&&this.connecting_output.type||(this._highlight_input=e)):this._highlight_input=null}isInsideRectangle(a.canvasX,a.canvasY,b.pos[0]+b.size[0]-5,b.pos[1]+b.size[1]-5,5,5)?this.canvas.style.cursor="se-resize":this.canvas.style.cursor=null}else this.canvas.style.cursor=null;if(this.node_capturing_input&&this.node_capturing_input!=b&&this.node_capturing_input.onMouseMove)this.node_capturing_input.onMouseMove(a);if(this.node_dragged&&!this.live_mode){for(d in this.selected_nodes)b=this.selected_nodes[d], @@ -78,7 +78,7 @@ LGraphCanvas.prototype.processMouseUp=function(a){if(this.graph){var b=this.getC b,-1);else{var c=this.isOverNodeInput(b,a.canvasX,a.canvasY);-1!=c?this.connecting_node.connect(this.connecting_slot,b,c):(c=b.getInputInfo(0))&&!c.link&&c.type==this.connecting_output.type&&this.connecting_node.connect(this.connecting_slot,b,0)}this.connecting_node=this.connecting_pos=this.connecting_output=null;this.connecting_slot=-1}else if(this.resizing_node)this.dirty_bgcanvas=this.dirty_canvas=!0,this.resizing_node=null;else if(this.node_dragged)this.dirty_bgcanvas=this.dirty_canvas=!0,this.node_dragged.pos[0]= Math.round(this.node_dragged.pos[0]),this.node_dragged.pos[1]=Math.round(this.node_dragged.pos[1]),this.graph.config.align_to_grid&&this.node_dragged.alignToGrid(),this.node_dragged=null;else{this.dirty_canvas=!0;this.dragging_canvas=!1;if(this.node_over&&this.node_over.onMouseUp)this.node_over.onMouseUp(a);if(this.node_capturing_input&&this.node_capturing_input.onMouseUp)this.node_capturing_input.onMouseUp(a)}else 2==a.which?(this.dirty_canvas=!0,this.dragging_canvas=!1):3==a.which&&(this.dirty_canvas= !0,this.dragging_canvas=!1);this.graph.change();a.stopPropagation();a.preventDefault();return!1}};LGraphCanvas.prototype.isOverNodeInput=function(a,b,c,d){if(a.inputs)for(var e=0,f=a.inputs.length;eb&&(c*=1/1.1);this.setZoom(c,[a.localX,a.localY]);this.graph.change();a.preventDefault();return!1}}; LGraphCanvas.prototype.processNodeSelected=function(a,b){a.selected=!0;if(a.onSelected)a.onSelected();b&&b.shiftKey||(this.selected_nodes={});this.selected_nodes[a.id]=a;this.dirty_canvas=!0;if(this.onNodeSelected)this.onNodeSelected(a)};LGraphCanvas.prototype.processNodeDeselected=function(a){a.selected=!1;if(a.onDeselected)a.onDeselected();delete this.selected_nodes[a.id];if(this.onNodeDeselected)this.onNodeDeselected();this.dirty_canvas=!0}; LGraphCanvas.prototype.processNodeDblClicked=function(a){if(this.onShowNodePanel)this.onShowNodePanel(a);if(this.onNodeDblClicked)this.onNodeDblClicked(a);this.setDirty(!0)};LGraphCanvas.prototype.selectNode=function(a){this.deselectAllNodes();if(a){if(!a.selected&&a.onSelected)a.onSelected();a.selected=!0;this.selected_nodes[a.id]=a;this.setDirty(!0)}}; @@ -90,10 +90,10 @@ LGraphCanvas.prototype.convertOffsetToCanvas=function(a){return[a[0]/this.scale- LGraphCanvas.prototype.bringToFront=function(a){var b=this.graph._nodes.indexOf(a);-1!=b&&(this.graph._nodes.splice(b,1),this.graph._nodes.push(a))};LGraphCanvas.prototype.sendToBack=function(a){var b=this.graph._nodes.indexOf(a);-1!=b&&(this.graph._nodes.splice(b,1),this.graph._nodes.unshift(a))}; LGraphCanvas.prototype.computeVisibleNodes=function(){var a=[],b;for(b in this.graph._nodes){var c=this.graph._nodes[b];(!this.live_mode||c.onDrawBackground||c.onDrawForeground)&&overlapBounding(this.visible_area,c.getBounding())&&a.push(c)}return a}; LGraphCanvas.prototype.draw=function(a,b){var c=LiteGraph.getTime();this.render_time=0.001*(c-this.last_draw_time);this.last_draw_time=c;if(this.graph){var c=[-this.offset[0],-this.offset[1]],d=[c[0]+this.canvas.width/this.scale,c[1]+this.canvas.height/this.scale];this.visible_area=new Float32Array([c[0],c[1],d[0],d[1]])}(this.dirty_bgcanvas||b)&&this.drawBackCanvas();(this.dirty_canvas||a)&&this.drawFrontCanvas();this.fps=this.render_time?1/this.render_time:0;this.frame+=1}; -LGraphCanvas.prototype.drawFrontCanvas=function(){this.ctx||(this.ctx=this.bgcanvas.getContext("2d"));var a=this.ctx;if(a){a.start&&a.start();var b=this.canvas;a.restore();a.setTransform(1,0,0,1,0,0);this.dirty_area&&(a.save(),a.beginPath(),a.rect(this.dirty_area[0],this.dirty_area[1],this.dirty_area[2],this.dirty_area[3]),a.clip());a.clearRect(0,0,b.width,b.height);this.bgcanvas==this.canvas?this.drawBackCanvas():a.drawImage(this.bgcanvas,0,0);if(this.onRender)this.onRender(b,a);this.show_info&& +LGraphCanvas.prototype.drawFrontCanvas=function(){this.ctx||(this.ctx=this.bgcanvas.getContext("2d"));var a=this.ctx;if(a){a.start2D&&a.start2D();var b=this.canvas;a.restore();a.setTransform(1,0,0,1,0,0);this.dirty_area&&(a.save(),a.beginPath(),a.rect(this.dirty_area[0],this.dirty_area[1],this.dirty_area[2],this.dirty_area[3]),a.clip());a.clearRect(0,0,b.width,b.height);this.bgcanvas==this.canvas?this.drawBackCanvas():a.drawImage(this.bgcanvas,0,0);if(this.onRender)this.onRender(b,a);this.show_info&& (a.font="10px Arial",a.fillStyle="#888",this.graph?(a.fillText("T: "+this.graph.globaltime.toFixed(2)+"s",5,13),a.fillText("I: "+this.graph.iteration,5,26),a.fillText("F: "+this.frame,5,39),a.fillText("FPS:"+this.fps.toFixed(2),5,52)):a.fillText("No graph selected",5,13));if(this.graph){a.save();a.scale(this.scale,this.scale);a.translate(this.offset[0],this.offset[1]);this.visible_nodes=b=this.computeVisibleNodes();for(var c in b){var d=b[c];a.save();a.translate(d.pos[0],d.pos[1]);this.drawNode(d, a);a.restore()}this.graph.config.links_ontop&&(this.live_mode||this.drawConnections(a));null!=this.connecting_pos&&(a.lineWidth=this.connections_width,this.renderLink(a,this.connecting_pos,[this.canvas_mouse[0],this.canvas_mouse[1]],"node"==this.connecting_output.type?"#F85":"#AFA"),a.beginPath(),a.arc(this.connecting_pos[0],this.connecting_pos[1],4,0,2*Math.PI),a.fill(),a.fillStyle="#ffcc00",this._highlight_input&&(a.beginPath(),a.arc(this._highlight_input[0],this._highlight_input[1],6,0,2*Math.PI), -a.fill()));a.restore()}this.dirty_area&&a.restore();a.finish&&a.finish();this.dirty_canvas=!1}}; +a.fill()));a.restore()}this.dirty_area&&a.restore();a.finish2D&&a.finish2D();this.dirty_canvas=!1}}; LGraphCanvas.prototype.drawBackCanvas=function(){var a=this.bgcanvas;this.bgctx||(this.bgctx=this.bgcanvas.getContext("2d"));var b=this.bgctx;b.start&&b.start();b.clearRect(0,0,a.width,a.height);b.restore();b.setTransform(1,0,0,1,0,0);if(this.graph){b.save();b.scale(this.scale,this.scale);b.translate(this.offset[0],this.offset[1]);if(this.background_image&&0.5c&&0.01>b.editor_alpha&&(clearInterval(d),1>c&&(b.live_mode=!0));1"+e+""})}LiteGraph.createContextualMenu(d,{event:b,callback:function(b){a&&(b=LGraphCanvas.node_colors[b.value])&&(a.color=b.color,a.bgcolor=b.bgcolor,a.setDirtyCanvas(!0))},from:c});return!1}; LGraphCanvas.onMenuNodeShapes=function(a,b){LiteGraph.createContextualMenu(["box","round"],{event:b,callback:function(b){a&&(a.shape=b,a.setDirtyCanvas(!0))}});return!1};LGraphCanvas.onMenuNodeRemove=function(a){!1!=a.removable&&(a.graph.remove(a),a.setDirtyCanvas(!0,!0))};LGraphCanvas.onMenuNodeClone=function(a){if(!1!=a.clonable){var b=a.clone();b&&(b.pos=[a.pos[0]+5,a.pos[1]+5],a.graph.add(b),a.setDirtyCanvas(!0,!0))}}; LGraphCanvas.node_colors={red:{color:"#FAA",bgcolor:"#A44"},green:{color:"#AFA",bgcolor:"#4A4"},blue:{color:"#AAF",bgcolor:"#44A"},white:{color:"#FFF",bgcolor:"#AAA"}}; @@ -130,22 +130,23 @@ CanvasRenderingContext2D.prototype.roundRect=function(a,b,c,d,e,f){void 0===e&&( function distance(a,b){return Math.sqrt((b[0]-a[0])*(b[0]-a[0])+(b[1]-a[1])*(b[1]-a[1]))}function colorToString(a){return"rgba("+Math.round(255*a[0]).toFixed()+","+Math.round(255*a[1]).toFixed()+","+Math.round(255*a[2]).toFixed()+","+(4==a.length?a[3].toFixed(2):"1.0")+")"}function isInsideRectangle(a,b,c,d,e,f){return ca&&db?!0:!1}function growBounding(a,b,c){ba[2]&&(a[2]=b);ca[3]&&(a[3]=c)} function isInsideBounding(a,b){return a[0]b[1][0]||a[1]>b[1][1]?!1:!0}function overlapBounding(a,b){return a[0]>b[2]||a[1]>b[3]||a[2]f;f+=2)d="0123456789ABCDEF".indexOf(a.charAt(f)),e="0123456789ABCDEF".indexOf(a.charAt(f+1)),b[c]=16*d+e,c++;return b} function num2hex(a){for(var b="#",c,d,e=0;3>e;e++)c=a[e]/16,d=a[e]%16,b+="0123456789ABCDEF".charAt(c)+"0123456789ABCDEF".charAt(d);return b} -LiteGraph.createContextualMenu=function(a,b,c){function d(a){var c=!0;b.callback&&(a=b.callback.call(e,this.data,a),void 0!=a&&(c=a));c&&LiteGraph.closeAllContextualMenus()}this.options=b=b||{};c=c||window;b.from||LiteGraph.closeAllContextualMenus();var e=c.document.createElement("div");e.className="litecontextualmenu litemenubar-panel";this.root=e;var f=e.style;f.minWidth="100px";f.minHeight="20px";f.position="fixed";f.top="100px";f.left="100px";f.color="#AAF";f.padding="2px";f.borderBottom="2px solid #AAF"; -f.backgroundColor="#444";e.addEventListener("contextmenu",function(a){a.preventDefault();return!1});for(var g in a){var f=a[g],h=c.document.createElement("div");h.className="litemenu-entry";null==f?h.className="litemenu-entry separator":(f.is_menu&&(h.className+=" submenu"),f.disabled&&(h.className+=" disabled"),h.style.cursor="pointer",h.dataset.value="string"==typeof f?f:f.value,h.data=f,h.innerHTML="string"==typeof f?a.constructor==Array?a[g]:g:f.content?f.content:g,h.addEventListener("click", +LiteGraph.createContextualMenu=function(a,b,c){function d(a){var c=!0;b.callback&&(a=b.callback.call(e,this.data,a),void 0!==a&&(c=a));c&&LiteGraph.closeAllContextualMenus()}this.options=b=b||{};c=c||window;b.from||LiteGraph.closeAllContextualMenus();var e=c.document.createElement("div");e.className="graphcontextualmenu graphmenubar-panel";this.root=e;var f=e.style;f.minWidth="100px";f.minHeight="20px";f.position="fixed";f.top="100px";f.left="100px";f.color="#AAF";f.padding="2px";f.borderBottom="2px solid #AAF"; +f.backgroundColor="#444";e.addEventListener("contextmenu",function(a){a.preventDefault();return!1});for(var g in a){var f=a[g],h=c.document.createElement("div");h.className="graphmenu-entry";null==f?h.className="graphmenu-entry separator":(f.is_menu&&(h.className+=" submenu"),f.disabled&&(h.className+=" disabled"),h.style.cursor="pointer",h.dataset.value="string"==typeof f?f:f.value,h.data=f,h.innerHTML="string"==typeof f?a.constructor==Array?a[g]:g:f.content?f.content:g,h.addEventListener("click", d));e.appendChild(h)}e.addEventListener("mouseover",function(a){this.mouse_inside=!0});e.addEventListener("mouseout",function(a){for(a=a.toElement;a!=this&&a!=c.document;)a=a.parentNode;a!=this&&(this.mouse_inside=!1,this.block_close||this.closeMenu())});c.document.body.appendChild(e);a=e.getClientRects()[0];b.from&&(b.from.block_close=!0);h=b.left||0;g=b.top||0;b.event&&(h=b.event.pageX-10,g=b.event.pageY-10,b.left&&(h=b.left),f=c.document.body.getClientRects()[0],b.from&&(h=b.from.getClientRects()[0], -h=h.left+h.width),h>f.width-a.width-10&&(h=f.width-a.width-10),g>f.height-a.height-10&&(g=f.height-a.height-10));e.style.left=h+"px";e.style.top=g+"px";e.closeMenu=function(){b.from&&(b.from.block_close=!1,b.from.mouse_inside||b.from.closeMenu());this.parentNode&&c.document.body.removeChild(this)};return e};LiteGraph.closeAllContextualMenus=function(){var a=document.querySelectorAll(".litecontextualmenu");if(a.length){for(var b=[],c=0;cf.width-a.width-10&&(h=f.width-a.width-10),g>f.height-a.height-10&&(g=f.height-a.height-10));e.style.left=h+"px";e.style.top=g+"px";e.closeMenu=function(){b.from&&(b.from.block_close=!1,b.from.mouse_inside||b.from.closeMenu());this.parentNode&&c.document.body.removeChild(this)};return e};LiteGraph.closeAllContextualMenus=function(){var a=document.querySelectorAll(".graphcontextualmenu");if(a.length){for(var b=[],c=0;cB":value=a>b;break;case "A=B":value=a>=b}this.setOutputData(c,value)}}};h.prototype.onGetOutputs=function(){return[["A==B","number"],["A!=B","number"], -["A>B","number"],["A=B","number"],["A<=B","number"]]};LiteGraph.registerNodeType("math/compare",h);l.title="Accumulate";l.desc="Increments a value every time";l.prototype.onExecute=function(){var a=this.getInputData(0);this.properties.value=null!==a?this.properties.value+a:this.properties.value+this.properties.increment;this.setOutputData(0,this.properties.value)};LiteGraph.registerNodeType("math/accumulate",l);n.title="Trigonometry";n.desc="Sin Cos Tan";n.filter="shader";n.prototype.onExecute= -function(){var a=this.getInputData(0),b=this.properties.amplitude,c=this.findInputSlot("amplitude");-1!=c&&(b=this.getInputData(c));var d=this.properties.offset,c=this.findInputSlot("offset");-1!=c&&(d=this.getInputData(c));for(var c=0,e=this.outputs.length;cXYZ",k.desc="vector 3 to components",k.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]))},LiteGraph.registerNodeType("math3d/vec3-to-xyz",k),k=function(){this.addInputs([["x","number"],["y","number"],["z","number"]]);this.addOutput("vec3", -"vec3");this.properties={x:0,y:0,z:0}},k.title="XYZ->Vec3",k.desc="components to vector3",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);this.setOutputData(0,vec3.fromValues(a,b,c))},LiteGraph.registerNodeType("math3d/xyz-to-vec3",k),k=function(){this.addInputs([["degrees","number"],["axis","vec3"]]);this.addOutput("quat","quat");this.properties= -{angle:90,axis:vec3.fromValues(0,1,0)}},k.title="Rotation",k.desc="quaternion rotation",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle);var b=this.getInputData(1);null==b&&(b=this.properties.axis);a=quat.setAxisAngle(quat.create(),b,0.0174532925*a);this.setOutputData(0,a)},LiteGraph.registerNodeType("math3d/rotation",k),k=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},k.title= -"Rot. Vec3",k.desc="rotate a point",k.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a):this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))},LiteGraph.registerNodeType("math3d/rotate_vec3",k),k=function(){this.addInputs([["A","quat"],["B","quat"]]);this.addOutput("A*B","quat")},k.title="Mult. Quat",k.desc="rotate quaternion",k.prototype.onExecute=function(){var a=this.getInputData(0);if(null!= -a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(quat.create(),a,b),this.setOutputData(0,a))}},LiteGraph.registerNodeType("math3d/mult-quat",k))})(); +"number",{label:""});this.addOutput("out","number",{label:""});this.size=[60,20];this.properties={factor:1}}function g(){this.addInput("A","number");this.addInput("B","number");this.addOutput("=","number");this.properties={A:1,B:1,OP:"+"}}function h(){this.addInput("A","number");this.addInput("B","number");this.addOutput("A==B","boolean");this.addOutput("A!=B","boolean");this.properties={A:0,B:0}}function k(){this.addInput("A","number");this.addInput("B","number");this.addOutput("out","boolean"); +this.properties={A:0,B:1,OP:">"};this.size=[60,40]}function n(){this.addInput("inc","number");this.addOutput("total","number");this.properties={increment:0,value:0}}function p(){this.addInput("v","number");this.addOutput("sin","number");this.properties={amplitude:1,offset:0};this.bgImageUrl="nodes/imgs/icon-sin.png"}a.title="Rand";a.desc="Random number";a.prototype.onExecute=function(){if(this.inputs)for(var a=0;aB":value=a>b;break;case "A=B":value=a>=b}this.setOutputData(c,value)}}};h.prototype.onGetOutputs=function(){return[["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]};LiteGraph.registerNodeType("math/compare",h);k["@OP"]={type:"enum",title:"operation",values:"> < == != <= >=".split(" ")}; +k.title="Condition";k.desc="evaluates condition between A and B";k.prototype.onExecute=function(){var a=this.getInputData(0);void 0===a?a=this.properties.A:this.properties.A=a;var b=this.getInputData(1);void 0===b?b=this.properties.B:this.properties.B=b;var c=!0;switch(this.properties.OP){case ">":c=a>b;break;case "<":c=a=":c=a>=b}this.setOutputData(0,c)};LiteGraph.registerNodeType("math/condition",k);n.title="Accumulate"; +n.desc="Increments a value every time";n.prototype.onExecute=function(){var a=this.getInputData(0);this.properties.value=null!==a?this.properties.value+a:this.properties.value+this.properties.increment;this.setOutputData(0,this.properties.value)};LiteGraph.registerNodeType("math/accumulate",n);p.title="Trigonometry";p.desc="Sin Cos Tan";p.filter="shader";p.prototype.onExecute=function(){var a=this.getInputData(0),b=this.properties.amplitude,c=this.findInputSlot("amplitude");-1!=c&&(b=this.getInputData(c)); +var d=this.properties.offset,c=this.findInputSlot("offset");-1!=c&&(d=this.getInputData(c));for(var c=0,e=this.outputs.length;cVec3",l.desc="components to vector3",l.prototype.onExecute= +function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);this.setOutputData(0,vec3.fromValues(a,b,c))},LiteGraph.registerNodeType("math3d/xyz-to-vec3",l),l=function(){this.addInputs([["degrees","number"],["axis","vec3"]]);this.addOutput("quat","quat");this.properties={angle:90,axis:vec3.fromValues(0,1,0)}},l.title="Rotation",l.desc="quaternion rotation",l.prototype.onExecute= +function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle);var b=this.getInputData(1);null==b&&(b=this.properties.axis);a=quat.setAxisAngle(quat.create(),b,0.0174532925*a);this.setOutputData(0,a)},LiteGraph.registerNodeType("math3d/rotation",l),l=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},l.title="Rot. Vec3",l.desc="rotate a point",l.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a= +this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a):this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))},LiteGraph.registerNodeType("math3d/rotate_vec3",l),l=function(){this.addInputs([["A","quat"],["B","quat"]]);this.addOutput("A*B","quat")},l.title="Mult. Quat",l.desc="rotate quaternion",l.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(quat.create(),a,b),this.setOutputData(0,a))}},LiteGraph.registerNodeType("math3d/mult-quat", +l))})();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 a=this.getInputData(0);if(void 0!==a){for(var b=1;b=this.size[1]||!this.properties.show||!this._video||(a.save(),a.drawImage(this._video,0,0,this.size[0],this.size[1]), a.restore())};LiteGraph.registerNodeType("graphics/webcam",g)})(); -if("undefined"!=typeof LiteGraph){var LGraphTexture=function(){this.addOutput("Texture","Texture");this.properties={name:""};this.size=[LGraphTexture.image_preview_size,LGraphTexture.image_preview_size]};LGraphTexture.title="Texture";LGraphTexture.desc="Texture";LGraphTexture.widgets_info={name:{widget:"texture"}};LGraphTexture.textures_container={};LGraphTexture.loadTextureCallback=null;LGraphTexture.image_preview_size=256;LGraphTexture.PASS_THROUGH=1;LGraphTexture.COPY=2;LGraphTexture.LOW=3;LGraphTexture.HIGH= -4;LGraphTexture.REUSE=5;LGraphTexture.DEFAULT=2;LGraphTexture.MODE_VALUES={"pass through":LGraphTexture.PASS_THROUGH,copy:LGraphTexture.COPY,low:LGraphTexture.LOW,high:LGraphTexture.HIGH,reuse:LGraphTexture.REUSE,"default":LGraphTexture.DEFAULT};LGraphTexture.getTexture=function(a){var b=LGraphTexture.textures_container||gl.textures;if(!b)throw"Cannot load texture, container of textures not found";var c=b[a];if(!c&&a&&":"!=a[0]){if(LGraphTexture.loadTextureCallback)return(b=LGraphTexture.loadTextureCallback)&& -b(a),null;c=a;"http://"==c.substr(0,7)&&LiteGraph.proxy&&(c=LiteGraph.proxy+c.substr(7));c=b[a]=GL.Texture.fromURL(c,{})}return c};LGraphTexture.getTargetTexture=function(a,b,c){if(!a)throw"LGraphTexture.getTargetTexture expects a reference texture";var d=null;switch(c){case LGraphTexture.LOW:d=gl.UNSIGNED_BYTE;break;case LGraphTexture.HIGH:d=gl.HIGH_PRECISION_FORMAT;break;case LGraphTexture.REUSE:return a;default:d=a?a.type:gl.UNSIGNED_BYTE}b&&b.width==a.width&&b.height==a.height&&b.type==d||(b= -new GL.Texture(a.width,a.height,{type:d,format:gl.RGBA,filter:gl.LINEAR}));return b};LGraphTexture.getNoiseTexture=function(){if(this._noise_texture)return this._noise_texture;for(var a=new Uint8Array(1048576),b=0;1048576>b;++b)a[b]=255*Math.random();return this._noise_texture=a=GL.Texture.fromMemory(512,512,a,{format:gl.RGBA,wrap:gl.REPEAT,filter:gl.NEAREST})};LGraphTexture.prototype.onDropFile=function(a,b,c){if(a){var d=null;"string"==typeof a?d=GL.Texture.fromURL(a):-1!=b.toLowerCase().indexOf(".dds")? -d=GL.Texture.fromDDSInMemory(a):(a=new Blob([c]),a=URL.createObjectURL(a),d=GL.Texture.fromURL(a));this._drop_texture=d;this.properties.name=b}else this._drop_texture=null,this.properties.name=""};LGraphTexture.prototype.getExtraMenuOptions=function(a){var b=this;if(this._drop_texture)return[{content:"Clear",callback:function(){b._drop_texture=null;b.properties.name=""}}]};LGraphTexture.prototype.onExecute=function(){if(this._drop_texture)this.setOutputData(0,this._drop_texture);else if(this.properties.name){var a= -LGraphTexture.getTexture(this.properties.name);a&&(this._last_tex=a,this.setOutputData(0,a))}};LGraphTexture.prototype.onResourceRenamed=function(a,b){this.properties.name==a&&(this.properties.name=b)};LGraphTexture.prototype.onDrawBackground=function(a){if(!(this.flags.collapsed||20>=this.size[1]))if(this._drop_texture&&a.webgl)a.drawImage(this._drop_texture,0,0,this.size[0],this.size[1]);else{if(this._last_preview_tex!=this._last_tex)if(a.webgl)this._canvas=this._last_tex;else{var b=LGraphTexture.generateLowResTexturePreview(this._last_tex); -if(!b)return;this._last_preview_tex=this._last_tex;this._canvas=cloneCanvas(b)}this._canvas&&(a.save(),a.webgl||(a.translate(0,this.size[1]),a.scale(1,-1)),a.drawImage(this._canvas,0,0,this.size[0],this.size[1]),a.restore())}};LGraphTexture.generateLowResTexturePreview=function(a){if(!a)return null;var b=LGraphTexture.image_preview_size,c=a;if(a.format==gl.DEPTH_COMPONENT)return null;if(a.width>b||a.height>b)c=this._preview_temp_tex,this._preview_temp_tex||(this._preview_temp_tex=c=new GL.Texture(b, -b,{minFilter:gl.NEAREST})),a.copyTo(c);a=this._preview_canvas;a||(this._preview_canvas=a=createCanvas(b,b));c&&c.toCanvas(a);return a};LiteGraph.registerNodeType("texture/texture",LGraphTexture);window.LGraphTexture=LGraphTexture;var LGraphTexturePreview=function(){this.addInput("Texture","Texture");this.properties={flipY:!1};this.size=[LGraphTexture.image_preview_size,LGraphTexture.image_preview_size]};LGraphTexturePreview.title="Preview";LGraphTexturePreview.desc="Show a texture in the graph canvas"; -LGraphTexturePreview.prototype.onDrawBackground=function(a){if(!this.flags.collapsed){var b=this.getInputData(0);if(b){var c=null,c=!b.handle&&a.webgl?b:LGraphTexture.generateLowResTexturePreview(b);a.save();this.properties.flipY&&(a.translate(0,this.size[1]),a.scale(1,-1));a.drawImage(c,0,0,this.size[0],this.size[1]);a.restore()}}};LiteGraph.registerNodeType("texture/preview",LGraphTexturePreview);window.LGraphTexturePreview=LGraphTexturePreview;var LGraphTextureSave=function(){this.addInput("Texture", -"Texture");this.addOutput("","Texture");this.properties={name:""}};LGraphTextureSave.title="Save";LGraphTextureSave.desc="Save a texture in the repository";LGraphTextureSave.prototype.onExecute=function(){var a=this.getInputData(0);a&&(this.properties.name&&(LGraphTexture.textures_container[this.properties.name]=a),this.setOutputData(0,a))};LiteGraph.registerNodeType("texture/save",LGraphTextureSave);window.LGraphTextureSave=LGraphTextureSave;var LGraphTextureOperation=function(){this.addInput("Texture", -"Texture");this.addInput("TextureB","Texture");this.addInput("value","number");this.addOutput("Texture","Texture");this.help="

pixelcode must be vec3

\t\t\t

uvcode must be vec2, is optional

\t\t\t

uv: tex. coords

color: texture

colorB: textureB

time: scene time

value: input value

";this.properties={value:1,uvcode:"",pixelcode:"color + colorB * value",precision:LGraphTexture.DEFAULT}}; -LGraphTextureOperation.widgets_info={uvcode:{widget:"textarea",height:100},pixelcode:{widget:"textarea",height:100},precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureOperation.title="Operation";LGraphTextureOperation.desc="Texture shader operation";LGraphTextureOperation.prototype.getExtraMenuOptions=function(a){var b=this;return[{content:b.properties.show?"Hide Texture":"Show Texture",callback:function(){b.properties.show=!b.properties.show}}]};LGraphTextureOperation.prototype.onDrawBackground= -function(a){this.flags.collapsed||20>=this.size[1]||!this.properties.show||!this._tex||this._tex.gl!=a||(a.save(),a.drawImage(this._tex,0,0,this.size[0],this.size[1]),a.restore())};LGraphTextureOperation.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else{var b=this.getInputData(1);if(this.properties.uvcode||this.properties.pixelcode){var c=512,d=512;a?(c=a.width,d=a.height):b&&(c=b.width,d=b.height);this._tex= -a||this._tex?LGraphTexture.getTargetTexture(a||this._tex,this._tex,this.properties.precision):new GL.Texture(c,d,{type:this.precision===LGraphTexture.LOW?gl.UNSIGNED_BYTE:gl.HIGH_PRECISION_FORMAT,format:gl.RGBA,filter:gl.LINEAR});var e="";this.properties.uvcode&&(e="uv = "+this.properties.uvcode,-1!=this.properties.uvcode.indexOf(";")&&(e=this.properties.uvcode));var f="";this.properties.pixelcode&&(f="result = "+this.properties.pixelcode,-1!=this.properties.pixelcode.indexOf(";")&&(f=this.properties.pixelcode)); -var g=this._shader;if(!g||this._shader_code!=e+"|"+f){try{this._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureOperation.pixel_shader,{UV_CODE:e,PIXEL_CODE:f}),this.boxcolor="#00FF00"}catch(h){console.log("Error compiling shader: ",h);this.boxcolor="#FF0000";return}this._shader_code=e+"|"+f;g=this._shader}if(g){this.boxcolor="green";var l=this.getInputData(2);null!=l?this.properties.value=l:l=parseFloat(this.properties.value);var n=this.graph.getTime();this._tex.drawTo(function(){gl.disable(gl.DEPTH_TEST); -gl.disable(gl.CULL_FACE);gl.disable(gl.BLEND);a&&a.bind(0);b&&b.bind(1);var e=Mesh.getScreenQuad();g.uniforms({u_texture:0,u_textureB:1,value:l,texSize:[c,d],time:n}).draw(e)});this.setOutputData(0,this._tex)}else this.boxcolor="red"}}};LGraphTextureOperation.pixel_shader="precision highp float;\n\t\t\t\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform vec2 texSize;\n\t\t\tuniform float time;\n\t\t\tuniform float value;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 uv = v_coord;\n\t\t\t\tUV_CODE;\n\t\t\t\tvec3 color = texture2D(u_texture, uv).rgb;\n\t\t\t\tvec3 colorB = texture2D(u_textureB, uv).rgb;\n\t\t\t\tvec3 result = color;\n\t\t\t\tfloat alpha = 1.0;\n\t\t\t\tPIXEL_CODE;\n\t\t\t\tgl_FragColor = vec4(result, alpha);\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/operation",LGraphTextureOperation);window.LGraphTextureOperation=LGraphTextureOperation;var LGraphTextureShader=function(){this.addOutput("Texture","Texture");this.properties={code:"",width:512,height:512};this.properties.code="\nvoid main() {\n vec2 uv = coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n"};LGraphTextureShader.title="Shader";LGraphTextureShader.desc="Texture shader";LGraphTextureShader.widgets_info={code:{widget:"code"}, -precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureShader.prototype.onExecute=function(){if(this._shader_code!=this.properties.code)if(this._shader_code=this.properties.code,this._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureShader.pixel_shader+this.properties.code))this.boxcolor="green";else{this.boxcolor="red";return}this._tex&&this._tex.width==this.properties.width&&this._tex.height==this.properties.height||(this._tex=new GL.Texture(this.properties.width, -this.properties.height,{format:gl.RGBA,filter:gl.LINEAR}));var a=this._tex,b=this._shader,c=this.graph.getTime();a.drawTo(function(){b.uniforms({texSize:[a.width,a.height],time:c}).draw(Mesh.getScreenQuad())});this.setOutputData(0,this._tex)};LGraphTextureShader.pixel_shader="precision highp float;\n\t\t\t\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform float time;\n\t\t\t";LiteGraph.registerNodeType("texture/shader",LGraphTextureShader);window.LGraphTextureShader=LGraphTextureShader;var LGraphTextureToViewport= -function(){this.addInput("Texture","Texture");this.properties={additive:!1,antialiasing:!1,disable_alpha:!1};this.size[0]=130;LGraphTextureToViewport._shader||(LGraphTextureToViewport._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureToViewport.pixel_shader))};LGraphTextureToViewport.title="to Viewport";LGraphTextureToViewport.desc="Texture to viewport";LGraphTextureToViewport.prototype.onExecute=function(){var a=this.getInputData(0);if(a)if(this.properties.disable_alpha?gl.disable(gl.BLEND): -(gl.enable(gl.BLEND),this.properties.additive?gl.blendFunc(gl.SRC_ALPHA,gl.ONE):gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA)),gl.disable(gl.DEPTH_TEST),this.properties.antialiasing){gl.getViewport();var b=Mesh.getScreenQuad();a.bind(0);LGraphTextureToViewport._shader.uniforms({u_texture:0,uViewportSize:[a.width,a.height],inverseVP:[1/a.width,1/a.height]}).draw(b)}else a.toViewport()};LGraphTextureToViewport.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 uViewportSize;\n\t\t\tuniform vec2 inverseVP;\n\t\t\t#define FXAA_REDUCE_MIN (1.0/ 128.0)\n\t\t\t#define FXAA_REDUCE_MUL (1.0 / 8.0)\n\t\t\t#define FXAA_SPAN_MAX 8.0\n\t\t\t\n\t\t\t/* from mitsuhiko/webgl-meincraft based on the code on geeks3d.com */\n\t\t\tvec4 applyFXAA(sampler2D tex, vec2 fragCoord)\n\t\t\t{\n\t\t\t\tvec4 color = vec4(0.0);\n\t\t\t\t/*vec2 inverseVP = vec2(1.0 / uViewportSize.x, 1.0 / uViewportSize.y);*/\n\t\t\t\tvec3 rgbNW = texture2D(tex, (fragCoord + vec2(-1.0, -1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbNE = texture2D(tex, (fragCoord + vec2(1.0, -1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbSW = texture2D(tex, (fragCoord + vec2(-1.0, 1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbSE = texture2D(tex, (fragCoord + vec2(1.0, 1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbM = texture2D(tex, fragCoord * inverseVP).xyz;\n\t\t\t\tvec3 luma = vec3(0.299, 0.587, 0.114);\n\t\t\t\tfloat lumaNW = dot(rgbNW, luma);\n\t\t\t\tfloat lumaNE = dot(rgbNE, luma);\n\t\t\t\tfloat lumaSW = dot(rgbSW, luma);\n\t\t\t\tfloat lumaSE = dot(rgbSE, luma);\n\t\t\t\tfloat lumaM = dot(rgbM, luma);\n\t\t\t\tfloat lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n\t\t\t\tfloat lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\t\t\t\t\n\t\t\t\tvec2 dir;\n\t\t\t\tdir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n\t\t\t\tdir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\t\t\t\t\n\t\t\t\tfloat dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\t\t\t\t\n\t\t\t\tfloat rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n\t\t\t\tdir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * inverseVP;\n\t\t\t\t\n\t\t\t\tvec3 rgbA = 0.5 * (texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + \n\t\t\t\t\ttexture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n\t\t\t\tvec3 rgbB = rgbA * 0.5 + 0.25 * (texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + \n\t\t\t\t\ttexture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\t\t\t\t\n\t\t\t\treturn vec4(rgbA,1.0);\n\t\t\t\tfloat lumaB = dot(rgbB, luma);\n\t\t\t\tif ((lumaB < lumaMin) || (lumaB > lumaMax))\n\t\t\t\t\tcolor = vec4(rgbA, 1.0);\n\t\t\t\telse\n\t\t\t\t\tcolor = vec4(rgbB, 1.0);\n\t\t\t\treturn color;\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/toviewport",LGraphTextureToViewport);window.LGraphTextureToViewport=LGraphTextureToViewport;var LGraphTextureCopy=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={size:0,generate_mipmaps:!1,precision:LGraphTexture.DEFAULT}};LGraphTextureCopy.title="Copy";LGraphTextureCopy.desc="Copy Texture";LGraphTextureCopy.widgets_info={size:{widget:"combo",values:[0,32,64,128,256,512,1024,2048]},precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}}; -LGraphTextureCopy.prototype.onExecute=function(){var a=this.getInputData(0);if(a||this._temp_texture){if(a){var b=a.width,c=a.height;0!=this.properties.size&&(c=b=this.properties.size);var d=this._temp_texture,e=a.type;this.properties.precision===LGraphTexture.LOW?e=gl.UNSIGNED_BYTE:this.properties.precision===LGraphTexture.HIGH&&(e=gl.HIGH_PRECISION_FORMAT);d&&d.width==b&&d.height==c&&d.type==e||(d=gl.LINEAR,this.properties.generate_mipmaps&&isPowerOfTwo(b)&&isPowerOfTwo(c)&&(d=gl.LINEAR_MIPMAP_LINEAR), -this._temp_texture=new GL.Texture(b,c,{type:e,format:gl.RGBA,minFilter:d,magFilter:gl.LINEAR}));a.copyTo(this._temp_texture);this.properties.generate_mipmaps&&(this._temp_texture.bind(0),gl.generateMipmap(this._temp_texture.texture_type),this._temp_texture.unbind(0))}this.setOutputData(0,this._temp_texture)}};LiteGraph.registerNodeType("texture/copy",LGraphTextureCopy);window.LGraphTextureCopy=LGraphTextureCopy;var LGraphTextureAverage=function(){this.addInput("Texture","Texture");this.addOutput("", -"Texture");this.properties={low_precision:!1}};LGraphTextureAverage.title="Average";LGraphTextureAverage.desc="Compute average of a texture and stores it as a texture";LGraphTextureAverage.prototype.onExecute=function(){var a=this.getInputData(0);if(a){if(!LGraphTextureAverage._shader){LGraphTextureAverage._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureAverage.pixel_shader);for(var b=new Float32Array(32),c=0;32>c;++c)b[c]=Math.random();LGraphTextureAverage._shader.uniforms({u_samples_a:b.subarray(0, -16),u_samples_b:b.subarray(16,32)})}b=this._temp_texture;c=this.properties.low_precision?gl.UNSIGNED_BYTE:a.type;b&&b.type==c||(this._temp_texture=new GL.Texture(1,1,{type:c,format:gl.RGBA,filter:gl.NEAREST}));var d=LGraphTextureAverage._shader;this._temp_texture.drawTo(function(){a.toViewport(d,{u_texture:0})});this.setOutputData(0,this._temp_texture)}};LGraphTextureAverage.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tuniform mat4 u_samples_a;\n\t\t\tuniform mat4 u_samples_b;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tvarying vec2 v_coord;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = vec4(0.0);\n\t\t\t\tfor(int i = 0; i < 4; ++i)\n\t\t\t\t\tfor(int j = 0; j < 4; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ) );\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], u_samples_b[i][j] ) );\n\t\t\t\t\t}\n\t\t\t gl_FragColor = color * 0.03125;\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/average",LGraphTextureAverage);window.LGraphTextureAverage=LGraphTextureAverage;var LGraphImageToTexture=function(){this.addInput("Image","image");this.addOutput("","Texture");this.properties={}};LGraphImageToTexture.title="Image to Texture";LGraphImageToTexture.desc="Uploads an image to the GPU";LGraphImageToTexture.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=a.videoWidth||a.width,c=a.videoHeight||a.height;if(a.gltexture)this.setOutputData(0, -a.gltexture);else{var d=this._temp_texture;d&&d.width==b&&d.height==c||(this._temp_texture=new GL.Texture(b,c,{format:gl.RGBA,filter:gl.LINEAR}));try{this._temp_texture.uploadImage(a)}catch(e){console.error("image comes from an unsafe location, cannot be uploaded to webgl");return}this.setOutputData(0,this._temp_texture)}}};LiteGraph.registerNodeType("texture/imageToTexture",LGraphImageToTexture);window.LGraphImageToTexture=LGraphImageToTexture;var LGraphTextureLUT=function(){this.addInput("Texture", -"Texture");this.addInput("LUT","Texture");this.addInput("Intensity","number");this.addOutput("","Texture");this.properties={intensity:1,precision:LGraphTexture.DEFAULT};LGraphTextureLUT._shader||(LGraphTextureLUT._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureLUT.pixel_shader))};LGraphTextureLUT.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureLUT.title="LUT";LGraphTextureLUT.desc="Apply LUT to Texture";LGraphTextureLUT.prototype.onExecute=function(){var a= -this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else if(a){var b=this.getInputData(1);if(b){b.bind(0);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);var c=this.properties.intensity;this.isInputConnected(2)&&(this.properties.intensity=c=this.getInputData(2));this._tex= -LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);this._tex.drawTo(function(){b.bind(1);a.toViewport(LGraphTextureLUT._shader,{u_texture:0,u_textureB:1,u_amount:c})});this.setOutputData(0,this._tex)}else this.setOutputData(0,a)}};LGraphTextureLUT.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform float u_amount;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\t lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\t\t\t\t mediump float blueColor = textureColor.b * 63.0;\n\t\t\t\t mediump vec2 quad1;\n\t\t\t\t quad1.y = floor(floor(blueColor) / 8.0);\n\t\t\t\t quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\t\t\t\t mediump vec2 quad2;\n\t\t\t\t quad2.y = floor(ceil(blueColor) / 8.0);\n\t\t\t\t quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\t\t\t\t highp vec2 texPos1;\n\t\t\t\t texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t highp vec2 texPos2;\n\t\t\t\t texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\t\t\t\t lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\t\t\t\t lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\t\t\t\t gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/LUT",LGraphTextureLUT);window.LGraphTextureLUT=LGraphTextureLUT;var LGraphTextureChannels=function(){this.addInput("Texture","Texture");this.addOutput("R","Texture");this.addOutput("G","Texture");this.addOutput("B","Texture");this.addOutput("A","Texture");this.properties={};LGraphTextureChannels._shader||(LGraphTextureChannels._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureChannels.pixel_shader))};LGraphTextureChannels.title="Texture to Channels"; -LGraphTextureChannels.desc="Split texture channels";LGraphTextureChannels.prototype.onExecute=function(){var a=this.getInputData(0);if(a){this._channels||(this._channels=Array(4));for(var b=0,c=0;4>c;c++)this.isOutputConnected(c)?(this._channels[c]&&this._channels[c].width==a.width&&this._channels[c].height==a.height&&this._channels[c].type==a.type||(this._channels[c]=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR})),b++):this._channels[c]=null;if(b){gl.disable(gl.BLEND); -gl.disable(gl.DEPTH_TEST);for(var d=Mesh.getScreenQuad(),e=LGraphTextureChannels._shader,f=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],c=0;4>c;c++)this._channels[c]&&(this._channels[c].drawTo(function(){a.bind(0);e.uniforms({u_texture:0,u_mask:f[c]}).draw(d)}),this.setOutputData(c,this._channels[c]))}}};LGraphTextureChannels.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec4 u_mask;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/textureChannels",LGraphTextureChannels);window.LGraphTextureChannels=LGraphTextureChannels;var LGraphChannelsTexture=function(){this.addInput("R","Texture");this.addInput("G","Texture");this.addInput("B","Texture");this.addInput("A","Texture");this.addOutput("Texture","Texture");this.properties={};LGraphChannelsTexture._shader||(LGraphChannelsTexture._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphChannelsTexture.pixel_shader))};LGraphChannelsTexture.title= -"Channels to Texture";LGraphChannelsTexture.desc="Split texture channels";LGraphChannelsTexture.prototype.onExecute=function(){var a=[this.getInputData(0),this.getInputData(1),this.getInputData(2),this.getInputData(3)];if(a[0]&&a[1]&&a[2]&&a[3]){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),c=LGraphChannelsTexture._shader;this._tex=LGraphTexture.getTargetTexture(a[0],this._tex);this._tex.drawTo(function(){a[0].bind(0);a[1].bind(1);a[2].bind(2);a[3].bind(3);c.uniforms({u_textureR:0, -u_textureG:1,u_textureB:2,u_textureA:3}).draw(b)});this.setOutputData(0,this._tex)}};LGraphChannelsTexture.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureR;\n\t\t\tuniform sampler2D u_textureG;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( \t\t\t\t\t\ttexture2D(u_textureR, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureG, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureB, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureA, v_coord).r);\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/channelsTexture",LGraphChannelsTexture);window.LGraphChannelsTexture=LGraphChannelsTexture;var LGraphTextureMix=function(){this.addInput("A","Texture");this.addInput("B","Texture");this.addInput("Mixer","Texture");this.addOutput("Texture","Texture");this.properties={precision:LGraphTexture.DEFAULT};LGraphTextureMix._shader||(LGraphTextureMix._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureMix.pixel_shader))};LGraphTextureMix.title="Mix";LGraphTextureMix.desc= -"Generates a texture mixing two textures";LGraphTextureMix.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureMix.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else{var b=this.getInputData(1),c=this.getInputData(2);if(a&&b&&c){this._tex=LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var d=Mesh.getScreenQuad(), -e=LGraphTextureMix._shader;this._tex.drawTo(function(){a.bind(0);b.bind(1);c.bind(2);e.uniforms({u_textureA:0,u_textureB:1,u_textureMix:2}).draw(d)});this.setOutputData(0,this._tex)}}};LGraphTextureMix.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureMix;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), texture2D(u_textureMix, v_coord) );\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/mix",LGraphTextureMix);window.LGraphTextureMix=LGraphTextureMix;var LGraphTextureEdges=function(){this.addInput("Tex.","Texture");this.addOutput("Edges","Texture");this.properties={invert:!0,precision:LGraphTexture.DEFAULT};LGraphTextureEdges._shader||(LGraphTextureEdges._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureEdges.pixel_shader))};LGraphTextureEdges.title="Edges";LGraphTextureEdges.desc="Detects edges";LGraphTextureEdges.widgets_info={precision:{widget:"combo", -values:LGraphTexture.MODE_VALUES}};LGraphTextureEdges.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),c=LGraphTextureEdges._shader,d=this.properties.invert;this._tex.drawTo(function(){a.bind(0);c.uniforms({u_texture:0,u_isize:[1/a.width,1/a.height], -u_invert:d?1:0}).draw(b)});this.setOutputData(0,this._tex)}};LGraphTextureEdges.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_isize;\n\t\t\tuniform int u_invert;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 center = texture2D(u_texture, v_coord);\n\t\t\t\tvec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\t\t\t\tvec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\t\t\t\tvec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\t\t\t\tvec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\t\t\t\tvec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\t\t\t\tif(u_invert == 1)\n\t\t\t\t\tdiff.xyz = vec3(1.0) - diff.xyz;\n\t\t\t gl_FragColor = vec4( diff.xyz, center.a );\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/edges",LGraphTextureEdges);window.LGraphTextureEdges=LGraphTextureEdges;var LGraphTextureDepthRange=function(){this.addInput("Texture","Texture");this.addInput("Distance","number");this.addInput("Range","number");this.addOutput("Texture","Texture");this.properties={distance:100,range:50,high_precision:!1};LGraphTextureDepthRange._shader||(LGraphTextureDepthRange._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureDepthRange.pixel_shader))};LGraphTextureDepthRange.title= -"Depth Range";LGraphTextureDepthRange.desc="Generates a texture with a depth range";LGraphTextureDepthRange.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=gl.UNSIGNED_BYTE;this.properties.high_precision&&(b=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==b&&this._temp_texture.width==a.width&&this._temp_texture.height==a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:b,format:gl.RGBA,filter:gl.LINEAR}));var c=this.properties.distance; -this.isInputConnected(1)&&(c=this.getInputData(1),this.properties.distance=c);var d=this.properties.range;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.range=d);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad(),f=LGraphTextureDepthRange._shader;this._temp_texture.drawTo(function(){a.bind(0);f.uniforms({u_texture:0,u_distance:c,u_range:d,u_camera_planes:[Renderer._current_camera.near,Renderer._current_camera.far]}).draw(e)});this.setOutputData(0,this._temp_texture)}}; -LGraphTextureDepthRange.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_distance;\n\t\t\tuniform float u_range;\n\t\t\t\n\t\t\tfloat LinearDepth()\n\t\t\t{\n\t\t\t\tfloat n = u_camera_planes.x;\n\t\t\t\tfloat f = u_camera_planes.y;\n\t\t\t\treturn (2.0 * n) / (f + n - texture2D(u_texture, v_coord).x * (f - n));\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tfloat diff = abs(LinearDepth() * u_camera_planes.y - u_distance);\n\t\t\t\tfloat dof = 1.0;\n\t\t\t\tif(diff <= u_range)\n\t\t\t\t\tdof = diff / u_range;\n\t\t\t gl_FragColor = vec4(dof);\n\t\t\t}\n\t\t\t"; -LiteGraph.registerNodeType("texture/depth_range",LGraphTextureDepthRange);window.LGraphTextureDepthRange=LGraphTextureDepthRange;var LGraphTextureBlur=function(){this.addInput("Texture","Texture");this.addInput("Iterations","number");this.addInput("Intensity","number");this.addOutput("Blurred","Texture");this.properties={intensity:1,iterations:1,preserve_aspect:!1,scale:[1,1]};LGraphTextureBlur._shader||(LGraphTextureBlur._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureBlur.pixel_shader))}; -LGraphTextureBlur.title="Blur";LGraphTextureBlur.desc="Blur a texture";LGraphTextureBlur.max_iterations=20;LGraphTextureBlur.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=this._temp_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}),this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));b=this.properties.iterations;this.isInputConnected(1)&& -(b=this.getInputData(1),this.properties.iterations=b);b=Math.min(Math.floor(b),LGraphTextureBlur.max_iterations);if(0==b)this.setOutputData(0,a);else{var c=this.properties.intensity;this.isInputConnected(2)&&(c=this.getInputData(2),this.properties.intensity=c);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var d=Mesh.getScreenQuad(),e=LGraphTextureBlur._shader,f=this.properties.scale||[1,1],g=LiteGraph.camera_aspect;g||void 0===window.gl||(g=gl.canvas.height/gl.canvas.width);g||(g=1);for(var h=a, -g=this.properties.preserve_aspect?g:1,a=0;a=this.size[1]||!this._video||(a.save(),a.webgl?this._temp_texture&&a.drawImage(this._temp_texture,0,0,this.size[0],this.size[1]):(a.translate(0,this.size[1]),a.scale(1,-1),a.drawImage(this._video,0,0,this.size[0],this.size[1])),a.restore())};LGraphTextureWebcam.prototype.onExecute=function(){null!=this._webcam_stream||this._waiting_confirmation||this.openStream(); -if(this._video&&this._video.videoWidth){var a=this._video.videoWidth,b=this._video.videoHeight,c=this._temp_texture;c&&c.width==a&&c.height==b||(this._temp_texture=new GL.Texture(a,b,{format:gl.RGB,filter:gl.LINEAR}));this._temp_texture.uploadImage(this._video);this.setOutputData(0,this._temp_texture)}};LiteGraph.registerNodeType("texture/webcam",LGraphTextureWebcam);window.LGraphTextureWebcam=LGraphTextureWebcam;var LGraphCubemap=function(){this.addOutput("Cubemap","Cubemap");this.properties={name:""}; -this.size=[LGraphTexture.image_preview_size,LGraphTexture.image_preview_size]};LGraphCubemap.prototype.onDropFile=function(a,b,c){a?(this._drop_texture="string"==typeof a?GL.Texture.fromURL(a):GL.Texture.fromDDSInMemory(a),this.properties.name=b):(this._drop_texture=null,this.properties.name="")};LGraphCubemap.prototype.onExecute=function(){if(this._drop_texture)this.setOutputData(0,this._drop_texture);else if(this.properties.name){var a=LGraphTexture.getTexture(this.properties.name);a&&(this._last_tex= -a,this.setOutputData(0,a))}};LGraphCubemap.prototype.onDrawBackground=function(a){this.flags.collapsed||20>=this.size[1]||a.webgl&&(gl.meshes.cube||(gl.meshes.cube=GL.Mesh.cube({size:1})))};LiteGraph.registerNodeType("texture/cubemap",LGraphCubemap);window.LGraphCubemap=LGraphCubemap} +if("undefined"!=typeof LiteGraph){var LGraphTexture=function(){this.addOutput("Texture","Texture");this.properties={name:""};this.size=[LGraphTexture.image_preview_size,LGraphTexture.image_preview_size]};LGraphTexture.title="Texture";LGraphTexture.desc="Texture";LGraphTexture.widgets_info={name:{widget:"texture"}};LGraphTexture.loadTextureCallback=null;LGraphTexture.image_preview_size=256;LGraphTexture.PASS_THROUGH=1;LGraphTexture.COPY=2;LGraphTexture.LOW=3;LGraphTexture.HIGH=4;LGraphTexture.REUSE= +5;LGraphTexture.DEFAULT=2;LGraphTexture.MODE_VALUES={"pass through":LGraphTexture.PASS_THROUGH,copy:LGraphTexture.COPY,low:LGraphTexture.LOW,high:LGraphTexture.HIGH,reuse:LGraphTexture.REUSE,"default":LGraphTexture.DEFAULT};LGraphTexture.getTexturesContainer=function(){return gl.textures};LGraphTexture.loadTexture=function(a,b){b=b||{};var c=a;"http://"==c.substr(0,7)&&LiteGraph.proxy&&(c=LiteGraph.proxy+c.substr(7));return LGraphTexture.getTexturesContainer()[a]=GL.Texture.fromURL(c,b)};LGraphTexture.getTexture= +function(a){var b=this.getTexturesContainer();if(!b)throw"Cannot load texture, container of textures not found";b=b[a];return!b&&a&&":"!=a[0]?(this.loadTexture(a),null):b};LGraphTexture.getTargetTexture=function(a,b,c){if(!a)throw"LGraphTexture.getTargetTexture expects a reference texture";var d=null;switch(c){case LGraphTexture.LOW:d=gl.UNSIGNED_BYTE;break;case LGraphTexture.HIGH:d=gl.HIGH_PRECISION_FORMAT;break;case LGraphTexture.REUSE:return a;default:d=a?a.type:gl.UNSIGNED_BYTE}b&&b.width==a.width&& +b.height==a.height&&b.type==d||(b=new GL.Texture(a.width,a.height,{type:d,format:gl.RGBA,filter:gl.LINEAR}));return b};LGraphTexture.getNoiseTexture=function(){if(this._noise_texture)return this._noise_texture;for(var a=new Uint8Array(1048576),b=0;1048576>b;++b)a[b]=255*Math.random();return this._noise_texture=a=GL.Texture.fromMemory(512,512,a,{format:gl.RGBA,wrap:gl.REPEAT,filter:gl.NEAREST})};LGraphTexture.prototype.onDropFile=function(a,b,c){if(a){var d=null;"string"==typeof a?d=GL.Texture.fromURL(a): +-1!=b.toLowerCase().indexOf(".dds")?d=GL.Texture.fromDDSInMemory(a):(a=new Blob([c]),a=URL.createObjectURL(a),d=GL.Texture.fromURL(a));this._drop_texture=d;this.properties.name=b}else this._drop_texture=null,this.properties.name=""};LGraphTexture.prototype.getExtraMenuOptions=function(a){var b=this;if(this._drop_texture)return[{content:"Clear",callback:function(){b._drop_texture=null;b.properties.name=""}}]};LGraphTexture.prototype.onExecute=function(){if(this._drop_texture)this.setOutputData(0,this._drop_texture); +else if(this.properties.name){var a=LGraphTexture.getTexture(this.properties.name);a&&(this._last_tex=a,this.setOutputData(0,a))}};LGraphTexture.prototype.onResourceRenamed=function(a,b){this.properties.name==a&&(this.properties.name=b)};LGraphTexture.prototype.onDrawBackground=function(a){if(!(this.flags.collapsed||20>=this.size[1]))if(this._drop_texture&&a.webgl)a.drawImage(this._drop_texture,0,0,this.size[0],this.size[1]);else{if(this._last_preview_tex!=this._last_tex)if(a.webgl)this._canvas=this._last_tex; +else{var b=LGraphTexture.generateLowResTexturePreview(this._last_tex);if(!b)return;this._last_preview_tex=this._last_tex;this._canvas=cloneCanvas(b)}this._canvas&&(a.save(),a.webgl||(a.translate(0,this.size[1]),a.scale(1,-1)),a.drawImage(this._canvas,0,0,this.size[0],this.size[1]),a.restore())}};LGraphTexture.generateLowResTexturePreview=function(a){if(!a)return null;var b=LGraphTexture.image_preview_size,c=a;if(a.format==gl.DEPTH_COMPONENT)return null;if(a.width>b||a.height>b)c=this._preview_temp_tex, +this._preview_temp_tex||(this._preview_temp_tex=c=new GL.Texture(b,b,{minFilter:gl.NEAREST})),a.copyTo(c);a=this._preview_canvas;a||(this._preview_canvas=a=createCanvas(b,b));c&&c.toCanvas(a);return a};LiteGraph.registerNodeType("texture/texture",LGraphTexture);var LGraphTexturePreview=function(){this.addInput("Texture","Texture");this.properties={flipY:!1};this.size=[LGraphTexture.image_preview_size,LGraphTexture.image_preview_size]};LGraphTexturePreview.title="Preview";LGraphTexturePreview.desc= +"Show a texture in the graph canvas";LGraphTexturePreview.prototype.onDrawBackground=function(a){if(!this.flags.collapsed){var b=this.getInputData(0);if(b){var c=null,c=!b.handle&&a.webgl?b:LGraphTexture.generateLowResTexturePreview(b);a.save();this.properties.flipY&&(a.translate(0,this.size[1]),a.scale(1,-1));a.drawImage(c,0,0,this.size[0],this.size[1]);a.restore()}}};LiteGraph.registerNodeType("texture/preview",LGraphTexturePreview);var LGraphTextureSave=function(){this.addInput("Texture","Texture"); +this.addOutput("","Texture");this.properties={name:""}};LGraphTextureSave.title="Save";LGraphTextureSave.desc="Save a texture in the repository";LGraphTextureSave.prototype.onExecute=function(){var a=this.getInputData(0);a&&(this.properties.name&&(LGraphTexture.getTexturesContainer()[this.properties.name]=a),this.setOutputData(0,a))};LiteGraph.registerNodeType("texture/save",LGraphTextureSave);var LGraphTextureOperation=function(){this.addInput("Texture","Texture");this.addInput("TextureB","Texture"); +this.addInput("value","number");this.addOutput("Texture","Texture");this.help="

pixelcode must be vec3

\t\t\t

uvcode must be vec2, is optional

\t\t\t

uv: tex. coords

color: texture

colorB: textureB

time: scene time

value: input value

";this.properties={value:1,uvcode:"",pixelcode:"color + colorB * value",precision:LGraphTexture.DEFAULT}};LGraphTextureOperation.widgets_info={uvcode:{widget:"textarea", +height:100},pixelcode:{widget:"textarea",height:100},precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureOperation.title="Operation";LGraphTextureOperation.desc="Texture shader operation";LGraphTextureOperation.prototype.getExtraMenuOptions=function(a){var b=this;return[{content:b.properties.show?"Hide Texture":"Show Texture",callback:function(){b.properties.show=!b.properties.show}}]};LGraphTextureOperation.prototype.onDrawBackground=function(a){this.flags.collapsed||20>=this.size[1]|| +!this.properties.show||!this._tex||this._tex.gl!=a||(a.save(),a.drawImage(this._tex,0,0,this.size[0],this.size[1]),a.restore())};LGraphTextureOperation.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else{var b=this.getInputData(1);if(this.properties.uvcode||this.properties.pixelcode){var c=512,d=512;a?(c=a.width,d=a.height):b&&(c=b.width,d=b.height);this._tex=a||this._tex?LGraphTexture.getTargetTexture(a|| +this._tex,this._tex,this.properties.precision):new GL.Texture(c,d,{type:this.precision===LGraphTexture.LOW?gl.UNSIGNED_BYTE:gl.HIGH_PRECISION_FORMAT,format:gl.RGBA,filter:gl.LINEAR});var e="";this.properties.uvcode&&(e="uv = "+this.properties.uvcode,-1!=this.properties.uvcode.indexOf(";")&&(e=this.properties.uvcode));var f="";this.properties.pixelcode&&(f="result = "+this.properties.pixelcode,-1!=this.properties.pixelcode.indexOf(";")&&(f=this.properties.pixelcode));var g=this._shader;if(!g||this._shader_code!= +e+"|"+f){try{this._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureOperation.pixel_shader,{UV_CODE:e,PIXEL_CODE:f}),this.boxcolor="#00FF00"}catch(h){console.log("Error compiling shader: ",h);this.boxcolor="#FF0000";return}this._shader_code=e+"|"+f;g=this._shader}if(g){this.boxcolor="green";var k=this.getInputData(2);null!=k?this.properties.value=k:k=parseFloat(this.properties.value);var n=this.graph.getTime();this._tex.drawTo(function(){gl.disable(gl.DEPTH_TEST);gl.disable(gl.CULL_FACE); +gl.disable(gl.BLEND);a&&a.bind(0);b&&b.bind(1);var e=Mesh.getScreenQuad();g.uniforms({u_texture:0,u_textureB:1,value:k,texSize:[c,d],time:n}).draw(e)});this.setOutputData(0,this._tex)}else this.boxcolor="red"}}};LGraphTextureOperation.pixel_shader="precision highp float;\n\t\t\t\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform vec2 texSize;\n\t\t\tuniform float time;\n\t\t\tuniform float value;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 uv = v_coord;\n\t\t\t\tUV_CODE;\n\t\t\t\tvec3 color = texture2D(u_texture, uv).rgb;\n\t\t\t\tvec3 colorB = texture2D(u_textureB, uv).rgb;\n\t\t\t\tvec3 result = color;\n\t\t\t\tfloat alpha = 1.0;\n\t\t\t\tPIXEL_CODE;\n\t\t\t\tgl_FragColor = vec4(result, alpha);\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/operation",LGraphTextureOperation);var LGraphTextureShader=function(){this.addOutput("Texture","Texture");this.properties={code:"",width:512,height:512};this.properties.code="\nvoid main() {\n vec2 uv = coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n"};LGraphTextureShader.title="Shader";LGraphTextureShader.desc="Texture shader";LGraphTextureShader.widgets_info={code:{widget:"code"},precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}}; +LGraphTextureShader.prototype.onExecute=function(){if(this._shader_code!=this.properties.code)if(this._shader_code=this.properties.code,this._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureShader.pixel_shader+this.properties.code))this.boxcolor="green";else{this.boxcolor="red";return}this._tex&&this._tex.width==this.properties.width&&this._tex.height==this.properties.height||(this._tex=new GL.Texture(this.properties.width,this.properties.height,{format:gl.RGBA,filter:gl.LINEAR}));var a= +this._tex,b=this._shader,c=this.graph.getTime();a.drawTo(function(){b.uniforms({texSize:[a.width,a.height],time:c}).draw(Mesh.getScreenQuad())});this.setOutputData(0,this._tex)};LGraphTextureShader.pixel_shader="precision highp float;\n\t\t\t\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform float time;\n\t\t\t";LiteGraph.registerNodeType("texture/shader",LGraphTextureShader);var LGraphTextureToViewport=function(){this.addInput("Texture","Texture");this.properties={additive:!1,antialiasing:!1,disable_alpha:!1}; +this.size[0]=130;LGraphTextureToViewport._shader||(LGraphTextureToViewport._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureToViewport.pixel_shader))};LGraphTextureToViewport.title="to Viewport";LGraphTextureToViewport.desc="Texture to viewport";LGraphTextureToViewport.prototype.onExecute=function(){var a=this.getInputData(0);if(a)if(this.properties.disable_alpha?gl.disable(gl.BLEND):(gl.enable(gl.BLEND),this.properties.additive?gl.blendFunc(gl.SRC_ALPHA,gl.ONE):gl.blendFunc(gl.SRC_ALPHA, +gl.ONE_MINUS_SRC_ALPHA)),gl.disable(gl.DEPTH_TEST),this.properties.antialiasing){gl.getViewport();var b=Mesh.getScreenQuad();a.bind(0);LGraphTextureToViewport._shader.uniforms({u_texture:0,uViewportSize:[a.width,a.height],inverseVP:[1/a.width,1/a.height]}).draw(b)}else a.toViewport()};LGraphTextureToViewport.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 uViewportSize;\n\t\t\tuniform vec2 inverseVP;\n\t\t\t#define FXAA_REDUCE_MIN (1.0/ 128.0)\n\t\t\t#define FXAA_REDUCE_MUL (1.0 / 8.0)\n\t\t\t#define FXAA_SPAN_MAX 8.0\n\t\t\t\n\t\t\t/* from mitsuhiko/webgl-meincraft based on the code on geeks3d.com */\n\t\t\tvec4 applyFXAA(sampler2D tex, vec2 fragCoord)\n\t\t\t{\n\t\t\t\tvec4 color = vec4(0.0);\n\t\t\t\t/*vec2 inverseVP = vec2(1.0 / uViewportSize.x, 1.0 / uViewportSize.y);*/\n\t\t\t\tvec3 rgbNW = texture2D(tex, (fragCoord + vec2(-1.0, -1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbNE = texture2D(tex, (fragCoord + vec2(1.0, -1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbSW = texture2D(tex, (fragCoord + vec2(-1.0, 1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbSE = texture2D(tex, (fragCoord + vec2(1.0, 1.0)) * inverseVP).xyz;\n\t\t\t\tvec3 rgbM = texture2D(tex, fragCoord * inverseVP).xyz;\n\t\t\t\tvec3 luma = vec3(0.299, 0.587, 0.114);\n\t\t\t\tfloat lumaNW = dot(rgbNW, luma);\n\t\t\t\tfloat lumaNE = dot(rgbNE, luma);\n\t\t\t\tfloat lumaSW = dot(rgbSW, luma);\n\t\t\t\tfloat lumaSE = dot(rgbSE, luma);\n\t\t\t\tfloat lumaM = dot(rgbM, luma);\n\t\t\t\tfloat lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n\t\t\t\tfloat lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\t\t\t\t\n\t\t\t\tvec2 dir;\n\t\t\t\tdir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n\t\t\t\tdir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\t\t\t\t\n\t\t\t\tfloat dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\t\t\t\t\n\t\t\t\tfloat rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n\t\t\t\tdir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * inverseVP;\n\t\t\t\t\n\t\t\t\tvec3 rgbA = 0.5 * (texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + \n\t\t\t\t\ttexture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n\t\t\t\tvec3 rgbB = rgbA * 0.5 + 0.25 * (texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + \n\t\t\t\t\ttexture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\t\t\t\t\n\t\t\t\treturn vec4(rgbA,1.0);\n\t\t\t\tfloat lumaB = dot(rgbB, luma);\n\t\t\t\tif ((lumaB < lumaMin) || (lumaB > lumaMax))\n\t\t\t\t\tcolor = vec4(rgbA, 1.0);\n\t\t\t\telse\n\t\t\t\t\tcolor = vec4(rgbB, 1.0);\n\t\t\t\treturn color;\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/toviewport",LGraphTextureToViewport);var LGraphTextureCopy=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={size:0,generate_mipmaps:!1,precision:LGraphTexture.DEFAULT}};LGraphTextureCopy.title="Copy";LGraphTextureCopy.desc="Copy Texture";LGraphTextureCopy.widgets_info={size:{widget:"combo",values:[0,32,64,128,256,512,1024,2048]},precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureCopy.prototype.onExecute= +function(){var a=this.getInputData(0);if(a||this._temp_texture){if(a){var b=a.width,c=a.height;0!=this.properties.size&&(c=b=this.properties.size);var d=this._temp_texture,e=a.type;this.properties.precision===LGraphTexture.LOW?e=gl.UNSIGNED_BYTE:this.properties.precision===LGraphTexture.HIGH&&(e=gl.HIGH_PRECISION_FORMAT);d&&d.width==b&&d.height==c&&d.type==e||(d=gl.LINEAR,this.properties.generate_mipmaps&&isPowerOfTwo(b)&&isPowerOfTwo(c)&&(d=gl.LINEAR_MIPMAP_LINEAR),this._temp_texture=new GL.Texture(b, +c,{type:e,format:gl.RGBA,minFilter:d,magFilter:gl.LINEAR}));a.copyTo(this._temp_texture);this.properties.generate_mipmaps&&(this._temp_texture.bind(0),gl.generateMipmap(this._temp_texture.texture_type),this._temp_texture.unbind(0))}this.setOutputData(0,this._temp_texture)}};LiteGraph.registerNodeType("texture/copy",LGraphTextureCopy);var LGraphTextureAverage=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={low_precision:!1}};LGraphTextureAverage.title="Average"; +LGraphTextureAverage.desc="Compute the total average of a texture and stores it as a 1x1 pixel texture";LGraphTextureAverage.prototype.onExecute=function(){var a=this.getInputData(0);if(a){if(!LGraphTextureAverage._shader){LGraphTextureAverage._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureAverage.pixel_shader);for(var b=new Float32Array(32),c=0;32>c;++c)b[c]=Math.random();LGraphTextureAverage._shader.uniforms({u_samples_a:b.subarray(0,16),u_samples_b:b.subarray(16,32)})}b=this._temp_texture; +c=this.properties.low_precision?gl.UNSIGNED_BYTE:a.type;b&&b.type==c||(this._temp_texture=new GL.Texture(1,1,{type:c,format:gl.RGBA,filter:gl.NEAREST}));var d=LGraphTextureAverage._shader;this._temp_texture.drawTo(function(){a.toViewport(d,{u_texture:0})});this.setOutputData(0,this._temp_texture)}};LGraphTextureAverage.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tuniform mat4 u_samples_a;\n\t\t\tuniform mat4 u_samples_b;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tvarying vec2 v_coord;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = vec4(0.0);\n\t\t\t\tfor(int i = 0; i < 4; ++i)\n\t\t\t\t\tfor(int j = 0; j < 4; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ) );\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], u_samples_b[i][j] ) );\n\t\t\t\t\t}\n\t\t\t gl_FragColor = color * 0.03125;\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/average",LGraphTextureAverage);var LGraphImageToTexture=function(){this.addInput("Image","image");this.addOutput("","Texture");this.properties={}};LGraphImageToTexture.title="Image to Texture";LGraphImageToTexture.desc="Uploads an image to the GPU";LGraphImageToTexture.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=a.videoWidth||a.width,c=a.videoHeight||a.height;if(a.gltexture)this.setOutputData(0,a.gltexture);else{var d=this._temp_texture; +d&&d.width==b&&d.height==c||(this._temp_texture=new GL.Texture(b,c,{format:gl.RGBA,filter:gl.LINEAR}));try{this._temp_texture.uploadImage(a)}catch(e){console.error("image comes from an unsafe location, cannot be uploaded to webgl");return}this.setOutputData(0,this._temp_texture)}}};LiteGraph.registerNodeType("texture/imageToTexture",LGraphImageToTexture);var LGraphTextureLUT=function(){this.addInput("Texture","Texture");this.addInput("LUT","Texture");this.addInput("Intensity","number");this.addOutput("", +"Texture");this.properties={intensity:1,precision:LGraphTexture.DEFAULT};LGraphTextureLUT._shader||(LGraphTextureLUT._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureLUT.pixel_shader))};LGraphTextureLUT.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureLUT.title="LUT";LGraphTextureLUT.desc="Apply LUT to Texture";LGraphTextureLUT.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0, +a);else if(a){var b=this.getInputData(1);if(b){b.bind(0);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);var c=this.properties.intensity;this.isInputConnected(2)&&(this.properties.intensity=c=this.getInputData(2));this._tex=LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);this._tex.drawTo(function(){b.bind(1); +a.toViewport(LGraphTextureLUT._shader,{u_texture:0,u_textureB:1,u_amount:c})});this.setOutputData(0,this._tex)}else this.setOutputData(0,a)}};LGraphTextureLUT.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform float u_amount;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\t lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\t\t\t\t mediump float blueColor = textureColor.b * 63.0;\n\t\t\t\t mediump vec2 quad1;\n\t\t\t\t quad1.y = floor(floor(blueColor) / 8.0);\n\t\t\t\t quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\t\t\t\t mediump vec2 quad2;\n\t\t\t\t quad2.y = floor(ceil(blueColor) / 8.0);\n\t\t\t\t quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\t\t\t\t highp vec2 texPos1;\n\t\t\t\t texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t highp vec2 texPos2;\n\t\t\t\t texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\t\t\t\t lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\t\t\t\t lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\t\t\t\t gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/LUT",LGraphTextureLUT);var LGraphTextureChannels=function(){this.addInput("Texture","Texture");this.addOutput("R","Texture");this.addOutput("G","Texture");this.addOutput("B","Texture");this.addOutput("A","Texture");this.properties={};LGraphTextureChannels._shader||(LGraphTextureChannels._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureChannels.pixel_shader))};LGraphTextureChannels.title="Texture to Channels";LGraphTextureChannels.desc="Split texture channels"; +LGraphTextureChannels.prototype.onExecute=function(){var a=this.getInputData(0);if(a){this._channels||(this._channels=Array(4));for(var b=0,c=0;4>c;c++)this.isOutputConnected(c)?(this._channels[c]&&this._channels[c].width==a.width&&this._channels[c].height==a.height&&this._channels[c].type==a.type||(this._channels[c]=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR})),b++):this._channels[c]=null;if(b){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);for(var d=Mesh.getScreenQuad(), +e=LGraphTextureChannels._shader,f=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],c=0;4>c;c++)this._channels[c]&&(this._channels[c].drawTo(function(){a.bind(0);e.uniforms({u_texture:0,u_mask:f[c]}).draw(d)}),this.setOutputData(c,this._channels[c]))}}};LGraphTextureChannels.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec4 u_mask;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/textureChannels",LGraphTextureChannels);var LGraphChannelsTexture=function(){this.addInput("R","Texture");this.addInput("G","Texture");this.addInput("B","Texture");this.addInput("A","Texture");this.addOutput("Texture","Texture");this.properties={};LGraphChannelsTexture._shader||(LGraphChannelsTexture._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphChannelsTexture.pixel_shader))};LGraphChannelsTexture.title="Channels to Texture";LGraphChannelsTexture.desc= +"Split texture channels";LGraphChannelsTexture.prototype.onExecute=function(){var a=[this.getInputData(0),this.getInputData(1),this.getInputData(2),this.getInputData(3)];if(a[0]&&a[1]&&a[2]&&a[3]){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),c=LGraphChannelsTexture._shader;this._tex=LGraphTexture.getTargetTexture(a[0],this._tex);this._tex.drawTo(function(){a[0].bind(0);a[1].bind(1);a[2].bind(2);a[3].bind(3);c.uniforms({u_textureR:0,u_textureG:1,u_textureB:2,u_textureA:3}).draw(b)}); +this.setOutputData(0,this._tex)}};LGraphChannelsTexture.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureR;\n\t\t\tuniform sampler2D u_textureG;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( \t\t\t\t\t\ttexture2D(u_textureR, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureG, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureB, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureA, v_coord).r);\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/channelsTexture",LGraphChannelsTexture);var LGraphTextureGradient=function(){this.addInput("A","color");this.addInput("B","color");this.addOutput("Texture","Texture");this.properties={angle:0,scale:1,A:[0,0,0],B:[1,1,1],texture_size:32};LGraphTextureGradient._shader||(LGraphTextureGradient._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureGradient.pixel_shader));this._uniforms={u_angle:0,u_colorA:vec3.create(),u_colorB:vec3.create()}};LGraphTextureGradient.title= +"Gradient";LGraphTextureGradient.desc="Generates a gradient";LGraphTextureGradient["@A"]={type:"color"};LGraphTextureGradient["@B"]={type:"color"};LGraphTextureGradient["@texture_size"]={type:"enum",values:[32,64,128,256,512]};LGraphTextureGradient.prototype.onExecute=function(){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var a=GL.Mesh.getScreenQuad(),b=LGraphTextureGradient._shader,c=this.getInputData(0);c||(c=this.properties.A);var d=this.getInputData(1);d||(d=this.properties.B);for(var e=2;e< +this.inputs.length;e++){var f=this.inputs[e],g=this.getInputData(e);void 0!==g&&(this.properties[f.name]=g)}var h=this._uniforms;this._uniforms.u_angle=this.properties.angle*DEG2RAD;this._uniforms.u_scale=this.properties.scale;vec3.copy(h.u_colorA,c);vec3.copy(h.u_colorB,d);c=parseInt(this.properties.texture_size);this._tex&&this._tex.width==c||(this._tex=new GL.Texture(c,c,{format:gl.RGB,filter:gl.LINEAR}));this._tex.drawTo(function(){b.uniforms(h).draw(a)});this.setOutputData(0,this._tex)};LGraphTextureGradient.prototype.onGetInputs= +function(){return[["angle","number"],["scale","number"]]};LGraphTextureGradient.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform float u_angle;\n\t\t\tuniform float u_scale;\n\t\t\tuniform vec3 u_colorA;\n\t\t\tuniform vec3 u_colorB;\n\t\t\t\n\t\t\tvec2 rotate(vec2 v, float angle)\n\t\t\t{\n\t\t\t\tvec2 result;\n\t\t\t\tfloat _cos = cos(angle);\n\t\t\t\tfloat _sin = sin(angle);\n\t\t\t\tresult.x = v.x * _cos - v.y * _sin;\n\t\t\t\tresult.y = v.x * _sin + v.y * _cos;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tvoid main() {\n\t\t\t\tfloat f = (rotate(u_scale * (v_coord - vec2(0.5)), u_angle) + vec2(0.5)).x;\n\t\t\t\tvec3 color = mix(u_colorA,u_colorB,clamp(f,0.0,1.0));\n\t\t\t gl_FragColor = vec4(color,1.0);\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/gradient",LGraphTextureGradient);var LGraphTextureMix=function(){this.addInput("A","Texture");this.addInput("B","Texture");this.addInput("Mixer","Texture");this.addOutput("Texture","Texture");this.properties={precision:LGraphTexture.DEFAULT};LGraphTextureMix._shader||(LGraphTextureMix._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureMix.pixel_shader))};LGraphTextureMix.title="Mix";LGraphTextureMix.desc="Generates a texture mixing two textures";LGraphTextureMix.widgets_info= +{precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphTextureMix.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else{var b=this.getInputData(1),c=this.getInputData(2);if(a&&b&&c){this._tex=LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var d=Mesh.getScreenQuad(),e=LGraphTextureMix._shader;this._tex.drawTo(function(){a.bind(0); +b.bind(1);c.bind(2);e.uniforms({u_textureA:0,u_textureB:1,u_textureMix:2}).draw(d)});this.setOutputData(0,this._tex)}}};LGraphTextureMix.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureMix;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), texture2D(u_textureMix, v_coord) );\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/mix",LGraphTextureMix);var LGraphTextureEdges=function(){this.addInput("Tex.","Texture");this.addOutput("Edges","Texture");this.properties={invert:!0,precision:LGraphTexture.DEFAULT};LGraphTextureEdges._shader||(LGraphTextureEdges._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureEdges.pixel_shader))};LGraphTextureEdges.title="Edges";LGraphTextureEdges.desc="Detects edges";LGraphTextureEdges.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}}; +LGraphTextureEdges.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),c=LGraphTextureEdges._shader,d=this.properties.invert;this._tex.drawTo(function(){a.bind(0);c.uniforms({u_texture:0,u_isize:[1/a.width,1/a.height],u_invert:d?1:0}).draw(b)});this.setOutputData(0, +this._tex)}};LGraphTextureEdges.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_isize;\n\t\t\tuniform int u_invert;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 center = texture2D(u_texture, v_coord);\n\t\t\t\tvec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\t\t\t\tvec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\t\t\t\tvec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\t\t\t\tvec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\t\t\t\tvec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\t\t\t\tif(u_invert == 1)\n\t\t\t\t\tdiff.xyz = vec3(1.0) - diff.xyz;\n\t\t\t gl_FragColor = vec4( diff.xyz, center.a );\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/edges",LGraphTextureEdges);var LGraphTextureDepthRange=function(){this.addInput("Texture","Texture");this.addInput("Distance","number");this.addInput("Range","number");this.addOutput("Texture","Texture");this.properties={distance:100,range:50,high_precision:!1};LGraphTextureDepthRange._shader||(LGraphTextureDepthRange._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureDepthRange.pixel_shader))};LGraphTextureDepthRange.title="Depth Range";LGraphTextureDepthRange.desc= +"Generates a texture with a depth range";LGraphTextureDepthRange.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=gl.UNSIGNED_BYTE;this.properties.high_precision&&(b=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==b&&this._temp_texture.width==a.width&&this._temp_texture.height==a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:b,format:gl.RGBA,filter:gl.LINEAR}));var c=this.properties.distance;this.isInputConnected(1)&& +(c=this.getInputData(1),this.properties.distance=c);var d=this.properties.range;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.range=d);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad(),f=LGraphTextureDepthRange._shader,g=[Renderer._current_camera.near,Renderer._current_camera.far];this._temp_texture.drawTo(function(){a.bind(0);f.uniforms({u_texture:0,u_distance:c,u_range:d,u_camera_planes:g}).draw(e)});this.setOutputData(0,this._temp_texture)}};LGraphTextureDepthRange.pixel_shader= +"precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_distance;\n\t\t\tuniform float u_range;\n\t\t\t\n\t\t\tfloat LinearDepth()\n\t\t\t{\n\t\t\t\tfloat n = u_camera_planes.x;\n\t\t\t\tfloat f = u_camera_planes.y;\n\t\t\t\treturn (2.0 * n) / (f + n - texture2D(u_texture, v_coord).x * (f - n));\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tfloat diff = abs(LinearDepth() * u_camera_planes.y - u_distance);\n\t\t\t\tfloat dof = 1.0;\n\t\t\t\tif(diff <= u_range)\n\t\t\t\t\tdof = diff / u_range;\n\t\t\t gl_FragColor = vec4(dof);\n\t\t\t}\n\t\t\t"; +LiteGraph.registerNodeType("texture/depth_range",LGraphTextureDepthRange);var LGraphTextureBlur=function(){this.addInput("Texture","Texture");this.addInput("Iterations","number");this.addInput("Intensity","number");this.addOutput("Blurred","Texture");this.properties={intensity:1,iterations:1,preserve_aspect:!1,scale:[1,1]};LGraphTextureBlur._shader||(LGraphTextureBlur._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphTextureBlur.pixel_shader))};LGraphTextureBlur.title="Blur";LGraphTextureBlur.desc= +"Blur a texture";LGraphTextureBlur.max_iterations=20;LGraphTextureBlur.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=this._temp_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}),this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));b=this.properties.iterations;this.isInputConnected(1)&&(b=this.getInputData(1),this.properties.iterations= +b);b=Math.min(Math.floor(b),LGraphTextureBlur.max_iterations);if(0==b)this.setOutputData(0,a);else{var c=this.properties.intensity;this.isInputConnected(2)&&(c=this.getInputData(2),this.properties.intensity=c);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var d=Mesh.getScreenQuad(),e=LGraphTextureBlur._shader,f=this.properties.scale||[1,1],g=LiteGraph.camera_aspect;g||void 0===window.gl||(g=gl.canvas.height/gl.canvas.width);g||(g=1);for(var h=a,g=this.properties.preserve_aspect?g:1,a=0;a=this.size[1]||!this._video||(a.save(),a.webgl?this._temp_texture&&a.drawImage(this._temp_texture,0,0,this.size[0],this.size[1]):(a.translate(0,this.size[1]),a.scale(1,-1),a.drawImage(this._video,0,0,this.size[0],this.size[1])),a.restore())};LGraphTextureWebcam.prototype.onExecute=function(){null!=this._webcam_stream||this._waiting_confirmation||this.openStream();if(this._video&& +this._video.videoWidth){var a=this._video.videoWidth,b=this._video.videoHeight,c=this._temp_texture;c&&c.width==a&&c.height==b||(this._temp_texture=new GL.Texture(a,b,{format:gl.RGB,filter:gl.LINEAR}));this._temp_texture.uploadImage(this._video);this.properties.texture_name&&(LGraphTexture.getTexturesContainer()[this.properties.texture_name]=this._temp_texture);this.setOutputData(0,this._temp_texture)}};LiteGraph.registerNodeType("texture/webcam",LGraphTextureWebcam);var LGraphCubemap=function(){this.addOutput("Cubemap", +"Cubemap");this.properties={name:""};this.size=[LGraphTexture.image_preview_size,LGraphTexture.image_preview_size]};LGraphCubemap.prototype.onDropFile=function(a,b,c){a?(this._drop_texture="string"==typeof a?GL.Texture.fromURL(a):GL.Texture.fromDDSInMemory(a),this.properties.name=b):(this._drop_texture=null,this.properties.name="")};LGraphCubemap.prototype.onExecute=function(){if(this._drop_texture)this.setOutputData(0,this._drop_texture);else if(this.properties.name){var a=LGraphTexture.getTexture(this.properties.name); +a&&(this._last_tex=a,this.setOutputData(0,a))}};LGraphCubemap.prototype.onDrawBackground=function(a){this.flags.collapsed||20>=this.size[1]||a.webgl&&(gl.meshes.cube||(gl.meshes.cube=GL.Mesh.cube({size:1})))};LiteGraph.registerNodeType("texture/cubemap",LGraphCubemap)} if("undefined"!=typeof LiteGraph){var LGraphFXLens=function(){this.addInput("Texture","Texture");this.addInput("Aberration","number");this.addInput("Distortion","number");this.addInput("Blur","number");this.addOutput("Texture","Texture");this.properties={aberration:1,distortion:1,blur:1,precision:LGraphTexture.DEFAULT};LGraphFXLens._shader||(LGraphFXLens._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphFXLens.pixel_shader))};LGraphFXLens.title="Lens";LGraphFXLens.desc="Camera Lens distortion"; LGraphFXLens.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};LGraphFXLens.prototype.onExecute=function(){var a=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=LGraphTexture.getTargetTexture(a,this._tex,this.properties.precision);var b=this.properties.aberration;this.isInputConnected(1)&&(b=this.getInputData(1),this.properties.aberration=b);var c=this.properties.distortion;this.isInputConnected(2)&& (c=this.getInputData(2),this.properties.distortion=c);var d=this.properties.blur;this.isInputConnected(3)&&(d=this.getInputData(3),this.properties.blur=d);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad(),f=LGraphFXLens._shader;this._tex.drawTo(function(){a.bind(0);f.uniforms({u_texture:0,u_aberration:b,u_distortion:c,u_blur:d}).draw(e)});this.setOutputData(0,this._tex)}};LGraphFXLens.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_aberration;\n\t\t\tuniform float u_distortion;\n\t\t\tuniform float u_blur;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 coord = v_coord;\n\t\t\t\tfloat dist = distance(vec2(0.5), coord);\n\t\t\t\tvec2 dist_coord = coord - vec2(0.5);\n\t\t\t\tfloat percent = 1.0 + ((0.5 - dist) / 0.5) * u_distortion;\n\t\t\t\tdist_coord *= percent;\n\t\t\t\tcoord = dist_coord + vec2(0.5);\n\t\t\t\tvec4 color = texture2D(u_texture,coord, u_blur * dist);\n\t\t\t\tcolor.r = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0+0.01*u_aberration), u_blur * dist ).r;\n\t\t\t\tcolor.b = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0-0.01*u_aberration), u_blur * dist ).b;\n\t\t\t\tgl_FragColor = color;\n\t\t\t}\n\t\t\t"; LiteGraph.registerNodeType("fx/lens",LGraphFXLens);window.LGraphFXLens=LGraphFXLens;var LGraphFXBokeh=function(){this.addInput("Texture","Texture");this.addInput("Blurred","Texture");this.addInput("Mask","Texture");this.addInput("Threshold","number");this.addOutput("Texture","Texture");this.properties={shape:"",size:10,alpha:1,threshold:1,high_precision:!1}};LGraphFXBokeh.title="Bokeh";LGraphFXBokeh.desc="applies an Bokeh effect";LGraphFXBokeh.widgets_info={shape:{widget:"texture"}};LGraphFXBokeh.prototype.onExecute= function(){var a=this.getInputData(0),b=this.getInputData(1),c=this.getInputData(2);if(a&&c&&this.properties.shape){b||(b=a);var d=LGraphTexture.getTexture(this.properties.shape);if(d){var e=this.properties.threshold;this.isInputConnected(3)&&(e=this.getInputData(3),this.properties.threshold=e);var f=gl.UNSIGNED_BYTE;this.properties.high_precision&&(f=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==f&&this._temp_texture.width==a.width&&this._temp_texture.height== -a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:f,format:gl.RGBA,filter:gl.LINEAR}));var g=LGraphFXBokeh._first_shader;g||(g=LGraphFXBokeh._first_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,LGraphFXBokeh._first_pixel_shader));var h=LGraphFXBokeh._second_shader;h||(h=LGraphFXBokeh._second_shader=new GL.Shader(LGraphFXBokeh._second_vertex_shader,LGraphFXBokeh._second_pixel_shader));var l=this._points_mesh;l&&l._width==a.width&&l._height==a.height&&2==l._spacing||(l=this.createPointsMesh(a.width, -a.height,2));var n=Mesh.getScreenQuad(),k=this.properties.size,p=this.properties.alpha;gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){a.bind(0);b.bind(1);c.bind(2);g.uniforms({u_texture:0,u_texture_blur:1,u_mask:2,u_texsize:[a.width,a.height]}).draw(n)});this._temp_texture.drawTo(function(){gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);a.bind(0);d.bind(3);h.uniforms({u_texture:0,u_mask:2,u_shape:3,u_alpha:p,u_threshold:e,u_pointSize:k,u_itexsize:[1/a.width,1/ -a.height]}).draw(l,gl.POINTS)});this.setOutputData(0,this._temp_texture)}}else this.setOutputData(0,a)};LGraphFXBokeh.prototype.createPointsMesh=function(a,b,c){for(var d=Math.round(a/c),e=Math.round(b/c),f=new Float32Array(d*e*2),g=-1,h=2/a*c,l=2/b*c,n=0;n -1 && slot < this.outputs.length && this.outputs[slot] && this.outputs[slot].links != null) { for(var i = 0; i < this.outputs[slot].links.length; i++) @@ -1327,17 +1347,18 @@ LGraphNode.prototype.setOutputData = function(slot,data) } /** -* retrieves the input data from one slot +* retrieves the input data (data traveling through the connection) from one slot * @method getInputData * @param {number} slot * @return {*} data */ LGraphNode.prototype.getInputData = function(slot) { - if(!this.inputs) return null; + if(!this.inputs) + return; //undefined; if(slot < this.inputs.length && this.inputs[slot].link != null) return this.graph.links[ this.inputs[slot].link ].data; - return null; + return; //undefined; } /** @@ -1348,7 +1369,8 @@ LGraphNode.prototype.getInputData = function(slot) */ LGraphNode.prototype.isInputConnected = function(slot) { - if(!this.inputs) return null; + if(!this.inputs) + return false; return (slot < this.inputs.length && this.inputs[slot].link != null); } @@ -1428,7 +1450,7 @@ LGraphNode.prototype.triggerOutput = function(slot,param) * @method addOutput * @param {string} name * @param {string} type string defining the output type ("vec3","number",...) -* @param {Object} extra_info this can be used to have special properties of an output (special color, position, etc) +* @param {Object} extra_info this can be used to have special properties of an output (label, special color, position, etc) */ LGraphNode.prototype.addOutput = function(name,type,extra_info) { @@ -1487,11 +1509,12 @@ LGraphNode.prototype.removeOutput = function(slot) * add a new input slot to use in this node * @method addInput * @param {string} name -* @param {string} type string defining the input type ("vec3","number",...) +* @param {string} type string defining the input type ("vec3","number",...), it its a generic one use 0 * @param {Object} extra_info this can be used to have special properties of an input (label, color, position, etc) */ LGraphNode.prototype.addInput = function(name,type,extra_info) { + type = type || 0; var o = {name:name,type:type,link:null}; if(extra_info) for(var i in extra_info) @@ -2509,7 +2532,7 @@ LGraphCanvas.prototype.processMouseDown = function(e) var link_pos = n.getConnectionPos(true,i); if( isInsideRectangle(e.canvasX, e.canvasY, link_pos[0] - 10, link_pos[1] - 5, 20,10) ) { - if(input.link) + if(input.link !== null) { n.disconnectInput(i); this.dirty_bgcanvas = true; @@ -2887,6 +2910,7 @@ LGraphCanvas.prototype.processKeyDown = function(e) if(e.keyCode == 46 || e.keyCode == 8) { this.deleteSelectedNodes(); + block_default = true; } //collapse @@ -3183,8 +3207,8 @@ LGraphCanvas.prototype.drawFrontCanvas = function() if(!ctx) //maybe is using webgl... return; - if(ctx.start) - ctx.start(); + if(ctx.start2D) + ctx.start2D(); var canvas = this.canvas; @@ -3298,8 +3322,8 @@ LGraphCanvas.prototype.drawFrontCanvas = function() //this.dirty_area = null; } - if(ctx.finish) //this is a function I use in webgl renderer - ctx.finish(); + if(ctx.finish2D) //this is a function I use in webgl renderer + ctx.finish2D(); this.dirty_canvas = false; } @@ -4057,11 +4081,11 @@ LGraphCanvas.onMenuNodeInputs = function(node, e, prev_menu) var entries = []; for (var i in options) { - var option = options[i]; - var label = option[0]; - if(option[2] && option[2].label) - label = option[2].label; - entries.push({content: label, value: option}); + var entry = options[i]; + var label = entry[0]; + if(entry[2] && entry[2].label) + label = entry[2].label; + entries.push({content: label, value: entry}); } var menu = LiteGraph.createContextualMenu(entries, {event: e, callback: inner_clicked, from: prev_menu}); } @@ -4087,9 +4111,13 @@ LGraphCanvas.onMenuNodeOutputs = function(node, e, prev_menu) var entries = []; for (var i in options) { - if(node.findOutputSlot(options[i][0]) != -1) + var entry = options[i]; + if(node.findOutputSlot(entry[0]) != -1) continue; //skip the ones already on - entries.push({content: options[i][0], value: options[i]}); + var label = entry[0]; + if(entry[2] && entry[2].label) + label = entry[2].label; + entries.push({content: label, value: entry}); } if(entries.length) var menu = LiteGraph.createContextualMenu(entries, {event: e, callback: inner_clicked, from: prev_menu}); @@ -4097,7 +4125,8 @@ LGraphCanvas.onMenuNodeOutputs = function(node, e, prev_menu) function inner_clicked(v) { - if(!node) return; + if(!node) + return; var value = v.value[1]; @@ -4110,7 +4139,7 @@ LGraphCanvas.onMenuNodeOutputs = function(node, e, prev_menu) return false; } else - node.addOutput(v.value[0],v.value[1]); + node.addOutput(v.value[0], v.value[1], v.value[2]); } return false; @@ -4423,7 +4452,7 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) LiteGraph.closeAllContextualMenus(); var root = ref_window.document.createElement("div"); - root.className = "litecontextualmenu litemenubar-panel"; + root.className = "graphcontextualmenu graphmenubar-panel"; this.root = root; var style = root.style; @@ -4445,11 +4474,11 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) { var item = values[i]; var element = ref_window.document.createElement("div"); - element.className = "litemenu-entry"; + element.className = "graphmenu-entry"; if(item == null) { - element.className = "litemenu-entry separator"; + element.className = "graphmenu-entry separator"; root.appendChild(element); continue; } @@ -4532,7 +4561,7 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) if(options.callback) { var ret = options.callback.call(root, this.data, e ); - if( ret != undefined ) close = ret; + if( ret !== undefined ) close = ret; } if(close) @@ -4557,7 +4586,7 @@ LiteGraph.createContextualMenu = function(values,options, ref_window) LiteGraph.closeAllContextualMenus = function() { - var elements = document.querySelectorAll(".litecontextualmenu"); + var elements = document.querySelectorAll(".graphcontextualmenu"); if(!elements.length) return; var result = []; diff --git a/src/nodes/base.js b/src/nodes/base.js index a26779b7a..c87513167 100644 --- a/src/nodes/base.js +++ b/src/nodes/base.js @@ -333,210 +333,34 @@ Watch.prototype.onDrawBackground = function(ctx) if (this.properties["value"].constructor === Number ) this.inputs[0].label = this.properties["value"].toFixed(3); else - this.inputs[0].label = this.properties["value"]; + { + var str = this.properties["value"]; + if(str && str.length) //convert typed to array + str = Array.prototype.slice.call(str).join(","); + this.inputs[0].label = str; + } } } LiteGraph.registerNodeType("basic/watch", Watch); +//Show value inside the debug console +function Console() +{ + this.size = [60,20]; + this.addInput("data",0); +} -/* -LiteGraph.registerNodeType("math/sinusoid",{ - title: "Sin", - desc: "Sinusoidal value generator", - bgImageUrl: "nodes/imgs/icon-sin.png", +Console.title = "Console"; +Console.desc = "Show value inside the console"; - inputs: [["f",'number'],["q",'number'],["a",'number'],["t",'number']], - outputs: [["",'number']], - properties: {amplitude:1.0, freq: 1, phase:0}, +Console.prototype.onExecute = function() +{ + console.log( this.getInputData(0) ); +} - onExecute: function() - { - var f = this.getInputData(0); - if(f != null) - this.properties["freq"] = f; - - var q = this.getInputData(1); - if(q != null) - this.properties["phase"] = q; - - var a = this.getInputData(2); - if(a != null) - this.properties["amplitude"] = a; - - var t = this.graph.getFixedTime(); - if(this.getInputData(3) != null) - t = this.getInputData(3); - // t = t/(2*Math.PI); t = (t-Math.floor(t))*(2*Math.PI); - - var v = this.properties["amplitude"] * Math.sin((2*Math.PI) * t * this.properties["freq"] + this.properties["phase"]); - this.setOutputData(0, v ); - }, - - onDragBackground: function(ctx) - { - this.boxcolor = colorToString(v > 0 ? [0.5,0.8,1,0.5] : [0,0,0,0.5]); - this.setDirtyCanvas(true); - }, -}); -*/ - -/* -LiteGraph.registerNodeType("basic/number",{ - title: "Number", - -// System vars ********************************* - -LiteGraph.registerNodeType("session/info",{ - title: "Time", - desc: "Seconds since start", - - outputs: [["secs",'number']], - properties: {scale:1.0}, - onExecute: function() - { - this.setOutputData(0, this.session.getTime() * this.properties.scale); - } -}); - -LiteGraph.registerNodeType("system/fixedtime",{ - title: "F.Time", - desc: "Constant time value", - - outputs: [["secs",'number']], - properties: {scale:1.0}, - onExecute: function() - { - this.setOutputData(0, this.session.getFixedTime() * this.properties.scale); - } -}); - - -LiteGraph.registerNodeType("system/elapsedtime",{ - title: "Elapsed", - desc: "Seconds elapsed since last execution", - - outputs: [["secs",'number']], - properties: {scale:1.0}, - onExecute: function() - { - this.setOutputData(0, this.session.getElapsedTime() * this.properties.scale); - } -}); - -LiteGraph.registerNodeType("system/iterations",{ - title: "Iterations", - desc: "Number of iterations (executions)", - - outputs: [["",'number']], - onExecute: function() - { - this.setOutputData(0, this.session.iterations ); - } -}); - -LiteGraph.registerNodeType("system/trace",{ - desc: "Outputs input to browser's console", - - inputs: [["",0]], - onExecute: function() - { - var data = this.getInputData(0); - if(data) - trace("DATA: "+data); - } -}); - -/* -LiteGraph.registerNodeType("math/not",{ - title: "Not", - desc: "0 -> 1 or 0 -> 1", - inputs: [["A",'number']], - outputs: [["!A",'number']], - size: [60,22], - onExecute: function() - { - var v = this.getInputData(0); - if(v != null) - this.setOutputData(0, v ? 0 : 1); - } -}); - - - -// Nodes for network in and out -LiteGraph.registerNodeType("network/general/network_input",{ - title: "N.Input", - desc: "Network Input", - outputs: [["",0]], - color: "#00ff96", - bgcolor: "#004327", - - setValue: function(v) - { - this.value = v; - }, - - onExecute: function() - { - this.setOutputData(0, this.value); - } -}); - -LiteGraph.registerNodeType("network/general/network_output",{ - title: "N.Output", - desc: "Network output", - inputs: [["",0]], - color: "#a8ff00", - bgcolor: "#293e00", - - properties: {value:null}, - - getValue: function() - { - return this.value; - }, - - onExecute: function() - { - this.value = this.getOutputData(0); - } -}); - -LiteGraph.registerNodeType("network/network_trigger",{ - title: "N.Trigger", - desc: "Network input trigger", - outputs: [["",0]], - color: "#ff9000", - bgcolor: "#522e00", - - onTrigger: function(v) - { - this.triggerOutput(0,v); - }, -}); - -LiteGraph.registerNodeType("network/network_callback",{ - title: "N.Callback", - desc: "Network callback output.", - outputs: [["",0]], - color: "#6A6", - bgcolor: "#363", - - setTrigger: function(func) - { - this.callback = func; - }, - - onTrigger: function(v) - { - if(this.callback) - this.callback(v); - }, -}); - -*/ +LiteGraph.registerNodeType("basic/console", Console ); })(); \ No newline at end of file diff --git a/src/nodes/gltextures.js b/src/nodes/gltextures.js index 9f7907cc6..cf8f0facf 100644 --- a/src/nodes/gltextures.js +++ b/src/nodes/gltextures.js @@ -13,7 +13,6 @@ if(typeof(LiteGraph) != "undefined") LGraphTexture.widgets_info = {"name": { widget:"texture"} }; //REPLACE THIS TO INTEGRATE WITH YOUR FRAMEWORK - LGraphTexture.textures_container = {}; //where to seek for the textures, if not specified it uses gl.textures LGraphTexture.loadTextureCallback = null; //function in charge of loading textures when not present in the container LGraphTexture.image_preview_size = 256; @@ -34,9 +33,31 @@ if(typeof(LiteGraph) != "undefined") "default": LGraphTexture.DEFAULT }; + //returns the container where all the loaded textures are stored (overwrite if you have a Resources Manager) + LGraphTexture.getTexturesContainer = function() + { + return gl.textures; + } + + //process the loading of a texture (overwrite if you have a Resources Manager) + LGraphTexture.loadTexture = function(name, options) + { + options = options || {}; + var url = name; + if(url.substr(0,7) == "http://") + { + if(LiteGraph.proxy) //proxy external files + url = LiteGraph.proxy + url.substr(7); + } + + var container = LGraphTexture.getTexturesContainer(); + var tex = container[ name ] = GL.Texture.fromURL(url, options); + return tex; + } + LGraphTexture.getTexture = function(name) { - var container = LGraphTexture.textures_container || gl.textures; + var container = this.getTexturesContainer(); if(!container) throw("Cannot load texture, container of textures not found"); @@ -44,25 +65,8 @@ if(typeof(LiteGraph) != "undefined") var tex = container[ name ]; if(!tex && name && name[0] != ":") { - //texture must be loaded - if(LGraphTexture.loadTextureCallback) - { - //calls the method in charge of loading resources (in LiteScene would be ResourcesManager.load) - var loader = LGraphTexture.loadTextureCallback; - if(loader) - loader( name ); - return null; - } - else - { - var url = name; - if(url.substr(0,7) == "http://") - { - if(LiteGraph.proxy) //proxy external files - url = LiteGraph.proxy + url.substr(7); - } - tex = container[ name ] = GL.Texture.fromURL(url, {}); - } + this.loadTexture(name); + return null; } return tex; @@ -255,7 +259,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/texture", LGraphTexture ); - window.LGraphTexture = LGraphTexture; //************************** function LGraphTexturePreview() @@ -294,7 +297,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/preview", LGraphTexturePreview ); - window.LGraphTexturePreview = LGraphTexturePreview; //************************************** @@ -314,13 +316,15 @@ if(typeof(LiteGraph) != "undefined") if(!tex) return; if(this.properties.name) - LGraphTexture.textures_container[ this.properties.name ] = tex; + { + var container = LGraphTexture.getTexturesContainer(); + container[ this.properties.name ] = tex; + } this.setOutputData(0, tex); } LiteGraph.registerNodeType("texture/save", LGraphTextureSave ); - window.LGraphTextureSave = LGraphTextureSave; //**************************************************** @@ -505,7 +509,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/operation", LGraphTextureOperation ); - window.LGraphTextureOperation = LGraphTextureOperation; //**************************************************** @@ -595,7 +598,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/shader", LGraphTextureShader ); - window.LGraphTextureShader = LGraphTextureShader; // Texture to Viewport ***************************************** function LGraphTextureToViewport() @@ -699,7 +701,6 @@ if(typeof(LiteGraph) != "undefined") LiteGraph.registerNodeType("texture/toviewport", LGraphTextureToViewport ); - window.LGraphTextureToViewport = LGraphTextureToViewport; // Texture Copy ***************************************** @@ -765,7 +766,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/copy", LGraphTextureCopy ); - window.LGraphTextureCopy = LGraphTextureCopy; // Texture Copy ***************************************** @@ -777,7 +777,7 @@ if(typeof(LiteGraph) != "undefined") } LGraphTextureAverage.title = "Average"; - LGraphTextureAverage.desc = "Compute average of a texture and stores it as a texture"; + LGraphTextureAverage.desc = "Compute the total average of a texture and stores it as a 1x1 pixel texture"; LGraphTextureAverage.prototype.onExecute = function() { @@ -826,7 +826,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/average", LGraphTextureAverage ); - window.LGraphTextureAverage = LGraphTextureAverage; // Image To Texture ***************************************** function LGraphImageToTexture() @@ -874,7 +873,6 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/imageToTexture", LGraphImageToTexture ); - window.LGraphImageToTexture = LGraphImageToTexture; // Texture LUT ***************************************** @@ -967,7 +965,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/LUT", LGraphTextureLUT ); - window.LGraphTextureLUT = LGraphTextureLUT; // Texture Channels ***************************************** function LGraphTextureChannels() @@ -1043,7 +1040,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/textureChannels", LGraphTextureChannels ); - window.LGraphTextureChannels = LGraphTextureChannels; // Texture Channels to Texture ***************************************** @@ -1110,7 +1106,98 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/channelsTexture", LGraphChannelsTexture ); - window.LGraphChannelsTexture = LGraphChannelsTexture; + + // Texture Channels to Texture ***************************************** + function LGraphTextureGradient() + { + this.addInput("A","color"); + this.addInput("B","color"); + this.addOutput("Texture","Texture"); + + this.properties = { angle: 0, scale: 1, A:[0,0,0], B:[1,1,1], texture_size:32 }; + if(!LGraphTextureGradient._shader) + LGraphTextureGradient._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphTextureGradient.pixel_shader ); + + this._uniforms = { u_angle: 0, u_colorA: vec3.create(), u_colorB: vec3.create()}; + } + + LGraphTextureGradient.title = "Gradient"; + LGraphTextureGradient.desc = "Generates a gradient"; + LGraphTextureGradient["@A"] = { type:"color" }; + LGraphTextureGradient["@B"] = { type:"color" }; + LGraphTextureGradient["@texture_size"] = { type:"enum", values:[32,64,128,256,512] }; + + LGraphTextureGradient.prototype.onExecute = function() + { + gl.disable( gl.BLEND ); + gl.disable( gl.DEPTH_TEST ); + + var mesh = GL.Mesh.getScreenQuad(); + var shader = LGraphTextureGradient._shader; + + var A = this.getInputData(0); + if(!A) + A = this.properties.A; + var B = this.getInputData(1); + if(!B) + B = this.properties.B; + + //angle and scale + for(var i = 2; 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 uniforms = this._uniforms; + this._uniforms.u_angle = this.properties.angle * DEG2RAD; + this._uniforms.u_scale = this.properties.scale; + vec3.copy( uniforms.u_colorA, A ); + vec3.copy( uniforms.u_colorB, B ); + + var size = parseInt( this.properties.texture_size ); + if(!this._tex || this._tex.width != size ) + this._tex = new GL.Texture( size, size, { format: gl.RGB, filter: gl.LINEAR }); + + this._tex.drawTo( function() { + shader.uniforms(uniforms).draw(mesh); + }); + this.setOutputData(0, this._tex); + } + + LGraphTextureGradient.prototype.onGetInputs = function() + { + return [["angle","number"],["scale","number"]]; + } + + LGraphTextureGradient.pixel_shader = "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform float u_angle;\n\ + uniform float u_scale;\n\ + uniform vec3 u_colorA;\n\ + uniform vec3 u_colorB;\n\ + \n\ + vec2 rotate(vec2 v, float angle)\n\ + {\n\ + vec2 result;\n\ + float _cos = cos(angle);\n\ + float _sin = sin(angle);\n\ + result.x = v.x * _cos - v.y * _sin;\n\ + result.y = v.x * _sin + v.y * _cos;\n\ + return result;\n\ + }\n\ + void main() {\n\ + float f = (rotate(u_scale * (v_coord - vec2(0.5)), u_angle) + vec2(0.5)).x;\n\ + vec3 color = mix(u_colorA,u_colorB,clamp(f,0.0,1.0));\n\ + gl_FragColor = vec4(color,1.0);\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/gradient", LGraphTextureGradient ); // Texture Mix ***************************************** function LGraphTextureMix() @@ -1178,7 +1265,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/mix", LGraphTextureMix ); - window.LGraphTextureMix = LGraphTextureMix; // Texture Edges detection ***************************************** function LGraphTextureEdges() @@ -1249,7 +1335,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/edges", LGraphTextureEdges ); - window.LGraphTextureEdges = LGraphTextureEdges; // Texture Depth ***************************************** function LGraphTextureDepthRange() @@ -1299,11 +1384,14 @@ if(typeof(LiteGraph) != "undefined") gl.disable( gl.DEPTH_TEST ); var mesh = Mesh.getScreenQuad(); var shader = LGraphTextureDepthRange._shader; + + //TODO: this asumes we have LiteScene, change it var camera = Renderer._current_camera; + var planes = [Renderer._current_camera.near,Renderer._current_camera.far]; this._temp_texture.drawTo( function() { tex.bind(0); - shader.uniforms({u_texture:0, u_distance: distance, u_range: range, u_camera_planes: [Renderer._current_camera.near,Renderer._current_camera.far] }) + shader.uniforms({u_texture:0, u_distance: distance, u_range: range, u_camera_planes: planes }) .draw(mesh); }); @@ -1335,7 +1423,6 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/depth_range", LGraphTextureDepthRange ); - window.LGraphTextureDepthRange = LGraphTextureDepthRange; // Texture Blur ***************************************** function LGraphTextureBlur() @@ -1449,13 +1536,12 @@ if(typeof(LiteGraph) != "undefined") "; LiteGraph.registerNodeType("texture/blur", LGraphTextureBlur ); - window.LGraphTextureBlur = LGraphTextureBlur; // Texture Webcam ***************************************** function LGraphTextureWebcam() { this.addOutput("Webcam","Texture"); - this.properties = {}; + this.properties = { texture_name: "" }; } LGraphTextureWebcam.title = "Webcam"; @@ -1556,14 +1642,20 @@ if(typeof(LiteGraph) != "undefined") this._temp_texture = new GL.Texture( width, height, { format: gl.RGB, filter: gl.LINEAR }); this._temp_texture.uploadImage( this._video ); + + if(this.properties.texture_name) + { + var container = LGraphTexture.getTexturesContainer(); + container[ this.properties.texture_name ] = this._temp_texture; + } + this.setOutputData(0,this._temp_texture); } LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam ); - window.LGraphTextureWebcam = LGraphTextureWebcam; - + //Cubemap reader function LGraphCubemap() { this.addOutput("Cubemap","Cubemap"); @@ -1623,7 +1715,5 @@ if(typeof(LiteGraph) != "undefined") } LiteGraph.registerNodeType("texture/cubemap", LGraphCubemap ); - window.LGraphCubemap = LGraphCubemap; - } //litegl.js defined \ No newline at end of file diff --git a/src/nodes/logic.js b/src/nodes/logic.js new file mode 100644 index 000000000..09099dcee --- /dev/null +++ b/src/nodes/logic.js @@ -0,0 +1,37 @@ +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); + diff --git a/src/nodes/math.js b/src/nodes/math.js index 091a5ca4f..1659fa7a4 100644 --- a/src/nodes/math.js +++ b/src/nodes/math.js @@ -13,6 +13,16 @@ MathRand.desc = "Random number"; MathRand.prototype.onExecute = function() { + if(this.inputs) + for(var i = 0; 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 min = this.properties.min; var max = this.properties.max; this._last_v = Math.random() * (max-min) + min; @@ -28,6 +38,10 @@ MathRand.prototype.onDrawBackground = function(ctx) this.outputs[0].label = "?"; } +MathRand.prototype.onGetInputs = function() { + return [["min","number"],["max","number"]]; +} + LiteGraph.registerNodeType("math/rand", MathRand); //Math clamp @@ -154,18 +168,19 @@ function MathOperation() { this.addInput("A","number"); this.addInput("B","number"); - this.addOutput("A+B","number"); - this.properties = {A:1.0, B:1.0}; + this.addOutput("=","number"); + this.properties = {A:1.0, B:1.0, OP:"+"}; } MathOperation.title = "Operation"; MathOperation.desc = "Easy math operators"; +MathOperation["@OP"] = { type:"enum", title: "operation", values:["+","-","*","/","%","^"]}; + MathOperation.prototype.setValue = function(v) { if( typeof(v) == "string") v = parseFloat(v); this.properties["value"] = v; - this.setDirtyCanvas(true); } MathOperation.prototype.onExecute = function() @@ -182,42 +197,36 @@ MathOperation.prototype.onExecute = function() else B = this.properties["B"]; - for(var i = 0, l = this.outputs.length; i < l; ++i) + var result = 0; + switch(this.properties.OP) { - var output = this.outputs[i]; - if(!output.links || !output.links.length) - continue; - var value = 0; - switch( output.name ) - { - case "A+B": value = A+B; break; - case "A-B": value = A-B; break; - case "A*B": value = A*B; break; - case "A/B": value = A/B; break; - } - this.setOutputData(i, value ); + case '+': result = A+B; break; + case '-': result = A-B; break; + case '/': result = A/B; break; + case '%': result = A%B; break; + case '^': result = Math.pow(A,B); break; } + this.setOutputData(0, result ); } -MathOperation.prototype.onGetOutputs = function() +MathOperation.prototype.onDrawBackground = function(ctx) { - return [["A-B","number"],["A*B","number"],["A/B","number"]]; + this.outputs[0].label = "A" + this.properties.OP + "B"; } LiteGraph.registerNodeType("math/operation", MathOperation ); - + //Math compare function MathCompare() { - this.addInputs( "A","number" ); - this.addInputs( "B","number" ); - this.addOutputs("A==B","number"); - this.addOutputs("A!=B","number"); + this.addInput( "A","number" ); + this.addInput( "B","number" ); + this.addOutput("A==B","boolean"); + this.addOutput("A!=B","boolean"); this.properties = {A:0,B:0}; } - MathCompare.title = "Compare"; MathCompare.desc = "compares between two values"; @@ -225,12 +234,12 @@ MathCompare.prototype.onExecute = function() { var A = this.getInputData(0); var B = this.getInputData(1); - if(A!=null) + if(A !== undefined) this.properties["A"] = A; else A = this.properties["A"]; - if(B!=null) + if(B !== undefined) this.properties["B"] = B; else B = this.properties["B"]; @@ -255,11 +264,56 @@ MathCompare.prototype.onExecute = function() MathCompare.prototype.onGetOutputs = function() { - return [["A==B","number"],["A!=B","number"],["A>B","number"],["A=B","number"],["A<=B","number"]]; + return [["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]; } LiteGraph.registerNodeType("math/compare",MathCompare); +function MathCondition() +{ + this.addInput("A","number"); + this.addInput("B","number"); + this.addOutput("out","boolean"); + this.properties = { A:0, B:1, OP:">" }; + this.size = [60,40]; +} + +MathCondition["@OP"] = { type:"enum", title: "operation", values:[">","<","==","!=","<=",">="]}; + +MathCondition.title = "Condition"; +MathCondition.desc = "evaluates condition between A and B"; + +MathCondition.prototype.onExecute = function() +{ + var A = this.getInputData(0); + if(A === undefined) + A = this.properties.A; + else + this.properties.A = A; + + var B = this.getInputData(1); + if(B === undefined) + B = this.properties.B; + else + this.properties.B = B; + + var result = true; + switch(this.properties.OP) + { + case ">": result = A>B; break; + case "<": result = A=": result = A>=B; break; + } + + this.setOutputData(0, result ); +} + +LiteGraph.registerNodeType("math/condition", MathCondition); + + function MathAccumulate() { this.addInput("inc","number"); diff --git a/utils/deploy_files.txt b/utils/deploy_files.txt index 022095d53..65cb39dd1 100644 --- a/utils/deploy_files.txt +++ b/utils/deploy_files.txt @@ -2,6 +2,7 @@ ../src/nodes/base.js ../src/nodes/interface.js ../src/nodes/math.js +../src/nodes/logic.js ../src/nodes/image.js ../src/nodes/gltextures.js ../src/nodes/glfx.js