diff --git a/src/litegraph-editor.js b/src/litegraph-editor.js index fe824d35a..62dd7e77a 100755 --- a/src/litegraph-editor.js +++ b/src/litegraph-editor.js @@ -47,7 +47,7 @@ function Editor(container_id, options) { ".tools-right" ); - if (!options.skip_livemode) + if (!options.skip_livemode) { this.addToolsButton( "livemode_button", "Live", @@ -55,7 +55,8 @@ function Editor(container_id, options) { this.onLiveButton.bind(this), ".tools-right" ); - if (!options.skip_maximize) + } + if (!options.skip_maximize) { this.addToolsButton( "maximize_button", "", @@ -63,11 +64,16 @@ function Editor(container_id, options) { this.onFullscreenButton.bind(this), ".tools-right" ); - if (options.miniwindow) this.addMiniWindow(300, 200); + } + if (options.miniwindow) { + this.addMiniWindow(300, 200); + } //append to DOM var parent = document.getElementById(container_id); - if (parent) parent.appendChild(root); + if (parent) { + parent.appendChild(root); + } graphcanvas.resize(); //graphcanvas.draw(true,true); @@ -89,10 +95,12 @@ Editor.prototype.addLoadCounter = function() { setInterval(function() { meter.querySelector(".cpuload .fgload").style.width = 2 * self.graph.execution_time * 90 + "px"; - if (self.graph.status == LGraph.STATUS_RUNNING) + if (self.graph.status == LGraph.STATUS_RUNNING) { meter.querySelector(".gpuload .fgload").style.width = self.graphcanvas.render_time * 10 * 90 + "px"; - else meter.querySelector(".gpuload .fgload").style.width = 4 + "px"; + } else { + meter.querySelector(".gpuload .fgload").style.width = 4 + "px"; + } }, 200); }; @@ -103,7 +111,9 @@ Editor.prototype.addToolsButton = function( callback, container ) { - if (!container) container = ".tools"; + if (!container) { + container = ".tools"; + } var button = this.createButton(name, icon_url); button.id = id; @@ -128,7 +138,9 @@ Editor.prototype.createPanel = function(title, options) { Editor.prototype.createButton = function(name, icon_url) { var button = document.createElement("button"); - if (icon_url) button.innerHTML = " "; + if (icon_url) { + button.innerHTML = " "; + } button.innerHTML += name; return button; }; @@ -181,13 +193,15 @@ Editor.prototype.onLiveButton = function() { }; Editor.prototype.goFullscreen = function() { - if (this.root.requestFullscreen) + if (this.root.requestFullscreen) { this.root.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - else if (this.root.mozRequestFullscreen) + } else if (this.root.mozRequestFullscreen) { this.root.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - else if (this.root.webkitRequestFullscreen) + } else if (this.root.webkitRequestFullscreen) { this.root.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - else throw "Fullscreen not supported"; + } else { + throw "Fullscreen not supported"; + } var self = this; setTimeout(function() { diff --git a/src/litegraph.js b/src/litegraph.js index 8c2a10b18..cb16b54a3 100755 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -97,11 +97,14 @@ */ registerNodeType: function(type, base_class) { - if (!base_class.prototype) + if (!base_class.prototype) { throw "Cannot register a simple object, it must be a class with a prototype"; + } base_class.type = type; - if (LiteGraph.debug) console.log("Node registered: " + type); + if (LiteGraph.debug) { + console.log("Node registered: " + type); + } var categories = type.split("/"); var classname = base_class.name; @@ -109,15 +112,20 @@ var pos = type.lastIndexOf("/"); base_class.category = type.substr(0, pos); - if (!base_class.title) base_class.title = classname; + if (!base_class.title) { + base_class.title = classname; + } //info.name = name.substr(pos+1,name.length - pos); //extend class - if (base_class.prototype) + if (base_class.prototype) { //is a class - for (var i in LGraphNode.prototype) - if (!base_class.prototype[i]) + for (var i in LGraphNode.prototype) { + if (!base_class.prototype[i]) { base_class.prototype[i] = LGraphNode.prototype[i]; + } + } + } Object.defineProperty(base_class.prototype, "shape", { set: function(v) { @@ -147,27 +155,33 @@ enumerable: true }); - var prev = this.registered_node_types[type]; + var prev = this.registered_node_types[type]; this.registered_node_types[type] = base_class; - if (base_class.constructor.name) this.Nodes[classname] = base_class; - if(LiteGraph.onNodeTypeRegistered) - LiteGraph.onNodeTypeRegistered(type,base_class); - if( prev && LiteGraph.onNodeTypeReplaced) - LiteGraph.onNodeTypeReplaced(type,base_class,prev); + if (base_class.constructor.name) { + this.Nodes[classname] = base_class; + } + if (LiteGraph.onNodeTypeRegistered) { + LiteGraph.onNodeTypeRegistered(type, base_class); + } + if (prev && LiteGraph.onNodeTypeReplaced) { + LiteGraph.onNodeTypeReplaced(type, base_class, prev); + } //warnings - if (base_class.prototype.onPropertyChange) + if (base_class.prototype.onPropertyChange) { console.warn( "LiteGraph node class " + type + " has onPropertyChange method, it must be called onPropertyChanged with d at the end" ); + } if (base_class.supported_extensions) { - for (var i in base_class.supported_extensions) + for (var i in base_class.supported_extensions) { this.node_types_by_file_extension[ base_class.supported_extensions[i].toLowerCase() ] = base_class; + } } }, @@ -191,7 +205,7 @@ var params = Array(func.length); var code = ""; var names = LiteGraph.getParameterNames(func); - for (var i = 0; i < names.length; ++i) + for (var i = 0; i < names.length; ++i) { code += "this.addInput('" + names[i] + @@ -200,19 +214,22 @@ ? "'" + param_types[i] + "'" : "0") + ");\n"; + } code += "this.addOutput('out'," + (return_type ? "'" + return_type + "'" : 0) + ");\n"; - if (properties) + if (properties) { code += "this.properties = " + JSON.stringify(properties) + ";\n"; + } var classobj = Function(code); classobj.title = name.split("/").pop(); classobj.desc = "Generated from " + func.name; classobj.prototype.onExecute = function onExecute() { - for (var i = 0; i < params.length; ++i) + for (var i = 0; i < params.length; ++i) { params[i] = this.getInputData(i); + } var r = func.apply(this, params); this.setOutputData(0, r); }; @@ -229,8 +246,9 @@ LGraphNode.prototype[name] = func; for (var i in this.registered_node_types) { var type = this.registered_node_types[i]; - if (type.prototype[name]) - type.prototype["_" + name] = type.prototype[name]; //keep old in case of replacing + if (type.prototype[name]) { + type.prototype["_" + name] = type.prototype[name]; + } //keep old in case of replacing type.prototype[name] = func; } }, @@ -246,10 +264,11 @@ createNode: function(type, title, options) { var base_class = this.registered_node_types[type]; if (!base_class) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log( 'GraphNode type "' + type + '" not registered.' ); + } return null; } @@ -266,21 +285,39 @@ console.error(err); return null; } - } else node = new base_class(title); + } else { + node = new base_class(title); + } node.type = type; - if (!node.title && title) node.title = title; - if (!node.properties) node.properties = {}; - if (!node.properties_info) node.properties_info = []; - if (!node.flags) node.flags = {}; - if (!node.size) node.size = node.computeSize(); - if (!node.pos) node.pos = LiteGraph.DEFAULT_POSITION.concat(); - if (!node.mode) node.mode = LiteGraph.ALWAYS; + if (!node.title && title) { + node.title = title; + } + if (!node.properties) { + node.properties = {}; + } + if (!node.properties_info) { + node.properties_info = []; + } + if (!node.flags) { + node.flags = {}; + } + if (!node.size) { + node.size = node.computeSize(); + } + if (!node.pos) { + node.pos = LiteGraph.DEFAULT_POSITION.concat(); + } + if (!node.mode) { + node.mode = LiteGraph.ALWAYS; + } //extra options if (options) { - for (var i in options) node[i] = options[i]; + for (var i in options) { + node[i] = options[i]; + } } return node; @@ -307,11 +344,17 @@ var r = []; for (var i in this.registered_node_types) { var type = this.registered_node_types[i]; - if (filter && type.filter && type.filter != filter) continue; + if (filter && type.filter && type.filter != filter) { + continue; + } if (category == "") { - if (type.category == null) r.push(type); - } else if (type.category == category) r.push(type); + if (type.category == null) { + r.push(type); + } + } else if (type.category == category) { + r.push(type); + } } return r; @@ -325,14 +368,18 @@ getNodeTypesCategories: function() { var categories = { "": 1 }; - for (var i in this.registered_node_types) + for (var i in this.registered_node_types) { if ( this.registered_node_types[i].category && !this.registered_node_types[i].skip_list - ) + ) { categories[this.registered_node_types[i].category] = 1; + } + } var result = []; - for (var i in categories) result.push(i); + for (var i in categories) { + result.push(i); + } return result; }, @@ -341,7 +388,9 @@ var tmp = document.getElementsByTagName("script"); //weird, this array changes by its own, so we use a copy var script_files = []; - for (var i in tmp) script_files.push(tmp[i]); + for (var i in tmp) { + script_files.push(tmp[i]); + } var docHeadObj = document.getElementsByTagName("head")[0]; folder_wildcard = document.location.href + folder_wildcard; @@ -351,33 +400,47 @@ if ( !src || src.substr(0, folder_wildcard.length) != folder_wildcard - ) + ) { continue; + } try { - if (LiteGraph.debug) console.log("Reloading: " + src); + if (LiteGraph.debug) { + console.log("Reloading: " + src); + } var dynamicScript = document.createElement("script"); dynamicScript.type = "text/javascript"; dynamicScript.src = src; docHeadObj.appendChild(dynamicScript); docHeadObj.removeChild(script_files[i]); } catch (err) { - if (LiteGraph.throw_errors) throw err; - if (LiteGraph.debug) + if (LiteGraph.throw_errors) { + throw err; + } + if (LiteGraph.debug) { console.log("Error while reloading " + src); + } } } - if (LiteGraph.debug) console.log("Nodes reloaded"); + if (LiteGraph.debug) { + console.log("Nodes reloaded"); + } }, //separated just to improve if it doesn't work cloneObject: function(obj, target) { - if (obj == null) return null; + if (obj == null) { + return null; + } var r = JSON.parse(JSON.stringify(obj)); - if (!target) return r; + if (!target) { + return r; + } - for (var i in r) target[i] = r[i]; + for (var i in r) { + target[i] = r[i]; + } return target; }, @@ -387,8 +450,9 @@ !type_b || //generic input type_a == type_b || //same type (is valid for triggers) (type_a == LiteGraph.EVENT && type_b == LiteGraph.ACTION) - ) + ) { return true; + } // Enforce string type to handle toLowerCase call (-1 number not ok) type_a = String(type_a); @@ -397,16 +461,20 @@ type_b = type_b.toLowerCase(); // For nodes supporting multiple connection types - if (type_a.indexOf(",") == -1 && type_b.indexOf(",") == -1) + if (type_a.indexOf(",") == -1 && type_b.indexOf(",") == -1) { return type_a == type_b; + } // Check all permutations to see if one is valid var supported_types_a = type_a.split(","); var supported_types_b = type_b.split(","); - for (var i = 0; i < supported_types_a.length; ++i) - for (var j = 0; j < supported_types_b.length; ++j) - if (supported_types_a[i] == supported_types_b[j]) + for (var i = 0; i < supported_types_a.length; ++i) { + for (var j = 0; j < supported_types_b.length; ++j) { + if (supported_types_a[i] == supported_types_b[j]) { return true; + } + } + } return false; }, @@ -421,19 +489,20 @@ }); //timer that works everywhere - if (typeof performance != "undefined") + if (typeof performance != "undefined") { LiteGraph.getTime = performance.now.bind(performance); - else if (typeof Date != "undefined" && Date.now) + } else if (typeof Date != "undefined" && Date.now) { LiteGraph.getTime = Date.now.bind(Date); - else if (typeof process != "undefined") + } else if (typeof process != "undefined") { LiteGraph.getTime = function() { var t = process.hrtime(); return t[0] * 0.001 + t[1] * 1e-6; }; - else + } else { LiteGraph.getTime = function getTime() { return new Date().getTime(); }; + } //********************************************************************************* // LGraph CLASS @@ -448,11 +517,15 @@ */ function LGraph(o) { - if (LiteGraph.debug) console.log("Graph created"); + if (LiteGraph.debug) { + console.log("Graph created"); + } this.list_of_graphcanvas = null; this.clear(); - if (o) this.configure(o); + if (o) { + this.configure(o); + } } global.LGraph = LiteGraph.LGraph = LGraph; @@ -483,11 +556,14 @@ this._version = -1; //used to detect changes //safe clear - if (this._nodes) + if (this._nodes) { for (var i = 0; i < this._nodes.length; ++i) { var node = this._nodes[i]; - if (node.onRemoved) node.onRemoved(); + if (node.onRemoved) { + node.onRemoved(); + } } + } //nodes this._nodes = []; @@ -535,13 +611,17 @@ */ LGraph.prototype.attachCanvas = function(graphcanvas) { - if (graphcanvas.constructor != LGraphCanvas) + if (graphcanvas.constructor != LGraphCanvas) { throw "attachCanvas expects a LGraphCanvas instance"; - if (graphcanvas.graph && graphcanvas.graph != this) + } + if (graphcanvas.graph && graphcanvas.graph != this) { graphcanvas.graph.detachCanvas(graphcanvas); + } graphcanvas.graph = this; - if (!this.list_of_graphcanvas) this.list_of_graphcanvas = []; + if (!this.list_of_graphcanvas) { + this.list_of_graphcanvas = []; + } this.list_of_graphcanvas.push(graphcanvas); }; @@ -551,10 +631,14 @@ * @param {GraphCanvas} graph_canvas */ LGraph.prototype.detachCanvas = function(graphcanvas) { - if (!this.list_of_graphcanvas) return; + if (!this.list_of_graphcanvas) { + return; + } var pos = this.list_of_graphcanvas.indexOf(graphcanvas); - if (pos == -1) return; + if (pos == -1) { + return; + } graphcanvas.graph = null; this.list_of_graphcanvas.splice(pos, 1); }; @@ -566,10 +650,14 @@ */ LGraph.prototype.start = function(interval) { - if (this.status == LGraph.STATUS_RUNNING) return; + if (this.status == LGraph.STATUS_RUNNING) { + return; + } this.status = LGraph.STATUS_RUNNING; - if (this.onPlayEvent) this.onPlayEvent(); + if (this.onPlayEvent) { + this.onPlayEvent(); + } this.sendEventToAllNodes("onStart"); @@ -585,17 +673,20 @@ window.requestAnimationFrame ) { function on_frame() { - if (that.execution_timer_id != -1) return; + if (that.execution_timer_id != -1) { + return; + } window.requestAnimationFrame(on_frame); that.runStep(1, !this.catch_errors); } this.execution_timer_id = -1; on_frame(); - } else + } else { this.execution_timer_id = setInterval(function() { //execute that.runStep(1, !this.catch_errors); }, interval); + } }; /** @@ -604,15 +695,20 @@ */ LGraph.prototype.stop = function() { - if (this.status == LGraph.STATUS_STOPPED) return; + if (this.status == LGraph.STATUS_STOPPED) { + return; + } this.status = LGraph.STATUS_STOPPED; - if (this.onStopEvent) this.onStopEvent(); + if (this.onStopEvent) { + this.onStopEvent(); + } if (this.execution_timer_id != null) { - if (this.execution_timer_id != -1) + if (this.execution_timer_id != -1) { clearInterval(this.execution_timer_id); + } this.execution_timer_id = null; } @@ -634,50 +730,67 @@ var nodes = this._nodes_executable ? this._nodes_executable : this._nodes; - if (!nodes) return; + if (!nodes) { + return; + } if (do_not_catch_errors) { //iterations for (var i = 0; i < num; i++) { for (var j = 0, l = nodes.length; j < l; ++j) { var node = nodes[j]; - if (node.mode == LiteGraph.ALWAYS && node.onExecute) + if (node.mode == LiteGraph.ALWAYS && node.onExecute) { node.onExecute(); + } } this.fixedtime += this.fixedtime_lapse; - if (this.onExecuteStep) this.onExecuteStep(); + if (this.onExecuteStep) { + this.onExecuteStep(); + } } - if (this.onAfterExecute) this.onAfterExecute(); + if (this.onAfterExecute) { + this.onAfterExecute(); + } } else { try { //iterations for (var i = 0; i < num; i++) { for (var j = 0, l = nodes.length; j < l; ++j) { var node = nodes[j]; - if (node.mode == LiteGraph.ALWAYS && node.onExecute) + if (node.mode == LiteGraph.ALWAYS && node.onExecute) { node.onExecute(); + } } this.fixedtime += this.fixedtime_lapse; - if (this.onExecuteStep) this.onExecuteStep(); + if (this.onExecuteStep) { + this.onExecuteStep(); + } } - if (this.onAfterExecute) this.onAfterExecute(); + if (this.onAfterExecute) { + this.onAfterExecute(); + } this.errors_in_execution = false; } catch (err) { this.errors_in_execution = true; - if (LiteGraph.throw_errors) throw err; - if (LiteGraph.debug) + if (LiteGraph.throw_errors) { + throw err; + } + if (LiteGraph.debug) { console.log("Error during execution: " + err); + } this.stop(); } } var now = LiteGraph.getTime(); var elapsed = now - start; - if (elapsed == 0) elapsed = 1; + if (elapsed == 0) { + elapsed = 1; + } this.execution_time = 0.001 * elapsed; this.globaltime += 0.001 * elapsed; this.iteration += 1; @@ -693,9 +806,11 @@ LGraph.prototype.updateExecutionOrder = function() { this._nodes_in_order = this.computeExecutionOrder(false); this._nodes_executable = []; - for (var i = 0; i < this._nodes_in_order.length; ++i) - if (this._nodes_in_order[i].onExecute) + for (var i = 0; i < this._nodes_in_order.length; ++i) { + if (this._nodes_in_order[i].onExecute) { this._nodes_executable.push(this._nodes_in_order[i]); + } + } }; //This is more internal, it computes the executable nodes in order and returns it @@ -712,35 +827,49 @@ //search for the nodes without inputs (starting nodes) for (var i = 0, l = this._nodes.length; i < l; ++i) { var node = this._nodes[i]; - if (only_onExecute && !node.onExecute) continue; + if (only_onExecute && !node.onExecute) { + continue; + } M[node.id] = node; //add to pending nodes var num = 0; //num of input connections - if (node.inputs) - for (var j = 0, l2 = node.inputs.length; j < l2; j++) - if (node.inputs[j] && node.inputs[j].link != null) num += 1; + if (node.inputs) { + for (var j = 0, l2 = node.inputs.length; j < l2; j++) { + if (node.inputs[j] && node.inputs[j].link != null) { + num += 1; + } + } + } if (num == 0) { //is a starting node S.push(node); - if (set_level) node._level = 1; + if (set_level) { + node._level = 1; + } } //num of input links else { - if (set_level) node._level = 0; + if (set_level) { + node._level = 0; + } remaining_links[node.id] = num; } } while (true) { - if (S.length == 0) break; + if (S.length == 0) { + break; + } //get an starting node var node = S.shift(); L.push(node); //add to ordered list delete M[node.id]; //remove from the pending nodes - if (!node.outputs) continue; + if (!node.outputs) { + continue; + } //for every output for (var i = 0; i < node.outputs.length; i++) { @@ -750,17 +879,22 @@ output == null || output.links == null || output.links.length == 0 - ) + ) { continue; + } //for every connection for (var j = 0; j < output.links.length; j++) { var link_id = output.links[j]; var link = this.links[link_id]; - if (!link) continue; + if (!link) { + continue; + } //already visited link (ignore it) - if (visited_links[link.id]) continue; + if (visited_links[link.id]) { + continue; + } var target_node = this.getNodeById(link.target_id); if (target_node == null) { @@ -772,40 +906,50 @@ set_level && (!target_node._level || target_node._level <= node._level) - ) + ) { target_node._level = node._level + 1; + } visited_links[link.id] = true; //mark as visited remaining_links[target_node.id] -= 1; //reduce the number of links remaining - if (remaining_links[target_node.id] == 0) - S.push(target_node); //if no more links, then add to starters array + if (remaining_links[target_node.id] == 0) { + S.push(target_node); + } //if no more links, then add to starters array } } } //the remaining ones (loops) - for (var i in M) L.push(M[i]); + for (var i in M) { + L.push(M[i]); + } - if (L.length != this._nodes.length && LiteGraph.debug) + if (L.length != this._nodes.length && LiteGraph.debug) { console.warn("something went wrong, nodes missing"); + } var l = L.length; //save order number in the node - for (var i = 0; i < l; ++i) L[i].order = i; + for (var i = 0; i < l; ++i) { + L[i].order = i; + } //sort now by priority L = L.sort(function(A, B) { var Ap = A.constructor.priority || A.priority || 0; var Bp = B.constructor.priority || B.priority || 0; - if (Ap == Bp) + if (Ap == Bp) { //if same priority, sort by order return A.order - B.order; + } return Ap - Bp; //sort by priority }); //save order number in the node, again... - for (var i = 0; i < l; ++i) L[i].order = i; + for (var i = 0; i < l; ++i) { + L[i].order = i; + } return L; }; @@ -823,7 +967,9 @@ while (pending.length) { var current = pending.shift(); - if (!current.inputs) continue; + if (!current.inputs) { + continue; + } if (!visited[current.id] && current != node) { visited[current.id] = true; ancestors.push(current); @@ -855,7 +1001,9 @@ for (var i = 0; i < nodes.length; ++i) { var node = nodes[i]; var col = node._level || 1; - if (!columns[col]) columns[col] = []; + if (!columns[col]) { + columns[col] = []; + } columns[col].push(node); } @@ -863,14 +1011,18 @@ for (var i = 0; i < columns.length; ++i) { var column = columns[i]; - if (!column) continue; + if (!column) { + continue; + } var max_size = 100; var y = margin; for (var j = 0; j < column.length; ++j) { var node = column[j]; node.pos[0] = x; node.pos[1] = y; - if (node.size[0] > max_size) max_size = node.size[0]; + if (node.size[0] > max_size) { + max_size = node.size[0]; + } y += node.size[1] + margin; } x += max_size + margin; @@ -919,7 +1071,9 @@ mode = mode || LiteGraph.ALWAYS; var nodes = this._nodes_in_order ? this._nodes_in_order : this._nodes; - if (!nodes) return; + if (!nodes) { + return; + } for (var j = 0, l = nodes.length; j < l; ++j) { var node = nodes[j]; @@ -928,25 +1082,35 @@ node.constructor === LiteGraph.Subgraph && eventname != "onExecute" ) { - if (node.mode == mode) + if (node.mode == mode) { node.sendEventToAllNodes(eventname, params, mode); + } continue; } - if (!node[eventname] || node.mode != mode) continue; - if (params === undefined) node[eventname](); - else if (params && params.constructor === Array) + if (!node[eventname] || node.mode != mode) { + continue; + } + if (params === undefined) { + node[eventname](); + } else if (params && params.constructor === Array) { node[eventname].apply(node, params); - else node[eventname](params); + } else { + node[eventname](params); + } } }; LGraph.prototype.sendActionToCanvas = function(action, params) { - if (!this.list_of_graphcanvas) return; + if (!this.list_of_graphcanvas) { + return; + } for (var i = 0; i < this.list_of_graphcanvas.length; ++i) { var c = this.list_of_graphcanvas[i]; - if (c[action]) c[action].apply(c, params); + if (c[action]) { + c[action].apply(c, params); + } } }; @@ -957,7 +1121,9 @@ */ LGraph.prototype.add = function(node, skip_compute_order) { - if (!node) return; + if (!node) { + return; + } //groups if (node.constructor === LGraphGroup) { @@ -977,12 +1143,16 @@ node.id = ++this.last_node_id; } - if (this._nodes.length >= LiteGraph.MAX_NUMBER_OF_NODES) + if (this._nodes.length >= LiteGraph.MAX_NUMBER_OF_NODES) { throw "LiteGraph: max number of nodes in a graph reached"; + } //give him an id - if (node.id == null || node.id == -1) node.id = ++this.last_node_id; - else if (this.last_node_id < node.id) this.last_node_id = node.id; + if (node.id == null || node.id == -1) { + node.id = ++this.last_node_id; + } else if (this.last_node_id < node.id) { + this.last_node_id = node.id; + } node.graph = this; this._version++; @@ -990,13 +1160,21 @@ this._nodes.push(node); this._nodes_by_id[node.id] = node; - if (node.onAdded) node.onAdded(this); + if (node.onAdded) { + node.onAdded(this); + } - if (this.config.align_to_grid) node.alignToGrid(); + if (this.config.align_to_grid) { + node.alignToGrid(); + } - if (!skip_compute_order) this.updateExecutionOrder(); + if (!skip_compute_order) { + this.updateExecutionOrder(); + } - if (this.onNodeAdded) this.onNodeAdded(node); + if (this.onNodeAdded) { + this.onNodeAdded(node); + } this.setDirtyCanvas(true); this.change(); @@ -1013,7 +1191,9 @@ LGraph.prototype.remove = function(node) { if (node.constructor === LiteGraph.LGraphGroup) { var index = this._groups.indexOf(node); - if (index != -1) this._groups.splice(index, 1); + if (index != -1) { + this._groups.splice(index, 1); + } node.graph = null; this._version++; this.setDirtyCanvas(true, true); @@ -1021,29 +1201,40 @@ return; } - if (this._nodes_by_id[node.id] == null) return; //not found + if (this._nodes_by_id[node.id] == null) { + return; + } //not found - if (node.ignore_remove) return; //cannot be removed + if (node.ignore_remove) { + return; + } //cannot be removed //disconnect inputs - if (node.inputs) + if (node.inputs) { for (var i = 0; i < node.inputs.length; i++) { var slot = node.inputs[i]; - if (slot.link != null) node.disconnectInput(i); + if (slot.link != null) { + node.disconnectInput(i); + } } + } //disconnect outputs - if (node.outputs) + if (node.outputs) { for (var i = 0; i < node.outputs.length; i++) { var slot = node.outputs[i]; - if (slot.links != null && slot.links.length) + if (slot.links != null && slot.links.length) { node.disconnectOutput(i); + } } + } //node.id = -1; //why? //callback - if (node.onRemoved) node.onRemoved(); + if (node.onRemoved) { + node.onRemoved(); + } node.graph = null; this._version++; @@ -1052,18 +1243,25 @@ if (this.list_of_graphcanvas) { for (var i = 0; i < this.list_of_graphcanvas.length; ++i) { var canvas = this.list_of_graphcanvas[i]; - if (canvas.selected_nodes[node.id]) + if (canvas.selected_nodes[node.id]) { delete canvas.selected_nodes[node.id]; - if (canvas.node_dragged == node) canvas.node_dragged = null; + } + if (canvas.node_dragged == node) { + canvas.node_dragged = null; + } } } //remove from containers var pos = this._nodes.indexOf(node); - if (pos != -1) this._nodes.splice(pos, 1); + if (pos != -1) { + this._nodes.splice(pos, 1); + } delete this._nodes_by_id[node.id]; - if (this.onNodeRemoved) this.onNodeRemoved(node); + if (this.onNodeRemoved) { + this.onNodeRemoved(node); + } this.setDirtyCanvas(true, true); this.change(); @@ -1078,7 +1276,9 @@ */ LGraph.prototype.getNodeById = function(id) { - if (id == null) return null; + if (id == null) { + return null; + } return this._nodes_by_id[id]; }; @@ -1091,9 +1291,11 @@ LGraph.prototype.findNodesByClass = function(classObject, result) { result = result || []; result.length = 0; - for (var i = 0, l = this._nodes.length; i < l; ++i) - if (this._nodes[i].constructor === classObject) + for (var i = 0, l = this._nodes.length; i < l; ++i) { + if (this._nodes[i].constructor === classObject) { result.push(this._nodes[i]); + } + } return result; }; @@ -1107,9 +1309,11 @@ var type = type.toLowerCase(); result = result || []; result.length = 0; - for (var i = 0, l = this._nodes.length; i < l; ++i) - if (this._nodes[i].type.toLowerCase() == type) + for (var i = 0, l = this._nodes.length; i < l; ++i) { + if (this._nodes[i].type.toLowerCase() == type) { result.push(this._nodes[i]); + } + } return result; }; @@ -1120,8 +1324,11 @@ * @return {Node} the node or null */ LGraph.prototype.findNodeByTitle = function(title) { - for (var i = 0, l = this._nodes.length; i < l; ++i) - if (this._nodes[i].title == title) return this._nodes[i]; + for (var i = 0, l = this._nodes.length; i < l; ++i) { + if (this._nodes[i].title == title) { + return this._nodes[i]; + } + } return null; }; @@ -1133,8 +1340,11 @@ */ LGraph.prototype.findNodesByTitle = function(title) { var result = []; - for (var i = 0, l = this._nodes.length; i < l; ++i) - if (this._nodes[i].title == title) result.push(this._nodes[i]); + for (var i = 0, l = this._nodes.length; i < l; ++i) { + if (this._nodes[i].title == title) { + result.push(this._nodes[i]); + } + } return result; }; @@ -1150,7 +1360,9 @@ nodes_list = nodes_list || this._nodes; for (var i = nodes_list.length - 1; i >= 0; i--) { var n = nodes_list[i]; - if (n.isPointInside(x, y, margin)) return n; + if (n.isPointInside(x, y, margin)) { + return n; + } } return null; }; @@ -1165,39 +1377,43 @@ LGraph.prototype.getGroupOnPos = function(x, y) { for (var i = this._groups.length - 1; i >= 0; i--) { var g = this._groups[i]; - if (g.isPointInside(x, y, 2, true)) return g; + if (g.isPointInside(x, y, 2, true)) { + return g; + } } return null; }; /** * Checks that the node type matches the node type registered, used when replacing a nodetype by a newer version during execution - * this replaces the ones using the old version with the new version + * this replaces the ones using the old version with the new version * @method checkNodeTypes */ LGraph.prototype.checkNodeTypes = function() { - var changes = false; + var changes = false; for (var i = 0; i < this._nodes.length; i++) { var node = this._nodes[i]; - var ctor = LiteGraph.registered_node_types[ node.type ]; - if(node.constructor == ctor) - continue; - console.log("node being replaced by newer version: " + node.type ); - var newnode = LiteGraph.createNode( node.type ); - changes = true; - this._nodes[i] = newnode; - newnode.configure( node.serialize() ); - newnode.graph = this; - this._nodes_by_id[newnode.id] = newnode; - if(node.inputs) - newnode.inputs = node.inputs.concat(); - if(node.outputs) - newnode.outputs = node.outputs.concat(); + var ctor = LiteGraph.registered_node_types[node.type]; + if (node.constructor == ctor) { + continue; + } + console.log("node being replaced by newer version: " + node.type); + var newnode = LiteGraph.createNode(node.type); + changes = true; + this._nodes[i] = newnode; + newnode.configure(node.serialize()); + newnode.graph = this; + this._nodes_by_id[newnode.id] = newnode; + if (node.inputs) { + newnode.inputs = node.inputs.concat(); + } + if (node.outputs) { + newnode.outputs = node.outputs.concat(); + } } - this.updateExecutionOrder(); + this.updateExecutionOrder(); }; - // ********** GLOBALS ***************** LGraph.prototype.onAction = function(action, param) { @@ -1207,14 +1423,18 @@ ); for (var i = 0; i < this._input_nodes.length; ++i) { var node = this._input_nodes[i]; - if (node.properties.name != action) continue; + if (node.properties.name != action) { + continue; + } node.onAction(action, param); break; } }; LGraph.prototype.trigger = function(action, param) { - if (this.onTrigger) this.onTrigger(action, param); + if (this.onTrigger) { + this.onTrigger(action, param); + } }; /** @@ -1226,16 +1446,21 @@ */ LGraph.prototype.addInput = function(name, type, value) { var input = this.inputs[name]; - if (input) + if (input) { //already exist return; + } this.inputs[name] = { name: name, type: type, value: value }; this._version++; - if (this.onInputAdded) this.onInputAdded(name, type); + if (this.onInputAdded) { + this.onInputAdded(name, type); + } - if (this.onInputsOutputsChange) this.onInputsOutputsChange(); + if (this.onInputsOutputsChange) { + this.onInputsOutputsChange(); + } }; /** @@ -1246,7 +1471,9 @@ */ LGraph.prototype.setInputData = function(name, data) { var input = this.inputs[name]; - if (!input) return; + if (!input) { + return; + } input.value = data; }; @@ -1258,7 +1485,9 @@ */ LGraph.prototype.getInputData = function(name) { var input = this.inputs[name]; - if (!input) return null; + if (!input) { + return null; + } return input.value; }; @@ -1269,9 +1498,13 @@ * @param {String} new_name */ LGraph.prototype.renameInput = function(old_name, name) { - if (name == old_name) return; + if (name == old_name) { + return; + } - if (!this.inputs[old_name]) return false; + if (!this.inputs[old_name]) { + return false; + } if (this.inputs[name]) { console.error("there is already one input with that name"); @@ -1282,9 +1515,13 @@ delete this.inputs[old_name]; this._version++; - if (this.onInputRenamed) this.onInputRenamed(old_name, name); + if (this.onInputRenamed) { + this.onInputRenamed(old_name, name); + } - if (this.onInputsOutputsChange) this.onInputsOutputsChange(); + if (this.onInputsOutputsChange) { + this.onInputsOutputsChange(); + } }; /** @@ -1294,18 +1531,23 @@ * @param {String} type */ LGraph.prototype.changeInputType = function(name, type) { - if (!this.inputs[name]) return false; + if (!this.inputs[name]) { + return false; + } if ( this.inputs[name].type && String(this.inputs[name].type).toLowerCase() == String(type).toLowerCase() - ) + ) { return; + } this.inputs[name].type = type; this._version++; - if (this.onInputTypeChanged) this.onInputTypeChanged(name, type); + if (this.onInputTypeChanged) { + this.onInputTypeChanged(name, type); + } }; /** @@ -1315,14 +1557,20 @@ * @param {String} type */ LGraph.prototype.removeInput = function(name) { - if (!this.inputs[name]) return false; + if (!this.inputs[name]) { + return false; + } delete this.inputs[name]; this._version++; - if (this.onInputRemoved) this.onInputRemoved(name); + if (this.onInputRemoved) { + this.onInputRemoved(name); + } - if (this.onInputsOutputsChange) this.onInputsOutputsChange(); + if (this.onInputsOutputsChange) { + this.onInputsOutputsChange(); + } return true; }; @@ -1337,9 +1585,13 @@ this.outputs[name] = { name: name, type: type, value: value }; this._version++; - if (this.onOutputAdded) this.onOutputAdded(name, type); + if (this.onOutputAdded) { + this.onOutputAdded(name, type); + } - if (this.onInputsOutputsChange) this.onInputsOutputsChange(); + if (this.onInputsOutputsChange) { + this.onInputsOutputsChange(); + } }; /** @@ -1350,7 +1602,9 @@ */ LGraph.prototype.setOutputData = function(name, value) { var output = this.outputs[name]; - if (!output) return; + if (!output) { + return; + } output.value = value; }; @@ -1362,7 +1616,9 @@ */ LGraph.prototype.getOutputData = function(name) { var output = this.outputs[name]; - if (!output) return null; + if (!output) { + return null; + } return output.value; }; @@ -1373,7 +1629,9 @@ * @param {String} new_name */ LGraph.prototype.renameOutput = function(old_name, name) { - if (!this.outputs[old_name]) return false; + if (!this.outputs[old_name]) { + return false; + } if (this.outputs[name]) { console.error("there is already one output with that name"); @@ -1384,9 +1642,13 @@ delete this.outputs[old_name]; this._version++; - if (this.onOutputRenamed) this.onOutputRenamed(old_name, name); + if (this.onOutputRenamed) { + this.onOutputRenamed(old_name, name); + } - if (this.onInputsOutputsChange) this.onInputsOutputsChange(); + if (this.onInputsOutputsChange) { + this.onInputsOutputsChange(); + } }; /** @@ -1396,18 +1658,23 @@ * @param {String} type */ LGraph.prototype.changeOutputType = function(name, type) { - if (!this.outputs[name]) return false; + if (!this.outputs[name]) { + return false; + } if ( this.outputs[name].type && String(this.outputs[name].type).toLowerCase() == String(type).toLowerCase() - ) + ) { return; + } this.outputs[name].type = type; this._version++; - if (this.onOutputTypeChanged) this.onOutputTypeChanged(name, type); + if (this.onOutputTypeChanged) { + this.onOutputTypeChanged(name, type); + } }; /** @@ -1416,29 +1683,41 @@ * @param {String} name */ LGraph.prototype.removeOutput = function(name) { - if (!this.outputs[name]) return false; + if (!this.outputs[name]) { + return false; + } delete this.outputs[name]; this._version++; - if (this.onOutputRemoved) this.onOutputRemoved(name); + if (this.onOutputRemoved) { + this.onOutputRemoved(name); + } - if (this.onInputsOutputsChange) this.onInputsOutputsChange(); + if (this.onInputsOutputsChange) { + this.onInputsOutputsChange(); + } return true; }; LGraph.prototype.triggerInput = function(name, value) { var nodes = this.findNodesByTitle(name); - for (var i = 0; i < nodes.length; ++i) nodes[i].onTrigger(value); + for (var i = 0; i < nodes.length; ++i) { + nodes[i].onTrigger(value); + } }; LGraph.prototype.setCallback = function(name, func) { var nodes = this.findNodesByTitle(name); - for (var i = 0; i < nodes.length; ++i) nodes[i].setTrigger(func); + for (var i = 0; i < nodes.length; ++i) { + nodes[i].setTrigger(func); + } }; LGraph.prototype.connectionChange = function(node, link_info) { this.updateExecutionOrder(); - if (this.onConnectionChange) this.onConnectionChange(node); + if (this.onConnectionChange) { + this.onConnectionChange(node); + } this._version++; this.sendActionToCanvas("onConnectionChange"); }; @@ -1449,11 +1728,15 @@ */ LGraph.prototype.isLive = function() { - if (!this.list_of_graphcanvas) return false; + if (!this.list_of_graphcanvas) { + return false; + } for (var i = 0; i < this.list_of_graphcanvas.length; ++i) { var c = this.list_of_graphcanvas[i]; - if (c.live_mode) return true; + if (c.live_mode) { + return true; + } } return false; }; @@ -1465,16 +1748,24 @@ LGraph.prototype.clearTriggeredSlots = function() { for (var i in this.links) { var link_info = this.links[i]; - if (!link_info) continue; - if (link_info._last_time) link_info._last_time = 0; + if (!link_info) { + continue; + } + if (link_info._last_time) { + link_info._last_time = 0; + } } }; /* Called when something visually changed (not the graph!) */ LGraph.prototype.change = function() { - if (LiteGraph.debug) console.log("Graph changed"); + if (LiteGraph.debug) { + console.log("Graph changed"); + } this.sendActionToCanvas("setDirty", [true, true]); - if (this.on_change) this.on_change(this); + if (this.on_change) { + this.on_change(this); + } }; LGraph.prototype.setDirtyCanvas = function(fg, bg) { @@ -1488,9 +1779,13 @@ */ LGraph.prototype.removeLink = function(link_id) { var link = this.links[link_id]; - if (!link) return; + if (!link) { + return; + } var node = this.getNodeById(link.target_id); - if (node) node.disconnectInput(link.target_slot); + if (node) { + node.disconnectInput(link.target_slot); + } }; //save and recover app state *************************************** @@ -1501,30 +1796,35 @@ */ LGraph.prototype.serialize = function() { var nodes_info = []; - for (var i = 0, l = this._nodes.length; i < l; ++i) + for (var i = 0, l = this._nodes.length; i < l; ++i) { nodes_info.push(this._nodes[i].serialize()); + } //pack link info into a non-verbose format var links = []; for (var i in this.links) { //links is an OBJECT var link = this.links[i]; - if(!link.serialize) //weird bug I havent solved yet - { - console.warn("weird LLink bug, link info is not a LLink but a regular object"); - var link2 = new LLink(); - for(var i in link) - link2[i] = link[i]; - this.links[i] = link2; - link = link2; - } + if (!link.serialize) { + //weird bug I havent solved yet + console.warn( + "weird LLink bug, link info is not a LLink but a regular object" + ); + var link2 = new LLink(); + for (var i in link) { + link2[i] = link[i]; + } + this.links[i] = link2; + link = link2; + } links.push(link.serialize()); } var groups_info = []; - for (var i = 0; i < this._groups.length; ++i) + for (var i = 0; i < this._groups.length; ++i) { groups_info.push(this._groups[i].serialize()); + } var data = { last_node_id: this.last_node_id, @@ -1546,9 +1846,13 @@ * @param {Boolean} returns if there was any error parsing */ LGraph.prototype.configure = function(data, keep_old) { - if (!data) return; + if (!data) { + return; + } - if (!keep_old) this.clear(); + if (!keep_old) { + this.clear(); + } var nodes = data.nodes; @@ -1565,7 +1869,9 @@ } //copy all stored fields - for (var i in data) this[i] = data[i]; + for (var i in data) { + this[i] = data[i]; + } var error = false; @@ -1576,10 +1882,11 @@ var n_info = nodes[i]; //stored info var node = LiteGraph.createNode(n_info.type, n_info.title); if (!node) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log( "Node not found or has errors: " + n_info.type ); + } //in case of error we create a replacement node to avoid losing info node = new LGraphNode(); @@ -1597,18 +1904,21 @@ for (var i = 0, l = nodes.length; i < l; ++i) { var n_info = nodes[i]; var node = this.getNodeById(n_info.id); - if (node) node.configure(n_info); + if (node) { + node.configure(n_info); + } } } //groups this._groups.length = 0; - if (data.groups) + if (data.groups) { for (var i = 0; i < data.groups.length; ++i) { var group = new LiteGraph.LGraphGroup(); group.configure(data.groups[i]); this.add(group); } + } this.updateExecutionOrder(); this._version++; @@ -1758,7 +2068,9 @@ Object.defineProperty(this, "pos", { set: function(v) { - if (!v || v.length < 2) return; + if (!v || v.length < 2) { + return; + } this._pos[0] = v[0]; this._pos[1] = v[1]; }, @@ -1788,32 +2100,43 @@ * @method configure */ LGraphNode.prototype.configure = function(info) { - if (this.graph) this.graph._version++; + if (this.graph) { + this.graph._version++; + } for (var j in info) { if (j == "properties") { //i don't want to clone properties, I want to reuse the old container for (var k in info.properties) { this.properties[k] = info.properties[k]; - if (this.onPropertyChanged) + if (this.onPropertyChanged) { this.onPropertyChanged(k, info.properties[k]); + } } continue; } - if (info[j] == null) continue; - else if (typeof info[j] == "object") { + if (info[j] == null) { + continue; + } else if (typeof info[j] == "object") { //object - if (this[j] && this[j].configure) this[j].configure(info[j]); - else this[j] = LiteGraph.cloneObject(info[j], this[j]); + if (this[j] && this[j].configure) { + this[j].configure(info[j]); + } else { + this[j] = LiteGraph.cloneObject(info[j], this[j]); + } } //value - else this[j] = info[j]; + else { + this[j] = info[j]; + } } - if (!info.title) this.title = this.constructor.title; + if (!info.title) { + this.title = this.constructor.title; + } if (this.onConnectionsChange) { - if (this.inputs) + if (this.inputs) { for (var i = 0; i < this.inputs.length; ++i) { var input = this.inputs[i]; var link_info = this.graph @@ -1827,11 +2150,14 @@ input ); //link_info has been created now, so its updated } + } - if (this.outputs) + if (this.outputs) { for (var i = 0; i < this.outputs.length; ++i) { var output = this.outputs[i]; - if (!output.links) continue; + if (!output.links) { + continue; + } for (var j = 0; j < output.links.length; ++j) { var link_info = this.graph ? this.graph.links[output.links[j]] @@ -1845,15 +2171,20 @@ ); //link_info has been created now, so its updated } } + } } if (info.widgets_values && this.widgets) { - for (var i = 0; i < info.widgets_values.length; ++i) - if (this.widgets[i]) + for (var i = 0; i < info.widgets_values.length; ++i) { + if (this.widgets[i]) { this.widgets[i].value = info.widgets_values[i]; + } + } } - if (this.onConfigure) this.onConfigure(info); + if (this.onConfigure) { + this.onConfigure(info); + } }; /** @@ -1873,42 +2204,60 @@ }; //special case for when there were errors - if (this.constructor === LGraphNode && this.last_serialization) + if (this.constructor === LGraphNode && this.last_serialization) { return this.last_serialization; + } - if (this.inputs) o.inputs = this.inputs; + if (this.inputs) { + o.inputs = this.inputs; + } if (this.outputs) { //clear outputs last data (because data in connections is never serialized but stored inside the outputs info) - for (var i = 0; i < this.outputs.length; i++) + for (var i = 0; i < this.outputs.length; i++) { delete this.outputs[i]._data; + } o.outputs = this.outputs; } - if (this.title && this.title != this.constructor.title) + if (this.title && this.title != this.constructor.title) { o.title = this.title; + } - if (this.properties) + if (this.properties) { o.properties = LiteGraph.cloneObject(this.properties); + } if (this.widgets && this.serialize_widgets) { o.widgets_values = []; - for (var i = 0; i < this.widgets.length; ++i) + for (var i = 0; i < this.widgets.length; ++i) { o.widgets_values[i] = this.widgets[i].value; + } } - if (!o.type) o.type = this.constructor.type; + if (!o.type) { + o.type = this.constructor.type; + } - if (this.color) o.color = this.color; - if (this.bgcolor) o.bgcolor = this.bgcolor; - if (this.boxcolor) o.boxcolor = this.boxcolor; - if (this.shape) o.shape = this.shape; + if (this.color) { + o.color = this.color; + } + if (this.bgcolor) { + o.bgcolor = this.bgcolor; + } + if (this.boxcolor) { + o.boxcolor = this.boxcolor; + } + if (this.shape) { + o.shape = this.shape; + } if (this.onSerialize) { - if (this.onSerialize(o)) + if (this.onSerialize(o)) { console.warn( "node onSerialize shouldnt return anything, data should be stored in the object pass in the first parameter" ); + } } return o; @@ -1917,20 +2266,27 @@ /* Creates a clone of this node */ LGraphNode.prototype.clone = function() { var node = LiteGraph.createNode(this.type); - if (!node) return null; + if (!node) { + return null; + } //we clone it because serialize returns shared containers var data = LiteGraph.cloneObject(this.serialize()); //remove links - if (data.inputs) - for (var i = 0; i < data.inputs.length; ++i) + if (data.inputs) { + for (var i = 0; i < data.inputs.length; ++i) { data.inputs[i].link = null; - - if (data.outputs) - for (var i = 0; i < data.outputs.length; ++i) { - if (data.outputs[i].links) data.outputs[i].links.length = 0; } + } + + if (data.outputs) { + for (var i = 0; i < data.outputs.length; ++i) { + if (data.outputs[i].links) { + data.outputs[i].links.length = 0; + } + } + } delete data["id"]; //remove links @@ -1965,12 +2321,14 @@ * @param {*} value */ LGraphNode.prototype.setProperty = function(name, value) { - if(!this.properties) - this.properties = {}; - this.properties[name] = value; - if (this.onPropertyChanged) - this.onPropertyChanged(name, value); - }; + if (!this.properties) { + this.properties = {}; + } + this.properties[name] = value; + if (this.onPropertyChanged) { + this.onPropertyChanged(name, value); + } + }; // Execution ************************* /** @@ -1980,16 +2338,22 @@ * @param {*} data */ LGraphNode.prototype.setOutputData = function(slot, data) { - if (!this.outputs) return; + if (!this.outputs) { + return; + } //this maybe slow and a niche case //if(slot && slot.constructor === String) // slot = this.findOutputSlot(slot); - if (slot == -1 || slot >= this.outputs.length) return; + if (slot == -1 || slot >= this.outputs.length) { + return; + } var output_info = this.outputs[slot]; - if (!output_info) return; + if (!output_info) { + return; + } //store data in the output itself in case we want to debug output_info._data = data; @@ -2010,10 +2374,16 @@ * @param {String} datatype */ LGraphNode.prototype.setOutputDataType = function(slot, type) { - if (!this.outputs) return; - if (slot == -1 || slot >= this.outputs.length) return; + if (!this.outputs) { + return; + } + if (slot == -1 || slot >= this.outputs.length) { + return; + } var output_info = this.outputs[slot]; - if (!output_info) return; + if (!output_info) { + return; + } //store data in the output itself in case we want to debug output_info.type = type; @@ -2034,25 +2404,36 @@ * @return {*} data or if it is not connected returns undefined */ LGraphNode.prototype.getInputData = function(slot, force_update) { - if (!this.inputs) return; //undefined; - - if (slot >= this.inputs.length || this.inputs[slot].link == null) + if (!this.inputs) { return; + } //undefined; + + if (slot >= this.inputs.length || this.inputs[slot].link == null) { + return; + } var link_id = this.inputs[slot].link; var link = this.graph.links[link_id]; - if (!link) + if (!link) { //bug: weird case but it happens sometimes return null; + } - if (!force_update) return link.data; + if (!force_update) { + return link.data; + } //special case: used to extract data from the incoming connection before the graph has been executed var node = this.graph.getNodeById(link.origin_id); - if (!node) return link.data; + if (!node) { + return link.data; + } - if (node.updateOutputData) node.updateOutputData(link.origin_slot); - else if (node.onExecute) node.onExecute(); + if (node.updateOutputData) { + node.updateOutputData(link.origin_slot); + } else if (node.onExecute) { + node.onExecute(); + } return link.data; }; @@ -2064,19 +2445,27 @@ * @return {String} datatype in string format */ LGraphNode.prototype.getInputDataType = function(slot) { - if (!this.inputs) return null; //undefined; - - if (slot >= this.inputs.length || this.inputs[slot].link == null) + if (!this.inputs) { return null; + } //undefined; + + if (slot >= this.inputs.length || this.inputs[slot].link == null) { + return null; + } var link_id = this.inputs[slot].link; var link = this.graph.links[link_id]; - if (!link) + if (!link) { //bug: weird case but it happens sometimes return null; + } var node = this.graph.getNodeById(link.origin_id); - if (!node) return link.type; + if (!node) { + return link.type; + } var output_info = node.outputs[link.origin_slot]; - if (output_info) return output_info.type; + if (output_info) { + return output_info.type; + } return null; }; @@ -2092,7 +2481,9 @@ force_update ) { var slot = this.findInputSlot(slot_name); - if (slot == -1) return null; + if (slot == -1) { + return null; + } return this.getInputData(slot, force_update); }; @@ -2103,7 +2494,9 @@ * @return {boolean} */ LGraphNode.prototype.isInputConnected = function(slot) { - if (!this.inputs) return false; + if (!this.inputs) { + return false; + } return slot < this.inputs.length && this.inputs[slot].link != null; }; @@ -2114,8 +2507,12 @@ * @return {Object} object or null { link: id, name: string, type: string or 0 } */ LGraphNode.prototype.getInputInfo = function(slot) { - if (!this.inputs) return null; - if (slot < this.inputs.length) return this.inputs[slot]; + if (!this.inputs) { + return null; + } + if (slot < this.inputs.length) { + return this.inputs[slot]; + } return null; }; @@ -2126,12 +2523,20 @@ * @return {LGraphNode} node or null */ LGraphNode.prototype.getInputNode = function(slot) { - if (!this.inputs) return null; - if (slot >= this.inputs.length) return null; + if (!this.inputs) { + return null; + } + if (slot >= this.inputs.length) { + return null; + } var input = this.inputs[slot]; - if (!input || input.link === null) return null; + if (!input || input.link === null) { + return null; + } var link_info = this.graph.links[input.link]; - if (!link_info) return null; + if (!link_info) { + return null; + } return this.graph.getNodeById(link_info.origin_id); }; @@ -2142,14 +2547,17 @@ * @return {*} value */ LGraphNode.prototype.getInputOrProperty = function(name) { - if (!this.inputs || !this.inputs.length) + if (!this.inputs || !this.inputs.length) { return this.properties ? this.properties[name] : null; + } for (var i = 0, l = this.inputs.length; i < l; ++i) { var input_info = this.inputs[i]; if (name == input_info.name && input_info.link != null) { var link = this.graph.links[input_info.link]; - if (link) return link.data; + if (link) { + return link.data; + } } } return this.properties[name]; @@ -2162,8 +2570,12 @@ * @return {Object} object or null */ LGraphNode.prototype.getOutputData = function(slot) { - if (!this.outputs) return null; - if (slot >= this.outputs.length) return null; + if (!this.outputs) { + return null; + } + if (slot >= this.outputs.length) { + return null; + } var info = this.outputs[slot]; return info._data; @@ -2176,8 +2588,12 @@ * @return {Object} object or null { name: string, type: string, links: [ ids of links in number ] } */ LGraphNode.prototype.getOutputInfo = function(slot) { - if (!this.outputs) return null; - if (slot < this.outputs.length) return this.outputs[slot]; + if (!this.outputs) { + return null; + } + if (slot < this.outputs.length) { + return this.outputs[slot]; + } return null; }; @@ -2188,7 +2604,9 @@ * @return {boolean} */ LGraphNode.prototype.isOutputConnected = function(slot) { - if (!this.outputs) return false; + if (!this.outputs) { + return false; + } return ( slot < this.outputs.length && this.outputs[slot].links && @@ -2202,10 +2620,14 @@ * @return {boolean} */ LGraphNode.prototype.isAnyOutputConnected = function() { - if (!this.outputs) return false; - for (var i = 0; i < this.outputs.length; ++i) - if (this.outputs[i].links && this.outputs[i].links.length) + if (!this.outputs) { + return false; + } + for (var i = 0; i < this.outputs.length; ++i) { + if (this.outputs[i].links && this.outputs[i].links.length) { return true; + } + } return false; }; @@ -2216,12 +2638,18 @@ * @return {array} */ LGraphNode.prototype.getOutputNodes = function(slot) { - if (!this.outputs || this.outputs.length == 0) return null; + if (!this.outputs || this.outputs.length == 0) { + return null; + } - if (slot >= this.outputs.length) return null; + if (slot >= this.outputs.length) { + return null; + } var output = this.outputs[slot]; - if (!output.links || output.links.length == 0) return null; + if (!output.links || output.links.length == 0) { + return null; + } var r = []; for (var i = 0; i < output.links.length; i++) { @@ -2229,7 +2657,9 @@ var link = this.graph.links[link_id]; if (link) { var target_node = this.graph.getNodeById(link.target_id); - if (target_node) r.push(target_node); + if (target_node) { + r.push(target_node); + } } } return r; @@ -2242,9 +2672,13 @@ * @param {*} param */ LGraphNode.prototype.trigger = function(action, param) { - if (!this.outputs || !this.outputs.length) return; + if (!this.outputs || !this.outputs.length) { + return; + } - if (this.graph) this.graph._last_trigger_time = LiteGraph.getTime(); + if (this.graph) { + this.graph._last_trigger_time = LiteGraph.getTime(); + } for (var i = 0; i < this.outputs.length; ++i) { var output = this.outputs[i]; @@ -2252,8 +2686,9 @@ !output || output.type !== LiteGraph.EVENT || (action && output.name != action) - ) + ) { continue; + } this.triggerSlot(i, param); } }; @@ -2266,38 +2701,52 @@ * @param {Number} link_id [optional] in case you want to trigger and specific output link in a slot */ LGraphNode.prototype.triggerSlot = function(slot, param, link_id) { - if (!this.outputs) return; + if (!this.outputs) { + return; + } var output = this.outputs[slot]; - if (!output) return; + if (!output) { + return; + } var links = output.links; - if (!links || !links.length) return; + if (!links || !links.length) { + return; + } - if (this.graph) this.graph._last_trigger_time = LiteGraph.getTime(); + if (this.graph) { + this.graph._last_trigger_time = LiteGraph.getTime(); + } //for every link attached here for (var k = 0; k < links.length; ++k) { var id = links[k]; - if (link_id != null && link_id != id) + if (link_id != null && link_id != id) { //to skip links continue; + } var link_info = this.graph.links[links[k]]; - if (!link_info) + if (!link_info) { //not connected continue; + } link_info._last_time = LiteGraph.getTime(); var node = this.graph.getNodeById(link_info.target_id); - if (!node) + if (!node) { //node not found? continue; + } //used to mark events in graph var target_connection = node.inputs[link_info.target_slot]; - if (node.onAction) node.onAction(target_connection.name, param); - else if (node.mode === LiteGraph.ON_TRIGGER) { - if (node.onExecute) node.onExecute(param); + if (node.onAction) { + node.onAction(target_connection.name, param); + } else if (node.mode === LiteGraph.ON_TRIGGER) { + if (node.onExecute) { + node.onExecute(param); + } } } }; @@ -2309,24 +2758,32 @@ * @param {Number} link_id [optional] in case you want to trigger and specific output link in a slot */ LGraphNode.prototype.clearTriggeredSlot = function(slot, link_id) { - if (!this.outputs) return; + if (!this.outputs) { + return; + } var output = this.outputs[slot]; - if (!output) return; + if (!output) { + return; + } var links = output.links; - if (!links || !links.length) return; + if (!links || !links.length) { + return; + } //for every link attached here for (var k = 0; k < links.length; ++k) { var id = links[k]; - if (link_id != null && link_id != id) + if (link_id != null && link_id != id) { //to skip links continue; + } var link_info = this.graph.links[links[k]]; - if (!link_info) + if (!link_info) { //not connected continue; + } link_info._last_time = 0; } }; @@ -2346,10 +2803,18 @@ extra_info ) { var o = { name: name, type: type, default_value: default_value }; - if (extra_info) for (var i in extra_info) o[i] = extra_info[i]; - if (!this.properties_info) this.properties_info = []; + if (extra_info) { + for (var i in extra_info) { + o[i] = extra_info[i]; + } + } + if (!this.properties_info) { + this.properties_info = []; + } this.properties_info.push(o); - if (!this.properties) this.properties = {}; + if (!this.properties) { + this.properties = {}; + } this.properties[name] = default_value; return o; }; @@ -2365,11 +2830,19 @@ */ LGraphNode.prototype.addOutput = function(name, type, extra_info) { var o = { name: name, type: type, links: null }; - if (extra_info) for (var i in extra_info) o[i] = extra_info[i]; + if (extra_info) { + for (var i in extra_info) { + o[i] = extra_info[i]; + } + } - if (!this.outputs) this.outputs = []; + if (!this.outputs) { + this.outputs = []; + } this.outputs.push(o); - if (this.onOutputAdded) this.onOutputAdded(o); + if (this.onOutputAdded) { + this.onOutputAdded(o); + } this.size = this.computeSize(); this.setDirtyCanvas(true, true); return o; @@ -2384,11 +2857,19 @@ for (var i = 0; i < array.length; ++i) { var info = array[i]; var o = { name: info[0], type: info[1], link: null }; - if (array[2]) for (var j in info[2]) o[j] = info[2][j]; + if (array[2]) { + for (var j in info[2]) { + o[j] = info[2][j]; + } + } - if (!this.outputs) this.outputs = []; + if (!this.outputs) { + this.outputs = []; + } this.outputs.push(o); - if (this.onOutputAdded) this.onOutputAdded(o); + if (this.onOutputAdded) { + this.onOutputAdded(o); + } } this.size = this.computeSize(); @@ -2404,17 +2885,23 @@ this.disconnectOutput(slot); this.outputs.splice(slot, 1); for (var i = slot; i < this.outputs.length; ++i) { - if (!this.outputs[i] || !this.outputs[i].links) continue; + if (!this.outputs[i] || !this.outputs[i].links) { + continue; + } var links = this.outputs[i].links; for (var j = 0; j < links.length; ++j) { var link = this.graph.links[links[j]]; - if (!link) continue; + if (!link) { + continue; + } link.origin_slot -= 1; } } this.size = this.computeSize(); - if (this.onOutputRemoved) this.onOutputRemoved(slot); + if (this.onOutputRemoved) { + this.onOutputRemoved(slot); + } this.setDirtyCanvas(true, true); }; @@ -2428,12 +2915,20 @@ 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) o[i] = extra_info[i]; + if (extra_info) { + for (var i in extra_info) { + o[i] = extra_info[i]; + } + } - if (!this.inputs) this.inputs = []; + if (!this.inputs) { + this.inputs = []; + } this.inputs.push(o); this.size = this.computeSize(); - if (this.onInputAdded) this.onInputAdded(o); + if (this.onInputAdded) { + this.onInputAdded(o); + } this.setDirtyCanvas(true, true); return o; }; @@ -2447,11 +2942,19 @@ for (var i = 0; i < array.length; ++i) { var info = array[i]; var o = { name: info[0], type: info[1], link: null }; - if (array[2]) for (var j in info[2]) o[j] = info[2][j]; + if (array[2]) { + for (var j in info[2]) { + o[j] = info[2][j]; + } + } - if (!this.inputs) this.inputs = []; + if (!this.inputs) { + this.inputs = []; + } this.inputs.push(o); - if (this.onInputAdded) this.onInputAdded(o); + if (this.onInputAdded) { + this.onInputAdded(o); + } } this.size = this.computeSize(); @@ -2467,13 +2970,19 @@ this.disconnectInput(slot); this.inputs.splice(slot, 1); for (var i = slot; i < this.inputs.length; ++i) { - if (!this.inputs[i]) continue; + if (!this.inputs[i]) { + continue; + } var link = this.graph.links[this.inputs[i].link]; - if (!link) continue; + if (!link) { + continue; + } link.target_slot -= 1; } this.size = this.computeSize(); - if (this.onInputRemoved) this.onInputRemoved(slot); + if (this.onInputRemoved) { + this.onInputRemoved(slot); + } this.setDirtyCanvas(true, true); }; @@ -2504,7 +3013,9 @@ * @return {number} the total size */ LGraphNode.prototype.computeSize = function(minHeight, out) { - if (this.constructor.size) return this.constructor.size.concat(); + if (this.constructor.size) { + return this.constructor.size.concat(); + } var rows = Math.max( this.inputs ? this.inputs.length : 1, @@ -2517,50 +3028,66 @@ (this.constructor.slot_start_y || 0) + rows * LiteGraph.NODE_SLOT_HEIGHT; var widgets_height = 0; - if (this.widgets && this.widgets.length) + if (this.widgets && this.widgets.length) { widgets_height = this.widgets.length * (LiteGraph.NODE_WIDGET_HEIGHT + 4) + 8; - if (this.widgets_up) size[1] = Math.max(size[1], widgets_height); - else size[1] += widgets_height; + } + if (this.widgets_up) { + size[1] = Math.max(size[1], widgets_height); + } else { + size[1] += widgets_height; + } var font_size = font_size; var title_width = compute_text_size(this.title); var input_width = 0; var output_width = 0; - if (this.inputs) + if (this.inputs) { for (var i = 0, l = this.inputs.length; i < l; ++i) { var input = this.inputs[i]; var text = input.label || input.name || ""; var text_width = compute_text_size(text); - if (input_width < text_width) input_width = text_width; + if (input_width < text_width) { + input_width = text_width; + } } + } - if (this.outputs) + if (this.outputs) { for (var i = 0, l = this.outputs.length; i < l; ++i) { var output = this.outputs[i]; var text = output.label || output.name || ""; var text_width = compute_text_size(text); - if (output_width < text_width) output_width = text_width; + if (output_width < text_width) { + output_width = text_width; + } } + } size[0] = Math.max(input_width + output_width + 10, title_width); size[0] = Math.max(size[0], LiteGraph.NODE_WIDTH); - if (this.widgets && this.widgets.length) + if (this.widgets && this.widgets.length) { size[0] = Math.max(size[0], LiteGraph.NODE_WIDTH * 1.5); + } - if (this.onResize) this.onResize(size); + if (this.onResize) { + this.onResize(size); + } function compute_text_size(text) { - if (!text) return 0; + if (!text) { + return 0; + } return font_size * text.length * 0.6; } if ( this.constructor.min_height && size[1] < this.constructor.min_height - ) + ) { size[1] = this.constructor.min_height; + } size[1] += 6; //margin @@ -2580,7 +3107,9 @@ callback, options ) { - if (!this.widgets) this.widgets = []; + if (!this.widgets) { + this.widgets = []; + } var w = { type: type.toLowerCase(), name: name, @@ -2589,18 +3118,24 @@ options: options || {} }; - if (w.options.y !== undefined) w.y = w.options.y; + if (w.options.y !== undefined) { + w.y = w.options.y; + } - if (!callback) + if (!callback) { console.warn("LiteGraph addWidget(...) without a callback"); - if (type == "combo" && !w.options.values) + } + if (type == "combo" && !w.options.values) { throw "LiteGraph addWidget('combo',...) requires to pass values in options: { values:['red','blue'] }"; + } this.widgets.push(w); return w; }; LGraphNode.prototype.addCustomWidget = function(custom_widget) { - if (!this.widgets) this.widgets = []; + if (!this.widgets) { + this.widgets = []; + } this.widgets.push(custom_widget); return custom_widget; }; @@ -2618,7 +3153,9 @@ out[2] = this.size[0] + 4; out[3] = this.size[1] + LiteGraph.NODE_TITLE_HEIGHT; - if (this.onBounding) this.onBounding(out); + if (this.onBounding) { + this.onBounding(out); + } return out; }; @@ -2633,7 +3170,9 @@ margin = margin || 0; var margin_top = this.graph && this.graph.isLive() ? 0 : 20; - if (skip_title) margin_top = 0; + if (skip_title) { + margin_top = 0; + } if (this.flags && this.flags.collapsed) { //if ( distance([x,y], [this.pos[0] + this.size[0]*0.5, this.pos[1] + this.size[1]*0.5]) < LiteGraph.NODE_COLLAPSED_RADIUS) if ( @@ -2646,15 +3185,17 @@ 2 * margin, LiteGraph.NODE_TITLE_HEIGHT + 2 * margin ) - ) + ) { return true; + } } else if ( this.pos[0] - 4 - margin < x && this.pos[0] + this.size[0] + 4 + margin > x && this.pos[1] - margin_top - margin < y && this.pos[1] + this.size[1] + margin > y - ) + ) { return true; + } return false; }; @@ -2668,7 +3209,7 @@ LGraphNode.prototype.getSlotInPosition = function(x, y) { //search for inputs var link_pos = new Float32Array(2); - if (this.inputs) + if (this.inputs) { for (var i = 0, l = this.inputs.length; i < l; ++i) { var input = this.inputs[i]; this.getConnectionPos(true, i, link_pos); @@ -2681,11 +3222,13 @@ 20, 10 ) - ) + ) { return { input: input, slot: i, link_pos: link_pos }; + } } + } - if (this.outputs) + if (this.outputs) { for (var i = 0, l = this.outputs.length; i < l; ++i) { var output = this.outputs[i]; this.getConnectionPos(false, i, link_pos); @@ -2698,9 +3241,11 @@ 20, 10 ) - ) + ) { return { output: output, slot: i, link_pos: link_pos }; + } } + } return null; }; @@ -2712,9 +3257,14 @@ * @return {number} the slot (-1 if not found) */ LGraphNode.prototype.findInputSlot = function(name) { - if (!this.inputs) return -1; - for (var i = 0, l = this.inputs.length; i < l; ++i) - if (name == this.inputs[i].name) return i; + if (!this.inputs) { + return -1; + } + for (var i = 0, l = this.inputs.length; i < l; ++i) { + if (name == this.inputs[i].name) { + return i; + } + } return -1; }; @@ -2725,9 +3275,14 @@ * @return {number} the slot (-1 if not found) */ LGraphNode.prototype.findOutputSlot = function(name) { - if (!this.outputs) return -1; - for (var i = 0, l = this.outputs.length; i < l; ++i) - if (name == this.outputs[i].name) return i; + if (!this.outputs) { + return -1; + } + for (var i = 0, l = this.outputs.length; i < l; ++i) { + if (name == this.outputs[i].name) { + return i; + } + } return -1; }; @@ -2754,31 +3309,39 @@ if (slot.constructor === String) { slot = this.findOutputSlot(slot); if (slot == -1) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, no slot of name " + slot); + } return null; } } else if (!this.outputs || slot >= this.outputs.length) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, slot number not found"); + } return null; } - if (target_node && target_node.constructor === Number) + if (target_node && target_node.constructor === Number) { target_node = this.graph.getNodeById(target_node); - if (!target_node) throw "target node is null"; + } + if (!target_node) { + throw "target node is null"; + } //avoid loopback - if (target_node == this) return null; + if (target_node == this) { + return null; + } //you can specify the slot by name if (target_slot.constructor === String) { target_slot = target_node.findInputSlot(target_slot); if (target_slot == -1) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log( "Connect: Error, no slot of name " + target_slot ); + } return null; } } else if (target_slot === LiteGraph.EVENT) { @@ -2794,14 +3357,16 @@ !target_node.inputs || target_slot >= target_node.inputs.length ) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, slot number not found"); + } return null; } //if there is something already plugged there, disconnect - if (target_node.inputs[target_slot].link != null) + if (target_node.inputs[target_slot].link != null) { target_node.disconnectInput(target_slot); + } //why here?? //this.setDirtyCanvas(false,true); @@ -2810,12 +3375,14 @@ var output = this.outputs[slot]; //allows nodes to block connection - if (target_node.onConnectInput) + if (target_node.onConnectInput) { if ( target_node.onConnectInput(target_slot, output.type, output) === false - ) + ) { return null; + } + } var input = target_node.inputs[target_slot]; var link_info = null; @@ -2834,20 +3401,25 @@ this.graph.links[link_info.id] = link_info; //connect in output - if (output.links == null) output.links = []; + if (output.links == null) { + output.links = []; + } output.links.push(link_info.id); //connect in input target_node.inputs[target_slot].link = link_info.id; - if (this.graph) this.graph._version++; - if (this.onConnectionsChange) + if (this.graph) { + this.graph._version++; + } + if (this.onConnectionsChange) { this.onConnectionsChange( LiteGraph.OUTPUT, slot, true, link_info, output - ); //link_info has been created now, so its updated - if (target_node.onConnectionsChange) + ); + } //link_info has been created now, so its updated + if (target_node.onConnectionsChange) { target_node.onConnectionsChange( LiteGraph.INPUT, target_slot, @@ -2855,6 +3427,7 @@ link_info, input ); + } if (this.graph && this.graph.onNodeConnectionChange) { this.graph.onNodeConnectionChange( LiteGraph.INPUT, @@ -2890,25 +3463,32 @@ if (slot.constructor === String) { slot = this.findOutputSlot(slot); if (slot == -1) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, no slot of name " + slot); + } return false; } } else if (!this.outputs || slot >= this.outputs.length) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, slot number not found"); + } return false; } //get output slot var output = this.outputs[slot]; - if (!output || !output.links || output.links.length == 0) return false; + if (!output || !output.links || output.links.length == 0) { + return false; + } //one of the output links in this slot if (target_node) { - if (target_node.constructor === Number) + if (target_node.constructor === Number) { target_node = this.graph.getNodeById(target_node); - if (!target_node) throw "Target Node not found"; + } + if (!target_node) { + throw "Target Node not found"; + } for (var i = 0, l = output.links.length; i < l; i++) { var link_id = output.links[i]; @@ -2920,16 +3500,19 @@ var input = target_node.inputs[link_info.target_slot]; input.link = null; //remove there delete this.graph.links[link_id]; //remove the link from the links pool - if (this.graph) this.graph._version++; - if (target_node.onConnectionsChange) + if (this.graph) { + this.graph._version++; + } + if (target_node.onConnectionsChange) { target_node.onConnectionsChange( LiteGraph.INPUT, link_info.target_slot, false, link_info, input - ); //link_info hasn't been modified so its ok - if (this.onConnectionsChange) + ); + } //link_info hasn't been modified so its ok + if (this.onConnectionsChange) { this.onConnectionsChange( LiteGraph.OUTPUT, slot, @@ -2937,12 +3520,14 @@ link_info, output ); - if (this.graph && this.graph.onNodeConnectionChange) + } + if (this.graph && this.graph.onNodeConnectionChange) { this.graph.onNodeConnectionChange( LiteGraph.OUTPUT, this, slot ); + } if (this.graph && this.graph.onNodeConnectionChange) { this.graph.onNodeConnectionChange( LiteGraph.OUTPUT, @@ -2963,33 +3548,38 @@ for (var i = 0, l = output.links.length; i < l; i++) { var link_id = output.links[i]; var link_info = this.graph.links[link_id]; - if (!link_info) + if (!link_info) { //bug: it happens sometimes continue; + } var target_node = this.graph.getNodeById(link_info.target_id); var input = null; - if (this.graph) this.graph._version++; + if (this.graph) { + this.graph._version++; + } if (target_node) { input = target_node.inputs[link_info.target_slot]; input.link = null; //remove other side link - if (target_node.onConnectionsChange) + if (target_node.onConnectionsChange) { target_node.onConnectionsChange( LiteGraph.INPUT, link_info.target_slot, false, link_info, input - ); //link_info hasn't been modified so its ok - if (this.graph && this.graph.onNodeConnectionChange) + ); + } //link_info hasn't been modified so its ok + if (this.graph && this.graph.onNodeConnectionChange) { this.graph.onNodeConnectionChange( LiteGraph.INPUT, target_node, link_info.target_slot ); + } } delete this.graph.links[link_id]; //remove the link from the links pool - if (this.onConnectionsChange) + if (this.onConnectionsChange) { this.onConnectionsChange( LiteGraph.OUTPUT, slot, @@ -2997,6 +3587,7 @@ link_info, output ); + } if (this.graph && this.graph.onNodeConnectionChange) { this.graph.onNodeConnectionChange( LiteGraph.OUTPUT, @@ -3029,18 +3620,22 @@ if (slot.constructor === String) { slot = this.findInputSlot(slot); if (slot == -1) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, no slot of name " + slot); + } return false; } } else if (!this.inputs || slot >= this.inputs.length) { - if (LiteGraph.debug) + if (LiteGraph.debug) { console.log("Connect: Error, slot number not found"); + } return false; } var input = this.inputs[slot]; - if (!input) return false; + if (!input) { + return false; + } var link_id = this.inputs[slot].link; this.inputs[slot].link = null; @@ -3049,11 +3644,14 @@ var link_info = this.graph.links[link_id]; if (link_info) { var target_node = this.graph.getNodeById(link_info.origin_id); - if (!target_node) return false; + if (!target_node) { + return false; + } var output = target_node.outputs[link_info.origin_slot]; - if (!output || !output.links || output.links.length == 0) + if (!output || !output.links || output.links.length == 0) { return false; + } //search in the inputs list for this link for (var i = 0, l = output.links.length; i < l; i++) { @@ -3064,8 +3662,10 @@ } delete this.graph.links[link_id]; //remove from the pool - if (this.graph) this.graph._version++; - if (this.onConnectionsChange) + if (this.graph) { + this.graph._version++; + } + if (this.onConnectionsChange) { this.onConnectionsChange( LiteGraph.INPUT, slot, @@ -3073,7 +3673,8 @@ link_info, input ); - if (target_node.onConnectionsChange) + } + if (target_node.onConnectionsChange) { target_node.onConnectionsChange( LiteGraph.OUTPUT, i, @@ -3081,6 +3682,7 @@ link_info, output ); + } if (this.graph && this.graph.onNodeConnectionChange) { this.graph.onNodeConnectionChange( LiteGraph.OUTPUT, @@ -3111,8 +3713,12 @@ ) { out = out || new Float32Array(2); var num_slots = 0; - if (is_input && this.inputs) num_slots = this.inputs.length; - if (!is_input && this.outputs) num_slots = this.outputs.length; + if (is_input && this.inputs) { + num_slots = this.inputs.length; + } + if (!is_input && this.outputs) { + num_slots = this.outputs.length; + } var offset = LiteGraph.NODE_SLOT_HEIGHT * 0.5; @@ -3120,12 +3726,17 @@ var w = this._collapsed_width || LiteGraph.NODE_COLLAPSED_WIDTH; if (this.horizontal) { out[0] = this.pos[0] + w * 0.5; - if (is_input) + if (is_input) { out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT; - else out[1] = this.pos[1]; + } else { + out[1] = this.pos[1]; + } } else { - if (is_input) out[0] = this.pos[0]; - else out[0] = this.pos[0] + w; + if (is_input) { + out[0] = this.pos[0]; + } else { + out[0] = this.pos[0] + w; + } out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT * 0.5; } return out; @@ -3161,14 +3772,20 @@ if (this.horizontal) { out[0] = this.pos[0] + (slot_number + 0.5) * (this.size[0] / num_slots); - if (is_input) out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT; - else out[1] = this.pos[1] + this.size[1]; + if (is_input) { + out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT; + } else { + out[1] = this.pos[1] + this.size[1]; + } return out; } //default vertical slots - if (is_input) out[0] = this.pos[0] + offset; - else out[0] = this.pos[0] + this.size[0] + 1 - offset; + if (is_input) { + out[0] = this.pos[0] + offset; + } else { + out[0] = this.pos[0] + this.size[0] + 1 - offset; + } out[1] = this.pos[1] + (slot_number + 0.7) * LiteGraph.NODE_SLOT_HEIGHT + @@ -3188,9 +3805,13 @@ /* Console output */ LGraphNode.prototype.trace = function(msg) { - if (!this.console) this.console = []; + if (!this.console) { + this.console = []; + } this.console.push(msg); - if (this.console.length > LGraphNode.MAX_CONSOLE) this.console.shift(); + if (this.console.length > LGraphNode.MAX_CONSOLE) { + this.console.shift(); + } this.graph.onNodeTrace(this, msg); }; @@ -3200,7 +3821,9 @@ dirty_foreground, dirty_background ) { - if (!this.graph) return; + if (!this.graph) { + return; + } this.graph.sendActionToCanvas("setDirty", [ dirty_foreground, dirty_background @@ -3261,14 +3884,18 @@ LGraphNode.prototype.executeAction = function(action) /* Allows to get onMouseMove and onMouseUp events even if the mouse is out of focus */ LGraphNode.prototype.captureInput = function(v) { - if (!this.graph || !this.graph.list_of_graphcanvas) return; + if (!this.graph || !this.graph.list_of_graphcanvas) { + return; + } var list = this.graph.list_of_graphcanvas; for (var i = 0; i < list.length; ++i) { var c = list[i]; //releasing somebody elses capture?! - if (!v && c.node_capturing_input != this) continue; + if (!v && c.node_capturing_input != this) { + continue; + } //change c.node_capturing_input = v ? this : null; @@ -3281,9 +3908,14 @@ LGraphNode.prototype.executeAction = function(action) **/ LGraphNode.prototype.collapse = function(force) { this.graph._version++; - if (this.constructor.collapsable === false && !force) return; - if (!this.flags.collapsed) this.flags.collapsed = true; - else this.flags.collapsed = false; + if (this.constructor.collapsable === false && !force) { + return; + } + if (!this.flags.collapsed) { + this.flags.collapsed = true; + } else { + this.flags.collapsed = false; + } this.setDirtyCanvas(true, true); }; @@ -3294,8 +3926,11 @@ LGraphNode.prototype.executeAction = function(action) LGraphNode.prototype.pin = function(v) { this.graph._version++; - if (v === undefined) this.flags.pinned = !this.flags.pinned; - else this.flags.pinned = v; + if (v === undefined) { + this.flags.pinned = !this.flags.pinned; + } else { + this.flags.pinned = v; + } }; LGraphNode.prototype.localToScreen = function(x, y, graphcanvas) { @@ -3325,7 +3960,9 @@ LGraphNode.prototype.executeAction = function(action) Object.defineProperty(this, "pos", { set: function(v) { - if (!v || v.length < 2) return; + if (!v || v.length < 2) { + return; + } this._pos[0] = v[0]; this._pos[1] = v[1]; }, @@ -3337,7 +3974,9 @@ LGraphNode.prototype.executeAction = function(action) Object.defineProperty(this, "size", { set: function(v) { - if (!v || v.length < 2) return; + if (!v || v.length < 2) { + return; + } this._size[0] = Math.max(140, v[0]); this._size[1] = Math.max(80, v[1]); }, @@ -3373,7 +4012,9 @@ LGraphNode.prototype.executeAction = function(action) LGraphGroup.prototype.move = function(deltax, deltay, ignore_nodes) { this._pos[0] += deltax; this._pos[1] += deltay; - if (ignore_nodes) return; + if (ignore_nodes) { + return; + } for (var i = 0; i < this._nodes.length; ++i) { var node = this._nodes[i]; node.pos[0] += deltax; @@ -3389,7 +4030,9 @@ LGraphNode.prototype.executeAction = function(action) for (var i = 0; i < nodes.length; ++i) { var node = nodes[i]; node.getBounding(node_bounding); - if (!overlapBounding(this._bounding, node_bounding)) continue; //out of the visible area + if (!overlapBounding(this._bounding, node_bounding)) { + continue; + } //out of the visible area this._nodes.push(node); } }; @@ -3413,7 +4056,9 @@ LGraphNode.prototype.executeAction = function(action) if (element) { this.element = element; - if (!skip_events) this.bindEvents(element); + if (!skip_events) { + this.bindEvents(element); + } } } @@ -3453,7 +4098,9 @@ LGraphNode.prototype.executeAction = function(action) }; DragAndScale.prototype.onMouse = function(e) { - if (!this.enabled) return; + if (!this.enabled) { + return; + } var canvas = this.element; var rect = canvas.getBoundingClientRect(); @@ -3464,7 +4111,9 @@ LGraphNode.prototype.executeAction = function(action) e.dragging = this.dragging; var ignore = false; - if (this.onmouse) ignore = this.onmouse(e); + if (this.onmouse) { + ignore = this.onmouse(e); + } if (e.type == "mousedown") { this.dragging = true; @@ -3484,7 +4133,9 @@ LGraphNode.prototype.executeAction = function(action) if (!ignore) { var deltax = x - this.last_mouse[0]; var deltay = y - this.last_mouse[1]; - if (this.dragging) this.mouseDrag(deltax, deltay); + if (this.dragging) { + this.mouseDrag(deltax, deltay); + } } } else if (e.type == "mouseup") { this.dragging = false; @@ -3503,10 +4154,12 @@ LGraphNode.prototype.executeAction = function(action) e.type == "DOMMouseScroll" ) { e.eventType = "mousewheel"; - if (e.type == "wheel") e.wheel = -e.deltaY; - else + if (e.type == "wheel") { + e.wheel = -e.deltaY; + } else { e.wheel = e.wheelDeltaY != null ? e.wheelDeltaY : e.detail * -60; + } //from stack overflow e.delta = e.wheelDelta @@ -3549,19 +4202,30 @@ LGraphNode.prototype.executeAction = function(action) this.offset[0] += x / this.scale; this.offset[1] += y / this.scale; - if (this.onredraw) this.onredraw(this); + if (this.onredraw) { + this.onredraw(this); + } }; DragAndScale.prototype.changeScale = function(value, zooming_center) { - if (value < this.min_scale) value = this.min_scale; - else if (value > this.max_scale) value = this.max_scale; + if (value < this.min_scale) { + value = this.min_scale; + } else if (value > this.max_scale) { + value = this.max_scale; + } - if (value == this.scale) return; + if (value == this.scale) { + return; + } - if (!this.element) return; + if (!this.element) { + return; + } var rect = this.element.getBoundingClientRect(); - if (!rect) return; + if (!rect) { + return; + } zooming_center = zooming_center || [ rect.width * 0.5, @@ -3569,7 +4233,9 @@ LGraphNode.prototype.executeAction = function(action) ]; var center = this.convertCanvasToOffset(zooming_center); this.scale = value; - if (Math.abs(this.scale - 1) < 0.01) this.scale = 1; + if (Math.abs(this.scale - 1) < 0.01) { + this.scale = 1; + } var new_center = this.convertCanvasToOffset(zooming_center); var delta_offset = [ @@ -3580,7 +4246,9 @@ LGraphNode.prototype.executeAction = function(action) this.offset[0] += delta_offset[0]; this.offset[1] += delta_offset[1]; - if (this.onredraw) this.onredraw(this); + if (this.onredraw) { + this.onredraw(this); + } }; DragAndScale.prototype.changeDeltaScale = function(value, zooming_center) { @@ -3615,8 +4283,9 @@ LGraphNode.prototype.executeAction = function(action) this.background_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII="; - if (canvas && canvas.constructor === String) + if (canvas && canvas.constructor === String) { canvas = document.querySelector(canvas); + } this.ds = new DragAndScale(); this.zoom_modify_alpha = true; //otherwise it generates ugly patterns when scaling down too much @@ -3688,12 +4357,16 @@ LGraphNode.prototype.executeAction = function(action) this.visible_links = []; //link canvas and graph - if (graph) graph.attachCanvas(this); + if (graph) { + graph.attachCanvas(this); + } this.setCanvas(canvas); this.clear(); - if (!options.skip_render) this.startRendering(); + if (!options.skip_render) { + this.startRendering(); + } this.autoresize = options.autoresize; } @@ -3744,7 +4417,9 @@ LGraphNode.prototype.executeAction = function(action) this.last_mouseclick = 0; this.visible_area.set([0, 0, 0, 0]); - if (this.onClear) this.onClear(); + if (this.onClear) { + this.onClear(); + } }; /** @@ -3754,9 +4429,13 @@ LGraphNode.prototype.executeAction = function(action) * @param {LGraph} graph */ LGraphCanvas.prototype.setGraph = function(graph, skip_clear) { - if (this.graph == graph) return; + if (this.graph == graph) { + return; + } - if (!skip_clear) this.clear(); + if (!skip_clear) { + this.clear(); + } if (!graph && this.graph) { this.graph.detachCanvas(this); @@ -3781,14 +4460,20 @@ LGraphNode.prototype.executeAction = function(action) * @param {LGraph} graph */ LGraphCanvas.prototype.openSubgraph = function(graph) { - if (!graph) throw "graph cannot be null"; + if (!graph) { + throw "graph cannot be null"; + } - if (this.graph == graph) throw "graph cannot be the same"; + if (this.graph == graph) { + throw "graph cannot be the same"; + } this.clear(); if (this.graph) { - if (!this._graph_stack) this._graph_stack = []; + if (!this._graph_stack) { + this._graph_stack = []; + } this._graph_stack.push(this.graph); } @@ -3803,7 +4488,9 @@ LGraphNode.prototype.executeAction = function(action) * @param {LGraph} assigns a graph */ LGraphCanvas.prototype.closeSubgraph = function() { - if (!this._graph_stack || this._graph_stack.length == 0) return; + if (!this._graph_stack || this._graph_stack.length == 0) { + return; + } var subgraph_node = this.graph._subgraph_node; var graph = this._graph_stack.pop(); this.selected_nodes = {}; @@ -3822,8 +4509,8 @@ LGraphNode.prototype.executeAction = function(action) * @return {LGraph} the active graph */ LGraphCanvas.prototype.getCurrentGraph = function() { - return this.graph; - } + return this.graph; + }; /** * assigns a canvas @@ -3837,22 +4524,29 @@ LGraphNode.prototype.executeAction = function(action) if (canvas) { if (canvas.constructor === String) { canvas = document.getElementById(canvas); - if (!canvas) + if (!canvas) { throw "Error creating LiteGraph canvas: Canvas not found"; + } } } - if (canvas === this.canvas) return; + if (canvas === this.canvas) { + return; + } if (!canvas && this.canvas) { //maybe detach events from old_canvas - if (!skip_events) this.unbindEvents(); + if (!skip_events) { + this.unbindEvents(); + } } this.canvas = canvas; this.ds.element = canvas; - if (!canvas) return; + if (!canvas) { + return; + } //this.canvas.tabindex = "1000"; canvas.className += " lgraphcanvas"; @@ -3868,18 +4562,20 @@ LGraphNode.prototype.executeAction = function(action) } if (canvas.getContext == null) { - if (canvas.localName != "canvas") + if (canvas.localName != "canvas") { throw "Element supplied for LGraphCanvas must be a element, you passed a " + canvas.localName; + } throw "This browser doesn't support Canvas"; } var ctx = (this.ctx = canvas.getContext("2d")); if (ctx == null) { - if (!canvas.webgl_enabled) + if (!canvas.webgl_enabled) { console.warn( "This canvas seems to be WebGL, enabling WebGL renderer" ); + } this.enableWebGL(); } @@ -3887,7 +4583,9 @@ LGraphNode.prototype.executeAction = function(action) this._mousemove_callback = this.processMouseMove.bind(this); this._mouseup_callback = this.processMouseUp.bind(this); - if (!skip_events) this.bindEvents(); + if (!skip_events) { + this.bindEvents(); + } }; //used in some events to capture them @@ -3997,9 +4695,13 @@ LGraphNode.prototype.executeAction = function(action) LGraphCanvas.getFileExtension = function(url) { var question = url.indexOf("?"); - if (question != -1) url = url.substr(0, question); + if (question != -1) { + url = url.substr(0, question); + } var point = url.lastIndexOf("."); - if (point == -1) return ""; + if (point == -1) { + return ""; + } return url.substr(point + 1).toLowerCase(); }; @@ -4009,10 +4711,12 @@ LGraphNode.prototype.executeAction = function(action) * @method enableWebGL **/ LGraphCanvas.prototype.enableWebGL = function() { - if (typeof GL === undefined) + if (typeof GL === undefined) { throw "litegl.js must be included to use a WebGL canvas"; - if (typeof enableWebGLCanvas === undefined) + } + if (typeof enableWebGLCanvas === undefined) { throw "webglCanvas.js must be included to use this feature"; + } this.gl = this.ctx = enableWebGLCanvas(this.canvas); this.ctx.webgl = true; @@ -4036,8 +4740,12 @@ LGraphNode.prototype.executeAction = function(action) * @param {bool} bgcanvas if the background canvas is dirty (the one containing the wires) */ LGraphCanvas.prototype.setDirty = function(fgcanvas, bgcanvas) { - if (fgcanvas) this.dirty_canvas = true; - if (bgcanvas) this.dirty_bgcanvas = true; + if (fgcanvas) { + this.dirty_canvas = true; + } + if (bgcanvas) { + this.dirty_bgcanvas = true; + } }; /** @@ -4047,7 +4755,9 @@ LGraphNode.prototype.executeAction = function(action) * @return {window} returns the window where the canvas is attached (the DOM root node) */ LGraphCanvas.prototype.getCanvasWindow = function() { - if (!this.canvas) return window; + if (!this.canvas) { + return window; + } var doc = this.canvas.ownerDocument; return doc.defaultView || doc.parentWindow; }; @@ -4058,17 +4768,22 @@ LGraphNode.prototype.executeAction = function(action) * @method startRendering */ LGraphCanvas.prototype.startRendering = function() { - if (this.is_rendering) return; //already rendering + if (this.is_rendering) { + return; + } //already rendering this.is_rendering = true; renderFrame.call(this); function renderFrame() { - if (!this.pause_rendering) this.draw(); + if (!this.pause_rendering) { + this.draw(); + } var window = this.getCanvasWindow(); - if (this.is_rendering) + if (this.is_rendering) { window.requestAnimationFrame(renderFrame.bind(this)); + } } }; @@ -4091,7 +4806,9 @@ LGraphNode.prototype.executeAction = function(action) /* LiteGraphCanvas input */ LGraphCanvas.prototype.processMouseDown = function(e) { - if (!this.graph) return; + if (!this.graph) { + return; + } this.adjustMouseEvent(e); @@ -4131,7 +4848,9 @@ LGraphNode.prototype.executeAction = function(action) LiteGraph.closeAllContextMenus(ref_window); if (this.onMouse) { - if (this.onMouse(e) == true) return; + if (this.onMouse(e) == true) { + return; + } } if (e.which == 1) { @@ -4150,8 +4869,9 @@ LGraphNode.prototype.executeAction = function(action) //when clicked on top of a node //and it is not interactive if (node && this.allow_interaction && !skip_action) { - if (!this.live_mode && !node.flags.pinned) - this.bringToFront(node); //if it wasn't selected? + if (!this.live_mode && !node.flags.pinned) { + this.bringToFront(node); + } //if it wasn't selected? //not dragging mouse to connect two slots if ( @@ -4177,7 +4897,7 @@ LGraphNode.prototype.executeAction = function(action) skip_action = true; } else { //search for outputs - if (node.outputs) + if (node.outputs) { for ( var i = 0, l = node.outputs.length; i < l; @@ -4203,23 +4923,28 @@ LGraphNode.prototype.executeAction = function(action) ); this.connecting_slot = i; - if (e.shiftKey) node.disconnectOutput(i); + if (e.shiftKey) { + node.disconnectOutput(i); + } if (is_double_click) { - if (node.onOutputDblClick) + if (node.onOutputDblClick) { node.onOutputDblClick(i, e); + } } else { - if (node.onOutputClick) + if (node.onOutputClick) { node.onOutputClick(i, e); + } } skip_action = true; break; } } + } //search for inputs - if (node.inputs) + if (node.inputs) { for ( var i = 0, l = node.inputs.length; i < l; @@ -4238,11 +4963,13 @@ LGraphNode.prototype.executeAction = function(action) ) ) { if (is_double_click) { - if (node.onInputDblClick) + if (node.onInputDblClick) { node.onInputDblClick(i, e); + } } else { - if (node.onInputClick) + if (node.onInputClick) { node.onInputClick(i, e); + } } if (input.link !== null) { @@ -4274,6 +5001,7 @@ LGraphNode.prototype.executeAction = function(action) } } } + } } //not resizing } @@ -4304,7 +5032,7 @@ LGraphNode.prototype.executeAction = function(action) //double clicking if (is_double_click && this.selected_nodes[node.id]) { //double click node - if (node.onDblClick) + if (node.onDblClick) { node.onDblClick( e, [ @@ -4313,6 +5041,7 @@ LGraphNode.prototype.executeAction = function(action) ], this ); + } this.processNodeDblClicked(node); block_drag_node = true; } @@ -4333,9 +5062,12 @@ LGraphNode.prototype.executeAction = function(action) } if (!block_drag_node) { - if (this.allow_dragnodes) this.node_dragged = node; - if (!this.selected_nodes[node.id]) + if (this.allow_dragnodes) { + this.node_dragged = node; + } + if (!this.selected_nodes[node.id]) { this.processNodeSelected(node, e); + } } this.dirty_canvas = true; @@ -4352,8 +5084,9 @@ LGraphNode.prototype.executeAction = function(action) e.canvasX > center[0] + 4 || e.canvasY < center[1] - 4 || e.canvasY > center[1] + 4 - ) + ) { continue; + } //link clicked this.showLinkMenu(link, e); break; @@ -4365,7 +5098,9 @@ LGraphNode.prototype.executeAction = function(action) ); this.selected_group_resizing = false; if (this.selected_group) { - if (e.ctrlKey) this.dragging_rectangle = null; + if (e.ctrlKey) { + this.dragging_rectangle = null; + } var dist = distance( [e.canvasX, e.canvasY], @@ -4376,12 +5111,16 @@ LGraphNode.prototype.executeAction = function(action) this.selected_group.size[1] ] ); - if (dist * this.ds.scale < 10) + if (dist * this.ds.scale < 10) { this.selected_group_resizing = true; - else this.selected_group.recomputeInsideNodes(); + } else { + this.selected_group.recomputeInsideNodes(); + } } - if (is_double_click) this.showSearchBox(e); + if (is_double_click) { + this.showSearchBox(e); + } clicking_canvas_bg = true; } @@ -4419,11 +5158,14 @@ LGraphNode.prototype.executeAction = function(action) "input" && ref_window.document.activeElement.nodeName.toLowerCase() != "textarea") - ) + ) { e.preventDefault(); + } e.stopPropagation(); - if (this.onMouseDown) this.onMouseDown(e); + if (this.onMouseDown) { + this.onMouseDown(e); + } return false; }; @@ -4433,9 +5175,13 @@ LGraphNode.prototype.executeAction = function(action) * @method processMouseMove **/ LGraphCanvas.prototype.processMouseMove = function(e) { - if (this.autoresize) this.resize(); + if (this.autoresize) { + this.resize(); + } - if (!this.graph) return; + if (!this.graph) { + return; + } LGraphCanvas.active_canvas = this; this.adjustMouseEvent(e); @@ -4465,16 +5211,18 @@ LGraphNode.prototype.executeAction = function(action) this.dirty_canvas = true; } else if (this.selected_group) { //moving/resizing a group - if (this.selected_group_resizing) + if (this.selected_group_resizing) { this.selected_group.size = [ e.canvasX - this.selected_group.pos[0], e.canvasY - this.selected_group.pos[1] ]; - else { + } else { var deltax = delta[0] / this.ds.scale; var deltay = delta[1] / this.ds.scale; this.selected_group.move(deltax, deltay, e.ctrlKey); - if (this.selected_group._nodes.length) this.dirty_canvas = true; + if (this.selected_group._nodes.length) { + this.dirty_canvas = true; + } } this.dirty_bgcanvas = true; } else if (this.dragging_canvas) { @@ -4483,7 +5231,9 @@ LGraphNode.prototype.executeAction = function(action) this.dirty_canvas = true; this.dirty_bgcanvas = true; } else if (this.allow_interaction) { - if (this.connecting_node) this.dirty_canvas = true; + if (this.connecting_node) { + this.dirty_canvas = true; + } //get node over var node = this.graph.getNodeOnPos( @@ -4500,8 +5250,9 @@ LGraphNode.prototype.executeAction = function(action) ) { //mouse leave this.graph._nodes[i].mouseOver = false; - if (this.node_over && this.node_over.onMouseLeave) + if (this.node_over && this.node_over.onMouseLeave) { this.node_over.onMouseLeave(e); + } this.node_over = null; this.dirty_canvas = true; } @@ -4516,16 +5267,19 @@ LGraphNode.prototype.executeAction = function(action) this.node_over = node; this.dirty_canvas = true; - if (node.onMouseEnter) node.onMouseEnter(e); + if (node.onMouseEnter) { + node.onMouseEnter(e); + } } //in case the node wants to do something - if (node.onMouseMove) + if (node.onMouseMove) { node.onMouseMove( e, [e.canvasX - node.pos[0], e.canvasY - node.pos[1]], this ); + } //if dragging a link if (this.connecting_node) { @@ -4549,9 +5303,12 @@ LGraphNode.prototype.executeAction = function(action) this.connecting_output.type, slot_type ) - ) + ) { this._highlight_input = pos; - } else this._highlight_input = null; + } + } else { + this._highlight_input = null; + } } } @@ -4566,11 +5323,15 @@ LGraphNode.prototype.executeAction = function(action) 5, 5 ) - ) + ) { this.canvas.style.cursor = "se-resize"; - else this.canvas.style.cursor = "crosshair"; + } else { + this.canvas.style.cursor = "crosshair"; + } } - } else if (this.canvas) this.canvas.style.cursor = ""; + } else if (this.canvas) { + this.canvas.style.cursor = ""; + } if ( this.node_capturing_input && @@ -4614,10 +5375,12 @@ LGraphNode.prototype.executeAction = function(action) : 0) * (LiteGraph.NODE_WIDGET_HEIGHT + 4) + 4; - if (this.resizing_node.size[1] < min_height) + if (this.resizing_node.size[1] < min_height) { this.resizing_node.size[1] = min_height; - if (this.resizing_node.size[0] < LiteGraph.NODE_MIN_WIDTH) + } + if (this.resizing_node.size[0] < LiteGraph.NODE_MIN_WIDTH) { this.resizing_node.size[0] = LiteGraph.NODE_MIN_WIDTH; + } this.canvas.style.cursor = "se-resize"; this.dirty_canvas = true; @@ -4634,7 +5397,9 @@ LGraphNode.prototype.executeAction = function(action) * @method processMouseUp **/ LGraphCanvas.prototype.processMouseUp = function(e) { - if (!this.graph) return; + if (!this.graph) { + return; + } var window = this.getCanvasWindow(); var document = window.document; @@ -4676,7 +5441,9 @@ LGraphNode.prototype.executeAction = function(action) this.selected_group.pos[1] = Math.round( this.selected_group.pos[1] ); - if (this.selected_group._nodes.length) this.dirty_canvas = true; + if (this.selected_group._nodes.length) { + this.dirty_canvas = true; + } this.selected_group = null; } this.selected_group_resizing = false; @@ -4712,11 +5479,14 @@ LGraphNode.prototype.executeAction = function(action) this.dragging_rectangle, node_bounding ) - ) - continue; //out of the visible area + ) { + continue; + } //out of the visible area to_select.push(node); } - if (to_select.length) this.selectNodes(to_select); + if (to_select.length) { + this.selectNodes(to_select); + } } this.dragging_rectangle = null; } else if (this.connecting_node) { @@ -4758,24 +5528,27 @@ LGraphNode.prototype.executeAction = function(action) //not on top of an input var input = node.getInputInfo(0); //auto connect - if (this.connecting_output.type == LiteGraph.EVENT) + if ( + this.connecting_output.type == LiteGraph.EVENT + ) { this.connecting_node.connect( this.connecting_slot, node, LiteGraph.EVENT ); - else if ( + } else if ( input && !input.link && LiteGraph.isValidConnection( input.type && this.connecting_output.type ) - ) + ) { this.connecting_node.connect( this.connecting_slot, node, 0 ); + } } } } @@ -4803,15 +5576,17 @@ LGraphNode.prototype.executeAction = function(action) LiteGraph.NODE_TITLE_HEIGHT, LiteGraph.NODE_TITLE_HEIGHT ) - ) + ) { node.collapse(); + } this.dirty_canvas = true; this.dirty_bgcanvas = true; this.node_dragged.pos[0] = Math.round(this.node_dragged.pos[0]); this.node_dragged.pos[1] = Math.round(this.node_dragged.pos[1]); - if (this.graph.config.align_to_grid) + if (this.graph.config.align_to_grid) { this.node_dragged.alignToGrid(); + } this.node_dragged = null; } //no node being dragged else { @@ -4822,12 +5597,14 @@ LGraphNode.prototype.executeAction = function(action) this.visible_nodes ); - if (!node && e.click_time < 300) this.deselectAllNodes(); + if (!node && e.click_time < 300) { + this.deselectAllNodes(); + } this.dirty_canvas = true; this.dragging_canvas = false; - if (this.node_over && this.node_over.onMouseUp) + if (this.node_over && this.node_over.onMouseUp) { this.node_over.onMouseUp( e, [ @@ -4836,14 +5613,16 @@ LGraphNode.prototype.executeAction = function(action) ], this ); + } if ( this.node_capturing_input && this.node_capturing_input.onMouseUp - ) + ) { this.node_capturing_input.onMouseUp(e, [ e.canvasX - this.node_capturing_input.pos[0], e.canvasY - this.node_capturing_input.pos[1] ]); + } } } else if (e.which == 2) { //middle button @@ -4874,7 +5653,9 @@ LGraphNode.prototype.executeAction = function(action) * @method processMouseWheel **/ LGraphCanvas.prototype.processMouseWheel = function(e) { - if (!this.graph || !this.allow_dragcanvas) return; + if (!this.graph || !this.allow_dragcanvas) { + return; + } var delta = e.wheelDeltaY != null ? e.wheelDeltaY : e.detail * -60; @@ -4882,8 +5663,11 @@ LGraphNode.prototype.executeAction = function(action) var scale = this.ds.scale; - if (delta > 0) scale *= 1.1; - else if (delta < 0) scale *= 1 / 1.1; + if (delta > 0) { + scale *= 1.1; + } else if (delta < 0) { + scale *= 1 / 1.1; + } //this.setZoom( scale, [ e.localX, e.localY ] ); this.ds.changeScale(scale, [e.localX, e.localY]); @@ -4909,8 +5693,9 @@ LGraphNode.prototype.executeAction = function(action) title_height - 4, title_height - 4 ) - ) + ) { return true; + } return false; }; @@ -4924,12 +5709,12 @@ LGraphNode.prototype.executeAction = function(action) canvasy, slot_pos ) { - if (node.inputs) + if (node.inputs) { for (var i = 0, l = node.inputs.length; i < l; ++i) { var input = node.inputs[i]; var link_pos = node.getConnectionPos(true, i); var is_inside = false; - if (node.horizontal) + if (node.horizontal) { is_inside = isInsideRectangle( canvasx, canvasy, @@ -4938,7 +5723,7 @@ LGraphNode.prototype.executeAction = function(action) 10, 20 ); - else + } else { is_inside = isInsideRectangle( canvasx, canvasy, @@ -4947,6 +5732,7 @@ LGraphNode.prototype.executeAction = function(action) 40, 10 ); + } if (is_inside) { if (slot_pos) { slot_pos[0] = link_pos[0]; @@ -4955,6 +5741,7 @@ LGraphNode.prototype.executeAction = function(action) return i; } } + } return -1; }; @@ -4963,12 +5750,16 @@ LGraphNode.prototype.executeAction = function(action) * @method processKey **/ LGraphCanvas.prototype.processKey = function(e) { - if (!this.graph) return; + if (!this.graph) { + return; + } var block_default = false; //console.log(e); //debug - if (e.target.localName == "input") return; + if (e.target.localName == "input") { + return; + } if (e.type == "keydown") { if (e.keyCode == 32) { @@ -5011,17 +5802,25 @@ LGraphNode.prototype.executeAction = function(action) //... //TODO - if (this.selected_nodes) - for (var i in this.selected_nodes) - if (this.selected_nodes[i].onKeyDown) + if (this.selected_nodes) { + for (var i in this.selected_nodes) { + if (this.selected_nodes[i].onKeyDown) { this.selected_nodes[i].onKeyDown(e); + } + } + } } else if (e.type == "keyup") { - if (e.keyCode == 32) this.dragging_canvas = false; + if (e.keyCode == 32) { + this.dragging_canvas = false; + } - if (this.selected_nodes) - for (var i in this.selected_nodes) - if (this.selected_nodes[i].onKeyUp) + if (this.selected_nodes) { + for (var i in this.selected_nodes) { + if (this.selected_nodes[i].onKeyUp) { this.selected_nodes[i].onKeyUp(e); + } + } + } } this.graph.change(); @@ -5050,18 +5849,23 @@ LGraphNode.prototype.executeAction = function(action) for (var i = 0; i < selected_nodes_array.length; ++i) { var node = selected_nodes_array[i]; clipboard_info.nodes.push(node.clone().serialize()); - if (node.inputs && node.inputs.length) + if (node.inputs && node.inputs.length) { for (var j = 0; j < node.inputs.length; ++j) { var input = node.inputs[j]; - if (!input || input.link == null) continue; + if (!input || input.link == null) { + continue; + } var link_info = this.graph.links[input.link]; - if (!link_info) continue; + if (!link_info) { + continue; + } var target_node = this.graph.getNodeById( link_info.origin_id ); - if (!target_node || !this.selected_nodes[target_node.id]) + if (!target_node || !this.selected_nodes[target_node.id]) { //improve this by allowing connections to non-selected nodes - continue; //not selected + continue; + } //not selected clipboard_info.links.push([ target_node._relative_id, j, @@ -5069,6 +5873,7 @@ LGraphNode.prototype.executeAction = function(action) link_info.target_slot ]); } + } } localStorage.setItem( "litegrapheditor_clipboard", @@ -5078,7 +5883,9 @@ LGraphNode.prototype.executeAction = function(action) LGraphCanvas.prototype.pasteFromClipboard = function() { var data = localStorage.getItem("litegrapheditor_clipboard"); - if (!data) return; + if (!data) { + return; + } //create nodes var clipboard_info = JSON.parse(data); @@ -5119,8 +5926,12 @@ LGraphNode.prototype.executeAction = function(action) if (!node) { var r = null; - if (this.onDropItem) r = this.onDropItem(event); - if (!r) this.checkDropItem(e); + if (this.onDropItem) { + r = this.onDropItem(event); + } + if (!r) { + this.checkDropItem(e); + } return; } @@ -5133,7 +5944,9 @@ LGraphNode.prototype.executeAction = function(action) var ext = LGraphCanvas.getFileExtension(filename); //console.log(file); - if (node.onDropFile) node.onDropFile(file); + if (node.onDropFile) { + node.onDropFile(file); + } if (node.onDropData) { //prepare reader @@ -5146,20 +5959,27 @@ LGraphNode.prototype.executeAction = function(action) //read data var type = file.type.split("/")[0]; - if (type == "text" || type == "") + if (type == "text" || type == "") { reader.readAsText(file); - else if (type == "image") reader.readAsDataURL(file); - else reader.readAsArrayBuffer(file); + } else if (type == "image") { + reader.readAsDataURL(file); + } else { + reader.readAsArrayBuffer(file); + } } } } } if (node.onDropItem) { - if (node.onDropItem(event)) return true; + if (node.onDropItem(event)) { + return true; + } } - if (this.onDropItem) return this.onDropItem(event); + if (this.onDropItem) { + return this.onDropItem(event); + } return false; }; @@ -5174,27 +5994,37 @@ LGraphNode.prototype.executeAction = function(action) var node = LiteGraph.createNode(nodetype.type); node.pos = [e.canvasX, e.canvasY]; this.graph.add(node); - if (node.onDropFile) node.onDropFile(file); + if (node.onDropFile) { + node.onDropFile(file); + } } } }; LGraphCanvas.prototype.processNodeDblClicked = function(n) { - if (this.onShowNodePanel) this.onShowNodePanel(n); + if (this.onShowNodePanel) { + this.onShowNodePanel(n); + } - if (this.onNodeDblClicked) this.onNodeDblClicked(n); + if (this.onNodeDblClicked) { + this.onNodeDblClicked(n); + } this.setDirty(true); }; LGraphCanvas.prototype.processNodeSelected = function(node, e) { this.selectNode(node, e && e.shiftKey); - if (this.onNodeSelected) this.onNodeSelected(node); + if (this.onNodeSelected) { + this.onNodeSelected(node); + } }; LGraphCanvas.prototype.processNodeDeselected = function(node) { this.deselectNode(node); - if (this.onNodeDeselected) this.onNodeDeselected(node); + if (this.onNodeDeselected) { + this.onNodeDeselected(node); + } }; /** @@ -5205,8 +6035,11 @@ LGraphNode.prototype.executeAction = function(action) node, add_to_current_selection ) { - if (node == null) this.deselectAllNodes(); - else this.selectNodes([node], add_to_current_selection); + if (node == null) { + this.deselectAllNodes(); + } else { + this.selectNodes([node], add_to_current_selection); + } }; /** @@ -5217,27 +6050,38 @@ LGraphNode.prototype.executeAction = function(action) nodes, add_to_current_selection ) { - if (!add_to_current_selection) this.deselectAllNodes(); + if (!add_to_current_selection) { + this.deselectAllNodes(); + } nodes = nodes || this.graph._nodes; for (var i = 0; i < nodes.length; ++i) { var node = nodes[i]; - if (node.is_selected) continue; + if (node.is_selected) { + continue; + } - if (!node.is_selected && node.onSelected) node.onSelected(); + if (!node.is_selected && node.onSelected) { + node.onSelected(); + } node.is_selected = true; this.selected_nodes[node.id] = node; - if (node.inputs) - for (var j = 0; j < node.inputs.length; ++j) + if (node.inputs) { + for (var j = 0; j < node.inputs.length; ++j) { this.highlighted_links[node.inputs[j].link] = true; - if (node.outputs) + } + } + if (node.outputs) { for (var j = 0; j < node.outputs.length; ++j) { var out = node.outputs[j]; - if (out.links) - for (var k = 0; k < out.links.length; ++k) + if (out.links) { + for (var k = 0; k < out.links.length; ++k) { this.highlighted_links[out.links[k]] = true; + } + } } + } } this.setDirty(true); @@ -5248,21 +6092,30 @@ LGraphNode.prototype.executeAction = function(action) * @method deselectNode **/ LGraphCanvas.prototype.deselectNode = function(node) { - if (!node.is_selected) return; - if (node.onDeselected) node.onDeselected(); + if (!node.is_selected) { + return; + } + if (node.onDeselected) { + node.onDeselected(); + } node.is_selected = false; //remove highlighted - if (node.inputs) - for (var i = 0; i < node.inputs.length; ++i) + if (node.inputs) { + for (var i = 0; i < node.inputs.length; ++i) { delete this.highlighted_links[node.inputs[i].link]; - if (node.outputs) + } + } + if (node.outputs) { for (var i = 0; i < node.outputs.length; ++i) { var out = node.outputs[i]; - if (out.links) - for (var j = 0; j < out.links.length; ++j) + if (out.links) { + for (var j = 0; j < out.links.length; ++j) { delete this.highlighted_links[out.links[j]]; + } + } } + } }; /** @@ -5270,12 +6123,18 @@ LGraphNode.prototype.executeAction = function(action) * @method deselectAllNodes **/ LGraphCanvas.prototype.deselectAllNodes = function() { - if (!this.graph) return; + if (!this.graph) { + return; + } var nodes = this.graph._nodes; for (var i = 0, l = nodes.length; i < l; ++i) { var node = nodes[i]; - if (!node.is_selected) continue; - if (node.onDeselected) node.onDeselected(); + if (!node.is_selected) { + continue; + } + if (node.onDeselected) { + node.onDeselected(); + } node.is_selected = false; } this.selected_nodes = {}; @@ -5401,7 +6260,9 @@ LGraphNode.prototype.executeAction = function(action) **/ LGraphCanvas.prototype.bringToFront = function(node) { var i = this.graph._nodes.indexOf(node); - if (i == -1) return; + if (i == -1) { + return; + } this.graph._nodes.splice(i, 1); this.graph._nodes.push(node); @@ -5413,7 +6274,9 @@ LGraphNode.prototype.executeAction = function(action) **/ LGraphCanvas.prototype.sendToBack = function(node) { var i = this.graph._nodes.indexOf(node); - if (i == -1) return; + if (i == -1) { + return; + } this.graph._nodes.splice(i, 1); this.graph._nodes.unshift(node); @@ -5436,11 +6299,13 @@ LGraphNode.prototype.executeAction = function(action) var n = nodes[i]; //skip rendering nodes in live mode - if (this.live_mode && !n.onDrawBackground && !n.onDrawForeground) + if (this.live_mode && !n.onDrawBackground && !n.onDrawForeground) { continue; + } - if (!overlapBounding(this.visible_area, n.getBounding(temp))) - continue; //out of the visible area + if (!overlapBounding(this.visible_area, n.getBounding(temp))) { + continue; + } //out of the visible area visible_nodes.push(n); } @@ -5452,14 +6317,18 @@ LGraphNode.prototype.executeAction = function(action) * @method draw **/ LGraphCanvas.prototype.draw = function(force_canvas, force_bgcanvas) { - if (!this.canvas) return; + if (!this.canvas) { + return; + } //fps counting var now = LiteGraph.getTime(); this.render_time = (now - this.last_draw_time) * 0.001; this.last_draw_time = now; - if (this.graph) this.ds.computeVisibleArea(); + if (this.graph) { + this.ds.computeVisibleArea(); + } if ( this.dirty_bgcanvas || @@ -5468,10 +6337,13 @@ LGraphNode.prototype.executeAction = function(action) (this.graph && this.graph._last_trigger_time && now - this.graph._last_trigger_time < 1000) - ) + ) { this.drawBackCanvas(); + } - if (this.dirty_canvas || force_canvas) this.drawFrontCanvas(); + if (this.dirty_canvas || force_canvas) { + this.drawFrontCanvas(); + } this.fps = this.render_time ? 1.0 / this.render_time : 0; this.frame += 1; @@ -5484,13 +6356,18 @@ LGraphNode.prototype.executeAction = function(action) LGraphCanvas.prototype.drawFrontCanvas = function() { this.dirty_canvas = false; - if (!this.ctx) this.ctx = this.bgcanvas.getContext("2d"); + if (!this.ctx) { + this.ctx = this.bgcanvas.getContext("2d"); + } var ctx = this.ctx; - if (!ctx) + if (!ctx) { //maybe is using webgl... return; + } - if (ctx.start2D) ctx.start2D(); + if (ctx.start2D) { + ctx.start2D(); + } var canvas = this.canvas; @@ -5513,18 +6390,26 @@ LGraphNode.prototype.executeAction = function(action) //clear //canvas.width = canvas.width; - if (this.clear_background) + if (this.clear_background) { ctx.clearRect(0, 0, canvas.width, canvas.height); + } //draw bg canvas - if (this.bgcanvas == this.canvas) this.drawBackCanvas(); - else ctx.drawImage(this.bgcanvas, 0, 0); + if (this.bgcanvas == this.canvas) { + this.drawBackCanvas(); + } else { + ctx.drawImage(this.bgcanvas, 0, 0); + } //rendering - if (this.onRender) this.onRender(canvas, ctx); + if (this.onRender) { + this.onRender(canvas, ctx); + } //info widget - if (this.show_info) this.renderInfo(ctx); + if (this.show_info) { + this.renderInfo(ctx); + } if (this.graph) { //apply transformations @@ -5554,11 +6439,16 @@ LGraphNode.prototype.executeAction = function(action) } //on top (debug) - if (this.render_execution_order) this.drawExecutionOrder(ctx); + if (this.render_execution_order) { + this.drawExecutionOrder(ctx); + } //connections ontop? - if (this.graph.config.links_ontop) - if (!this.live_mode) this.drawConnections(ctx); + if (this.graph.config.links_ontop) { + if (!this.live_mode) { + this.drawConnections(ctx); + } + } //current connection (the one being dragged by the mouse) if (this.connecting_pos != null) { @@ -5593,14 +6483,14 @@ LGraphNode.prototype.executeAction = function(action) if ( this.connecting_output.type === LiteGraph.EVENT || this.connecting_output.shape === LiteGraph.BOX_SHAPE - ) + ) { ctx.rect( this.connecting_pos[0] - 6 + 0.5, this.connecting_pos[1] - 5 + 0.5, 14, 10 ); - else + } else { ctx.arc( this.connecting_pos[0], this.connecting_pos[1], @@ -5608,6 +6498,7 @@ LGraphNode.prototype.executeAction = function(action) 0, Math.PI * 2 ); + } ctx.fill(); ctx.fillStyle = "#ffcc00"; @@ -5634,22 +6525,26 @@ LGraphNode.prototype.executeAction = function(action) ); } - if (this.onDrawForeground) + if (this.onDrawForeground) { this.onDrawForeground(ctx, this.visible_rect); + } ctx.restore(); } - if (this.onDrawOverlay) this.onDrawOverlay(ctx); + if (this.onDrawOverlay) { + this.onDrawOverlay(ctx); + } if (this.dirty_area) { ctx.restore(); //this.dirty_area = null; } - if (ctx.finish2D) + if (ctx.finish2D) { //this is a function I use in webgl renderer ctx.finish2D(); + } }; /** @@ -5683,7 +6578,9 @@ LGraphNode.prototype.executeAction = function(action) ); ctx.fillText("V: " + this.graph._version, 5, 13 * 4); ctx.fillText("FPS:" + this.fps.toFixed(2), 5, 13 * 5); - } else ctx.fillText("No graph selected", 5, 13 * 1); + } else { + ctx.fillText("No graph selected", 5, 13 * 1); + } ctx.restore(); }; @@ -5701,13 +6598,18 @@ LGraphNode.prototype.executeAction = function(action) canvas.height = this.canvas.height; } - if (!this.bgctx) this.bgctx = this.bgcanvas.getContext("2d"); + if (!this.bgctx) { + this.bgctx = this.bgcanvas.getContext("2d"); + } var ctx = this.bgctx; - if (ctx.start) ctx.start(); + if (ctx.start) { + ctx.start(); + } //clear - if (this.clear_background) + if (this.clear_background) { ctx.clearRect(0, 0, canvas.width, canvas.height); + } if (this._graph_stack && this._graph_stack.length) { ctx.save(); @@ -5721,9 +6623,10 @@ LGraphNode.prototype.executeAction = function(action) ctx.textAlign = "center"; ctx.fillStyle = subgraph_node.bgcolor || "#AAA"; var title = ""; - for (var i = 1; i < this._graph_stack.length; ++i) + for (var i = 1; i < this._graph_stack.length; ++i) { title += this._graph_stack[i]._subgraph_node.getTitle() + " >> "; + } ctx.fillText( title + subgraph_node.getTitle(), canvas.width * 0.5, @@ -5733,8 +6636,9 @@ LGraphNode.prototype.executeAction = function(action) } var bg_already_painted = false; - if (this.onRenderBackground) + if (this.onRenderBackground) { bg_already_painted = this.onRenderBackground(canvas, ctx); + } //reset in case of error ctx.restore(); @@ -5752,10 +6656,12 @@ LGraphNode.prototype.executeAction = function(action) this.ds.scale > 0.5 && !bg_already_painted ) { - if (this.zoom_modify_alpha) + if (this.zoom_modify_alpha) { ctx.globalAlpha = (1.0 - 0.5 / this.ds.scale) * this.editor_alpha; - else ctx.globalAlpha = this.editor_alpha; + } else { + ctx.globalAlpha = this.editor_alpha; + } ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = false; if ( !this._bg_img || @@ -5775,7 +6681,9 @@ LGraphNode.prototype.executeAction = function(action) pattern = ctx.createPattern(this._bg_img, "repeat"); this._pattern_img = this._bg_img; this._pattern = pattern; - } else pattern = this._pattern; + } else { + pattern = this._pattern; + } if (pattern) { ctx.fillStyle = pattern; ctx.fillRect( @@ -5792,11 +6700,13 @@ LGraphNode.prototype.executeAction = function(action) } //groups - if (this.graph._groups.length && !this.live_mode) + if (this.graph._groups.length && !this.live_mode) { this.drawGroups(canvas, ctx); + } - if (this.onDrawBackground) + if (this.onDrawBackground) { this.onDrawBackground(ctx, this.visible_area); + } if (this.onBackgroundRender) { //LEGACY console.error( @@ -5820,10 +6730,14 @@ LGraphNode.prototype.executeAction = function(action) ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.shadowBlur = 6; - } else ctx.shadowColor = "rgba(0,0,0,0)"; + } else { + ctx.shadowColor = "rgba(0,0,0,0)"; + } //draw connections - if (!this.live_mode) this.drawConnections(ctx); + if (!this.live_mode) { + this.drawConnections(ctx); + } ctx.shadowColor = "rgba(0,0,0,0)"; @@ -5831,7 +6745,9 @@ LGraphNode.prototype.executeAction = function(action) ctx.restore(); } - if (ctx.finish) ctx.finish(); + if (ctx.finish) { + ctx.finish(); + } this.dirty_bgcanvas = false; this.dirty_canvas = true; //to force to repaint the front canvas with the bgcanvas @@ -5857,14 +6773,17 @@ LGraphNode.prototype.executeAction = function(action) LiteGraph.NODE_DEFAULT_BGCOLOR; //shadow and glow - if (node.mouseOver) glow = true; + if (node.mouseOver) { + glow = true; + } //only render if it forces it to do it if (this.live_mode) { if (!node.flags.collapsed) { ctx.shadowColor = "transparent"; - if (node.onDrawForeground) + if (node.onDrawForeground) { node.onDrawForeground(ctx, this, this.canvas); + } } return; } @@ -5877,15 +6796,18 @@ LGraphNode.prototype.executeAction = function(action) ctx.shadowOffsetX = 2 * this.ds.scale; ctx.shadowOffsetY = 2 * this.ds.scale; ctx.shadowBlur = 3 * this.ds.scale; - } else ctx.shadowColor = "transparent"; + } else { + ctx.shadowColor = "transparent"; + } //custom draw collapsed method (draw after shadows because they are affected) if ( node.flags.collapsed && node.onDrawCollapsed && node.onDrawCollapsed(ctx, this) == true - ) + ) { return; + } //clip if required (mask) var shape = node._shape || LiteGraph.BOX_SHAPE; @@ -5911,10 +6833,11 @@ LGraphNode.prototype.executeAction = function(action) //Start clipping ctx.save(); ctx.beginPath(); - if (shape == LiteGraph.BOX_SHAPE) ctx.rect(0, 0, size[0], size[1]); - else if (shape == LiteGraph.ROUND_SHAPE) + if (shape == LiteGraph.BOX_SHAPE) { + ctx.rect(0, 0, size[0], size[1]); + } else if (shape == LiteGraph.ROUND_SHAPE) { ctx.roundRect(0, 0, size[0], size[1], 10); - else if (shape == LiteGraph.CIRCLE_SHAPE) + } else if (shape == LiteGraph.CIRCLE_SHAPE) { ctx.arc( size[0] * 0.5, size[1] * 0.5, @@ -5922,11 +6845,14 @@ LGraphNode.prototype.executeAction = function(action) 0, Math.PI * 2 ); + } ctx.clip(); } //draw shape - if (node.has_errors) bgcolor = "red"; + if (node.has_errors) { + bgcolor = "red"; + } this.drawNodeShape( node, ctx, @@ -5939,8 +6865,9 @@ LGraphNode.prototype.executeAction = function(action) ctx.shadowColor = "transparent"; //draw foreground - if (node.onDrawForeground) + if (node.onDrawForeground) { node.onDrawForeground(ctx, this, this.canvas); + } //connection slots ctx.textAlign = horizontal ? "center" : "left"; @@ -5957,7 +6884,7 @@ LGraphNode.prototype.executeAction = function(action) //render inputs and outputs if (!node.flags.collapsed) { //input connection slots - if (node.inputs) + if (node.inputs) { for (var i = 0; i < node.inputs.length; i++) { var slot = node.inputs[i]; @@ -5966,8 +6893,9 @@ LGraphNode.prototype.executeAction = function(action) if ( this.connecting_node && LiteGraph.isValidConnection(slot.type && out_slot.type) - ) + ) { ctx.globalAlpha = 0.4 * editor_alpha; + } ctx.fillStyle = slot.link != null @@ -5979,8 +6907,9 @@ LGraphNode.prototype.executeAction = function(action) var pos = node.getConnectionPos(true, i, slot_pos); pos[0] -= node.pos[0]; pos[1] -= node.pos[1]; - if (max_y < pos[1] + LiteGraph.NODE_SLOT_HEIGHT * 0.5) + if (max_y < pos[1] + LiteGraph.NODE_SLOT_HEIGHT * 0.5) { max_y = pos[1] + LiteGraph.NODE_SLOT_HEIGHT * 0.5; + } ctx.beginPath(); @@ -5988,20 +6917,21 @@ LGraphNode.prototype.executeAction = function(action) slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE ) { - if (horizontal) + if (horizontal) { ctx.rect( pos[0] - 5 + 0.5, pos[1] - 8 + 0.5, 10, 14 ); - else + } else { ctx.rect( pos[0] - 6 + 0.5, pos[1] - 5 + 0.5, 14, 10 ); + } } else if (slot.shape === LiteGraph.ARROW_SHAPE) { ctx.moveTo(pos[0] + 8, pos[1] + 0.5); ctx.lineTo(pos[0] - 4, pos[1] + 6 + 0.5); @@ -6018,27 +6948,33 @@ LGraphNode.prototype.executeAction = function(action) var text = slot.label != null ? slot.label : slot.name; if (text) { ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR; - if (horizontal || slot.dir == LiteGraph.UP) + if (horizontal || slot.dir == LiteGraph.UP) { ctx.fillText(text, pos[0], pos[1] - 10); - else ctx.fillText(text, pos[0] + 10, pos[1] + 5); + } else { + ctx.fillText(text, pos[0] + 10, pos[1] + 5); + } } } } + } //output connection slots - if (this.connecting_node) ctx.globalAlpha = 0.4 * editor_alpha; + if (this.connecting_node) { + ctx.globalAlpha = 0.4 * editor_alpha; + } ctx.textAlign = horizontal ? "center" : "right"; ctx.strokeStyle = "black"; - if (node.outputs) + if (node.outputs) { for (var i = 0; i < node.outputs.length; i++) { var slot = node.outputs[i]; var pos = node.getConnectionPos(false, i, slot_pos); pos[0] -= node.pos[0]; pos[1] -= node.pos[1]; - if (max_y < pos[1] + LiteGraph.NODE_SLOT_HEIGHT * 0.5) + if (max_y < pos[1] + LiteGraph.NODE_SLOT_HEIGHT * 0.5) { max_y = pos[1] + LiteGraph.NODE_SLOT_HEIGHT * 0.5; + } ctx.fillStyle = slot.links && slot.links.length @@ -6053,20 +6989,21 @@ LGraphNode.prototype.executeAction = function(action) slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE ) { - if (horizontal) + if (horizontal) { ctx.rect( pos[0] - 5 + 0.5, pos[1] - 8 + 0.5, 10, 14 ); - else + } else { ctx.rect( pos[0] - 6 + 0.5, pos[1] - 5 + 0.5, 14, 10 ); + } } else if (slot.shape === LiteGraph.ARROW_SHAPE) { ctx.moveTo(pos[0] + 8, pos[1] + 0.5); ctx.lineTo(pos[0] - 4, pos[1] + 6 + 0.5); @@ -6089,18 +7026,23 @@ LGraphNode.prototype.executeAction = function(action) var text = slot.label != null ? slot.label : slot.name; if (text) { ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR; - if (horizontal || slot.dir == LiteGraph.DOWN) + if (horizontal || slot.dir == LiteGraph.DOWN) { ctx.fillText(text, pos[0], pos[1] - 8); - else ctx.fillText(text, pos[0] - 10, pos[1] + 5); + } else { + ctx.fillText(text, pos[0] - 10, pos[1] + 5); + } } } } + } ctx.textAlign = "left"; ctx.globalAlpha = 1; if (node.widgets) { - if (horizontal || node.widgets_up) max_y = 2; + if (horizontal || node.widgets_up) { + max_y = 2; + } this.drawNodeWidgets( node, max_y, @@ -6119,7 +7061,9 @@ LGraphNode.prototype.executeAction = function(action) if (node.inputs) { for (var i = 0; i < node.inputs.length; i++) { var slot = node.inputs[i]; - if (slot.link == null) continue; + if (slot.link == null) { + continue; + } input_slot = slot; break; } @@ -6127,7 +7071,9 @@ LGraphNode.prototype.executeAction = function(action) if (node.outputs) { for (var i = 0; i < node.outputs.length; i++) { var slot = node.outputs[i]; - if (!slot.links || !slot.links.length) continue; + if (!slot.links || !slot.links.length) { + continue; + } output_slot = slot; } } @@ -6185,7 +7131,9 @@ LGraphNode.prototype.executeAction = function(action) } } - if (node.clip_area) ctx.restore(); + if (node.clip_area) { + ctx.restore(); + } ctx.globalAlpha = 1.0; }; @@ -6219,9 +7167,11 @@ LGraphNode.prototype.executeAction = function(action) var title_mode = node.constructor.title_mode; var render_title = true; - if (title_mode == LiteGraph.TRANSPARENT_TITLE) render_title = false; - else if (title_mode == LiteGraph.AUTOHIDE_TITLE && mouse_over) + if (title_mode == LiteGraph.TRANSPARENT_TITLE) { + render_title = false; + } else if (title_mode == LiteGraph.AUTOHIDE_TITLE && mouse_over) { render_title = true; + } var area = tmp_area; area[0] = 0; //x @@ -6235,12 +7185,12 @@ LGraphNode.prototype.executeAction = function(action) //if(node.flags.collapsed) { ctx.beginPath(); - if (shape == LiteGraph.BOX_SHAPE || low_quality) + if (shape == LiteGraph.BOX_SHAPE || low_quality) { ctx.fillRect(area[0], area[1], area[2], area[3]); - else if ( + } else if ( shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CARD_SHAPE - ) + ) { ctx.roundRect( area[0], area[1], @@ -6249,7 +7199,7 @@ LGraphNode.prototype.executeAction = function(action) this.round_radius, shape == LiteGraph.CARD_SHAPE ? 0 : this.round_radius ); - else if (shape == LiteGraph.CIRCLE_SHAPE) + } else if (shape == LiteGraph.CIRCLE_SHAPE) { ctx.arc( size[0] * 0.5, size[1] * 0.5, @@ -6257,6 +7207,7 @@ LGraphNode.prototype.executeAction = function(action) 0, Math.PI * 2 ); + } ctx.fill(); ctx.shadowColor = "transparent"; @@ -6265,8 +7216,9 @@ LGraphNode.prototype.executeAction = function(action) } ctx.shadowColor = "transparent"; - if (node.onDrawBackground) + if (node.onDrawBackground) { node.onDrawBackground(ctx, this, this.canvas); + } //title bg (remember, it is rendered ABOVE the node) if (render_title || title_mode == LiteGraph.TRANSPARENT_TITLE) { @@ -6285,8 +7237,9 @@ LGraphNode.prototype.executeAction = function(action) ) { var title_color = node.constructor.title_color || fgcolor; - if (node.flags.collapsed) + if (node.flags.collapsed) { ctx.shadowColor = LiteGraph.DEFAULT_SHADOW_COLOR; + } //* gradient test if (this.use_gradients) { @@ -6299,16 +7252,18 @@ LGraphNode.prototype.executeAction = function(action) grad.addColorStop(1, "#000"); } ctx.fillStyle = grad; - } else ctx.fillStyle = title_color; + } else { + ctx.fillStyle = title_color; + } //ctx.globalAlpha = 0.5 * old_alpha; ctx.beginPath(); - if (shape == LiteGraph.BOX_SHAPE || low_quality) + if (shape == LiteGraph.BOX_SHAPE || low_quality) { ctx.rect(0, -title_height, size[0] + 1, title_height); - else if ( + } else if ( shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CARD_SHAPE - ) + ) { ctx.roundRect( 0, -title_height, @@ -6317,6 +7272,7 @@ LGraphNode.prototype.executeAction = function(action) this.round_radius, node.flags.collapsed ? this.round_radius : 0 ); + } ctx.fill(); ctx.shadowColor = "transparent"; } @@ -6390,11 +7346,13 @@ LGraphNode.prototype.executeAction = function(action) ctx.font = this.title_text_font; var title = node.getTitle(); if (title) { - if (selected) ctx.fillStyle = "white"; - else + if (selected) { + ctx.fillStyle = "white"; + } else { ctx.fillStyle = node.constructor.title_text_color || this.node_title_color; + } if (node.flags.collapsed) { ctx.textAlign = "center"; var measure = ctx.measureText(title); @@ -6415,12 +7373,16 @@ LGraphNode.prototype.executeAction = function(action) } } - if (node.onDrawTitle) node.onDrawTitle(ctx); + if (node.onDrawTitle) { + node.onDrawTitle(ctx); + } } //render selection marker if (selected) { - if (node.onBounding) node.onBounding(area); + if (node.onBounding) { + node.onBounding(area); + } if (title_mode == LiteGraph.TRANSPARENT_TITLE) { area[1] -= title_height; @@ -6429,17 +7391,17 @@ LGraphNode.prototype.executeAction = function(action) ctx.lineWidth = 1; ctx.globalAlpha = 0.8; ctx.beginPath(); - if (shape == LiteGraph.BOX_SHAPE) + if (shape == LiteGraph.BOX_SHAPE) { ctx.rect( -6 + area[0], -6 + area[1], 12 + area[2], 12 + area[3] ); - else if ( + } else if ( shape == LiteGraph.ROUND_SHAPE || (shape == LiteGraph.CARD_SHAPE && node.flags.collapsed) - ) + ) { ctx.roundRect( -6 + area[0], -6 + area[1], @@ -6447,7 +7409,7 @@ LGraphNode.prototype.executeAction = function(action) 12 + area[3], this.round_radius * 2 ); - else if (shape == LiteGraph.CARD_SHAPE) + } else if (shape == LiteGraph.CARD_SHAPE) { ctx.roundRect( -6 + area[0], -6 + area[1], @@ -6456,7 +7418,7 @@ LGraphNode.prototype.executeAction = function(action) this.round_radius * 2, 2 ); - else if (shape == LiteGraph.CIRCLE_SHAPE) + } else if (shape == LiteGraph.CIRCLE_SHAPE) { ctx.arc( size[0] * 0.5, size[1] * 0.5, @@ -6464,6 +7426,7 @@ LGraphNode.prototype.executeAction = function(action) 0, Math.PI * 2 ); + } ctx.strokeStyle = "#FFF"; ctx.stroke(); ctx.strokeStyle = fgcolor; @@ -6500,31 +7463,40 @@ LGraphNode.prototype.executeAction = function(action) for (var n = 0, l = nodes.length; n < l; ++n) { var node = nodes[n]; //for every input (we render just inputs because it is easier as every slot can only have one input) - if (!node.inputs || !node.inputs.length) continue; + if (!node.inputs || !node.inputs.length) { + continue; + } for (var i = 0; i < node.inputs.length; ++i) { var input = node.inputs[i]; - if (!input || input.link == null) continue; + if (!input || input.link == null) { + continue; + } var link_id = input.link; var link = this.graph.links[link_id]; - if (!link) continue; + if (!link) { + continue; + } //find link info var start_node = this.graph.getNodeById(link.origin_id); - if (start_node == null) continue; + if (start_node == null) { + continue; + } var start_node_slot = link.origin_slot; var start_node_slotpos = null; - if (start_node_slot == -1) + if (start_node_slot == -1) { start_node_slotpos = [ start_node.pos[0] + 10, start_node.pos[1] + 10 ]; - else + } else { start_node_slotpos = start_node.getConnectionPos( false, start_node_slot, tempA ); + } var end_node_slotpos = node.getConnectionPos(true, i, tempB); //compute link bounding @@ -6542,11 +7514,15 @@ LGraphNode.prototype.executeAction = function(action) } //skip links outside of the visible area of the canvas - if (!overlapBounding(link_bounding, margin_area)) continue; + if (!overlapBounding(link_bounding, margin_area)) { + continue; + } var start_slot = start_node.outputs[start_node_slot]; var end_slot = node.inputs[i]; - if (!start_slot || !end_slot) continue; + if (!start_slot || !end_slot) { + continue; + } var start_dir = start_slot.dir || (start_node.horizontal ? LiteGraph.DOWN : LiteGraph.RIGHT); @@ -6614,24 +7590,34 @@ LGraphNode.prototype.executeAction = function(action) end_dir, num_sublines ) { - if (link) this.visible_links.push(link); + if (link) { + this.visible_links.push(link); + } //choose color - if (!color && link) + if (!color && link) { color = link.color || LGraphCanvas.link_type_colors[link.type]; - if (!color) color = this.default_link_color; - if (link != null && this.highlighted_links[link.id]) color = "#FFF"; + } + if (!color) { + color = this.default_link_color; + } + if (link != null && this.highlighted_links[link.id]) { + color = "#FFF"; + } start_dir = start_dir || LiteGraph.RIGHT; end_dir = end_dir || LiteGraph.LEFT; var dist = distance(a, b); - if (this.render_connections_border && this.ds.scale > 0.6) + if (this.render_connections_border && this.ds.scale > 0.6) { ctx.lineWidth = this.connections_width + 4; + } ctx.lineJoin = "round"; num_sublines = num_sublines || 1; - if (num_sublines > 1) ctx.lineWidth = 0.5; + if (num_sublines > 1) { + ctx.lineWidth = 0.5; + } //begin line shape ctx.beginPath(); @@ -6730,16 +7716,24 @@ LGraphNode.prototype.executeAction = function(action) var start_y = a[1]; var end_x = b[0]; var end_y = b[1]; - if (start_dir == LiteGraph.RIGHT) start_x += 10; - else start_y += 10; - if (end_dir == LiteGraph.LEFT) end_x -= 10; - else end_y -= 10; + if (start_dir == LiteGraph.RIGHT) { + start_x += 10; + } else { + start_y += 10; + } + if (end_dir == LiteGraph.LEFT) { + end_x -= 10; + } else { + end_y -= 10; + } ctx.lineTo(start_x, start_y); ctx.lineTo((start_x + end_x) * 0.5, start_y); ctx.lineTo((start_x + end_x) * 0.5, end_y); ctx.lineTo(end_x, end_y); ctx.lineTo(b[0], b[1]); - } else return; //unknown + } else { + return; + } //unknown } //rendering the outline of the connection can be a little bit slow @@ -6807,7 +7801,9 @@ LGraphNode.prototype.executeAction = function(action) if (this.render_curved_connections) { angleA = -Math.atan2(posB[0] - posA[0], posB[1] - posA[1]); angleB = -Math.atan2(posD[0] - posC[0], posD[1] - posC[1]); - } else angleB = angleA = b[1] > a[1] ? 0 : Math.PI; + } else { + angleB = angleA = b[1] > a[1] ? 0 : Math.PI; + } //render arrow ctx.save(); @@ -6929,13 +7925,14 @@ LGraphNode.prototype.executeAction = function(action) LiteGraph.NODE_TITLE_HEIGHT, LiteGraph.NODE_TITLE_HEIGHT ); - if (node.order == 0) + if (node.order == 0) { ctx.strokeRect( node.pos[0] - LiteGraph.NODE_TITLE_HEIGHT + 0.5, node.pos[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5, LiteGraph.NODE_TITLE_HEIGHT, LiteGraph.NODE_TITLE_HEIGHT ); + } ctx.fillStyle = "#FFF"; ctx.fillText( node.order, @@ -6956,7 +7953,9 @@ LGraphNode.prototype.executeAction = function(action) ctx, active_widget ) { - if (!node.widgets || !node.widgets.length) return 0; + if (!node.widgets || !node.widgets.length) { + return 0; + } var width = node.size[0]; var widgets = node.widgets; posY += 2; @@ -6971,7 +7970,9 @@ LGraphNode.prototype.executeAction = function(action) for (var i = 0; i < widgets.length; ++i) { var w = widgets[i]; var y = posY; - if (w.y) y = w.y; + if (w.y) { + y = w.y; + } w.last_y = y; ctx.strokeStyle = outline_color; ctx.fillStyle = "#222"; @@ -7012,8 +8013,9 @@ LGraphNode.prototype.executeAction = function(action) ctx.fill(); if (show_text) { ctx.fillStyle = "#999"; - if (w.name != null) + if (w.name != null) { ctx.fillText(w.name, margin * 2, y + H * 0.7); + } ctx.fillStyle = w.value ? "#DDD" : "#888"; ctx.textAlign = "right"; ctx.fillText( @@ -7076,7 +8078,7 @@ LGraphNode.prototype.executeAction = function(action) ctx.fillText(w.name, margin * 2 + 5, y + H * 0.7); ctx.fillStyle = "#DDD"; ctx.textAlign = "right"; - if (w.type == "number") + if (w.type == "number") { ctx.fillText( Number(w.value).toFixed( w.options.precision !== undefined @@ -7086,12 +8088,13 @@ LGraphNode.prototype.executeAction = function(action) width - margin * 2 - 20, y + H * 0.7 ); - else + } else { ctx.fillText( w.value, width - margin * 2 - 20, y + H * 0.7 ); + } } break; case "string": @@ -7105,15 +8108,18 @@ LGraphNode.prototype.executeAction = function(action) ctx.stroke(); if (show_text) { ctx.fillStyle = "#999"; - if (w.name != null) + if (w.name != null) { ctx.fillText(w.name, margin * 2, y + H * 0.7); + } ctx.fillStyle = "#DDD"; ctx.textAlign = "right"; ctx.fillText(w.value, width - margin * 2, y + H * 0.7); } break; default: - if (w.draw) w.draw(ctx, node, w, y, H); + if (w.draw) { + w.draw(ctx, node, w, y, H); + } break; } posY += H + 4; @@ -7131,7 +8137,9 @@ LGraphNode.prototype.executeAction = function(action) event, active_widget ) { - if (!node.widgets || !node.widgets.length) return null; + if (!node.widgets || !node.widgets.length) { + return null; + } var x = pos[0] - node.pos[0]; var y = pos[1] - node.pos[1]; @@ -7154,10 +8162,11 @@ LGraphNode.prototype.executeAction = function(action) if (event.type === "mousemove") { break; } - if (w.callback) + if (w.callback) { setTimeout(function() { w.callback(w, that, node, pos); }, 20); + } w.clicked = true; this.dirty_canvas = true; break; @@ -7167,10 +8176,11 @@ LGraphNode.prototype.executeAction = function(action) w.value = w.options.min + (w.options.max - w.options.min) * nvalue; - if (w.callback) + if (w.callback) { setTimeout(function() { inner_value_change(w, w.value); }, 20); + } this.dirty_canvas = true; break; case "number": @@ -7181,17 +8191,20 @@ LGraphNode.prototype.executeAction = function(action) if ( w.options.min != null && w.value < w.options.min - ) + ) { w.value = w.options.min; + } if ( w.options.max != null && w.value > w.options.max - ) + ) { w.value = w.options.max; + } } else if (event.type == "mousedown") { var values = w.options.values; - if (values && values.constructor === Function) + if (values && values.constructor === Function) { values = w.options.values(w, node); + } var delta = x < 40 ? -1 : x > width - 40 ? 1 : 0; if (w.type == "number") { @@ -7199,17 +8212,23 @@ LGraphNode.prototype.executeAction = function(action) if ( w.options.min != null && w.value < w.options.min - ) + ) { w.value = w.options.min; + } if ( w.options.max != null && w.value > w.options.max - ) + ) { w.value = w.options.max; + } } else if (delta) { var index = values.indexOf(w.value) + delta; - if (index >= values.length) index = 0; - if (index < 0) index = values.length - 1; + if (index >= values.length) { + index = 0; + } + if (index < 0) { + index = values.length - 1; + } w.value = values[index]; } else { var menu = new LiteGraph.ContextMenu( @@ -7241,15 +8260,16 @@ LGraphNode.prototype.executeAction = function(action) case "toggle": if (event.type == "mousedown") { w.value = !w.value; - if (w.callback) + if (w.callback) { setTimeout(function() { inner_value_change(w, w.value); }, 20); + } } break; case "string": case "text": - if (event.type == "mousedown") + if (event.type == "mousedown") { this.prompt( "Value", w.value, @@ -7259,9 +8279,12 @@ LGraphNode.prototype.executeAction = function(action) }.bind(w), event ); + } break; default: - if (w.mouse) w.mouse(ctx, event, [x, y], node); + if (w.mouse) { + w.mouse(ctx, event, [x, y], node); + } break; } @@ -7274,10 +8297,12 @@ LGraphNode.prototype.executeAction = function(action) if ( widget.property && node.properties[widget.property] !== undefined - ) + ) { node.properties[widget.property] = value; - if (widget.callback) + } + if (widget.callback) { widget.callback(widget.value, that, node, pos, event); + } } return null; @@ -7288,7 +8313,9 @@ LGraphNode.prototype.executeAction = function(action) * @method drawGroups **/ LGraphCanvas.prototype.drawGroups = function(canvas, ctx) { - if (!this.graph) return; + if (!this.graph) { + return; + } var groups = this.graph._groups; @@ -7298,7 +8325,9 @@ LGraphNode.prototype.executeAction = function(action) for (var i = 0; i < groups.length; ++i) { var group = groups[i]; - if (!overlapBounding(this.visible_area, group._bounding)) continue; //out of the visible area + if (!overlapBounding(this.visible_area, group._bounding)) { + continue; + } //out of the visible area ctx.fillStyle = group.color || "#335"; ctx.strokeStyle = group.color || "#335"; @@ -7328,8 +8357,9 @@ LGraphNode.prototype.executeAction = function(action) LGraphCanvas.prototype.adjustNodesSize = function() { var nodes = this.graph._nodes; - for (var i = 0; i < nodes.length; ++i) + for (var i = 0; i < nodes.length; ++i) { nodes[i].size = nodes[i].computeSize(); + } this.setDirty(true, true); }; @@ -7344,7 +8374,9 @@ LGraphNode.prototype.executeAction = function(action) height = parent.offsetHeight; } - if (this.canvas.width == width && this.canvas.height == height) return; + if (this.canvas.width == width && this.canvas.height == height) { + return; + } this.canvas.width = width; this.canvas.height = height; @@ -7380,7 +8412,9 @@ LGraphNode.prototype.executeAction = function(action) if (delta < 1 && self.editor_alpha < 0.01) { clearInterval(t); - if (delta < 1) self.live_mode = true; + if (delta < 1) { + self.live_mode = true; + } } if (delta > 1 && self.editor_alpha > 0.99) { clearInterval(t); @@ -7459,13 +8493,15 @@ LGraphNode.prototype.executeAction = function(action) var values = LiteGraph.getNodeTypesCategories(); var entries = []; - for (var i in values) - if (values[i]) + for (var i in values) { + if (values[i]) { entries.push({ value: values[i], content: values[i], has_submenu: true }); + } + } //show categories var menu = new LiteGraph.ContextMenu( @@ -7481,12 +8517,14 @@ LGraphNode.prototype.executeAction = function(action) canvas.filter ); var values = []; - for (var i in node_types) - if (!node_types[i].skip_list) + for (var i in node_types) { + if (!node_types[i].skip_list) { values.push({ content: node_types[i].title, value: node_types[i].type }); + } + } new LiteGraph.ContextMenu( values, @@ -7519,17 +8557,21 @@ LGraphNode.prototype.executeAction = function(action) prev_menu, node ) { - if (!node) return; + if (!node) { + return; + } var that = this; var canvas = LGraphCanvas.active_canvas; var ref_window = canvas.getCanvasWindow(); var options = node.optional_inputs; - if (node.onGetInputs) options = node.onGetInputs(); + if (node.onGetInputs) { + options = node.onGetInputs(); + } var entries = []; - if (options) + if (options) { for (var i in options) { var entry = options[i]; if (!entry) { @@ -7537,15 +8579,24 @@ LGraphNode.prototype.executeAction = function(action) continue; } var label = entry[0]; - if (entry[2] && entry[2].label) label = entry[2].label; + if (entry[2] && entry[2].label) { + label = entry[2].label; + } var data = { content: label, value: entry }; - if (entry[1] == LiteGraph.ACTION) data.className = "event"; + if (entry[1] == LiteGraph.ACTION) { + data.className = "event"; + } entries.push(data); } + } - if (this.onMenuNodeInputs) entries = this.onMenuNodeInputs(entries); + if (this.onMenuNodeInputs) { + entries = this.onMenuNodeInputs(entries); + } - if (!entries.length) return; + if (!entries.length) { + return; + } var menu = new LiteGraph.ContextMenu( entries, @@ -7559,9 +8610,13 @@ LGraphNode.prototype.executeAction = function(action) ); function inner_clicked(v, e, prev) { - if (!node) return; + if (!node) { + return; + } - if (v.callback) v.callback.call(that, node, v, e, prev); + if (v.callback) { + v.callback.call(that, node, v, e, prev); + } if (v.value) { node.addInput(v.value[0], v.value[1], v.value[2]); @@ -7579,17 +8634,21 @@ LGraphNode.prototype.executeAction = function(action) prev_menu, node ) { - if (!node) return; + if (!node) { + return; + } var that = this; var canvas = LGraphCanvas.active_canvas; var ref_window = canvas.getCanvasWindow(); var options = node.optional_outputs; - if (node.onGetOutputs) options = node.onGetOutputs(); + if (node.onGetOutputs) { + options = node.onGetOutputs(); + } var entries = []; - if (options) + if (options) { for (var i in options) { var entry = options[i]; if (!entry) { @@ -7602,18 +8661,28 @@ LGraphNode.prototype.executeAction = function(action) node.flags && node.flags.skip_repeated_outputs && node.findOutputSlot(entry[0]) != -1 - ) - continue; //skip the ones already on + ) { + continue; + } //skip the ones already on var label = entry[0]; - if (entry[2] && entry[2].label) label = entry[2].label; + if (entry[2] && entry[2].label) { + label = entry[2].label; + } var data = { content: label, value: entry }; - if (entry[1] == LiteGraph.EVENT) data.className = "event"; + if (entry[1] == LiteGraph.EVENT) { + data.className = "event"; + } entries.push(data); } + } - if (this.onMenuNodeOutputs) entries = this.onMenuNodeOutputs(entries); + if (this.onMenuNodeOutputs) { + entries = this.onMenuNodeOutputs(entries); + } - if (!entries.length) return; + if (!entries.length) { + return; + } var menu = new LiteGraph.ContextMenu( entries, @@ -7627,11 +8696,17 @@ LGraphNode.prototype.executeAction = function(action) ); function inner_clicked(v, e, prev) { - if (!node) return; + if (!node) { + return; + } - if (v.callback) v.callback.call(that, node, v, e, prev); + if (v.callback) { + v.callback.call(that, node, v, e, prev); + } - if (!v.value) return; + if (!v.value) { + return; + } var value = v.value[1]; @@ -7641,8 +8716,9 @@ LGraphNode.prototype.executeAction = function(action) ) { //submenu why? var entries = []; - for (var i in value) + for (var i in value) { entries.push({ content: i, value: value[i] }); + } new LiteGraph.ContextMenu(entries, { event: e, callback: inner_clicked, @@ -7666,7 +8742,9 @@ LGraphNode.prototype.executeAction = function(action) prev_menu, node ) { - if (!node || !node.properties) return; + if (!node || !node.properties) { + return; + } var that = this; var canvas = LGraphCanvas.active_canvas; @@ -7689,7 +8767,9 @@ LGraphNode.prototype.executeAction = function(action) value: i }); } - if (!entries.length) return; + if (!entries.length) { + return; + } var menu = new LiteGraph.ContextMenu( entries, @@ -7704,7 +8784,9 @@ LGraphNode.prototype.executeAction = function(action) ); function inner_clicked(v, options, e, prev) { - if (!node) return; + if (!node) { + return; + } var rect = this.getBoundingClientRect(); canvas.showEditPropertyValue(node, v.value, { position: [rect.left, rect.top] @@ -7721,7 +8803,9 @@ LGraphNode.prototype.executeAction = function(action) }; LGraphCanvas.onResizeNode = function(value, options, e, menu, node) { - if (!node) return; + if (!node) { + return; + } node.size = node.computeSize(); node.setDirtyCanvas(true, true); }; @@ -7764,7 +8848,9 @@ LGraphNode.prototype.executeAction = function(action) this.focus(); }); input.addEventListener("keydown", function(e) { - if (e.keyCode != 13) return; + if (e.keyCode != 13) { + return; + } inner(); e.preventDefault(); e.stopPropagation(); @@ -7799,10 +8885,15 @@ LGraphNode.prototype.executeAction = function(action) } function setValue(value) { - if (item.type == "Number") value = Number(value); - else if (item.type == "Boolean") value = Boolean(value); + if (item.type == "Number") { + value = Number(value); + } else if (item.type == "Boolean") { + value = Boolean(value); + } node[property] = value; - if (dialog.parentNode) dialog.parentNode.removeChild(dialog); + if (dialog.parentNode) { + dialog.parentNode.removeChild(dialog); + } node.setDirtyCanvas(true, true); } }; @@ -7820,17 +8911,24 @@ LGraphNode.prototype.executeAction = function(action) " OK"; dialog.close = function() { that.prompt_box = null; - if (dialog.parentNode) dialog.parentNode.removeChild(dialog); + if (dialog.parentNode) { + dialog.parentNode.removeChild(dialog); + } }; - if (this.ds.scale > 1) + if (this.ds.scale > 1) { dialog.style.transform = "scale(" + this.ds.scale + ")"; + } dialog.addEventListener("mouseleave", function(e) { - if (!modified) dialog.close(); + if (!modified) { + dialog.close(); + } }); - if (that.prompt_box) that.prompt_box.close(); + if (that.prompt_box) { + that.prompt_box.close(); + } that.prompt_box = dialog; var first = null; @@ -7845,20 +8943,26 @@ LGraphNode.prototype.executeAction = function(action) var input = dialog.querySelector("input"); input.addEventListener("keydown", function(e) { modified = true; - if (e.keyCode == 27) + if (e.keyCode == 27) { //ESC dialog.close(); - else if (e.keyCode == 13) { - if (callback) callback(this.value); + } else if (e.keyCode == 13) { + if (callback) { + callback(this.value); + } dialog.close(); - } else return; + } else { + return; + } e.preventDefault(); e.stopPropagation(); }); var button = dialog.querySelector("button"); button.addEventListener("click", function(e) { - if (callback) callback(input.value); + if (callback) { + callback(input.value); + } that.setDirty(true); dialog.close(); }); @@ -7905,13 +9009,16 @@ LGraphNode.prototype.executeAction = function(action) setTimeout(function() { that.canvas.focus(); }, 20); //important, if canvas loses focus keys wont be captured - if (dialog.parentNode) dialog.parentNode.removeChild(dialog); + if (dialog.parentNode) { + dialog.parentNode.removeChild(dialog); + } }; var timeout_close = null; - if (this.ds.scale > 1) + if (this.ds.scale > 1) { dialog.style.transform = "scale(" + this.ds.scale + ")"; + } dialog.addEventListener("mouseenter", function(e) { if (timeout_close) { @@ -7927,7 +9034,9 @@ LGraphNode.prototype.executeAction = function(action) }, 500); }); - if (that.search_box) that.search_box.close(); + if (that.search_box) { + that.search_box.close(); + } that.search_box = dialog; var helper = dialog.querySelector(".helper"); @@ -7942,21 +9051,27 @@ LGraphNode.prototype.executeAction = function(action) this.focus(); }); input.addEventListener("keydown", function(e) { - if (e.keyCode == 38) + if (e.keyCode == 38) { //UP changeSelection(false); - else if (e.keyCode == 40) + } else if (e.keyCode == 40) { //DOWN changeSelection(true); - else if (e.keyCode == 27) + } else if (e.keyCode == 27) { //ESC dialog.close(); - else if (e.keyCode == 13) { - if (selected) select(selected.innerHTML); - else if (first) select(first); - else dialog.close(); + } else if (e.keyCode == 13) { + if (selected) { + select(selected.innerHTML); + } else if (first) { + select(first); + } else { + dialog.close(); + } } else { - if (timeout) clearInterval(timeout); + if (timeout) { + clearInterval(timeout); + } timeout = setTimeout(refreshHelper, 10); return; } @@ -7989,11 +9104,13 @@ LGraphNode.prototype.executeAction = function(action) function select(name) { if (name) { - if (that.onSearchBoxSelection) + if (that.onSearchBoxSelection) { that.onSearchBoxSelection(name, event, graphcanvas); - else { + } else { var extra = LiteGraph.searchbox_extras[name]; - if (extra) name = extra.type; + if (extra) { + name = extra.type; + } var node = LiteGraph.createNode(name); if (node) { @@ -8004,30 +9121,38 @@ LGraphNode.prototype.executeAction = function(action) } if (extra && extra.data) { - if (extra.data.properties) - for (var i in extra.data.properties) + if (extra.data.properties) { + for (var i in extra.data.properties) { node.addProperty( extra.data.properties[i][0], extra.data.properties[i][0] ); + } + } if (extra.data.inputs) { node.inputs = []; - for (var i in extra.data.inputs) + for (var i in extra.data.inputs) { node.addOutput( extra.data.inputs[i][0], extra.data.inputs[i][1] ); + } } if (extra.data.outputs) { node.outputs = []; - for (var i in extra.data.outputs) + for (var i in extra.data.outputs) { node.addOutput( extra.data.outputs[i][0], extra.data.outputs[i][1] ); + } + } + if (extra.data.title) { + node.title = extra.data.title; + } + if (extra.data.json) { + node.configure(extra.data.json); } - if (extra.data.title) node.title = extra.data.title; - if (extra.data.json) node.configure(extra.data.json); } } } @@ -8037,18 +9162,24 @@ LGraphNode.prototype.executeAction = function(action) function changeSelection(forward) { var prev = selected; - if (selected) selected.classList.remove("selected"); - if (!selected) + if (selected) { + selected.classList.remove("selected"); + } + if (!selected) { selected = forward ? helper.childNodes[0] : helper.childNodes[helper.childNodes.length]; - else { + } else { selected = forward ? selected.nextSibling : selected.previousSibling; - if (!selected) selected = prev; + if (!selected) { + selected = prev; + } + } + if (!selected) { + return; } - if (!selected) return; selected.classList.add("selected"); selected.scrollIntoView(); } @@ -8058,25 +9189,33 @@ LGraphNode.prototype.executeAction = function(action) var str = input.value; first = null; helper.innerHTML = ""; - if (!str) return; + if (!str) { + return; + } if (that.onSearchBox) { var list = that.onSearchBox(helper, str, graphcanvas); - if (list) - for (var i = 0; i < list.length; ++i) addResult(list[i]); + if (list) { + for (var i = 0; i < list.length; ++i) { + addResult(list[i]); + } + } } else { var c = 0; str = str.toLowerCase(); //extras for (var i in LiteGraph.searchbox_extras) { var extra = LiteGraph.searchbox_extras[i]; - if (extra.desc.toLowerCase().indexOf(str) === -1) continue; + if (extra.desc.toLowerCase().indexOf(str) === -1) { + continue; + } addResult(extra.desc, "searchbox_extra"); if ( LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit - ) + ) { break; + } } if (Array.prototype.filter) { @@ -8091,8 +9230,9 @@ LGraphNode.prototype.executeAction = function(action) if ( LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit - ) + ) { break; + } } } else { for (var i in LiteGraph.registered_node_types) { @@ -8101,8 +9241,9 @@ LGraphNode.prototype.executeAction = function(action) if ( LGraphCanvas.search_limit !== -1 && c++ > LGraphCanvas.search_limit - ) + ) { break; + } } } } @@ -8110,11 +9251,15 @@ LGraphNode.prototype.executeAction = function(action) function addResult(type, className) { var help = document.createElement("div"); - if (!first) first = type; + if (!first) { + first = type; + } help.innerText = type; help.dataset["type"] = escape(type); help.className = "litegraph lite-search-item"; - if (className) help.className += " " + className; + if (className) { + help.className += " " + className; + } help.addEventListener("click", function(e) { select(unescape(this.dataset["type"])); }); @@ -8130,23 +9275,30 @@ LGraphNode.prototype.executeAction = function(action) property, options ) { - if (!node || node.properties[property] === undefined) return; + if (!node || node.properties[property] === undefined) { + return; + } options = options || {}; var that = this; var type = "string"; - if (node.properties[property] !== null) + if (node.properties[property] !== null) { type = typeof node.properties[property]; + } //for arrays if (type == "object") { - if (node.properties[property].length) type = "array"; + if (node.properties[property].length) { + type = "array"; + } } var info = null; - if (node.getPropertyInfo) info = node.getPropertyInfo(property); + if (node.getPropertyInfo) { + info = node.getPropertyInfo(property); + } if (node.properties_info) { for (var i = 0; i < node.properties_info.length; ++i) { if (node.properties_info[i].name == property) { @@ -8156,13 +9308,15 @@ LGraphNode.prototype.executeAction = function(action) } } - if (info !== undefined && info !== null && info.type) type = info.type; + if (info !== undefined && info !== null && info.type) { + type = info.type; + } var input_html = ""; - if (type == "string" || type == "number" || type == "array") + if (type == "string" || type == "number" || type == "array") { input_html = ""; - else if (type == "enum" && info.values) { + } else if (type == "enum" && info.values) { input_html = ""; for (var i in info.values) { var v = info.values.constructor === Array ? info.values[i] : i; @@ -8220,7 +9374,9 @@ LGraphNode.prototype.executeAction = function(action) ? node.properties[property] : ""; input.addEventListener("keydown", function(e) { - if (e.keyCode != 13) return; + if (e.keyCode != 13) { + return; + } inner(); e.preventDefault(); e.stopPropagation(); @@ -8236,12 +9392,19 @@ LGraphNode.prototype.executeAction = function(action) } function setValue(value) { - if (typeof node.properties[property] == "number") + if (typeof node.properties[property] == "number") { value = Number(value); - if (type == "array") value = value.split(",").map(Number); + } + if (type == "array") { + value = value.split(",").map(Number); + } node.properties[property] = value; - if (node._graph) node._graph._version++; - if (node.onPropertyChanged) node.onPropertyChanged(property, value); + if (node._graph) { + node._graph._version++; + } + if (node.onPropertyChanged) { + node.onPropertyChanged(property, value); + } dialog.close(); node.setDirtyCanvas(true, true); } @@ -8280,7 +9443,9 @@ LGraphNode.prototype.executeAction = function(action) this.canvas.parentNode.appendChild(dialog); dialog.close = function() { - if (this.parentNode) this.parentNode.removeChild(this); + if (this.parentNode) { + this.parentNode.removeChild(this); + } }; return dialog; @@ -8301,7 +9466,9 @@ LGraphNode.prototype.executeAction = function(action) ); function inner_clicked(v) { - if (!node) return; + if (!node) { + return; + } switch (v) { case "On Event": node.mode = LiteGraph.ON_EVENT; @@ -8323,7 +9490,9 @@ LGraphNode.prototype.executeAction = function(action) }; LGraphCanvas.onMenuNodeColors = function(value, options, e, menu, node) { - if (!node) throw "no node for color"; + if (!node) { + throw "no node for color"; + } var values = []; values.push({ @@ -8355,13 +9524,15 @@ LGraphNode.prototype.executeAction = function(action) }); function inner_clicked(v) { - if (!node) return; + if (!node) { + return; + } var color = v.value ? LGraphCanvas.node_colors[v.value] : null; if (color) { - if (node.constructor === LiteGraph.LGraphGroup) + if (node.constructor === LiteGraph.LGraphGroup) { node.color = color.groupcolor; - else { + } else { node.color = color.color; node.bgcolor = color.bgcolor; } @@ -8376,7 +9547,9 @@ LGraphNode.prototype.executeAction = function(action) }; LGraphCanvas.onMenuNodeShapes = function(value, options, e, menu, node) { - if (!node) throw "no node passed"; + if (!node) { + throw "no node passed"; + } new LiteGraph.ContextMenu(LiteGraph.VALID_SHAPES, { event: e, @@ -8386,7 +9559,9 @@ LGraphNode.prototype.executeAction = function(action) }); function inner_clicked(v) { - if (!node) return; + if (!node) { + return; + } node.shape = v; node.setDirtyCanvas(true); } @@ -8395,18 +9570,26 @@ LGraphNode.prototype.executeAction = function(action) }; LGraphCanvas.onMenuNodeRemove = function(value, options, e, menu, node) { - if (!node) throw "no node passed"; + if (!node) { + throw "no node passed"; + } - if (node.removable === false) return; + if (node.removable === false) { + return; + } node.graph.remove(node); node.setDirtyCanvas(true, true); }; LGraphCanvas.onMenuNodeClone = function(value, options, e, menu, node) { - if (node.clonable == false) return; + if (node.clonable == false) { + return; + } var newnode = node.clone(); - if (!newnode) return; + if (!newnode) { + return; + } newnode.pos = [node.pos[0] + 5, node.pos[1] + 5]; node.graph.add(newnode); node.setDirtyCanvas(true, true); @@ -8430,8 +9613,9 @@ LGraphNode.prototype.executeAction = function(action) LGraphCanvas.prototype.getCanvasMenuOptions = function() { var options = null; - if (this.getMenuOptions) options = this.getMenuOptions(); - else { + if (this.getMenuOptions) { + options = this.getMenuOptions(); + } else { options = [ { content: "Add Node", @@ -8442,16 +9626,19 @@ LGraphNode.prototype.executeAction = function(action) //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } ]; - if (this._graph_stack && this._graph_stack.length > 0) + if (this._graph_stack && this._graph_stack.length > 0) { options.push(null, { content: "Close subgraph", callback: this.closeSubgraph.bind(this) }); + } } if (this.getExtraMenuOptions) { var extra = this.getExtraMenuOptions(this, options); - if (extra) options = options.concat(extra); + if (extra) { + options = options.concat(extra); + } } return options; @@ -8461,8 +9648,9 @@ LGraphNode.prototype.executeAction = function(action) LGraphCanvas.prototype.getNodeMenuOptions = function(node) { var options = null; - if (node.getMenuOptions) options = node.getMenuOptions(this); - else + if (node.getMenuOptions) { + options = node.getMenuOptions(this); + } else { options = [ { content: "Inputs", @@ -8510,15 +9698,20 @@ LGraphNode.prototype.executeAction = function(action) }, null ]; + } if (node.onGetInputs) { var inputs = node.onGetInputs(); - if (inputs && inputs.length) options[0].disabled = false; + if (inputs && inputs.length) { + options[0].disabled = false; + } } if (node.onGetOutputs) { var outputs = node.onGetOutputs(); - if (outputs && outputs.length) options[1].disabled = false; + if (outputs && outputs.length) { + options[1].disabled = false; + } } if (node.getExtraMenuOptions) { @@ -8529,19 +9722,22 @@ LGraphNode.prototype.executeAction = function(action) } } - if (node.clonable !== false) + if (node.clonable !== false) { options.push({ content: "Clone", callback: LGraphCanvas.onMenuNodeClone }); - if (node.removable !== false) + } + if (node.removable !== false) { options.push(null, { content: "Remove", callback: LGraphCanvas.onMenuNodeRemove }); + } - if (node.graph && node.graph.onGetNodeMenuOptions) + if (node.graph && node.graph.onGetNodeMenuOptions) { node.graph.onGetNodeMenuOptions(options, node); + } return options; }; @@ -8594,8 +9790,9 @@ LGraphNode.prototype.executeAction = function(action) slot.output && slot.output.links && slot.output.links.length - ) + ) { menu_info.push({ content: "Disconnect Links", slot: slot }); + } var _slot = slot.input || slot.output; menu_info.push( _slot.locked @@ -8609,21 +9806,23 @@ LGraphNode.prototype.executeAction = function(action) ); options.title = (slot.input ? slot.input.type : slot.output.type) || "*"; - if (slot.input && slot.input.type == LiteGraph.ACTION) + if (slot.input && slot.input.type == LiteGraph.ACTION) { options.title = "Action"; - if (slot.output && slot.output.type == LiteGraph.EVENT) + } + if (slot.output && slot.output.type == LiteGraph.EVENT) { options.title = "Event"; + } } else { - if (node) + if (node) { //on node menu_info = this.getNodeMenuOptions(node); - else { + } else { menu_info = this.getCanvasMenuOptions(); var group = this.graph.getGroupOnPos( event.canvasX, event.canvasY ); - if (group) + if (group) { //on group menu_info.push(null, { content: "Edit Group", @@ -8634,26 +9833,37 @@ LGraphNode.prototype.executeAction = function(action) options: this.getGroupMenuOptions(group) } }); + } } } //show menu - if (!menu_info) return; + if (!menu_info) { + return; + } var menu = new LiteGraph.ContextMenu(menu_info, options, ref_window); function inner_option_clicked(v, options, e) { - if (!v) return; + if (!v) { + return; + } if (v.content == "Remove Slot") { var info = v.slot; - if (info.input) node.removeInput(info.slot); - else if (info.output) node.removeOutput(info.slot); + if (info.input) { + node.removeInput(info.slot); + } else if (info.output) { + node.removeOutput(info.slot); + } return; } else if (v.content == "Disconnect Links") { var info = v.slot; - if (info.output) node.disconnectOutput(info.slot); - else if (info.input) node.disconnectInput(info.slot); + if (info.output) { + node.disconnectOutput(info.slot); + } else if (info.input) { + node.disconnectInput(info.slot); + } return; } else if (v.content == "Rename Slot") { var info = v.slot; @@ -8672,7 +9882,9 @@ LGraphNode.prototype.executeAction = function(action) .querySelector("button") .addEventListener("click", function(e) { if (input.value) { - if (slot_info) slot_info.label = input.value; + if (slot_info) { + slot_info.label = input.value; + } that.setDirty(true); } dialog.close(); @@ -8686,7 +9898,7 @@ LGraphNode.prototype.executeAction = function(action) //API ************************************************* //like rect but rounded corners - if (this.CanvasRenderingContext2D) + if (this.CanvasRenderingContext2D) { CanvasRenderingContext2D.prototype.roundRect = function( x, y, @@ -8699,7 +9911,9 @@ LGraphNode.prototype.executeAction = function(action) radius = 5; } - if (radius_low === undefined) radius_low = radius; + if (radius_low === undefined) { + radius_low = radius; + } this.moveTo(x + radius, y); this.lineTo(x + width - radius, y); @@ -8717,9 +9931,14 @@ LGraphNode.prototype.executeAction = function(action) this.lineTo(x, y + radius); this.quadraticCurveTo(x, y, x + radius, y); }; + } function compareObjects(a, b) { - for (var i in a) if (a[i] != b[i]) return false; + for (var i in a) { + if (a[i] != b[i]) { + return false; + } + } return true; } LiteGraph.compareObjects = compareObjects; @@ -8747,19 +9966,26 @@ LGraphNode.prototype.executeAction = function(action) LiteGraph.colorToString = colorToString; function isInsideRectangle(x, y, left, top, width, height) { - if (left < x && left + width > x && top < y && top + height > y) + if (left < x && left + width > x && top < y && top + height > y) { return true; + } return false; } LiteGraph.isInsideRectangle = isInsideRectangle; //[minx,miny,maxx,maxy] function growBounding(bounding, x, y) { - if (x < bounding[0]) bounding[0] = x; - else if (x > bounding[2]) bounding[2] = x; + if (x < bounding[0]) { + bounding[0] = x; + } else if (x > bounding[2]) { + bounding[2] = x; + } - if (y < bounding[1]) bounding[1] = y; - else if (y > bounding[3]) bounding[3] = y; + if (y < bounding[1]) { + bounding[1] = y; + } else if (y > bounding[3]) { + bounding[3] = y; + } } LiteGraph.growBounding = growBounding; @@ -8770,8 +9996,9 @@ LGraphNode.prototype.executeAction = function(action) p[1] < bb[0][1] || p[0] > bb[1][0] || p[1] > bb[1][1] - ) + ) { return false; + } return true; } LiteGraph.isInsideBounding = isInsideBounding; @@ -8788,8 +10015,9 @@ LGraphNode.prototype.executeAction = function(action) a[1] > B_end_y || A_end_x < b[0] || A_end_y < b[1] - ) + ) { return false; + } return true; } LiteGraph.overlapBounding = overlapBounding; @@ -8798,7 +10026,9 @@ LGraphNode.prototype.executeAction = function(action) // format of a hex triplet - the kind we use for HTML colours. The function // will return an array with three values. function hex2num(hex) { - if (hex.charAt(0) == "#") hex = hex.slice(1); //Remove the '#' char - if there is one. + if (hex.charAt(0) == "#") { + hex = hex.slice(1); + } //Remove the '#' char - if there is one. hex = hex.toUpperCase(); var hex_alphabets = "0123456789ABCDEF"; var value = new Array(3); @@ -8878,7 +10108,9 @@ LGraphNode.prototype.executeAction = function(action) var root = document.createElement("div"); root.className = "litegraph litecontextmenu litemenubar-panel"; - if (options.className) root.className += " " + options.className; + if (options.className) { + root.className += " " + options.className; + } root.style.minWidth = 100; root.style.minHeight = 100; root.style.pointerEvents = "none"; @@ -8898,9 +10130,10 @@ LGraphNode.prototype.executeAction = function(action) root.addEventListener( "contextmenu", function(e) { - if (e.button != 2) + if (e.button != 2) { //right button return false; + } e.preventDefault(); return false; }, @@ -8927,7 +10160,9 @@ LGraphNode.prototype.executeAction = function(action) return true; } - if (!options.scroll_speed) options.scroll_speed = 0.1; + if (!options.scroll_speed) { + options.scroll_speed = 0.1; + } root.addEventListener("wheel", on_mouse_wheel, true); root.addEventListener("mousewheel", on_mouse_wheel, true); @@ -8946,8 +10181,9 @@ LGraphNode.prototype.executeAction = function(action) var num = 0; for (var i in values) { var name = values.constructor == Array ? values[i] : i; - if (name != null && name.constructor !== String) + if (name != null && name.constructor !== String) { name = name.content === undefined ? String(name) : name.content; + } var value = values[i]; this.addItem(name, value, options); num++; @@ -8955,21 +10191,31 @@ LGraphNode.prototype.executeAction = function(action) //close on leave root.addEventListener("mouseleave", function(e) { - if (that.lock) return; - if (root.closing_timer) clearTimeout(root.closing_timer); + if (that.lock) { + return; + } + if (root.closing_timer) { + clearTimeout(root.closing_timer); + } root.closing_timer = setTimeout(that.close.bind(that, e), 500); //that.close(e); }); root.addEventListener("mouseenter", function(e) { - if (root.closing_timer) clearTimeout(root.closing_timer); + if (root.closing_timer) { + clearTimeout(root.closing_timer); + } }); //insert before checking position var root_document = document; - if (options.event) root_document = options.event.target.ownerDocument; + if (options.event) { + root_document = options.event.target.ownerDocument; + } - if (!root_document) root_document = document; + if (!root_document) { + root_document = document; + } root_document.body.appendChild(root); //compute best position @@ -8978,7 +10224,9 @@ LGraphNode.prototype.executeAction = function(action) if (options.event) { left = options.event.clientX - 10; top = options.event.clientY - 10; - if (options.title) top -= 20; + if (options.title) { + top -= 20; + } if (options.parentMenu) { var rect = options.parentMenu.root.getBoundingClientRect(); @@ -8988,17 +10236,20 @@ LGraphNode.prototype.executeAction = function(action) var body_rect = document.body.getBoundingClientRect(); var root_rect = root.getBoundingClientRect(); - if (left > body_rect.width - root_rect.width - 10) + if (left > body_rect.width - root_rect.width - 10) { left = body_rect.width - root_rect.width - 10; - if (top > body_rect.height - root_rect.height - 10) + } + if (top > body_rect.height - root_rect.height - 10) { top = body_rect.height - root_rect.height - 10; + } } root.style.left = left + "px"; root.style.top = top + "px"; - if (options.scale) + if (options.scale) { root.style.transform = "scale(" + options.scale + ")"; + } } ContextMenu.prototype.addItem = function(name, value, options) { @@ -9023,26 +10274,36 @@ LGraphNode.prototype.executeAction = function(action) disabled = true; element.classList.add("disabled"); } - if (value.submenu || value.has_submenu) + if (value.submenu || value.has_submenu) { element.classList.add("has_submenu"); + } } if (typeof value == "function") { element.dataset["value"] = name; element.onclick_callback = value; - } else element.dataset["value"] = value; + } else { + element.dataset["value"] = value; + } - if (value.className) element.className += " " + value.className; + if (value.className) { + element.className += " " + value.className; + } } this.root.appendChild(element); - if (!disabled) element.addEventListener("click", inner_onclick); - if (options.autoopen) + if (!disabled) { + element.addEventListener("click", inner_onclick); + } + if (options.autoopen) { element.addEventListener("mouseenter", inner_over); + } function inner_over(e) { var value = this.value; - if (!value || !value.has_submenu) return; + if (!value || !value.has_submenu) { + return; + } //if it is a submenu, autoopen like the item was clicked inner_onclick.call(this, e); } @@ -9052,7 +10313,9 @@ LGraphNode.prototype.executeAction = function(action) var value = this.value; var close_parent = true; - if (that.current_submenu) that.current_submenu.close(e); + if (that.current_submenu) { + that.current_submenu.close(e); + } //global callback if (options.callback) { @@ -9064,7 +10327,9 @@ LGraphNode.prototype.executeAction = function(action) that, options.node ); - if (r === true) close_parent = false; + if (r === true) { + close_parent = false; + } } //special cases @@ -9083,11 +10348,14 @@ LGraphNode.prototype.executeAction = function(action) that, options.extra ); - if (r === true) close_parent = false; + if (r === true) { + close_parent = false; + } } if (value.submenu) { - if (!value.submenu.options) + if (!value.submenu.options) { throw "ContextMenu submenu needs options"; + } var submenu = new that.constructor(value.submenu.options, { callback: value.submenu.callback, event: e, @@ -9102,28 +10370,37 @@ LGraphNode.prototype.executeAction = function(action) } } - if (close_parent && !that.lock) that.close(); + if (close_parent && !that.lock) { + that.close(); + } } return element; }; ContextMenu.prototype.close = function(e, ignore_parent_menu) { - if (this.root.parentNode) this.root.parentNode.removeChild(this.root); + if (this.root.parentNode) { + this.root.parentNode.removeChild(this.root); + } if (this.parentMenu && !ignore_parent_menu) { this.parentMenu.lock = false; this.parentMenu.current_submenu = null; - if (e === undefined) this.parentMenu.close(); - else if ( + if (e === undefined) { + this.parentMenu.close(); + } else if ( e && !ContextMenu.isCursorOverElement(e, this.parentMenu.root) ) { ContextMenu.trigger(this.parentMenu.root, "mouseleave", e); } } - if (this.current_submenu) this.current_submenu.close(e, true); + if (this.current_submenu) { + this.current_submenu.close(e, true); + } - if (this.root.closing_timer) clearTimeout(this.root.closing_timer); + if (this.root.closing_timer) { + clearTimeout(this.root.closing_timer); + } }; //this code is used to trigger events easily (used in the context menu mouseleave @@ -9131,22 +10408,27 @@ LGraphNode.prototype.executeAction = function(action) var evt = document.createEvent("CustomEvent"); evt.initCustomEvent(event_name, true, true, params); //canBubble, cancelable, detail evt.srcElement = origin; - if (element.dispatchEvent) element.dispatchEvent(evt); - else if (element.__events) element.__events.dispatchEvent(evt); + if (element.dispatchEvent) { + element.dispatchEvent(evt); + } else if (element.__events) { + element.__events.dispatchEvent(evt); + } //else nothing seems binded here so nothing to do return evt; }; //returns the top most menu ContextMenu.prototype.getTopMenu = function() { - if (this.options.parentMenu) + if (this.options.parentMenu) { return this.options.parentMenu.getTopMenu(); + } return this; }; ContextMenu.prototype.getFirstEvent = function() { - if (this.options.parentMenu) + if (this.options.parentMenu) { return this.options.parentMenu.getFirstEvent(); + } return this.options.event; }; @@ -9154,14 +10436,17 @@ LGraphNode.prototype.executeAction = function(action) var left = event.clientX; var top = event.clientY; var rect = element.getBoundingClientRect(); - if (!rect) return false; + if (!rect) { + return false; + } if ( top > rect.top && top < rect.top + rect.height && left > rect.left && left < rect.left + rect.width - ) + ) { return true; + } return false; }; @@ -9171,50 +10456,65 @@ LGraphNode.prototype.executeAction = function(action) ref_window = ref_window || window; var elements = ref_window.document.querySelectorAll(".litecontextmenu"); - if (!elements.length) return; + if (!elements.length) { + return; + } var result = []; - for (var i = 0; i < elements.length; i++) result.push(elements[i]); + for (var i = 0; i < elements.length; i++) { + result.push(elements[i]); + } for (var i in result) { - if (result[i].close) result[i].close(); - else if (result[i].parentNode) + if (result[i].close) { + result[i].close(); + } else if (result[i].parentNode) { result[i].parentNode.removeChild(result[i]); + } } }; LiteGraph.extendClass = function(target, origin) { for (var i in origin) { //copy class properties - if (target.hasOwnProperty(i)) continue; + if (target.hasOwnProperty(i)) { + continue; + } target[i] = origin[i]; } - if (origin.prototype) + if (origin.prototype) { //copy prototype properties for (var i in origin.prototype) { //only enumerable - if (!origin.prototype.hasOwnProperty(i)) continue; + if (!origin.prototype.hasOwnProperty(i)) { + continue; + } - if (target.prototype.hasOwnProperty(i)) + if (target.prototype.hasOwnProperty(i)) { //avoid overwriting existing ones continue; + } //copy getters - if (origin.prototype.__lookupGetter__(i)) + if (origin.prototype.__lookupGetter__(i)) { target.prototype.__defineGetter__( i, origin.prototype.__lookupGetter__(i) ); - else target.prototype[i] = origin.prototype[i]; + } else { + target.prototype[i] = origin.prototype[i]; + } //and setters - if (origin.prototype.__lookupSetter__(i)) + if (origin.prototype.__lookupSetter__(i)) { target.prototype.__defineSetter__( i, origin.prototype.__lookupSetter__(i) ); + } } + } }; //used to create nodes from wrapping functions @@ -9244,4 +10544,6 @@ LGraphNode.prototype.executeAction = function(action) } })(this); -if (typeof exports != "undefined") exports.LiteGraph = this.LiteGraph; +if (typeof exports != "undefined") { + exports.LiteGraph = this.LiteGraph; +} diff --git a/src/nodes/audio.js b/src/nodes/audio.js index f6e2bb60c..1c63ea2d1 100644 --- a/src/nodes/audio.js +++ b/src/nodes/audio.js @@ -51,24 +51,32 @@ for (var i = 0; i < node.inputs.length; ++i) { var input = node.inputs[i]; var link_info = node.graph.links[input.link]; - if (!link_info) continue; + if (!link_info) { + continue; + } var origin_node = node.graph.getNodeById(link_info.origin_id); var origin_audionode = null; - if (origin_node.getAudioNodeInOutputSlot) + if (origin_node.getAudioNodeInOutputSlot) { origin_audionode = origin_node.getAudioNodeInOutputSlot( link_info.origin_slot ); - else origin_audionode = origin_node.audionode; + } else { + origin_audionode = origin_node.audionode; + } var target_audionode = null; - if (node.getAudioNodeInInputSlot) + if (node.getAudioNodeInInputSlot) { target_audionode = node.getAudioNodeInInputSlot(i); - else target_audionode = node.audionode; + } else { + target_audionode = node.audionode; + } - if (connect) + if (connect) { LGAudio.connect(origin_audionode, target_audionode); - else LGAudio.disconnect(origin_audionode, target_audionode); + } else { + LGAudio.disconnect(origin_audionode, target_audionode); + } } } @@ -77,26 +85,34 @@ var output = node.outputs[i]; for (var j = 0; j < output.links.length; ++j) { var link_info = node.graph.links[output.links[j]]; - if (!link_info) continue; + if (!link_info) { + continue; + } var origin_audionode = null; - if (node.getAudioNodeInOutputSlot) + if (node.getAudioNodeInOutputSlot) { origin_audionode = node.getAudioNodeInOutputSlot(i); - else origin_audionode = node.audionode; + } else { + origin_audionode = node.audionode; + } var target_node = node.graph.getNodeById( link_info.target_id ); var target_audionode = null; - if (target_node.getAudioNodeInInputSlot) + if (target_node.getAudioNodeInInputSlot) { target_audionode = target_node.getAudioNodeInInputSlot( link_info.target_slot ); - else target_audionode = target_node.audionode; + } else { + target_audionode = target_node.audionode; + } - if (connect) + if (connect) { LGAudio.connect(origin_audionode, target_audionode); - else LGAudio.disconnect(origin_audionode, target_audionode); + } else { + LGAudio.disconnect(origin_audionode, target_audionode); + } } } } @@ -110,31 +126,43 @@ link_info ) { //only process the outputs events - if (connection != LiteGraph.OUTPUT) return; + if (connection != LiteGraph.OUTPUT) { + return; + } var target_node = null; - if (link_info) + if (link_info) { target_node = this.graph.getNodeById(link_info.target_id); + } - if (!target_node) return; + if (!target_node) { + return; + } //get origin audionode var local_audionode = null; - if (this.getAudioNodeInOutputSlot) + if (this.getAudioNodeInOutputSlot) { local_audionode = this.getAudioNodeInOutputSlot(slot); - else local_audionode = this.audionode; + } else { + local_audionode = this.audionode; + } //get target audionode var target_audionode = null; - if (target_node.getAudioNodeInInputSlot) + if (target_node.getAudioNodeInInputSlot) { target_audionode = target_node.getAudioNodeInInputSlot( link_info.target_slot ); - else target_audionode = target_node.audionode; + } else { + target_audionode = target_node.audionode; + } //do the connection/disconnection - if (connected) LGAudio.connect(local_audionode, target_audionode); - else LGAudio.disconnect(local_audionode, target_audionode); + if (connected) { + LGAudio.connect(local_audionode, target_audionode); + } else { + LGAudio.disconnect(local_audionode, target_audionode); + } }; //this function helps creating wrappers to existing classes @@ -142,15 +170,23 @@ var old_func = class_object.prototype.onPropertyChanged; class_object.prototype.onPropertyChanged = function(name, value) { - if (old_func) old_func.call(this, name, value); + if (old_func) { + old_func.call(this, name, value); + } - if (!this.audionode) return; + if (!this.audionode) { + return; + } - if (this.audionode[name] === undefined) return; + if (this.audionode[name] === undefined) { + return; + } - if (this.audionode[name].value !== undefined) + if (this.audionode[name].value !== undefined) { this.audionode[name].value = value; - else this.audionode[name] = value; + } else { + this.audionode[name] = value; + } }; class_object.prototype.onConnectionsChange = @@ -162,11 +198,15 @@ LGAudio.loadSound = function(url, on_complete, on_error) { if (LGAudio.cached_audios[url] && url.indexOf("blob:") == -1) { - if (on_complete) on_complete(LGAudio.cached_audios[url]); + if (on_complete) { + on_complete(LGAudio.cached_audios[url]); + } return; } - if (LGAudio.onProcessAudioURL) url = LGAudio.onProcessAudioURL(url); + if (LGAudio.onProcessAudioURL) { + url = LGAudio.onProcessAudioURL(url); + } //load new sample var request = new XMLHttpRequest(); @@ -183,7 +223,9 @@ function(buffer) { console.log("AudioSource decoded"); LGAudio.cached_audios[url] = buffer; - if (on_complete) on_complete(buffer); + if (on_complete) { + on_complete(buffer); + } }, onError ); @@ -192,7 +234,9 @@ function onError(err) { console.log("Audio loading sample error:", err); - if (on_error) on_error(err); + if (on_error) { + on_error(err); + } } return request; @@ -226,20 +270,28 @@ this.audionode.gain.value = this.properties.gain; //debug - if (this.properties.src) this.loadSound(this.properties.src); + if (this.properties.src) { + this.loadSound(this.properties.src); + } } LGAudioSource["@src"] = { widget: "resource" }; LGAudioSource.supported_extensions = ["wav", "ogg", "mp3"]; LGAudioSource.prototype.onAdded = function(graph) { - if (graph.status === LGraph.STATUS_RUNNING) this.onStart(); + if (graph.status === LGraph.STATUS_RUNNING) { + this.onStart(); + } }; LGAudioSource.prototype.onStart = function() { - if (!this._audiobuffer) return; + if (!this._audiobuffer) { + return; + } - if (this.properties.autoplay) this.playBuffer(this._audiobuffer); + if (this.properties.autoplay) { + this.playBuffer(this._audiobuffer); + } }; LGAudioSource.prototype.onStop = function() { @@ -257,7 +309,9 @@ LGAudioSource.prototype.onRemoved = function() { this.stopAllSounds(); - if (this._dropped_url) URL.revokeObjectURL(this._url); + if (this._dropped_url) { + URL.revokeObjectURL(this._url); + } }; LGAudioSource.prototype.stopAllSounds = function() { @@ -281,41 +335,56 @@ }; LGAudioSource.prototype.onExecute = function() { - if (this.inputs) + if (this.inputs) { for (var i = 0; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null) continue; + if (input.link == null) { + continue; + } var v = this.getInputData(i); - if (v === undefined) continue; - if (input.name == "gain") this.audionode.gain.value = v; - else if (input.name == "playbackRate") { + if (v === undefined) { + continue; + } + if (input.name == "gain") { + this.audionode.gain.value = v; + } else if (input.name == "playbackRate") { this.properties.playbackRate = v; - for (var j = 0; j < this._audionodes.length; ++j) + for (var j = 0; j < this._audionodes.length; ++j) { this._audionodes[j].playbackRate.value = v; + } } } + } - if (this.outputs) + if (this.outputs) { for (var i = 0; i < this.outputs.length; ++i) { var output = this.outputs[i]; - if (output.name == "buffer" && this._audiobuffer) + if (output.name == "buffer" && this._audiobuffer) { this.setOutputData(i, this._audiobuffer); + } } + } }; LGAudioSource.prototype.onAction = function(event) { if (this._audiobuffer) { - if (event == "Play") this.playBuffer(this._audiobuffer); - else if (event == "Stop") this.stopAllSounds(); + if (event == "Play") { + this.playBuffer(this._audiobuffer); + } else if (event == "Stop") { + this.stopAllSounds(); + } } }; LGAudioSource.prototype.onPropertyChanged = function(name, value) { - if (name == "src") this.loadSound(value); - else if (name == "gain") this.audionode.gain.value = value; - else if (name == "playbackRate") { - for (var j = 0; j < this._audionodes.length; ++j) + if (name == "src") { + this.loadSound(value); + } else if (name == "gain") { + this.audionode.gain.value = value; + } else if (name == "playbackRate") { + for (var j = 0; j < this._audionodes.length; ++j) { this._audionodes[j].playbackRate.value = value; + } } }; @@ -339,7 +408,9 @@ that.trigger("ended"); //remove var index = that._audionodes.indexOf(audionode); - if (index != -1) that._audionodes.splice(index, 1); + if (index != -1) { + that._audionodes.splice(index, 1); + } }; if (!audionode.started) { @@ -361,7 +432,9 @@ this._audiobuffer = null; //points to the audiobuffer once the audio is loaded this._loading_audio = false; - if (!url) return; + if (!url) { + return; + } this._request = LGAudio.loadSound(url, inner); @@ -373,8 +446,9 @@ that._audiobuffer = buffer; that._loading_audio = false; //if is playing, then play it - if (that.graph && that.graph.status === LGraph.STATUS_RUNNING) - that.onStart(); //this controls the autoplay already + if (that.graph && that.graph.status === LGraph.STATUS_RUNNING) { + that.onStart(); + } //this controls the autoplay already } }; @@ -394,7 +468,9 @@ }; LGAudioSource.prototype.onDropFile = function(file) { - if (this._dropped_url) URL.revokeObjectURL(this._dropped_url); + if (this._dropped_url) { + URL.revokeObjectURL(this._dropped_url); + } var url = URL.createObjectURL(file); this.properties.src = url; this.loadSound(url); @@ -426,12 +502,15 @@ } LGAudioMediaSource.prototype.onAdded = function(graph) { - if (graph.status === LGraph.STATUS_RUNNING) this.onStart(); + if (graph.status === LGraph.STATUS_RUNNING) { + this.onStart(); + } }; LGAudioMediaSource.prototype.onStart = function() { - if (this._media_stream == null && !this._waiting_confirmation) + if (this._media_stream == null && !this._waiting_confirmation) { this.openStream(); + } }; LGAudioMediaSource.prototype.onStop = function() { @@ -454,7 +533,9 @@ } if (this._media_stream) { var tracks = this._media_stream.getTracks(); - if (tracks.length) tracks[0].stop(); + if (tracks.length) { + tracks[0].stop(); + } } }; @@ -487,8 +568,9 @@ //this._waiting_confirmation = false; //init context - if (this.audiosource_node) + if (this.audiosource_node) { this.audiosource_node.disconnect(this.audionode); + } var context = LGAudio.getAudioContext(); this.audiosource_node = context.createMediaStreamSource( localMediaStream @@ -499,27 +581,39 @@ }; LGAudioMediaSource.prototype.onExecute = function() { - if (this._media_stream == null && !this._waiting_confirmation) + if (this._media_stream == null && !this._waiting_confirmation) { this.openStream(); + } - if (this.inputs) + if (this.inputs) { for (var i = 0; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null) continue; + if (input.link == null) { + continue; + } var v = this.getInputData(i); - if (v === undefined) continue; - if (input.name == "gain") + if (v === undefined) { + continue; + } + if (input.name == "gain") { this.audionode.gain.value = this.properties.gain = v; + } } + } }; LGAudioMediaSource.prototype.onAction = function(event) { - if (event == "Play") this.audionode.gain.value = this.properties.gain; - else if (event == "Stop") this.audionode.gain.value = 0; + if (event == "Play") { + this.audionode.gain.value = this.properties.gain; + } else if (event == "Stop") { + this.audionode.gain.value = 0; + } }; LGAudioMediaSource.prototype.onPropertyChanged = function(name, value) { - if (name == "gain") this.audionode.gain.value = value; + if (name == "gain") { + this.audionode.gain.value = value; + } }; //Helps connect/disconnect AudioNodes when new connections are made in the node @@ -573,8 +667,9 @@ if (this.isOutputConnected(0)) { //send FFT var bufferLength = this.audionode.frequencyBinCount; - if (!this._freq_bin || this._freq_bin.length != bufferLength) + if (!this._freq_bin || this._freq_bin.length != bufferLength) { this._freq_bin = new Uint8Array(bufferLength); + } this.audionode.getByteFrequencyData(this._freq_bin); this.setOutputData(0, this._freq_bin); } @@ -583,8 +678,9 @@ if (this.isOutputConnected(1)) { //send Samples var bufferLength = this.audionode.frequencyBinCount; - if (!this._time_bin || this._time_bin.length != bufferLength) + if (!this._time_bin || this._time_bin.length != bufferLength) { this._time_bin = new Uint8Array(bufferLength); + } this.audionode.getByteTimeDomainData(this._time_bin); this.setOutputData(1, this._time_bin); } @@ -592,9 +688,13 @@ //properties for (var i = 1; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null) continue; + if (input.link == null) { + continue; + } var v = this.getInputData(i); - if (v !== undefined) this.audionode[input.name].value = v; + if (v !== undefined) { + this.audionode[input.name].value = v; + } } //time domain @@ -632,12 +732,16 @@ } LGAudioGain.prototype.onExecute = function() { - if (!this.inputs || !this.inputs.length) return; + if (!this.inputs || !this.inputs.length) { + return; + } for (var i = 1; i < this.inputs.length; ++i) { var input = this.inputs[i]; var v = this.getInputData(i); - if (v !== undefined) this.audionode[input.name].value = v; + if (v !== undefined) { + this.audionode[input.name].value = v; + } } }; @@ -662,16 +766,23 @@ LGAudio.createAudioNodeWrapper(LGAudioConvolver); LGAudioConvolver.prototype.onRemove = function() { - if (this._dropped_url) URL.revokeObjectURL(this._dropped_url); + if (this._dropped_url) { + URL.revokeObjectURL(this._dropped_url); + } }; LGAudioConvolver.prototype.onPropertyChanged = function(name, value) { - if (name == "impulse_src") this.loadImpulse(value); - else if (name == "normalize") this.audionode.normalize = value; + if (name == "impulse_src") { + this.loadImpulse(value); + } else if (name == "normalize") { + this.audionode.normalize = value; + } }; LGAudioConvolver.prototype.onDropFile = function(file) { - if (this._dropped_url) URL.revokeObjectURL(this._dropped_url); + if (this._dropped_url) { + URL.revokeObjectURL(this._dropped_url); + } this._dropped_url = URL.createObjectURL(file); this.properties.impulse_src = this._dropped_url; this.loadImpulse(this._dropped_url); @@ -689,7 +800,9 @@ this._impulse_buffer = null; this._loading_impulse = false; - if (!url) return; + if (!url) { + return; + } //load new sample this._request = LGAudio.loadSound(url, inner); @@ -727,12 +840,18 @@ LGAudio.createAudioNodeWrapper(LGAudioDynamicsCompressor); LGAudioDynamicsCompressor.prototype.onExecute = function() { - if (!this.inputs || !this.inputs.length) return; + if (!this.inputs || !this.inputs.length) { + return; + } for (var i = 1; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null) continue; + if (input.link == null) { + continue; + } var v = this.getInputData(i); - if (v !== undefined) this.audionode[input.name].value = v; + if (v !== undefined) { + this.audionode[input.name].value = v; + } } }; @@ -765,9 +884,13 @@ } LGAudioWaveShaper.prototype.onExecute = function() { - if (!this.inputs || !this.inputs.length) return; + if (!this.inputs || !this.inputs.length) { + return; + } var v = this.getInputData(1); - if (v === undefined) return; + if (v === undefined) { + return; + } this.audionode.curve = v; }; @@ -809,28 +932,43 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); } LGAudioMixer.prototype.getAudioNodeInInputSlot = function(slot) { - if (slot == 0) return this.audionode1; - else if (slot == 2) return this.audionode2; + if (slot == 0) { + return this.audionode1; + } else if (slot == 2) { + return this.audionode2; + } }; LGAudioMixer.prototype.onPropertyChanged = function(name, value) { - if (name == "gain1") this.audionode1.gain.value = value; - else if (name == "gain2") this.audionode2.gain.value = value; + if (name == "gain1") { + this.audionode1.gain.value = value; + } else if (name == "gain2") { + this.audionode2.gain.value = value; + } }; LGAudioMixer.prototype.onExecute = function() { - if (!this.inputs || !this.inputs.length) return; + if (!this.inputs || !this.inputs.length) { + return; + } for (var i = 1; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null || input.type == "audio") continue; + if (input.link == null || input.type == "audio") { + continue; + } var v = this.getInputData(i); - if (v === undefined) continue; + if (v === undefined) { + continue; + } - if (i == 1) this.audionode1.gain.value = v; - else if (i == 3) this.audionode2.gain.value = v; + if (i == 1) { + this.audionode1.gain.value = v; + } else if (i == 3) { + this.audionode2.gain.value = v; + } } }; @@ -915,7 +1053,9 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); LGAudioDelay.prototype.onExecute = function() { var v = this.getInputData(1); - if (v !== undefined) this.audionode.delayTime.value = v; + if (v !== undefined) { + this.audionode.delayTime.value = v; + } }; LGAudioDelay.title = "Delay"; @@ -951,13 +1091,19 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); } LGAudioBiquadFilter.prototype.onExecute = function() { - if (!this.inputs || !this.inputs.length) return; + if (!this.inputs || !this.inputs.length) { + return; + } for (var i = 1; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null) continue; + if (input.link == null) { + continue; + } var v = this.getInputData(i); - if (v !== undefined) this.audionode[input.name].value = v; + if (v !== undefined) { + this.audionode[input.name].value = v; + } } }; @@ -1014,13 +1160,19 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); }; LGAudioOscillatorNode.prototype.onExecute = function() { - if (!this.inputs || !this.inputs.length) return; + if (!this.inputs || !this.inputs.length) { + return; + } for (var i = 0; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == null) continue; + if (input.link == null) { + continue; + } var v = this.getInputData(i); - if (v !== undefined) this.audionode[input.name].value = v; + if (v !== undefined) { + this.audionode[input.name].value = v; + } } }; @@ -1057,12 +1209,16 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); LGAudioVisualization.prototype.onExecute = function() { this._last_buffer = this.getInputData(0); var v = this.getInputData(1); - if (v !== undefined) this.properties.mark = v; + if (v !== undefined) { + this.properties.mark = v; + } this.setDirtyCanvas(true, false); }; LGAudioVisualization.prototype.onDrawForeground = function(ctx) { - if (!this._last_buffer) return; + if (!this._last_buffer) { + return; + } var buffer = this._last_buffer; @@ -1095,7 +1251,9 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); var samplerate = LGAudio.getAudioContext().sampleRate; var binfreq = samplerate / buffer.length; var x = (2 * (this.properties.mark / binfreq)) / delta; - if (x >= this.size[0]) x = this.size[0] - 1; + if (x >= this.size[0]) { + x = this.size[0] - 1; + } ctx.strokeStyle = "red"; ctx.beginPath(); ctx.moveTo(x, h); @@ -1121,20 +1279,26 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); LGAudioBandSignal.prototype.onExecute = function() { this._freqs = this.getInputData(0); - if (!this._freqs) return; + if (!this._freqs) { + return; + } var band = this.properties.band; var v = this.getInputData(1); - if (v !== undefined) band = v; + if (v !== undefined) { + band = v; + } var samplerate = LGAudio.getAudioContext().sampleRate; var binfreq = samplerate / this._freqs.length; var index = 2 * (band / binfreq); var v = 0; - if (index < 0) v = this._freqs[0]; - if (index >= this._freqs.length) + if (index < 0) { + v = this._freqs[0]; + } + if (index >= this._freqs.length) { v = this._freqs[this._freqs.length - 1]; - else { + } else { var pos = index | 0; var v0 = this._freqs[pos]; var v1 = this._freqs[pos + 1]; @@ -1168,8 +1332,9 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); //create node var ctx = LGAudio.getAudioContext(); - if (ctx.createScriptProcessor) + if (ctx.createScriptProcessor) { this.audionode = ctx.createScriptProcessor(4096, 1, 1); + } //buffer size, input channels, output channels else { console.warn("ScriptProcessorNode deprecated"); @@ -1177,8 +1342,9 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); } this.processCode(); - if (!LGAudioScript._bypass_function) + if (!LGAudioScript._bypass_function) { LGAudioScript._bypass_function = this.audionode.onaudioprocess; + } //slots this.addInput("in", "audio"); @@ -1186,8 +1352,9 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); } LGAudioScript.prototype.onAdded = function(graph) { - if (graph.status == LGraph.STATUS_RUNNING) + if (graph.status == LGraph.STATUS_RUNNING) { this.audionode.onaudioprocess = this._callback; + } }; LGAudioScript["@code"] = { widget: "code" }; @@ -1233,8 +1400,9 @@ LiteGraph.registerNodeType("audio/waveShaper", LGAudioWaveShaper); if (name == "code") { this.properties.code = value; this.processCode(); - if (this.graph && this.graph.status == LGraph.STATUS_RUNNING) + if (this.graph && this.graph.status == LGraph.STATUS_RUNNING) { this.audionode.onaudioprocess = this._callback; + } } }; diff --git a/src/nodes/base.js b/src/nodes/base.js index aa4f8e6c8..8f113bde9 100755 --- a/src/nodes/base.js +++ b/src/nodes/base.js @@ -56,7 +56,9 @@ }; Subgraph.prototype.onDrawTitle = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } ctx.fillStyle = "#555"; var w = LiteGraph.NODE_TITLE_HEIGHT; @@ -96,89 +98,111 @@ Subgraph.prototype.onExecute = function() { this.enabled = this.getInputOrProperty("enabled"); - if (!this.enabled) return; + if (!this.enabled) { + return; + } //send inputs to subgraph global inputs - if (this.inputs) + if (this.inputs) { for (var i = 0; i < this.inputs.length; i++) { var input = this.inputs[i]; var value = this.getInputData(i); this.subgraph.setInputData(input.name, value); } + } //execute this.subgraph.runStep(); //send subgraph global outputs to outputs - if (this.outputs) + if (this.outputs) { for (var i = 0; i < this.outputs.length; i++) { var output = this.outputs[i]; var value = this.subgraph.getOutputData(output.name); this.setOutputData(i, value); } + } }; Subgraph.prototype.sendEventToAllNodes = function(eventname, param, mode) { - if (this.enabled) + if (this.enabled) { this.subgraph.sendEventToAllNodes(eventname, param, mode); + } }; //**** INPUTS *********************************** Subgraph.prototype.onSubgraphTrigger = function(event, param) { var slot = this.findOutputSlot(event); - if (slot != -1) this.triggerSlot(slot); + if (slot != -1) { + this.triggerSlot(slot); + } }; Subgraph.prototype.onSubgraphNewInput = function(name, type) { var slot = this.findInputSlot(name); - if (slot == -1) + if (slot == -1) { //add input to the node this.addInput(name, type); + } }; Subgraph.prototype.onSubgraphRenamedInput = function(oldname, name) { var slot = this.findInputSlot(oldname); - if (slot == -1) return; + if (slot == -1) { + return; + } var info = this.getInputInfo(slot); info.name = name; }; Subgraph.prototype.onSubgraphTypeChangeInput = function(name, type) { var slot = this.findInputSlot(name); - if (slot == -1) return; + if (slot == -1) { + return; + } var info = this.getInputInfo(slot); info.type = type; }; Subgraph.prototype.onSubgraphRemovedInput = function(name) { var slot = this.findInputSlot(name); - if (slot == -1) return; + if (slot == -1) { + return; + } this.removeInput(slot); }; //**** OUTPUTS *********************************** Subgraph.prototype.onSubgraphNewOutput = function(name, type) { var slot = this.findOutputSlot(name); - if (slot == -1) this.addOutput(name, type); + if (slot == -1) { + this.addOutput(name, type); + } }; Subgraph.prototype.onSubgraphRenamedOutput = function(oldname, name) { var slot = this.findOutputSlot(oldname); - if (slot == -1) return; + if (slot == -1) { + return; + } var info = this.getOutputInfo(slot); info.name = name; }; Subgraph.prototype.onSubgraphTypeChangeOutput = function(name, type) { var slot = this.findOutputSlot(name); - if (slot == -1) return; + if (slot == -1) { + return; + } var info = this.getOutputInfo(slot); info.type = type; }; Subgraph.prototype.onSubgraphRemovedOutput = function(name) { var slot = this.findInputSlot(name); - if (slot == -1) return; + if (slot == -1) { + return; + } this.removeOutput(slot); }; // ***************************************************** @@ -232,12 +256,15 @@ return that.name_in_graph; }, set: function(v) { - if (v == "" || v == that.name_in_graph || v == "enabled") + if (v == "" || v == that.name_in_graph || v == "enabled") { return; - if (that.name_in_graph) + } + if (that.name_in_graph) { //already added that.graph.renameInput(that.name_in_graph, v); - else that.graph.addInput(v, that.properties.type); + } else { + that.graph.addInput(v, that.properties.type); + } that.name_widget.value = v; that.name_in_graph = v; }, @@ -249,14 +276,17 @@ return that.outputs[0].type; }, set: function(v) { - if (v == "event") v = LiteGraph.EVENT; + if (v == "event") { + v = LiteGraph.EVENT; + } that.outputs[0].type = v; - if (that.name_in_graph) + if (that.name_in_graph) { //already added that.graph.changeInputType( that.name_in_graph, that.outputs[0].type ); + } that.type_widget.value = v; }, enumerable: true @@ -267,7 +297,9 @@ "Name", this.properties.name, function(v) { - if (!v) return; + if (!v) { + return; + } that.properties.name = v; } ); @@ -289,12 +321,16 @@ GraphInput.desc = "Input of the graph"; GraphInput.prototype.getTitle = function() { - if (this.flags.collapsed) return this.properties.name; + if (this.flags.collapsed) { + return this.properties.name; + } return this.title; }; GraphInput.prototype.onAction = function(action, param) { - if (this.properties.type == LiteGraph.EVENT) this.triggerSlot(0, param); + if (this.properties.type == LiteGraph.EVENT) { + this.triggerSlot(0, param); + } }; GraphInput.prototype.onExecute = function() { @@ -302,14 +338,18 @@ //read from global input var data = this.graph.inputs[name]; - if (!data) return; + if (!data) { + return; + } //put through output this.setOutputData(0, data.value); }; GraphInput.prototype.onRemoved = function() { - if (this.name_in_graph) this.graph.removeInput(this.name_in_graph); + if (this.name_in_graph) { + this.graph.removeInput(this.name_in_graph); + } }; LiteGraph.GraphInput = GraphInput; @@ -328,11 +368,15 @@ return that.name_in_graph; }, set: function(v) { - if (v == "" || v == that.name_in_graph) return; - if (that.name_in_graph) + if (v == "" || v == that.name_in_graph) { + return; + } + if (that.name_in_graph) { //already added that.graph.renameOutput(that.name_in_graph, v); - else that.graph.addOutput(v, that.properties.type); + } else { + that.graph.addOutput(v, that.properties.type); + } that.name_widget.value = v; that.name_in_graph = v; }, @@ -344,14 +388,17 @@ return that.inputs[0].type; }, set: function(v) { - if (v == "action" || v == "event") v = LiteGraph.ACTION; + if (v == "action" || v == "event") { + v = LiteGraph.ACTION; + } that.inputs[0].type = v; - if (that.name_in_graph) + if (that.name_in_graph) { //already added that.graph.changeOutputType( that.name_in_graph, that.inputs[0].type ); + } that.type_widget.value = v || ""; }, enumerable: true @@ -362,7 +409,9 @@ "Name", this.properties.name, function(v) { - if (!v) return; + if (!v) { + return; + } that.properties.name = v; } ); @@ -389,16 +438,21 @@ }; GraphOutput.prototype.onAction = function(action, param) { - if (this.properties.type == LiteGraph.ACTION) + if (this.properties.type == LiteGraph.ACTION) { this.graph.trigger(this.properties.name, param); + } }; GraphOutput.prototype.onRemoved = function() { - if (this.name_in_graph) this.graph.removeOutput(this.name_in_graph); + if (this.name_in_graph) { + this.graph.removeOutput(this.name_in_graph); + } }; GraphOutput.prototype.getTitle = function() { - if (this.flags.collapsed) return this.properties.name; + if (this.flags.collapsed) { + return this.properties.name; + } return this.title; }; @@ -419,7 +473,9 @@ }; ConstantNumber.prototype.getTitle = function() { - if (this.flags.collapsed) return this.properties.value; + if (this.flags.collapsed) { + return this.properties.value; + } return this.title; }; @@ -490,7 +546,9 @@ ConstantData.prototype.onPropertyChanged = function(name, value) { this.widget.value = value; - if (value == null || value == "") return; + if (value == null || value == "") { + return; + } try { this._value = JSON.parse(value); @@ -530,7 +588,9 @@ }; ObjectProperty.prototype.getTitle = function() { - if (this.flags.collapsed) return "in." + this.properties.value; + if (this.flags.collapsed) { + return "in." + this.properties.value; + } return this.title; }; @@ -540,7 +600,9 @@ ObjectProperty.prototype.onExecute = function() { var data = this.getInputData(0); - if (data != null) this.setOutputData(0, data[this.properties.value]); + if (data != null) { + this.setOutputData(0, data[this.properties.value]); + } }; LiteGraph.registerNodeType("basic/object_property", ObjectProperty); @@ -556,24 +618,33 @@ Watch.desc = "Show value of input"; Watch.prototype.onExecute = function() { - if (this.inputs[0]) this.value = this.getInputData(0); + if (this.inputs[0]) { + this.value = this.getInputData(0); + } }; Watch.prototype.getTitle = function() { - if (this.flags.collapsed) return this.inputs[0].label; + if (this.flags.collapsed) { + return this.inputs[0].label; + } return this.title; }; Watch.toString = function(o) { - if (o == null) return "null"; - else if (o.constructor === Number) return o.toFixed(3); - else if (o.constructor === Array) { + if (o == null) { + return "null"; + } else if (o.constructor === Number) { + return o.toFixed(3); + } else if (o.constructor === Array) { var str = "["; - for (var i = 0; i < o.length; ++i) + for (var i = 0; i < o.length; ++i) { str += Watch.toString(o[i]) + (i + 1 != o.length ? "," : ""); + } str += "]"; return str; - } else return String(o); + } else { + return String(o); + } }; Watch.prototype.onDrawBackground = function(ctx) { @@ -612,14 +683,20 @@ Console.desc = "Show value inside the console"; Console.prototype.onAction = function(action, param) { - if (action == "log") console.log(param); - else if (action == "warn") console.warn(param); - else if (action == "error") console.error(param); + if (action == "log") { + console.log(param); + } else if (action == "warn") { + console.warn(param); + } else if (action == "error") { + console.error(param); + } }; Console.prototype.onExecute = function() { var msg = this.getInputData(1); - if (msg !== null) this.properties.msg = msg; + if (msg !== null) { + this.properties.msg = msg; + } console.log(msg); }; @@ -676,7 +753,9 @@ } NodeScript.prototype.onConfigure = function(o) { - if (o.properties.onExecute) this.compileCode(o.properties.onExecute); + if (o.properties.onExecute) { + this.compileCode(o.properties.onExecute); + } }; NodeScript.title = "Script"; @@ -694,8 +773,9 @@ NodeScript.prototype.compileCode = function(code) { this._func = null; - if (code.length > 100) console.warn("Script too long, max 100 chars"); - else { + if (code.length > 100) { + console.warn("Script too long, max 100 chars"); + } else { var code_low = code.toLowerCase(); var forbidden_words = [ "script", @@ -705,11 +785,12 @@ "nodescript", "function" ]; //bad security solution - for (var i = 0; i < forbidden_words.length; ++i) + for (var i = 0; i < forbidden_words.length; ++i) { if (code_low.indexOf(forbidden_words[i]) != -1) { console.warn("invalid script"); return; } + } try { this._func = new Function("A", "B", "C", "DATA", "node", code); } catch (err) { @@ -720,7 +801,9 @@ }; NodeScript.prototype.onExecute = function() { - if (!this._func) return; + if (!this._func) { + return; + } try { var A = this.getInputData(0); @@ -738,4 +821,4 @@ }; LiteGraph.registerNodeType("basic/script", NodeScript); -})(this); \ No newline at end of file +})(this); diff --git a/src/nodes/events.js b/src/nodes/events.js index 4ebc6680c..0f3156e94 100644 --- a/src/nodes/events.js +++ b/src/nodes/events.js @@ -43,9 +43,11 @@ }; Sequencer.prototype.onAction = function(action, param) { - if (this.outputs) - for (var i = 0; i < this.outputs.length; ++i) + if (this.outputs) { + for (var i = 0; i < this.outputs.length; ++i) { this.triggerSlot(i, param); + } + } }; LiteGraph.registerNodeType("events/sequencer", Sequencer); @@ -66,20 +68,26 @@ FilterEvent.desc = "Blocks events that do not match the filter"; FilterEvent.prototype.onAction = function(action, param) { - if (param == null) return; - - if (this.properties.equal_to && this.properties.equal_to != param) + if (param == null) { return; + } + + if (this.properties.equal_to && this.properties.equal_to != param) { + return; + } if (this.properties.has_property) { var prop = param[this.properties.has_property]; - if (prop == null) return; + if (prop == null) { + return; + } if ( this.properties.property_equal_to && this.properties.property_equal_to != prop - ) + ) { return; + } } this.triggerSlot(0, param); @@ -101,20 +109,30 @@ EventCounter.desc = "Counts events"; EventCounter.prototype.getTitle = function() { - if (this.flags.collapsed) return String(this.num); + if (this.flags.collapsed) { + return String(this.num); + } return this.title; }; EventCounter.prototype.onAction = function(action, param) { var v = this.num; - if (action == "inc") this.num += 1; - else if (action == "dec") this.num -= 1; - else if (action == "reset") this.num = 0; - if (this.num != v) this.trigger("change", this.num); + if (action == "inc") { + this.num += 1; + } else if (action == "dec") { + this.num -= 1; + } else if (action == "reset") { + this.num = 0; + } + if (this.num != v) { + this.trigger("change", this.num); + } }; EventCounter.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } ctx.fillStyle = "#AAA"; ctx.font = "20px Arial"; ctx.textAlign = "center"; @@ -142,20 +160,26 @@ DelayEvent.prototype.onAction = function(action, param) { var time = this.properties.time_in_ms; - if (time <= 0) this.trigger(null, param); - else this._pending.push([time, param]); + if (time <= 0) { + this.trigger(null, param); + } else { + this._pending.push([time, param]); + } }; DelayEvent.prototype.onExecute = function() { var dt = this.graph.elapsed_time * 1000; //in ms - if (this.isInputConnected(1)) + if (this.isInputConnected(1)) { this.properties.time_in_ms = this.getInputData(1); + } for (var i = 0; i < this._pending.length; ++i) { var action = this._pending[i]; action[0] -= dt; - if (action[0] > 0) continue; + if (action[0] > 0) { + continue; + } //remove this._pending.splice(i, 1); @@ -218,16 +242,18 @@ !trigger && (this.time < this.last_interval || isNaN(this.last_interval)) ) { - if (this.inputs && this.inputs.length > 1 && this.inputs[1]) + if (this.inputs && this.inputs.length > 1 && this.inputs[1]) { this.setOutputData(1, false); + } return; } this.triggered = true; this.time = this.time % this.last_interval; this.trigger("on_tick", this.properties.event); - if (this.inputs && this.inputs.length > 1 && this.inputs[1]) + if (this.inputs && this.inputs.length > 1 && this.inputs[1]) { this.setOutputData(1, true); + } }; TimerEvent.prototype.onGetInputs = function() { diff --git a/src/nodes/glfx.js b/src/nodes/glfx.js index 1f3529641..681623881 100755 --- a/src/nodes/glfx.js +++ b/src/nodes/glfx.js @@ -45,7 +45,9 @@ return; } - if (!tex) return; + if (!tex) { + return; + } this._tex = LGraphTexture.getTargetTexture( tex, @@ -272,10 +274,14 @@ return; } - if (!blurred_tex) blurred_tex = tex; + if (!blurred_tex) { + blurred_tex = tex; + } var shape_tex = LGraphTexture.getTexture(this.properties.shape); - if (!shape_tex) return; + if (!shape_tex) { + return; + } var threshold = this.properties.threshold; if (this.isInputConnected(3)) { @@ -284,36 +290,40 @@ } var precision = gl.UNSIGNED_BYTE; - if (this.properties.high_precision) + if (this.properties.high_precision) { precision = gl.half_float_ext ? gl.HALF_FLOAT_OES : gl.FLOAT; + } if ( !this._temp_texture || this._temp_texture.type != precision || this._temp_texture.width != tex.width || this._temp_texture.height != tex.height - ) + ) { this._temp_texture = new GL.Texture(tex.width, tex.height, { type: precision, format: gl.RGBA, filter: gl.LINEAR }); + } //iterations var size = this.properties.size; var first_shader = LGraphFXBokeh._first_shader; - if (!first_shader) + if (!first_shader) { first_shader = LGraphFXBokeh._first_shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphFXBokeh._first_pixel_shader ); + } var second_shader = LGraphFXBokeh._second_shader; - if (!second_shader) + if (!second_shader) { second_shader = LGraphFXBokeh._second_shader = new GL.Shader( LGraphFXBokeh._second_vertex_shader, LGraphFXBokeh._second_pixel_shader ); + } var points_mesh = this._points_mesh; if ( @@ -321,8 +331,9 @@ points_mesh._width != tex.width || points_mesh._height != tex.height || points_mesh._spacing != 2 - ) + ) { points_mesh = this.createPointsMesh(tex.width, tex.height, 2); + } var screen_mesh = Mesh.getScreenQuad(); @@ -506,7 +517,9 @@ LGraphFXGeneric.shaders = {}; LGraphFXGeneric.prototype.onExecute = function() { - if (!this.isOutputConnected(0)) return; //saves work + if (!this.isOutputConnected(0)) { + return; + } //saves work var tex = this.getInputData(0); if (this.properties.precision === LGraphTexture.PASS_THROUGH) { @@ -514,7 +527,9 @@ return; } - if (!tex) return; + if (!tex) { + return; + } this._tex = LGraphTexture.getTargetTexture( tex, @@ -539,7 +554,9 @@ var shader = LGraphFXGeneric.shaders[fx]; if (!shader) { var pixel_shader_code = LGraphFXGeneric["pixel_shader_" + fx]; - if (!pixel_shader_code) return; + if (!pixel_shader_code) { + return; + } shader = LGraphFXGeneric.shaders[fx] = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, @@ -552,19 +569,25 @@ var mesh = Mesh.getScreenQuad(); var camera = global.LS ? LS.Renderer._current_camera : null; var camera_planes; - if (camera) + if (camera) { camera_planes = [ LS.Renderer._current_camera.near, LS.Renderer._current_camera.far ]; - else camera_planes = [1, 100]; + } else { + camera_planes = [1, 100]; + } var noise = null; - if (fx == "noise") noise = LGraphTexture.getNoiseTexture(); + if (fx == "noise") { + noise = LGraphTexture.getNoiseTexture(); + } this._tex.drawTo(function() { tex.bind(0); - if (fx == "noise") noise.bind(1); + if (fx == "noise") { + noise.bind(1); + } shader .uniforms({ @@ -679,11 +702,12 @@ precision: LGraphTexture.DEFAULT }; - if (!LGraphFXVigneting._shader) + if (!LGraphFXVigneting._shader) { LGraphFXVigneting._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphFXVigneting.pixel_shader ); + } } LGraphFXVigneting.title = "Vigneting"; @@ -701,7 +725,9 @@ return; } - if (!tex) return; + if (!tex) { + return; + } this._tex = LGraphTexture.getTargetTexture( tex, diff --git a/src/nodes/gltextures.js b/src/nodes/gltextures.js index a3aca662b..a7d634b34 100755 --- a/src/nodes/gltextures.js +++ b/src/nodes/gltextures.js @@ -43,7 +43,7 @@ low: LGraphTexture.LOW, high: LGraphTexture.HIGH, reuse: LGraphTexture.REUSE, - "default": LGraphTexture.DEFAULT + default: LGraphTexture.DEFAULT }; //returns the container where all the loaded textures are stored (overwrite if you have a Resources Manager) @@ -56,9 +56,10 @@ options = options || {}; var url = name; if (url.substr(0, 7) == "http://") { - if (LiteGraph.proxy) + if (LiteGraph.proxy) { //proxy external files url = LiteGraph.proxy + url.substr(7); + } } var container = LGraphTexture.getTexturesContainer(); @@ -69,19 +70,23 @@ LGraphTexture.getTexture = function(name) { var container = this.getTexturesContainer(); - if (!container) + if (!container) { throw "Cannot load texture, container of textures not found"; + } var tex = container[name]; - if (!tex && name && name[0] != ":") return this.loadTexture(name); + if (!tex && name && name[0] != ":") { + return this.loadTexture(name); + } return tex; }; //used to compute the appropiate output texture LGraphTexture.getTargetTexture = function(origin, target, mode) { - if (!origin) + if (!origin) { throw "LGraphTexture.getTargetTexture expects a reference texture"; + } var tex_type = null; @@ -93,2751 +98,2996 @@ tex_type = gl.HIGH_PRECISION_FORMAT; break; case LGraphTexture.REUSE: - return origin; - break; - case LGraphTexture.COPY: - default: - tex_type = origin ? origin.type : gl.UNSIGNED_BYTE; - break; - } - - if ( - !target || - target.width != origin.width || - target.height != origin.height || - target.type != tex_type - ) - target = new GL.Texture(origin.width, origin.height, { - type: tex_type, - format: gl.RGBA, - filter: gl.LINEAR - }); - - return target; - }; - - LGraphTexture.getTextureType = function(precision, ref_texture) { - var type = ref_texture ? ref_texture.type : gl.UNSIGNED_BYTE; - switch (precision) { - case LGraphTexture.HIGH: - type = gl.HIGH_PRECISION_FORMAT; - break; - case LGraphTexture.LOW: - type = gl.UNSIGNED_BYTE; - break; - //no default - } - return type; - }; - - LGraphTexture.getWhiteTexture = function() { - if (this._white_texture) return this._white_texture; - var texture = (this._white_texture = GL.Texture.fromMemory( - 1, - 1, - [255, 255, 255, 255], - { format: gl.RGBA, wrap: gl.REPEAT, filter: gl.NEAREST } - )); - return texture; - }; - - LGraphTexture.getNoiseTexture = function() { - if (this._noise_texture) return this._noise_texture; - - var noise = new Uint8Array(512 * 512 * 4); - for (var i = 0; i < 512 * 512 * 4; ++i) - noise[i] = Math.random() * 255; - - var texture = GL.Texture.fromMemory(512, 512, noise, { - format: gl.RGBA, - wrap: gl.REPEAT, - filter: gl.NEAREST - }); - this._noise_texture = texture; - return texture; - }; - - LGraphTexture.prototype.onDropFile = function(data, filename, file) { - if (!data) { - this._drop_texture = null; - this.properties.name = ""; - } else { - var texture = null; - if (typeof data == "string") texture = GL.Texture.fromURL(data); - else if (filename.toLowerCase().indexOf(".dds") != -1) - texture = GL.Texture.fromDDSInMemory(data); - else { - var blob = new Blob([file]); - var url = URL.createObjectURL(blob); - texture = GL.Texture.fromURL(url); - } - - this._drop_texture = texture; - this.properties.name = filename; - } - }; - - LGraphTexture.prototype.getExtraMenuOptions = function(graphcanvas) { - var that = this; - if (!this._drop_texture) return; - return [ - { - content: "Clear", - callback: function() { - that._drop_texture = null; - that.properties.name = ""; - } - } - ]; - }; - - LGraphTexture.prototype.onExecute = function() { - var tex = null; - if (this.isOutputConnected(1)) tex = this.getInputData(0); - - if (!tex && this._drop_texture) tex = this._drop_texture; - - if (!tex && this.properties.name) - tex = LGraphTexture.getTexture(this.properties.name); - - if (!tex) return; - - this._last_tex = tex; - - if (this.properties.filter === false) - tex.setParameter(gl.TEXTURE_MAG_FILTER, gl.NEAREST); - else tex.setParameter(gl.TEXTURE_MAG_FILTER, gl.LINEAR); - - this.setOutputData(0, tex); - - for (var i = 1; i < this.outputs.length; i++) { - var output = this.outputs[i]; - if (!output) continue; - var v = null; - if (output.name == "width") v = tex.width; - else if (output.name == "height") v = tex.height; - else if (output.name == "aspect") v = tex.width / tex.height; - this.setOutputData(i, v); - } - }; - - LGraphTexture.prototype.onResourceRenamed = function( - old_name, - new_name - ) { - if (this.properties.name == old_name) - this.properties.name = new_name; - }; - - LGraphTexture.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed || this.size[1] <= 20) return; - - if (this._drop_texture && ctx.webgl) { - ctx.drawImage( - this._drop_texture, - 0, - 0, - this.size[0], - this.size[1] - ); - //this._drop_texture.renderQuad(this.pos[0],this.pos[1],this.size[0],this.size[1]); - return; - } - - //Different texture? then get it from the GPU - if (this._last_preview_tex != this._last_tex) { - if (ctx.webgl) { - this._canvas = this._last_tex; - } else { - var tex_canvas = LGraphTexture.generateLowResTexturePreview( - this._last_tex - ); - if (!tex_canvas) return; - - this._last_preview_tex = this._last_tex; - this._canvas = cloneCanvas(tex_canvas); - } - } - - if (!this._canvas) return; - - //render to graph canvas - ctx.save(); - if (!ctx.webgl) { - //reverse image - ctx.translate(0, this.size[1]); - ctx.scale(1, -1); - } - ctx.drawImage(this._canvas, 0, 0, this.size[0], this.size[1]); - ctx.restore(); - }; - - //very slow, used at your own risk - LGraphTexture.generateLowResTexturePreview = function(tex) { - if (!tex) return null; - - var size = LGraphTexture.image_preview_size; - var temp_tex = tex; - - if (tex.format == gl.DEPTH_COMPONENT) return null; //cannot generate from depth - - //Generate low-level version in the GPU to speed up - if (tex.width > size || tex.height > size) { - temp_tex = this._preview_temp_tex; - if (!this._preview_temp_tex) { - temp_tex = new GL.Texture(size, size, { - minFilter: gl.NEAREST - }); - this._preview_temp_tex = temp_tex; - } - - //copy - tex.copyTo(temp_tex); - tex = temp_tex; - } - - //create intermediate canvas with lowquality version - var tex_canvas = this._preview_canvas; - if (!tex_canvas) { - tex_canvas = createCanvas(size, size); - this._preview_canvas = tex_canvas; - } - - if (temp_tex) temp_tex.toCanvas(tex_canvas); - return tex_canvas; - }; - - LGraphTexture.prototype.getResources = function(res) { - res[this.properties.name] = GL.Texture; - return res; - }; - - LGraphTexture.prototype.onGetInputs = function() { - return [["in", "Texture"]]; - }; - - LGraphTexture.prototype.onGetOutputs = function() { - return [ - ["width", "number"], - ["height", "number"], - ["aspect", "number"] - ]; - }; - - LiteGraph.registerNodeType("texture/texture", LGraphTexture); - - //************************** - function LGraphTexturePreview() { - this.addInput("Texture", "Texture"); - this.properties = { flipY: false }; - this.size = [ - LGraphTexture.image_preview_size, - LGraphTexture.image_preview_size - ]; - } - - LGraphTexturePreview.title = "Preview"; - LGraphTexturePreview.desc = "Show a texture in the graph canvas"; - LGraphTexturePreview.allow_preview = false; - - LGraphTexturePreview.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; - - if (!ctx.webgl && !LGraphTexturePreview.allow_preview) return; //not working well - - var tex = this.getInputData(0); - if (!tex) return; - - var tex_canvas = null; - - if (!tex.handle && ctx.webgl) tex_canvas = tex; - else tex_canvas = LGraphTexture.generateLowResTexturePreview(tex); - - //render to graph canvas - ctx.save(); - if (this.properties.flipY) { - ctx.translate(0, this.size[1]); - ctx.scale(1, -1); - } - ctx.drawImage(tex_canvas, 0, 0, this.size[0], this.size[1]); - ctx.restore(); - }; - - LiteGraph.registerNodeType("texture/preview", LGraphTexturePreview); - - //************************************** - - function LGraphTextureSave() { - 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 tex = this.getInputData(0); - if (!tex) return; - - if (this.properties.name) { - //for cases where we want to perform something when storing it - if (LGraphTexture.storeTexture) - LGraphTexture.storeTexture(this.properties.name, tex); - else { - var container = LGraphTexture.getTexturesContainer(); - container[this.properties.name] = tex; - } - } - - this.setOutputData(0, tex); - }; - - LiteGraph.registerNodeType("texture/save", LGraphTextureSave); - - //**************************************************** - - function LGraphTextureOperation() { - this.addInput("Texture", "Texture"); - this.addInput("TextureB", "Texture"); - this.addInput("value", "number"); - this.addOutput("Texture", "Texture"); - this.help = - "pixelcode must be vec3\ - uvcode must be vec2, is optional\ - uv: tex. coordscolor: texturecolorB: textureBtime: scene timevalue: 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( - graphcanvas - ) { - var that = this; - var txt = !that.properties.show ? "Show Texture" : "Hide Texture"; - return [ - { - content: txt, - callback: function() { - that.properties.show = !that.properties.show; - } - } - ]; - }; - - LGraphTextureOperation.prototype.onDrawBackground = function(ctx) { - if ( - this.flags.collapsed || - this.size[1] <= 20 || - !this.properties.show - ) - return; - - if (!this._tex) return; - - //only works if using a webgl renderer - if (this._tex.gl != ctx) return; - - //render to graph canvas - ctx.save(); - ctx.drawImage(this._tex, 0, 0, this.size[0], this.size[1]); - ctx.restore(); - }; - - LGraphTextureOperation.prototype.onExecute = function() { - var tex = this.getInputData(0); - - if (!this.isOutputConnected(0)) return; //saves work - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, tex); - return; - } - - var texB = this.getInputData(1); - - if (!this.properties.uvcode && !this.properties.pixelcode) return; - - var width = 512; - var height = 512; - if (tex) { - width = tex.width; - height = tex.height; - } else if (texB) { - width = texB.width; - height = texB.height; - } - - var type = LGraphTexture.getTextureType( - this.properties.precision, - tex - ); - - if (!tex && !this._tex) - this._tex = new GL.Texture(width, height, { - type: type, - format: gl.RGBA, - filter: gl.LINEAR - }); - else - this._tex = LGraphTexture.getTargetTexture( - tex || this._tex, - this._tex, - this.properties.precision - ); - - var uvcode = ""; - if (this.properties.uvcode) { - uvcode = "uv = " + this.properties.uvcode; - if (this.properties.uvcode.indexOf(";") != -1) - //there are line breaks, means multiline code - uvcode = this.properties.uvcode; - } - - var pixelcode = ""; - if (this.properties.pixelcode) { - pixelcode = "result = " + this.properties.pixelcode; - if (this.properties.pixelcode.indexOf(";") != -1) - //there are line breaks, means multiline code - pixelcode = this.properties.pixelcode; - } - - var shader = this._shader; - - if (!shader || this._shader_code != uvcode + "|" + pixelcode) { - try { - this._shader = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureOperation.pixel_shader, - { UV_CODE: uvcode, PIXEL_CODE: pixelcode } - ); - this.boxcolor = "#00FF00"; - } catch (err) { - console.log("Error compiling shader: ", err); - this.boxcolor = "#FF0000"; - return; - } - this.boxcolor = "#FF0000"; - - this._shader_code = uvcode + "|" + pixelcode; - shader = this._shader; - } - - if (!shader) { - this.boxcolor = "red"; - return; - } else this.boxcolor = "green"; - - var value = this.getInputData(2); - if (value != null) this.properties.value = value; - else value = parseFloat(this.properties.value); - - var time = this.graph.getTime(); - - this._tex.drawTo(function() { - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.disable(gl.BLEND); - if (tex) tex.bind(0); - if (texB) texB.bind(1); - var mesh = Mesh.getScreenQuad(); - shader - .uniforms({ - u_texture: 0, - u_textureB: 1, - value: value, - texSize: [width, height], - time: time - }) - .draw(mesh); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureOperation.pixel_shader = - "precision highp float;\n\ - \n\ - uniform sampler2D u_texture;\n\ - uniform sampler2D u_textureB;\n\ - varying vec2 v_coord;\n\ - uniform vec2 texSize;\n\ - uniform float time;\n\ - uniform float value;\n\ - \n\ - void main() {\n\ - vec2 uv = v_coord;\n\ - UV_CODE;\n\ - vec4 color4 = texture2D(u_texture, uv);\n\ - vec3 color = color4.rgb;\n\ - vec4 color4B = texture2D(u_textureB, uv);\n\ - vec3 colorB = color4B.rgb;\n\ - vec3 result = color;\n\ - float alpha = 1.0;\n\ - PIXEL_CODE;\n\ - gl_FragColor = vec4(result, alpha);\n\ - }\n\ - "; - - LiteGraph.registerNodeType("texture/operation", LGraphTextureOperation); - - //**************************************************** - - function LGraphTextureShader() { - this.addOutput("out", "Texture"); - this.properties = { - code: "", - width: 512, - height: 512, - precision: LGraphTexture.DEFAULT - }; - - this.properties.code = - "\nvoid main() {\n vec2 uv = v_coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n"; - this._uniforms = { in_texture: 0, texSize: vec2.create(), time: 0 }; - } - - LGraphTextureShader.title = "Shader"; - LGraphTextureShader.desc = "Texture shader"; - LGraphTextureShader.widgets_info = { - code: { type: "code" }, - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureShader.prototype.onPropertyChanged = function( - name, - value - ) { - if (name != "code") return; - - var shader = this.getShader(); - if (!shader) return; - - //update connections - var uniforms = shader.uniformInfo; - - //remove deprecated slots - if (this.inputs) { - var already = {}; - for (var i = 0; i < this.inputs.length; ++i) { - var info = this.getInputInfo(i); - if (!info) continue; - - if (uniforms[info.name] && !already[info.name]) { - already[info.name] = true; - continue; - } - this.removeInput(i); - i--; - } - } - - //update existing ones - for (var i in uniforms) { - var info = shader.uniformInfo[i]; - if (info.loc === null) continue; //is an attribute, not a uniform - if (i == "time") - //default one - continue; - - var type = "number"; - if (this._shader.samplers[i]) type = "texture"; - else { - switch (info.size) { - case 1: - type = "number"; - break; - case 2: - type = "vec2"; - break; - case 3: - type = "vec3"; - break; - case 4: - type = "vec4"; - break; - case 9: - type = "mat3"; - break; - case 16: - type = "mat4"; - break; - default: - continue; - } - } - - var slot = this.findInputSlot(i); - if (slot == -1) { - this.addInput(i, type); - continue; - } - - var input_info = this.getInputInfo(slot); - if (!input_info) this.addInput(i, type); - else { - if (input_info.type == type) continue; - this.removeInput(slot, type); - this.addInput(i, type); - } - } - }; - - LGraphTextureShader.prototype.getShader = function() { - //replug - if (this._shader && this._shader_code == this.properties.code) - return this._shader; - - this._shader_code = this.properties.code; - this._shader = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureShader.pixel_shader + this.properties.code - ); - if (!this._shader) { - this.boxcolor = "red"; - return null; - } else this.boxcolor = "green"; - return this._shader; - }; - - LGraphTextureShader.prototype.onExecute = function() { - if (!this.isOutputConnected(0)) return; //saves work - - var shader = this.getShader(); - if (!shader) return; - - var tex_slot = 0; - var in_tex = null; - - //set uniforms - for (var i = 0; i < this.inputs.length; ++i) { - var info = this.getInputInfo(i); - var data = this.getInputData(i); - if (data == null) continue; - - if (data.constructor === GL.Texture) { - data.bind(tex_slot); - if (!in_tex) in_tex = data; - data = tex_slot; - tex_slot++; - } - shader.setUniform(info.name, data); //data is tex_slot - } - - var uniforms = this._uniforms; - var type = LGraphTexture.getTextureType( - this.properties.precision, - in_tex - ); - - //render to texture - var w = this.properties.width | 0; - var h = this.properties.height | 0; - if (w == 0) w = in_tex ? in_tex.width : gl.canvas.width; - if (h == 0) h = in_tex ? in_tex.height : gl.canvas.height; - uniforms.texSize[0] = w; - uniforms.texSize[1] = h; - uniforms.time = this.graph.getTime(); - - if ( - !this._tex || - this._tex.type != type || - this._tex.width != w || - this._tex.height != h - ) - this._tex = new GL.Texture(w, h, { - type: type, - format: gl.RGBA, - filter: gl.LINEAR - }); - var tex = this._tex; - tex.drawTo(function() { - shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureShader.pixel_shader = - "precision highp float;\n\ - \n\ - varying vec2 v_coord;\n\ - uniform float time;\n\ - "; - - LiteGraph.registerNodeType("texture/shader", LGraphTextureShader); - - // Texture Scale Offset - - function LGraphTextureScaleOffset() { - this.addInput("in", "Texture"); - this.addInput("scale", "vec2"); - this.addInput("offset", "vec2"); - this.addOutput("out", "Texture"); - this.properties = { - offset: vec2.fromValues(0, 0), - scale: vec2.fromValues(1, 1), - precision: LGraphTexture.DEFAULT - }; - } - - LGraphTextureScaleOffset.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureScaleOffset.title = "Scale/Offset"; - LGraphTextureScaleOffset.desc = "Applies an scaling and offseting"; - - LGraphTextureScaleOffset.prototype.onExecute = function() { - var tex = this.getInputData(0); - - if (!this.isOutputConnected(0) || !tex) return; //saves work - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, tex); - return; - } - - var width = tex.width; - var height = tex.height; - var type = - this.precision === LGraphTexture.LOW - ? gl.UNSIGNED_BYTE - : gl.HIGH_PRECISION_FORMAT; - if (this.precision === LGraphTexture.DEFAULT) type = tex.type; - - if ( - !this._tex || - this._tex.width != width || - this._tex.height != height || - this._tex.type != type - ) - this._tex = new GL.Texture(width, height, { - type: type, - format: gl.RGBA, - filter: gl.LINEAR - }); - - var shader = this._shader; - - if (!shader) - shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureScaleOffset.pixel_shader - ); - - var scale = this.getInputData(1); - if (scale) { - this.properties.scale[0] = scale[0]; - this.properties.scale[1] = scale[1]; - } else scale = this.properties.scale; - - var offset = this.getInputData(2); - if (offset) { - this.properties.offset[0] = offset[0]; - this.properties.offset[1] = offset[1]; - } else offset = this.properties.offset; - - this._tex.drawTo(function() { - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.disable(gl.BLEND); - tex.bind(0); - var mesh = Mesh.getScreenQuad(); - shader - .uniforms({ - u_texture: 0, - u_scale: scale, - u_offset: offset - }) - .draw(mesh); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureScaleOffset.pixel_shader = - "precision highp float;\n\ - \n\ - uniform sampler2D u_texture;\n\ - uniform sampler2D u_textureB;\n\ - varying vec2 v_coord;\n\ - uniform vec2 u_scale;\n\ - uniform vec2 u_offset;\n\ - \n\ - void main() {\n\ - vec2 uv = v_coord;\n\ - uv = uv / u_scale - u_offset;\n\ - gl_FragColor = texture2D(u_texture, uv);\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/scaleOffset", - LGraphTextureScaleOffset - ); - - // Warp (distort a texture) ************************* - - function LGraphTextureWarp() { - this.addInput("in", "Texture"); - this.addInput("warp", "Texture"); - this.addInput("factor", "number"); - this.addOutput("out", "Texture"); - this.properties = { - factor: 0.01, - precision: LGraphTexture.DEFAULT - }; - } - - LGraphTextureWarp.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureWarp.title = "Warp"; - LGraphTextureWarp.desc = "Texture warp operation"; - - LGraphTextureWarp.prototype.onExecute = function() { - var tex = this.getInputData(0); - - if (!this.isOutputConnected(0)) return; //saves work - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, tex); - return; - } - - var texB = this.getInputData(1); - - var width = 512; - var height = 512; - var type = gl.UNSIGNED_BYTE; - if (tex) { - width = tex.width; - height = tex.height; - type = tex.type; - } else if (texB) { - width = texB.width; - height = texB.height; - type = texB.type; - } - - if (!tex && !this._tex) - this._tex = new GL.Texture(width, height, { - type: - this.precision === LGraphTexture.LOW - ? gl.UNSIGNED_BYTE - : gl.HIGH_PRECISION_FORMAT, - format: gl.RGBA, - filter: gl.LINEAR - }); - else - this._tex = LGraphTexture.getTargetTexture( - tex || this._tex, - this._tex, - this.properties.precision - ); - - var shader = this._shader; - - if (!shader) - shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureWarp.pixel_shader - ); - - var factor = this.getInputData(2); - if (factor != null) this.properties.factor = factor; - else factor = parseFloat(this.properties.factor); - - this._tex.drawTo(function() { - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.disable(gl.BLEND); - if (tex) tex.bind(0); - if (texB) texB.bind(1); - var mesh = Mesh.getScreenQuad(); - shader - .uniforms({ u_texture: 0, u_textureB: 1, u_factor: factor }) - .draw(mesh); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureWarp.pixel_shader = - "precision highp float;\n\ - \n\ - uniform sampler2D u_texture;\n\ - uniform sampler2D u_textureB;\n\ - varying vec2 v_coord;\n\ - uniform float u_factor;\n\ - \n\ - void main() {\n\ - vec2 uv = v_coord;\n\ - uv += ( texture2D(u_textureB, uv).rg - vec2(0.5)) * u_factor;\n\ - gl_FragColor = texture2D(u_texture, uv);\n\ - }\n\ - "; - - LiteGraph.registerNodeType("texture/warp", LGraphTextureWarp); - - //**************************************************** - - // Texture to Viewport ***************************************** - function LGraphTextureToViewport() { - this.addInput("Texture", "Texture"); - this.properties = { - additive: false, - antialiasing: false, - filter: true, - disable_alpha: false, - gamma: 1.0 - }; - this.size[0] = 130; - } - - LGraphTextureToViewport.title = "to Viewport"; - LGraphTextureToViewport.desc = "Texture to viewport"; - - LGraphTextureToViewport.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex) return; - - if (this.properties.disable_alpha) gl.disable(gl.BLEND); - else { - gl.enable(gl.BLEND); - if (this.properties.additive) - gl.blendFunc(gl.SRC_ALPHA, gl.ONE); - else gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - } - - gl.disable(gl.DEPTH_TEST); - var gamma = this.properties.gamma || 1.0; - if (this.isInputConnected(1)) gamma = this.getInputData(1); - - tex.setParameter( - gl.TEXTURE_MAG_FILTER, - this.properties.filter ? gl.LINEAR : gl.NEAREST - ); - - if (this.properties.antialiasing) { - if (!LGraphTextureToViewport._shader) - LGraphTextureToViewport._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureToViewport.aa_pixel_shader - ); - - var viewport = gl.getViewport(); //gl.getParameter(gl.VIEWPORT); - var mesh = Mesh.getScreenQuad(); - tex.bind(0); - LGraphTextureToViewport._shader - .uniforms({ - u_texture: 0, - uViewportSize: [tex.width, tex.height], - u_igamma: 1 / gamma, - inverseVP: [1 / tex.width, 1 / tex.height] - }) - .draw(mesh); - } else { - if (gamma != 1.0) { - if (!LGraphTextureToViewport._gamma_shader) - LGraphTextureToViewport._gamma_shader = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureToViewport.gamma_pixel_shader - ); - tex.toViewport(LGraphTextureToViewport._gamma_shader, { - u_texture: 0, - u_igamma: 1 / gamma - }); - } else tex.toViewport(); - } - }; - - LGraphTextureToViewport.prototype.onGetInputs = function() { - return [["gamma", "number"]]; - }; - - LGraphTextureToViewport.aa_pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform vec2 uViewportSize;\n\ - uniform vec2 inverseVP;\n\ - uniform float u_igamma;\n\ - #define FXAA_REDUCE_MIN (1.0/ 128.0)\n\ - #define FXAA_REDUCE_MUL (1.0 / 8.0)\n\ - #define FXAA_SPAN_MAX 8.0\n\ - \n\ - /* from mitsuhiko/webgl-meincraft based on the code on geeks3d.com */\n\ - vec4 applyFXAA(sampler2D tex, vec2 fragCoord)\n\ - {\n\ - vec4 color = vec4(0.0);\n\ - /*vec2 inverseVP = vec2(1.0 / uViewportSize.x, 1.0 / uViewportSize.y);*/\n\ - vec3 rgbNW = texture2D(tex, (fragCoord + vec2(-1.0, -1.0)) * inverseVP).xyz;\n\ - vec3 rgbNE = texture2D(tex, (fragCoord + vec2(1.0, -1.0)) * inverseVP).xyz;\n\ - vec3 rgbSW = texture2D(tex, (fragCoord + vec2(-1.0, 1.0)) * inverseVP).xyz;\n\ - vec3 rgbSE = texture2D(tex, (fragCoord + vec2(1.0, 1.0)) * inverseVP).xyz;\n\ - vec3 rgbM = texture2D(tex, fragCoord * inverseVP).xyz;\n\ - vec3 luma = vec3(0.299, 0.587, 0.114);\n\ - float lumaNW = dot(rgbNW, luma);\n\ - float lumaNE = dot(rgbNE, luma);\n\ - float lumaSW = dot(rgbSW, luma);\n\ - float lumaSE = dot(rgbSE, luma);\n\ - float lumaM = dot(rgbM, luma);\n\ - float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n\ - float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\ - \n\ - vec2 dir;\n\ - dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n\ - dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\ - \n\ - float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\ - \n\ - float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n\ - dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * inverseVP;\n\ - \n\ - vec3 rgbA = 0.5 * (texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + \n\ - texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n\ - vec3 rgbB = rgbA * 0.5 + 0.25 * (texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + \n\ - texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\ - \n\ - //return vec4(rgbA,1.0);\n\ - float lumaB = dot(rgbB, luma);\n\ - if ((lumaB < lumaMin) || (lumaB > lumaMax))\n\ - color = vec4(rgbA, 1.0);\n\ - else\n\ - color = vec4(rgbB, 1.0);\n\ - if(u_igamma != 1.0)\n\ - color.xyz = pow( color.xyz, vec3(u_igamma) );\n\ - return color;\n\ - }\n\ - \n\ - void main() {\n\ - gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\ - }\n\ - "; - - LGraphTextureToViewport.gamma_pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform float u_igamma;\n\ - void main() {\n\ - vec4 color = texture2D( u_texture, v_coord);\n\ - color.xyz = pow(color.xyz, vec3(u_igamma) );\n\ - gl_FragColor = color;\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/toviewport", - LGraphTextureToViewport - ); - - // Texture Copy ***************************************** - function LGraphTextureCopy() { - this.addInput("Texture", "Texture"); - this.addOutput("", "Texture"); - this.properties = { - size: 0, - generate_mipmaps: false, - 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 tex = this.getInputData(0); - if (!tex && !this._temp_texture) return; - - if (!this.isOutputConnected(0)) return; //saves work - - //copy the texture - if (tex) { - var width = tex.width; - var height = tex.height; - - if (this.properties.size != 0) { - width = this.properties.size; - height = this.properties.size; - } - - var temp = this._temp_texture; - - var type = tex.type; - if (this.properties.precision === LGraphTexture.LOW) - type = gl.UNSIGNED_BYTE; - else if (this.properties.precision === LGraphTexture.HIGH) - type = gl.HIGH_PRECISION_FORMAT; - - if ( - !temp || - temp.width != width || - temp.height != height || - temp.type != type - ) { - var minFilter = gl.LINEAR; - if ( - this.properties.generate_mipmaps && - isPowerOfTwo(width) && - isPowerOfTwo(height) - ) - minFilter = gl.LINEAR_MIPMAP_LINEAR; - this._temp_texture = new GL.Texture(width, height, { - type: type, - format: gl.RGBA, - minFilter: minFilter, - magFilter: gl.LINEAR - }); - } - tex.copyTo(this._temp_texture); - - if (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); - - // Texture Downsample ***************************************** - function LGraphTextureDownsample() { - this.addInput("Texture", "Texture"); - this.addOutput("", "Texture"); - this.properties = { - iterations: 1, - generate_mipmaps: false, - precision: LGraphTexture.DEFAULT - }; - } - - LGraphTextureDownsample.title = "Downsample"; - LGraphTextureDownsample.desc = "Downsample Texture"; - LGraphTextureDownsample.widgets_info = { - iterations: { type: "number", step: 1, precision: 0, min: 0 }, - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureDownsample.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex && !this._temp_texture) return; - - if (!this.isOutputConnected(0)) return; //saves work - - //we do not allow any texture different than texture 2D - if (!tex || tex.texture_type !== GL.TEXTURE_2D) return; - - if (this.properties.iterations < 1) { - this.setOutputData(0, tex); - return; - } - - var shader = LGraphTextureDownsample._shader; - if (!shader) - LGraphTextureDownsample._shader = shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureDownsample.pixel_shader - ); - - var width = tex.width | 0; - var height = tex.height | 0; - var type = tex.type; - if (this.properties.precision === LGraphTexture.LOW) - type = gl.UNSIGNED_BYTE; - else if (this.properties.precision === LGraphTexture.HIGH) - type = gl.HIGH_PRECISION_FORMAT; - var iterations = this.properties.iterations || 1; - - var origin = tex; - var target = null; - - var temp = []; - var options = { - type: type, - format: tex.format - }; - - var offset = vec2.create(); - var uniforms = { - u_offset: offset - }; - - if (this._texture) GL.Texture.releaseTemporary(this._texture); - - for (var i = 0; i < iterations; ++i) { - offset[0] = 1 / width; - offset[1] = 1 / height; - width = width >> 1 || 0; - height = height >> 1 || 0; - target = GL.Texture.getTemporary(width, height, options); - temp.push(target); - origin.setParameter(GL.TEXTURE_MAG_FILTER, GL.NEAREST); - origin.copyTo(target, shader, uniforms); - if (width == 1 && height == 1) break; //nothing else to do - origin = target; - } - - //keep the last texture used - this._texture = temp.pop(); - - //free the rest - for (var i = 0; i < temp.length; ++i) - GL.Texture.releaseTemporary(temp[i]); - - if (this.properties.generate_mipmaps) { - this._texture.bind(0); - gl.generateMipmap(this._texture.texture_type); - this._texture.unbind(0); - } - - this.setOutputData(0, this._texture); - }; - - LGraphTextureDownsample.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - uniform sampler2D u_texture;\n\ - uniform vec2 u_offset;\n\ - varying vec2 v_coord;\n\ - \n\ - void main() {\n\ - vec4 color = texture2D(u_texture, v_coord );\n\ - color += texture2D(u_texture, v_coord + vec2( u_offset.x, 0.0 ) );\n\ - color += texture2D(u_texture, v_coord + vec2( 0.0, u_offset.y ) );\n\ - color += texture2D(u_texture, v_coord + vec2( u_offset.x, u_offset.y ) );\n\ - gl_FragColor = color * 0.25;\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/downsample", - LGraphTextureDownsample - ); - - // Texture Average ***************************************** - function LGraphTextureAverage() { - this.addInput("Texture", "Texture"); - this.addOutput("tex", "Texture"); - this.addOutput("avg", "vec4"); - this.addOutput("lum", "number"); - this.properties = { - use_previous_frame: true, - mipmap_offset: 0, - low_precision: false - }; - - this._uniforms = { - u_texture: 0, - u_mipmap_offset: this.properties.mipmap_offset - }; - this._luminance = new Float32Array(4); - } - - LGraphTextureAverage.title = "Average"; - LGraphTextureAverage.desc = - "Compute a partial average (32 random samples) of a texture and stores it as a 1x1 pixel texture"; - - LGraphTextureAverage.prototype.onExecute = function() { - if (!this.properties.use_previous_frame) this.updateAverage(); - - var v = this._luminance; - this.setOutputData(0, this._temp_texture); - this.setOutputData(1, v); - this.setOutputData(2, (v[0] + v[1] + v[2]) / 3); - }; - - //executed before rendering the frame - LGraphTextureAverage.prototype.onPreRenderExecute = function() { - this.updateAverage(); - }; - - LGraphTextureAverage.prototype.updateAverage = function() { - var tex = this.getInputData(0); - if (!tex) return; - - if ( - !this.isOutputConnected(0) && - !this.isOutputConnected(1) && - !this.isOutputConnected(2) - ) - return; //saves work - - if (!LGraphTextureAverage._shader) { - LGraphTextureAverage._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureAverage.pixel_shader - ); - //creates 32 random numbers and stores the, in two mat4 - var samples = new Float32Array(32); - for (var i = 0; i < 32; ++i) samples[i] = Math.random(); - LGraphTextureAverage._shader.uniforms({ - u_samples_a: samples.subarray(0, 16), - u_samples_b: samples.subarray(16, 32) - }); - } - - var temp = this._temp_texture; - var type = gl.UNSIGNED_BYTE; - if (tex.type != type) - //force floats, half floats cannot be read with gl.readPixels - type = gl.FLOAT; - - if (!temp || temp.type != type) - this._temp_texture = new GL.Texture(1, 1, { - type: type, - format: gl.RGBA, - filter: gl.NEAREST - }); - - var shader = LGraphTextureAverage._shader; - var uniforms = this._uniforms; - uniforms.u_mipmap_offset = this.properties.mipmap_offset; - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.BLEND); - this._temp_texture.drawTo(function() { - tex.toViewport(shader, uniforms); - }); - - if (this.isOutputConnected(1) || this.isOutputConnected(2)) { - var pixel = this._temp_texture.getPixels(); - if (pixel) { - var v = this._luminance; - var type = this._temp_texture.type; - v.set(pixel); - if (type == gl.UNSIGNED_BYTE) vec4.scale(v, v, 1 / 255); - else if ( - type == GL.HALF_FLOAT || - type == GL.HALF_FLOAT_OES - ) { - //no half floats possible, hard to read back unless copyed to a FLOAT texture, so temp_texture is always forced to FLOAT - } - } - } - }; - - LGraphTextureAverage.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - uniform mat4 u_samples_a;\n\ - uniform mat4 u_samples_b;\n\ - uniform sampler2D u_texture;\n\ - uniform float u_mipmap_offset;\n\ - varying vec2 v_coord;\n\ - \n\ - void main() {\n\ - vec4 color = vec4(0.0);\n\ - for(int i = 0; i < 4; ++i)\n\ - for(int j = 0; j < 4; ++j)\n\ - {\n\ - color += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\ - color += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\ - }\n\ - gl_FragColor = color * 0.03125;\n\ - }\n\ - "; - - LiteGraph.registerNodeType("texture/average", LGraphTextureAverage); - - function LGraphTextureTemporalSmooth() { - this.addInput("in", "Texture"); - this.addInput("factor", "Number"); - this.addOutput("out", "Texture"); - this.properties = { factor: 0.5 }; - this._uniforms = { - u_texture: 0, - u_textureB: 1, - u_factor: this.properties.factor - }; - } - - LGraphTextureTemporalSmooth.title = "Smooth"; - LGraphTextureTemporalSmooth.desc = "Smooth texture over time"; - - LGraphTextureTemporalSmooth.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex || !this.isOutputConnected(0)) return; - - if (!LGraphTextureTemporalSmooth._shader) - LGraphTextureTemporalSmooth._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureTemporalSmooth.pixel_shader - ); - - var temp = this._temp_texture; - if ( - !temp || - temp.type != tex.type || - temp.width != tex.width || - temp.height != tex.height - ) { - this._temp_texture = new GL.Texture(tex.width, tex.height, { - type: tex.type, - format: gl.RGBA, - filter: gl.NEAREST - }); - this._temp_texture2 = new GL.Texture(tex.width, tex.height, { - type: tex.type, - format: gl.RGBA, - filter: gl.NEAREST - }); - tex.copyTo(this._temp_texture2); - } - - var tempA = this._temp_texture; - var tempB = this._temp_texture2; - - var shader = LGraphTextureTemporalSmooth._shader; - var uniforms = this._uniforms; - uniforms.u_factor = 1.0 - this.getInputOrProperty("factor"); - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - tempA.drawTo(function() { - tempB.bind(1); - tex.toViewport(shader, uniforms); - }); - - this.setOutputData(0, tempA); - - //swap - this._temp_texture = tempB; - this._temp_texture2 = tempA; - }; - - LGraphTextureTemporalSmooth.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - uniform sampler2D u_texture;\n\ - uniform sampler2D u_textureB;\n\ - uniform float u_factor;\n\ - varying vec2 v_coord;\n\ - \n\ - void main() {\n\ - gl_FragColor = mix( texture2D( u_texture, v_coord ), texture2D( u_textureB, v_coord ), u_factor );\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/temporal_smooth", - LGraphTextureTemporalSmooth - ); - - // Image To Texture ***************************************** - function LGraphImageToTexture() { - this.addInput("Image", "image"); - this.addOutput("", "Texture"); - this.properties = {}; - } - - LGraphImageToTexture.title = "Image to Texture"; - LGraphImageToTexture.desc = "Uploads an image to the GPU"; - //LGraphImageToTexture.widgets_info = { size: { widget:"combo", values:[0,32,64,128,256,512,1024,2048]} }; - - LGraphImageToTexture.prototype.onExecute = function() { - var img = this.getInputData(0); - if (!img) return; - - var width = img.videoWidth || img.width; - var height = img.videoHeight || img.height; - - //this is in case we are using a webgl canvas already, no need to reupload it - if (img.gltexture) { - this.setOutputData(0, img.gltexture); - return; - } - - var temp = this._temp_texture; - if (!temp || temp.width != width || temp.height != height) - this._temp_texture = new GL.Texture(width, height, { - format: gl.RGBA, - filter: gl.LINEAR - }); - - try { - this._temp_texture.uploadImage(img); - } catch (err) { - console.error( - "image comes from an unsafe location, cannot be uploaded to webgl: " + - err - ); - return; - } - - this.setOutputData(0, this._temp_texture); - }; - - LiteGraph.registerNodeType( - "texture/imageToTexture", - LGraphImageToTexture - ); - - // Texture LUT ***************************************** - function LGraphTextureLUT() { - this.addInput("Texture", "Texture"); - this.addInput("LUT", "Texture"); - this.addInput("Intensity", "number"); - this.addOutput("", "Texture"); - this.properties = { - intensity: 1, - precision: LGraphTexture.DEFAULT, - texture: null - }; - - if (!LGraphTextureLUT._shader) - LGraphTextureLUT._shader = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureLUT.pixel_shader - ); - } - - LGraphTextureLUT.widgets_info = { - texture: { widget: "texture" }, - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureLUT.title = "LUT"; - LGraphTextureLUT.desc = "Apply LUT to Texture"; - - LGraphTextureLUT.prototype.onExecute = function() { - if (!this.isOutputConnected(0)) return; //saves work - - var tex = this.getInputData(0); - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, tex); - return; - } - - if (!tex) return; - - var lut_tex = this.getInputData(1); - - if (!lut_tex) - lut_tex = LGraphTexture.getTexture(this.properties.texture); - - if (!lut_tex) { - this.setOutputData(0, tex); - return; - } - - lut_tex.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 intensity = this.properties.intensity; - if (this.isInputConnected(2)) - this.properties.intensity = intensity = this.getInputData(2); - - this._tex = LGraphTexture.getTargetTexture( - tex, - this._tex, - this.properties.precision - ); - - //var mesh = Mesh.getScreenQuad(); - - this._tex.drawTo(function() { - lut_tex.bind(1); - tex.toViewport(LGraphTextureLUT._shader, { - u_texture: 0, - u_textureB: 1, - u_amount: intensity - }); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureLUT.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform sampler2D u_textureB;\n\ - uniform float u_amount;\n\ - \n\ - void main() {\n\ - lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\ - mediump float blueColor = textureColor.b * 63.0;\n\ - mediump vec2 quad1;\n\ - quad1.y = floor(floor(blueColor) / 8.0);\n\ - quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\ - mediump vec2 quad2;\n\ - quad2.y = floor(ceil(blueColor) / 8.0);\n\ - quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\ - highp vec2 texPos1;\n\ - texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\ - texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\ - highp vec2 texPos2;\n\ - texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\ - texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\ - lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\ - lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\ - lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\ - gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\ - }\n\ - "; - - LiteGraph.registerNodeType("texture/LUT", LGraphTextureLUT); - - // Texture Channels ***************************************** - function LGraphTextureChannels() { - this.addInput("Texture", "Texture"); - - this.addOutput("R", "Texture"); - this.addOutput("G", "Texture"); - this.addOutput("B", "Texture"); - this.addOutput("A", "Texture"); - - this.properties = { use_luminance: true }; - if (!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 texA = this.getInputData(0); - if (!texA) return; - - if (!this._channels) this._channels = Array(4); - - var format = this.properties.use_luminance ? gl.LUMINANCE : gl.RGBA; - var connections = 0; - for (var i = 0; i < 4; i++) { - if (this.isOutputConnected(i)) { - if ( - !this._channels[i] || - this._channels[i].width != texA.width || - this._channels[i].height != texA.height || - this._channels[i].type != texA.type || - this._channels[i].format != format - ) - this._channels[i] = new GL.Texture( - texA.width, - texA.height, - { - type: texA.type, - format: format, - filter: gl.LINEAR - } - ); - connections++; - } else this._channels[i] = null; - } - - if (!connections) return; - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - - var mesh = Mesh.getScreenQuad(); - var shader = LGraphTextureChannels._shader; - var masks = [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1] - ]; - - for (var i = 0; i < 4; i++) { - if (!this._channels[i]) continue; - - this._channels[i].drawTo(function() { - texA.bind(0); - shader - .uniforms({ u_texture: 0, u_mask: masks[i] }) - .draw(mesh); - }); - this.setOutputData(i, this._channels[i]); - } - }; - - LGraphTextureChannels.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform vec4 u_mask;\n\ - \n\ - void main() {\n\ - gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/textureChannels", - LGraphTextureChannels - ); - - // Texture Channels to Texture ***************************************** - function LGraphChannelsTexture() { - this.addInput("R", "Texture"); - this.addInput("G", "Texture"); - this.addInput("B", "Texture"); - this.addInput("A", "Texture"); - - this.addOutput("Texture", "Texture"); - - this.properties = { - precision: LGraphTexture.DEFAULT, - R: 1, - G: 1, - B: 1, - A: 1 - }; - this._color = vec4.create(); - this._uniforms = { - u_textureR: 0, - u_textureG: 1, - u_textureB: 2, - u_textureA: 3, - u_color: this._color - }; - } - - LGraphChannelsTexture.title = "Channels to Texture"; - LGraphChannelsTexture.desc = "Split texture channels"; - LGraphChannelsTexture.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphChannelsTexture.prototype.onExecute = function() { - var white = LGraphTexture.getWhiteTexture(); - var texR = this.getInputData(0) || white; - var texG = this.getInputData(1) || white; - var texB = this.getInputData(2) || white; - var texA = this.getInputData(3) || white; - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - - var mesh = Mesh.getScreenQuad(); - if (!LGraphChannelsTexture._shader) - LGraphChannelsTexture._shader = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphChannelsTexture.pixel_shader - ); - var shader = LGraphChannelsTexture._shader; - - var w = Math.max(texR.width, texG.width, texB.width, texA.width); - var h = Math.max( - texR.height, - texG.height, - texB.height, - texA.height - ); - var type = - this.properties.precision == LGraphTexture.HIGH - ? LGraphTexture.HIGH_PRECISION_FORMAT - : gl.UNSIGNED_BYTE; - - if ( - !this._texture || - this._texture.width != w || - this._texture.height != h || - this._texture.type != type - ) - this._texture = new GL.Texture(w, h, { - type: type, - format: gl.RGBA, - filter: gl.LINEAR - }); - - var color = this._color; - color[0] = this.properties.R; - color[1] = this.properties.G; - color[2] = this.properties.B; - color[3] = this.properties.A; - var uniforms = this._uniforms; - - this._texture.drawTo(function() { - texR.bind(0); - texG.bind(1); - texB.bind(2); - texA.bind(3); - shader.uniforms(uniforms).draw(mesh); - }); - this.setOutputData(0, this._texture); - }; - - LGraphChannelsTexture.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_textureR;\n\ - uniform sampler2D u_textureG;\n\ - uniform sampler2D u_textureB;\n\ - uniform sampler2D u_textureA;\n\ - uniform vec4 u_color;\n\ - \n\ - void main() {\n\ - gl_FragColor = u_color * vec4( \ - texture2D(u_textureR, v_coord).r,\ - texture2D(u_textureG, v_coord).r,\ - texture2D(u_textureB, v_coord).r,\ - texture2D(u_textureA, v_coord).r);\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/channelsTexture", - LGraphChannelsTexture - ); - - // Texture Color ***************************************** - function LGraphTextureColor() { - this.addOutput("Texture", "Texture"); - - this._tex_color = vec4.create(); - this.properties = { - color: vec4.create(), - precision: LGraphTexture.DEFAULT - }; - } - - LGraphTextureColor.title = "Color"; - LGraphTextureColor.desc = - "Generates a 1x1 texture with a constant color"; - - LGraphTextureColor.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureColor.prototype.onDrawBackground = function(ctx) { - var c = this.properties.color; - ctx.fillStyle = - "rgb(" + - Math.floor(Math.clamp(c[0], 0, 1) * 255) + - "," + - Math.floor(Math.clamp(c[1], 0, 1) * 255) + - "," + - Math.floor(Math.clamp(c[2], 0, 1) * 255) + - ")"; - if (this.flags.collapsed) this.boxcolor = ctx.fillStyle; - else ctx.fillRect(0, 0, this.size[0], this.size[1]); - }; - - LGraphTextureColor.prototype.onExecute = function() { - var type = - this.properties.precision == LGraphTexture.HIGH - ? LGraphTexture.HIGH_PRECISION_FORMAT - : gl.UNSIGNED_BYTE; - - if (!this._tex || this._tex.type != type) - this._tex = new GL.Texture(1, 1, { - format: gl.RGBA, - type: type, - minFilter: gl.NEAREST - }); - var color = this.properties.color; - - 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; - switch (input.name) { - case "RGB": - case "RGBA": - color.set(v); - break; - case "R": - color[0] = v; - break; - case "G": - color[1] = v; - break; - case "B": - color[2] = v; - break; - case "A": - color[3] = v; - break; - } - } - - if (vec4.sqrDist(this._tex_color, color) > 0.001) { - this._tex_color.set(color); - this._tex.fill(color); - } - this.setOutputData(0, this._tex); - }; - - LGraphTextureColor.prototype.onGetInputs = function() { - return [ - ["RGB", "vec3"], - ["RGBA", "vec4"], - ["R", "number"], - ["G", "number"], - ["B", "number"], - ["A", "number"] - ]; - }; - - LiteGraph.registerNodeType("texture/color", LGraphTextureColor); - - // 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() { - this.addInput("A", "Texture"); - this.addInput("B", "Texture"); - this.addInput("Mixer", "Texture"); - - this.addOutput("Texture", "Texture"); - this.properties = { factor: 0.5, precision: LGraphTexture.DEFAULT }; - this._uniforms = { - u_textureA: 0, - u_textureB: 1, - u_textureMix: 2, - u_mix: vec4.create() - }; - } - - 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 texA = this.getInputData(0); - - if (!this.isOutputConnected(0)) return; //saves work - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, texA); - return; - } - - var texB = this.getInputData(1); - if (!texA || !texB) return; - - var texMix = this.getInputData(2); - - var factor = this.getInputData(3); - - this._tex = LGraphTexture.getTargetTexture( - texA, - this._tex, - this.properties.precision - ); - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - - var mesh = Mesh.getScreenQuad(); - var shader = null; - var uniforms = this._uniforms; - if (texMix) { - shader = LGraphTextureMix._shader_tex; - if (!shader) - shader = LGraphTextureMix._shader_tex = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureMix.pixel_shader, - { MIX_TEX: "" } - ); - } else { - shader = LGraphTextureMix._shader_factor; - if (!shader) - shader = LGraphTextureMix._shader_factor = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureMix.pixel_shader - ); - var f = factor == null ? this.properties.factor : factor; - uniforms.u_mix.set([f, f, f, f]); - } - - this._tex.drawTo(function() { - texA.bind(0); - texB.bind(1); - if (texMix) texMix.bind(2); - shader.uniforms(uniforms).draw(mesh); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureMix.prototype.onGetInputs = function() { - return [["factor", "number"]]; - }; - - LGraphTextureMix.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_textureA;\n\ - uniform sampler2D u_textureB;\n\ - #ifdef MIX_TEX\n\ - uniform sampler2D u_textureMix;\n\ - #else\n\ - uniform vec4 u_mix;\n\ - #endif\n\ - \n\ - void main() {\n\ - #ifdef MIX_TEX\n\ - vec4 f = texture2D(u_textureMix, v_coord);\n\ - #else\n\ - vec4 f = u_mix;\n\ - #endif\n\ - gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), f );\n\ - }\n\ - "; - - LiteGraph.registerNodeType("texture/mix", LGraphTextureMix); - - // Texture Edges detection ***************************************** - function LGraphTextureEdges() { - this.addInput("Tex.", "Texture"); - - this.addOutput("Edges", "Texture"); - this.properties = { - invert: true, - threshold: false, - factor: 1, - precision: LGraphTexture.DEFAULT - }; - - if (!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() { - if (!this.isOutputConnected(0)) return; //saves work - - var tex = this.getInputData(0); - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, tex); - return; - } - - if (!tex) return; - - this._tex = LGraphTexture.getTargetTexture( - tex, - this._tex, - this.properties.precision - ); - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - - var mesh = Mesh.getScreenQuad(); - var shader = LGraphTextureEdges._shader; - var invert = this.properties.invert; - var factor = this.properties.factor; - var threshold = this.properties.threshold ? 1 : 0; - - this._tex.drawTo(function() { - tex.bind(0); - shader - .uniforms({ - u_texture: 0, - u_isize: [1 / tex.width, 1 / tex.height], - u_factor: factor, - u_threshold: threshold, - u_invert: invert ? 1 : 0 - }) - .draw(mesh); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureEdges.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform vec2 u_isize;\n\ - uniform int u_invert;\n\ - uniform float u_factor;\n\ - uniform float u_threshold;\n\ - \n\ - void main() {\n\ - vec4 center = texture2D(u_texture, v_coord);\n\ - vec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\ - vec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\ - vec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\ - vec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\ - vec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\ - diff *= u_factor;\n\ - if(u_invert == 1)\n\ - diff.xyz = vec3(1.0) - diff.xyz;\n\ - if( u_threshold == 0.0 )\n\ - gl_FragColor = vec4( diff.xyz, center.a );\n\ - else\n\ - gl_FragColor = vec4( diff.x > 0.5 ? 1.0 : 0.0, diff.y > 0.5 ? 1.0 : 0.0, diff.z > 0.5 ? 1.0 : 0.0, center.a );\n\ - }\n\ - "; - - LiteGraph.registerNodeType("texture/edges", LGraphTextureEdges); - - // Texture Depth ***************************************** - function LGraphTextureDepthRange() { - this.addInput("Texture", "Texture"); - this.addInput("Distance", "number"); - this.addInput("Range", "number"); - this.addOutput("Texture", "Texture"); - this.properties = { - distance: 100, - range: 50, - only_depth: false, - high_precision: false - }; - this._uniforms = { - u_texture: 0, - u_distance: 100, - u_range: 50, - u_camera_planes: null - }; - } - - LGraphTextureDepthRange.title = "Depth Range"; - LGraphTextureDepthRange.desc = "Generates a texture with a depth range"; - - LGraphTextureDepthRange.prototype.onExecute = function() { - if (!this.isOutputConnected(0)) return; //saves work - - var tex = this.getInputData(0); - if (!tex) return; - - var precision = gl.UNSIGNED_BYTE; - if (this.properties.high_precision) - precision = gl.half_float_ext ? gl.HALF_FLOAT_OES : gl.FLOAT; - - if ( - !this._temp_texture || - this._temp_texture.type != precision || - this._temp_texture.width != tex.width || - this._temp_texture.height != tex.height - ) - this._temp_texture = new GL.Texture(tex.width, tex.height, { - type: precision, - format: gl.RGBA, - filter: gl.LINEAR - }); - - var uniforms = this._uniforms; - - //iterations - var distance = this.properties.distance; - if (this.isInputConnected(1)) { - distance = this.getInputData(1); - this.properties.distance = distance; - } - - var range = this.properties.range; - if (this.isInputConnected(2)) { - range = this.getInputData(2); - this.properties.range = range; - } - - uniforms.u_distance = distance; - uniforms.u_range = range; - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - var mesh = Mesh.getScreenQuad(); - if (!LGraphTextureDepthRange._shader) { - LGraphTextureDepthRange._shader = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureDepthRange.pixel_shader - ); - LGraphTextureDepthRange._shader_onlydepth = new GL.Shader( - Shader.SCREEN_VERTEX_SHADER, - LGraphTextureDepthRange.pixel_shader, - { ONLY_DEPTH: "" } - ); - } - var shader = this.properties.only_depth - ? LGraphTextureDepthRange._shader_onlydepth - : LGraphTextureDepthRange._shader; - - //NEAR AND FAR PLANES - var planes = null; - if (tex.near_far_planes) planes = tex.near_far_planes; - else if (window.LS && LS.Renderer._main_camera) - planes = LS.Renderer._main_camera._uniforms.u_camera_planes; - else planes = [0.1, 1000]; //hardcoded - uniforms.u_camera_planes = planes; - - this._temp_texture.drawTo(function() { - tex.bind(0); - shader.uniforms(uniforms).draw(mesh); - }); - - this._temp_texture.near_far_planes = planes; - this.setOutputData(0, this._temp_texture); - }; - - LGraphTextureDepthRange.pixel_shader = - "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform vec2 u_camera_planes;\n\ - uniform float u_distance;\n\ - uniform float u_range;\n\ - \n\ - float LinearDepth()\n\ - {\n\ - float zNear = u_camera_planes.x;\n\ - float zFar = u_camera_planes.y;\n\ - float depth = texture2D(u_texture, v_coord).x;\n\ - depth = depth * 2.0 - 1.0;\n\ - return zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\ - }\n\ - \n\ - void main() {\n\ - float depth = LinearDepth();\n\ - #ifdef ONLY_DEPTH\n\ - gl_FragColor = vec4(depth);\n\ - #else\n\ - float diff = abs(depth * u_camera_planes.y - u_distance);\n\ - float dof = 1.0;\n\ - if(diff <= u_range)\n\ - dof = diff / u_range;\n\ - gl_FragColor = vec4(dof);\n\ - #endif\n\ - }\n\ - "; - - LiteGraph.registerNodeType( - "texture/depth_range", - LGraphTextureDepthRange - ); - - // Texture Blur ***************************************** - function LGraphTextureBlur() { - this.addInput("Texture", "Texture"); - this.addInput("Iterations", "number"); - this.addInput("Intensity", "number"); - this.addOutput("Blurred", "Texture"); - this.properties = { - intensity: 1, - iterations: 1, - preserve_aspect: false, - scale: [1, 1], - precision: LGraphTexture.DEFAULT - }; - } - - LGraphTextureBlur.title = "Blur"; - LGraphTextureBlur.desc = "Blur a texture"; - - LGraphTextureBlur.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureBlur.max_iterations = 20; - - LGraphTextureBlur.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex) return; - - if (!this.isOutputConnected(0)) return; //saves work - - var temp = this._final_texture; - - if ( - !temp || - temp.width != tex.width || - temp.height != tex.height || - temp.type != tex.type - ) { - //we need two textures to do the blurring - //this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); - temp = this._final_texture = new GL.Texture( - tex.width, - tex.height, - { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } - ); - } - - //iterations - var iterations = this.properties.iterations; - if (this.isInputConnected(1)) { - iterations = this.getInputData(1); - this.properties.iterations = iterations; - } - iterations = Math.min( - Math.floor(iterations), - LGraphTextureBlur.max_iterations - ); - if (iterations == 0) { - //skip blurring - this.setOutputData(0, tex); - return; - } - - var intensity = this.properties.intensity; - if (this.isInputConnected(2)) { - intensity = this.getInputData(2); - this.properties.intensity = intensity; - } - - //blur sometimes needs an aspect correction - var aspect = LiteGraph.camera_aspect; - if (!aspect && window.gl !== undefined) - aspect = gl.canvas.height / gl.canvas.width; - if (!aspect) aspect = 1; - aspect = this.properties.preserve_aspect ? aspect : 1; - - var scale = this.properties.scale || [1, 1]; - tex.applyBlur(aspect * scale[0], scale[1], intensity, temp); - for (var i = 1; i < iterations; ++i) - temp.applyBlur( - aspect * scale[0] * (i + 1), - scale[1] * (i + 1), - intensity - ); - - this.setOutputData(0, temp); - }; - - /* - LGraphTextureBlur.pixel_shader = "precision highp float;\n\ - precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform vec2 u_offset;\n\ - uniform float u_intensity;\n\ - void main() {\n\ - vec4 sum = vec4(0.0);\n\ - vec4 center = texture2D(u_texture, v_coord);\n\ - sum += texture2D(u_texture, v_coord + u_offset * -4.0) * 0.05/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * -3.0) * 0.09/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * -2.0) * 0.12/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * -1.0) * 0.15/0.98;\n\ - sum += center * 0.16/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * 4.0) * 0.05/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * 3.0) * 0.09/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * 2.0) * 0.12/0.98;\n\ - sum += texture2D(u_texture, v_coord + u_offset * 1.0) * 0.15/0.98;\n\ - gl_FragColor = u_intensity * sum;\n\ - }\n\ - "; - */ - - LiteGraph.registerNodeType("texture/blur", LGraphTextureBlur); - - // Texture Glow ***************************************** - //based in https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/ - function LGraphTextureGlow() { - this.addInput("in", "Texture"); - this.addInput("dirt", "Texture"); - this.addOutput("out", "Texture"); - this.addOutput("glow", "Texture"); - this.properties = { - enabled: true, - intensity: 1, - persistence: 0.99, - iterations: 16, - threshold: 0, - scale: 1, - dirt_factor: 0.5, - precision: LGraphTexture.DEFAULT - }; - this._textures = []; - this._uniforms = { - u_intensity: 1, - u_texture: 0, - u_glow_texture: 1, - u_threshold: 0, - u_texel_size: vec2.create() - }; - } - - LGraphTextureGlow.title = "Glow"; - LGraphTextureGlow.desc = "Filters a texture giving it a glow effect"; - LGraphTextureGlow.weights = new Float32Array([0.5, 0.4, 0.3, 0.2]); - - LGraphTextureGlow.widgets_info = { - iterations: { - type: "number", - min: 0, - max: 16, - step: 1, - precision: 0 - }, - threshold: { - type: "number", - min: 0, - max: 10, - step: 0.01, - precision: 2 - }, - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureGlow.prototype.onGetInputs = function() { - return [ - ["enabled", "boolean"], - ["threshold", "number"], - ["intensity", "number"], - ["persistence", "number"], - ["iterations", "number"], - ["dirt_factor", "number"] - ]; - }; - - LGraphTextureGlow.prototype.onGetOutputs = function() { - return [["average", "Texture"]]; - }; - - LGraphTextureGlow.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex) return; - - if (!this.isAnyOutputConnected()) return; //saves work - - if ( - this.properties.precision === LGraphTexture.PASS_THROUGH || - this.getInputOrProperty("enabled") === false - ) { - this.setOutputData(0, tex); - return; - } - - var width = tex.width; - var height = tex.height; - - var texture_info = { - format: tex.format, - type: tex.type, - minFilter: GL.LINEAR, - magFilter: GL.LINEAR, - wrap: gl.CLAMP_TO_EDGE - }; - var type = LGraphTexture.getTextureType( - this.properties.precision, - tex - ); - - var uniforms = this._uniforms; - var textures = this._textures; - - //cut - var shader = LGraphTextureGlow._cut_shader; - if (!shader) - shader = LGraphTextureGlow._cut_shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureGlow.cut_pixel_shader - ); - - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.BLEND); - - uniforms.u_threshold = this.getInputOrProperty("threshold"); - var currentDestination = (textures[0] = GL.Texture.getTemporary( - width, - height, - texture_info - )); - tex.blit(currentDestination, shader.uniforms(uniforms)); - var currentSource = currentDestination; - - var iterations = this.getInputOrProperty("iterations"); - iterations = Math.clamp(iterations, 1, 16) | 0; - var texel_size = uniforms.u_texel_size; - var intensity = this.getInputOrProperty("intensity"); - - uniforms.u_intensity = 1; - uniforms.u_delta = this.properties.scale; //1 - - //downscale/upscale shader - var shader = LGraphTextureGlow._shader; - if (!shader) - shader = LGraphTextureGlow._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureGlow.scale_pixel_shader - ); - - var i = 1; - //downscale - for (; i < iterations; i++) { - width = width >> 1; - if ((height | 0) > 1) height = height >> 1; - if (width < 2) break; - currentDestination = textures[i] = GL.Texture.getTemporary( - width, - height, - texture_info - ); - texel_size[0] = 1 / currentSource.width; - texel_size[1] = 1 / currentSource.height; - currentSource.blit( - currentDestination, - shader.uniforms(uniforms) - ); - currentSource = currentDestination; - } - - //average - if (this.isOutputConnected(2)) { - var average_texture = this._average_texture; - if ( - !average_texture || - average_texture.type != tex.type || - average_texture.format != tex.format - ) - average_texture = this._average_texture = new GL.Texture( - 1, - 1, - { - type: tex.type, - format: tex.format, - filter: gl.LINEAR - } - ); - texel_size[0] = 1 / currentSource.width; - texel_size[1] = 1 / currentSource.height; - uniforms.u_intensity = intensity; - uniforms.u_delta = 1; - currentSource.blit(average_texture, shader.uniforms(uniforms)); - this.setOutputData(2, average_texture); - } - - //upscale and blend - gl.enable(gl.BLEND); - gl.blendFunc(gl.ONE, gl.ONE); - uniforms.u_intensity = this.getInputOrProperty("persistence"); - uniforms.u_delta = 0.5; - - for ( - i -= 2; - i >= 0; - i-- // i-=2 => -1 to point to last element in array, -1 to go to texture above - ) { - currentDestination = textures[i]; - textures[i] = null; - texel_size[0] = 1 / currentSource.width; - texel_size[1] = 1 / currentSource.height; - currentSource.blit( - currentDestination, - shader.uniforms(uniforms) - ); - GL.Texture.releaseTemporary(currentSource); - currentSource = currentDestination; - } - gl.disable(gl.BLEND); - - //glow - if (this.isOutputConnected(1)) { - var glow_texture = this._glow_texture; - if ( - !glow_texture || - glow_texture.width != tex.width || - glow_texture.height != tex.height || - glow_texture.type != type || - glow_texture.format != tex.format - ) - glow_texture = this._glow_texture = new GL.Texture( - tex.width, - tex.height, - { type: type, format: tex.format, filter: gl.LINEAR } - ); - currentSource.blit(glow_texture); - this.setOutputData(1, glow_texture); - } - - //final composition - if (this.isOutputConnected(0)) { - var final_texture = this._final_texture; - if ( - !final_texture || - final_texture.width != tex.width || - final_texture.height != tex.height || - final_texture.type != type || - final_texture.format != tex.format - ) - final_texture = this._final_texture = new GL.Texture( - tex.width, - tex.height, - { type: type, format: tex.format, filter: gl.LINEAR } - ); - - var dirt_texture = this.getInputData(1); - var dirt_factor = this.getInputOrProperty("dirt_factor"); - - uniforms.u_intensity = intensity; - - shader = dirt_texture - ? LGraphTextureGlow._dirt_final_shader - : LGraphTextureGlow._final_shader; - if (!shader) { - if (dirt_texture) + return origin; + break; + case LGraphTexture.COPY: + default: + tex_type = origin ? origin.type : gl.UNSIGNED_BYTE; + break; + } + + if ( + !target || + target.width != origin.width || + target.height != origin.height || + target.type != tex_type + ) { + target = new GL.Texture(origin.width, origin.height, { + type: tex_type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } + + return target; + }; + + LGraphTexture.getTextureType = function(precision, ref_texture) { + var type = ref_texture ? ref_texture.type : gl.UNSIGNED_BYTE; + switch (precision) { + case LGraphTexture.HIGH: + type = gl.HIGH_PRECISION_FORMAT; + break; + case LGraphTexture.LOW: + type = gl.UNSIGNED_BYTE; + break; + //no default + } + return type; + }; + + LGraphTexture.getWhiteTexture = function() { + if (this._white_texture) { + return this._white_texture; + } + var texture = (this._white_texture = GL.Texture.fromMemory( + 1, + 1, + [255, 255, 255, 255], + { format: gl.RGBA, wrap: gl.REPEAT, filter: gl.NEAREST } + )); + return texture; + }; + + LGraphTexture.getNoiseTexture = function() { + if (this._noise_texture) { + return this._noise_texture; + } + + var noise = new Uint8Array(512 * 512 * 4); + for (var i = 0; i < 512 * 512 * 4; ++i) { + noise[i] = Math.random() * 255; + } + + var texture = GL.Texture.fromMemory(512, 512, noise, { + format: gl.RGBA, + wrap: gl.REPEAT, + filter: gl.NEAREST + }); + this._noise_texture = texture; + return texture; + }; + + LGraphTexture.prototype.onDropFile = function(data, filename, file) { + if (!data) { + this._drop_texture = null; + this.properties.name = ""; + } else { + var texture = null; + if (typeof data == "string") { + texture = GL.Texture.fromURL(data); + } else if (filename.toLowerCase().indexOf(".dds") != -1) { + texture = GL.Texture.fromDDSInMemory(data); + } else { + var blob = new Blob([file]); + var url = URL.createObjectURL(blob); + texture = GL.Texture.fromURL(url); + } + + this._drop_texture = texture; + this.properties.name = filename; + } + }; + + LGraphTexture.prototype.getExtraMenuOptions = function(graphcanvas) { + var that = this; + if (!this._drop_texture) { + return; + } + return [ + { + content: "Clear", + callback: function() { + that._drop_texture = null; + that.properties.name = ""; + } + } + ]; + }; + + LGraphTexture.prototype.onExecute = function() { + var tex = null; + if (this.isOutputConnected(1)) { + tex = this.getInputData(0); + } + + if (!tex && this._drop_texture) { + tex = this._drop_texture; + } + + if (!tex && this.properties.name) { + tex = LGraphTexture.getTexture(this.properties.name); + } + + if (!tex) { + return; + } + + this._last_tex = tex; + + if (this.properties.filter === false) { + tex.setParameter(gl.TEXTURE_MAG_FILTER, gl.NEAREST); + } else { + tex.setParameter(gl.TEXTURE_MAG_FILTER, gl.LINEAR); + } + + this.setOutputData(0, tex); + + for (var i = 1; i < this.outputs.length; i++) { + var output = this.outputs[i]; + if (!output) { + continue; + } + var v = null; + if (output.name == "width") { + v = tex.width; + } else if (output.name == "height") { + v = tex.height; + } else if (output.name == "aspect") { + v = tex.width / tex.height; + } + this.setOutputData(i, v); + } + }; + + LGraphTexture.prototype.onResourceRenamed = function( + old_name, + new_name + ) { + if (this.properties.name == old_name) { + this.properties.name = new_name; + } + }; + + LGraphTexture.prototype.onDrawBackground = function(ctx) { + if (this.flags.collapsed || this.size[1] <= 20) { + return; + } + + if (this._drop_texture && ctx.webgl) { + ctx.drawImage( + this._drop_texture, + 0, + 0, + this.size[0], + this.size[1] + ); + //this._drop_texture.renderQuad(this.pos[0],this.pos[1],this.size[0],this.size[1]); + return; + } + + //Different texture? then get it from the GPU + if (this._last_preview_tex != this._last_tex) { + if (ctx.webgl) { + this._canvas = this._last_tex; + } else { + var tex_canvas = LGraphTexture.generateLowResTexturePreview( + this._last_tex + ); + if (!tex_canvas) { + return; + } + + this._last_preview_tex = this._last_tex; + this._canvas = cloneCanvas(tex_canvas); + } + } + + if (!this._canvas) { + return; + } + + //render to graph canvas + ctx.save(); + if (!ctx.webgl) { + //reverse image + ctx.translate(0, this.size[1]); + ctx.scale(1, -1); + } + ctx.drawImage(this._canvas, 0, 0, this.size[0], this.size[1]); + ctx.restore(); + }; + + //very slow, used at your own risk + LGraphTexture.generateLowResTexturePreview = function(tex) { + if (!tex) { + return null; + } + + var size = LGraphTexture.image_preview_size; + var temp_tex = tex; + + if (tex.format == gl.DEPTH_COMPONENT) { + return null; + } //cannot generate from depth + + //Generate low-level version in the GPU to speed up + if (tex.width > size || tex.height > size) { + temp_tex = this._preview_temp_tex; + if (!this._preview_temp_tex) { + temp_tex = new GL.Texture(size, size, { + minFilter: gl.NEAREST + }); + this._preview_temp_tex = temp_tex; + } + + //copy + tex.copyTo(temp_tex); + tex = temp_tex; + } + + //create intermediate canvas with lowquality version + var tex_canvas = this._preview_canvas; + if (!tex_canvas) { + tex_canvas = createCanvas(size, size); + this._preview_canvas = tex_canvas; + } + + if (temp_tex) { + temp_tex.toCanvas(tex_canvas); + } + return tex_canvas; + }; + + LGraphTexture.prototype.getResources = function(res) { + res[this.properties.name] = GL.Texture; + return res; + }; + + LGraphTexture.prototype.onGetInputs = function() { + return [["in", "Texture"]]; + }; + + LGraphTexture.prototype.onGetOutputs = function() { + return [ + ["width", "number"], + ["height", "number"], + ["aspect", "number"] + ]; + }; + + LiteGraph.registerNodeType("texture/texture", LGraphTexture); + + //************************** + function LGraphTexturePreview() { + this.addInput("Texture", "Texture"); + this.properties = { flipY: false }; + this.size = [ + LGraphTexture.image_preview_size, + LGraphTexture.image_preview_size + ]; + } + + LGraphTexturePreview.title = "Preview"; + LGraphTexturePreview.desc = "Show a texture in the graph canvas"; + LGraphTexturePreview.allow_preview = false; + + LGraphTexturePreview.prototype.onDrawBackground = function(ctx) { + if (this.flags.collapsed) { + return; + } + + if (!ctx.webgl && !LGraphTexturePreview.allow_preview) { + return; + } //not working well + + var tex = this.getInputData(0); + if (!tex) { + return; + } + + var tex_canvas = null; + + if (!tex.handle && ctx.webgl) { + tex_canvas = tex; + } else { + tex_canvas = LGraphTexture.generateLowResTexturePreview(tex); + } + + //render to graph canvas + ctx.save(); + if (this.properties.flipY) { + ctx.translate(0, this.size[1]); + ctx.scale(1, -1); + } + ctx.drawImage(tex_canvas, 0, 0, this.size[0], this.size[1]); + ctx.restore(); + }; + + LiteGraph.registerNodeType("texture/preview", LGraphTexturePreview); + + //************************************** + + function LGraphTextureSave() { + 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 tex = this.getInputData(0); + if (!tex) { + return; + } + + if (this.properties.name) { + //for cases where we want to perform something when storing it + if (LGraphTexture.storeTexture) { + LGraphTexture.storeTexture(this.properties.name, tex); + } else { + var container = LGraphTexture.getTexturesContainer(); + container[this.properties.name] = tex; + } + } + + this.setOutputData(0, tex); + }; + + LiteGraph.registerNodeType("texture/save", LGraphTextureSave); + + //**************************************************** + + function LGraphTextureOperation() { + this.addInput("Texture", "Texture"); + this.addInput("TextureB", "Texture"); + this.addInput("value", "number"); + this.addOutput("Texture", "Texture"); + this.help = + "pixelcode must be vec3\ + uvcode must be vec2, is optional\ + uv: tex. coordscolor: texturecolorB: textureBtime: scene timevalue: 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( + graphcanvas + ) { + var that = this; + var txt = !that.properties.show ? "Show Texture" : "Hide Texture"; + return [ + { + content: txt, + callback: function() { + that.properties.show = !that.properties.show; + } + } + ]; + }; + + LGraphTextureOperation.prototype.onDrawBackground = function(ctx) { + if ( + this.flags.collapsed || + this.size[1] <= 20 || + !this.properties.show + ) { + return; + } + + if (!this._tex) { + return; + } + + //only works if using a webgl renderer + if (this._tex.gl != ctx) { + return; + } + + //render to graph canvas + ctx.save(); + ctx.drawImage(this._tex, 0, 0, this.size[0], this.size[1]); + ctx.restore(); + }; + + LGraphTextureOperation.prototype.onExecute = function() { + var tex = this.getInputData(0); + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, tex); + return; + } + + var texB = this.getInputData(1); + + if (!this.properties.uvcode && !this.properties.pixelcode) { + return; + } + + var width = 512; + var height = 512; + if (tex) { + width = tex.width; + height = tex.height; + } else if (texB) { + width = texB.width; + height = texB.height; + } + + var type = LGraphTexture.getTextureType( + this.properties.precision, + tex + ); + + if (!tex && !this._tex) { + this._tex = new GL.Texture(width, height, { + type: type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } else { + this._tex = LGraphTexture.getTargetTexture( + tex || this._tex, + this._tex, + this.properties.precision + ); + } + + var uvcode = ""; + if (this.properties.uvcode) { + uvcode = "uv = " + this.properties.uvcode; + if (this.properties.uvcode.indexOf(";") != -1) { + //there are line breaks, means multiline code + uvcode = this.properties.uvcode; + } + } + + var pixelcode = ""; + if (this.properties.pixelcode) { + pixelcode = "result = " + this.properties.pixelcode; + if (this.properties.pixelcode.indexOf(";") != -1) { + //there are line breaks, means multiline code + pixelcode = this.properties.pixelcode; + } + } + + var shader = this._shader; + + if (!shader || this._shader_code != uvcode + "|" + pixelcode) { + try { + this._shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureOperation.pixel_shader, + { UV_CODE: uvcode, PIXEL_CODE: pixelcode } + ); + this.boxcolor = "#00FF00"; + } catch (err) { + console.log("Error compiling shader: ", err); + this.boxcolor = "#FF0000"; + return; + } + this.boxcolor = "#FF0000"; + + this._shader_code = uvcode + "|" + pixelcode; + shader = this._shader; + } + + if (!shader) { + this.boxcolor = "red"; + return; + } else { + this.boxcolor = "green"; + } + + var value = this.getInputData(2); + if (value != null) { + this.properties.value = value; + } else { + value = parseFloat(this.properties.value); + } + + var time = this.graph.getTime(); + + this._tex.drawTo(function() { + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + gl.disable(gl.BLEND); + if (tex) { + tex.bind(0); + } + if (texB) { + texB.bind(1); + } + var mesh = Mesh.getScreenQuad(); + shader + .uniforms({ + u_texture: 0, + u_textureB: 1, + value: value, + texSize: [width, height], + time: time + }) + .draw(mesh); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureOperation.pixel_shader = + "precision highp float;\n\ + \n\ + uniform sampler2D u_texture;\n\ + uniform sampler2D u_textureB;\n\ + varying vec2 v_coord;\n\ + uniform vec2 texSize;\n\ + uniform float time;\n\ + uniform float value;\n\ + \n\ + void main() {\n\ + vec2 uv = v_coord;\n\ + UV_CODE;\n\ + vec4 color4 = texture2D(u_texture, uv);\n\ + vec3 color = color4.rgb;\n\ + vec4 color4B = texture2D(u_textureB, uv);\n\ + vec3 colorB = color4B.rgb;\n\ + vec3 result = color;\n\ + float alpha = 1.0;\n\ + PIXEL_CODE;\n\ + gl_FragColor = vec4(result, alpha);\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/operation", LGraphTextureOperation); + + //**************************************************** + + function LGraphTextureShader() { + this.addOutput("out", "Texture"); + this.properties = { + code: "", + width: 512, + height: 512, + precision: LGraphTexture.DEFAULT + }; + + this.properties.code = + "\nvoid main() {\n vec2 uv = v_coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n"; + this._uniforms = { in_texture: 0, texSize: vec2.create(), time: 0 }; + } + + LGraphTextureShader.title = "Shader"; + LGraphTextureShader.desc = "Texture shader"; + LGraphTextureShader.widgets_info = { + code: { type: "code" }, + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureShader.prototype.onPropertyChanged = function( + name, + value + ) { + if (name != "code") { + return; + } + + var shader = this.getShader(); + if (!shader) { + return; + } + + //update connections + var uniforms = shader.uniformInfo; + + //remove deprecated slots + if (this.inputs) { + var already = {}; + for (var i = 0; i < this.inputs.length; ++i) { + var info = this.getInputInfo(i); + if (!info) { + continue; + } + + if (uniforms[info.name] && !already[info.name]) { + already[info.name] = true; + continue; + } + this.removeInput(i); + i--; + } + } + + //update existing ones + for (var i in uniforms) { + var info = shader.uniformInfo[i]; + if (info.loc === null) { + continue; + } //is an attribute, not a uniform + if (i == "time") { + //default one + continue; + } + + var type = "number"; + if (this._shader.samplers[i]) { + type = "texture"; + } else { + switch (info.size) { + case 1: + type = "number"; + break; + case 2: + type = "vec2"; + break; + case 3: + type = "vec3"; + break; + case 4: + type = "vec4"; + break; + case 9: + type = "mat3"; + break; + case 16: + type = "mat4"; + break; + default: + continue; + } + } + + var slot = this.findInputSlot(i); + if (slot == -1) { + this.addInput(i, type); + continue; + } + + var input_info = this.getInputInfo(slot); + if (!input_info) { + this.addInput(i, type); + } else { + if (input_info.type == type) { + continue; + } + this.removeInput(slot, type); + this.addInput(i, type); + } + } + }; + + LGraphTextureShader.prototype.getShader = function() { + //replug + if (this._shader && this._shader_code == this.properties.code) { + return this._shader; + } + + this._shader_code = this.properties.code; + this._shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureShader.pixel_shader + this.properties.code + ); + if (!this._shader) { + this.boxcolor = "red"; + return null; + } else { + this.boxcolor = "green"; + } + return this._shader; + }; + + LGraphTextureShader.prototype.onExecute = function() { + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var shader = this.getShader(); + if (!shader) { + return; + } + + var tex_slot = 0; + var in_tex = null; + + //set uniforms + for (var i = 0; i < this.inputs.length; ++i) { + var info = this.getInputInfo(i); + var data = this.getInputData(i); + if (data == null) { + continue; + } + + if (data.constructor === GL.Texture) { + data.bind(tex_slot); + if (!in_tex) { + in_tex = data; + } + data = tex_slot; + tex_slot++; + } + shader.setUniform(info.name, data); //data is tex_slot + } + + var uniforms = this._uniforms; + var type = LGraphTexture.getTextureType( + this.properties.precision, + in_tex + ); + + //render to texture + var w = this.properties.width | 0; + var h = this.properties.height | 0; + if (w == 0) { + w = in_tex ? in_tex.width : gl.canvas.width; + } + if (h == 0) { + h = in_tex ? in_tex.height : gl.canvas.height; + } + uniforms.texSize[0] = w; + uniforms.texSize[1] = h; + uniforms.time = this.graph.getTime(); + + if ( + !this._tex || + this._tex.type != type || + this._tex.width != w || + this._tex.height != h + ) { + this._tex = new GL.Texture(w, h, { + type: type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } + var tex = this._tex; + tex.drawTo(function() { + shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureShader.pixel_shader = + "precision highp float;\n\ + \n\ + varying vec2 v_coord;\n\ + uniform float time;\n\ + "; + + LiteGraph.registerNodeType("texture/shader", LGraphTextureShader); + + // Texture Scale Offset + + function LGraphTextureScaleOffset() { + this.addInput("in", "Texture"); + this.addInput("scale", "vec2"); + this.addInput("offset", "vec2"); + this.addOutput("out", "Texture"); + this.properties = { + offset: vec2.fromValues(0, 0), + scale: vec2.fromValues(1, 1), + precision: LGraphTexture.DEFAULT + }; + } + + LGraphTextureScaleOffset.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureScaleOffset.title = "Scale/Offset"; + LGraphTextureScaleOffset.desc = "Applies an scaling and offseting"; + + LGraphTextureScaleOffset.prototype.onExecute = function() { + var tex = this.getInputData(0); + + if (!this.isOutputConnected(0) || !tex) { + return; + } //saves work + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, tex); + return; + } + + var width = tex.width; + var height = tex.height; + var type = + this.precision === LGraphTexture.LOW + ? gl.UNSIGNED_BYTE + : gl.HIGH_PRECISION_FORMAT; + if (this.precision === LGraphTexture.DEFAULT) { + type = tex.type; + } + + if ( + !this._tex || + this._tex.width != width || + this._tex.height != height || + this._tex.type != type + ) { + this._tex = new GL.Texture(width, height, { + type: type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } + + var shader = this._shader; + + if (!shader) { + shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureScaleOffset.pixel_shader + ); + } + + var scale = this.getInputData(1); + if (scale) { + this.properties.scale[0] = scale[0]; + this.properties.scale[1] = scale[1]; + } else { + scale = this.properties.scale; + } + + var offset = this.getInputData(2); + if (offset) { + this.properties.offset[0] = offset[0]; + this.properties.offset[1] = offset[1]; + } else { + offset = this.properties.offset; + } + + this._tex.drawTo(function() { + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + gl.disable(gl.BLEND); + tex.bind(0); + var mesh = Mesh.getScreenQuad(); + shader + .uniforms({ + u_texture: 0, + u_scale: scale, + u_offset: offset + }) + .draw(mesh); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureScaleOffset.pixel_shader = + "precision highp float;\n\ + \n\ + uniform sampler2D u_texture;\n\ + uniform sampler2D u_textureB;\n\ + varying vec2 v_coord;\n\ + uniform vec2 u_scale;\n\ + uniform vec2 u_offset;\n\ + \n\ + void main() {\n\ + vec2 uv = v_coord;\n\ + uv = uv / u_scale - u_offset;\n\ + gl_FragColor = texture2D(u_texture, uv);\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/scaleOffset", + LGraphTextureScaleOffset + ); + + // Warp (distort a texture) ************************* + + function LGraphTextureWarp() { + this.addInput("in", "Texture"); + this.addInput("warp", "Texture"); + this.addInput("factor", "number"); + this.addOutput("out", "Texture"); + this.properties = { + factor: 0.01, + precision: LGraphTexture.DEFAULT + }; + } + + LGraphTextureWarp.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureWarp.title = "Warp"; + LGraphTextureWarp.desc = "Texture warp operation"; + + LGraphTextureWarp.prototype.onExecute = function() { + var tex = this.getInputData(0); + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, tex); + return; + } + + var texB = this.getInputData(1); + + var width = 512; + var height = 512; + var type = gl.UNSIGNED_BYTE; + if (tex) { + width = tex.width; + height = tex.height; + type = tex.type; + } else if (texB) { + width = texB.width; + height = texB.height; + type = texB.type; + } + + if (!tex && !this._tex) { + this._tex = new GL.Texture(width, height, { + type: + this.precision === LGraphTexture.LOW + ? gl.UNSIGNED_BYTE + : gl.HIGH_PRECISION_FORMAT, + format: gl.RGBA, + filter: gl.LINEAR + }); + } else { + this._tex = LGraphTexture.getTargetTexture( + tex || this._tex, + this._tex, + this.properties.precision + ); + } + + var shader = this._shader; + + if (!shader) { + shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureWarp.pixel_shader + ); + } + + var factor = this.getInputData(2); + if (factor != null) { + this.properties.factor = factor; + } else { + factor = parseFloat(this.properties.factor); + } + + this._tex.drawTo(function() { + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + gl.disable(gl.BLEND); + if (tex) { + tex.bind(0); + } + if (texB) { + texB.bind(1); + } + var mesh = Mesh.getScreenQuad(); + shader + .uniforms({ u_texture: 0, u_textureB: 1, u_factor: factor }) + .draw(mesh); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureWarp.pixel_shader = + "precision highp float;\n\ + \n\ + uniform sampler2D u_texture;\n\ + uniform sampler2D u_textureB;\n\ + varying vec2 v_coord;\n\ + uniform float u_factor;\n\ + \n\ + void main() {\n\ + vec2 uv = v_coord;\n\ + uv += ( texture2D(u_textureB, uv).rg - vec2(0.5)) * u_factor;\n\ + gl_FragColor = texture2D(u_texture, uv);\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/warp", LGraphTextureWarp); + + //**************************************************** + + // Texture to Viewport ***************************************** + function LGraphTextureToViewport() { + this.addInput("Texture", "Texture"); + this.properties = { + additive: false, + antialiasing: false, + filter: true, + disable_alpha: false, + gamma: 1.0 + }; + this.size[0] = 130; + } + + LGraphTextureToViewport.title = "to Viewport"; + LGraphTextureToViewport.desc = "Texture to viewport"; + + LGraphTextureToViewport.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if (this.properties.disable_alpha) { + gl.disable(gl.BLEND); + } else { + gl.enable(gl.BLEND); + if (this.properties.additive) { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + } else { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + } + } + + gl.disable(gl.DEPTH_TEST); + var gamma = this.properties.gamma || 1.0; + if (this.isInputConnected(1)) { + gamma = this.getInputData(1); + } + + tex.setParameter( + gl.TEXTURE_MAG_FILTER, + this.properties.filter ? gl.LINEAR : gl.NEAREST + ); + + if (this.properties.antialiasing) { + if (!LGraphTextureToViewport._shader) { + LGraphTextureToViewport._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureToViewport.aa_pixel_shader + ); + } + + var viewport = gl.getViewport(); //gl.getParameter(gl.VIEWPORT); + var mesh = Mesh.getScreenQuad(); + tex.bind(0); + LGraphTextureToViewport._shader + .uniforms({ + u_texture: 0, + uViewportSize: [tex.width, tex.height], + u_igamma: 1 / gamma, + inverseVP: [1 / tex.width, 1 / tex.height] + }) + .draw(mesh); + } else { + if (gamma != 1.0) { + if (!LGraphTextureToViewport._gamma_shader) { + LGraphTextureToViewport._gamma_shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureToViewport.gamma_pixel_shader + ); + } + tex.toViewport(LGraphTextureToViewport._gamma_shader, { + u_texture: 0, + u_igamma: 1 / gamma + }); + } else { + tex.toViewport(); + } + } + }; + + LGraphTextureToViewport.prototype.onGetInputs = function() { + return [["gamma", "number"]]; + }; + + LGraphTextureToViewport.aa_pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform vec2 uViewportSize;\n\ + uniform vec2 inverseVP;\n\ + uniform float u_igamma;\n\ + #define FXAA_REDUCE_MIN (1.0/ 128.0)\n\ + #define FXAA_REDUCE_MUL (1.0 / 8.0)\n\ + #define FXAA_SPAN_MAX 8.0\n\ + \n\ + /* from mitsuhiko/webgl-meincraft based on the code on geeks3d.com */\n\ + vec4 applyFXAA(sampler2D tex, vec2 fragCoord)\n\ + {\n\ + vec4 color = vec4(0.0);\n\ + /*vec2 inverseVP = vec2(1.0 / uViewportSize.x, 1.0 / uViewportSize.y);*/\n\ + vec3 rgbNW = texture2D(tex, (fragCoord + vec2(-1.0, -1.0)) * inverseVP).xyz;\n\ + vec3 rgbNE = texture2D(tex, (fragCoord + vec2(1.0, -1.0)) * inverseVP).xyz;\n\ + vec3 rgbSW = texture2D(tex, (fragCoord + vec2(-1.0, 1.0)) * inverseVP).xyz;\n\ + vec3 rgbSE = texture2D(tex, (fragCoord + vec2(1.0, 1.0)) * inverseVP).xyz;\n\ + vec3 rgbM = texture2D(tex, fragCoord * inverseVP).xyz;\n\ + vec3 luma = vec3(0.299, 0.587, 0.114);\n\ + float lumaNW = dot(rgbNW, luma);\n\ + float lumaNE = dot(rgbNE, luma);\n\ + float lumaSW = dot(rgbSW, luma);\n\ + float lumaSE = dot(rgbSE, luma);\n\ + float lumaM = dot(rgbM, luma);\n\ + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n\ + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\ + \n\ + vec2 dir;\n\ + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n\ + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\ + \n\ + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\ + \n\ + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n\ + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * inverseVP;\n\ + \n\ + vec3 rgbA = 0.5 * (texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + \n\ + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n\ + vec3 rgbB = rgbA * 0.5 + 0.25 * (texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + \n\ + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\ + \n\ + //return vec4(rgbA,1.0);\n\ + float lumaB = dot(rgbB, luma);\n\ + if ((lumaB < lumaMin) || (lumaB > lumaMax))\n\ + color = vec4(rgbA, 1.0);\n\ + else\n\ + color = vec4(rgbB, 1.0);\n\ + if(u_igamma != 1.0)\n\ + color.xyz = pow( color.xyz, vec3(u_igamma) );\n\ + return color;\n\ + }\n\ + \n\ + void main() {\n\ + gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\ + }\n\ + "; + + LGraphTextureToViewport.gamma_pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float u_igamma;\n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord);\n\ + color.xyz = pow(color.xyz, vec3(u_igamma) );\n\ + gl_FragColor = color;\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/toviewport", + LGraphTextureToViewport + ); + + // Texture Copy ***************************************** + function LGraphTextureCopy() { + this.addInput("Texture", "Texture"); + this.addOutput("", "Texture"); + this.properties = { + size: 0, + generate_mipmaps: false, + 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 tex = this.getInputData(0); + if (!tex && !this._temp_texture) { + return; + } + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + //copy the texture + if (tex) { + var width = tex.width; + var height = tex.height; + + if (this.properties.size != 0) { + width = this.properties.size; + height = this.properties.size; + } + + var temp = this._temp_texture; + + var type = tex.type; + if (this.properties.precision === LGraphTexture.LOW) { + type = gl.UNSIGNED_BYTE; + } else if (this.properties.precision === LGraphTexture.HIGH) { + type = gl.HIGH_PRECISION_FORMAT; + } + + if ( + !temp || + temp.width != width || + temp.height != height || + temp.type != type + ) { + var minFilter = gl.LINEAR; + if ( + this.properties.generate_mipmaps && + isPowerOfTwo(width) && + isPowerOfTwo(height) + ) { + minFilter = gl.LINEAR_MIPMAP_LINEAR; + } + this._temp_texture = new GL.Texture(width, height, { + type: type, + format: gl.RGBA, + minFilter: minFilter, + magFilter: gl.LINEAR + }); + } + tex.copyTo(this._temp_texture); + + if (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); + + // Texture Downsample ***************************************** + function LGraphTextureDownsample() { + this.addInput("Texture", "Texture"); + this.addOutput("", "Texture"); + this.properties = { + iterations: 1, + generate_mipmaps: false, + precision: LGraphTexture.DEFAULT + }; + } + + LGraphTextureDownsample.title = "Downsample"; + LGraphTextureDownsample.desc = "Downsample Texture"; + LGraphTextureDownsample.widgets_info = { + iterations: { type: "number", step: 1, precision: 0, min: 0 }, + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureDownsample.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex && !this._temp_texture) { + return; + } + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + //we do not allow any texture different than texture 2D + if (!tex || tex.texture_type !== GL.TEXTURE_2D) { + return; + } + + if (this.properties.iterations < 1) { + this.setOutputData(0, tex); + return; + } + + var shader = LGraphTextureDownsample._shader; + if (!shader) { + LGraphTextureDownsample._shader = shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureDownsample.pixel_shader + ); + } + + var width = tex.width | 0; + var height = tex.height | 0; + var type = tex.type; + if (this.properties.precision === LGraphTexture.LOW) { + type = gl.UNSIGNED_BYTE; + } else if (this.properties.precision === LGraphTexture.HIGH) { + type = gl.HIGH_PRECISION_FORMAT; + } + var iterations = this.properties.iterations || 1; + + var origin = tex; + var target = null; + + var temp = []; + var options = { + type: type, + format: tex.format + }; + + var offset = vec2.create(); + var uniforms = { + u_offset: offset + }; + + if (this._texture) { + GL.Texture.releaseTemporary(this._texture); + } + + for (var i = 0; i < iterations; ++i) { + offset[0] = 1 / width; + offset[1] = 1 / height; + width = width >> 1 || 0; + height = height >> 1 || 0; + target = GL.Texture.getTemporary(width, height, options); + temp.push(target); + origin.setParameter(GL.TEXTURE_MAG_FILTER, GL.NEAREST); + origin.copyTo(target, shader, uniforms); + if (width == 1 && height == 1) { + break; + } //nothing else to do + origin = target; + } + + //keep the last texture used + this._texture = temp.pop(); + + //free the rest + for (var i = 0; i < temp.length; ++i) { + GL.Texture.releaseTemporary(temp[i]); + } + + if (this.properties.generate_mipmaps) { + this._texture.bind(0); + gl.generateMipmap(this._texture.texture_type); + this._texture.unbind(0); + } + + this.setOutputData(0, this._texture); + }; + + LGraphTextureDownsample.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + uniform sampler2D u_texture;\n\ + uniform vec2 u_offset;\n\ + varying vec2 v_coord;\n\ + \n\ + void main() {\n\ + vec4 color = texture2D(u_texture, v_coord );\n\ + color += texture2D(u_texture, v_coord + vec2( u_offset.x, 0.0 ) );\n\ + color += texture2D(u_texture, v_coord + vec2( 0.0, u_offset.y ) );\n\ + color += texture2D(u_texture, v_coord + vec2( u_offset.x, u_offset.y ) );\n\ + gl_FragColor = color * 0.25;\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/downsample", + LGraphTextureDownsample + ); + + // Texture Average ***************************************** + function LGraphTextureAverage() { + this.addInput("Texture", "Texture"); + this.addOutput("tex", "Texture"); + this.addOutput("avg", "vec4"); + this.addOutput("lum", "number"); + this.properties = { + use_previous_frame: true, + mipmap_offset: 0, + low_precision: false + }; + + this._uniforms = { + u_texture: 0, + u_mipmap_offset: this.properties.mipmap_offset + }; + this._luminance = new Float32Array(4); + } + + LGraphTextureAverage.title = "Average"; + LGraphTextureAverage.desc = + "Compute a partial average (32 random samples) of a texture and stores it as a 1x1 pixel texture"; + + LGraphTextureAverage.prototype.onExecute = function() { + if (!this.properties.use_previous_frame) { + this.updateAverage(); + } + + var v = this._luminance; + this.setOutputData(0, this._temp_texture); + this.setOutputData(1, v); + this.setOutputData(2, (v[0] + v[1] + v[2]) / 3); + }; + + //executed before rendering the frame + LGraphTextureAverage.prototype.onPreRenderExecute = function() { + this.updateAverage(); + }; + + LGraphTextureAverage.prototype.updateAverage = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if ( + !this.isOutputConnected(0) && + !this.isOutputConnected(1) && + !this.isOutputConnected(2) + ) { + return; + } //saves work + + if (!LGraphTextureAverage._shader) { + LGraphTextureAverage._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureAverage.pixel_shader + ); + //creates 32 random numbers and stores the, in two mat4 + var samples = new Float32Array(32); + for (var i = 0; i < 32; ++i) { + samples[i] = Math.random(); + } + LGraphTextureAverage._shader.uniforms({ + u_samples_a: samples.subarray(0, 16), + u_samples_b: samples.subarray(16, 32) + }); + } + + var temp = this._temp_texture; + var type = gl.UNSIGNED_BYTE; + if (tex.type != type) { + //force floats, half floats cannot be read with gl.readPixels + type = gl.FLOAT; + } + + if (!temp || temp.type != type) { + this._temp_texture = new GL.Texture(1, 1, { + type: type, + format: gl.RGBA, + filter: gl.NEAREST + }); + } + + var shader = LGraphTextureAverage._shader; + var uniforms = this._uniforms; + uniforms.u_mipmap_offset = this.properties.mipmap_offset; + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.BLEND); + this._temp_texture.drawTo(function() { + tex.toViewport(shader, uniforms); + }); + + if (this.isOutputConnected(1) || this.isOutputConnected(2)) { + var pixel = this._temp_texture.getPixels(); + if (pixel) { + var v = this._luminance; + var type = this._temp_texture.type; + v.set(pixel); + if (type == gl.UNSIGNED_BYTE) { + vec4.scale(v, v, 1 / 255); + } else if ( + type == GL.HALF_FLOAT || + type == GL.HALF_FLOAT_OES + ) { + //no half floats possible, hard to read back unless copyed to a FLOAT texture, so temp_texture is always forced to FLOAT + } + } + } + }; + + LGraphTextureAverage.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + uniform mat4 u_samples_a;\n\ + uniform mat4 u_samples_b;\n\ + uniform sampler2D u_texture;\n\ + uniform float u_mipmap_offset;\n\ + varying vec2 v_coord;\n\ + \n\ + void main() {\n\ + vec4 color = vec4(0.0);\n\ + for(int i = 0; i < 4; ++i)\n\ + for(int j = 0; j < 4; ++j)\n\ + {\n\ + color += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\ + color += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\ + }\n\ + gl_FragColor = color * 0.03125;\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/average", LGraphTextureAverage); + + function LGraphTextureTemporalSmooth() { + this.addInput("in", "Texture"); + this.addInput("factor", "Number"); + this.addOutput("out", "Texture"); + this.properties = { factor: 0.5 }; + this._uniforms = { + u_texture: 0, + u_textureB: 1, + u_factor: this.properties.factor + }; + } + + LGraphTextureTemporalSmooth.title = "Smooth"; + LGraphTextureTemporalSmooth.desc = "Smooth texture over time"; + + LGraphTextureTemporalSmooth.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex || !this.isOutputConnected(0)) { + return; + } + + if (!LGraphTextureTemporalSmooth._shader) { + LGraphTextureTemporalSmooth._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureTemporalSmooth.pixel_shader + ); + } + + var temp = this._temp_texture; + if ( + !temp || + temp.type != tex.type || + temp.width != tex.width || + temp.height != tex.height + ) { + this._temp_texture = new GL.Texture(tex.width, tex.height, { + type: tex.type, + format: gl.RGBA, + filter: gl.NEAREST + }); + this._temp_texture2 = new GL.Texture(tex.width, tex.height, { + type: tex.type, + format: gl.RGBA, + filter: gl.NEAREST + }); + tex.copyTo(this._temp_texture2); + } + + var tempA = this._temp_texture; + var tempB = this._temp_texture2; + + var shader = LGraphTextureTemporalSmooth._shader; + var uniforms = this._uniforms; + uniforms.u_factor = 1.0 - this.getInputOrProperty("factor"); + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + tempA.drawTo(function() { + tempB.bind(1); + tex.toViewport(shader, uniforms); + }); + + this.setOutputData(0, tempA); + + //swap + this._temp_texture = tempB; + this._temp_texture2 = tempA; + }; + + LGraphTextureTemporalSmooth.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + uniform sampler2D u_texture;\n\ + uniform sampler2D u_textureB;\n\ + uniform float u_factor;\n\ + varying vec2 v_coord;\n\ + \n\ + void main() {\n\ + gl_FragColor = mix( texture2D( u_texture, v_coord ), texture2D( u_textureB, v_coord ), u_factor );\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/temporal_smooth", + LGraphTextureTemporalSmooth + ); + + // Image To Texture ***************************************** + function LGraphImageToTexture() { + this.addInput("Image", "image"); + this.addOutput("", "Texture"); + this.properties = {}; + } + + LGraphImageToTexture.title = "Image to Texture"; + LGraphImageToTexture.desc = "Uploads an image to the GPU"; + //LGraphImageToTexture.widgets_info = { size: { widget:"combo", values:[0,32,64,128,256,512,1024,2048]} }; + + LGraphImageToTexture.prototype.onExecute = function() { + var img = this.getInputData(0); + if (!img) { + return; + } + + var width = img.videoWidth || img.width; + var height = img.videoHeight || img.height; + + //this is in case we are using a webgl canvas already, no need to reupload it + if (img.gltexture) { + this.setOutputData(0, img.gltexture); + return; + } + + var temp = this._temp_texture; + if (!temp || temp.width != width || temp.height != height) { + this._temp_texture = new GL.Texture(width, height, { + format: gl.RGBA, + filter: gl.LINEAR + }); + } + + try { + this._temp_texture.uploadImage(img); + } catch (err) { + console.error( + "image comes from an unsafe location, cannot be uploaded to webgl: " + + err + ); + return; + } + + this.setOutputData(0, this._temp_texture); + }; + + LiteGraph.registerNodeType( + "texture/imageToTexture", + LGraphImageToTexture + ); + + // Texture LUT ***************************************** + function LGraphTextureLUT() { + this.addInput("Texture", "Texture"); + this.addInput("LUT", "Texture"); + this.addInput("Intensity", "number"); + this.addOutput("", "Texture"); + this.properties = { + intensity: 1, + precision: LGraphTexture.DEFAULT, + texture: null + }; + + if (!LGraphTextureLUT._shader) { + LGraphTextureLUT._shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureLUT.pixel_shader + ); + } + } + + LGraphTextureLUT.widgets_info = { + texture: { widget: "texture" }, + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureLUT.title = "LUT"; + LGraphTextureLUT.desc = "Apply LUT to Texture"; + + LGraphTextureLUT.prototype.onExecute = function() { + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var tex = this.getInputData(0); + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, tex); + return; + } + + if (!tex) { + return; + } + + var lut_tex = this.getInputData(1); + + if (!lut_tex) { + lut_tex = LGraphTexture.getTexture(this.properties.texture); + } + + if (!lut_tex) { + this.setOutputData(0, tex); + return; + } + + lut_tex.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 intensity = this.properties.intensity; + if (this.isInputConnected(2)) { + this.properties.intensity = intensity = this.getInputData(2); + } + + this._tex = LGraphTexture.getTargetTexture( + tex, + this._tex, + this.properties.precision + ); + + //var mesh = Mesh.getScreenQuad(); + + this._tex.drawTo(function() { + lut_tex.bind(1); + tex.toViewport(LGraphTextureLUT._shader, { + u_texture: 0, + u_textureB: 1, + u_amount: intensity + }); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureLUT.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform sampler2D u_textureB;\n\ + uniform float u_amount;\n\ + \n\ + void main() {\n\ + lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\ + mediump float blueColor = textureColor.b * 63.0;\n\ + mediump vec2 quad1;\n\ + quad1.y = floor(floor(blueColor) / 8.0);\n\ + quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\ + mediump vec2 quad2;\n\ + quad2.y = floor(ceil(blueColor) / 8.0);\n\ + quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\ + highp vec2 texPos1;\n\ + texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\ + texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\ + highp vec2 texPos2;\n\ + texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\ + texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\ + lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\ + lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\ + lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\ + gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/LUT", LGraphTextureLUT); + + // Texture Channels ***************************************** + function LGraphTextureChannels() { + this.addInput("Texture", "Texture"); + + this.addOutput("R", "Texture"); + this.addOutput("G", "Texture"); + this.addOutput("B", "Texture"); + this.addOutput("A", "Texture"); + + this.properties = { use_luminance: true }; + if (!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 texA = this.getInputData(0); + if (!texA) { + return; + } + + if (!this._channels) { + this._channels = Array(4); + } + + var format = this.properties.use_luminance ? gl.LUMINANCE : gl.RGBA; + var connections = 0; + for (var i = 0; i < 4; i++) { + if (this.isOutputConnected(i)) { + if ( + !this._channels[i] || + this._channels[i].width != texA.width || + this._channels[i].height != texA.height || + this._channels[i].type != texA.type || + this._channels[i].format != format + ) { + this._channels[i] = new GL.Texture( + texA.width, + texA.height, + { + type: texA.type, + format: format, + filter: gl.LINEAR + } + ); + } + connections++; + } else { + this._channels[i] = null; + } + } + + if (!connections) { + return; + } + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + + var mesh = Mesh.getScreenQuad(); + var shader = LGraphTextureChannels._shader; + var masks = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ]; + + for (var i = 0; i < 4; i++) { + if (!this._channels[i]) { + continue; + } + + this._channels[i].drawTo(function() { + texA.bind(0); + shader + .uniforms({ u_texture: 0, u_mask: masks[i] }) + .draw(mesh); + }); + this.setOutputData(i, this._channels[i]); + } + }; + + LGraphTextureChannels.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform vec4 u_mask;\n\ + \n\ + void main() {\n\ + gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/textureChannels", + LGraphTextureChannels + ); + + // Texture Channels to Texture ***************************************** + function LGraphChannelsTexture() { + this.addInput("R", "Texture"); + this.addInput("G", "Texture"); + this.addInput("B", "Texture"); + this.addInput("A", "Texture"); + + this.addOutput("Texture", "Texture"); + + this.properties = { + precision: LGraphTexture.DEFAULT, + R: 1, + G: 1, + B: 1, + A: 1 + }; + this._color = vec4.create(); + this._uniforms = { + u_textureR: 0, + u_textureG: 1, + u_textureB: 2, + u_textureA: 3, + u_color: this._color + }; + } + + LGraphChannelsTexture.title = "Channels to Texture"; + LGraphChannelsTexture.desc = "Split texture channels"; + LGraphChannelsTexture.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphChannelsTexture.prototype.onExecute = function() { + var white = LGraphTexture.getWhiteTexture(); + var texR = this.getInputData(0) || white; + var texG = this.getInputData(1) || white; + var texB = this.getInputData(2) || white; + var texA = this.getInputData(3) || white; + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + + var mesh = Mesh.getScreenQuad(); + if (!LGraphChannelsTexture._shader) { + LGraphChannelsTexture._shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphChannelsTexture.pixel_shader + ); + } + var shader = LGraphChannelsTexture._shader; + + var w = Math.max(texR.width, texG.width, texB.width, texA.width); + var h = Math.max( + texR.height, + texG.height, + texB.height, + texA.height + ); + var type = + this.properties.precision == LGraphTexture.HIGH + ? LGraphTexture.HIGH_PRECISION_FORMAT + : gl.UNSIGNED_BYTE; + + if ( + !this._texture || + this._texture.width != w || + this._texture.height != h || + this._texture.type != type + ) { + this._texture = new GL.Texture(w, h, { + type: type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } + + var color = this._color; + color[0] = this.properties.R; + color[1] = this.properties.G; + color[2] = this.properties.B; + color[3] = this.properties.A; + var uniforms = this._uniforms; + + this._texture.drawTo(function() { + texR.bind(0); + texG.bind(1); + texB.bind(2); + texA.bind(3); + shader.uniforms(uniforms).draw(mesh); + }); + this.setOutputData(0, this._texture); + }; + + LGraphChannelsTexture.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_textureR;\n\ + uniform sampler2D u_textureG;\n\ + uniform sampler2D u_textureB;\n\ + uniform sampler2D u_textureA;\n\ + uniform vec4 u_color;\n\ + \n\ + void main() {\n\ + gl_FragColor = u_color * vec4( \ + texture2D(u_textureR, v_coord).r,\ + texture2D(u_textureG, v_coord).r,\ + texture2D(u_textureB, v_coord).r,\ + texture2D(u_textureA, v_coord).r);\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/channelsTexture", + LGraphChannelsTexture + ); + + // Texture Color ***************************************** + function LGraphTextureColor() { + this.addOutput("Texture", "Texture"); + + this._tex_color = vec4.create(); + this.properties = { + color: vec4.create(), + precision: LGraphTexture.DEFAULT + }; + } + + LGraphTextureColor.title = "Color"; + LGraphTextureColor.desc = + "Generates a 1x1 texture with a constant color"; + + LGraphTextureColor.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureColor.prototype.onDrawBackground = function(ctx) { + var c = this.properties.color; + ctx.fillStyle = + "rgb(" + + Math.floor(Math.clamp(c[0], 0, 1) * 255) + + "," + + Math.floor(Math.clamp(c[1], 0, 1) * 255) + + "," + + Math.floor(Math.clamp(c[2], 0, 1) * 255) + + ")"; + if (this.flags.collapsed) { + this.boxcolor = ctx.fillStyle; + } else { + ctx.fillRect(0, 0, this.size[0], this.size[1]); + } + }; + + LGraphTextureColor.prototype.onExecute = function() { + var type = + this.properties.precision == LGraphTexture.HIGH + ? LGraphTexture.HIGH_PRECISION_FORMAT + : gl.UNSIGNED_BYTE; + + if (!this._tex || this._tex.type != type) { + this._tex = new GL.Texture(1, 1, { + format: gl.RGBA, + type: type, + minFilter: gl.NEAREST + }); + } + var color = this.properties.color; + + 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; + } + switch (input.name) { + case "RGB": + case "RGBA": + color.set(v); + break; + case "R": + color[0] = v; + break; + case "G": + color[1] = v; + break; + case "B": + color[2] = v; + break; + case "A": + color[3] = v; + break; + } + } + } + + if (vec4.sqrDist(this._tex_color, color) > 0.001) { + this._tex_color.set(color); + this._tex.fill(color); + } + this.setOutputData(0, this._tex); + }; + + LGraphTextureColor.prototype.onGetInputs = function() { + return [ + ["RGB", "vec3"], + ["RGBA", "vec4"], + ["R", "number"], + ["G", "number"], + ["B", "number"], + ["A", "number"] + ]; + }; + + LiteGraph.registerNodeType("texture/color", LGraphTextureColor); + + // 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() { + this.addInput("A", "Texture"); + this.addInput("B", "Texture"); + this.addInput("Mixer", "Texture"); + + this.addOutput("Texture", "Texture"); + this.properties = { factor: 0.5, precision: LGraphTexture.DEFAULT }; + this._uniforms = { + u_textureA: 0, + u_textureB: 1, + u_textureMix: 2, + u_mix: vec4.create() + }; + } + + 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 texA = this.getInputData(0); + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, texA); + return; + } + + var texB = this.getInputData(1); + if (!texA || !texB) { + return; + } + + var texMix = this.getInputData(2); + + var factor = this.getInputData(3); + + this._tex = LGraphTexture.getTargetTexture( + texA, + this._tex, + this.properties.precision + ); + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + + var mesh = Mesh.getScreenQuad(); + var shader = null; + var uniforms = this._uniforms; + if (texMix) { + shader = LGraphTextureMix._shader_tex; + if (!shader) { + shader = LGraphTextureMix._shader_tex = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureMix.pixel_shader, + { MIX_TEX: "" } + ); + } + } else { + shader = LGraphTextureMix._shader_factor; + if (!shader) { + shader = LGraphTextureMix._shader_factor = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureMix.pixel_shader + ); + } + var f = factor == null ? this.properties.factor : factor; + uniforms.u_mix.set([f, f, f, f]); + } + + this._tex.drawTo(function() { + texA.bind(0); + texB.bind(1); + if (texMix) { + texMix.bind(2); + } + shader.uniforms(uniforms).draw(mesh); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureMix.prototype.onGetInputs = function() { + return [["factor", "number"]]; + }; + + LGraphTextureMix.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_textureA;\n\ + uniform sampler2D u_textureB;\n\ + #ifdef MIX_TEX\n\ + uniform sampler2D u_textureMix;\n\ + #else\n\ + uniform vec4 u_mix;\n\ + #endif\n\ + \n\ + void main() {\n\ + #ifdef MIX_TEX\n\ + vec4 f = texture2D(u_textureMix, v_coord);\n\ + #else\n\ + vec4 f = u_mix;\n\ + #endif\n\ + gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), f );\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/mix", LGraphTextureMix); + + // Texture Edges detection ***************************************** + function LGraphTextureEdges() { + this.addInput("Tex.", "Texture"); + + this.addOutput("Edges", "Texture"); + this.properties = { + invert: true, + threshold: false, + factor: 1, + precision: LGraphTexture.DEFAULT + }; + + if (!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() { + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var tex = this.getInputData(0); + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, tex); + return; + } + + if (!tex) { + return; + } + + this._tex = LGraphTexture.getTargetTexture( + tex, + this._tex, + this.properties.precision + ); + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + + var mesh = Mesh.getScreenQuad(); + var shader = LGraphTextureEdges._shader; + var invert = this.properties.invert; + var factor = this.properties.factor; + var threshold = this.properties.threshold ? 1 : 0; + + this._tex.drawTo(function() { + tex.bind(0); + shader + .uniforms({ + u_texture: 0, + u_isize: [1 / tex.width, 1 / tex.height], + u_factor: factor, + u_threshold: threshold, + u_invert: invert ? 1 : 0 + }) + .draw(mesh); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureEdges.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform vec2 u_isize;\n\ + uniform int u_invert;\n\ + uniform float u_factor;\n\ + uniform float u_threshold;\n\ + \n\ + void main() {\n\ + vec4 center = texture2D(u_texture, v_coord);\n\ + vec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\ + vec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\ + vec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\ + vec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\ + vec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\ + diff *= u_factor;\n\ + if(u_invert == 1)\n\ + diff.xyz = vec3(1.0) - diff.xyz;\n\ + if( u_threshold == 0.0 )\n\ + gl_FragColor = vec4( diff.xyz, center.a );\n\ + else\n\ + gl_FragColor = vec4( diff.x > 0.5 ? 1.0 : 0.0, diff.y > 0.5 ? 1.0 : 0.0, diff.z > 0.5 ? 1.0 : 0.0, center.a );\n\ + }\n\ + "; + + LiteGraph.registerNodeType("texture/edges", LGraphTextureEdges); + + // Texture Depth ***************************************** + function LGraphTextureDepthRange() { + this.addInput("Texture", "Texture"); + this.addInput("Distance", "number"); + this.addInput("Range", "number"); + this.addOutput("Texture", "Texture"); + this.properties = { + distance: 100, + range: 50, + only_depth: false, + high_precision: false + }; + this._uniforms = { + u_texture: 0, + u_distance: 100, + u_range: 50, + u_camera_planes: null + }; + } + + LGraphTextureDepthRange.title = "Depth Range"; + LGraphTextureDepthRange.desc = "Generates a texture with a depth range"; + + LGraphTextureDepthRange.prototype.onExecute = function() { + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var tex = this.getInputData(0); + if (!tex) { + return; + } + + var precision = gl.UNSIGNED_BYTE; + if (this.properties.high_precision) { + precision = gl.half_float_ext ? gl.HALF_FLOAT_OES : gl.FLOAT; + } + + if ( + !this._temp_texture || + this._temp_texture.type != precision || + this._temp_texture.width != tex.width || + this._temp_texture.height != tex.height + ) { + this._temp_texture = new GL.Texture(tex.width, tex.height, { + type: precision, + format: gl.RGBA, + filter: gl.LINEAR + }); + } + + var uniforms = this._uniforms; + + //iterations + var distance = this.properties.distance; + if (this.isInputConnected(1)) { + distance = this.getInputData(1); + this.properties.distance = distance; + } + + var range = this.properties.range; + if (this.isInputConnected(2)) { + range = this.getInputData(2); + this.properties.range = range; + } + + uniforms.u_distance = distance; + uniforms.u_range = range; + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + var mesh = Mesh.getScreenQuad(); + if (!LGraphTextureDepthRange._shader) { + LGraphTextureDepthRange._shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureDepthRange.pixel_shader + ); + LGraphTextureDepthRange._shader_onlydepth = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureDepthRange.pixel_shader, + { ONLY_DEPTH: "" } + ); + } + var shader = this.properties.only_depth + ? LGraphTextureDepthRange._shader_onlydepth + : LGraphTextureDepthRange._shader; + + //NEAR AND FAR PLANES + var planes = null; + if (tex.near_far_planes) { + planes = tex.near_far_planes; + } else if (window.LS && LS.Renderer._main_camera) { + planes = LS.Renderer._main_camera._uniforms.u_camera_planes; + } else { + planes = [0.1, 1000]; + } //hardcoded + uniforms.u_camera_planes = planes; + + this._temp_texture.drawTo(function() { + tex.bind(0); + shader.uniforms(uniforms).draw(mesh); + }); + + this._temp_texture.near_far_planes = planes; + this.setOutputData(0, this._temp_texture); + }; + + LGraphTextureDepthRange.pixel_shader = + "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform vec2 u_camera_planes;\n\ + uniform float u_distance;\n\ + uniform float u_range;\n\ + \n\ + float LinearDepth()\n\ + {\n\ + float zNear = u_camera_planes.x;\n\ + float zFar = u_camera_planes.y;\n\ + float depth = texture2D(u_texture, v_coord).x;\n\ + depth = depth * 2.0 - 1.0;\n\ + return zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\ + }\n\ + \n\ + void main() {\n\ + float depth = LinearDepth();\n\ + #ifdef ONLY_DEPTH\n\ + gl_FragColor = vec4(depth);\n\ + #else\n\ + float diff = abs(depth * u_camera_planes.y - u_distance);\n\ + float dof = 1.0;\n\ + if(diff <= u_range)\n\ + dof = diff / u_range;\n\ + gl_FragColor = vec4(dof);\n\ + #endif\n\ + }\n\ + "; + + LiteGraph.registerNodeType( + "texture/depth_range", + LGraphTextureDepthRange + ); + + // Texture Blur ***************************************** + function LGraphTextureBlur() { + this.addInput("Texture", "Texture"); + this.addInput("Iterations", "number"); + this.addInput("Intensity", "number"); + this.addOutput("Blurred", "Texture"); + this.properties = { + intensity: 1, + iterations: 1, + preserve_aspect: false, + scale: [1, 1], + precision: LGraphTexture.DEFAULT + }; + } + + LGraphTextureBlur.title = "Blur"; + LGraphTextureBlur.desc = "Blur a texture"; + + LGraphTextureBlur.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureBlur.max_iterations = 20; + + LGraphTextureBlur.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var temp = this._final_texture; + + if ( + !temp || + temp.width != tex.width || + temp.height != tex.height || + temp.type != tex.type + ) { + //we need two textures to do the blurring + //this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + temp = this._final_texture = new GL.Texture( + tex.width, + tex.height, + { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } + ); + } + + //iterations + var iterations = this.properties.iterations; + if (this.isInputConnected(1)) { + iterations = this.getInputData(1); + this.properties.iterations = iterations; + } + iterations = Math.min( + Math.floor(iterations), + LGraphTextureBlur.max_iterations + ); + if (iterations == 0) { + //skip blurring + this.setOutputData(0, tex); + return; + } + + var intensity = this.properties.intensity; + if (this.isInputConnected(2)) { + intensity = this.getInputData(2); + this.properties.intensity = intensity; + } + + //blur sometimes needs an aspect correction + var aspect = LiteGraph.camera_aspect; + if (!aspect && window.gl !== undefined) { + aspect = gl.canvas.height / gl.canvas.width; + } + if (!aspect) { + aspect = 1; + } + aspect = this.properties.preserve_aspect ? aspect : 1; + + var scale = this.properties.scale || [1, 1]; + tex.applyBlur(aspect * scale[0], scale[1], intensity, temp); + for (var i = 1; i < iterations; ++i) { + temp.applyBlur( + aspect * scale[0] * (i + 1), + scale[1] * (i + 1), + intensity + ); + } + + this.setOutputData(0, temp); + }; + + /* + LGraphTextureBlur.pixel_shader = "precision highp float;\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform vec2 u_offset;\n\ + uniform float u_intensity;\n\ + void main() {\n\ + vec4 sum = vec4(0.0);\n\ + vec4 center = texture2D(u_texture, v_coord);\n\ + sum += texture2D(u_texture, v_coord + u_offset * -4.0) * 0.05/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * -3.0) * 0.09/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * -2.0) * 0.12/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * -1.0) * 0.15/0.98;\n\ + sum += center * 0.16/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * 4.0) * 0.05/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * 3.0) * 0.09/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * 2.0) * 0.12/0.98;\n\ + sum += texture2D(u_texture, v_coord + u_offset * 1.0) * 0.15/0.98;\n\ + gl_FragColor = u_intensity * sum;\n\ + }\n\ + "; + */ + + LiteGraph.registerNodeType("texture/blur", LGraphTextureBlur); + + // Texture Glow ***************************************** + //based in https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/ + function LGraphTextureGlow() { + this.addInput("in", "Texture"); + this.addInput("dirt", "Texture"); + this.addOutput("out", "Texture"); + this.addOutput("glow", "Texture"); + this.properties = { + enabled: true, + intensity: 1, + persistence: 0.99, + iterations: 16, + threshold: 0, + scale: 1, + dirt_factor: 0.5, + precision: LGraphTexture.DEFAULT + }; + this._textures = []; + this._uniforms = { + u_intensity: 1, + u_texture: 0, + u_glow_texture: 1, + u_threshold: 0, + u_texel_size: vec2.create() + }; + } + + LGraphTextureGlow.title = "Glow"; + LGraphTextureGlow.desc = "Filters a texture giving it a glow effect"; + LGraphTextureGlow.weights = new Float32Array([0.5, 0.4, 0.3, 0.2]); + + LGraphTextureGlow.widgets_info = { + iterations: { + type: "number", + min: 0, + max: 16, + step: 1, + precision: 0 + }, + threshold: { + type: "number", + min: 0, + max: 10, + step: 0.01, + precision: 2 + }, + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureGlow.prototype.onGetInputs = function() { + return [ + ["enabled", "boolean"], + ["threshold", "number"], + ["intensity", "number"], + ["persistence", "number"], + ["iterations", "number"], + ["dirt_factor", "number"] + ]; + }; + + LGraphTextureGlow.prototype.onGetOutputs = function() { + return [["average", "Texture"]]; + }; + + LGraphTextureGlow.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if (!this.isAnyOutputConnected()) { + return; + } //saves work + + if ( + this.properties.precision === LGraphTexture.PASS_THROUGH || + this.getInputOrProperty("enabled") === false + ) { + this.setOutputData(0, tex); + return; + } + + var width = tex.width; + var height = tex.height; + + var texture_info = { + format: tex.format, + type: tex.type, + minFilter: GL.LINEAR, + magFilter: GL.LINEAR, + wrap: gl.CLAMP_TO_EDGE + }; + var type = LGraphTexture.getTextureType( + this.properties.precision, + tex + ); + + var uniforms = this._uniforms; + var textures = this._textures; + + //cut + var shader = LGraphTextureGlow._cut_shader; + if (!shader) { + shader = LGraphTextureGlow._cut_shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureGlow.cut_pixel_shader + ); + } + + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.BLEND); + + uniforms.u_threshold = this.getInputOrProperty("threshold"); + var currentDestination = (textures[0] = GL.Texture.getTemporary( + width, + height, + texture_info + )); + tex.blit(currentDestination, shader.uniforms(uniforms)); + var currentSource = currentDestination; + + var iterations = this.getInputOrProperty("iterations"); + iterations = Math.clamp(iterations, 1, 16) | 0; + var texel_size = uniforms.u_texel_size; + var intensity = this.getInputOrProperty("intensity"); + + uniforms.u_intensity = 1; + uniforms.u_delta = this.properties.scale; //1 + + //downscale/upscale shader + var shader = LGraphTextureGlow._shader; + if (!shader) { + shader = LGraphTextureGlow._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureGlow.scale_pixel_shader + ); + } + + var i = 1; + //downscale + for (; i < iterations; i++) { + width = width >> 1; + if ((height | 0) > 1) { + height = height >> 1; + } + if (width < 2) { + break; + } + currentDestination = textures[i] = GL.Texture.getTemporary( + width, + height, + texture_info + ); + texel_size[0] = 1 / currentSource.width; + texel_size[1] = 1 / currentSource.height; + currentSource.blit( + currentDestination, + shader.uniforms(uniforms) + ); + currentSource = currentDestination; + } + + //average + if (this.isOutputConnected(2)) { + var average_texture = this._average_texture; + if ( + !average_texture || + average_texture.type != tex.type || + average_texture.format != tex.format + ) { + average_texture = this._average_texture = new GL.Texture( + 1, + 1, + { + type: tex.type, + format: tex.format, + filter: gl.LINEAR + } + ); + } + texel_size[0] = 1 / currentSource.width; + texel_size[1] = 1 / currentSource.height; + uniforms.u_intensity = intensity; + uniforms.u_delta = 1; + currentSource.blit(average_texture, shader.uniforms(uniforms)); + this.setOutputData(2, average_texture); + } + + //upscale and blend + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ONE); + uniforms.u_intensity = this.getInputOrProperty("persistence"); + uniforms.u_delta = 0.5; + + for ( + i -= 2; + i >= 0; + i-- // i-=2 => -1 to point to last element in array, -1 to go to texture above + ) { + currentDestination = textures[i]; + textures[i] = null; + texel_size[0] = 1 / currentSource.width; + texel_size[1] = 1 / currentSource.height; + currentSource.blit( + currentDestination, + shader.uniforms(uniforms) + ); + GL.Texture.releaseTemporary(currentSource); + currentSource = currentDestination; + } + gl.disable(gl.BLEND); + + //glow + if (this.isOutputConnected(1)) { + var glow_texture = this._glow_texture; + if ( + !glow_texture || + glow_texture.width != tex.width || + glow_texture.height != tex.height || + glow_texture.type != type || + glow_texture.format != tex.format + ) { + glow_texture = this._glow_texture = new GL.Texture( + tex.width, + tex.height, + { type: type, format: tex.format, filter: gl.LINEAR } + ); + } + currentSource.blit(glow_texture); + this.setOutputData(1, glow_texture); + } + + //final composition + if (this.isOutputConnected(0)) { + var final_texture = this._final_texture; + if ( + !final_texture || + final_texture.width != tex.width || + final_texture.height != tex.height || + final_texture.type != type || + final_texture.format != tex.format + ) { + final_texture = this._final_texture = new GL.Texture( + tex.width, + tex.height, + { type: type, format: tex.format, filter: gl.LINEAR } + ); + } + + var dirt_texture = this.getInputData(1); + var dirt_factor = this.getInputOrProperty("dirt_factor"); + + uniforms.u_intensity = intensity; + + shader = dirt_texture + ? LGraphTextureGlow._dirt_final_shader + : LGraphTextureGlow._final_shader; + if (!shader) { + if (dirt_texture) { shader = LGraphTextureGlow._dirt_final_shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureGlow.final_pixel_shader, { USE_DIRT: "" } ); - else + } else { shader = LGraphTextureGlow._final_shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureGlow.final_pixel_shader ); + } } final_texture.drawTo(function() { @@ -2908,74 +3158,102 @@ glow = mix( glow, glow * texture2D( u_dirt_texture, v_coord ), u_dirt_factor );\n\ #endif\n\ gl_FragColor = texture2D( u_texture, v_coord ) + u_intensity * glow;\n\ - }" + }"; - LiteGraph.registerNodeType("texture/glow", LGraphTextureGlow ); + LiteGraph.registerNodeType("texture/glow", LGraphTextureGlow); + // Texture Filter ***************************************** + function LGraphTextureKuwaharaFilter() { + this.addInput("Texture", "Texture"); + this.addOutput("Filtered", "Texture"); + this.properties = { intensity: 1, radius: 5 }; + } - // Texture Filter ***************************************** - function LGraphTextureKuwaharaFilter() - { - this.addInput("Texture","Texture"); - this.addOutput("Filtered","Texture"); - this.properties = { intensity: 1, radius: 5 }; - } + LGraphTextureKuwaharaFilter.title = "Kuwahara Filter"; + LGraphTextureKuwaharaFilter.desc = + "Filters a texture giving an artistic oil canvas painting"; - LGraphTextureKuwaharaFilter.title = "Kuwahara Filter"; - LGraphTextureKuwaharaFilter.desc = "Filters a texture giving an artistic oil canvas painting"; + LGraphTextureKuwaharaFilter.max_radius = 10; + LGraphTextureKuwaharaFilter._shaders = []; - LGraphTextureKuwaharaFilter.max_radius = 10; - LGraphTextureKuwaharaFilter._shaders = []; + LGraphTextureKuwaharaFilter.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } - LGraphTextureKuwaharaFilter.prototype.onExecute = function() - { - var tex = this.getInputData(0); - if(!tex) - return; + if (!this.isOutputConnected(0)) { + return; + } //saves work - if(!this.isOutputConnected(0)) - return; //saves work + var temp = this._temp_texture; - var temp = this._temp_texture; + if ( + !temp || + temp.width != tex.width || + temp.height != tex.height || + temp.type != tex.type + ) { + this._temp_texture = new GL.Texture(tex.width, tex.height, { + type: tex.type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } - if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) - this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + //iterations + var radius = this.properties.radius; + radius = Math.min( + Math.floor(radius), + LGraphTextureKuwaharaFilter.max_radius + ); + if (radius == 0) { + //skip blurring + this.setOutputData(0, tex); + return; + } - //iterations - var radius = this.properties.radius; - radius = Math.min( Math.floor(radius), LGraphTextureKuwaharaFilter.max_radius ); - if(radius == 0) //skip blurring - { - this.setOutputData(0, tex); - return; - } + var intensity = this.properties.intensity; - var intensity = this.properties.intensity; + //blur sometimes needs an aspect correction + var aspect = LiteGraph.camera_aspect; + if (!aspect && window.gl !== undefined) { + aspect = gl.canvas.height / gl.canvas.width; + } + if (!aspect) { + aspect = 1; + } + aspect = this.properties.preserve_aspect ? aspect : 1; - //blur sometimes needs an aspect correction - var aspect = LiteGraph.camera_aspect; - if(!aspect && window.gl !== undefined) - aspect = gl.canvas.height / gl.canvas.width; - if(!aspect) - aspect = 1; - aspect = this.properties.preserve_aspect ? aspect : 1; + if (!LGraphTextureKuwaharaFilter._shaders[radius]) { + LGraphTextureKuwaharaFilter._shaders[radius] = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureKuwaharaFilter.pixel_shader, + { RADIUS: radius.toFixed(0) } + ); + } - if(!LGraphTextureKuwaharaFilter._shaders[ radius ]) - LGraphTextureKuwaharaFilter._shaders[ radius ] = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphTextureKuwaharaFilter.pixel_shader, { RADIUS: radius.toFixed(0) }); + var shader = LGraphTextureKuwaharaFilter._shaders[radius]; + var mesh = GL.Mesh.getScreenQuad(); + tex.bind(0); - var shader = LGraphTextureKuwaharaFilter._shaders[ radius ]; - var mesh = GL.Mesh.getScreenQuad(); - tex.bind(0); + this._temp_texture.drawTo(function() { + shader + .uniforms({ + u_texture: 0, + u_intensity: intensity, + u_resolution: [tex.width, tex.height], + u_iResolution: [1 / tex.width, 1 / tex.height] + }) + .draw(mesh); + }); - this._temp_texture.drawTo( function() { - shader.uniforms({ u_texture: 0, u_intensity: intensity, u_resolution: [tex.width, tex.height], u_iResolution: [1/tex.width,1/tex.height]}).draw(mesh); - }); + this.setOutputData(0, this._temp_texture); + }; - this.setOutputData(0, this._temp_texture); - } - -//from https://www.shadertoy.com/view/MsXSz4 -LGraphTextureKuwaharaFilter.pixel_shader = "\n\ + //from https://www.shadertoy.com/view/MsXSz4 + LGraphTextureKuwaharaFilter.pixel_shader = + "\n\ precision highp float;\n\ varying vec2 v_coord;\n\ uniform sampler2D u_texture;\n\ @@ -3069,55 +3347,91 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ }\n\ "; - LiteGraph.registerNodeType("texture/kuwahara", LGraphTextureKuwaharaFilter ); + LiteGraph.registerNodeType( + "texture/kuwahara", + LGraphTextureKuwaharaFilter + ); - // Texture ***************************************** - function LGraphTextureXDoGFilter() - { - this.addInput("Texture","Texture"); - this.addOutput("Filtered","Texture"); - this.properties = { sigma: 1.4, k: 1.6, p:21.7, epsilon:79, phi:0.017 }; - } + // Texture ***************************************** + function LGraphTextureXDoGFilter() { + this.addInput("Texture", "Texture"); + this.addOutput("Filtered", "Texture"); + this.properties = { + sigma: 1.4, + k: 1.6, + p: 21.7, + epsilon: 79, + phi: 0.017 + }; + } - LGraphTextureXDoGFilter.title = "XDoG Filter"; - LGraphTextureXDoGFilter.desc = "Filters a texture giving an artistic ink style"; + LGraphTextureXDoGFilter.title = "XDoG Filter"; + LGraphTextureXDoGFilter.desc = + "Filters a texture giving an artistic ink style"; - LGraphTextureXDoGFilter.max_radius = 10; - LGraphTextureXDoGFilter._shaders = []; + LGraphTextureXDoGFilter.max_radius = 10; + LGraphTextureXDoGFilter._shaders = []; - LGraphTextureXDoGFilter.prototype.onExecute = function() - { - var tex = this.getInputData(0); - if(!tex) - return; + LGraphTextureXDoGFilter.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } - if(!this.isOutputConnected(0)) - return; //saves work + if (!this.isOutputConnected(0)) { + return; + } //saves work - var temp = this._temp_texture; - if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) - this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + var temp = this._temp_texture; + if ( + !temp || + temp.width != tex.width || + temp.height != tex.height || + temp.type != tex.type + ) { + this._temp_texture = new GL.Texture(tex.width, tex.height, { + type: tex.type, + format: gl.RGBA, + filter: gl.LINEAR + }); + } - if(!LGraphTextureXDoGFilter._xdog_shader) - LGraphTextureXDoGFilter._xdog_shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphTextureXDoGFilter.xdog_pixel_shader ); - var shader = LGraphTextureXDoGFilter._xdog_shader; - var mesh = GL.Mesh.getScreenQuad(); + if (!LGraphTextureXDoGFilter._xdog_shader) { + LGraphTextureXDoGFilter._xdog_shader = new GL.Shader( + Shader.SCREEN_VERTEX_SHADER, + LGraphTextureXDoGFilter.xdog_pixel_shader + ); + } + var shader = LGraphTextureXDoGFilter._xdog_shader; + var mesh = GL.Mesh.getScreenQuad(); - var sigma = this.properties.sigma; - var k = this.properties.k; - var p = this.properties.p; - var epsilon = this.properties.epsilon; - var phi = this.properties.phi; - tex.bind(0); - this._temp_texture.drawTo( function() { - shader.uniforms({ src:0, sigma: sigma, k:k, p:p, epsilon:epsilon, phi:phi, cvsWidth: tex.width, cvsHeight: tex.height }).draw(mesh); - }); + var sigma = this.properties.sigma; + var k = this.properties.k; + var p = this.properties.p; + var epsilon = this.properties.epsilon; + var phi = this.properties.phi; + tex.bind(0); + this._temp_texture.drawTo(function() { + shader + .uniforms({ + src: 0, + sigma: sigma, + k: k, + p: p, + epsilon: epsilon, + phi: phi, + cvsWidth: tex.width, + cvsHeight: tex.height + }) + .draw(mesh); + }); - this.setOutputData(0, this._temp_texture ); - } + this.setOutputData(0, this._temp_texture); + }; - //from https://github.com/RaymondMcGuire/GPU-Based-Image-Processing-Tools/blob/master/lib_webgl/scripts/main.js - LGraphTextureXDoGFilter.xdog_pixel_shader = "\n\ + //from https://github.com/RaymondMcGuire/GPU-Based-Image-Processing-Tools/blob/master/lib_webgl/scripts/main.js + LGraphTextureXDoGFilter.xdog_pixel_shader = + "\n\ precision highp float;\n\ uniform sampler2D src;\n\n\ uniform float cvsHeight;\n\ @@ -3161,254 +3475,297 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ for(int cnt=0;cnt (2*halfWidth+1)*(2*halfWidth+1)){break;}\n\ int i = int(cnt / (2*halfWidth+1)) - halfWidth;\n\ - int j = cnt - halfWidth - int(cnt / (2*halfWidth+1)) * (2*halfWidth+1);\n\n\ - float d = length(vec2(i,j));\n\ - vec2 kernel = vec2( exp( -d * d / twoSigmaESquared ), \n\ - exp( -d * d / twoSigmaRSquared ));\n\n\ - vec2 L = texture2D(src, (uv + vec2(i,j)) * Frag).xx;\n\n\ - norm += kernel;\n\ - sum += kernel * L;\n\ - }\n\n\ - sum /= norm;\n\n\ - float H = 100.0 * ((1.0 + p) * sum.x - p * sum.y);\n\ - float edge = ( H > epsilon )? 1.0 : 1.0 + tanh( phi * (H - epsilon));\n\ - destColor = vec3(edge);\n\ - gl_FragColor = vec4(destColor, 1.0);\n\ - }"; - - LiteGraph.registerNodeType("texture/xDoG", LGraphTextureXDoGFilter ); - - // Texture Webcam ***************************************** - function LGraphTextureWebcam() - { - this.addOutput("Webcam","Texture"); - this.properties = { texture_name: "", facingMode: "user" }; - this.boxcolor = "black"; - this.version = 0; - } - - LGraphTextureWebcam.title = "Webcam"; - LGraphTextureWebcam.desc = "Webcam texture"; - - LGraphTextureWebcam.is_webcam_open = false; - - LGraphTextureWebcam.prototype.openStream = function() - { - if (!navigator.getUserMedia) { - //console.log('getUserMedia() is not supported in your browser, use chrome and enable WebRTC from about://flags'); - return; - } - - this._waiting_confirmation = true; - - // Not showing vendor prefixes. - var constraints = { audio: false, video: { facingMode: this.properties.facingMode } }; - navigator.mediaDevices.getUserMedia( constraints ).then( this.streamReady.bind(this) ).catch( onFailSoHard ); - - var that = this; - function onFailSoHard(e) { - LGraphTextureWebcam.is_webcam_open = false; - console.log('Webcam rejected', e); - that._webcam_stream = false; - that.boxcolor = "red"; - that.trigger("stream_error"); - } - } - - LGraphTextureWebcam.prototype.closeStream = function() - { - if(this._webcam_stream) - { - var tracks = this._webcam_stream.getTracks(); - if(tracks.length) - { - for(var i = 0;i < tracks.length; ++i) - tracks[i].stop(); - } - LGraphTextureWebcam.is_webcam_open = false; - this._webcam_stream = null; - this._video = null; - this.boxcolor = "black"; - this.trigger("stream_closed"); - } - } - - LGraphTextureWebcam.prototype.streamReady = function(localMediaStream) - { - this._webcam_stream = localMediaStream; - //this._waiting_confirmation = false; - this.boxcolor = "green"; - var video = this._video; - if(!video) - { - video = document.createElement("video"); - video.autoplay = true; - video.srcObject = localMediaStream; - this._video = video; - //document.body.appendChild( video ); //debug - //when video info is loaded (size and so) - video.onloadedmetadata = function(e) { - // Ready to go. Do some stuff. - LGraphTextureWebcam.is_webcam_open = true; - console.log(e); - }; - } - this.trigger("stream_ready",video); - } - - LGraphTextureWebcam.prototype.onPropertyChanged = function(name,value) - { - if(name == "facingMode") - { - this.properties.facingMode = value; - this.closeStream(); - this.openStream(); - } - } - - LGraphTextureWebcam.prototype.onRemoved = function() - { - if(!this._webcam_stream) - return; - - var tracks = this._webcam_stream.getTracks(); - if(tracks.length) - { - for(var i = 0;i < tracks.length; ++i) - tracks[i].stop(); - } - - this._webcam_stream = null; - this._video = null; - } - - LGraphTextureWebcam.prototype.onDrawBackground = function(ctx) - { - if(this.flags.collapsed || this.size[1] <= 20) - return; - - if(!this._video) - return; + int j = cnt - halfWidth - int(cnt / (2*halfWidth+1)) * (2*halfWidth+1);\n\n\ + float d = length(vec2(i,j));\n\ + vec2 kernel = vec2( exp( -d * d / twoSigmaESquared ), \n\ + exp( -d * d / twoSigmaRSquared ));\n\n\ + vec2 L = texture2D(src, (uv + vec2(i,j)) * Frag).xx;\n\n\ + norm += kernel;\n\ + sum += kernel * L;\n\ + }\n\n\ + sum /= norm;\n\n\ + float H = 100.0 * ((1.0 + p) * sum.x - p * sum.y);\n\ + float edge = ( H > epsilon )? 1.0 : 1.0 + tanh( phi * (H - epsilon));\n\ + destColor = vec3(edge);\n\ + gl_FragColor = vec4(destColor, 1.0);\n\ + }"; - //render to graph canvas - ctx.save(); - if(!ctx.webgl) //reverse image - ctx.drawImage(this._video, 0, 0, this.size[0], this.size[1]); - else - { - if(this._video_texture) - ctx.drawImage(this._video_texture, 0, 0, this.size[0], this.size[1]); - } - ctx.restore(); - } + LiteGraph.registerNodeType("texture/xDoG", LGraphTextureXDoGFilter); - LGraphTextureWebcam.prototype.onExecute = function() - { - if(this._webcam_stream == null && !this._waiting_confirmation) - this.openStream(); + // Texture Webcam ***************************************** + function LGraphTextureWebcam() { + this.addOutput("Webcam", "Texture"); + this.properties = { texture_name: "", facingMode: "user" }; + this.boxcolor = "black"; + this.version = 0; + } - if(!this._video || !this._video.videoWidth) - return; + LGraphTextureWebcam.title = "Webcam"; + LGraphTextureWebcam.desc = "Webcam texture"; - var width = this._video.videoWidth; - var height = this._video.videoHeight; + LGraphTextureWebcam.is_webcam_open = false; - var temp = this._video_texture; - if(!temp || temp.width != width || temp.height != height ) - this._video_texture = new GL.Texture( width, height, { format: gl.RGB, filter: gl.LINEAR }); + LGraphTextureWebcam.prototype.openStream = function() { + if (!navigator.getUserMedia) { + //console.log('getUserMedia() is not supported in your browser, use chrome and enable WebRTC from about://flags'); + return; + } - this._video_texture.uploadImage( this._video ); - this._video_texture.version = ++this.version; - - if(this.properties.texture_name) - { - var container = LGraphTexture.getTexturesContainer(); - container[ this.properties.texture_name ] = this._video_texture; - } + this._waiting_confirmation = true; - this.setOutputData(0,this._video_texture); - for(var i = 1; i < this.outputs.length; ++i) - { - if(!this.outputs[i]) - continue; - switch( this.outputs[i].name ) - { - case "width": this.setOutputData(i,this._video.videoWidth);break; - case "height": this.setOutputData(i,this._video.videoHeight);break; - } - } - } + // Not showing vendor prefixes. + var constraints = { + audio: false, + video: { facingMode: this.properties.facingMode } + }; + navigator.mediaDevices + .getUserMedia(constraints) + .then(this.streamReady.bind(this)) + .catch(onFailSoHard); - LGraphTextureWebcam.prototype.onGetOutputs = function() - { - return [["width","number"],["height","number"],["stream_ready",LiteGraph.EVENT],["stream_closed",LiteGraph.EVENT],["stream_error",LiteGraph.EVENT]]; - } + var that = this; + function onFailSoHard(e) { + LGraphTextureWebcam.is_webcam_open = false; + console.log("Webcam rejected", e); + that._webcam_stream = false; + that.boxcolor = "red"; + that.trigger("stream_error"); + } + }; - LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam ); + LGraphTextureWebcam.prototype.closeStream = function() { + if (this._webcam_stream) { + var tracks = this._webcam_stream.getTracks(); + if (tracks.length) { + for (var i = 0; i < tracks.length; ++i) { + tracks[i].stop(); + } + } + LGraphTextureWebcam.is_webcam_open = false; + this._webcam_stream = null; + this._video = null; + this.boxcolor = "black"; + this.trigger("stream_closed"); + } + }; + LGraphTextureWebcam.prototype.streamReady = function(localMediaStream) { + this._webcam_stream = localMediaStream; + //this._waiting_confirmation = false; + this.boxcolor = "green"; + var video = this._video; + if (!video) { + video = document.createElement("video"); + video.autoplay = true; + video.srcObject = localMediaStream; + this._video = video; + //document.body.appendChild( video ); //debug + //when video info is loaded (size and so) + video.onloadedmetadata = function(e) { + // Ready to go. Do some stuff. + LGraphTextureWebcam.is_webcam_open = true; + console.log(e); + }; + } + this.trigger("stream_ready", video); + }; + LGraphTextureWebcam.prototype.onPropertyChanged = function( + name, + value + ) { + if (name == "facingMode") { + this.properties.facingMode = value; + this.closeStream(); + this.openStream(); + } + }; - //from https://github.com/spite/Wagner - function LGraphLensFX() - { - this.addInput("in","Texture"); - this.addInput("f","number"); - this.addOutput("out","Texture"); - this.properties = { enabled: true, factor: 1, precision: LGraphTexture.LOW }; + LGraphTextureWebcam.prototype.onRemoved = function() { + if (!this._webcam_stream) { + return; + } - this._uniforms = { u_texture: 0, u_factor: 1 }; - } + var tracks = this._webcam_stream.getTracks(); + if (tracks.length) { + for (var i = 0; i < tracks.length; ++i) { + tracks[i].stop(); + } + } - LGraphLensFX.title = "Lens FX"; - LGraphLensFX.desc = "distortion and chromatic aberration"; + this._webcam_stream = null; + this._video = null; + }; - LGraphLensFX.widgets_info = { - "precision": { widget:"combo", values: LGraphTexture.MODE_VALUES } - }; + LGraphTextureWebcam.prototype.onDrawBackground = function(ctx) { + if (this.flags.collapsed || this.size[1] <= 20) { + return; + } - LGraphLensFX.prototype.onGetInputs = function() { return [["enabled","boolean"]]; } + if (!this._video) { + return; + } - LGraphLensFX.prototype.onExecute = function() - { - var tex = this.getInputData(0); - if(!tex) - return; + //render to graph canvas + ctx.save(); + if (!ctx.webgl) { + //reverse image + ctx.drawImage(this._video, 0, 0, this.size[0], this.size[1]); + } else { + if (this._video_texture) { + ctx.drawImage( + this._video_texture, + 0, + 0, + this.size[0], + this.size[1] + ); + } + } + ctx.restore(); + }; - if(!this.isOutputConnected(0)) - return; //saves work + LGraphTextureWebcam.prototype.onExecute = function() { + if (this._webcam_stream == null && !this._waiting_confirmation) { + this.openStream(); + } - if(this.properties.precision === LGraphTexture.PASS_THROUGH || this.getInputOrProperty("enabled" ) === false ) - { - this.setOutputData(0, tex ); - return; - } + if (!this._video || !this._video.videoWidth) { + return; + } - var temp = this._temp_texture; - if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) - temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + var width = this._video.videoWidth; + var height = this._video.videoHeight; - var shader = LGraphLensFX._shader; - if(!shader) - shader = LGraphLensFX._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphLensFX.pixel_shader ); + var temp = this._video_texture; + if (!temp || temp.width != width || temp.height != height) { + this._video_texture = new GL.Texture(width, height, { + format: gl.RGB, + filter: gl.LINEAR + }); + } - var factor = this.getInputData(1); - if(factor == null) - factor = this.properties.factor; + this._video_texture.uploadImage(this._video); + this._video_texture.version = ++this.version; - var uniforms = this._uniforms; - uniforms.u_factor = factor; + if (this.properties.texture_name) { + var container = LGraphTexture.getTexturesContainer(); + container[this.properties.texture_name] = this._video_texture; + } - //apply shader - gl.disable( gl.DEPTH_TEST ); - temp.drawTo(function(){ - tex.bind(0); - shader.uniforms(uniforms).draw( GL.Mesh.getScreenQuad() ); - }); + this.setOutputData(0, this._video_texture); + for (var i = 1; i < this.outputs.length; ++i) { + if (!this.outputs[i]) { + continue; + } + switch (this.outputs[i].name) { + case "width": + this.setOutputData(i, this._video.videoWidth); + break; + case "height": + this.setOutputData(i, this._video.videoHeight); + break; + } + } + }; - this.setOutputData(0,temp); - } + LGraphTextureWebcam.prototype.onGetOutputs = function() { + return [ + ["width", "number"], + ["height", "number"], + ["stream_ready", LiteGraph.EVENT], + ["stream_closed", LiteGraph.EVENT], + ["stream_error", LiteGraph.EVENT] + ]; + }; - LGraphLensFX.pixel_shader = "precision highp float;\n\ + LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam); + + //from https://github.com/spite/Wagner + function LGraphLensFX() { + this.addInput("in", "Texture"); + this.addInput("f", "number"); + this.addOutput("out", "Texture"); + this.properties = { + enabled: true, + factor: 1, + precision: LGraphTexture.LOW + }; + + this._uniforms = { u_texture: 0, u_factor: 1 }; + } + + LGraphLensFX.title = "Lens FX"; + LGraphLensFX.desc = "distortion and chromatic aberration"; + + LGraphLensFX.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphLensFX.prototype.onGetInputs = function() { + return [["enabled", "boolean"]]; + }; + + LGraphLensFX.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + if ( + this.properties.precision === LGraphTexture.PASS_THROUGH || + this.getInputOrProperty("enabled") === false + ) { + this.setOutputData(0, tex); + return; + } + + var temp = this._temp_texture; + if ( + !temp || + temp.width != tex.width || + temp.height != tex.height || + temp.type != tex.type + ) { + temp = this._temp_texture = new GL.Texture( + tex.width, + tex.height, + { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } + ); + } + + var shader = LGraphLensFX._shader; + if (!shader) { + shader = LGraphLensFX._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphLensFX.pixel_shader + ); + } + + var factor = this.getInputData(1); + if (factor == null) { + factor = this.properties.factor; + } + + var uniforms = this._uniforms; + uniforms.u_factor = factor; + + //apply shader + gl.disable(gl.DEPTH_TEST); + temp.drawTo(function() { + tex.bind(0); + shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); + }); + + this.setOutputData(0, temp); + }; + + LGraphLensFX.pixel_shader = + "precision highp float;\n\ varying vec2 v_coord;\n\ uniform sampler2D u_texture;\n\ uniform float u_factor;\n\ @@ -3466,633 +3823,680 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ function LGraphExposition() { this.addInput("in", "Texture"); this.addInput("exp", "number"); - this.addOutput("out", "Texture"); - this.properties = { exposition: 1, precision: LGraphTexture.LOW }; - this._uniforms = { u_texture: 0, u_exposition: 1 }; - } - - LGraphExposition.title = "Exposition"; - LGraphExposition.desc = "Controls texture exposition"; - - LGraphExposition.widgets_info = { - exposition: { widget: "slider", min: 0, max: 3 }, - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphExposition.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex) return; - - if (!this.isOutputConnected(0)) return; //saves work - - var temp = this._temp_texture; - if ( - !temp || - temp.width != tex.width || - temp.height != tex.height || - temp.type != tex.type - ) - temp = this._temp_texture = new GL.Texture( - tex.width, - tex.height, - { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } - ); - - var shader = LGraphExposition._shader; - if (!shader) - shader = LGraphExposition._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphExposition.pixel_shader - ); - - var exp = this.properties.exposition; - var exp_input = this.getInputData(1); - if (exp_input != null) exp = this.properties.exposition = exp_input; - var uniforms = this._uniforms; - - //apply shader - temp.drawTo(function() { - gl.disable(gl.DEPTH_TEST); - tex.bind(0); - shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); - }); - - this.setOutputData(0, temp); - }; - - LGraphExposition.pixel_shader = - "precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform float u_exposition;\n\ - \n\ - void main() {\n\ - vec4 color = texture2D( u_texture, v_coord );\n\ - gl_FragColor = vec4( color.xyz * u_exposition, color.a );\n\ - }"; - - LiteGraph.registerNodeType("texture/exposition", LGraphExposition); - - function LGraphToneMapping() { - this.addInput("in", "Texture"); - this.addInput("avg", "number,Texture"); - this.addOutput("out", "Texture"); - this.properties = { - enabled: true, - scale: 1, - gamma: 1, - average_lum: 1, - lum_white: 1, - precision: LGraphTexture.LOW - }; - - this._uniforms = { - u_texture: 0, - u_lumwhite2: 1, - u_igamma: 1, - u_scale: 1, - u_average_lum: 1 - }; - } - - LGraphToneMapping.title = "Tone Mapping"; - LGraphToneMapping.desc = - "Applies Tone Mapping to convert from high to low"; - - LGraphToneMapping.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphToneMapping.prototype.onGetInputs = function() { - return [["enabled", "boolean"]]; - }; - - LGraphToneMapping.prototype.onExecute = function() { - var tex = this.getInputData(0); - if (!tex) return; - - if (!this.isOutputConnected(0)) return; //saves work - - if ( - this.properties.precision === LGraphTexture.PASS_THROUGH || - this.getInputOrProperty("enabled") === false - ) { - this.setOutputData(0, tex); - return; - } - - var temp = this._temp_texture; - - if ( - !temp || - temp.width != tex.width || - temp.height != tex.height || - temp.type != tex.type - ) - temp = this._temp_texture = new GL.Texture( - tex.width, - tex.height, - { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } - ); - - var avg = this.getInputData(1); - if (avg == null) avg = this.properties.average_lum; - - var uniforms = this._uniforms; - var shader = null; - - if (avg.constructor === Number) { - this.properties.average_lum = avg; - uniforms.u_average_lum = this.properties.average_lum; - shader = LGraphToneMapping._shader; - if (!shader) - shader = LGraphToneMapping._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphToneMapping.pixel_shader - ); - } else if (avg.constructor === GL.Texture) { - uniforms.u_average_texture = avg.bind(1); - shader = LGraphToneMapping._shader_texture; - if (!shader) - shader = LGraphToneMapping._shader_texture = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphToneMapping.pixel_shader, - { AVG_TEXTURE: "" } - ); - } - - uniforms.u_lumwhite2 = - this.properties.lum_white * this.properties.lum_white; - uniforms.u_scale = this.properties.scale; - uniforms.u_igamma = 1 / this.properties.gamma; - - //apply shader - gl.disable(gl.DEPTH_TEST); - temp.drawTo(function() { - tex.bind(0); - shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); - }); - - this.setOutputData(0, this._temp_texture); - }; - - LGraphToneMapping.pixel_shader = - "precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform float u_scale;\n\ - #ifdef AVG_TEXTURE\n\ - uniform sampler2D u_average_texture;\n\ - #else\n\ - uniform float u_average_lum;\n\ - #endif\n\ - uniform float u_lumwhite2;\n\ - uniform float u_igamma;\n\ - vec3 RGB2xyY (vec3 rgb)\n\ - {\n\ - const mat3 RGB2XYZ = mat3(0.4124, 0.3576, 0.1805,\n\ - 0.2126, 0.7152, 0.0722,\n\ - 0.0193, 0.1192, 0.9505);\n\ - vec3 XYZ = RGB2XYZ * rgb;\n\ - \n\ - float f = (XYZ.x + XYZ.y + XYZ.z);\n\ - return vec3(XYZ.x / f,\n\ - XYZ.y / f,\n\ - XYZ.y);\n\ - }\n\ - \n\ - void main() {\n\ - vec4 color = texture2D( u_texture, v_coord );\n\ - vec3 rgb = color.xyz;\n\ - float average_lum = 0.0;\n\ - #ifdef AVG_TEXTURE\n\ - vec3 pixel = texture2D(u_average_texture,vec2(0.5)).xyz;\n\ - average_lum = (pixel.x + pixel.y + pixel.z) / 3.0;\n\ - #else\n\ - average_lum = u_average_lum;\n\ - #endif\n\ - //Ld - this part of the code is the same for both versions\n\ - float lum = dot(rgb, vec3(0.2126, 0.7152, 0.0722));\n\ - float L = (u_scale / average_lum) * lum;\n\ - float Ld = (L * (1.0 + L / u_lumwhite2)) / (1.0 + L);\n\ - //first\n\ - //vec3 xyY = RGB2xyY(rgb);\n\ - //xyY.z *= Ld;\n\ - //rgb = xyYtoRGB(xyY);\n\ - //second\n\ - rgb = (rgb / lum) * Ld;\n\ - rgb = pow( rgb, vec3( u_igamma ) );\n\ - gl_FragColor = vec4( rgb, color.a );\n\ - }"; - - LiteGraph.registerNodeType("texture/tonemapping", LGraphToneMapping); - - function LGraphTexturePerlin() { - this.addOutput("out", "Texture"); - this.properties = { - width: 512, - height: 512, - seed: 0, - persistence: 0.1, - octaves: 8, - scale: 1, - offset: [0, 0], - amplitude: 1, - precision: LGraphTexture.DEFAULT - }; - this._key = 0; - this._texture = null; - this._uniforms = { - u_persistence: 0.1, - u_seed: 0, - u_offset: vec2.create(), - u_scale: 1, - u_viewport: vec2.create() - }; - } - - LGraphTexturePerlin.title = "Perlin"; - LGraphTexturePerlin.desc = "Generates a perlin noise texture"; - - LGraphTexturePerlin.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES }, - width: { type: "Number", precision: 0, step: 1 }, - height: { type: "Number", precision: 0, step: 1 }, - octaves: { type: "Number", precision: 0, step: 1, min: 1, max: 50 } - }; - - LGraphTexturePerlin.prototype.onGetInputs = function() { - return [ - ["seed", "Number"], - ["persistence", "Number"], - ["octaves", "Number"], - ["scale", "Number"], - ["amplitude", "Number"], - ["offset", "vec2"] - ]; - }; - - LGraphTexturePerlin.prototype.onExecute = function() { - if (!this.isOutputConnected(0)) return; //saves work - - var w = this.properties.width | 0; - var h = this.properties.height | 0; - if (w == 0) w = gl.viewport_data[2]; //0 means default - if (h == 0) h = gl.viewport_data[3]; //0 means default - var type = LGraphTexture.getTextureType(this.properties.precision); - - var temp = this._texture; - if ( - !temp || - temp.width != w || - temp.height != h || - temp.type != type - ) - temp = this._texture = new GL.Texture(w, h, { - type: type, - format: gl.RGB, - filter: gl.LINEAR - }); - - var persistence = this.getInputOrProperty("persistence"); - var octaves = this.getInputOrProperty("octaves"); - var offset = this.getInputOrProperty("offset"); - var scale = this.getInputOrProperty("scale"); - var amplitude = this.getInputOrProperty("amplitude"); - var seed = this.getInputOrProperty("seed"); - - //reusing old texture - var key = - "" + - w + - h + - type + - persistence + - octaves + - scale + - seed + - offset[0] + - offset[1] + - amplitude; - if (key == this._key) { - this.setOutputData(0, temp); - return; - } - this._key = key; - - //gather uniforms - var uniforms = this._uniforms; - uniforms.u_persistence = persistence; - uniforms.u_octaves = octaves; - uniforms.u_offset.set(offset); - uniforms.u_scale = scale; - uniforms.u_amplitude = amplitude; - uniforms.u_seed = seed * 128; - uniforms.u_viewport[0] = w; - uniforms.u_viewport[1] = h; - - //render - var shader = LGraphTexturePerlin._shader; - if (!shader) - shader = LGraphTexturePerlin._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTexturePerlin.pixel_shader - ); - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - - temp.drawTo(function() { - shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); - }); - - this.setOutputData(0, temp); - }; - - LGraphTexturePerlin.pixel_shader = - "precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform vec2 u_offset;\n\ - uniform float u_scale;\n\ - uniform float u_persistence;\n\ - uniform int u_octaves;\n\ - uniform float u_amplitude;\n\ - uniform vec2 u_viewport;\n\ - uniform float u_seed;\n\ - #define M_PI 3.14159265358979323846\n\ - \n\ - float rand(vec2 c){ return fract(sin(dot(c.xy ,vec2( 12.9898 + u_seed,78.233 + u_seed))) * 43758.5453); }\n\ - \n\ - float noise(vec2 p, float freq ){\n\ - float unit = u_viewport.x/freq;\n\ - vec2 ij = floor(p/unit);\n\ - vec2 xy = mod(p,unit)/unit;\n\ - //xy = 3.*xy*xy-2.*xy*xy*xy;\n\ - xy = .5*(1.-cos(M_PI*xy));\n\ - float a = rand((ij+vec2(0.,0.)));\n\ - float b = rand((ij+vec2(1.,0.)));\n\ - float c = rand((ij+vec2(0.,1.)));\n\ - float d = rand((ij+vec2(1.,1.)));\n\ - float x1 = mix(a, b, xy.x);\n\ - float x2 = mix(c, d, xy.x);\n\ - return mix(x1, x2, xy.y);\n\ - }\n\ - \n\ - float pNoise(vec2 p, int res){\n\ - float persistance = u_persistence;\n\ - float n = 0.;\n\ - float normK = 0.;\n\ - float f = 4.;\n\ - float amp = 1.0;\n\ - int iCount = 0;\n\ - for (int i = 0; i<50; i++){\n\ - n+=amp*noise(p, f);\n\ - f*=2.;\n\ - normK+=amp;\n\ - amp*=persistance;\n\ - if (iCount >= res)\n\ - break;\n\ - iCount++;\n\ - }\n\ - float nf = n/normK;\n\ - return nf*nf*nf*nf;\n\ - }\n\ - void main() {\n\ - vec2 uv = v_coord * u_scale * u_viewport + u_offset * u_scale;\n\ - vec4 color = vec4( pNoise( uv, u_octaves ) * u_amplitude );\n\ - gl_FragColor = color;\n\ - }"; - - LiteGraph.registerNodeType("texture/perlin", LGraphTexturePerlin); - - function LGraphTextureCanvas2D() { - this.addOutput("out", "Texture"); - this.properties = { - code: "", - width: 512, - height: 512, - precision: LGraphTexture.DEFAULT - }; - this._func = null; - this._temp_texture = null; - } - - LGraphTextureCanvas2D.title = "Canvas2D"; - LGraphTextureCanvas2D.desc = - "Executes Canvas2D code inside a texture or the viewport"; - - LGraphTextureCanvas2D.widgets_info = { - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES }, - code: { type: "code" }, - width: { type: "Number", precision: 0, step: 1 }, - height: { type: "Number", precision: 0, step: 1 } - }; - - LGraphTextureCanvas2D.prototype.onPropertyChanged = function( - name, - value - ) { - if (name == "code" && LiteGraph.allow_scripts) { - this._func = null; - try { - this._func = new Function( - "canvas", - "ctx", - "time", - "script", - value - ); - this.boxcolor = "#00FF00"; - } catch (err) { - this.boxcolor = "#FF0000"; - console.error("Error parsing script"); - console.error(err); - } - } - }; - - LGraphTextureCanvas2D.prototype.onExecute = function() { - var func = this._func; - if (!func || !this.isOutputConnected(0)) return; - - if (!global.enableWebGLCanvas) { - console.warn( - "cannot use LGraphTextureCanvas2D if Canvas2DtoWebGL is not included" - ); - return; - } - - var width = this.properties.width || gl.canvas.width; - var height = this.properties.height || gl.canvas.height; - var temp = this._temp_texture; - if (!temp || temp.width != width || temp.height != height) - temp = this._temp_texture = new GL.Texture(width, height, { - format: gl.RGBA, - filter: gl.LINEAR - }); - - var that = this; - var time = this.graph.getTime(); - temp.drawTo(function() { - gl.start2D(); - try { - if (func.draw) - func.draw.call(that, gl.canvas, gl, time, func); - else func.call(that, gl.canvas, gl, time, func); - that.boxcolor = "#00FF00"; - } catch (err) { - that.boxcolor = "#FF0000"; - console.error("Error executing script"); - console.error(err); - } - gl.finish2D(); - }); - - this.setOutputData(0, temp); - }; - - LiteGraph.registerNodeType("texture/canvas2D", LGraphTextureCanvas2D); - - function LGraphTextureMatte() { - this.addInput("in", "Texture"); - - this.addOutput("out", "Texture"); - this.properties = { - key_color: vec3.fromValues(0, 1, 0), - threshold: 0.8, - slope: 0.2, - precision: LGraphTexture.DEFAULT - }; - } - - LGraphTextureMatte.title = "Matte"; - LGraphTextureMatte.desc = "Extracts background"; - - LGraphTextureMatte.widgets_info = { - key_color: { widget: "color" }, - precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } - }; - - LGraphTextureMatte.prototype.onExecute = function() { - if (!this.isOutputConnected(0)) return; //saves work - - var tex = this.getInputData(0); - - if (this.properties.precision === LGraphTexture.PASS_THROUGH) { - this.setOutputData(0, tex); - return; - } - - if (!tex) return; - - this._tex = LGraphTexture.getTargetTexture( - tex, - this._tex, - this.properties.precision - ); - - gl.disable(gl.BLEND); - gl.disable(gl.DEPTH_TEST); - - if (!this._uniforms) - this._uniforms = { - u_texture: 0, - u_key_color: this.properties.key_color, - u_threshold: 1, - u_slope: 1 - }; - var uniforms = this._uniforms; - - var mesh = Mesh.getScreenQuad(); - var shader = LGraphTextureMatte._shader; - if (!shader) - shader = LGraphTextureMatte._shader = new GL.Shader( - GL.Shader.SCREEN_VERTEX_SHADER, - LGraphTextureMatte.pixel_shader - ); - - uniforms.u_key_color = this.properties.key_color; - uniforms.u_threshold = this.properties.threshold; - uniforms.u_slope = this.properties.slope; - - this._tex.drawTo(function() { - tex.bind(0); - shader.uniforms(uniforms).draw(mesh); - }); - - this.setOutputData(0, this._tex); - }; - - LGraphTextureMatte.pixel_shader = - "precision highp float;\n\ - varying vec2 v_coord;\n\ - uniform sampler2D u_texture;\n\ - uniform vec3 u_key_color;\n\ - uniform float u_threshold;\n\ - uniform float u_slope;\n\ - \n\ - void main() {\n\ - vec3 color = texture2D( u_texture, v_coord ).xyz;\n\ - float diff = length( normalize(color) - normalize(u_key_color) );\n\ - float edge = u_threshold * (1.0 - u_slope);\n\ - float alpha = smoothstep( edge, u_threshold, diff);\n\ - gl_FragColor = vec4( color, alpha );\n\ - }"; - - LiteGraph.registerNodeType("texture/matte", LGraphTextureMatte); - - //*********************************** - //Cubemap reader (to pass a cubemap to a node that requires cubemaps and no images) - function LGraphCubemap() { - this.addOutput("Cubemap", "Cubemap"); - this.properties = { name: "" }; - this.size = [ - LGraphTexture.image_preview_size, - LGraphTexture.image_preview_size - ]; - } - - LGraphCubemap.title = "Cubemap"; - - LGraphCubemap.prototype.onDropFile = function(data, filename, file) { - if (!data) { - this._drop_texture = null; - this.properties.name = ""; - } else { - if (typeof data == "string") - this._drop_texture = GL.Texture.fromURL(data); - else this._drop_texture = GL.Texture.fromDDSInMemory(data); - this.properties.name = filename; - } - }; - - LGraphCubemap.prototype.onExecute = function() { - if (this._drop_texture) { - this.setOutputData(0, this._drop_texture); - return; - } - - if (!this.properties.name) return; - - var tex = LGraphTexture.getTexture(this.properties.name); - if (!tex) return; - - this._last_tex = tex; - this.setOutputData(0, tex); - }; - - LGraphCubemap.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed || this.size[1] <= 20) return; - - if (!ctx.webgl) return; - - var cube_mesh = gl.meshes["cube"]; - if (!cube_mesh) - cube_mesh = gl.meshes["cube"] = GL.Mesh.cube({ size: 1 }); - - //var view = mat4.lookAt( mat4.create(), [0,0 - }; - + this.addOutput("out", "Texture"); + this.properties = { exposition: 1, precision: LGraphTexture.LOW }; + this._uniforms = { u_texture: 0, u_exposition: 1 }; + } + + LGraphExposition.title = "Exposition"; + LGraphExposition.desc = "Controls texture exposition"; + + LGraphExposition.widgets_info = { + exposition: { widget: "slider", min: 0, max: 3 }, + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphExposition.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var temp = this._temp_texture; + if ( + !temp || + temp.width != tex.width || + temp.height != tex.height || + temp.type != tex.type + ) { + temp = this._temp_texture = new GL.Texture( + tex.width, + tex.height, + { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } + ); + } + + var shader = LGraphExposition._shader; + if (!shader) { + shader = LGraphExposition._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphExposition.pixel_shader + ); + } + + var exp = this.properties.exposition; + var exp_input = this.getInputData(1); + if (exp_input != null) { + exp = this.properties.exposition = exp_input; + } + var uniforms = this._uniforms; + + //apply shader + temp.drawTo(function() { + gl.disable(gl.DEPTH_TEST); + tex.bind(0); + shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); + }); + + this.setOutputData(0, temp); + }; + + LGraphExposition.pixel_shader = + "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float u_exposition;\n\ + \n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord );\n\ + gl_FragColor = vec4( color.xyz * u_exposition, color.a );\n\ + }"; + + LiteGraph.registerNodeType("texture/exposition", LGraphExposition); + + function LGraphToneMapping() { + this.addInput("in", "Texture"); + this.addInput("avg", "number,Texture"); + this.addOutput("out", "Texture"); + this.properties = { + enabled: true, + scale: 1, + gamma: 1, + average_lum: 1, + lum_white: 1, + precision: LGraphTexture.LOW + }; + + this._uniforms = { + u_texture: 0, + u_lumwhite2: 1, + u_igamma: 1, + u_scale: 1, + u_average_lum: 1 + }; + } + + LGraphToneMapping.title = "Tone Mapping"; + LGraphToneMapping.desc = + "Applies Tone Mapping to convert from high to low"; + + LGraphToneMapping.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphToneMapping.prototype.onGetInputs = function() { + return [["enabled", "boolean"]]; + }; + + LGraphToneMapping.prototype.onExecute = function() { + var tex = this.getInputData(0); + if (!tex) { + return; + } + + if (!this.isOutputConnected(0)) { + return; + } //saves work + + if ( + this.properties.precision === LGraphTexture.PASS_THROUGH || + this.getInputOrProperty("enabled") === false + ) { + this.setOutputData(0, tex); + return; + } + + var temp = this._temp_texture; + + if ( + !temp || + temp.width != tex.width || + temp.height != tex.height || + temp.type != tex.type + ) { + temp = this._temp_texture = new GL.Texture( + tex.width, + tex.height, + { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } + ); + } + + var avg = this.getInputData(1); + if (avg == null) { + avg = this.properties.average_lum; + } + + var uniforms = this._uniforms; + var shader = null; + + if (avg.constructor === Number) { + this.properties.average_lum = avg; + uniforms.u_average_lum = this.properties.average_lum; + shader = LGraphToneMapping._shader; + if (!shader) { + shader = LGraphToneMapping._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphToneMapping.pixel_shader + ); + } + } else if (avg.constructor === GL.Texture) { + uniforms.u_average_texture = avg.bind(1); + shader = LGraphToneMapping._shader_texture; + if (!shader) { + shader = LGraphToneMapping._shader_texture = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphToneMapping.pixel_shader, + { AVG_TEXTURE: "" } + ); + } + } + + uniforms.u_lumwhite2 = + this.properties.lum_white * this.properties.lum_white; + uniforms.u_scale = this.properties.scale; + uniforms.u_igamma = 1 / this.properties.gamma; + + //apply shader + gl.disable(gl.DEPTH_TEST); + temp.drawTo(function() { + tex.bind(0); + shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); + }); + + this.setOutputData(0, this._temp_texture); + }; + + LGraphToneMapping.pixel_shader = + "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float u_scale;\n\ + #ifdef AVG_TEXTURE\n\ + uniform sampler2D u_average_texture;\n\ + #else\n\ + uniform float u_average_lum;\n\ + #endif\n\ + uniform float u_lumwhite2;\n\ + uniform float u_igamma;\n\ + vec3 RGB2xyY (vec3 rgb)\n\ + {\n\ + const mat3 RGB2XYZ = mat3(0.4124, 0.3576, 0.1805,\n\ + 0.2126, 0.7152, 0.0722,\n\ + 0.0193, 0.1192, 0.9505);\n\ + vec3 XYZ = RGB2XYZ * rgb;\n\ + \n\ + float f = (XYZ.x + XYZ.y + XYZ.z);\n\ + return vec3(XYZ.x / f,\n\ + XYZ.y / f,\n\ + XYZ.y);\n\ + }\n\ + \n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord );\n\ + vec3 rgb = color.xyz;\n\ + float average_lum = 0.0;\n\ + #ifdef AVG_TEXTURE\n\ + vec3 pixel = texture2D(u_average_texture,vec2(0.5)).xyz;\n\ + average_lum = (pixel.x + pixel.y + pixel.z) / 3.0;\n\ + #else\n\ + average_lum = u_average_lum;\n\ + #endif\n\ + //Ld - this part of the code is the same for both versions\n\ + float lum = dot(rgb, vec3(0.2126, 0.7152, 0.0722));\n\ + float L = (u_scale / average_lum) * lum;\n\ + float Ld = (L * (1.0 + L / u_lumwhite2)) / (1.0 + L);\n\ + //first\n\ + //vec3 xyY = RGB2xyY(rgb);\n\ + //xyY.z *= Ld;\n\ + //rgb = xyYtoRGB(xyY);\n\ + //second\n\ + rgb = (rgb / lum) * Ld;\n\ + rgb = pow( rgb, vec3( u_igamma ) );\n\ + gl_FragColor = vec4( rgb, color.a );\n\ + }"; + + LiteGraph.registerNodeType("texture/tonemapping", LGraphToneMapping); + + function LGraphTexturePerlin() { + this.addOutput("out", "Texture"); + this.properties = { + width: 512, + height: 512, + seed: 0, + persistence: 0.1, + octaves: 8, + scale: 1, + offset: [0, 0], + amplitude: 1, + precision: LGraphTexture.DEFAULT + }; + this._key = 0; + this._texture = null; + this._uniforms = { + u_persistence: 0.1, + u_seed: 0, + u_offset: vec2.create(), + u_scale: 1, + u_viewport: vec2.create() + }; + } + + LGraphTexturePerlin.title = "Perlin"; + LGraphTexturePerlin.desc = "Generates a perlin noise texture"; + + LGraphTexturePerlin.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES }, + width: { type: "Number", precision: 0, step: 1 }, + height: { type: "Number", precision: 0, step: 1 }, + octaves: { type: "Number", precision: 0, step: 1, min: 1, max: 50 } + }; + + LGraphTexturePerlin.prototype.onGetInputs = function() { + return [ + ["seed", "Number"], + ["persistence", "Number"], + ["octaves", "Number"], + ["scale", "Number"], + ["amplitude", "Number"], + ["offset", "vec2"] + ]; + }; + + LGraphTexturePerlin.prototype.onExecute = function() { + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var w = this.properties.width | 0; + var h = this.properties.height | 0; + if (w == 0) { + w = gl.viewport_data[2]; + } //0 means default + if (h == 0) { + h = gl.viewport_data[3]; + } //0 means default + var type = LGraphTexture.getTextureType(this.properties.precision); + + var temp = this._texture; + if ( + !temp || + temp.width != w || + temp.height != h || + temp.type != type + ) { + temp = this._texture = new GL.Texture(w, h, { + type: type, + format: gl.RGB, + filter: gl.LINEAR + }); + } + + var persistence = this.getInputOrProperty("persistence"); + var octaves = this.getInputOrProperty("octaves"); + var offset = this.getInputOrProperty("offset"); + var scale = this.getInputOrProperty("scale"); + var amplitude = this.getInputOrProperty("amplitude"); + var seed = this.getInputOrProperty("seed"); + + //reusing old texture + var key = + "" + + w + + h + + type + + persistence + + octaves + + scale + + seed + + offset[0] + + offset[1] + + amplitude; + if (key == this._key) { + this.setOutputData(0, temp); + return; + } + this._key = key; + + //gather uniforms + var uniforms = this._uniforms; + uniforms.u_persistence = persistence; + uniforms.u_octaves = octaves; + uniforms.u_offset.set(offset); + uniforms.u_scale = scale; + uniforms.u_amplitude = amplitude; + uniforms.u_seed = seed * 128; + uniforms.u_viewport[0] = w; + uniforms.u_viewport[1] = h; + + //render + var shader = LGraphTexturePerlin._shader; + if (!shader) { + shader = LGraphTexturePerlin._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTexturePerlin.pixel_shader + ); + } + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + + temp.drawTo(function() { + shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad()); + }); + + this.setOutputData(0, temp); + }; + + LGraphTexturePerlin.pixel_shader = + "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform vec2 u_offset;\n\ + uniform float u_scale;\n\ + uniform float u_persistence;\n\ + uniform int u_octaves;\n\ + uniform float u_amplitude;\n\ + uniform vec2 u_viewport;\n\ + uniform float u_seed;\n\ + #define M_PI 3.14159265358979323846\n\ + \n\ + float rand(vec2 c){ return fract(sin(dot(c.xy ,vec2( 12.9898 + u_seed,78.233 + u_seed))) * 43758.5453); }\n\ + \n\ + float noise(vec2 p, float freq ){\n\ + float unit = u_viewport.x/freq;\n\ + vec2 ij = floor(p/unit);\n\ + vec2 xy = mod(p,unit)/unit;\n\ + //xy = 3.*xy*xy-2.*xy*xy*xy;\n\ + xy = .5*(1.-cos(M_PI*xy));\n\ + float a = rand((ij+vec2(0.,0.)));\n\ + float b = rand((ij+vec2(1.,0.)));\n\ + float c = rand((ij+vec2(0.,1.)));\n\ + float d = rand((ij+vec2(1.,1.)));\n\ + float x1 = mix(a, b, xy.x);\n\ + float x2 = mix(c, d, xy.x);\n\ + return mix(x1, x2, xy.y);\n\ + }\n\ + \n\ + float pNoise(vec2 p, int res){\n\ + float persistance = u_persistence;\n\ + float n = 0.;\n\ + float normK = 0.;\n\ + float f = 4.;\n\ + float amp = 1.0;\n\ + int iCount = 0;\n\ + for (int i = 0; i<50; i++){\n\ + n+=amp*noise(p, f);\n\ + f*=2.;\n\ + normK+=amp;\n\ + amp*=persistance;\n\ + if (iCount >= res)\n\ + break;\n\ + iCount++;\n\ + }\n\ + float nf = n/normK;\n\ + return nf*nf*nf*nf;\n\ + }\n\ + void main() {\n\ + vec2 uv = v_coord * u_scale * u_viewport + u_offset * u_scale;\n\ + vec4 color = vec4( pNoise( uv, u_octaves ) * u_amplitude );\n\ + gl_FragColor = color;\n\ + }"; + + LiteGraph.registerNodeType("texture/perlin", LGraphTexturePerlin); + + function LGraphTextureCanvas2D() { + this.addOutput("out", "Texture"); + this.properties = { + code: "", + width: 512, + height: 512, + precision: LGraphTexture.DEFAULT + }; + this._func = null; + this._temp_texture = null; + } + + LGraphTextureCanvas2D.title = "Canvas2D"; + LGraphTextureCanvas2D.desc = + "Executes Canvas2D code inside a texture or the viewport"; + + LGraphTextureCanvas2D.widgets_info = { + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES }, + code: { type: "code" }, + width: { type: "Number", precision: 0, step: 1 }, + height: { type: "Number", precision: 0, step: 1 } + }; + + LGraphTextureCanvas2D.prototype.onPropertyChanged = function( + name, + value + ) { + if (name == "code" && LiteGraph.allow_scripts) { + this._func = null; + try { + this._func = new Function( + "canvas", + "ctx", + "time", + "script", + value + ); + this.boxcolor = "#00FF00"; + } catch (err) { + this.boxcolor = "#FF0000"; + console.error("Error parsing script"); + console.error(err); + } + } + }; + + LGraphTextureCanvas2D.prototype.onExecute = function() { + var func = this._func; + if (!func || !this.isOutputConnected(0)) { + return; + } + + if (!global.enableWebGLCanvas) { + console.warn( + "cannot use LGraphTextureCanvas2D if Canvas2DtoWebGL is not included" + ); + return; + } + + var width = this.properties.width || gl.canvas.width; + var height = this.properties.height || gl.canvas.height; + var temp = this._temp_texture; + if (!temp || temp.width != width || temp.height != height) { + temp = this._temp_texture = new GL.Texture(width, height, { + format: gl.RGBA, + filter: gl.LINEAR + }); + } + + var that = this; + var time = this.graph.getTime(); + temp.drawTo(function() { + gl.start2D(); + try { + if (func.draw) { + func.draw.call(that, gl.canvas, gl, time, func); + } else { + func.call(that, gl.canvas, gl, time, func); + } + that.boxcolor = "#00FF00"; + } catch (err) { + that.boxcolor = "#FF0000"; + console.error("Error executing script"); + console.error(err); + } + gl.finish2D(); + }); + + this.setOutputData(0, temp); + }; + + LiteGraph.registerNodeType("texture/canvas2D", LGraphTextureCanvas2D); + + function LGraphTextureMatte() { + this.addInput("in", "Texture"); + + this.addOutput("out", "Texture"); + this.properties = { + key_color: vec3.fromValues(0, 1, 0), + threshold: 0.8, + slope: 0.2, + precision: LGraphTexture.DEFAULT + }; + } + + LGraphTextureMatte.title = "Matte"; + LGraphTextureMatte.desc = "Extracts background"; + + LGraphTextureMatte.widgets_info = { + key_color: { widget: "color" }, + precision: { widget: "combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphTextureMatte.prototype.onExecute = function() { + if (!this.isOutputConnected(0)) { + return; + } //saves work + + var tex = this.getInputData(0); + + if (this.properties.precision === LGraphTexture.PASS_THROUGH) { + this.setOutputData(0, tex); + return; + } + + if (!tex) { + return; + } + + this._tex = LGraphTexture.getTargetTexture( + tex, + this._tex, + this.properties.precision + ); + + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + + if (!this._uniforms) { + this._uniforms = { + u_texture: 0, + u_key_color: this.properties.key_color, + u_threshold: 1, + u_slope: 1 + }; + } + var uniforms = this._uniforms; + + var mesh = Mesh.getScreenQuad(); + var shader = LGraphTextureMatte._shader; + if (!shader) { + shader = LGraphTextureMatte._shader = new GL.Shader( + GL.Shader.SCREEN_VERTEX_SHADER, + LGraphTextureMatte.pixel_shader + ); + } + + uniforms.u_key_color = this.properties.key_color; + uniforms.u_threshold = this.properties.threshold; + uniforms.u_slope = this.properties.slope; + + this._tex.drawTo(function() { + tex.bind(0); + shader.uniforms(uniforms).draw(mesh); + }); + + this.setOutputData(0, this._tex); + }; + + LGraphTextureMatte.pixel_shader = + "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform vec3 u_key_color;\n\ + uniform float u_threshold;\n\ + uniform float u_slope;\n\ + \n\ + void main() {\n\ + vec3 color = texture2D( u_texture, v_coord ).xyz;\n\ + float diff = length( normalize(color) - normalize(u_key_color) );\n\ + float edge = u_threshold * (1.0 - u_slope);\n\ + float alpha = smoothstep( edge, u_threshold, diff);\n\ + gl_FragColor = vec4( color, alpha );\n\ + }"; + + LiteGraph.registerNodeType("texture/matte", LGraphTextureMatte); + + //*********************************** + //Cubemap reader (to pass a cubemap to a node that requires cubemaps and no images) + function LGraphCubemap() { + this.addOutput("Cubemap", "Cubemap"); + this.properties = { name: "" }; + this.size = [ + LGraphTexture.image_preview_size, + LGraphTexture.image_preview_size + ]; + } + + LGraphCubemap.title = "Cubemap"; + + LGraphCubemap.prototype.onDropFile = function(data, filename, file) { + if (!data) { + this._drop_texture = null; + this.properties.name = ""; + } else { + if (typeof data == "string") { + this._drop_texture = GL.Texture.fromURL(data); + } else { + this._drop_texture = GL.Texture.fromDDSInMemory(data); + } + this.properties.name = filename; + } + }; + + LGraphCubemap.prototype.onExecute = function() { + if (this._drop_texture) { + this.setOutputData(0, this._drop_texture); + return; + } + + if (!this.properties.name) { + return; + } + + var tex = LGraphTexture.getTexture(this.properties.name); + if (!tex) { + return; + } + + this._last_tex = tex; + this.setOutputData(0, tex); + }; + + LGraphCubemap.prototype.onDrawBackground = function(ctx) { + if (this.flags.collapsed || this.size[1] <= 20) { + return; + } + + if (!ctx.webgl) { + return; + } + + var cube_mesh = gl.meshes["cube"]; + if (!cube_mesh) { + cube_mesh = gl.meshes["cube"] = GL.Mesh.cube({ size: 1 }); + } + + //var view = mat4.lookAt( mat4.create(), [0,0 + }; + LiteGraph.registerNodeType("texture/cubemap", LGraphCubemap); } //litegl.js defined })(this); diff --git a/src/nodes/graphics.js b/src/nodes/graphics.js index 8115ba9b7..9f90f499b 100755 --- a/src/nodes/graphics.js +++ b/src/nodes/graphics.js @@ -16,21 +16,29 @@ GraphicsPlot.colors = ["#FFF", "#F99", "#9F9", "#99F"]; GraphicsPlot.prototype.onExecute = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } var size = this.size; for (var i = 0; i < 4; ++i) { var v = this.getInputData(i); - if (v == null) continue; + if (v == null) { + continue; + } var values = this.values[i]; values.push(v); - if (values.length > size[0]) values.shift(); + if (values.length > size[0]) { + values.shift(); + } } }; GraphicsPlot.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } var size = this.size; @@ -46,10 +54,12 @@ ctx.lineTo(size[0], offset); ctx.stroke(); - if (this.inputs) + if (this.inputs) { for (var i = 0; i < 4; ++i) { var values = this.values[i]; - if (!this.inputs[i] || !this.inputs[i].link) continue; + if (!this.inputs[i] || !this.inputs[i].link) { + continue; + } ctx.strokeStyle = colors[i]; ctx.beginPath(); var v = values[0] * scale * -1 + offset; @@ -60,6 +70,7 @@ } ctx.stroke(); } + } }; LiteGraph.registerNodeType("graphics/plot", GraphicsPlot); @@ -82,21 +93,33 @@ }; GraphicsImage.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; - if (this.img && this.size[0] > 5 && this.size[1] > 5) + if (this.flags.collapsed) { + return; + } + if (this.img && this.size[0] > 5 && this.size[1] > 5) { ctx.drawImage(this.img, 0, 0, this.size[0], this.size[1]); + } }; GraphicsImage.prototype.onExecute = function() { - if (!this.img) this.boxcolor = "#000"; - if (this.img && this.img.width) this.setOutputData(0, this.img); - else this.setOutputData(0, null); - if (this.img && this.img.dirty) this.img.dirty = false; + if (!this.img) { + this.boxcolor = "#000"; + } + if (this.img && this.img.width) { + this.setOutputData(0, this.img); + } else { + this.setOutputData(0, null); + } + if (this.img && this.img.dirty) { + this.img.dirty = false; + } }; GraphicsImage.prototype.onPropertyChanged = function(name, value) { this.properties[name] = value; - if (name == "url" && value != "") this.loadImage(value); + if (name == "url" && value != "") { + this.loadImage(value); + } return true; }; @@ -109,14 +132,17 @@ this.img = document.createElement("img"); - if (url.substr(0, 4) == "http" && LiteGraph.proxy) + if (url.substr(0, 4) == "http" && LiteGraph.proxy) { url = LiteGraph.proxy + url.substr(url.indexOf(":") + 3); + } this.img.src = url; this.boxcolor = "#F95"; var that = this; this.img.onload = function() { - if (callback) callback(this); + if (callback) { + callback(this); + } that.trace( "Image loaded, size: " + that.img.width + "x" + that.img.height ); @@ -134,7 +160,9 @@ GraphicsImage.prototype.onDropFile = function(file) { var that = this; - if (this._url) URL.revokeObjectURL(this._url); + if (this._url) { + URL.revokeObjectURL(this._url); + } this._url = URL.createObjectURL(file); this.properties.url = this._url; this.loadImage(this._url, function(img) { @@ -161,26 +189,39 @@ ColorPalette.prototype.onExecute = function() { var c = []; - if (this.properties.colorA != null) + if (this.properties.colorA != null) { c.push(hex2num(this.properties.colorA)); - if (this.properties.colorB != null) + } + if (this.properties.colorB != null) { c.push(hex2num(this.properties.colorB)); - if (this.properties.colorC != null) + } + if (this.properties.colorC != null) { c.push(hex2num(this.properties.colorC)); - if (this.properties.colorD != null) + } + if (this.properties.colorD != null) { c.push(hex2num(this.properties.colorD)); + } var f = this.getInputData(0); - if (f == null) f = 0.5; - if (f > 1.0) f = 1.0; - else if (f < 0.0) f = 0.0; + if (f == null) { + f = 0.5; + } + if (f > 1.0) { + f = 1.0; + } else if (f < 0.0) { + f = 0.0; + } - if (c.length == 0) return; + if (c.length == 0) { + return; + } var result = [0, 0, 0]; - if (f == 0) result = c[0]; - else if (f == 1) result = c[c.length - 1]; - else { + if (f == 0) { + result = c[0]; + } else if (f == 1) { + result = c[c.length - 1]; + } else { var pos = (c.length - 1) * f; var c1 = c[Math.floor(pos)]; var c2 = c[Math.floor(pos) + 1]; @@ -196,7 +237,9 @@ c[2] = Math.abs( Math.sin( 0.01 * reModular.getTime() * Math.PI) ); */ - for (var i in result) result[i] /= 255; + for (var i in result) { + result[i] /= 255; + } this.boxcolor = colorToString(result); this.setOutputData(0, result); @@ -217,8 +260,9 @@ ]; ImageFrame.prototype.onDrawBackground = function(ctx) { - if (this.frame && !this.flags.collapsed) + if (this.frame && !this.flags.collapsed) { ctx.drawImage(this.frame, 0, 0, this.size[0], this.size[1]); + } }; ImageFrame.prototype.onExecute = function() { @@ -236,14 +280,20 @@ height = this.frame.videoHeight; } - if (width && height) this.size = [width, height]; + if (width && height) { + this.size = [width, height]; + } this.setDirtyCanvas(true, true); - } else if (widget.name == "view") this.show(); + } else if (widget.name == "view") { + this.show(); + } }; ImageFrame.prototype.show = function() { //var str = this.canvas.toDataURL("image/png"); - if (showElement && this.frame) showElement(this.frame); + if (showElement && this.frame) { + showElement(this.frame); + } }; LiteGraph.registerNodeType("graphics/frame", ImageFrame); @@ -288,8 +338,11 @@ } var fade = this.getInputData(2); - if (fade == null) fade = this.properties["fade"]; - else this.properties["fade"] = fade; + if (fade == null) { + fade = this.properties["fade"]; + } else { + this.properties["fade"] = fade; + } ctx.globalAlpha = fade; var B = this.getInputData(1); @@ -326,7 +379,9 @@ ImageCrop.prototype.onExecute = function() { var input = this.getInputData(0); - if (!input) return; + if (!input) { + return; + } if (input.width) { var ctx = this.canvas.getContext("2d"); @@ -339,12 +394,16 @@ input.height * this.properties["scale"] ); this.setOutputData(0, this.canvas); - } else this.setOutputData(0, null); + } else { + this.setOutputData(0, null); + } }; ImageCrop.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; - if (this.canvas) + if (this.flags.collapsed) { + return; + } + if (this.canvas) { ctx.drawImage( this.canvas, 0, @@ -356,6 +415,7 @@ this.size[0], this.size[1] ); + } }; ImageCrop.prototype.onPropertyChanged = function(name, value) { @@ -367,7 +427,9 @@ this.trace("Error in scale"); this.properties[name] = 1.0; } - } else this.properties[name] = parseInt(value); + } else { + this.properties[name] = parseInt(value); + } this.createCanvas(); @@ -394,17 +456,23 @@ var canvas = this.canvas; var w = this.properties.width | 0; var h = this.properties.height | 0; - if (canvas.width != w) canvas.width = w; - if (canvas.height != h) canvas.height = h; + if (canvas.width != w) { + canvas.width = w; + } + if (canvas.height != h) { + canvas.height = h; + } - if (this.properties.autoclear) + if (this.properties.autoclear) { this.ctx.clearRect(0, 0, canvas.width, canvas.height); + } this.setOutputData(0, canvas); }; CanvasNode.prototype.onAction = function(action, param) { - if (action == "clear") + if (action == "clear") { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + } }; LiteGraph.registerNodeType("graphics/canvas", CanvasNode); @@ -422,10 +490,14 @@ DrawImageNode.prototype.onExecute = function() { var canvas = this.getInputData(0); - if (!canvas) return; + if (!canvas) { + return; + } var img = this.getInputOrProperty("img"); - if (!img) return; + if (!img) { + return; + } var x = this.getInputOrProperty("x"); var y = this.getInputOrProperty("y"); @@ -456,7 +528,9 @@ DrawRectangleNode.prototype.onExecute = function() { var canvas = this.getInputData(0); - if (!canvas) return; + if (!canvas) { + return; + } var x = this.getInputOrProperty("x"); var y = this.getInputOrProperty("y"); @@ -484,12 +558,17 @@ ]; ImageVideo.prototype.onExecute = function() { - if (!this.properties.url) return; + if (!this.properties.url) { + return; + } - if (this.properties.url != this._video_url) + if (this.properties.url != this._video_url) { this.loadVideo(this.properties.url); + } - if (!this._video || this._video.width == 0) return; + if (!this._video || this._video.width == 0) { + return; + } var t = this.getInputData(0); if (t && t >= 0 && t <= 1.0) { @@ -519,8 +598,9 @@ this.properties.use_proxy && url.substr(0, 4) == "http" && LiteGraph.proxy - ) + ) { url = LiteGraph.proxy + url.substr(url.indexOf(":") + 3); + } this._video = document.createElement("video"); this._video.src = url; @@ -575,29 +655,42 @@ ImageVideo.prototype.onPropertyChanged = function(name, value) { this.properties[name] = value; - if (name == "url" && value != "") this.loadVideo(value); + if (name == "url" && value != "") { + this.loadVideo(value); + } return true; }; ImageVideo.prototype.play = function() { - if (this._video) this._video.play(); + if (this._video) { + this._video.play(); + } }; ImageVideo.prototype.playPause = function() { - if (!this._video) return; - if (this._video.paused) this.play(); - else this.pause(); + if (!this._video) { + return; + } + if (this._video.paused) { + this.play(); + } else { + this.pause(); + } }; ImageVideo.prototype.stop = function() { - if (!this._video) return; + if (!this._video) { + return; + } this._video.pause(); this._video.currentTime = 0; }; ImageVideo.prototype.pause = function() { - if (!this._video) return; + if (!this._video) { + return; + } this.trace("Video paused"); this._video.pause(); }; @@ -671,7 +764,9 @@ if (this._webcam_stream) { var tracks = this._webcam_stream.getTracks(); if (tracks.length) { - for (var i = 0; i < tracks.length; ++i) tracks[i].stop(); + for (var i = 0; i < tracks.length; ++i) { + tracks[i].stop(); + } } ImageWebcam.is_webcam_open = false; this._webcam_stream = null; @@ -717,17 +812,22 @@ }; ImageWebcam.prototype.onExecute = function() { - if (this._webcam_stream == null && !this._waiting_confirmation) + if (this._webcam_stream == null && !this._waiting_confirmation) { this.openStream(); + } - if (!this._video || !this._video.videoWidth) return; + if (!this._video || !this._video.videoWidth) { + return; + } this._video.frame = ++this.frame; this._video.width = this._video.videoWidth; this._video.height = this._video.videoHeight; this.setOutputData(0, this._video); for (var i = 1; i < this.outputs.length; ++i) { - if (!this.outputs[i]) continue; + if (!this.outputs[i]) { + continue; + } switch (this.outputs[i].name) { case "width": this.setOutputData(i, this._video.videoWidth); @@ -753,10 +853,17 @@ }; ImageWebcam.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed || this.size[1] <= 20 || !this.properties.show) + if ( + this.flags.collapsed || + this.size[1] <= 20 || + !this.properties.show + ) { return; + } - if (!this._video) return; + if (!this._video) { + return; + } //render to graph canvas ctx.save(); diff --git a/src/nodes/input.js b/src/nodes/input.js index 1d92e67d3..aeb0c8ae6 100755 --- a/src/nodes/input.js +++ b/src/nodes/input.js @@ -75,7 +75,9 @@ if (this.outputs) { for (var i = 0; i < this.outputs.length; i++) { var output = this.outputs[i]; - if (!output.links || !output.links.length) continue; + if (!output.links || !output.links.length) { + continue; + } var v = null; if (gamepad) { @@ -158,11 +160,12 @@ if ( this._current_buttons[j] && !this._previous_buttons[j] - ) + ) { this.triggerSlot( i, GamepadInput.buttons[j] ); + } } break; default: @@ -191,7 +194,9 @@ navigator.getGamepads || navigator.webkitGetGamepads || navigator.mozGetGamepads; - if (!getGamepads) return null; + if (!getGamepads) { + return null; + } var gamepads = getGamepads.call(navigator); var gamepad = null; @@ -199,18 +204,21 @@ //pick the first connected for (var i = this.properties.gamepad_index; i < 4; i++) { - if (!gamepads[i]) continue; + if (!gamepads[i]) { + continue; + } gamepad = gamepads[i]; //xbox controller mapping var xbox = this.xbox_mapping; - if (!xbox) + if (!xbox) { xbox = this.xbox_mapping = { axes: [], buttons: {}, hat: "", hatmap: GamepadInput.CENTER }; + } xbox.axes["lx"] = gamepad.axes[0]; xbox.axes["ly"] = gamepad.axes[1]; @@ -300,7 +308,9 @@ }; GamepadInput.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } //render gamepad state? var la = this._left_axis; @@ -321,8 +331,11 @@ ); var h = this.size[1] / this._current_buttons.length; ctx.fillStyle = "#AEB"; - for (var i = 0; i < this._current_buttons.length; ++i) - if (this._current_buttons[i]) ctx.fillRect(0, h * i, 6, h); + for (var i = 0; i < this._current_buttons.length; ++i) { + if (this._current_buttons[i]) { + ctx.fillRect(0, h * i, 6, h); + } + } }; GamepadInput.prototype.onGetOutputs = function() { diff --git a/src/nodes/interface.js b/src/nodes/interface.js index 9ef952ae8..6e0881143 100755 --- a/src/nodes/interface.js +++ b/src/nodes/interface.js @@ -19,7 +19,9 @@ WidgetButton.font = "Arial"; WidgetButton.prototype.onDrawForeground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } var margin = 10; ctx.fillStyle = "black"; ctx.fillRect( @@ -97,7 +99,9 @@ WidgetToggle.desc = "Toggles between true or false"; WidgetToggle.prototype.onDrawForeground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } var size = this.size[1] * 0.5; var margin = 0.25; @@ -130,7 +134,9 @@ WidgetToggle.prototype.onExecute = function() { var v = this.getInputData(0); - if (v != null) this.properties.value = v; + if (v != null) { + this.properties.value = v; + } this.setOutputData(0, this.properties.value); }; @@ -184,7 +190,9 @@ ctx.lineTo(x + h * -0.1, h * 0.8); ctx.fill(); ctx.font = (h * 0.7).toFixed(1) + "px Arial"; - } else ctx.font = (h * 0.8).toFixed(1) + "px Arial"; + } else { + ctx.font = (h * 0.8).toFixed(1) + "px Arial"; + } ctx.textAlign = "center"; ctx.font = (h * 0.7).toFixed(1) + "px Arial"; @@ -206,7 +214,9 @@ }; WidgetNumber.prototype.onMouseDown = function(e, pos) { - if (pos[1] < 0) return; + if (pos[1] < 0) { + return; + } this.old_y = e.canvasY; this.captureInput(true); @@ -216,11 +226,17 @@ }; WidgetNumber.prototype.onMouseMove = function(e) { - if (!this.mouse_captured) return; + if (!this.mouse_captured) { + return; + } var delta = this.old_y - e.canvasY; - if (e.shiftKey) delta *= 10; - if (e.metaKey || e.altKey) delta *= 0.1; + if (e.shiftKey) { + delta *= 10; + } + if (e.metaKey || e.altKey) { + delta *= 0.1; + } this.old_y = e.canvasY; var steps = this._remainder + delta / WidgetNumber.pixels_threshold; @@ -277,12 +293,15 @@ WidgetKnob.size = [80, 100]; WidgetKnob.prototype.onDrawForeground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } - if (this.value == -1) + if (this.value == -1) { this.value = (this.properties.value - this.properties.min) / (this.properties.max - this.properties.min); + } var center_x = this.size[0] * 0.5; var center_y = this.size[1] * 0.5; @@ -370,22 +389,28 @@ [e.canvasX, e.canvasY], [this.pos[0] + this.center[0], this.pos[1] + this.center[1]] ) > this.radius - ) + ) { return false; + } this.oldmouse = [e.canvasX - this.pos[0], e.canvasY - this.pos[1]]; this.captureInput(true); return true; }; WidgetKnob.prototype.onMouseMove = function(e) { - if (!this.oldmouse) return; + if (!this.oldmouse) { + return; + } var m = [e.canvasX - this.pos[0], e.canvasY - this.pos[1]]; var v = this.value; v -= (m[1] - this.oldmouse[1]) * 0.01; - if (v > 1.0) v = 1.0; - else if (v < 0.0) v = 0.0; + if (v > 1.0) { + v = 1.0; + } else if (v < 0.0) { + v = 0.0; + } this.value = v; this.properties.value = this.properties.min + @@ -436,7 +461,9 @@ WidgetSliderGUI.title = "Inner Slider"; WidgetSliderGUI.prototype.onPropertyChanged = function(name, value) { - if (name == "value") this.slider.value = value; + if (name == "value") { + this.slider.value = value; + } }; WidgetSliderGUI.prototype.onExecute = function() { @@ -457,10 +484,11 @@ WidgetHSlider.desc = "Linear slider controller"; WidgetHSlider.prototype.onDrawForeground = function(ctx) { - if (this.value == -1) + if (this.value == -1) { this.value = (this.properties.value - this.properties.min) / (this.properties.max - this.properties.min); + } //border ctx.globalAlpha = 1; @@ -487,7 +515,9 @@ }; WidgetHSlider.prototype.onMouseDown = function(e) { - if (e.canvasY - this.pos[1] < 0) return false; + if (e.canvasY - this.pos[1] < 0) { + return false; + } this.oldmouse = [e.canvasX - this.pos[0], e.canvasY - this.pos[1]]; this.captureInput(true); @@ -495,15 +525,20 @@ }; WidgetHSlider.prototype.onMouseMove = function(e) { - if (!this.oldmouse) return; + if (!this.oldmouse) { + return; + } var m = [e.canvasX - this.pos[0], e.canvasY - this.pos[1]]; var v = this.value; var delta = m[0] - this.oldmouse[0]; v += delta / this.size[0]; - if (v > 1.0) v = 1.0; - else if (v < 0.0) v = 0.0; + if (v > 1.0) { + v = 1.0; + } else if (v < 0.0) { + v = 0.0; + } this.value = v; @@ -533,7 +568,9 @@ WidgetProgress.prototype.onExecute = function() { var v = this.getInputData(0); - if (v != undefined) this.properties["value"] = v; + if (v != undefined) { + this.properties["value"] = v; + } }; WidgetProgress.prototype.onDrawForeground = function(ctx) { @@ -582,7 +619,9 @@ ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.shadowBlur = this.properties["glowSize"]; - } else ctx.shadowColor = "transparent"; + } else { + ctx.shadowColor = "transparent"; + } var fontsize = this.properties["fontsize"]; @@ -593,12 +632,13 @@ if (typeof this.str == "string") { var lines = this.str.split("\\n"); - for (var i in lines) + for (var i in lines) { ctx.fillText( lines[i], this.properties["align"] == "left" ? 15 : this.size[0] - 15, fontsize * -0.15 + fontsize * (parseInt(i) + 1) ); + } } ctx.shadowColor = "transparent"; @@ -608,12 +648,16 @@ WidgetText.prototype.onExecute = function() { var v = this.getInputData(0); - if (v != null) this.properties["value"] = v; + if (v != null) { + this.properties["value"] = v; + } //this.setDirtyCanvas(true); }; WidgetText.prototype.resize = function() { - if (!this.last_ctx) return; + if (!this.last_ctx) { + return; + } var lines = this.str.split("\\n"); this.last_ctx.font = @@ -621,7 +665,9 @@ var max = 0; for (var i in lines) { var w = this.last_ctx.measureText(lines[i]).width; - if (max < w) max = w; + if (max < w) { + max = w; + } } this.size[0] = max + 20; this.size[1] = 4 + lines.length * this.properties["fontsize"]; @@ -668,11 +714,17 @@ }; WidgetPanel.prototype.onDrawForeground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } - if (this.lineargradient == null) this.createGradient(ctx); + if (this.lineargradient == null) { + this.createGradient(ctx); + } - if (!this.lineargradient) return; + if (!this.lineargradient) { + return; + } ctx.lineWidth = 1; ctx.strokeStyle = this.properties["borderColor"]; @@ -684,7 +736,9 @@ ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.shadowBlur = this.properties["shadowSize"]; - } else ctx.shadowColor = "transparent"; + } else { + ctx.shadowColor = "transparent"; + } ctx.roundRect( 0, diff --git a/src/nodes/logic.js b/src/nodes/logic.js index a0fe1c7a4..19fbd4714 100755 --- a/src/nodes/logic.js +++ b/src/nodes/logic.js @@ -16,7 +16,9 @@ Selector.desc = "selects an output"; Selector.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } ctx.fillStyle = "#AFB"; var y = (this.selected + 1) * LiteGraph.NODE_SLOT_HEIGHT + 6; ctx.beginPath(); @@ -28,10 +30,14 @@ Selector.prototype.onExecute = function() { var sel = this.getInputData(0); - if (sel == null) sel = 0; + if (sel == null) { + sel = 0; + } this.selected = sel = Math.round(sel) % (this.inputs.length - 1); var v = this.getInputData(sel + 1); - if (v !== undefined) this.setOutputData(0, v); + if (v !== undefined) { + this.setOutputData(0, v); + } }; Selector.prototype.onGetInputs = function() { @@ -68,7 +74,9 @@ this.current_sequence = seq; } var index = this.getInputData(0); - if (index == null) index = 0; + if (index == null) { + index = 0; + } this.index = index = Math.round(index) % this.values.length; this.setOutputData(0, this.values[index]); diff --git a/src/nodes/math.js b/src/nodes/math.js index ad016fc86..e8f1d7410 100755 --- a/src/nodes/math.js +++ b/src/nodes/math.js @@ -12,12 +12,16 @@ Converter.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } - if (this.outputs) + if (this.outputs) { for (var i = 0; i < this.outputs.length; i++) { var output = this.outputs[i]; - if (!output.links || !output.links.length) continue; + if (!output.links || !output.links.length) { + continue; + } var result = null; switch (output.name) { @@ -47,13 +51,17 @@ var j = 0; j < v.length && j < result.length; j++ - ) + ) { result[j] = v[j]; - } else result[0] = parseFloat(v); + } + } else { + result[0] = parseFloat(v); + } break; } this.setOutputData(i, result); } + } }; Converter.prototype.onGetOutputs = function() { @@ -116,21 +124,28 @@ MathRange.desc = "Convert a number from one range to another"; MathRange.prototype.getTitle = function() { - if (this.flags.collapsed) return (this._last_v || 0).toFixed(2); + if (this.flags.collapsed) { + return (this._last_v || 0).toFixed(2); + } return this.title; }; MathRange.prototype.onExecute = function() { - if (this.inputs) + 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; + if (v === undefined) { + continue; + } this.properties[input.name] = v; } + } var v = this.properties["in"]; - if (v === undefined || v === null || v.constructor !== Number) v = 0; + if (v === undefined || v === null || v.constructor !== Number) { + v = 0; + } var in_min = this.properties.in_min; var in_max = this.properties.in_max; @@ -144,8 +159,11 @@ MathRange.prototype.onDrawBackground = function(ctx) { //show the current value - if (this._last_v) this.outputs[0].label = this._last_v.toFixed(3); - else this.outputs[0].label = "?"; + if (this._last_v) { + this.outputs[0].label = this._last_v.toFixed(3); + } else { + this.outputs[0].label = "?"; + } }; MathRange.prototype.onGetInputs = function() { @@ -170,13 +188,16 @@ MathRand.desc = "Random number"; MathRand.prototype.onExecute = function() { - if (this.inputs) + 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; + if (v === undefined) { + continue; + } this.properties[input.name] = v; } + } var min = this.properties.min; var max = this.properties.max; @@ -212,16 +233,21 @@ MathNoise.getValue = function(f, smooth) { if (!MathNoise.data) { MathNoise.data = new Float32Array(1024); - for (var i = 0; i < MathNoise.data.length; ++i) + for (var i = 0; i < MathNoise.data.length; ++i) { MathNoise.data[i] = Math.random(); + } } f = f % 1024; - if (f < 0) f += 1024; + if (f < 0) { + f += 1024; + } var f_min = Math.floor(f); var f = f - f_min; var r1 = MathNoise.data[f_min]; var r2 = MathNoise.data[f_min == 1023 ? 0 : f_min + 1]; - if (smooth) f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); + if (smooth) { + f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); + } return r1 * (1 - f) + r2 * f; }; @@ -274,7 +300,9 @@ this.properties.min_time; this._blink_time = this.properties.duration; this.boxcolor = "#FFF"; - } else this.boxcolor = "#000"; + } else { + this.boxcolor = "#000"; + } this.setOutputData(0, v); }; @@ -295,7 +323,9 @@ MathClamp.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } v = Math.max(this.properties.min, v); v = Math.min(this.properties.max, v); this.setOutputData(0, v); @@ -303,13 +333,14 @@ MathClamp.prototype.getCode = function(lang) { var code = ""; - if (this.isInputConnected(0)) + if (this.isInputConnected(0)) { code += "clamp({{0}}," + this.properties.min + "," + this.properties.max + ")"; + } return code; }; @@ -329,14 +360,20 @@ MathLerp.prototype.onExecute = function() { var v1 = this.getInputData(0); - if (v1 == null) v1 = 0; + if (v1 == null) { + v1 = 0; + } var v2 = this.getInputData(1); - if (v2 == null) v2 = 0; + if (v2 == null) { + v2 = 0; + } var f = this.properties.f; var _f = this.getInputData(2); - if (_f !== undefined) f = _f; + if (_f !== undefined) { + f = _f; + } this.setOutputData(0, v1 * (1 - f) + v2 * f); }; @@ -359,7 +396,9 @@ MathAbs.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, Math.abs(v)); }; @@ -377,7 +416,9 @@ MathFloor.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, Math.floor(v)); }; @@ -395,7 +436,9 @@ MathFrac.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v % 1); }; @@ -414,7 +457,9 @@ MathSmoothStep.prototype.onExecute = function() { var v = this.getInputData(0); - if (v === undefined) return; + if (v === undefined) { + return; + } var edge0 = this.properties.A; var edge1 = this.properties.B; @@ -442,8 +487,9 @@ MathScale.prototype.onExecute = function() { var value = this.getInputData(0); - if (value != null) + if (value != null) { this.setOutputData(0, value * this.properties.factor); + } }; LiteGraph.registerNodeType("math/scale", MathScale); @@ -463,28 +509,39 @@ MathAverageFilter.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) v = 0; + if (v == null) { + v = 0; + } var num_samples = this._values.length; this._values[this._current % num_samples] = v; this._current += 1; - if (this._current > num_samples) this._current = 0; + if (this._current > num_samples) { + this._current = 0; + } var avr = 0; - for (var i = 0; i < num_samples; ++i) avr += this._values[i]; + for (var i = 0; i < num_samples; ++i) { + avr += this._values[i]; + } this.setOutputData(0, avr / num_samples); }; MathAverageFilter.prototype.onPropertyChanged = function(name, value) { - if (value < 1) value = 1; + if (value < 1) { + value = 1; + } this.properties.samples = Math.round(value); var old = this._values; this._values = new Float32Array(this.properties.samples); - if (old.length <= this._values.length) this._values.set(old); - else this._values.set(old.subarray(0, this._values.length)); + if (old.length <= this._values.length) { + this._values.set(old); + } else { + this._values.set(old.subarray(0, this._values.length)); + } }; LiteGraph.registerNodeType("math/average", MathAverageFilter); @@ -503,10 +560,15 @@ MathTendTo.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) v = 0; + if (v == null) { + v = 0; + } var f = this.properties.factor; - if (this._value == null) this._value = v; - else this._value = this._value * (1 - f) + v * f; + if (this._value == null) { + this._value = v; + } else { + this._value = this._value * (1 - f) + v * f; + } this.setOutputData(0, this._value); }; @@ -538,18 +600,26 @@ }; MathOperation.prototype.setValue = function(v) { - if (typeof v == "string") v = parseFloat(v); + if (typeof v == "string") { + v = parseFloat(v); + } this.properties["value"] = v; }; MathOperation.prototype.onExecute = function() { var A = this.getInputData(0); var B = this.getInputData(1); - if (A != null) this.properties["A"] = A; - else A = this.properties["A"]; + if (A != null) { + this.properties["A"] = A; + } else { + A = this.properties["A"]; + } - if (B != null) this.properties["B"] = B; - else B = this.properties["B"]; + if (B != null) { + this.properties["B"] = B; + } else { + B = this.properties["B"]; + } var result = 0; switch (this.properties.OP) { @@ -580,7 +650,9 @@ }; MathOperation.prototype.onDrawBackground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } ctx.font = "40px Arial"; ctx.fillStyle = "#666"; @@ -611,15 +683,23 @@ MathCompare.prototype.onExecute = function() { var A = this.getInputData(0); var B = this.getInputData(1); - if (A !== undefined) this.properties["A"] = A; - else A = this.properties["A"]; + if (A !== undefined) { + this.properties["A"] = A; + } else { + A = this.properties["A"]; + } - if (B !== undefined) this.properties["B"] = B; - else B = this.properties["B"]; + if (B !== undefined) { + this.properties["B"] = B; + } else { + B = this.properties["B"]; + } for (var i = 0, l = this.outputs.length; i < l; ++i) { var output = this.outputs[i]; - if (!output.links || !output.links.length) continue; + if (!output.links || !output.links.length) { + continue; + } var value; switch (output.name) { case "A==B": @@ -706,12 +786,18 @@ MathCondition.prototype.onExecute = function() { var A = this.getInputData(0); - if (A === undefined) A = this.properties.A; - else this.properties.A = A; + 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; + if (B === undefined) { + B = this.properties.B; + } else { + this.properties.B = B; + } var result = true; switch (this.properties.OP) { @@ -751,11 +837,16 @@ MathAccumulate.desc = "Increments a value every time"; MathAccumulate.prototype.onExecute = function() { - if (this.properties.value === null) this.properties.value = 0; + if (this.properties.value === null) { + this.properties.value = 0; + } var inc = this.getInputData(0); - if (inc !== null) this.properties.value += inc; - else this.properties.value += this.properties.increment; + if (inc !== null) { + this.properties.value += inc; + } else { + this.properties.value += this.properties.increment; + } this.setOutputData(0, this.properties.value); }; @@ -777,13 +868,19 @@ MathTrigonometry.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) v = 0; + if (v == null) { + v = 0; + } var amplitude = this.properties["amplitude"]; var slot = this.findInputSlot("amplitude"); - if (slot != -1) amplitude = this.getInputData(slot); + if (slot != -1) { + amplitude = this.getInputData(slot); + } var offset = this.properties["offset"]; slot = this.findInputSlot("offset"); - if (slot != -1) offset = this.getInputData(slot); + if (slot != -1) { + offset = this.getInputData(slot); + } for (var i = 0, l = this.outputs.length; i < l; ++i) { var output = this.outputs[i]; @@ -867,19 +964,29 @@ MathFormula.size = [160, 100]; MathAverageFilter.prototype.onPropertyChanged = function(name, value) { - if (name == "formula") this.code_widget.value = value; + if (name == "formula") { + this.code_widget.value = value; + } }; MathFormula.prototype.onExecute = function() { - if (!LiteGraph.allow_scripts) return; + if (!LiteGraph.allow_scripts) { + return; + } var x = this.getInputData(0); var y = this.getInputData(1); - if (x != null) this.properties["x"] = x; - else x = this.properties["x"]; + if (x != null) { + this.properties["x"] = x; + } else { + x = this.properties["x"]; + } - if (y != null) this.properties["y"] = y; - else y = this.properties["y"]; + if (y != null) { + this.properties["y"] = y; + } else { + y = this.properties["y"]; + } var f = this.properties["formula"]; @@ -908,7 +1015,9 @@ MathFormula.prototype.onDrawBackground = function() { var f = this.properties["formula"]; - if (this.outputs && this.outputs.length) this.outputs[0].label = f; + if (this.outputs && this.outputs.length) { + this.outputs[0].label = f; + } }; LiteGraph.registerNodeType("math/formula", MathFormula); @@ -924,7 +1033,9 @@ Math3DVec2ToXYZ.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v[0]); this.setOutputData(1, v[1]); @@ -944,9 +1055,13 @@ Math3DXYToVec2.prototype.onExecute = function() { var x = this.getInputData(0); - if (x == null) x = this.properties.x; + if (x == null) { + x = this.properties.x; + } var y = this.getInputData(1); - if (y == null) y = this.properties.y; + if (y == null) { + y = this.properties.y; + } var data = this._data; data[0] = x; @@ -969,7 +1084,9 @@ Math3DVec3ToXYZ.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v[0]); this.setOutputData(1, v[1]); @@ -990,11 +1107,17 @@ Math3DXYZToVec3.prototype.onExecute = function() { var x = this.getInputData(0); - if (x == null) x = this.properties.x; + if (x == null) { + x = this.properties.x; + } var y = this.getInputData(1); - if (y == null) y = this.properties.y; + if (y == null) { + y = this.properties.y; + } var z = this.getInputData(2); - if (z == null) z = this.properties.z; + if (z == null) { + z = this.properties.z; + } var data = this._data; data[0] = x; @@ -1019,7 +1142,9 @@ Math3DVec4ToXYZW.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v[0]); this.setOutputData(1, v[1]); @@ -1046,13 +1171,21 @@ Math3DXYZWToVec4.prototype.onExecute = function() { var x = this.getInputData(0); - if (x == null) x = this.properties.x; + if (x == null) { + x = this.properties.x; + } var y = this.getInputData(1); - if (y == null) y = this.properties.y; + if (y == null) { + y = this.properties.y; + } var z = this.getInputData(2); - if (z == null) z = this.properties.z; + if (z == null) { + z = this.properties.z; + } var w = this.getInputData(3); - if (w == null) w = this.properties.w; + if (w == null) { + w = this.properties.w; + } var data = this._data; data[0] = x; @@ -1099,9 +1232,13 @@ Math3DRotation.prototype.onExecute = function() { var angle = this.getInputData(0); - if (angle == null) angle = this.properties.angle; + if (angle == null) { + angle = this.properties.angle; + } var axis = this.getInputData(1); - if (axis == null) axis = this.properties.axis; + if (axis == null) { + axis = this.properties.axis; + } var R = quat.setAxisAngle(this._value, axis, angle * 0.0174532925); this.setOutputData(0, R); @@ -1121,14 +1258,18 @@ Math3DRotateVec3.prototype.onExecute = function() { var vec = this.getInputData(0); - if (vec == null) vec = this.properties.vec; + if (vec == null) { + vec = this.properties.vec; + } var quat = this.getInputData(1); - if (quat == null) this.setOutputData(vec); - else + if (quat == null) { + this.setOutputData(vec); + } else { this.setOutputData( 0, vec3.transformQuat(vec3.create(), vec, quat) ); + } }; LiteGraph.registerNodeType("math3d/rotate_vec3", Math3DRotateVec3); @@ -1145,9 +1286,13 @@ Math3DMultQuat.prototype.onExecute = function() { var A = this.getInputData(0); - if (A == null) return; + if (A == null) { + return; + } var B = this.getInputData(1); - if (B == null) return; + if (B == null) { + return; + } var R = quat.multiply(this._value, A, B); this.setOutputData(0, R); @@ -1172,11 +1317,17 @@ Math3DQuatSlerp.prototype.onExecute = function() { var A = this.getInputData(0); - if (A == null) return; + if (A == null) { + return; + } var B = this.getInputData(1); - if (B == null) return; + if (B == null) { + return; + } var factor = this.properties.factor; - if (this.getInputData(2) != null) factor = this.getInputData(2); + if (this.getInputData(2) != null) { + factor = this.getInputData(2); + } var R = quat.slerp(this._value, A, B, factor); this.setOutputData(0, R); diff --git a/src/nodes/math3d.js b/src/nodes/math3d.js index 9b8a6a3a7..e67807020 100644 --- a/src/nodes/math3d.js +++ b/src/nodes/math3d.js @@ -12,7 +12,9 @@ Math3DVec2ToXYZ.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v[0]); this.setOutputData(1, v[1]); @@ -32,9 +34,13 @@ Math3DXYToVec2.prototype.onExecute = function() { var x = this.getInputData(0); - if (x == null) x = this.properties.x; + if (x == null) { + x = this.properties.x; + } var y = this.getInputData(1); - if (y == null) y = this.properties.y; + if (y == null) { + y = this.properties.y; + } var data = this._data; data[0] = x; @@ -57,7 +63,9 @@ Math3DVec3ToXYZ.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v[0]); this.setOutputData(1, v[1]); @@ -78,11 +86,17 @@ Math3DXYZToVec3.prototype.onExecute = function() { var x = this.getInputData(0); - if (x == null) x = this.properties.x; + if (x == null) { + x = this.properties.x; + } var y = this.getInputData(1); - if (y == null) y = this.properties.y; + if (y == null) { + y = this.properties.y; + } var z = this.getInputData(2); - if (z == null) z = this.properties.z; + if (z == null) { + z = this.properties.z; + } var data = this._data; data[0] = x; @@ -107,7 +121,9 @@ Math3DVec4ToXYZW.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } this.setOutputData(0, v[0]); this.setOutputData(1, v[1]); @@ -134,13 +150,21 @@ Math3DXYZWToVec4.prototype.onExecute = function() { var x = this.getInputData(0); - if (x == null) x = this.properties.x; + if (x == null) { + x = this.properties.x; + } var y = this.getInputData(1); - if (y == null) y = this.properties.y; + if (y == null) { + y = this.properties.y; + } var z = this.getInputData(2); - if (z == null) z = this.properties.z; + if (z == null) { + z = this.properties.z; + } var w = this.getInputData(3); - if (w == null) w = this.properties.w; + if (w == null) { + w = this.properties.w; + } var data = this._data; data[0] = x; @@ -166,9 +190,13 @@ Math3DVec3Scale.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } var f = this.getInputData(1); - if (f == null) f = this.properties.f; + if (f == null) { + f = this.properties.f; + } var data = this._data; data[0] = v[0] * f; @@ -189,7 +217,9 @@ Math3DVec3Length.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } var dist = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); this.setOutputData(0, dist); }; @@ -207,7 +237,9 @@ Math3DVec3Normalize.prototype.onExecute = function() { var v = this.getInputData(0); - if (v == null) return; + if (v == null) { + return; + } var dist = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); var data = this._data; data[0] = v[0] / dist; @@ -233,9 +265,13 @@ Math3DVec3Lerp.prototype.onExecute = function() { var A = this.getInputData(0); - if (A == null) return; + if (A == null) { + return; + } var B = this.getInputData(1); - if (B == null) return; + if (B == null) { + return; + } var f = this.getInputOrProperty("f"); var data = this._data; @@ -259,9 +295,13 @@ Math3DVec3Dot.prototype.onExecute = function() { var A = this.getInputData(0); - if (A == null) return; + if (A == null) { + return; + } var B = this.getInputData(1); - if (B == null) return; + if (B == null) { + return; + } var dot = A[0] * B[0] + A[1] * B[1] + A[2] * B[2]; this.setOutputData(0, dot); @@ -285,8 +325,9 @@ this._value[1] = this.getInputOrProperty("y"); this._value[2] = this.getInputOrProperty("z"); this._value[3] = this.getInputOrProperty("w"); - if (this.properties.normalize) + if (this.properties.normalize) { quat.normalize(this._value, this._value); + } this.setOutputData(0, this._value); }; @@ -314,9 +355,13 @@ Math3DRotation.prototype.onExecute = function() { var angle = this.getInputData(0); - if (angle == null) angle = this.properties.angle; + if (angle == null) { + angle = this.properties.angle; + } var axis = this.getInputData(1); - if (axis == null) axis = this.properties.axis; + if (axis == null) { + axis = this.properties.axis; + } var R = quat.setAxisAngle(this._value, axis, angle * 0.0174532925); this.setOutputData(0, R); @@ -336,14 +381,18 @@ Math3DRotateVec3.prototype.onExecute = function() { var vec = this.getInputData(0); - if (vec == null) vec = this.properties.vec; + if (vec == null) { + vec = this.properties.vec; + } var quat = this.getInputData(1); - if (quat == null) this.setOutputData(vec); - else + if (quat == null) { + this.setOutputData(vec); + } else { this.setOutputData( 0, vec3.transformQuat(vec3.create(), vec, quat) ); + } }; LiteGraph.registerNodeType("math3d/rotate_vec3", Math3DRotateVec3); @@ -360,9 +409,13 @@ Math3DMultQuat.prototype.onExecute = function() { var A = this.getInputData(0); - if (A == null) return; + if (A == null) { + return; + } var B = this.getInputData(1); - if (B == null) return; + if (B == null) { + return; + } var R = quat.multiply(this._value, A, B); this.setOutputData(0, R); @@ -387,11 +440,17 @@ Math3DQuatSlerp.prototype.onExecute = function() { var A = this.getInputData(0); - if (A == null) return; + if (A == null) { + return; + } var B = this.getInputData(1); - if (B == null) return; + if (B == null) { + return; + } var factor = this.properties.factor; - if (this.getInputData(2) != null) factor = this.getInputData(2); + if (this.getInputData(2) != null) { + factor = this.getInputData(2); + } var R = quat.slerp(this._value, A, B, factor); this.setOutputData(0, R); diff --git a/src/nodes/midi.js b/src/nodes/midi.js index 180171773..1a20122ed 100644 --- a/src/nodes/midi.js +++ b/src/nodes/midi.js @@ -7,7 +7,9 @@ this.cmd = 0; this.data = new Uint32Array(3); - if (data) this.setup(data); + if (data) { + this.setup(data); + } } LiteGraph.MIDIEvent = MIDIEvent; @@ -18,7 +20,9 @@ MIDIEvent.prototype.setup = function(data) { var raw_data = data; - if (data.constructor === Object) raw_data = data.data; + if (data.constructor === Object) { + raw_data = data.data; + } this.data.set(raw_data); @@ -27,11 +31,15 @@ var midiCommand = midiStatus & 0xf0; - if (midiStatus >= 0xf0) this.cmd = midiStatus; - else this.cmd = midiCommand; + if (midiStatus >= 0xf0) { + this.cmd = midiStatus; + } else { + this.cmd = midiCommand; + } - if (this.cmd == MIDIEvent.NOTEON && this.velocity == 0) + if (this.cmd == MIDIEvent.NOTEON && this.velocity == 0) { this.cmd = MIDIEvent.NOTEOFF; + } this.cmd_str = MIDIEvent.commands[this.cmd] || ""; @@ -45,7 +53,9 @@ Object.defineProperty(MIDIEvent.prototype, "velocity", { get: function() { - if (this.cmd == MIDIEvent.NOTEON) return this.data[2]; + if (this.cmd == MIDIEvent.NOTEON) { + return this.data[2]; + } return -1; }, set: function(v) { @@ -85,7 +95,9 @@ Object.defineProperty(MIDIEvent.prototype, "note", { get: function() { - if (this.cmd != MIDIEvent.NOTEON) return -1; + if (this.cmd != MIDIEvent.NOTEON) { + return -1; + } return MIDIEvent.toNoteString(this.data[1], true); }, set: function(v) { @@ -96,7 +108,9 @@ Object.defineProperty(MIDIEvent.prototype, "octave", { get: function() { - if (this.cmd != MIDIEvent.NOTEON) return -1; + if (this.cmd != MIDIEvent.NOTEON) { + return -1; + } var octave = this.data[1] - 24; return Math.floor(octave / 12 + 1); }, @@ -137,9 +151,13 @@ }; MIDIEvent.computeCommandFromString = function(str) { - if (!str) return 0; + if (!str) { + return 0; + } - if (str && str.constructor === Number) return str; + if (str && str.constructor === Number) { + return str; + } str = str.toUpperCase(); switch (str) { @@ -188,7 +206,9 @@ var note = d - 21; var octave = Math.floor((d - 24) / 12 + 1); note = note % 12; - if (note < 0) note = 12 + note; + if (note < 0) { + note = 12 + note; + } return MIDIEvent.notes[note] + (skip_octave ? "" : octave); }; @@ -199,12 +219,18 @@ if (str[1] == "#") { note += "#"; - if (str.length > 2) octave = Number(str[2]); + if (str.length > 2) { + octave = Number(str[2]); + } } else { - if (str.length > 1) octave = Number(str[1]); + if (str.length > 1) { + octave = Number(str[1]); + } } var pitch = MIDIEvent.note_to_index[note]; - if (pitch == null) return null; + if (pitch == null) { + return null; + } return (octave - 1) * 12 + pitch + 21; }; @@ -236,8 +262,9 @@ MIDIEvent.prototype.toHexString = function() { var str = ""; - for (var i = 0; i < this.data.length; i++) + for (var i = 0; i < this.data.length; i++) { str += this.data[i].toString(16) + " "; + } }; MIDIEvent.prototype.toJSON = function() { @@ -297,15 +324,19 @@ }; MIDIEvent.commands_reversed = {}; - for (var i in MIDIEvent.commands) + for (var i in MIDIEvent.commands) { MIDIEvent.commands_reversed[MIDIEvent.commands[i]] = i; + } //MIDI wrapper function MIDIInterface(on_ready, on_error) { if (!navigator.requestMIDIAccess) { this.error = "not suppoorted"; - if (on_error) on_error("Not supported"); - else console.error("MIDI NOT SUPPORTED, enable by chrome://flags"); + if (on_error) { + on_error("Not supported"); + } else { + console.error("MIDI NOT SUPPORTED, enable by chrome://flags"); + } return; } @@ -331,7 +362,9 @@ this.midi = midiAccess; // store in the global (in real usage, would probably keep in an object instance) this.updatePorts(); - if (this.on_ready) this.on_ready(this); + if (this.on_ready) { + this.on_ready(this); + } }; MIDIInterface.prototype.updatePorts = function() { @@ -419,16 +452,21 @@ MIDIInterface.prototype.openInputPort = function(port, callback) { var input_port = this.input_ports.get("input-" + port); - if (!input_port) return false; + if (!input_port) { + return false; + } MIDIInterface.input = this; var that = this; input_port.onmidimessage = function(a) { var midi_event = new MIDIEvent(a.data); that.updateState(midi_event); - if (callback) callback(a.data, midi_event); - if (MIDIInterface.on_message) + if (callback) { + callback(a.data, midi_event); + } + if (MIDIInterface.on_message) { MIDIInterface.on_message(a.data, midi_event); + } }; console.log("port open: ", input_port); return true; @@ -451,16 +489,22 @@ }; MIDIInterface.prototype.sendMIDI = function(port, midi_data) { - if (!midi_data) return; + if (!midi_data) { + return; + } var output_port = this.output_ports.get("output-" + port); - if (!output_port) return; + if (!output_port) { + return; + } MIDIInterface.output = this; - if (midi_data.constructor === MIDIEvent) + if (midi_data.constructor === MIDIEvent) { output_port.send(midi_data.data); - else output_port.send(midi_data); + } else { + output_port.send(midi_data); + } }; function LGMIDIIn() { @@ -476,7 +520,9 @@ new MIDIInterface(function(midi) { //open that._midi = midi; - if (that._waiting) that.onStart(); + if (that._waiting) { + that.onStart(); + } that._waiting = false; }); } @@ -488,7 +534,9 @@ LGMIDIIn.color = MIDI_COLOR; LGMIDIIn.prototype.getPropertyInfo = function(name) { - if (!this._midi) return; + if (!this._midi) { + return; + } if (name == "port") { var values = {}; @@ -502,12 +550,14 @@ }; LGMIDIIn.prototype.onStart = function() { - if (this._midi) + if (this._midi) { this._midi.openInputPort( this.properties.port, this.onMIDIEvent.bind(this) ); - else this._waiting = true; + } else { + this._waiting = true; + } }; LGMIDIIn.prototype.onMIDIEvent = function(data, midi_event) { @@ -515,16 +565,17 @@ this.boxcolor = "#AFA"; this._last_time = LiteGraph.getTime(); this.trigger("on_midi", midi_event); - if (midi_event.cmd == MIDIEvent.NOTEON) + if (midi_event.cmd == MIDIEvent.NOTEON) { this.trigger("on_noteon", midi_event); - else if (midi_event.cmd == MIDIEvent.NOTEOFF) + } else if (midi_event.cmd == MIDIEvent.NOTEOFF) { this.trigger("on_noteoff", midi_event); - else if (midi_event.cmd == MIDIEvent.CONTROLLERCHANGE) + } else if (midi_event.cmd == MIDIEvent.CONTROLLERCHANGE) { this.trigger("on_cc", midi_event); - else if (midi_event.cmd == MIDIEvent.PROGRAMCHANGE) + } else if (midi_event.cmd == MIDIEvent.PROGRAMCHANGE) { this.trigger("on_pc", midi_event); - else if (midi_event.cmd == MIDIEvent.PITCHBEND) + } else if (midi_event.cmd == MIDIEvent.PITCHBEND) { this.trigger("on_pitchbend", midi_event); + } }; LGMIDIIn.prototype.onDrawBackground = function(ctx) { @@ -600,7 +651,9 @@ LGMIDIOut.color = MIDI_COLOR; LGMIDIOut.prototype.getPropertyInfo = function(name) { - if (!this._midi) return; + if (!this._midi) { + return; + } if (name == "port") { var values = {}; @@ -615,8 +668,12 @@ LGMIDIOut.prototype.onAction = function(event, midi_event) { //console.log(midi_event); - if (!this._midi) return; - if (event == "send") this._midi.sendMIDI(this.port, midi_event); + if (!this._midi) { + return; + } + if (event == "send") { + this._midi.sendMIDI(this.port, midi_event); + } this.trigger("midi", midi_event); }; @@ -641,19 +698,27 @@ LGMIDIShow.color = MIDI_COLOR; LGMIDIShow.prototype.getTitle = function() { - if (this.flags.collapsed) return this._str; + if (this.flags.collapsed) { + return this._str; + } return this.title; }; LGMIDIShow.prototype.onAction = function(event, midi_event) { - if (!midi_event) return; - if (midi_event.constructor === MIDIEvent) + if (!midi_event) { + return; + } + if (midi_event.constructor === MIDIEvent) { this._str = midi_event.toString(); - else this._str = "???"; + } else { + this._str = "???"; + } }; LGMIDIShow.prototype.onDrawForeground = function(ctx) { - if (!this._str || this.flags.collapsed) return; + if (!this._str || this.flags.collapsed) { + return; + } ctx.font = "30px Arial"; ctx.fillText(this._str, 10, this.size[1] * 0.8); @@ -701,10 +766,16 @@ LGMIDIFilter.prototype.getTitle = function() { var str = null; - if (this.properties.cmd == -1) str = "Nothing"; - else str = MIDIEvent.commands_short[this.properties.cmd] || "Unknown"; + if (this.properties.cmd == -1) { + str = "Nothing"; + } else { + str = MIDIEvent.commands_short[this.properties.cmd] || "Unknown"; + } - if (this.properties.min_value != -1 && this.properties.max_value != -1) + if ( + this.properties.min_value != -1 && + this.properties.max_value != -1 + ) { str += " " + (this.properties.min_value == this.properties.max_value @@ -712,6 +783,7 @@ : this.properties.min_value + ".." + this.properties.max_value); + } return "Filter: " + str; }; @@ -719,13 +791,17 @@ LGMIDIFilter.prototype.onPropertyChanged = function(name, value) { if (name == "cmd") { var num = Number(value); - if (isNaN(num)) num = MIDIEvent.commands[value] || 0; + if (isNaN(num)) { + num = MIDIEvent.commands[value] || 0; + } this.properties.cmd = num; } }; LGMIDIFilter.prototype.onAction = function(event, midi_event) { - if (!midi_event || midi_event.constructor !== MIDIEvent) return; + if (!midi_event || midi_event.constructor !== MIDIEvent) { + return; + } if (this._learning) { this._learning = false; @@ -738,23 +814,27 @@ if ( this.properties.channel != -1 && midi_event.channel != this.properties.channel - ) + ) { return; + } if ( this.properties.cmd != -1 && midi_event.cmd != this.properties.cmd - ) + ) { return; + } if ( this.properties.min_value != -1 && midi_event.data[1] < this.properties.min_value - ) + ) { return; + } if ( this.properties.max_value != -1 && midi_event.data[1] > this.properties.max_value - ) + ) { return; + } } this.trigger("on_midi", midi_event); @@ -788,17 +868,22 @@ this.properties.cmd = midi_event.cmd; this.properties.value1 = midi_event.data[1]; this.properties.value2 = midi_event.data[2]; - if (midi_event.cmd == MIDIEvent.NOTEON) this.gate = true; - else if (midi_event.cmd == MIDIEvent.NOTEOFF) this.gate = false; + if (midi_event.cmd == MIDIEvent.NOTEON) { + this.gate = true; + } else if (midi_event.cmd == MIDIEvent.NOTEOFF) { + this.gate = false; + } return; } //send var midi_event = this.midi_event; midi_event.channel = this.properties.channel; - if (this.properties.cmd && this.properties.cmd.constructor === String) + if (this.properties.cmd && this.properties.cmd.constructor === String) { midi_event.setCommandFromString(this.properties.cmd); - else midi_event.cmd = this.properties.cmd; + } else { + midi_event.cmd = this.properties.cmd; + } midi_event.data[0] = midi_event.cmd | midi_event.channel; midi_event.data[1] = Number(this.properties.value1); midi_event.data[2] = Number(this.properties.value2); @@ -812,13 +897,16 @@ if (this.inputs) { for (var i = 0; i < this.inputs.length; ++i) { var input = this.inputs[i]; - if (input.link == -1) continue; + if (input.link == -1) { + continue; + } switch (input.name) { case "note": var v = this.getInputData(i); if (v != null) { - if (v.constructor === String) + if (v.constructor === String) { v = MIDIEvent.NoteStringToPitch(v); + } this.properties.value1 = (v | 0) % 255; } break; @@ -876,14 +964,17 @@ default: continue; } - if (v !== null) this.setOutputData(i, v); + if (v !== null) { + this.setOutputData(i, v); + } } } }; LGMIDIEvent.prototype.onPropertyChanged = function(name, value) { - if (name == "cmd") + if (name == "cmd") { this.properties.cmd = MIDIEvent.computeCommandFromString(value); + } }; LGMIDIEvent.prototype.onGetInputs = function() { @@ -923,9 +1014,10 @@ LGMIDICC.prototype.onExecute = function() { var props = this.properties; - if (MIDIInterface.input) + if (MIDIInterface.input) { this.properties.value = MIDIInterface.input.state.cc[this.properties.cc]; + } this.setOutputData(0, this.properties.value); }; @@ -957,24 +1049,31 @@ var notes = scale.split(","); for (var i = 0; i < notes.length; ++i) { var n = notes[i]; - if ((n.length == 2 && n[1] != "#") || n.length > 2) + if ((n.length == 2 && n[1] != "#") || n.length > 2) { notes[i] = -LiteGraph.MIDIEvent.NoteStringToPitch(n); - else notes[i] = MIDIEvent.note_to_index[n] || 0; + } else { + notes[i] = MIDIEvent.note_to_index[n] || 0; + } } return notes; }; LGMIDIGenerator.prototype.onPropertyChanged = function(name, value) { - if (name == "notes") + if (name == "notes") { this.notes_pitches = LGMIDIGenerator.processScale(value); + } }; LGMIDIGenerator.prototype.onExecute = function() { var octave = this.getInputData(2); - if (octave != null) this.properties.octave = octave; + if (octave != null) { + this.properties.octave = octave; + } var scale = this.getInputData(1); - if (scale) this.notes_pitches = LGMIDIGenerator.processScale(scale); + if (scale) { + this.notes_pitches = LGMIDIGenerator.processScale(scale); + } }; LGMIDIGenerator.prototype.onAction = function(event, midi_event) { @@ -984,14 +1083,18 @@ var range = this.notes_pitches.length; var index = 0; - if (this.properties.mode == "sequence") + if (this.properties.mode == "sequence") { index = this.sequence_index = (this.sequence_index + 1) % range; - else if (this.properties.mode == "random") + } else if (this.properties.mode == "random") { index = Math.floor(Math.random() * range); + } var note = this.notes_pitches[index]; - if (note >= 0) pitch = note + (this.properties.octave - 1) * 12 + 33; - else pitch = -note; + if (note >= 0) { + pitch = note + (this.properties.octave - 1) * 12 + 33; + } else { + pitch = -note; + } var midi_event = new MIDIEvent(); midi_event.setup([MIDIEvent.NOTEON, pitch, 10]); @@ -1027,7 +1130,9 @@ LGMIDITranspose.color = MIDI_COLOR; LGMIDITranspose.prototype.onAction = function(event, midi_event) { - if (!midi_event || midi_event.constructor !== MIDIEvent) return; + if (!midi_event || midi_event.constructor !== MIDIEvent) { + return; + } if ( midi_event.data[0] == MIDIEvent.NOTEON || @@ -1039,12 +1144,16 @@ this.midi_event.data[1] + this.properties.amount ); this.trigger("out", this.midi_event); - } else this.trigger("out", midi_event); + } else { + this.trigger("out", midi_event); + } }; LGMIDITranspose.prototype.onExecute = function() { var amount = this.getInputData(1); - if (amount != null) this.properties.amount = amount; + if (amount != null) { + this.properties.amount = amount; + } }; LiteGraph.registerNodeType("midi/transpose", LGMIDITranspose); @@ -1067,14 +1176,17 @@ LGMIDIQuantize.color = MIDI_COLOR; LGMIDIQuantize.prototype.onPropertyChanged = function(name, value) { - if (name == "scale") this.processScale(value); + if (name == "scale") { + this.processScale(value); + } }; LGMIDIQuantize.prototype.processScale = function(scale) { this._current_scale = scale; this.notes_pitches = LGMIDIGenerator.processScale(scale); - for (var i = 0; i < 12; ++i) + for (var i = 0; i < 12; ++i) { this.valid_notes[i] = this.notes_pitches.indexOf(i) != -1; + } for (var i = 0; i < 12; ++i) { if (this.valid_notes[i]) { this.offset_notes[i] = 0; @@ -1094,7 +1206,9 @@ }; LGMIDIQuantize.prototype.onAction = function(event, midi_event) { - if (!midi_event || midi_event.constructor !== MIDIEvent) return; + if (!midi_event || midi_event.constructor !== MIDIEvent) { + return; + } if ( midi_event.data[0] == MIDIEvent.NOTEON || @@ -1107,13 +1221,16 @@ var offset = this.offset_notes[index]; this.midi_event.data[1] += offset; this.trigger("out", this.midi_event); - } else this.trigger("out", midi_event); + } else { + this.trigger("out", midi_event); + } }; LGMIDIQuantize.prototype.onExecute = function() { var scale = this.getInputData(1); - if (scale != null && scale != this._current_scale) + if (scale != null && scale != this._current_scale) { this.processScale(scale); + } }; LiteGraph.registerNodeType("midi/quantize", LGMIDIQuantize); @@ -1144,12 +1261,15 @@ LGMIDIPlay.color = MIDI_COLOR; LGMIDIPlay.prototype.onAction = function(event, midi_event) { - if (!midi_event || midi_event.constructor !== MIDIEvent) return; + if (!midi_event || midi_event.constructor !== MIDIEvent) { + return; + } if (this.instrument && midi_event.data[0] == MIDIEvent.NOTEON) { var note = midi_event.note; //C# - if (!note || note == "undefined" || note.constructor !== String) + if (!note || note == "undefined" || note.constructor !== String) { return; + } this.instrument.play( note, midi_event.octave, @@ -1162,10 +1282,14 @@ LGMIDIPlay.prototype.onExecute = function() { var volume = this.getInputData(1); - if (volume != null) this.properties.volume = volume; + if (volume != null) { + this.properties.volume = volume; + } var duration = this.getInputData(2); - if (duration != null) this.properties.duration = duration; + if (duration != null) { + this.properties.duration = duration; + } }; LiteGraph.registerNodeType("midi/play", LGMIDIPlay); @@ -1203,7 +1327,9 @@ ]; LGMIDIKeys.prototype.onDrawForeground = function(ctx) { - if (this.flags.collapsed) return; + if (this.flags.collapsed) { + return; + } var num_keys = this.properties.num_octaves * 12; this.keys.length = num_keys; @@ -1216,14 +1342,19 @@ var k = 0; k < 2; k++ //draw first whites (0) then blacks (1) - ) + ) { for (var i = 0; i < num_keys; ++i) { var key_info = LGMIDIKeys.keys[i % 12]; - if (key_info.t != k) continue; + if (key_info.t != k) { + continue; + } var octave = Math.floor(i / 12); var x = octave * 7 * key_width + key_info.x * key_width; - if (k == 0) ctx.fillStyle = this.keys[i] ? "#CCC" : "white"; - else ctx.fillStyle = this.keys[i] ? "#333" : "black"; + if (k == 0) { + ctx.fillStyle = this.keys[i] ? "#CCC" : "white"; + } else { + ctx.fillStyle = this.keys[i] ? "#333" : "black"; + } ctx.fillRect( x + 1, 0, @@ -1231,6 +1362,7 @@ key_height * key_info.h ); } + } }; LGMIDIKeys.prototype.getKeyIndex = function(pos) { @@ -1242,41 +1374,54 @@ var k = 1; k >= 0; k-- //test blacks first (1) then whites (0) - ) + ) { for (var i = 0; i < this.keys.length; ++i) { var key_info = LGMIDIKeys.keys[i % 12]; - if (key_info.t != k) continue; + if (key_info.t != k) { + continue; + } var octave = Math.floor(i / 12); var x = octave * 7 * key_width + key_info.x * key_width; var w = key_width * key_info.w; var h = key_height * key_info.h; - if (pos[0] < x || pos[0] > x + w || pos[1] > h) continue; + if (pos[0] < x || pos[0] > x + w || pos[1] > h) { + continue; + } return i; } + } return -1; }; LGMIDIKeys.prototype.onAction = function(event, params) { if (event == "reset") { - for (var i = 0; i < this.keys.length; ++i) this.keys[i] = false; + for (var i = 0; i < this.keys.length; ++i) { + this.keys[i] = false; + } return; } - if (!params || params.constructor !== MIDIEvent) return; + if (!params || params.constructor !== MIDIEvent) { + return; + } var midi_event = params; var start_note = (this.properties.start_octave - 1) * 12 + 29; var index = midi_event.data[1] - start_note; if (index >= 0 && index < this.keys.length) { - if (midi_event.data[0] == MIDIEvent.NOTEON) this.keys[index] = true; - else if (midi_event.data[0] == MIDIEvent.NOTEOFF) + if (midi_event.data[0] == MIDIEvent.NOTEON) { + this.keys[index] = true; + } else if (midi_event.data[0] == MIDIEvent.NOTEOFF) { this.keys[index] = false; + } } this.trigger("note", midi_event); }; LGMIDIKeys.prototype.onMouseDown = function(e, pos) { - if (pos[1] < 0) return; + if (pos[1] < 0) { + return; + } var index = this.getKeyIndex(pos); this.keys[index] = true; this._last_key = index; @@ -1288,10 +1433,14 @@ }; LGMIDIKeys.prototype.onMouseMove = function(e, pos) { - if (pos[1] < 0 || this._last_key == -1) return; + if (pos[1] < 0 || this._last_key == -1) { + return; + } this.setDirtyCanvas(true); var index = this.getKeyIndex(pos); - if (this._last_key == index) return true; + if (this._last_key == index) { + return true; + } this.keys[this._last_key] = false; var pitch = (this.properties.start_octave - 1) * 12 + 29 + this._last_key; @@ -1310,7 +1459,9 @@ }; LGMIDIKeys.prototype.onMouseUp = function(e, pos) { - if (pos[1] < 0) return; + if (pos[1] < 0) { + return; + } var index = this.getKeyIndex(pos); this.keys[index] = false; this._last_key = -1; diff --git a/src/nodes/network.js b/src/nodes/network.js index 45aacbc3e..a1cd7001a 100644 --- a/src/nodes/network.js +++ b/src/nodes/network.js @@ -22,20 +22,28 @@ LGWebSocket.desc = "Send data through a websocket"; LGWebSocket.prototype.onPropertyChanged = function(name, value) { - if (name == "url") this.connectSocket(); + if (name == "url") { + this.connectSocket(); + } }; LGWebSocket.prototype.onExecute = function() { - if (!this._ws && this.properties.url) this.connectSocket(); + if (!this._ws && this.properties.url) { + this.connectSocket(); + } - if (!this._ws || this._ws.readyState != WebSocket.OPEN) return; + if (!this._ws || this._ws.readyState != WebSocket.OPEN) { + return; + } var room = this.properties.room; var only_changes = this.properties.only_send_changes; for (var i = 1; i < this.inputs.length; ++i) { var data = this.getInputData(i); - if (data == null) continue; + if (data == null) { + continue; + } var json; try { json = JSON.stringify({ @@ -47,22 +55,29 @@ } catch (err) { continue; } - if (only_changes && this._last_sent_data[i] == json) continue; + if (only_changes && this._last_sent_data[i] == json) { + continue; + } this._last_sent_data[i] = json; this._ws.send(json); } - for (var i = 1; i < this.outputs.length; ++i) + for (var i = 1; i < this.outputs.length; ++i) { this.setOutputData(i, this._last_received_data[i]); + } - if (this.boxcolor == "#AFA") this.boxcolor = "#6C6"; + if (this.boxcolor == "#AFA") { + this.boxcolor = "#6C6"; + } }; LGWebSocket.prototype.connectSocket = function() { var that = this; var url = this.properties.url; - if (url.substr(0, 2) != "ws") url = "ws://" + url; + if (url.substr(0, 2) != "ws") { + url = "ws://" + url; + } this._ws = new WebSocket(url); this._ws.onopen = function() { console.log("ready"); @@ -71,7 +86,9 @@ this._ws.onmessage = function(e) { that.boxcolor = "#AFA"; var data = JSON.parse(e.data); - if (data.room && data.room != this.properties.room) return; + if (data.room && data.room != this.properties.room) { + return; + } if (e.data.type == 1) { if ( data.data.object_class && @@ -84,8 +101,12 @@ } catch (err) { return; } - } else that.triggerSlot(0, data.data); - } else that._last_received_data[e.data.channel || 0] = data.data; + } else { + that.triggerSlot(0, data.data); + } + } else { + that._last_received_data[e.data.channel || 0] = data.data; + } }; this._ws.onerror = function(e) { console.log("couldnt connect to websocket"); @@ -98,12 +119,16 @@ }; LGWebSocket.prototype.send = function(data) { - if (!this._ws || this._ws.readyState != WebSocket.OPEN) return; + if (!this._ws || this._ws.readyState != WebSocket.OPEN) { + return; + } this._ws.send(JSON.stringify({ type: 1, msg: data })); }; LGWebSocket.prototype.onAction = function(action, param) { - if (!this._ws || this._ws.readyState != WebSocket.OPEN) return; + if (!this._ws || this._ws.readyState != WebSocket.OPEN) { + return; + } this._ws.send({ type: 1, room: this.properties.room, @@ -160,7 +185,9 @@ LGSillyClient.desc = "Connects to SillyServer to broadcast messages"; LGSillyClient.prototype.onPropertyChanged = function(name, value) { - if (name == "room") this.room_widget.value = value; + if (name == "room") { + this.room_widget.value = value; + } this.connectSocket(); }; @@ -183,33 +210,40 @@ }; LGSillyClient.prototype.onExecute = function() { - if (!this._server || !this._server.is_connected) return; + if (!this._server || !this._server.is_connected) { + return; + } var only_send_changes = this.properties.only_send_changes; for (var i = 1; i < this.inputs.length; ++i) { var data = this.getInputData(i); if (data != null) { - if (only_send_changes && this._last_sent_data[i] == data) + if (only_send_changes && this._last_sent_data[i] == data) { continue; + } this._server.sendMessage({ type: 0, channel: i, data: data }); this._last_sent_data[i] = data; } } - for (var i = 1; i < this.outputs.length; ++i) + for (var i = 1; i < this.outputs.length; ++i) { this.setOutputData(i, this._last_received_data[i]); + } - if (this.boxcolor == "#AFA") this.boxcolor = "#6C6"; + if (this.boxcolor == "#AFA") { + this.boxcolor = "#6C6"; + } }; LGSillyClient.prototype.connectSocket = function() { var that = this; if (typeof SillyClient == "undefined") { - if (!this._error) + if (!this._error) { console.error( "SillyClient node cannot be used, you must include SillyServer.js" ); + } this._error = true; return; } @@ -240,9 +274,13 @@ } catch (err) { return; } - } else that.triggerSlot(0, data.data); + } else { + that.triggerSlot(0, data.data); + } } //for FLOW slots - else that._last_received_data[data.channel || 0] = data.data; + else { + that._last_received_data[data.channel || 0] = data.data; + } that.boxcolor = "#AFA"; }; this._server.on_error = function(e) { @@ -267,12 +305,16 @@ }; LGSillyClient.prototype.send = function(data) { - if (!this._server || !this._server.is_connected) return; + if (!this._server || !this._server.is_connected) { + return; + } this._server.sendMessage({ type: 1, data: data }); }; LGSillyClient.prototype.onAction = function(action, param) { - if (!this._server || !this._server.is_connected) return; + if (!this._server || !this._server.is_connected) { + return; + } this._server.sendMessage({ type: 1, action: action, data: param }); }; diff --git a/src/nodes/strings.js b/src/nodes/strings.js index 177d556e5..b84b3af0e 100644 --- a/src/nodes/strings.js +++ b/src/nodes/strings.js @@ -20,8 +20,12 @@ ); function concatenate(a, b) { - if (a === undefined) return b; - if (b === undefined) return a; + if (a === undefined) { + return b; + } + if (b === undefined) { + return a; + } return a + b; } @@ -33,7 +37,9 @@ ); function contains(a, b) { - if (a === undefined || b === undefined) return false; + if (a === undefined || b === undefined) { + return false; + } return a.indexOf(b) != -1; } @@ -45,7 +51,9 @@ ); function toUpperCase(a) { - if (a != null && a.constructor === String) return a.toUpperCase(); + if (a != null && a.constructor === String) { + return a.toUpperCase(); + } return a; } @@ -57,7 +65,9 @@ ); function split(a, b) { - if (a != null && a.constructor === String) return a.split(b || " "); + if (a != null && a.constructor === String) { + return a.split(b || " "); + } return [a]; } @@ -69,8 +79,9 @@ ); function toFixed(a) { - if (a != null && a.constructor === Number) + if (a != null && a.constructor === Number) { return a.toFixed(this.properties.precision); + } return a; }
pixelcode must be vec3
uvcode must be vec2, is optional
uv: tex. coords
color: texture
colorB: textureB
time: scene time
value: input value