diff --git a/build/litegraph.js b/build/litegraph.js index de9f892f5..ace937693 100644 --- a/build/litegraph.js +++ b/build/litegraph.js @@ -1721,11 +1721,16 @@ LGraph.prototype.onNodeTrace = function(node, msg, color) input|output: every connection + { name:string, type:string, pos: [x,y]=Optional, direction: "input"|"output", links: Array }); - flags: + general properties: + clip_area: if you render outside the node, it will be cliped + unsafe_execution: not allowed for safe execution + skip_repeated_outputs: when adding new outputs, it wont show if there is one already connected + resizable: if set to false it wont be resizable with the mouse + + horizontal: slots are distributed horizontally + + widgets_up: widgets start from the top of the node + + flags object: + + collapsed: if it is collapsed supported callbacks: + onAdded: when added to graph @@ -2170,13 +2175,16 @@ LGraphNode.prototype.getInputOrProperty = function( name ) return this.properties ? this.properties[name] : null; for(var i = 0, l = this.inputs.length; i < l; ++i) - if(name == this.inputs[i].name) + { + var input_info = this.inputs[i]; + if(name == input_info.name && input_info.link != null) { - var link_id = this.inputs[i].link; - var link = this.graph.links[ link_id ]; - return link ? link.data : null; + var link = this.graph.links[ input_info.link ]; + if(link) + return link.data; } - return this.properties[name]; + } + return this.properties[ name ]; } @@ -3987,7 +3995,7 @@ LGraphCanvas.prototype.processMouseDown = function(e) if(!this.connecting_node && !node.flags.collapsed && !this.live_mode) { //Search for corner for resize - if( !skip_action && node.flags.resizable !== false && isInsideRectangle( e.canvasX, e.canvasY, node.pos[0] + node.size[0] - 5, node.pos[1] + node.size[1] - 5 ,10,10 )) + if( !skip_action && node.resizable !== false && isInsideRectangle( e.canvasX, e.canvasY, node.pos[0] + node.size[0] - 5, node.pos[1] + node.size[1] - 5 ,10,10 )) { this.resizing_node = node; this.canvas.style.cursor = "se-resize"; @@ -5537,6 +5545,8 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) var shape = node._shape || LiteGraph.BOX_SHAPE; var size = temp_vec2; temp_vec2.set( node.size ); + var horizontal = node.horizontal || node.flags.horizontal; + if( node.flags.collapsed ) { ctx.font = this.inner_text_font; @@ -5546,7 +5556,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) size[1] = 0; } - if( node.flags.clip_area ) //Start clipping + if( node.clip_area ) //Start clipping { ctx.save(); ctx.beginPath(); @@ -5564,7 +5574,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) ctx.shadowColor = "transparent"; //connection slots - ctx.textAlign = node.flags.horizontal ? "center" : "left"; + ctx.textAlign = horizontal ? "center" : "left"; ctx.font = this.inner_text_font; var render_text = this.scale > 0.6; @@ -5599,8 +5609,12 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) ctx.beginPath(); - if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) { - ctx.rect((pos[0] - 6) + 0.5, (pos[1] - 5) + 0.5, 14, 10); + if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) + { + if (horizontal) + ctx.rect((pos[0] - 5) + 0.5, (pos[1] - 8) + 0.5, 10, 14); + 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); @@ -5619,7 +5633,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(text) { ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR; - if( node.flags.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); @@ -5631,7 +5645,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(this.connecting_node) ctx.globalAlpha = 0.4 * editor_alpha; - ctx.textAlign = node.flags.horizontal ? "center" : "right"; + ctx.textAlign = horizontal ? "center" : "right"; ctx.strokeStyle = "black"; if(node.outputs) for(var i = 0; i < node.outputs.length; i++) @@ -5648,8 +5662,12 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) ctx.beginPath(); //ctx.rect( node.size[0] - 14,i*14,10,10); - if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) { - ctx.rect((pos[0] - 6) + 0.5,(pos[1] - 5) + 0.5,14,10); + if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) + { + if( horizontal ) + ctx.rect((pos[0] - 5) + 0.5,(pos[1] - 8) + 0.5,10,14); + 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); @@ -5674,7 +5692,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(text) { ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR; - if( node.flags.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); @@ -5687,7 +5705,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(node.widgets) { - if( node.flags.horizontal || node.flags.widgets_up ) + if( horizontal || node.widgets_up ) max_y = 2; this.drawNodeWidgets( node, max_y, ctx, (this.node_widget && this.node_widget[0] == node) ? this.node_widget[1] : null ); } @@ -5728,7 +5746,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) { var x = 0; var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center - if( node.flags.horizontal ) + if( horizontal ) { x = node._collapsed_width * 0.5; y = -LiteGraph.NODE_TITLE_HEIGHT; @@ -5752,7 +5770,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) { var x = node._collapsed_width; var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center - if( node.flags.horizontal ) + if( horizontal ) { x = node._collapsed_width * 0.5; y = 0; @@ -5775,7 +5793,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) } } - if(node.flags.clip_area) + if(node.clip_area) ctx.restore(); ctx.globalAlpha = 1.0; @@ -5871,30 +5889,33 @@ LGraphCanvas.prototype.drawNodeShape = function( node, ctx, size, fgcolor, bgcol } //title box - if (shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CIRCLE_SHAPE || shape == LiteGraph.CARD_SHAPE) + if(node.flags.render_box !== false) { - if( this.scale > 0.5 ) + if (shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CIRCLE_SHAPE || shape == LiteGraph.CARD_SHAPE) { - ctx.fillStyle = "black"; + if( this.scale > 0.5 ) + { + ctx.fillStyle = "black"; + ctx.beginPath(); + ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.5,0,Math.PI*2); + ctx.fill(); + } + + ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; ctx.beginPath(); - ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.5,0,Math.PI*2); + ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.4,0,Math.PI*2); ctx.fill(); } - - ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; - ctx.beginPath(); - ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.4,0,Math.PI*2); - ctx.fill(); - } - else - { - if( this.scale > 0.5 ) + else { - ctx.fillStyle = "black"; - ctx.fillRect(4,-title_height + 4,title_height - 8,title_height - 8); + if( this.scale > 0.5 ) + { + ctx.fillStyle = "black"; + ctx.fillRect(4,-title_height + 4,title_height - 8,title_height - 8); + } + ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; + ctx.fillRect(5,-title_height + 5,title_height - 10,title_height - 10); } - ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; - ctx.fillRect(5,-title_height + 5,title_height - 10,title_height - 10); } ctx.globalAlpha = old_alpha; @@ -6343,6 +6364,7 @@ LGraphCanvas.prototype.drawNodeWidgets = function( node, posY, ctx, active_widge ctx.fillText( w.value, width - 40, y + H*0.7 ); } break; + case "string": case "text": ctx.textAlign = "left"; ctx.strokeStyle = "#AAA"; @@ -6465,6 +6487,7 @@ LGraphCanvas.prototype.processNodeWidgets = function( node, pos, event, active_w setTimeout( function(){ w.callback( w.value, that, node, pos ); }, 20 ); } break; + case "string": case "text": if( event.type == "mousedown" ) this.prompt( "Value", w.value, (function(v){ this.value = v; if(w.callback) w.callback(v, that, node ); }).bind(w), event ); @@ -8646,36 +8669,55 @@ LiteGraph.registerNodeType("graph/output", GlobalOutput); //Constant -function Constant() +function ConstantNumber() { this.addOutput("value","number"); this.addProperty( "value", 1.0 ); - this.editable = { property:"value", type:"number" }; } -Constant.title = "Const"; -Constant.desc = "Constant value"; +ConstantNumber.title = "Const Number"; +ConstantNumber.desc = "Constant number"; - -Constant.prototype.setValue = function(v) -{ - if( typeof(v) == "string") v = parseFloat(v); - this.properties["value"] = v; - this.setDirtyCanvas(true); -}; - -Constant.prototype.onExecute = function() +ConstantNumber.prototype.onExecute = function() { this.setOutputData(0, parseFloat( this.properties["value"] ) ); } -Constant.prototype.onDrawBackground = function(ctx) +ConstantNumber.prototype.onDrawBackground = function(ctx) { //show the current value this.outputs[0].label = this.properties["value"].toFixed(3); } -LiteGraph.registerNodeType("basic/const", Constant); +LiteGraph.registerNodeType("basic/const", ConstantNumber); + +function ConstantString() +{ + this.addOutput("","string"); + this.addProperty( "value", "" ); + this.widget = this.addWidget("text","value","", this.setValue.bind(this) ); + this.widgets_up = true; +} + +ConstantString.title = "Const String"; +ConstantString.desc = "Constant string"; + +ConstantString.prototype.setValue = function(v) +{ + this.properties.value = v; +} + +ConstantString.prototype.onPropertyChanged = function(name,value) +{ + this.widget.value = value; +} + +ConstantString.prototype.onExecute = function() +{ + this.setOutputData(0, this.properties["value"] ); +} + +LiteGraph.registerNodeType("basic/string", ConstantString ); //Watch a value in the editor @@ -8859,6 +8901,39 @@ LogEvent.prototype.onAction = function( action, param ) LiteGraph.registerNodeType("events/log", LogEvent ); +//Sequencer for events +function Sequencer() +{ + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.size = [120,30]; + this.flags = { horizontal: true, render_box: false }; +} + +Sequencer.title = "Sequencer"; +Sequencer.desc = "Trigger events when an event arrives"; + +Sequencer.prototype.getTitle = function() { return ""; } + +Sequencer.prototype.onAction = function( action, param ) +{ + if(this.outputs) + for(var i = 0; i < this.outputs.length; ++i) + this.triggerSlot( i, param ); +} + +LiteGraph.registerNodeType("events/sequencer", Sequencer ); + //Filter events function FilterEvent() { @@ -8898,6 +8973,52 @@ FilterEvent.prototype.onAction = function( action, param ) LiteGraph.registerNodeType("events/filter", FilterEvent ); + +//Show value inside the debug console +function EventCounter() +{ + this.addInput("inc", LiteGraph.ACTION); + this.addInput("dec", LiteGraph.ACTION); + this.addInput("reset", LiteGraph.ACTION); + this.addOutput("change", LiteGraph.EVENT); + this.addOutput("num", "number"); + this.num = 0; +} + +EventCounter.title = "Counter"; +EventCounter.desc = "Counts events"; + +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); +} + +EventCounter.prototype.onDrawBackground = function(ctx) +{ + if(this.flags.collapsed) + return; + ctx.fillStyle = "#AAA"; + ctx.font = "20px Arial"; + ctx.textAlign = "center"; + ctx.fillText( this.num, this.size[0] * 0.5, this.size[1] * 0.5 ); +} + + +EventCounter.prototype.onExecute = function() +{ + this.setOutputData(1,this.num); +} + +LiteGraph.registerNodeType("events/counter", EventCounter ); + //Show value inside the debug console function DelayEvent() { @@ -8981,15 +9102,19 @@ TimerEvent.prototype.onDrawBackground = function() TimerEvent.prototype.onExecute = function() { var dt = this.graph.elapsed_time * 1000; //in ms + + var trigger = this.time == 0; + this.time += dt; this.last_interval = Math.max(1, this.getInputOrProperty("interval") | 0); - if( this.time < this.last_interval || isNaN(this.last_interval) ) + if( !trigger && ( this.time < this.last_interval || isNaN(this.last_interval)) ) { 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 ); @@ -10027,6 +10152,23 @@ Bypass.prototype.onExecute = function() LiteGraph.registerNodeType("math/bypass", Bypass ); +function ToNumber() +{ + this.addInput("in"); + this.addOutput("out"); +} + +ToNumber.title = "to Number"; +ToNumber.desc = "Cast to number"; + +ToNumber.prototype.onExecute = function() +{ + var v = this.getInputData(0); + this.setOutputData(0, Number(v) ); +} + +LiteGraph.registerNodeType("math/to_number", ToNumber ); + function MathRange() { @@ -11054,41 +11196,94 @@ var LiteGraph = global.LiteGraph; function Selector() { - this.addInput("sel","boolean"); - this.addOutput("value","number"); - this.properties = { A:0, B:1 }; - this.size = [60,20]; + this.addInput("sel","number"); + this.addInput("A"); + this.addInput("B"); + this.addInput("C"); + this.addInput("D"); + this.addOutput("out"); + + this.selected = 0; } Selector.title = "Selector"; -Selector.desc = "outputs A if selector is true, B if selector is false"; +Selector.desc = "selects an output"; + +Selector.prototype.onDrawBackground = function(ctx) +{ + if(this.flags.collapsed) + return; + ctx.fillStyle = "#AFB"; + var y = (this.selected + 1) * LiteGraph.NODE_SLOT_HEIGHT + 2; + ctx.beginPath(); + ctx.moveTo(30, y); + ctx.lineTo(30, y+LiteGraph.NODE_SLOT_HEIGHT); + ctx.lineTo(24, y+LiteGraph.NODE_SLOT_HEIGHT*0.5); + ctx.fill(); +} Selector.prototype.onExecute = function() { - var cond = this.getInputData(0); - if(cond === undefined) - return; - - for(var i = 1; i < this.inputs.length; i++) - { - var input = this.inputs[i]; - var v = this.getInputData(i); - if(v === undefined) - continue; - this.properties[input.name] = v; - } - - var A = this.properties.A; - var B = this.properties.B; - this.setOutputData(0, cond ? A : B ); + var sel = this.getInputData(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 ); } Selector.prototype.onGetInputs = function() { - return [["A",0],["B",0]]; + return [["E",0],["F",0],["G",0],["H",0]]; } LiteGraph.registerNodeType("logic/selector", Selector); + + +function Sequence() +{ + this.properties = { + sequence: "A,B,C" + }; + this.addInput("index","number"); + this.addInput("seq"); + this.addOutput("out"); + + this.index = 0; + this.values = this.properties.sequence.split(","); +} + +Sequence.title = "Sequence"; +Sequence.desc = "select one element from a sequence from a string"; + +Sequence.prototype.onPropertyChanged = function(name,value) +{ + if(name == "sequence") + { + this.values = value.split(","); + } +} + +Sequence.prototype.onExecute = function() +{ + var seq = this.getInputData(1); + if(seq && seq != this.current_sequence) + { + this.values = seq.split(","); + this.current_sequence = seq; + } + var index = this.getInputData(0); + if(index == null) + index = 0; + this.index = index = Math.round(index) % this.values.length; + + this.setOutputData( 0, this.values[ index ] ); +} + + +LiteGraph.registerNodeType("logic/sequence", Sequence ); + })(this); (function(global){ var LiteGraph = global.LiteGraph; @@ -11190,6 +11385,8 @@ GraphicsImage.prototype.onAdded = function() GraphicsImage.prototype.onDrawBackground = function(ctx) { + 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]); } @@ -11336,7 +11533,7 @@ LiteGraph.registerNodeType("color/palette", ColorPalette ); function ImageFrame() { - this.addInput("","image"); + this.addInput("","image,canvas"); this.size = [200,200]; } @@ -11347,7 +11544,7 @@ ImageFrame.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"vie ImageFrame.prototype.onDrawBackground = function(ctx) { - if(this.frame) + if(this.frame && !this.flags.collapsed) ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]); } @@ -11390,86 +11587,6 @@ LiteGraph.registerNodeType("graphics/frame", ImageFrame ); -/* -LiteGraph.registerNodeType("visualization/graph", { - desc: "Shows a graph of the inputs", - - inputs: [["",0],["",0],["",0],["",0]], - size: [200,200], - properties: {min:-1,max:1,bgColor:"#000"}, - onDrawBackground: function(ctx) - { - var colors = ["#FFF","#FAA","#AFA","#AAF"]; - - if(this.properties.bgColor != null && this.properties.bgColor != "") - { - ctx.fillStyle="#000"; - ctx.fillRect(2,2,this.size[0] - 4, this.size[1]-4); - } - - if(this.data) - { - var min = this.properties["min"]; - var max = this.properties["max"]; - - for(var i in this.data) - { - var data = this.data[i]; - if(!data) continue; - - if(this.getInputInfo(i) == null) continue; - - ctx.strokeStyle = colors[i]; - ctx.beginPath(); - - var d = data.length / this.size[0]; - for(var j = 0; j < data.length; j += d) - { - var value = data[ Math.floor(j) ]; - value = (value - min) / (max - min); - if (value > 1.0) value = 1.0; - else if(value < 0) value = 0; - - if(j == 0) - ctx.moveTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); - else - ctx.lineTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); - } - - ctx.stroke(); - } - } - - //ctx.restore(); - }, - - onExecute: function() - { - if(!this.data) this.data = []; - - for(var i in this.inputs) - { - var value = this.getInputData(i); - - if(typeof(value) == "number") - { - value = value ? value : 0; - if(!this.data[i]) - this.data[i] = []; - this.data[i].push(value); - - if(this.data[i].length > (this.size[1] - 4)) - this.data[i] = this.data[i].slice(1,this.data[i].length); - } - else - this.data[i] = value; - } - - if(this.data.length) - this.setDirtyCanvas(true); - } - }); -*/ function ImageFade() { @@ -11601,6 +11718,105 @@ ImageCrop.prototype.onPropertyChanged = function(name,value) LiteGraph.registerNodeType("graphics/cropImage", ImageCrop ); +//CANVAS stuff + +function CanvasNode() +{ + this.addInput("clear", LiteGraph.ACTION ); + this.addOutput("","canvas"); + this.properties = {width:512,height:512,autoclear:true}; + + this.canvas = document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); +} + +CanvasNode.title = "Canvas"; +CanvasNode.desc = "Canvas to render stuff"; + +CanvasNode.prototype.onExecute = function() +{ + 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(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") + this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height); +} + +LiteGraph.registerNodeType("graphics/canvas", CanvasNode ); + +function DrawImageNode() +{ + this.addInput("canvas", "canvas" ); + this.addInput("img", "image,canvas" ); + this.addInput("x", "number" ); + this.addInput("y", "number" ); + this.properties = {x:0,y:0,opacity:1}; +} + +DrawImageNode.title = "DrawImage"; +DrawImageNode.desc = "Draws image into a canvas"; + +DrawImageNode.prototype.onExecute = function() +{ + var canvas = this.getInputData(0); + if(!canvas) + return; + + var img = this.getInputOrProperty("img"); + if(!img) + return; + + var x = this.getInputOrProperty("x"); + var y = this.getInputOrProperty("y"); + var ctx = canvas.getContext("2d"); + ctx.drawImage( img, x, y ); +} + +LiteGraph.registerNodeType("graphics/drawImage", DrawImageNode ); + + +function DrawRectangleNode() +{ + this.addInput("canvas", "canvas" ); + this.addInput("x", "number" ); + this.addInput("y", "number" ); + this.addInput("w", "number" ); + this.addInput("h", "number" ); + this.properties = { x:0,y:0,w:10,h:10,color:"white",opacity:1 }; +} + +DrawRectangleNode.title = "DrawRectangle"; +DrawRectangleNode.desc = "Draws rectangle in canvas"; + +DrawRectangleNode.prototype.onExecute = function() +{ + var canvas = this.getInputData(0); + if(!canvas) + return; + + var x = this.getInputOrProperty("x"); + var y = this.getInputOrProperty("y"); + var w = this.getInputOrProperty("w"); + var h = this.getInputOrProperty("h"); + var ctx = canvas.getContext("2d"); + ctx.fillRect( x, y, w, h ); +} + +LiteGraph.registerNodeType("graphics/drawRectangle", DrawRectangleNode ); + + function ImageVideo() { @@ -16011,16 +16227,17 @@ function MIDIEvent( data ) { this.channel = 0; this.cmd = 0; + this.data = new Uint32Array(3); if(data) this.setup(data) - else - this.data = [0,0,0]; } +LiteGraph.MIDIEvent = MIDIEvent; + MIDIEvent.prototype.setup = function( raw_data ) { - this.data = raw_data; + this.data.set(raw_data); var midiStatus = raw_data[0]; this.status = midiStatus; @@ -16055,6 +16272,32 @@ Object.defineProperty( MIDIEvent.prototype, "velocity", { }); MIDIEvent.notes = ["A","A#","B","C","C#","D","D#","E","F","F#","G","G#"]; +MIDIEvent.note_to_index = {"A":0,"A#":1,"B":2,"C":3,"C#":4,"D":5,"D#":6,"E":7,"F":8,"F#":9,"G":10,"G#":11}; + +Object.defineProperty( MIDIEvent.prototype, "note", { + get: function() { + if(this.cmd != MIDIEvent.NOTEON) + return -1; + return MIDIEvent.toNoteString( this.data[1], true ); + }, + set: function(v) { + throw("notes cannot be assigned this way, must modify the data[1]"); + }, + enumerable: true +}); + +Object.defineProperty( MIDIEvent.prototype, "octave", { + get: function() { + if(this.cmd != MIDIEvent.NOTEON) + return -1; + var octave = this.data[1] - 24; + return Math.floor(octave / 12 + 1); + }, + set: function(v) { + throw("octave cannot be assigned this way, must modify the data[1]"); + }, + enumerable: true +}); //returns HZs MIDIEvent.prototype.getPitch = function() @@ -16126,14 +16369,39 @@ MIDIEvent.computeCommandFromString = function( str ) } } -MIDIEvent.toNoteString = function(d) +//transform from a pitch number to string like "C4" +MIDIEvent.toNoteString = function( d, skip_octave ) { + d = Math.round(d); //in case it has decimals var note = d - 21; - var octave = d - 24; + var octave = Math.floor((d - 24) / 12 + 1); note = note % 12; if(note < 0) note = 12 + note; - return MIDIEvent.notes[ note ] + Math.floor(octave / 12 + 1); + return MIDIEvent.notes[ note ] + (skip_octave ? "" : octave); +} + +MIDIEvent.NoteStringToPitch = function(str) +{ + str = str.toUpperCase(); + var note = str[0]; + var octave = 4; + + if(str[1] == "#") + { + note += "#"; + if( str.length > 2 ) + octave = Number( str[2] ); + } + else + { + if( str.length > 1 ) + octave = Number( str[1] ); + } + var pitch = MIDIEvent.note_to_index[note]; + if(pitch == null) + return null; + return ((octave - 1) * 12) + pitch + 21; } MIDIEvent.prototype.toString = function() @@ -16487,7 +16755,7 @@ LGMIDIOut.prototype.getPropertyInfo = function(name) LGMIDIOut.prototype.onAction = function(event, midi_event ) { - console.log(midi_event); + //console.log(midi_event); if(!this._midi) return; if(event == "send") @@ -16586,7 +16854,7 @@ function LGMIDIEvent() { this.properties = { channel: 0, - cmd: "CC", + cmd: 144, //0x90 value1: 1, value2: 1 }; @@ -16594,6 +16862,8 @@ function LGMIDIEvent() this.addInput( "send", LiteGraph.EVENT ); this.addInput( "assign", LiteGraph.EVENT ); this.addOutput( "on_midi", LiteGraph.EVENT ); + + this.midi_event = new MIDIEvent(); } LGMIDIEvent.title = "MIDIEvent"; @@ -16611,7 +16881,7 @@ LGMIDIEvent.prototype.onAction = function( event, midi_event ) } //send - var midi_event = new MIDIEvent(); + var midi_event = this.midi_event; midi_event.channel = this.properties.channel; if(this.properties.cmd && this.properties.cmd.constructor === String) midi_event.setCommandFromString( this.properties.cmd ); @@ -16620,6 +16890,7 @@ LGMIDIEvent.prototype.onAction = function( event, midi_event ) 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); + this.trigger("on_midi",midi_event); } @@ -16627,6 +16898,28 @@ LGMIDIEvent.prototype.onExecute = function() { var props = this.properties; + if(this.inputs) + { + for(var i = 0; i < this.inputs.length; ++i) + { + var input = this.inputs[i]; + if(input.link == -1) + continue; + switch (input.name) + { + case "note": + var v = this.getInputData(i); + if(v != null) + { + if(v.constructor === String) + v = MIDIEvent.NoteStringToPitch(v); + this.properties.value1 = (v|0)%255; + } + break; + } + } + } + if(this.outputs) { for(var i = 0; i < this.outputs.length; ++i) @@ -16662,6 +16955,9 @@ LGMIDIEvent.prototype.onPropertyChanged = function(name,value) this.properties.cmd = MIDIEvent.computeCommandFromString( value ); } +LGMIDIEvent.prototype.onGetInputs = function() { + return [ ["note","number"] ]; +} LGMIDIEvent.prototype.onGetOutputs = function() { return [ @@ -16706,6 +17002,232 @@ LGMIDICC.prototype.onExecute = function() LiteGraph.registerNodeType("midi/cc", LGMIDICC); +function LGMIDIGenerator() +{ + this.addInput( "generate", LiteGraph.ACTION ); + this.addInput( "scale", "string" ); + this.addInput( "octave", "number" ); + this.addOutput( "note", LiteGraph.EVENT ); + this.properties = { + notes: "A,A#,B,C,C#,D,D#,E,F,F#,G,G#", + octave: 2, + mode: "sequence" + }; + + this.notes_pitches = LGMIDIGenerator.processScale( this.properties.notes ); + this.sequence_index = 0; +} + +LGMIDIGenerator.title = "MIDI Generator"; +LGMIDIGenerator.desc = "Generates a random MIDI note"; + +LGMIDIGenerator.processScale = function(scale) +{ + var notes = scale.split(","); + for(var i = 0; i < notes.length; ++i) + notes[i] = MIDIEvent.note_to_index[ notes[i] ] || 0; + return notes; +} + +LGMIDIGenerator.prototype.onPropertyChanged = function(name,value) +{ + 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; + + var scale = this.getInputData(1); + if(scale) + this.notes_pitches = LGMIDIGenerator.processScale( scale ); +} + +LGMIDIGenerator.prototype.onAction = function( event, midi_event ) +{ + //var range = this.properties.max - this.properties.min; + //var pitch = this.properties.min + ((Math.random() * range)|0); + var pitch = 0; + var range = this.notes_pitches.length; + + if( this.properties.mode == "sequence" ) + { + var index = this.sequence_index = (this.sequence_index + 1) % range; + pitch = this.notes_pitches[ index ] + ( (this.properties.octave-1) * 12) + 33; + } + else if( this.properties.mode == "random" ) + { + var index = Math.floor(Math.random()*range); + pitch = this.notes_pitches[ index ] + ( (this.properties.octave-1) * 12) + 33; + } + var note = new MIDIEvent(); + note.setup([ MIDIEvent.NOTEON, pitch, 10 ]); + this.trigger("note", note); +} + + +LiteGraph.registerNodeType("midi/generator", LGMIDIGenerator); + +function LGMIDITranspose() +{ + this.properties = { + amount: 0 + }; + this.addInput( "in", LiteGraph.ACTION ); + this.addInput( "amount", "number" ); + this.addOutput( "out", LiteGraph.EVENT ); + + this.midi_event = new MIDIEvent(); +} + +LGMIDITranspose.title = "MIDI Transpose"; +LGMIDITranspose.desc = "Transpose a MIDI note"; + +LGMIDITranspose.prototype.onAction = function( event, midi_event ) +{ + this.midi_event.setup( midi_event.data ); + this.midi_event.data[1] = Math.round( this.midi_event.data[1] + this.properties.amount ); + this.trigger("out", this.midi_event ); +} + +LGMIDITranspose.prototype.onExecute = function() +{ + var amount = this.getInputData(1); + if(amount!= null) + this.properties.amount = amount; +} + +LiteGraph.registerNodeType("midi/transpose", LGMIDITranspose); + + +function LGMIDIQuantize() +{ + this.properties = { + scale: "A,A#,B,C,C#,D,D#,E,F,F#,G,G#" + }; + this.addInput( "note", LiteGraph.ACTION ); + this.addInput( "scale", "string" ); + this.addOutput( "out", LiteGraph.EVENT ); + + this.valid_notes = new Array(12); + this.offset_notes = new Array(12); + this.processScale( this.properties.scale ); + this.midi_event = new MIDIEvent(); +} + +LGMIDIQuantize.title = "MIDI Quantize Pitch"; +LGMIDIQuantize.desc = "Transpose a MIDI note tp fit an scale"; + +LGMIDIQuantize.prototype.onPropertyChanged = function(name,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) + 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; + continue; + } + for(var j = 1; j < 12; ++j) + { + if( this.valid_notes[ (i - j)%12 ] ) + { + this.offset_notes[i] = -j; + break; + } + if( this.valid_notes[ (i + j)%12 ] ) + { + this.offset_notes[i] = j; + break; + } + } + } +} + +LGMIDIQuantize.prototype.onAction = function( event, midi_event ) +{ + this.midi_event.setup( midi_event.data ); + var note = midi_event.note; + var index = MIDIEvent.note_to_index[ note ]; + var offset = this.offset_notes[index]; + this.midi_event.data[1] += offset; + this.trigger("out", this.midi_event ); +} + +LGMIDIQuantize.prototype.onExecute = function() +{ + var scale = this.getInputData(1); + if(scale != null && scale != this._current_scale ) + this.processScale( scale ); +} + +LiteGraph.registerNodeType("midi/quantize", LGMIDIQuantize); + + +function LGMIDIPlay() +{ + this.properties = { + volume: 0.5, + duration: 1 + }; + this.addInput( "note", LiteGraph.ACTION ); + this.addInput( "volume", "number" ); + this.addInput( "duration", "number" ); + this.addOutput( "note", LiteGraph.EVENT ); + + if(typeof(AudioSynth) == "undefined") + { + console.error("Audiosynth.js not included, LGMidiPlay requires that library"); + this.boxcolor = "red"; + } + else + { + var Synth = this.synth = new AudioSynth(); + this.instrument = Synth.createInstrument('piano'); + } +} + +LGMIDIPlay.title = "MIDI Play"; +LGMIDIPlay.desc = "Plays a MIDI note"; + +LGMIDIPlay.prototype.onAction = function( event, midi_event ) +{ + if(!this.instrument) + return; + var note = midi_event.note; //C# + if( !note || note == "undefined" || note.constructor !== String ) + return; + this.instrument.play( note, midi_event.octave, this.properties.duration, this.properties.volume ); + this.trigger("note", midi_event ); +} + +LGMIDIPlay.prototype.onExecute = function() +{ + var volume = this.getInputData(1); + if(volume != null) + this.properties.volume = volume; + + var duration = this.getInputData(2); + if(duration != null) + this.properties.duration = duration; +} + +LiteGraph.registerNodeType("midi/play", LGMIDIPlay); + + function now() { return window.performance.now() } diff --git a/build/litegraph.min.js b/build/litegraph.min.js index e888761bf..680e0109e 100755 --- a/build/litegraph.min.js +++ b/build/litegraph.min.js @@ -1,516 +1,533 @@ -(function(v){function h(a){k.debug&&console.log("Graph created");this.list_of_graphcanvas=null;this.clear();a&&this.configure(a)}function f(a){this._ctor(a)}function q(a){this._ctor(a)}function d(a,c,e){e=e||{};this.background_image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII="; +(function(v){function e(a){k.debug&&console.log("Graph created");this.list_of_graphcanvas=null;this.clear();a&&this.configure(a)}function h(a){this._ctor(a)}function p(a){this._ctor(a)}function d(a,b,c){c=c||{};this.background_image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII="; a&&a.constructor===String&&(a=document.querySelector(a));this.max_zoom=10;this.min_zoom=0.1;this.zoom_modify_alpha=!0;this.title_text_font="bold "+k.NODE_TEXT_SIZE+"px Arial";this.inner_text_font="normal "+k.NODE_SUBTEXT_SIZE+"px Arial";this.node_title_color=k.NODE_TITLE_COLOR;this.default_link_color=k.LINK_COLOR;this.default_connection_color={input_off:"#AAB",input_on:"#7F7",output_off:"#AAB",output_on:"#7F7"};this.highquality_render=!0;this.use_gradients=!1;this.editor_alpha=1;this.pause_rendering= !1;this.render_only_selected=this.clear_background=this.render_shadows=!0;this.live_mode=!1;this.allow_searchbox=this.allow_interaction=this.allow_dragnodes=this.allow_dragcanvas=this.show_info=!0;this.drag_mode=this.allow_reconnect_links=!1;this.filter=this.dragging_rectangle=null;this.always_render_background=!1;this.render_canvas_border=!0;this.render_connections_shadows=!1;this.render_connection_arrows=this.render_curved_connections=this.render_connections_border=!0;this.render_execution_order= -!1;this.canvas_mouse=[0,0];this.onDrawOverlay=this.onDrawForeground=this.onDrawBackground=this.onMouse=this.onSearchBoxSelection=this.onSearchBox=null;this.connections_width=3;this.round_radius=8;this.node_widget=this.current_node=null;this.last_mouse_position=[0,0];this.visible_area=new Float32Array(4);c&&c.attachCanvas(this);this.setCanvas(a);this.clear();e.skip_render||this.startRendering();this.autoresize=e.autoresize}function r(a,c){return Math.sqrt((c[0]-a[0])*(c[0]-a[0])+(c[1]-a[1])*(c[1]- -a[1]))}function t(a,c,e,s,g,b){return ea&&sc?!0:!1}function w(a,c){var e=a[0]+a[2],s=a[1]+a[3],g=c[1]+c[3];return a[0]>c[0]+c[2]||a[1]>g||ek.width-d.width-10&&(b=k.width-d.width-10);n>k.height-d.height-10&&(n=k.height-d.height-10)}g.style.left=b+"px";g.style.top=n+"px"}var k=v.LiteGraph={CANVAS_GRID_SIZE:10,NODE_TITLE_HEIGHT:20,NODE_SLOT_HEIGHT:15,NODE_WIDGET_HEIGHT:20,NODE_WIDTH:140,NODE_MIN_WIDTH:50,NODE_COLLAPSED_RADIUS:10,NODE_COLLAPSED_WIDTH:80, +!1;this.canvas_mouse=[0,0];this.onDrawOverlay=this.onDrawForeground=this.onDrawBackground=this.onMouse=this.onSearchBoxSelection=this.onSearchBox=null;this.connections_width=3;this.round_radius=8;this.node_widget=this.current_node=null;this.last_mouse_position=[0,0];this.visible_area=new Float32Array(4);b&&b.attachCanvas(this);this.setCanvas(a);this.clear();c.skip_render||this.startRendering();this.autoresize=c.autoresize}function s(a,b){return Math.sqrt((b[0]-a[0])*(b[0]-a[0])+(b[1]-a[1])*(b[1]- +a[1]))}function r(a,b,c,f,g,l){return ca&&fb?!0:!1}function t(a,b){var c=a[0]+a[2],f=a[1]+a[3],g=b[1]+b[3];return a[0]>b[0]+b[2]||a[1]>g||cd.width-k.width-10&&(l=d.width-k.width-10);q>d.height-k.height-10&&(q=d.height-k.height-10)}g.style.left=l+"px";g.style.top=q+"px"}var k=v.LiteGraph={CANVAS_GRID_SIZE:10,NODE_TITLE_HEIGHT:20,NODE_SLOT_HEIGHT:15,NODE_WIDGET_HEIGHT:20,NODE_WIDTH:140,NODE_MIN_WIDTH:50,NODE_COLLAPSED_RADIUS:10,NODE_COLLAPSED_WIDTH:80, NODE_TITLE_COLOR:"#999",NODE_TEXT_SIZE:14,NODE_TEXT_COLOR:"#AAA",NODE_SUBTEXT_SIZE:12,NODE_DEFAULT_COLOR:"#333",NODE_DEFAULT_BGCOLOR:"#444",NODE_DEFAULT_BOXCOLOR:"#666",NODE_DEFAULT_SHAPE:"box",DEFAULT_SHADOW_COLOR:"rgba(0,0,0,0.5)",DEFAULT_GROUP_FONT:24,LINK_COLOR:"#AAD",EVENT_LINK_COLOR:"#F85",CONNECTING_LINK_COLOR:"#AFA",MAX_NUMBER_OF_NODES:1E3,DEFAULT_POSITION:[100,100],VALID_SHAPES:["default","box","round","card"],BOX_SHAPE:1,ROUND_SHAPE:2,CIRCLE_SHAPE:3,CARD_SHAPE:4,ARROW_SHAPE:5,INPUT:1,OUTPUT:2, -EVENT:-1,ACTION:-1,ALWAYS:0,ON_EVENT:1,NEVER:2,ON_TRIGGER:3,UP:1,DOWN:2,LEFT:3,RIGHT:4,CENTER:5,NORMAL_TITLE:0,NO_TITLE:1,TRANSPARENT_TITLE:2,AUTOHIDE_TITLE:3,proxy:null,node_images_path:"",debug:!1,throw_errors:!0,allow_scripts:!1,registered_node_types:{},node_types_by_file_extension:{},Nodes:{},searchbox_extras:{},registerNodeType:function(a,c){if(!c.prototype)throw"Cannot register a simple object, it must be a class with a prototype";c.type=a;k.debug&&console.log("Node registered: "+a);a.split("/"); -var e=c.name,s=a.lastIndexOf("/");c.category=a.substr(0,s);c.title||(c.title=e);if(c.prototype)for(var g in f.prototype)c.prototype[g]||(c.prototype[g]=f.prototype[g]);Object.defineProperty(c.prototype,"shape",{set:function(a){switch(a){case "default":delete this._shape;break;case "box":this._shape=k.BOX_SHAPE;break;case "round":this._shape=k.ROUND_SHAPE;break;case "circle":this._shape=k.CIRCLE_SHAPE;break;case "card":this._shape=k.CARD_SHAPE;break;default:this._shape=a}},get:function(a){return this._shape}, -enumerable:!0});this.registered_node_types[a]=c;c.constructor.name&&(this.Nodes[e]=c);c.prototype.onPropertyChange&&console.warn("LiteGraph node class "+a+" has onPropertyChange method, it must be called onPropertyChanged with d at the end");if(c.supported_extensions)for(g in c.supported_extensions)this.node_types_by_file_extension[c.supported_extensions[g].toLowerCase()]=c},wrapFunctionAsNode:function(a,c,e,s){for(var g=Array(c.length),b="",n=k.getParameterNames(c),d=0;dn&&(n=g.size[0]),d+=g.size[1]+a;c+=n+a}this.setDirtyCanvas(!0,!0)};h.prototype.getTime=function(){return this.globaltime};h.prototype.getFixedTime=function(){return this.fixedtime};h.prototype.getElapsedTime=function(){return this.elapsed_time};h.prototype.sendEventToAllNodes=function(a,c,e){e=e||k.ALWAYS;var b=this._nodes_in_order?this._nodes_in_order:this._nodes;if(b)for(var g=0,l=b.length;g=k.MAX_NUMBER_OF_NODES)throw"LiteGraph: max number of nodes in a graph reached";null==a.id||-1==a.id?a.id=++this.last_node_id:this.last_node_ida.length|| -(this._pos[0]=a[0],this._pos[1]=a[1])},get:function(){return this._pos},enumerable:!0});this.id=-1;this.type=null;this.inputs=[];this.outputs=[];this.connections=[];this.properties={};this.properties_info=[];this.flags={}};f.prototype.configure=function(a){this.graph&&this.graph._version++;for(var c in a)if("console"!=c)if("properties"==c)for(var e in a.properties){if(this.properties[e]=a.properties[e],this.onPropertyChanged)this.onPropertyChanged(e,a.properties[e])}else null!=a[c]&&("object"==typeof a[c]? -this[c]&&this[c].configure?this[c].configure(a[c]):this[c]=k.cloneObject(a[c],this[c]):this[c]=a[c]);a.title||(this.title=this.constructor.title);if(this.onConnectionsChange){if(this.inputs)for(var b=0;b=this.outputs.length)){var e=this.outputs[a];if(e&&(e._data=c,this.outputs[a].links))for(e=0;e=this.inputs.length||null==this.inputs[a].link)){var e=this.graph.links[this.inputs[a].link];if(!e)return null;if(!c)return e.data;var b=this.graph.getNodeById(e.origin_id); -if(!b)return e.data;if(b.updateOutputData)b.updateOutputData(e.origin_slot);else if(b.onExecute)b.onExecute();return e.data}};f.prototype.getInputDataByName=function(a,c){var e=this.findInputSlot(a);return-1==e?null:this.getInputData(e,c)};f.prototype.isInputConnected=function(a){return this.inputs?a=this.inputs.length)return null;a=this.inputs[a];return a&&null!==a.link?(a=this.graph.links[a.link])?this.graph.getNodeById(a.origin_id):null:null};f.prototype.getInputOrProperty=function(a){if(!this.inputs||!this.inputs.length)return this.properties?this.properties[a]:null;for(var c=0,e=this.inputs.length;c=this.outputs.length? -null:this.outputs[a]._data};f.prototype.getOutputInfo=function(a){return this.outputs?a=this.outputs.length)return null;a=this.outputs[a];if(!a.links||0==a.links.length)return null;for(var c=[],e=0;ea&&this.pos[1]-g-ec)return!0;return!1};f.prototype.getSlotInPosition=function(a,c){var e=new Float32Array(2);if(this.inputs)for(var b=0,g=this.inputs.length;b=this.outputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),null;c&&c.constructor===Number&&(c=this.graph.getNodeById(c));if(!c)throw"target node is null";if(c==this)return null;if(e.constructor===String){if(e=c.findInputSlot(e),-1==e)return k.debug&&console.log("Connect: Error, no slot of name "+e),null}else{if(e=== -k.EVENT)return null;if(!c.inputs||e>=c.inputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),null}null!=c.inputs[e].link&&c.disconnectInput(e);var b=this.outputs[a];if(c.onConnectInput&&!1===c.onConnectInput(e,b.type,b))return null;var g=c.inputs[e],l=null;if(k.isValidConnection(b.type,g.type)){l={id:this.graph.last_link_id++,type:g.type,origin_id:this.id,origin_slot:a,target_id:c.id,target_slot:e};this.graph.links[l.id]=l;null==b.links&&(b.links=[]);b.links.push(l.id); -c.inputs[e].link=l.id;this.graph&&this.graph._version++;if(this.onConnectionsChange)this.onConnectionsChange(k.OUTPUT,a,!0,l,b);if(c.onConnectionsChange)c.onConnectionsChange(k.INPUT,e,!0,l,g);this.graph&&this.graph.onNodeConnectionChange&&(this.graph.onNodeConnectionChange(k.INPUT,c,e,this,a),this.graph.onNodeConnectionChange(k.OUTPUT,this,a,c,e))}this.setDirtyCanvas(!1,!0);this.graph.connectionChange(this,l);return l};f.prototype.disconnectOutput=function(a,c){if(a.constructor===String){if(a=this.findOutputSlot(a), --1==a)return k.debug&&console.log("Connect: Error, no slot of name "+a),!1}else if(!this.outputs||a>=this.outputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),!1;var e=this.outputs[a];if(!e||!e.links||0==e.links.length)return!1;if(c){c.constructor===Number&&(c=this.graph.getNodeById(c));if(!c)throw"Target Node not found";for(var b=0,g=e.links.length;b=this.inputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),!1;var c=this.inputs[a]; -if(!c)return!1;var e=this.inputs[a].link;this.inputs[a].link=null;var b=this.graph.links[e];if(b){var g=this.graph.getNodeById(b.origin_id);if(!g)return!1;var l=g.outputs[b.origin_slot];if(!l||!l.links||0==l.links.length)return!1;for(var n=0,d=l.links.length;nc&&this.inputs[c].pos)return e[0]=this.pos[0]+this.inputs[c].pos[0],e[1]=this.pos[1]+this.inputs[c].pos[1],e;if(!a&&b>c&&this.outputs[c].pos)return e[0]=this.pos[0]+this.outputs[c].pos[0],e[1]=this.pos[1]+this.outputs[c].pos[1],e;if(this.flags.horizontal)return e[0]=this.pos[0]+this.size[0]/b*(c+ -0.5),e[1]=a?this.pos[1]-k.NODE_TITLE_HEIGHT:this.pos[1]+this.size[1],e;e[0]=a?this.pos[0]:this.pos[0]+this.size[0]+1;e[1]=this.pos[1]+10+c*k.NODE_SLOT_HEIGHT+(this.constructor.slot_start_y||0);return e};f.prototype.alignToGrid=function(){this.pos[0]=k.CANVAS_GRID_SIZE*Math.round(this.pos[0]/k.CANVAS_GRID_SIZE);this.pos[1]=k.CANVAS_GRID_SIZE*Math.round(this.pos[1]/k.CANVAS_GRID_SIZE)};f.prototype.trace=function(a){this.console||(this.console=[]);this.console.push(a);this.console.length>f.MAX_CONSOLE&& -this.console.shift();this.graph.onNodeTrace(this,a)};f.prototype.setDirtyCanvas=function(a,c){this.graph&&this.graph.sendActionToCanvas("setDirty",[a,c])};f.prototype.loadImage=function(a){var c=new Image;c.src=k.node_images_path+a;c.ready=!1;var e=this;c.onload=function(){this.ready=!0;e.setDirtyCanvas(!0)};return c};f.prototype.captureInput=function(a){if(this.graph&&this.graph.list_of_graphcanvas)for(var c=this.graph.list_of_graphcanvas,e=0;eq&&(q=g.size[0]),d+=g.size[1]+a;b+=q+a}this.setDirtyCanvas(!0,!0)};e.prototype.getTime=function(){return this.globaltime};e.prototype.getFixedTime=function(){return this.fixedtime};e.prototype.getElapsedTime=function(){return this.elapsed_time};e.prototype.sendEventToAllNodes=function(a,b,c){c=c||k.ALWAYS;var f=this._nodes_in_order?this._nodes_in_order:this._nodes;if(f)for(var g=0,l=f.length;g=k.MAX_NUMBER_OF_NODES)throw"LiteGraph: max number of nodes in a graph reached";null==a.id||-1==a.id?a.id=++this.last_node_id:this.last_node_ida.length|| +(this._pos[0]=a[0],this._pos[1]=a[1])},get:function(){return this._pos},enumerable:!0});this.id=-1;this.type=null;this.inputs=[];this.outputs=[];this.connections=[];this.properties={};this.properties_info=[];this.flags={}};h.prototype.configure=function(a){this.graph&&this.graph._version++;for(var b in a)if("console"!=b)if("properties"==b)for(var c in a.properties){if(this.properties[c]=a.properties[c],this.onPropertyChanged)this.onPropertyChanged(c,a.properties[c])}else null!=a[b]&&("object"==typeof a[b]? +this[b]&&this[b].configure?this[b].configure(a[b]):this[b]=k.cloneObject(a[b],this[b]):this[b]=a[b]);a.title||(this.title=this.constructor.title);if(this.onConnectionsChange){if(this.inputs)for(var f=0;f=this.outputs.length)){var c=this.outputs[a];if(c&&(c._data=b,this.outputs[a].links))for(c=0;c=this.inputs.length||null==this.inputs[a].link)){var c=this.graph.links[this.inputs[a].link];if(!c)return null;if(!b)return c.data;var f=this.graph.getNodeById(c.origin_id); +if(!f)return c.data;if(f.updateOutputData)f.updateOutputData(c.origin_slot);else if(f.onExecute)f.onExecute();return c.data}};h.prototype.getInputDataByName=function(a,b){var c=this.findInputSlot(a);return-1==c?null:this.getInputData(c,b)};h.prototype.isInputConnected=function(a){return this.inputs?a=this.inputs.length)return null;a=this.inputs[a];return a&&null!==a.link?(a=this.graph.links[a.link])?this.graph.getNodeById(a.origin_id):null:null};h.prototype.getInputOrProperty=function(a){if(!this.inputs||!this.inputs.length)return this.properties?this.properties[a]:null;for(var b=0,c=this.inputs.length;b= +this.outputs.length?null:this.outputs[a]._data};h.prototype.getOutputInfo=function(a){return this.outputs?a=this.outputs.length)return null;a=this.outputs[a];if(!a.links||0==a.links.length)return null;for(var b=[],c=0;ca&&this.pos[1]-g-cb)return!0;return!1};h.prototype.getSlotInPosition=function(a,b){var c=new Float32Array(2);if(this.inputs)for(var f=0,g=this.inputs.length;f=this.outputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),null;b&&b.constructor===Number&&(b=this.graph.getNodeById(b));if(!b)throw"target node is null";if(b==this)return null;if(c.constructor===String){if(c=b.findInputSlot(c),-1==c)return k.debug&&console.log("Connect: Error, no slot of name "+c),null}else{if(c=== +k.EVENT)return null;if(!b.inputs||c>=b.inputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),null}null!=b.inputs[c].link&&b.disconnectInput(c);var f=this.outputs[a];if(b.onConnectInput&&!1===b.onConnectInput(c,f.type,f))return null;var g=b.inputs[c],l=null;if(k.isValidConnection(f.type,g.type)){l={id:this.graph.last_link_id++,type:g.type,origin_id:this.id,origin_slot:a,target_id:b.id,target_slot:c};this.graph.links[l.id]=l;null==f.links&&(f.links=[]);f.links.push(l.id); +b.inputs[c].link=l.id;this.graph&&this.graph._version++;if(this.onConnectionsChange)this.onConnectionsChange(k.OUTPUT,a,!0,l,f);if(b.onConnectionsChange)b.onConnectionsChange(k.INPUT,c,!0,l,g);this.graph&&this.graph.onNodeConnectionChange&&(this.graph.onNodeConnectionChange(k.INPUT,b,c,this,a),this.graph.onNodeConnectionChange(k.OUTPUT,this,a,b,c))}this.setDirtyCanvas(!1,!0);this.graph.connectionChange(this,l);return l};h.prototype.disconnectOutput=function(a,b){if(a.constructor===String){if(a=this.findOutputSlot(a), +-1==a)return k.debug&&console.log("Connect: Error, no slot of name "+a),!1}else if(!this.outputs||a>=this.outputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),!1;var c=this.outputs[a];if(!c||!c.links||0==c.links.length)return!1;if(b){b.constructor===Number&&(b=this.graph.getNodeById(b));if(!b)throw"Target Node not found";for(var f=0,g=c.links.length;f=this.inputs.length)return k.debug&&console.log("Connect: Error, slot number not found"),!1;var b=this.inputs[a]; +if(!b)return!1;var c=this.inputs[a].link;this.inputs[a].link=null;var f=this.graph.links[c];if(f){var g=this.graph.getNodeById(f.origin_id);if(!g)return!1;var l=g.outputs[f.origin_slot];if(!l||!l.links||0==l.links.length)return!1;for(var d=0,n=l.links.length;db&&this.inputs[b].pos)return c[0]=this.pos[0]+this.inputs[b].pos[0],c[1]=this.pos[1]+this.inputs[b].pos[1],c;if(!a&&f>b&&this.outputs[b].pos)return c[0]=this.pos[0]+this.outputs[b].pos[0],c[1]=this.pos[1]+this.outputs[b].pos[1],c;if(this.flags.horizontal)return c[0]=this.pos[0]+this.size[0]/f*(b+ +0.5),c[1]=a?this.pos[1]-k.NODE_TITLE_HEIGHT:this.pos[1]+this.size[1],c;c[0]=a?this.pos[0]:this.pos[0]+this.size[0]+1;c[1]=this.pos[1]+10+b*k.NODE_SLOT_HEIGHT+(this.constructor.slot_start_y||0);return c};h.prototype.alignToGrid=function(){this.pos[0]=k.CANVAS_GRID_SIZE*Math.round(this.pos[0]/k.CANVAS_GRID_SIZE);this.pos[1]=k.CANVAS_GRID_SIZE*Math.round(this.pos[1]/k.CANVAS_GRID_SIZE)};h.prototype.trace=function(a){this.console||(this.console=[]);this.console.push(a);this.console.length>h.MAX_CONSOLE&& +this.console.shift();this.graph.onNodeTrace(this,a)};h.prototype.setDirtyCanvas=function(a,b){this.graph&&this.graph.sendActionToCanvas("setDirty",[a,b])};h.prototype.loadImage=function(a){var b=new Image;b.src=k.node_images_path+a;b.ready=!1;var c=this;b.onload=function(){this.ready=!0;c.setDirtyCanvas(!0)};return b};h.prototype.captureInput=function(a){if(this.graph&&this.graph.list_of_graphcanvas)for(var b=this.graph.list_of_graphcanvas,c=0;ca.length||(this._pos[0]=a[0],this._pos[1]=a[1])},get:function(){return this._pos},enumerable:!0});Object.defineProperty(this,"size",{set:function(a){!a||2>a.length||(this._size[0]=Math.max(140, -a[0]),this._size[1]=Math.max(80,a[1]))},get:function(){return this._size},enumerable:!0})};q.prototype.configure=function(a){this.title=a.title;this._bounding.set(a.bounding);this.color=a.color;this.font=a.font};q.prototype.serialize=function(){var a=this._bounding;return{title:this.title,bounding:[Math.round(a[0]),Math.round(a[1]),Math.round(a[2]),Math.round(a[3])],color:this.color,font:this.font}};q.prototype.move=function(a,c,e){this._pos[0]+=a;this._pos[1]+=c;if(!e)for(e=0;e element, you passed a "+a.localName;throw"This browser doesnt support Canvas";}null==(this.ctx=a.getContext("2d"))&&(a.webgl_enabled||console.warn("This canvas seems to be WebGL, enabling WebGL renderer"),this.enableWebGL());this._mousemove_callback=this.processMouseMove.bind(this);this._mouseup_callback=this.processMouseUp.bind(this); -c||this.bindEvents()}};d.prototype._doNothing=function(a){a.preventDefault();return!1};d.prototype._doReturnTrue=function(a){a.preventDefault();return!0};d.prototype.bindEvents=function(){if(this._events_binded)console.warn("LGraphCanvas: events already binded");else{var a=this.canvas,c=this.getCanvasWindow().document;this._mousedown_callback=this.processMouseDown.bind(this);this._mousewheel_callback=this.processMouseWheel.bind(this);a.addEventListener("mousedown",this._mousedown_callback,!0);a.addEventListener("mousemove", +b||this.bindEvents()}};d.prototype._doNothing=function(a){a.preventDefault();return!1};d.prototype._doReturnTrue=function(a){a.preventDefault();return!0};d.prototype.bindEvents=function(){if(this._events_binded)console.warn("LGraphCanvas: events already binded");else{var a=this.canvas,b=this.getCanvasWindow().document;this._mousedown_callback=this.processMouseDown.bind(this);this._mousewheel_callback=this.processMouseWheel.bind(this);a.addEventListener("mousedown",this._mousedown_callback,!0);a.addEventListener("mousemove", this._mousemove_callback);a.addEventListener("mousewheel",this._mousewheel_callback,!1);a.addEventListener("contextmenu",this._doNothing);a.addEventListener("DOMMouseScroll",this._mousewheel_callback,!1);a.addEventListener("touchstart",this.touchHandler,!0);a.addEventListener("touchmove",this.touchHandler,!0);a.addEventListener("touchend",this.touchHandler,!0);a.addEventListener("touchcancel",this.touchHandler,!0);this._key_callback=this.processKey.bind(this);a.addEventListener("keydown",this._key_callback, -!0);c.addEventListener("keyup",this._key_callback,!0);this._ondrop_callback=this.processDrop.bind(this);a.addEventListener("dragover",this._doNothing,!1);a.addEventListener("dragend",this._doNothing,!1);a.addEventListener("drop",this._ondrop_callback,!1);a.addEventListener("dragenter",this._doReturnTrue,!1);this._events_binded=!0}};d.prototype.unbindEvents=function(){if(this._events_binded){var a=this.getCanvasWindow().document;this.canvas.removeEventListener("mousedown",this._mousedown_callback); +!0);b.addEventListener("keyup",this._key_callback,!0);this._ondrop_callback=this.processDrop.bind(this);a.addEventListener("dragover",this._doNothing,!1);a.addEventListener("dragend",this._doNothing,!1);a.addEventListener("drop",this._ondrop_callback,!1);a.addEventListener("dragenter",this._doReturnTrue,!1);this._events_binded=!0}};d.prototype.unbindEvents=function(){if(this._events_binded){var a=this.getCanvasWindow().document;this.canvas.removeEventListener("mousedown",this._mousedown_callback); this.canvas.removeEventListener("mousewheel",this._mousewheel_callback);this.canvas.removeEventListener("DOMMouseScroll",this._mousewheel_callback);this.canvas.removeEventListener("keydown",this._key_callback);a.removeEventListener("keyup",this._key_callback);this.canvas.removeEventListener("contextmenu",this._doNothing);this.canvas.removeEventListener("drop",this._ondrop_callback);this.canvas.removeEventListener("dragenter",this._doReturnTrue);this.canvas.removeEventListener("touchstart",this.touchHandler); -this.canvas.removeEventListener("touchmove",this.touchHandler);this.canvas.removeEventListener("touchend",this.touchHandler);this.canvas.removeEventListener("touchcancel",this.touchHandler);this._ondrop_callback=this._key_callback=this._mousewheel_callback=this._mousedown_callback=null;this._events_binded=!1}else console.warn("LGraphCanvas: no events binded")};d.getFileExtension=function(a){var c=a.indexOf("?");-1!=c&&(a=a.substr(0,c));c=a.lastIndexOf(".");return-1==c?"":a.substr(c+1).toLowerCase()}; -d.prototype.enableWebGL=function(){if(void 0===typeof GL)throw"litegl.js must be included to use a WebGL canvas";if(void 0===typeof enableWebGLCanvas)throw"webglCanvas.js must be included to use this feature";this.gl=this.ctx=enableWebGLCanvas(this.canvas);this.ctx.webgl=!0;this.bgcanvas=this.canvas;this.bgctx=this.gl;this.canvas.webgl_enabled=!0};d.prototype.setDirty=function(a,c){a&&(this.dirty_canvas=!0);c&&(this.dirty_bgcanvas=!0)};d.prototype.getCanvasWindow=function(){if(!this.canvas)return window; -var a=this.canvas.ownerDocument;return a.defaultView||a.parentWindow};d.prototype.startRendering=function(){function a(){this.pause_rendering||this.draw();var c=this.getCanvasWindow();this.is_rendering&&c.requestAnimationFrame(a.bind(this))}this.is_rendering||(this.is_rendering=!0,a.call(this))};d.prototype.stopRendering=function(){this.is_rendering=!1};d.prototype.processMouseDown=function(a){if(this.graph){this.adjustMouseEvent(a);var c=this.getCanvasWindow();d.active_canvas=this;this.canvas.removeEventListener("mousemove", -this._mousemove_callback);c.document.addEventListener("mousemove",this._mousemove_callback,!0);c.document.addEventListener("mouseup",this._mouseup_callback,!0);var e=this.graph.getNodeOnPos(a.canvasX,a.canvasY,this.visible_nodes,5),b=!1,g=300>k.getTime()-this.last_mouseclick;this.canvas_mouse[0]=a.canvasX;this.canvas_mouse[1]=a.canvasY;k.closeAllContextMenus(c);if(!this.onMouse||!0!=this.onMouse(a)){if(1==a.which){a.ctrlKey&&(this.dragging_rectangle=new Float32Array(4),this.dragging_rectangle[0]= -a.canvasX,this.dragging_rectangle[1]=a.canvasY,this.dragging_rectangle[2]=1,this.dragging_rectangle[3]=1,b=!0);var l=!1;if(e&&this.allow_interaction&&!b){this.live_mode||e.flags.pinned||this.bringToFront(e);if(!this.connecting_node&&!e.flags.collapsed&&!this.live_mode)if(!b&&!1!==e.flags.resizable&&t(a.canvasX,a.canvasY,e.pos[0]+e.size[0]-5,e.pos[1]+e.size[1]-5,10,10))this.resizing_node=e,this.canvas.style.cursor="se-resize",b=!0;else{if(e.outputs)for(var n=0,m=e.outputs.length;nr([a.canvasX,a.canvasY],[this.selected_group.pos[0]+this.selected_group.size[0],this.selected_group.pos[1]+this.selected_group.size[1]])*this.scale?this.selected_group_resizing=!0:this.selected_group.recomputeInsideNodes()),g&&this.showSearchBox(a),l=!0;!b&&l&&this.allow_dragcanvas&&(this.dragging_canvas=!0)}else 2!=a.which&& -3==a.which&&this.processContextMenu(e,a);this.last_mouse[0]=a.localX;this.last_mouse[1]=a.localY;this.last_mouseclick=k.getTime();this.last_mouse_dragging=!0;this.graph.change();(!c.document.activeElement||"input"!=c.document.activeElement.nodeName.toLowerCase()&&"textarea"!=c.document.activeElement.nodeName.toLowerCase())&&a.preventDefault();a.stopPropagation();if(this.onMouseDown)this.onMouseDown(a);return!1}}};d.prototype.processMouseMove=function(a){this.autoresize&&this.resize();if(this.graph){d.active_canvas= -this;this.adjustMouseEvent(a);var c=[a.localX,a.localY],e=[c[0]-this.last_mouse[0],c[1]-this.last_mouse[1]];this.last_mouse=c;this.canvas_mouse[0]=a.canvasX;this.canvas_mouse[1]=a.canvasY;a.dragging=this.last_mouse_dragging;this.node_widget&&(this.processNodeWidgets(this.node_widget[0],this.canvas_mouse,a,this.node_widget[1]),this.dirty_canvas=!0);if(this.dragging_rectangle)this.dragging_rectangle[2]=a.canvasX-this.dragging_rectangle[0],this.dragging_rectangle[3]=a.canvasY-this.dragging_rectangle[1], -this.dirty_canvas=!0;else if(this.selected_group)this.selected_group_resizing?this.selected_group.size=[a.canvasX-this.selected_group.pos[0],a.canvasY-this.selected_group.pos[1]]:(this.selected_group.move(e[0]/this.scale,e[1]/this.scale,a.ctrlKey),this.selected_group._nodes.length&&(this.dirty_canvas=!0)),this.dirty_bgcanvas=!0;else if(this.dragging_canvas)this.offset[0]+=e[0]/this.scale,this.offset[1]+=e[1]/this.scale,this.dirty_bgcanvas=this.dirty_canvas=!0;else if(this.allow_interaction){this.connecting_node&& -(this.dirty_canvas=!0);for(var b=this.graph.getNodeOnPos(a.canvasX,a.canvasY,this.visible_nodes),c=0,g=this.graph._nodes.length;cthis.dragging_rectangle[3]?this.dragging_rectangle[1]-g:this.dragging_rectangle[1];this.dragging_rectangle[0]=0>this.dragging_rectangle[2]?this.dragging_rectangle[0]-b:this.dragging_rectangle[0];this.dragging_rectangle[1]=l;this.dragging_rectangle[2]=b;this.dragging_rectangle[3]=g;g=[];for(l=0;la.click_time&&this.deselectAllNodes();this.dirty_canvas=!0;this.dragging_canvas=!1;if(this.node_over&&this.node_over.onMouseUp)this.node_over.onMouseUp(a,[a.canvasX-this.node_over.pos[0],a.canvasY-this.node_over.pos[1]],this);if(this.node_capturing_input&&this.node_capturing_input.onMouseUp)this.node_capturing_input.onMouseUp(a,[a.canvasX-this.node_capturing_input.pos[0],a.canvasY-this.node_capturing_input.pos[1]])}}else 2== -a.which?(this.dirty_canvas=!0,this.dragging_canvas=!1):3==a.which&&(this.dirty_canvas=!0,this.dragging_canvas=!1);this.graph.change();a.stopPropagation();a.preventDefault();return!1}};d.prototype.processMouseWheel=function(a){if(this.graph&&this.allow_dragcanvas){var c=null!=a.wheelDeltaY?a.wheelDeltaY:-60*a.detail;this.adjustMouseEvent(a);var e=this.scale;0c&&(e*=1/1.1);this.setZoom(e,[a.localX,a.localY]);this.graph.change();a.preventDefault();return!1}};d.prototype.isOverNodeBox=function(a, -c,e){var b=k.NODE_TITLE_HEIGHT;return t(c,e,a.pos[0]+2,a.pos[1]+2-b,b-4,b-4)?!0:!1};d.prototype.isOverNodeInput=function(a,c,e,b){if(a.inputs)for(var g=0,l=a.inputs.length;gthis.max_zoom?this.scale=this.max_zoom:this.scalee-this.graph._last_trigger_time)&&this.drawBackCanvas();(this.dirty_canvas||a)&&this.drawFrontCanvas();this.fps=this.render_time?1/this.render_time:0;this.frame+=1}};d.prototype.drawFrontCanvas=function(){this.dirty_canvas=!1;this.ctx||(this.ctx=this.bgcanvas.getContext("2d"));var a=this.ctx;if(a){a.start2D&&a.start2D();var c=this.canvas;a.restore();a.setTransform(1,0,0,1,0,0);this.dirty_area&& -(a.save(),a.beginPath(),a.rect(this.dirty_area[0],this.dirty_area[1],this.dirty_area[2],this.dirty_area[3]),a.clip());this.clear_background&&a.clearRect(0,0,c.width,c.height);this.bgcanvas==this.canvas?this.drawBackCanvas():a.drawImage(this.bgcanvas,0,0);if(this.onRender)this.onRender(c,a);this.show_info&&this.renderInfo(a);if(this.graph){a.save();a.scale(this.scale,this.scale);a.translate(this.offset[0],this.offset[1]);for(var c=this.computeVisibleNodes(null,this.visible_nodes),e=0;ek.getTime()-this.last_mouseclick;this.canvas_mouse[0]=a.canvasX;this.canvas_mouse[1]=a.canvasY;k.closeAllContextMenus(b);if(!this.onMouse||!0!=this.onMouse(a)){if(1==a.which){a.ctrlKey&&(this.dragging_rectangle=new Float32Array(4),this.dragging_rectangle[0]= +a.canvasX,this.dragging_rectangle[1]=a.canvasY,this.dragging_rectangle[2]=1,this.dragging_rectangle[3]=1,f=!0);var l=!1;if(c&&this.allow_interaction&&!f){this.live_mode||c.flags.pinned||this.bringToFront(c);if(!this.connecting_node&&!c.flags.collapsed&&!this.live_mode)if(!f&&!1!==c.resizable&&r(a.canvasX,a.canvasY,c.pos[0]+c.size[0]-5,c.pos[1]+c.size[1]-5,10,10))this.resizing_node=c,this.canvas.style.cursor="se-resize",f=!0;else{if(c.outputs)for(var q=0,n=c.outputs.length;qs([a.canvasX,a.canvasY],[this.selected_group.pos[0]+this.selected_group.size[0],this.selected_group.pos[1]+this.selected_group.size[1]])*this.scale?this.selected_group_resizing=!0:this.selected_group.recomputeInsideNodes()),g&&this.showSearchBox(a),l=!0;!f&&l&&this.allow_dragcanvas&&(this.dragging_canvas=!0)}else 2!=a.which&& +3==a.which&&this.processContextMenu(c,a);this.last_mouse[0]=a.localX;this.last_mouse[1]=a.localY;this.last_mouseclick=k.getTime();this.last_mouse_dragging=!0;this.graph.change();(!b.document.activeElement||"input"!=b.document.activeElement.nodeName.toLowerCase()&&"textarea"!=b.document.activeElement.nodeName.toLowerCase())&&a.preventDefault();a.stopPropagation();if(this.onMouseDown)this.onMouseDown(a);return!1}}};d.prototype.processMouseMove=function(a){this.autoresize&&this.resize();if(this.graph){d.active_canvas= +this;this.adjustMouseEvent(a);var b=[a.localX,a.localY],c=[b[0]-this.last_mouse[0],b[1]-this.last_mouse[1]];this.last_mouse=b;this.canvas_mouse[0]=a.canvasX;this.canvas_mouse[1]=a.canvasY;a.dragging=this.last_mouse_dragging;this.node_widget&&(this.processNodeWidgets(this.node_widget[0],this.canvas_mouse,a,this.node_widget[1]),this.dirty_canvas=!0);if(this.dragging_rectangle)this.dragging_rectangle[2]=a.canvasX-this.dragging_rectangle[0],this.dragging_rectangle[3]=a.canvasY-this.dragging_rectangle[1], +this.dirty_canvas=!0;else if(this.selected_group)this.selected_group_resizing?this.selected_group.size=[a.canvasX-this.selected_group.pos[0],a.canvasY-this.selected_group.pos[1]]:(this.selected_group.move(c[0]/this.scale,c[1]/this.scale,a.ctrlKey),this.selected_group._nodes.length&&(this.dirty_canvas=!0)),this.dirty_bgcanvas=!0;else if(this.dragging_canvas)this.offset[0]+=c[0]/this.scale,this.offset[1]+=c[1]/this.scale,this.dirty_bgcanvas=this.dirty_canvas=!0;else if(this.allow_interaction){this.connecting_node&& +(this.dirty_canvas=!0);for(var f=this.graph.getNodeOnPos(a.canvasX,a.canvasY,this.visible_nodes),b=0,g=this.graph._nodes.length;bthis.dragging_rectangle[3]?this.dragging_rectangle[1]-g:this.dragging_rectangle[1];this.dragging_rectangle[0]=0>this.dragging_rectangle[2]?this.dragging_rectangle[0]-f:this.dragging_rectangle[0];this.dragging_rectangle[1]=l;this.dragging_rectangle[2]=f;this.dragging_rectangle[3]=g;g=[];for(l=0;la.click_time&&this.deselectAllNodes();this.dirty_canvas=!0;this.dragging_canvas=!1;if(this.node_over&&this.node_over.onMouseUp)this.node_over.onMouseUp(a,[a.canvasX-this.node_over.pos[0],a.canvasY-this.node_over.pos[1]],this);if(this.node_capturing_input&&this.node_capturing_input.onMouseUp)this.node_capturing_input.onMouseUp(a,[a.canvasX-this.node_capturing_input.pos[0],a.canvasY-this.node_capturing_input.pos[1]])}}else 2== +a.which?(this.dirty_canvas=!0,this.dragging_canvas=!1):3==a.which&&(this.dirty_canvas=!0,this.dragging_canvas=!1);this.graph.change();a.stopPropagation();a.preventDefault();return!1}};d.prototype.processMouseWheel=function(a){if(this.graph&&this.allow_dragcanvas){var b=null!=a.wheelDeltaY?a.wheelDeltaY:-60*a.detail;this.adjustMouseEvent(a);var c=this.scale;0b&&(c*=1/1.1);this.setZoom(c,[a.localX,a.localY]);this.graph.change();a.preventDefault();return!1}};d.prototype.isOverNodeBox=function(a, +b,c){var f=k.NODE_TITLE_HEIGHT;return r(b,c,a.pos[0]+2,a.pos[1]+2-f,f-4,f-4)?!0:!1};d.prototype.isOverNodeInput=function(a,b,c,f){if(a.inputs)for(var g=0,l=a.inputs.length;gthis.max_zoom?this.scale=this.max_zoom:this.scalec-this.graph._last_trigger_time)&&this.drawBackCanvas();(this.dirty_canvas||a)&&this.drawFrontCanvas();this.fps=this.render_time?1/this.render_time:0;this.frame+=1}};d.prototype.drawFrontCanvas=function(){this.dirty_canvas=!1;this.ctx||(this.ctx=this.bgcanvas.getContext("2d"));var a=this.ctx;if(a){a.start2D&&a.start2D();var b=this.canvas;a.restore();a.setTransform(1,0,0,1,0,0);this.dirty_area&& +(a.save(),a.beginPath(),a.rect(this.dirty_area[0],this.dirty_area[1],this.dirty_area[2],this.dirty_area[3]),a.clip());this.clear_background&&a.clearRect(0,0,b.width,b.height);this.bgcanvas==this.canvas?this.drawBackCanvas():a.drawImage(this.bgcanvas,0,0);if(this.onRender)this.onRender(b,a);this.show_info&&this.renderInfo(a);if(this.graph){a.save();a.scale(this.scale,this.scale);a.translate(this.offset[0],this.offset[1]);for(var b=this.computeVisibleNodes(null,this.visible_nodes),c=0;c> ";c.fillText(b+e.getTitle(),0.5*a.width,40);c.restore()}e=!1;this.onRenderBackground&&(e=this.onRenderBackground(a,c));c.restore();c.setTransform(1, -0,0,1,0,0);if(this.graph){c.save();c.scale(this.scale,this.scale);c.translate(this.offset[0],this.offset[1]);if(this.background_image&&0.5this.scale?c.fillRect(p[0],p[1],p[2],p[3]):m==k.ROUND_SHAPE||m==k.CARD_SHAPE?c.roundRect(p[0],p[1],p[2],p[3],this.round_radius,m==k.CARD_SHAPE?0:this.round_radius):m==k.CIRCLE_SHAPE&&c.arc(0.5*b[0],0.5*b[1],0.5*b[0],0,2*Math.PI),c.fill());c.shadowColor="transparent";a.bgImage&&a.bgImage.width&& -c.drawImage(a.bgImage,0.5*(b[0]-a.bgImage.width),0.5*(b[1]-a.bgImage.height));a.bgImageUrl&&!a.bgImage&&(a.bgImage=a.loadImage(a.bgImageUrl));if(a.onDrawBackground)a.onDrawBackground(c,this,this.canvas);if(A||h==k.TRANSPARENT_TITLE){if(h!=k.TRANSPARENT_TITLE){a.flags.collapsed&&(c.shadowColor=k.DEFAULT_SHADOW_COLOR);this.use_gradients?(n=d.gradients[f],n||(n=d.gradients[f]=c.createLinearGradient(0,0,400,0),n.addColorStop(0,f),n.addColorStop(1,"#000")),c.fillStyle=n):c.fillStyle=f;var B=c.globalAlpha; -c.beginPath();m==k.BOX_SHAPE||0.5>this.scale?c.rect(0,-g,b[0]+1,g):m!=k.ROUND_SHAPE&&m!=k.CARD_SHAPE||c.roundRect(0,-g,b[0]+1,g,this.round_radius,a.flags.collapsed?this.round_radius:0);c.fill();c.shadowColor="transparent"}m==k.ROUND_SHAPE||m==k.CIRCLE_SHAPE||m==k.CARD_SHAPE?(0.5d[2]&&(d[0]+=d[2],d[2]=Math.abs(d[2]));0>d[3]&&(d[1]+=d[3],d[3]=Math.abs(d[3]));if(w(d,b)){var G=r.outputs[t],t=m.inputs[h];if(G&&t&&(r=G.dir||(r.flags.horizontal?k.DOWN:k.RIGHT),t=t.dir||(m.flags.horizontal?k.UP:k.LEFT),this.renderLink(a,z,F,q,!1,0,null,r,t),q&&q._last_time&&1E3>c-q._last_time)){var G=2-0.002*(c-q._last_time), -H=a.globalAlpha;a.globalAlpha=H*G;this.renderLink(a,z,F,q,!0,G,"white",r,t);a.globalAlpha=H}}}}}}a.globalAlpha=1};d.prototype.renderLink=function(a,c,b,f,g,l,n,p,m){if(this.highquality_render){p=p||k.RIGHT;m=m||k.LEFT;var h=r(c,b);this.render_connections_border&&0.6c[1]?0:Math.PI,a.save(),a.translate(g[0],g[1]),a.rotate(h),a.beginPath(),a.moveTo(-5,-5),a.lineTo(0,5),a.lineTo(5,-5),a.fill(),a.restore()); -if(l)for(l=0;5>l;++l)g=(0.001*k.getTime()+0.2*l)%1,g=this.computeConnectionPoint(c,b,g,p,m),a.beginPath(),a.arc(g[0],g[1],5,0,2*Math.PI),a.fill()}else a.beginPath(),a.moveTo(c[0],c[1]),a.lineTo(b[0],b[1]),a.stroke()};d.prototype.computeConnectionPoint=function(a,c,b,d,g){d=d||k.RIGHT;g=g||k.LEFT;var l=r(a,c),n=[a[0],a[1]],f=[c[0],c[1]];switch(d){case k.LEFT:n[0]+=-0.25*l;break;case k.RIGHT:n[0]+=0.25*l;break;case k.UP:n[1]+=-0.25*l;break;case k.DOWN:n[1]+=0.25*l}switch(g){case k.LEFT:f[0]+=-0.25* -l;break;case k.RIGHT:f[0]+=0.25*l;break;case k.UP:f[1]+=-0.25*l;break;case k.DOWN:f[1]+=0.25*l}d=(1-b)*(1-b)*(1-b);g=3*(1-b)*(1-b)*b;l=3*(1-b)*b*b;b*=b*b;return[d*a[0]+g*n[0]+l*f[0]+b*c[0],d*a[1]+g*n[1]+l*f[1]+b*c[1]]};d.prototype.drawExecutionOrder=function(a){a.shadowColor="transparent";a.globalAlpha=0.25;a.textAlign="center";a.strokeStyle="white";a.globalAlpha=0.75;for(var c=this.visible_nodes,b=0;bh.last_y&&lh.options.max&&(h.value=h.options.max);else if("mousedown"==b.type)if((d=h.options.values)&&d.constructor===Function&&(d=h.options.values(h,a)),g=40>g?-1:g>n-40?1:0,"number"==h.type)h.value+=0.1*g*(h.options.step||1),null!=h.options.min&&h.valueh.options.max&&(h.value=h.options.max);else if(g)b=d.indexOf(h.value)+g,b>=d.length&&(b=0),0>b&&(b=d.length-1),h.value=d[b];else{new k.ContextMenu(d,{event:b,className:"dark",callback:q.bind(h)},m);var q=function(a,c,b){this.value=a;f.dirty_canvas=!0;return!1}}h.callback&&setTimeout(function(){this.callback(this.value,f,a,c)}.bind(h),20);this.dirty_canvas=!0;break;case "toggle":"mousedown"==b.type&&(h.value=!h.value,h.callback&&setTimeout(function(){h.callback(h.value, -f,a,c)},20));break;case "text":"mousedown"==b.type&&this.prompt("Value",h.value,function(c){this.value=c;h.callback&&h.callback(c,f,a)}.bind(h),b);break;default:h.mouse&&h.mouse(ctx,b,[g,l],a)}return h}}return null};d.prototype.drawGroups=function(a,c){if(this.graph){var b=this.graph._groups;c.save();c.globalAlpha=0.5*this.editor_alpha;for(var d=0;db&&0.01>c.editor_alpha&&(clearInterval(d),1>b&&(c.live_mode=!0));1"+h+""+a+"",value:h});if(p.length)return new k.ContextMenu(p,{event:b,callback:l,parentMenu:f,allow_html:!0,node:g},c),!1}};d.decodeHTML=function(a){var c=document.createElement("div");c.innerText=a;return c.innerHTML};d.onResizeNode=function(a,c,b,d,g){g&&(g.size=g.computeSize(),g.setDirtyCanvas(!0,!0))};d.onShowPropertyEditor=function(a,c,b,f,g){function l(){var c=h.value; -"Number"==a.type?c=Number(c):"Boolean"==a.type&&(c=Boolean(c));g[m]=c;p.parentNode.removeChild(p);g.setDirtyCanvas(!0,!0)}var m=a.property||"title";c=g[m];var p=document.createElement("div");p.className="graphdialog";p.innerHTML="";p.querySelector(".name").innerText=m;var h=p.querySelector("input");h&&(h.value=c,h.addEventListener("blur",function(a){this.focus()}),h.addEventListener("keydown",function(a){13== -a.keyCode&&(l(),a.preventDefault(),a.stopPropagation())}));c=d.active_canvas.canvas;b=c.getBoundingClientRect();var k=f=-20;b&&(f-=b.left,k-=b.top);event?(p.style.left=event.pageX+f+"px",p.style.top=event.pageY+k+"px"):(p.style.left=0.5*c.width+f+"px",p.style.top=0.5*c.height+k+"px");p.querySelector("button").addEventListener("click",l);c.parentNode.appendChild(p)};d.prototype.prompt=function(a,c,b,f){var g=this;a=a||"";var l=document.createElement("div");l.className="graphdialog rounded";l.innerHTML= -" ";l.close=function(){g.prompt_box=null;l.parentNode.removeChild(l)};l.addEventListener("mouseleave",function(a){l.close()});g.prompt_box&&g.prompt_box.close();g.prompt_box=l;l.querySelector(".name").innerText=a;l.querySelector(".value").value=c;var m=l.querySelector("input");m.addEventListener("keydown",function(a){if(27==a.keyCode)l.close();else if(13==a.keyCode)b&&b(this.value),l.close();else return; -a.preventDefault();a.stopPropagation()});l.querySelector("button").addEventListener("click",function(a){b&&b(m.value);g.setDirty(!0);l.close()});a=d.active_canvas.canvas;c=a.getBoundingClientRect();var p=-20,h=-20;c&&(p-=c.left,h-=c.top);f?(l.style.left=f.pageX+p+"px",l.style.top=f.pageY+h+"px"):(l.style.left=0.5*a.width+p+"px",l.style.top=0.5*a.height+h+"px");a.parentNode.appendChild(l);setTimeout(function(){m.focus()},10);return l};d.search_limit=-1;d.prototype.showSearchBox=function(a){function c(c){if(c)if(g.onSearchBoxSelection)g.onSearchBoxSelection(c, -a,t);else{var b=k.searchbox_extras[c];b&&(c=b.type);if(c=k.createNode(c))c.pos=t.convertEventToCanvas(a),t.graph.add(c);if(b&&b.data){if(b.data.properties)for(var e in b.data.properties)c.addProperty(b.data.properties[e][0],b.data.properties[e][0]);if(b.data.inputs)for(e in c.inputs=[],b.data.inputs)c.addOutput(b.data.inputs[e][0],b.data.inputs[e][1]);if(b.data.outputs)for(e in c.outputs=[],b.data.outputs)c.addOutput(b.data.outputs[e][0],b.data.outputs[e][1]);b.data.title&&(c.title=b.data.title); -b.data.json&&c.configure(b.data.json)}}l.close()}function b(a){var c=q;q&&q.classList.remove("selected");q?(q=a?q.nextSibling:q.previousSibling)||(q=c):q=a?m.childNodes[0]:m.childNodes[m.childNodes.length];q&&(q.classList.add("selected"),q.scrollIntoView())}function f(){function a(b,e){var g=document.createElement("div");p||(p=b);g.innerText=b;g.dataset.type=escape(b);g.className="litegraph lite-search-item";e&&(g.className+=" "+e);g.addEventListener("click",function(a){c(unescape(this.dataset.type))}); -m.appendChild(g)}h=null;var b=r.value;p=null;m.innerHTML="";if(b)if(g.onSearchBox){var e=g.onSearchBox(help,b,t);if(e)for(var z=0;zd.search_limit))break}if(Array.prototype.filter)for(l=Object.keys(k.registered_node_types).filter(function(a){return-1!==a.toLowerCase().indexOf(b)}),z=0;zd.search_limit);z++);else for(z in k.registered_node_types)if(-1!=z.indexOf(b)&&(a(z),-1!==d.search_limit&&e++>d.search_limit))break}}var g=this,l=document.createElement("div");l.className="litegraph litesearchbox graphdialog rounded";l.innerHTML="Search
";l.close=function(){g.search_box=null;l.parentNode.removeChild(l)};l.addEventListener("mouseleave",function(a){l.close()}); -g.search_box&&g.search_box.close();g.search_box=l;var m=l.querySelector(".helper"),p=null,h=null,q=null,r=l.querySelector("input");r&&(r.addEventListener("blur",function(a){this.focus()}),r.addEventListener("keydown",function(a){if(38==a.keyCode)b(!1);else if(40==a.keyCode)b(!0);else if(27==a.keyCode)l.close();else if(13==a.keyCode)q?c(q.innerHTML):p?c(p):l.close();else{h&&clearInterval(h);h=setTimeout(f,10);return}a.preventDefault();a.stopPropagation()}));var t=d.active_canvas,w=t.canvas,u=w.getBoundingClientRect(), -z=-20,F=-20;u&&(z-=u.left,F-=u.top);a?(l.style.left=a.pageX+z+"px",l.style.top=a.pageY+F+"px"):(l.style.left=0.5*w.width+z+"px",l.style.top=0.5*w.height+F+"px");w.parentNode.appendChild(l);r.focus();return l};d.prototype.showEditPropertyValue=function(a,c,b){function d(){g(q.value)}function g(b){"number"==typeof a.properties[c]&&(b=Number(b));"array"==l&&(b=b.split(",").map(Number));a.properties[c]=b;a._graph&&a._graph._version++;if(a.onPropertyChanged)a.onPropertyChanged(c,b);k.close();a.setDirtyCanvas(!0, -!0)}if(a&&void 0!==a.properties[c]){b=b||{};var l="string";null!==a.properties[c]&&(l=typeof a.properties[c]);"object"==l&&a.properties[c].length&&(l="array");var f=null;a.getPropertyInfo&&(f=a.getPropertyInfo(c));if(a.properties_info)for(var m=0;m";else if("enum"==l&&f.values){p= -""}else if("boolean"==l)p="";else{console.warn("unknown type: "+l);return}var k=this.createDialog(""+c+""+p+"",b);if("enum"==l&&f.values){var q=k.querySelector("select"); -q.addEventListener("change",function(a){g(a.target.value)})}else if("boolean"==l)(q=k.querySelector("input"))&&q.addEventListener("click",function(a){g(!!q.checked)});else if(q=k.querySelector("input"))q.addEventListener("blur",function(a){this.focus()}),q.value=void 0!==a.properties[c]?a.properties[c]:"",q.addEventListener("keydown",function(a){13==a.keyCode&&(d(),a.preventDefault(),a.stopPropagation())});k.querySelector("button").addEventListener("click",d)}};d.prototype.createDialog=function(a, -c){c=c||{};var b=document.createElement("div");b.className="graphdialog";b.innerHTML=a;var d=this.canvas.getBoundingClientRect(),g=-20,l=-20;d&&(g-=d.left,l-=d.top);c.position?(g+=c.position[0],l+=c.position[1]):c.event?(g+=c.event.pageX,l+=c.event.pageY):(g+=0.5*this.canvas.width,l+=0.5*this.canvas.height);b.style.left=g+"px";b.style.top=l+"px";this.canvas.parentNode.appendChild(b);b.close=function(){this.parentNode&&this.parentNode.removeChild(this)};return b};d.onMenuNodeCollapse=function(a,c, -b,d,g){g.collapse()};d.onMenuNodePin=function(a,c,b,d,g){g.pin()};d.onMenuNodeMode=function(a,c,b,d,g){new k.ContextMenu(["Always","On Event","On Trigger","Never"],{event:b,callback:function(a){if(g)switch(a){case "On Event":g.mode=k.ON_EVENT;break;case "On Trigger":g.mode=k.ON_TRIGGER;break;case "Never":g.mode=k.NEVER;break;default:g.mode=k.ALWAYS}},parentMenu:d,node:g});return!1};d.onMenuNodeColors=function(a,c,b,f,g){if(!g)throw"no node for color";c=[];c.push({value:null,content:"No color"}); -for(var l in d.node_colors)a=d.node_colors[l],a={value:l,content:""+l+""},c.push(a);new k.ContextMenu(c,{event:b,callback:function(a){g&&((a=a.value?d.node_colors[a.value]:null)?g.constructor===k.LGraphGroup?g.color=a.groupcolor:(g.color=a.color,g.bgcolor=a.bgcolor):(delete g.color,delete g.bgcolor),g.setDirtyCanvas(!0,!0))},parentMenu:f,node:g});return!1};d.onMenuNodeShapes= -function(a,c,b,d,g){if(!g)throw"no node passed";new k.ContextMenu(k.VALID_SHAPES,{event:b,callback:function(a){g&&(g.shape=a,g.setDirtyCanvas(!0))},parentMenu:d,node:g});return!1};d.onMenuNodeRemove=function(a,b,e,d,g){if(!g)throw"no node passed";!1!==g.removable&&(g.graph.remove(g),g.setDirtyCanvas(!0,!0))};d.onMenuNodeClone=function(a,b,e,d,g){!1!=g.clonable&&(a=g.clone())&&(a.pos=[g.pos[0]+5,g.pos[1]+5],g.graph.add(a),g.setDirtyCanvas(!0,!0))};d.node_colors={red:{color:"#322",bgcolor:"#533",groupcolor:"#A88"}, -brown:{color:"#332922",bgcolor:"#593930",groupcolor:"#b06634"},green:{color:"#232",bgcolor:"#353",groupcolor:"#8A8"},blue:{color:"#223",bgcolor:"#335",groupcolor:"#88A"},pale_blue:{color:"#2a363b",bgcolor:"#3f5159",groupcolor:"#3f789e"},cyan:{color:"#233",bgcolor:"#355",groupcolor:"#8AA"},purple:{color:"#323",bgcolor:"#535",groupcolor:"#a1309b"},yellow:{color:"#432",bgcolor:"#653",groupcolor:"#b58b2a"},black:{color:"#222",bgcolor:"#000",groupcolor:"#444"}};d.prototype.getCanvasMenuOptions=function(){var a= -null;this.getMenuOptions?a=this.getMenuOptions():(a=[{content:"Add Node",has_submenu:!0,callback:d.onMenuAdd},{content:"Add Group",callback:d.onGroupAdd}],this._graph_stack&&0Name",c),m=d.querySelector("input");m&&l&&(m.value=l.label);d.querySelector("button").addEventListener("click",function(a){m.value&& -(l&&(l.label=m.value),e.setDirty(!0));d.close()})}},extra:a},m=null;a&&(m=a.getSlotInPosition(b.canvasX,b.canvasY),d.active_node=a);m?(g=[],m&&m.output&&m.output.links&&m.output.links.length&&g.push({content:"Disconnect Links",slot:m}),g.push(m.locked?"Cannot remove":{content:"Remove Slot",slot:m}),g.push(m.nameLocked?"Cannot rename":{content:"Rename Slot",slot:m}),l.title=(m.input?m.input.type:m.output.type)||"*",m.input&&m.input.type==k.ACTION&&(l.title="Action"),m.output&&m.output.type==k.EVENT&& -(l.title="Event")):a?g=this.getNodeMenuOptions(a):(g=this.getCanvasMenuOptions(),(m=this.graph.getGroupOnPos(b.canvasX,b.canvasY))&&g.push(null,{content:"Edit Group",has_submenu:!0,submenu:{title:"Group",extra:m,options:this.getGroupMenuOptions(m)}}));g&&new k.ContextMenu(g,l,f)};this.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.roundRect=function(a,b,e,d,g,l){void 0===g&&(g=5);void 0===l&&(l=g);this.moveTo(a+g,b);this.lineTo(a+e-g,b);this.quadraticCurveTo(a+e,b,a+e,b+g);this.lineTo(a+ -e,b+d-l);this.quadraticCurveTo(a+e,b+d,a+e-l,b+d);this.lineTo(a+l,b+d);this.quadraticCurveTo(a,b+d,a,b+d-l);this.lineTo(a,b+g);this.quadraticCurveTo(a,b,a+g,b)});k.compareObjects=function(a,b){for(var e in a)if(a[e]!=b[e])return!1;return!0};k.distance=r;k.colorToString=function(a){return"rgba("+Math.round(255*a[0]).toFixed()+","+Math.round(255*a[1]).toFixed()+","+Math.round(255*a[2]).toFixed()+","+(4==a.length?a[3].toFixed(2):"1.0")+")"};k.isInsideRectangle=t;k.growBounding=function(a,b,e){ba[2]&&(a[2]=b);ea[3]&&(a[3]=e)};k.isInsideBounding=function(a,b){return a[0]b[1][0]||a[1]>b[1][1]?!1:!0};k.overlapBounding=w;k.hex2num=function(a){"#"==a.charAt(0)&&(a=a.slice(1));a=a.toUpperCase();for(var b=Array(3),e=0,d,g,l=0;6>l;l+=2)d="0123456789ABCDEF".indexOf(a.charAt(l)),g="0123456789ABCDEF".indexOf(a.charAt(l+1)),b[e]=16*d+g,e++;return b};k.num2hex=function(a){for(var b="#",e,d,g=0;3>g;g++)e=a[g]/16,d=a[g]%16,b+="0123456789ABCDEF".charAt(e)+ -"0123456789ABCDEF".charAt(d);return b};u.prototype.addItem=function(a,b,e){function d(a){var b=this.value;b&&b.has_submenu&&g.call(this,a)}function g(a){var b=this.value,c=!0;l.current_submenu&&l.current_submenu.close(a);if(e.callback){var g=e.callback.call(this,b,e,a,l,e.node);!0===g&&(c=!1)}if(b&&(b.callback&&!e.ignore_item_callbacks&&!0!==b.disabled&&(g=b.callback.call(this,b,e,a,l,e.extra),!0===g&&(c=!1)),b.submenu)){if(!b.submenu.options)throw"ContextMenu submenu needs options";new l.constructor(b.submenu.options, -{callback:b.submenu.callback,event:a,parentMenu:l,ignore_item_callbacks:b.submenu.ignore_item_callbacks,title:b.submenu.title,extra:b.submenu.extra,autoopen:e.autoopen});c=!1}c&&!l.lock&&l.close()}var l=this;e=e||{};var m=document.createElement("div");m.className="litemenu-entry submenu";var f=!1;if(null===b)m.classList.add("separator");else{m.innerHTML=b&&b.title?b.title:a;if(m.value=b)b.disabled&&(f=!0,m.classList.add("disabled")),(b.submenu||b.has_submenu)&&m.classList.add("has_submenu");"function"== -typeof b?(m.dataset.value=a,m.onclick_callback=b):m.dataset.value=b;b.className&&(m.className+=" "+b.className)}this.root.appendChild(m);f||m.addEventListener("click",g);e.autoopen&&m.addEventListener("mouseenter",d);return m};u.prototype.close=function(a,b){this.root.parentNode&&this.root.parentNode.removeChild(this.root);this.parentMenu&&!b&&(this.parentMenu.lock=!1,this.parentMenu.current_submenu=null,void 0===a?this.parentMenu.close():a&&!u.isCursorOverElement(a,this.parentMenu.root)&&u.trigger(this.parentMenu.root, -"mouseleave",a));this.current_submenu&&this.current_submenu.close(a,!0);this.root.closing_timer&&clearTimeout(this.root.closing_timer)};u.trigger=function(a,b,e,d){var g=document.createEvent("CustomEvent");g.initCustomEvent(b,!0,!0,e);g.srcElement=d;a.dispatchEvent?a.dispatchEvent(g):a.__events&&a.__events.dispatchEvent(g);return g};u.prototype.getTopMenu=function(){return this.options.parentMenu?this.options.parentMenu.getTopMenu():this};u.prototype.getFirstEvent=function(){return this.options.parentMenu? -this.options.parentMenu.getFirstEvent():this.options.event};u.isCursorOverElement=function(a,b){var e=a.pageX,d=a.pageY,g=b.getBoundingClientRect();return g?d>g.top&&dg.left&&ea?b:ethis.size[0]-m.NODE_TITLE_HEIGHT&&0>d[1]){var c=this;setTimeout(function(){a.openSubgraph(c.subgraph)},10)}};f.prototype.onSubgraphNewGlobalInput=function(b,d){this.addInput(b,d)};f.prototype.onSubgraphRenamedGlobalInput=function(b,d){var a=this.findInputSlot(b);-1!=a&&(this.getInputInfo(a).name=d)};f.prototype.onSubgraphTypeChangeGlobalInput=function(b,d){var a=this.findInputSlot(b);-1!=a&&(this.getInputInfo(a).type=d)};f.prototype.onSubgraphNewGlobalOutput=function(b, -d){this.addOutput(b,d)};f.prototype.onSubgraphRenamedGlobalOutput=function(b,d){var a=this.findOutputSlot(b);-1!=a&&(this.getOutputInfo(a).name=d)};f.prototype.onSubgraphTypeChangeGlobalOutput=function(b,d){var a=this.findOutputSlot(b);-1!=a&&(this.getOutputInfo(a).type=d)};f.prototype.getExtraMenuOptions=function(b){var d=this;return[{content:"Open",callback:function(){b.openSubgraph(d.subgraph)}}]};f.prototype.onResize=function(b){b[1]+=20};f.prototype.onExecute=function(){if(this.inputs)for(var b= -0;bd[1]))return this.old_y=b.canvasY,this.captureInput(!0),this.mouse_captured=!0};q.prototype.onMouseMove=function(b){if(this.mouse_captured){var d=this.old_y-b.canvasY;b.shiftKey&&(d*=10);if(b.metaKey||b.altKey)d*=0.1;this.old_y=b.canvasY;b=this._remainder+d/q.pixels_threshold;this._remainder=b%1;b=Math.clamp(this.properties.value+(b|0)*this.properties.step,this.properties.min,this.properties.max);this.properties.value=b;this.graph._version++; -this.setDirtyCanvas(!0)}};q.prototype.onMouseUp=function(b,d){200>b.click_time&&(this.properties.value=Math.clamp(this.properties.value+(d[1]>0.5*this.size[1]?-1:1)*this.properties.step,this.properties.min,this.properties.max),this.graph._version++,this.setDirtyCanvas(!0));this.mouse_captured&&(this.mouse_captured=!1,this.captureInput(!1))};m.registerNodeType("widget/number",q);d.title="Knob";d.desc="Circular controller";d.widgets=[{name:"increase",text:"+",type:"minibutton"},{name:"decrease",text:"-", -type:"minibutton"}];d.prototype.onAdded=function(){this.value=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min);this.imgbg=this.loadImage("imgs/knob_bg.png");this.imgfg=this.loadImage("imgs/knob_fg.png")};d.prototype.onDrawImageKnob=function(b){if(this.imgfg&&this.imgfg.width){var d=0.5*this.imgbg.width,a=this.size[0]/this.imgfg.width;b.save();b.translate(0,20);b.scale(a,a);b.drawImage(this.imgbg,0,0);b.translate(d,d);b.rotate(2*this.value*Math.PI*6/8+10*Math.PI/ -8);b.translate(-d,-d);b.drawImage(this.imgfg,0,0);b.restore();this.title&&(b.font="bold 16px Criticized,Tahoma",b.fillStyle="rgba(100,100,100,0.8)",b.textAlign="center",b.fillText(this.title.toUpperCase(),0.5*this.size[0],18),b.textAlign="left")}};d.prototype.onDrawVectorKnob=function(b){if(this.imgfg&&this.imgfg.width){b.lineWidth=1;b.strokeStyle=this.mouseOver?"#FFF":"#AAA";b.fillStyle="#000";b.beginPath();b.arc(0.5*this.size[0],0.5*this.size[1]+10,0.5*this.properties.size,0,2*Math.PI,!0);b.stroke(); -0b.canvasY-this.pos[1]||m.distance([b.canvasX,b.canvasY],[this.pos[0]+this.center[0],this.pos[1]+this.center[1]])>this.radius)return!1;this.oldmouse=[b.canvasX-this.pos[0],b.canvasY-this.pos[1]];this.captureInput(!0); -return!0}};d.prototype.onMouseMove=function(b){if(this.oldmouse){b=[b.canvasX-this.pos[0],b.canvasY-this.pos[1]];var d=this.value,d=d-0.01*(b[1]-this.oldmouse[1]);1d&&(d=0);this.value=d;this.properties.value=this.properties.min+(this.properties.max-this.properties.min)*this.value;this.oldmouse=b;this.setDirtyCanvas(!0)}};d.prototype.onMouseUp=function(b){this.oldmouse&&(this.oldmouse=null,this.captureInput(!1))};d.prototype.onMouseLeave=function(b){};d.prototype.onPropertyChanged=function(b, -d){if("wcolor"==b)this.properties[b]=d;else if("size"==b)d=parseInt(d),this.properties[b]=d,this.size=[d+4,d+24],this.setDirtyCanvas(!0,!0);else if("min"==b||"max"==b||"value"==b)this.properties[b]=parseFloat(d);else return!1;return!0};m.registerNodeType("widget/knob",d);r.title="Internal Slider";r.prototype.onPropertyChanged=function(b,d){"value"==b&&(this.slider.value=d)};r.prototype.onExecute=function(){this.setOutputData(0,this.properties.value)};m.registerNodeType("widget/internal_slider",r); -t.title="H.Slider";t.desc="Linear slider controller";t.prototype.onAdded=function(){this.value=0.5;this.imgfg=this.loadImage("imgs/slider_fg.png")};t.prototype.onDrawVectorial=function(b){this.imgfg&&this.imgfg.width&&(b.lineWidth=1,b.strokeStyle=this.mouseOver?"#FFF":"#AAA",b.fillStyle="#000",b.beginPath(),b.rect(2,0,this.size[0]-4,20),b.stroke(),b.fillStyle=this.properties.wcolor,b.beginPath(),b.rect(2+(this.size[0]-4-20)*this.value,0,20,20),b.fill())};t.prototype.onDrawImage=function(b){this.imgfg&& -this.imgfg.width&&(b.lineWidth=1,b.fillStyle="#000",b.fillRect(2,9,this.size[0]-4,2),b.strokeStyle="#333",b.beginPath(),b.moveTo(2,9),b.lineTo(this.size[0]-4,9),b.stroke(),b.strokeStyle="#AAA",b.beginPath(),b.moveTo(2,11),b.lineTo(this.size[0]-4,11),b.stroke(),b.drawImage(this.imgfg,2+(this.size[0]-4)*this.value-0.5*this.imgfg.width,0.5*-this.imgfg.height+10))};t.prototype.onDrawForeground=function(b){this.onDrawImage(b)};t.prototype.onExecute=function(){this.properties.value=this.properties.min+ -(this.properties.max-this.properties.min)*this.value;this.setOutputData(0,this.properties.value);this.boxcolor=m.colorToString([this.value,this.value,this.value])};t.prototype.onMouseDown=function(b){if(0>b.canvasY-this.pos[1])return!1;this.oldmouse=[b.canvasX-this.pos[0],b.canvasY-this.pos[1]];this.captureInput(!0);return!0};t.prototype.onMouseMove=function(b){if(this.oldmouse){b=[b.canvasX-this.pos[0],b.canvasY-this.pos[1]];var d=this.value,d=d+(b[0]-this.oldmouse[0])/this.size[0];1d&& -(d=0);this.value=d;this.oldmouse=b;this.setDirtyCanvas(!0)}};t.prototype.onMouseUp=function(b){this.oldmouse=null;this.captureInput(!1)};t.prototype.onMouseLeave=function(b){};t.prototype.onPropertyChanged=function(b,d){if("wcolor"==b)this.properties[b]=d;else return!1;return!0};m.registerNodeType("widget/hslider",t);w.title="Progress";w.desc="Shows data in linear progress";w.prototype.onExecute=function(){var b=this.getInputData(0);void 0!=b&&(this.properties.value=b)};w.prototype.onDrawForeground= -function(b){b.lineWidth=1;b.fillStyle=this.properties.wcolor;var d=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min),d=Math.min(1,d),d=Math.max(0,d);b.fillRect(2,2,(this.size[0]-4)*d,this.size[1]-4)};m.registerNodeType("widget/progress",w);u.title="Text";u.desc="Shows the input value";u.widgets=[{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}];u.prototype.onDrawForeground= -function(b){b.fillStyle=this.properties.color;var d=this.properties.value;this.properties.glowSize?(b.shadowColor=this.properties.color,b.shadowOffsetX=0,b.shadowOffsetY=0,b.shadowBlur=this.properties.glowSize):b.shadowColor="transparent";var a=this.properties.fontsize;b.textAlign=this.properties.align;b.font=a.toString()+"px "+this.properties.font;this.str="number"==typeof d?d.toFixed(this.properties.decimals):d;if("string"==typeof this.str){var d=this.str.split("\\n"),c;for(c in d)b.fillText(d[c], -"left"==this.properties.align?15:this.size[0]-15,-0.15*a+a*(parseInt(c)+1))}b.shadowColor="transparent";this.last_ctx=b;b.textAlign="left"};u.prototype.onExecute=function(){var b=this.getInputData(0);null!=b&&(this.properties.value=b)};u.prototype.resize=function(){if(this.last_ctx){var b=this.str.split("\\n");this.last_ctx.font=this.properties.fontsize+"px "+this.properties.font;var d=0,a;for(a in b){var c=this.last_ctx.measureText(b[a]).width;dd?f.xbox.axes.lx:0,this._left_axis[1]=Math.abs(f.xbox.axes.ly)>d?f.xbox.axes.ly:0,this._right_axis[0]=Math.abs(f.xbox.axes.rx)>d?f.xbox.axes.rx:0,this._right_axis[1]=Math.abs(f.xbox.axes.ry)>d?f.xbox.axes.ry:0,this._triggers[0]=Math.abs(f.xbox.axes.ltrigger)>d?f.xbox.axes.ltrigger:0,this._triggers[1]=Math.abs(f.xbox.axes.rtrigger)>d?f.xbox.axes.rtrigger:0);if(this.outputs)for(d= -0;df;f++)if(d[f]){f=d[f];d=this.xbox_mapping;d||(d=this.xbox_mapping= -{axes:[],buttons:{},hat:""});d.axes.lx=f.axes[0];d.axes.ly=f.axes[1];d.axes.rx=f.axes[2];d.axes.ry=f.axes[3];d.axes.ltrigger=f.buttons[6].value;d.axes.rtrigger=f.buttons[7].value;for(var h=0;h","string",{values:s.values});this.size=[60,40]}function g(){this.addInput("inc","number");this.addOutput("total","number");this.addProperty("increment",1);this.addProperty("value",0)}function l(){this.addInput("v","number");this.addOutput("sin","number");this.addProperty("amplitude",1);this.addProperty("offset",0);this.bgImageUrl="nodes/imgs/icon-sin.png"} -function n(){this.addInput("x","number");this.addInput("y","number");this.addOutput("","number");this.properties={x:1,y:1,formula:"x+y"};this.addWidget("toggle","allow",x.allow_scripts,function(a){x.allow_scripts=a});this._func=null}function y(){this.addInput("vec2","vec2");this.addOutput("x","number");this.addOutput("y","number")}function C(){this.addInputs([["x","number"],["y","number"]]);this.addOutput("vec2","vec2");this.properties={x:0,y:0};this._data=new Float32Array(2)}function A(){this.addInput("vec3", -"vec3");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number")}function B(){this.addInputs([["x","number"],["y","number"],["z","number"]]);this.addOutput("vec3","vec3");this.properties={x:0,y:0,z:0};this._data=new Float32Array(3)}function D(){this.addInput("vec4","vec4");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number");this.addOutput("w","number")}function E(){this.addInputs([["x","number"],["y","number"],["z","number"],["w","number"]]); -this.addOutput("vec4","vec4");this.properties={x:0,y:0,z:0,w:0};this._data=new Float32Array(4)}var x=v.LiteGraph;h.title="Converter";h.desc="type A to type B";h.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a&&this.outputs)for(var b=0;bb&&(this._current=0);for(var c=a=0;cb&&(b=1);this.properties.samples=Math.round(b);var c=this._values;this._values=new Float32Array(this.properties.samples);c.length<= -this._values.length?this._values.set(c):this._values.set(c.subarray(0,this._values.length))};x.registerNodeType("math/average",p);a.title="TendTo";a.desc="moves the output value always closer to the input";a.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=0);var b=this.properties.factor;this._value=null==this._value?a:this._value*(1-b)+a*b;this.setOutputData(0,this._value)};x.registerNodeType("math/tendTo",a);c.values="+-*/%^".split("");c.title="Operation";c.desc="Easy math operators"; -c["@OP"]={type:"enum",title:"operation",values:c.values};c.prototype.getTitle=function(){return"A "+this.properties.OP+" B"};c.prototype.setValue=function(a){"string"==typeof a&&(a=parseFloat(a));this.properties.value=a};c.prototype.onExecute=function(){var a=this.getInputData(0),b=this.getInputData(1);null!=a?this.properties.A=a:a=this.properties.A;null!=b?this.properties.B=b:b=this.properties.B;var c=0;switch(this.properties.OP){case "+":c=a+b;break;case "-":c=a-b;break;case "x":case "X":case "*":c= -a*b;break;case "/":c=a/b;break;case "%":c=a%b;break;case "^":c=Math.pow(a,b);break;default:console.warn("Unknown operation: "+this.properties.OP)}this.setOutputData(0,c)};c.prototype.onDrawBackground=function(a){this.flags.collapsed||(a.font="40px Arial",a.fillStyle="#CCC",a.textAlign="center",a.fillText(this.properties.OP,0.5*this.size[0],0.35*this.size[1]+x.NODE_TITLE_HEIGHT),a.textAlign="left")};x.registerNodeType("math/operation",c);e.title="Compare";e.desc="compares between two values";e.prototype.onExecute= -function(){var a=this.getInputData(0),b=this.getInputData(1);void 0!==a?this.properties.A=a:a=this.properties.A;void 0!==b?this.properties.B=b:b=this.properties.B;for(var c=0,e=this.outputs.length;cB":value=a>b;break;case "A=B":value=a>=b}this.setOutputData(c,value)}}};e.prototype.onGetOutputs=function(){return[["A==B", -"boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]};x.registerNodeType("math/compare",e);x.registerSearchboxExtra("math/compare","==",{outputs:[["A==B","boolean"]],title:"A==B"});x.registerSearchboxExtra("math/compare","!=",{outputs:[["A!=B","boolean"]],title:"A!=B"});x.registerSearchboxExtra("math/compare",">",{outputs:[["A>B","boolean"]],title:"A>B"});x.registerSearchboxExtra("math/compare","<",{outputs:[["A=",{outputs:[["A>=B","boolean"]],title:"A>=B"});x.registerSearchboxExtra("math/compare","<=",{outputs:[["A<=B","boolean"]],title:"A<=B"});s.values="> < == != <= >=".split(" ");s["@OP"]={type:"enum",title:"operation",values:s.values};s.title="Condition";s.desc="evaluates condition between A and B";s.prototype.onExecute=function(){var a=this.getInputData(0);void 0===a?a=this.properties.A:this.properties.A=a;var b=this.getInputData(1);void 0===b?b=this.properties.B:this.properties.B=b;var c=!0;switch(this.properties.OP){case ">":c= -a>b;break;case "<":c=a=":c=a>=b}this.setOutputData(0,c)};x.registerNodeType("math/condition",s);g.title="Accumulate";g.desc="Increments a value every time";g.prototype.onExecute=function(){null===this.properties.value&&(this.properties.value=0);var a=this.getInputData(0);this.properties.value=null!==a?this.properties.value+a:this.properties.value+this.properties.increment;this.setOutputData(0,this.properties.value)}; -x.registerNodeType("math/accumulate",g);l.title="Trigonometry";l.desc="Sin Cos Tan";l.filter="shader";l.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=0);var b=this.properties.amplitude,c=this.findInputSlot("amplitude");-1!=c&&(b=this.getInputData(c));var e=this.properties.offset,c=this.findInputSlot("offset");-1!=c&&(e=this.getInputData(c));for(var c=0,d=this.outputs.length;cXY";y.desc="vector 2 to components";y.prototype.onExecute= -function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]))};x.registerNodeType("math3d/vec2-to-xyz",y);C.title="XY->Vec2";C.desc="components to vector2";C.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this._data;c[0]=a;c[1]=b;this.setOutputData(0,c)};x.registerNodeType("math3d/xy-to-vec2",C);A.title="Vec3->XYZ";A.desc="vector 3 to components";A.prototype.onExecute= -function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]))};x.registerNodeType("math3d/vec3-to-xyz",A);B.title="XYZ->Vec3";B.desc="components to vector3";B.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);var e=this._data;e[0]=a;e[1]=b;e[2]=c;this.setOutputData(0,e)};x.registerNodeType("math3d/xyz-to-vec3", -B);D.title="Vec4->XYZW";D.desc="vector 4 to components";D.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]),this.setOutputData(3,a[3]))};x.registerNodeType("math3d/vec4-to-xyzw",D);E.title="XYZW->Vec4";E.desc="components to vector4";E.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2); -null==c&&(c=this.properties.z);var e=this.getInputData(3);null==e&&(e=this.properties.w);var d=this._data;d[0]=a;d[1]=b;d[2]=c;d[3]=e;this.setOutputData(0,d)};x.registerNodeType("math3d/xyzw-to-vec4",E);v.glMatrix&&(v=function(){this.addOutput("quat","quat");this.properties={x:0,y:0,z:0,w:1};this._value=quat.create()},v.title="Quaternion",v.desc="quaternion",v.prototype.onExecute=function(){this._value[0]=this.properties.x;this._value[1]=this.properties.y;this._value[2]=this.properties.z;this._value[3]= -this.properties.w;this.setOutputData(0,this._value)},x.registerNodeType("math3d/quaternion",v),v=function(){this.addInputs([["degrees","number"],["axis","vec3"]]);this.addOutput("quat","quat");this.properties={angle:90,axis:vec3.fromValues(0,1,0)};this._value=quat.create()},v.title="Rotation",v.desc="quaternion rotation",v.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle);var b=this.getInputData(1);null==b&&(b=this.properties.axis);a=quat.setAxisAngle(this._value, -b,0.0174532925*a);this.setOutputData(0,a)},x.registerNodeType("math3d/rotation",v),v=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},v.title="Rot. Vec3",v.desc="rotate a point",v.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a):this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))},x.registerNodeType("math3d/rotate_vec3", -v),v=function(){this.addInputs([["A","quat"],["B","quat"]]);this.addOutput("A*B","quat");this._value=quat.create()},v.title="Mult. Quat",v.desc="rotate quaternion",v.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(this._value,a,b),this.setOutputData(0,a))}},x.registerNodeType("math3d/mult-quat",v),v=function(){this.addInputs([["A","quat"],["B","quat"],["factor","number"]]);this.addOutput("slerp","quat");this.addProperty("factor", -0.5);this._value=quat.create()},v.title="Quat Slerp",v.desc="quaternion spherical interpolation",v.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a){var b=this.getInputData(1);if(null!=b){var c=this.properties.factor;null!=this.getInputData(2)&&(c=this.getInputData(2));a=quat.slerp(this._value,a,b,c);this.setOutputData(0,a)}}},x.registerNodeType("math3d/quat-slerp",v))})(this); -(function(v){function h(){this.addInput("sel","boolean");this.addOutput("value","number");this.properties={A:0,B:1};this.size=[60,20]}v=v.LiteGraph;h.title="Selector";h.desc="outputs A if selector is true, B if selector is false";h.prototype.onExecute=function(){var f=this.getInputData(0);if(void 0!==f){for(var h=1;hb;++b){var f=this.getInputData(b);if(null!=f){var a=this.values[b];a.push(f);a.length>d[0]&&a.shift()}}}};h.prototype.onDrawBackground=function(d){if(!this.flags.collapsed){var b=this.size,f=0.5*b[1]/this.properties.scale,a=h.colors,c=0.5*b[1];d.fillStyle="#000";d.fillRect(0,0,b[0],b[1]);d.strokeStyle= -"#555";d.beginPath();d.moveTo(0,c);d.lineTo(b[0],c);d.stroke();if(this.inputs)for(var e=0;4>e;++e){var k=this.values[e];if(this.inputs[e]&&this.inputs[e].link){d.strokeStyle=a[e];d.beginPath();var g=k[0]*f*-1+c;d.moveTo(0,Math.clamp(g,0,b[1]));for(var l=1;lb&&(b=0);if(0!=d.length){var f=[0,0,0];if(0==b)f=d[0];else if(1==b)f=d[d.length-1];else{var a=(d.length-1)*b,b=d[Math.floor(a)],d=d[Math.floor(a)+1],a=a-Math.floor(a);f[0]=b[0]*(1-a)+d[0]*a;f[1]=b[1]*(1-a)+d[1]*a;f[2]=b[2]*(1-a)+d[2]*a}for(var c in f)f[c]/=255;this.boxcolor=colorToString(f);this.setOutputData(0,f)}};k.registerNodeType("color/palette", -q);d.title="Frame";d.desc="Frame viewerew";d.widgets=[{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}];d.prototype.onDrawBackground=function(d){this.frame&&d.drawImage(this.frame,0,0,this.size[0],this.size[1])};d.prototype.onExecute=function(){this.frame=this.getInputData(0);this.setDirtyCanvas(!0)};d.prototype.onWidget=function(d,b){if("resize"==b.name&&this.frame){var f=this.frame.width,a=this.frame.height;f||null==this.frame.videoWidth||(f=this.frame.videoWidth, -a=this.frame.videoHeight);f&&a&&(this.size=[f,a]);this.setDirtyCanvas(!0,!0)}else"view"==b.name&&this.show()};d.prototype.show=function(){showElement&&this.frame&&showElement(this.frame)};k.registerNodeType("graphics/frame",d);r.title="Image fade";r.desc="Fades between images";r.widgets=[{name:"resizeA",text:"Resize to A",type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}];r.prototype.onAdded=function(){this.createCanvas();var d=this.canvas.getContext("2d");d.fillStyle="#000";d.fillRect(0, -0,this.properties.width,this.properties.height)};r.prototype.createCanvas=function(){this.canvas=document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height};r.prototype.onExecute=function(){var d=this.canvas.getContext("2d");this.canvas.width=this.canvas.width;var b=this.getInputData(0);null!=b&&d.drawImage(b,0,0,this.canvas.width,this.canvas.height);b=this.getInputData(2);null==b?b=this.properties.fade:this.properties.fade=b;d.globalAlpha=b; -b=this.getInputData(1);null!=b&&d.drawImage(b,0,0,this.canvas.width,this.canvas.height);d.globalAlpha=1;this.setOutputData(0,this.canvas);this.setDirtyCanvas(!0)};k.registerNodeType("graphics/imagefade",r);t.title="Crop";t.desc="Crop Image";t.prototype.onAdded=function(){this.createCanvas()};t.prototype.createCanvas=function(){this.canvas=document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height};t.prototype.onExecute=function(){var d=this.getInputData(0); -d&&(d.width?(this.canvas.getContext("2d").drawImage(d,-this.properties.x,-this.properties.y,d.width*this.properties.scale,d.height*this.properties.scale),this.setOutputData(0,this.canvas)):this.setOutputData(0,null))};t.prototype.onDrawBackground=function(d){this.flags.collapsed||this.canvas&&d.drawImage(this.canvas,0,0,this.canvas.width,this.canvas.height,0,0,this.size[0],this.size[1])};t.prototype.onPropertyChanged=function(d,b){this.properties[d]=b;"scale"==d?(this.properties[d]=parseFloat(b), -0==this.properties[d]&&(this.trace("Error in scale"),this.properties[d]=1)):this.properties[d]=parseInt(b);this.createCanvas();return!0};k.registerNodeType("graphics/cropImage",t);w.title="Video";w.desc="Video playback";w.widgets=[{name:"play",text:"PLAY",type:"minibutton"},{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}];w.prototype.onExecute=function(){if(this.properties.url&&(this.properties.url!=this._video_url&& -this.loadVideo(this.properties.url),this._video&&0!=this._video.width)){var d=this.getInputData(0);d&&0<=d&&1>=d&&(this._video.currentTime=d*this._video.duration,this._video.pause());this._video.dirty=!0;this.setOutputData(0,this._video);this.setOutputData(1,this._video.currentTime);this.setOutputData(2,this._video.duration);this.setDirtyCanvas(!0)}};w.prototype.onStart=function(){this.play()};w.prototype.onStop=function(){this.stop()};w.prototype.loadVideo=function(d){this._video_url=d;this.properties.use_proxy&& -"http"==d.substr(0,4)&&k.proxy&&(d=k.proxy+d.substr(d.indexOf(":")+3));this._video=document.createElement("video");this._video.src=d;this._video.type="type=video/mp4";this._video.muted=!0;this._video.autoplay=!0;var b=this;this._video.addEventListener("loadedmetadata",function(d){b.trace("Duration: "+this.duration+" seconds");b.trace("Size: "+this.videoWidth+","+this.videoHeight);b.setDirtyCanvas(!0);this.width=this.videoWidth;this.height=this.videoHeight});this._video.addEventListener("progress", -function(b){});this._video.addEventListener("error",function(d){console.log("Error loading video: "+this.src);b.trace("Error loading video: "+this.src);if(this.error)switch(this.error.code){case this.error.MEDIA_ERR_ABORTED:b.trace("You stopped the video.");break;case this.error.MEDIA_ERR_NETWORK:b.trace("Network error - please try again later.");break;case this.error.MEDIA_ERR_DECODE:b.trace("Video is broken..");break;case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED:b.trace("Sorry, your browser can't play this video.")}}); -this._video.addEventListener("ended",function(d){b.trace("Ended.");this.play()})};w.prototype.onPropertyChanged=function(d,b){this.properties[d]=b;"url"==d&&""!=b&&this.loadVideo(b);return!0};w.prototype.play=function(){this._video&&this._video.play()};w.prototype.playPause=function(){this._video&&(this._video.paused?this.play():this.pause())};w.prototype.stop=function(){this._video&&(this._video.pause(),this._video.currentTime=0)};w.prototype.pause=function(){this._video&&(this.trace("Video paused"), -this._video.pause())};w.prototype.onWidget=function(d,b){};k.registerNodeType("graphics/video",w);u.title="Webcam";u.desc="Webcam image";u.prototype.openStream=function(){function d(f){console.log("Webcam rejected",f);b._webcam_stream=!1;b.boxcolor="red";b.trigger("stream_error")}if(navigator.getUserMedia){this._waiting_confirmation=!0;navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:this.properties.facingMode}}).then(this.streamReady.bind(this))["catch"](d);var b=this}};u.prototype.closeStream= -function(){if(this._webcam_stream){var d=this._webcam_stream.getTracks();if(d.length)for(var b=0;b=this.size[1]||!this.properties.show||!this._video||(d.save(),d.drawImage(this._video,0,0,this.size[0],this.size[1]),d.restore())};u.prototype.onGetOutputs=function(){return[["width", -"number"],["height","number"],["stream_ready",k.EVENT],["stream_closed",k.EVENT],["stream_error",k.EVENT]]};k.registerNodeType("graphics/webcam",u)})(this); -(function(v){var h=v.LiteGraph;v.LGraphTexture=null;if("undefined"!=typeof GL){LGraphCanvas.link_type_colors.Texture="#AEF";var f=function(){this.addOutput("Texture","Texture");this.properties={name:"",filter:!0};this.size=[f.image_preview_size,f.image_preview_size]};v.LGraphTexture=f;f.title="Texture";f.desc="Texture";f.widgets_info={name:{widget:"texture"},filter:{widget:"checkbox"}};f.loadTextureCallback=null;f.image_preview_size=256;f.PASS_THROUGH=1;f.COPY=2;f.LOW=3;f.HIGH=4;f.REUSE=5;f.DEFAULT= -2;f.MODE_VALUES={"pass through":f.PASS_THROUGH,copy:f.COPY,low:f.LOW,high:f.HIGH,reuse:f.REUSE,"default":f.DEFAULT};f.getTexturesContainer=function(){return gl.textures};f.loadTexture=function(a,b){b=b||{};var c=a;"http://"==c.substr(0,7)&&h.proxy&&(c=h.proxy+c.substr(7));return f.getTexturesContainer()[a]=GL.Texture.fromURL(c,b)};f.getTexture=function(a){var b=this.getTexturesContainer();if(!b)throw"Cannot load texture, container of textures not found";b=b[a];return!b&&a&&":"!=a[0]?this.loadTexture(a): -b};f.getTargetTexture=function(a,b,c){if(!a)throw"LGraphTexture.getTargetTexture expects a reference texture";var d=null;switch(c){case f.LOW:d=gl.UNSIGNED_BYTE;break;case f.HIGH:d=gl.HIGH_PRECISION_FORMAT;break;case f.REUSE:return a;default:d=a?a.type:gl.UNSIGNED_BYTE}b&&b.width==a.width&&b.height==a.height&&b.type==d||(b=new GL.Texture(a.width,a.height,{type:d,format:gl.RGBA,filter:gl.LINEAR}));return b};f.getTextureType=function(a,b){var c=b?b.type:gl.UNSIGNED_BYTE;switch(a){case f.HIGH:c=gl.HIGH_PRECISION_FORMAT; -break;case f.LOW:c=gl.UNSIGNED_BYTE}return c};f.getNoiseTexture=function(){if(this._noise_texture)return this._noise_texture;for(var a=new Uint8Array(1048576),b=0;1048576>b;++b)a[b]=255*Math.random();return this._noise_texture=a=GL.Texture.fromMemory(512,512,a,{format:gl.RGBA,wrap:gl.REPEAT,filter:gl.NEAREST})};f.prototype.onDropFile=function(a,b,c){if(a){var d=null;"string"==typeof a?d=GL.Texture.fromURL(a):-1!=b.toLowerCase().indexOf(".dds")?d=GL.Texture.fromDDSInMemory(a):(a=new Blob([c]),a=URL.createObjectURL(a), -d=GL.Texture.fromURL(a));this._drop_texture=d;this.properties.name=b}else this._drop_texture=null,this.properties.name=""};f.prototype.getExtraMenuOptions=function(a){var b=this;if(this._drop_texture)return[{content:"Clear",callback:function(){b._drop_texture=null;b.properties.name=""}}]};f.prototype.onExecute=function(){var a=null;this.isOutputConnected(1)&&(a=this.getInputData(0));!a&&this._drop_texture&&(a=this._drop_texture);!a&&this.properties.name&&(a=f.getTexture(this.properties.name));if(a){this._last_tex= -a;!1===this.properties.filter?a.setParameter(gl.TEXTURE_MAG_FILTER,gl.NEAREST):a.setParameter(gl.TEXTURE_MAG_FILTER,gl.LINEAR);this.setOutputData(0,a);for(var b=1;b=this.size[1]))if(this._drop_texture&&a.webgl)a.drawImage(this._drop_texture,0,0,this.size[0],this.size[1]);else{if(this._last_preview_tex!=this._last_tex)if(a.webgl)this._canvas=this._last_tex;else{var b=f.generateLowResTexturePreview(this._last_tex);if(!b)return;this._last_preview_tex=this._last_tex;this._canvas=cloneCanvas(b)}this._canvas&&(a.save(),a.webgl||(a.translate(0,this.size[1]),a.scale(1,-1)),a.drawImage(this._canvas,0,0,this.size[0],this.size[1]),a.restore())}};f.generateLowResTexturePreview= -function(a){if(!a)return null;var b=f.image_preview_size,c=a;if(a.format==gl.DEPTH_COMPONENT)return null;if(a.width>b||a.height>b)c=this._preview_temp_tex,this._preview_temp_tex||(this._preview_temp_tex=c=new GL.Texture(b,b,{minFilter:gl.NEAREST})),a.copyTo(c);a=this._preview_canvas;a||(this._preview_canvas=a=createCanvas(b,b));c&&c.toCanvas(a);return a};f.prototype.getResources=function(a){a[this.properties.name]=GL.Texture;return a};f.prototype.onGetInputs=function(){return[["in","Texture"]]};f.prototype.onGetOutputs= -function(){return[["width","number"],["height","number"],["aspect","number"]]};h.registerNodeType("texture/texture",f);var q=function(){this.addInput("Texture","Texture");this.properties={flipY:!1};this.size=[f.image_preview_size,f.image_preview_size]};q.title="Preview";q.desc="Show a texture in the graph canvas";q.allow_preview=!1;q.prototype.onDrawBackground=function(a){if(!this.flags.collapsed&&(a.webgl||q.allow_preview)){var b=this.getInputData(0);if(b){var c=null,c=!b.handle&&a.webgl?b:f.generateLowResTexturePreview(b); -a.save();this.properties.flipY&&(a.translate(0,this.size[1]),a.scale(1,-1));a.drawImage(c,0,0,this.size[0],this.size[1]);a.restore()}}};h.registerNodeType("texture/preview",q);var d=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={name:""}};d.title="Save";d.desc="Save a texture in the repository";d.prototype.onExecute=function(){var a=this.getInputData(0);a&&(this.properties.name&&(f.storeTexture?f.storeTexture(this.properties.name,a):f.getTexturesContainer()[this.properties.name]= -a),this.setOutputData(0,a))};h.registerNodeType("texture/save",d);var r=function(){this.addInput("Texture","Texture");this.addInput("TextureB","Texture");this.addInput("value","number");this.addOutput("Texture","Texture");this.help="

pixelcode must be vec3

\t\t\t

uvcode must be vec2, is optional

\t\t\t

uv: tex. coords

color: texture

colorB: textureB

time: scene time

value: input value

"; -this.properties={value:1,uvcode:"",pixelcode:"color + colorB * value",precision:f.DEFAULT}};r.widgets_info={uvcode:{widget:"textarea",height:100},pixelcode:{widget:"textarea",height:100},precision:{widget:"combo",values:f.MODE_VALUES}};r.title="Operation";r.desc="Texture shader operation";r.prototype.getExtraMenuOptions=function(a){var b=this;return[{content:b.properties.show?"Hide Texture":"Show Texture",callback:function(){b.properties.show=!b.properties.show}}]};r.prototype.onDrawBackground=function(a){this.flags.collapsed|| -20>=this.size[1]||!this.properties.show||!this._tex||this._tex.gl!=a||(a.save(),a.drawImage(this._tex,0,0,this.size[0],this.size[1]),a.restore())};r.prototype.onExecute=function(){var a=this.getInputData(0);if(this.isOutputConnected(0))if(this.properties.precision===f.PASS_THROUGH)this.setOutputData(0,a);else{var b=this.getInputData(1);if(this.properties.uvcode||this.properties.pixelcode){var c=512,d=512;a?(c=a.width,d=a.height):b&&(c=b.width,d=b.height);var e=f.getTextureType(this.properties.precision, -a);this._tex=a||this._tex?f.getTargetTexture(a||this._tex,this._tex,this.properties.precision):new GL.Texture(c,d,{type:e,format:gl.RGBA,filter:gl.LINEAR});e="";this.properties.uvcode&&(e="uv = "+this.properties.uvcode,-1!=this.properties.uvcode.indexOf(";")&&(e=this.properties.uvcode));var g="";this.properties.pixelcode&&(g="result = "+this.properties.pixelcode,-1!=this.properties.pixelcode.indexOf(";")&&(g=this.properties.pixelcode));var l=this._shader;if(!l||this._shader_code!=e+"|"+g){try{this._shader= -new GL.Shader(Shader.SCREEN_VERTEX_SHADER,r.pixel_shader,{UV_CODE:e,PIXEL_CODE:g}),this.boxcolor="#00FF00"}catch(h){console.log("Error compiling shader: ",h);this.boxcolor="#FF0000";return}this.boxcolor="#FF0000";this._shader_code=e+"|"+g;l=this._shader}if(l){this.boxcolor="green";var k=this.getInputData(2);null!=k?this.properties.value=k:k=parseFloat(this.properties.value);var m=this.graph.getTime();this._tex.drawTo(function(){gl.disable(gl.DEPTH_TEST);gl.disable(gl.CULL_FACE);gl.disable(gl.BLEND); -a&&a.bind(0);b&&b.bind(1);var e=Mesh.getScreenQuad();l.uniforms({u_texture:0,u_textureB:1,value:k,texSize:[c,d],time:m}).draw(e)});this.setOutputData(0,this._tex)}else this.boxcolor="red"}}};r.pixel_shader="precision highp float;\n\t\t\t\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform vec2 texSize;\n\t\t\tuniform float time;\n\t\t\tuniform float value;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 uv = v_coord;\n\t\t\t\tUV_CODE;\n\t\t\t\tvec4 color4 = texture2D(u_texture, uv);\n\t\t\t\tvec3 color = color4.rgb;\n\t\t\t\tvec4 color4B = texture2D(u_textureB, uv);\n\t\t\t\tvec3 colorB = color4B.rgb;\n\t\t\t\tvec3 result = color;\n\t\t\t\tfloat alpha = 1.0;\n\t\t\t\tPIXEL_CODE;\n\t\t\t\tgl_FragColor = vec4(result, alpha);\n\t\t\t}\n\t\t\t"; -h.registerNodeType("texture/operation",r);var t=function(){this.addOutput("out","Texture");this.properties={code:"",width:512,height:512,precision:f.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}};t.title="Shader";t.desc="Texture shader";t.widgets_info={code:{type:"code"},precision:{widget:"combo",values:f.MODE_VALUES}};t.prototype.onPropertyChanged= -function(a,b){if("code"==a){var c=this.getShader();if(c){var d=c.uniformInfo;if(this.inputs)for(var e={},g=0;g> ";b.fillText(f+c.getTitle(),0.5*a.width,40);b.restore()}c=!1;this.onRenderBackground&&(c=this.onRenderBackground(a,b));b.restore();b.setTransform(1, +0,0,1,0,0);if(this.graph){b.save();b.scale(this.scale,this.scale);b.translate(this.offset[0],this.offset[1]);if(this.background_image&&0.5this.scale?b.fillRect(m[0],m[1],m[2],m[3]):n==k.ROUND_SHAPE||n==k.CARD_SHAPE?b.roundRect(m[0],m[1],m[2],m[3],this.round_radius,n==k.CARD_SHAPE?0:this.round_radius):n==k.CIRCLE_SHAPE&&b.arc(0.5*c[0],0.5*c[1],0.5*c[0],0,2*Math.PI),b.fill());b.shadowColor="transparent";a.bgImage&&a.bgImage.width&&b.drawImage(a.bgImage,0.5*(c[0]-a.bgImage.width), +0.5*(c[1]-a.bgImage.height));a.bgImageUrl&&!a.bgImage&&(a.bgImage=a.loadImage(a.bgImageUrl));if(a.onDrawBackground)a.onDrawBackground(b,this,this.canvas);if(e||h==k.TRANSPARENT_TITLE){if(h!=k.TRANSPARENT_TITLE){a.flags.collapsed&&(b.shadowColor=k.DEFAULT_SHADOW_COLOR);this.use_gradients?(q=d.gradients[f],q||(q=d.gradients[f]=b.createLinearGradient(0,0,400,0),q.addColorStop(0,f),q.addColorStop(1,"#000")),b.fillStyle=q):b.fillStyle=f;var w=b.globalAlpha;b.beginPath();n==k.BOX_SHAPE||0.5>this.scale? +b.rect(0,-g,c[0]+1,g):n!=k.ROUND_SHAPE&&n!=k.CARD_SHAPE||b.roundRect(0,-g,c[0]+1,g,this.round_radius,a.flags.collapsed?this.round_radius:0);b.fill();b.shadowColor="transparent"}!1!==a.flags.render_box&&(n==k.ROUND_SHAPE||n==k.CIRCLE_SHAPE||n==k.CARD_SHAPE?(0.5f[2]&&(f[0]+=f[2],f[2]=Math.abs(f[2]));0>f[3]&&(f[1]+=f[3],f[3]=Math.abs(f[3]));if(t(f,c)){var G=r.outputs[s],s=m.inputs[e];if(G&&s&&(r=G.dir||(r.flags.horizontal?k.DOWN:k.RIGHT),s=s.dir||(m.flags.horizontal?k.UP:k.LEFT),this.renderLink(a,x,D,p,!1,0,null,r,s),p&&p._last_time&&1E3>b-p._last_time)){var G=2-0.002*(b-p._last_time), +H=a.globalAlpha;a.globalAlpha=H*G;this.renderLink(a,x,D,p,!0,G,"white",r,s);a.globalAlpha=H}}}}}}a.globalAlpha=1};d.prototype.renderLink=function(a,b,c,f,g,l,q,n,h){if(this.highquality_render){n=n||k.RIGHT;h=h||k.LEFT;var m=s(b,c);this.render_connections_border&&0.6b[1]?0:Math.PI,a.save(),a.translate(g[0],g[1]),a.rotate(m),a.beginPath(),a.moveTo(-5,-5),a.lineTo(0,5),a.lineTo(5,-5),a.fill(),a.restore()); +if(l)for(l=0;5>l;++l)g=(0.001*k.getTime()+0.2*l)%1,g=this.computeConnectionPoint(b,c,g,n,h),a.beginPath(),a.arc(g[0],g[1],5,0,2*Math.PI),a.fill()}else a.beginPath(),a.moveTo(b[0],b[1]),a.lineTo(c[0],c[1]),a.stroke()};d.prototype.computeConnectionPoint=function(a,b,c,f,g){f=f||k.RIGHT;g=g||k.LEFT;var l=s(a,b),d=[a[0],a[1]],n=[b[0],b[1]];switch(f){case k.LEFT:d[0]+=-0.25*l;break;case k.RIGHT:d[0]+=0.25*l;break;case k.UP:d[1]+=-0.25*l;break;case k.DOWN:d[1]+=0.25*l}switch(g){case k.LEFT:n[0]+=-0.25* +l;break;case k.RIGHT:n[0]+=0.25*l;break;case k.UP:n[1]+=-0.25*l;break;case k.DOWN:n[1]+=0.25*l}f=(1-c)*(1-c)*(1-c);g=3*(1-c)*(1-c)*c;l=3*(1-c)*c*c;c*=c*c;return[f*a[0]+g*d[0]+l*n[0]+c*b[0],f*a[1]+g*d[1]+l*n[1]+c*b[1]]};d.prototype.drawExecutionOrder=function(a){a.shadowColor="transparent";a.globalAlpha=0.25;a.textAlign="center";a.strokeStyle="white";a.globalAlpha=0.75;for(var b=this.visible_nodes,c=0;ce.last_y&&le.options.max&&(e.value=e.options.max);else if("mousedown"==c.type)if((f=e.options.values)&&f.constructor===Function&&(f=e.options.values(e,a)),g=40>g?-1:g>d-40?1:0,"number"==e.type)e.value+=0.1*g*(e.options.step||1),null!=e.options.min&&e.valuee.options.max&&(e.value=e.options.max);else if(g)c=f.indexOf(e.value)+g,c>=f.length&&(c=0),0>c&&(c=f.length-1),e.value=f[c];else{new k.ContextMenu(f,{event:c,className:"dark",callback:p.bind(e)},n);var p=function(a,b,c){this.value=a;m.dirty_canvas=!0;return!1}}e.callback&&setTimeout(function(){this.callback(this.value,m,a,b)}.bind(e),20);this.dirty_canvas=!0;break;case "toggle":"mousedown"==c.type&&(e.value=!e.value,e.callback&&setTimeout(function(){e.callback(e.value, +m,a,b)},20));break;case "string":case "text":"mousedown"==c.type&&this.prompt("Value",e.value,function(b){this.value=b;e.callback&&e.callback(b,m,a)}.bind(e),c);break;default:e.mouse&&e.mouse(ctx,c,[g,l],a)}return e}}return null};d.prototype.drawGroups=function(a,b){if(this.graph){var c=this.graph._groups;b.save();b.globalAlpha=0.5*this.editor_alpha;for(var f=0;fc&&0.01>b.editor_alpha&&(clearInterval(f),1>c&&(b.live_mode=!0));1"+n+""+a+"",value:n});if(m.length)return new k.ContextMenu(m,{event:c,callback:l,parentMenu:f,allow_html:!0,node:g},b),!1}};d.decodeHTML=function(a){var b=document.createElement("div");b.innerText=a;return b.innerHTML};d.onResizeNode=function(a,b,c,f,g){g&&(g.size=g.computeSize(), +g.setDirtyCanvas(!0,!0))};d.onShowPropertyEditor=function(a,b,c,f,g){function l(){var b=n.value;"Number"==a.type?b=Number(b):"Boolean"==a.type&&(b=Boolean(b));g[e]=b;m.parentNode.removeChild(m);g.setDirtyCanvas(!0,!0)}var e=a.property||"title";b=g[e];var m=document.createElement("div");m.className="graphdialog";m.innerHTML="";m.querySelector(".name").innerText=e;var n=m.querySelector("input");n&&(n.value=b,n.addEventListener("blur", +function(a){this.focus()}),n.addEventListener("keydown",function(a){13==a.keyCode&&(l(),a.preventDefault(),a.stopPropagation())}));b=d.active_canvas.canvas;c=b.getBoundingClientRect();var k=f=-20;c&&(f-=c.left,k-=c.top);event?(m.style.left=event.pageX+f+"px",m.style.top=event.pageY+k+"px"):(m.style.left=0.5*b.width+f+"px",m.style.top=0.5*b.height+k+"px");m.querySelector("button").addEventListener("click",l);b.parentNode.appendChild(m)};d.prototype.prompt=function(a,b,c,f){var g=this;a=a||"";var l= +document.createElement("div");l.className="graphdialog rounded";l.innerHTML=" ";l.close=function(){g.prompt_box=null;l.parentNode.removeChild(l)};l.addEventListener("mouseleave",function(a){l.close()});g.prompt_box&&g.prompt_box.close();g.prompt_box=l;l.querySelector(".name").innerText=a;l.querySelector(".value").value=b;var m=l.querySelector("input");m.addEventListener("keydown",function(a){if(27== +a.keyCode)l.close();else if(13==a.keyCode)c&&c(this.value),l.close();else return;a.preventDefault();a.stopPropagation()});l.querySelector("button").addEventListener("click",function(a){c&&c(m.value);g.setDirty(!0);l.close()});a=d.active_canvas.canvas;b=a.getBoundingClientRect();var e=-20,n=-20;b&&(e-=b.left,n-=b.top);f?(l.style.left=f.pageX+e+"px",l.style.top=f.pageY+n+"px"):(l.style.left=0.5*a.width+e+"px",l.style.top=0.5*a.height+n+"px");a.parentNode.appendChild(l);setTimeout(function(){m.focus()}, +10);return l};d.search_limit=-1;d.prototype.showSearchBox=function(a){function b(b){if(b)if(g.onSearchBoxSelection)g.onSearchBoxSelection(b,a,r);else{var c=k.searchbox_extras[b];c&&(b=c.type);if(b=k.createNode(b))b.pos=r.convertEventToCanvas(a),r.graph.add(b);if(c&&c.data){if(c.data.properties)for(var f in c.data.properties)b.addProperty(c.data.properties[f][0],c.data.properties[f][0]);if(c.data.inputs)for(f in b.inputs=[],c.data.inputs)b.addOutput(c.data.inputs[f][0],c.data.inputs[f][1]);if(c.data.outputs)for(f in b.outputs= +[],c.data.outputs)b.addOutput(c.data.outputs[f][0],c.data.outputs[f][1]);c.data.title&&(b.title=c.data.title);c.data.json&&b.configure(c.data.json)}}l.close()}function c(a){var b=h;h&&h.classList.remove("selected");h?(h=a?h.nextSibling:h.previousSibling)||(h=b):h=a?m.childNodes[0]:m.childNodes[m.childNodes.length];h&&(h.classList.add("selected"),h.scrollIntoView())}function f(){function a(c,f){var g=document.createElement("div");e||(e=c);g.innerText=c;g.dataset.type=escape(c);g.className="litegraph lite-search-item"; +f&&(g.className+=" "+f);g.addEventListener("click",function(a){b(unescape(this.dataset.type))});m.appendChild(g)}n=null;var c=p.value;e=null;m.innerHTML="";if(c)if(g.onSearchBox){var f=g.onSearchBox(help,c,r);if(f)for(var l=0;ld.search_limit))break}if(Array.prototype.filter)for(D=Object.keys(k.registered_node_types).filter(function(a){return-1!== +a.toLowerCase().indexOf(c)}),l=0;ld.search_limit);l++);else for(l in k.registered_node_types)if(-1!=l.indexOf(c)&&(a(l),-1!==d.search_limit&&f++>d.search_limit))break}}var g=this,l=document.createElement("div");l.className="litegraph litesearchbox graphdialog rounded";l.innerHTML="Search
";l.close=function(){g.search_box=null;l.parentNode.removeChild(l)}; +l.addEventListener("mouseleave",function(a){l.close()});g.search_box&&g.search_box.close();g.search_box=l;var m=l.querySelector(".helper"),e=null,n=null,h=null,p=l.querySelector("input");p&&(p.addEventListener("blur",function(a){this.focus()}),p.addEventListener("keydown",function(a){if(38==a.keyCode)c(!1);else if(40==a.keyCode)c(!0);else if(27==a.keyCode)l.close();else if(13==a.keyCode)h?b(h.innerHTML):e?b(e):l.close();else{n&&clearInterval(n);n=setTimeout(f,10);return}a.preventDefault();a.stopPropagation()})); +var r=d.active_canvas,s=r.canvas,t=s.getBoundingClientRect(),x=-20,D=-20;t&&(x-=t.left,D-=t.top);a?(l.style.left=a.pageX+x+"px",l.style.top=a.pageY+D+"px"):(l.style.left=0.5*s.width+x+"px",l.style.top=0.5*s.height+D+"px");s.parentNode.appendChild(l);p.focus();return l};d.prototype.showEditPropertyValue=function(a,b,c){function f(){g(k.value)}function g(c){"number"==typeof a.properties[b]&&(c=Number(c));"array"==l&&(c=c.split(",").map(Number));a.properties[b]=c;a._graph&&a._graph._version++;if(a.onPropertyChanged)a.onPropertyChanged(b, +c);h.close();a.setDirtyCanvas(!0,!0)}if(a&&void 0!==a.properties[b]){c=c||{};var l="string";null!==a.properties[b]&&(l=typeof a.properties[b]);"object"==l&&a.properties[b].length&&(l="array");var d=null;a.getPropertyInfo&&(d=a.getPropertyInfo(b));if(a.properties_info)for(var m=0;m"; +else if("enum"==l&&d.values){e=""}else if("boolean"==l)e="";else{console.warn("unknown type: "+l);return}var h=this.createDialog(""+b+""+e+"",c);if("enum"== +l&&d.values){var k=h.querySelector("select");k.addEventListener("change",function(a){g(a.target.value)})}else if("boolean"==l)(k=h.querySelector("input"))&&k.addEventListener("click",function(a){g(!!k.checked)});else if(k=h.querySelector("input"))k.addEventListener("blur",function(a){this.focus()}),k.value=void 0!==a.properties[b]?a.properties[b]:"",k.addEventListener("keydown",function(a){13==a.keyCode&&(f(),a.preventDefault(),a.stopPropagation())});h.querySelector("button").addEventListener("click", +f)}};d.prototype.createDialog=function(a,b){b=b||{};var c=document.createElement("div");c.className="graphdialog";c.innerHTML=a;var f=this.canvas.getBoundingClientRect(),g=-20,l=-20;f&&(g-=f.left,l-=f.top);b.position?(g+=b.position[0],l+=b.position[1]):b.event?(g+=b.event.pageX,l+=b.event.pageY):(g+=0.5*this.canvas.width,l+=0.5*this.canvas.height);c.style.left=g+"px";c.style.top=l+"px";this.canvas.parentNode.appendChild(c);c.close=function(){this.parentNode&&this.parentNode.removeChild(this)};return c}; +d.onMenuNodeCollapse=function(a,b,c,f,g){g.collapse()};d.onMenuNodePin=function(a,b,c,f,g){g.pin()};d.onMenuNodeMode=function(a,b,c,f,g){new k.ContextMenu(["Always","On Event","On Trigger","Never"],{event:c,callback:function(a){if(g)switch(a){case "On Event":g.mode=k.ON_EVENT;break;case "On Trigger":g.mode=k.ON_TRIGGER;break;case "Never":g.mode=k.NEVER;break;default:g.mode=k.ALWAYS}},parentMenu:f,node:g});return!1};d.onMenuNodeColors=function(a,b,c,f,g){if(!g)throw"no node for color";b=[];b.push({value:null, +content:"No color"});for(var l in d.node_colors)a=d.node_colors[l],a={value:l,content:""+l+""},b.push(a);new k.ContextMenu(b,{event:c,callback:function(a){g&&((a=a.value?d.node_colors[a.value]:null)?g.constructor===k.LGraphGroup?g.color=a.groupcolor:(g.color=a.color,g.bgcolor=a.bgcolor):(delete g.color,delete g.bgcolor), +g.setDirtyCanvas(!0,!0))},parentMenu:f,node:g});return!1};d.onMenuNodeShapes=function(a,b,c,f,g){if(!g)throw"no node passed";new k.ContextMenu(k.VALID_SHAPES,{event:c,callback:function(a){g&&(g.shape=a,g.setDirtyCanvas(!0))},parentMenu:f,node:g});return!1};d.onMenuNodeRemove=function(a,b,c,f,g){if(!g)throw"no node passed";!1!==g.removable&&(g.graph.remove(g),g.setDirtyCanvas(!0,!0))};d.onMenuNodeClone=function(a,b,c,f,g){!1!=g.clonable&&(a=g.clone())&&(a.pos=[g.pos[0]+5,g.pos[1]+5],g.graph.add(a), +g.setDirtyCanvas(!0,!0))};d.node_colors={red:{color:"#322",bgcolor:"#533",groupcolor:"#A88"},brown:{color:"#332922",bgcolor:"#593930",groupcolor:"#b06634"},green:{color:"#232",bgcolor:"#353",groupcolor:"#8A8"},blue:{color:"#223",bgcolor:"#335",groupcolor:"#88A"},pale_blue:{color:"#2a363b",bgcolor:"#3f5159",groupcolor:"#3f789e"},cyan:{color:"#233",bgcolor:"#355",groupcolor:"#8AA"},purple:{color:"#323",bgcolor:"#535",groupcolor:"#a1309b"},yellow:{color:"#432",bgcolor:"#653",groupcolor:"#b58b2a"},black:{color:"#222", +bgcolor:"#000",groupcolor:"#444"}};d.prototype.getCanvasMenuOptions=function(){var a=null;this.getMenuOptions?a=this.getMenuOptions():(a=[{content:"Add Node",has_submenu:!0,callback:d.onMenuAdd},{content:"Add Group",callback:d.onGroupAdd}],this._graph_stack&&0Name",f),m=d.querySelector("input");m&& +l&&(m.value=l.label);d.querySelector("button").addEventListener("click",function(a){m.value&&(l&&(l.label=m.value),c.setDirty(!0));d.close()})}},extra:a},m=null;a&&(m=a.getSlotInPosition(b.canvasX,b.canvasY),d.active_node=a);m?(g=[],m&&m.output&&m.output.links&&m.output.links.length&&g.push({content:"Disconnect Links",slot:m}),g.push(m.locked?"Cannot remove":{content:"Remove Slot",slot:m}),g.push(m.nameLocked?"Cannot rename":{content:"Rename Slot",slot:m}),l.title=(m.input?m.input.type:m.output.type)|| +"*",m.input&&m.input.type==k.ACTION&&(l.title="Action"),m.output&&m.output.type==k.EVENT&&(l.title="Event")):a?g=this.getNodeMenuOptions(a):(g=this.getCanvasMenuOptions(),(m=this.graph.getGroupOnPos(b.canvasX,b.canvasY))&&g.push(null,{content:"Edit Group",has_submenu:!0,submenu:{title:"Group",extra:m,options:this.getGroupMenuOptions(m)}}));g&&new k.ContextMenu(g,l,f)};this.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.roundRect=function(a,b,c,f,g,l){void 0===g&&(g=5);void 0===l&&(l= +g);this.moveTo(a+g,b);this.lineTo(a+c-g,b);this.quadraticCurveTo(a+c,b,a+c,b+g);this.lineTo(a+c,b+f-l);this.quadraticCurveTo(a+c,b+f,a+c-l,b+f);this.lineTo(a+l,b+f);this.quadraticCurveTo(a,b+f,a,b+f-l);this.lineTo(a,b+g);this.quadraticCurveTo(a,b,a+g,b)});k.compareObjects=function(a,b){for(var c in a)if(a[c]!=b[c])return!1;return!0};k.distance=s;k.colorToString=function(a){return"rgba("+Math.round(255*a[0]).toFixed()+","+Math.round(255*a[1]).toFixed()+","+Math.round(255*a[2]).toFixed()+","+(4==a.length? +a[3].toFixed(2):"1.0")+")"};k.isInsideRectangle=r;k.growBounding=function(a,b,c){ba[2]&&(a[2]=b);ca[3]&&(a[3]=c)};k.isInsideBounding=function(a,b){return a[0]b[1][0]||a[1]>b[1][1]?!1:!0};k.overlapBounding=t;k.hex2num=function(a){"#"==a.charAt(0)&&(a=a.slice(1));a=a.toUpperCase();for(var b=Array(3),c=0,f,g,l=0;6>l;l+=2)f="0123456789ABCDEF".indexOf(a.charAt(l)),g="0123456789ABCDEF".indexOf(a.charAt(l+1)),b[c]=16*f+g,c++;return b};k.num2hex= +function(a){for(var b="#",c,f,g=0;3>g;g++)c=a[g]/16,f=a[g]%16,b+="0123456789ABCDEF".charAt(c)+"0123456789ABCDEF".charAt(f);return b};y.prototype.addItem=function(a,b,c){function f(a){var b=this.value;b&&b.has_submenu&&g.call(this,a)}function g(a){var b=this.value,f=!0;l.current_submenu&&l.current_submenu.close(a);if(c.callback){var g=c.callback.call(this,b,c,a,l,c.node);!0===g&&(f=!1)}if(b&&(b.callback&&!c.ignore_item_callbacks&&!0!==b.disabled&&(g=b.callback.call(this,b,c,a,l,c.extra),!0===g&&(f= +!1)),b.submenu)){if(!b.submenu.options)throw"ContextMenu submenu needs options";new l.constructor(b.submenu.options,{callback:b.submenu.callback,event:a,parentMenu:l,ignore_item_callbacks:b.submenu.ignore_item_callbacks,title:b.submenu.title,extra:b.submenu.extra,autoopen:c.autoopen});f=!1}f&&!l.lock&&l.close()}var l=this;c=c||{};var d=document.createElement("div");d.className="litemenu-entry submenu";var m=!1;if(null===b)d.classList.add("separator");else{d.innerHTML=b&&b.title?b.title:a;if(d.value= +b)b.disabled&&(m=!0,d.classList.add("disabled")),(b.submenu||b.has_submenu)&&d.classList.add("has_submenu");"function"==typeof b?(d.dataset.value=a,d.onclick_callback=b):d.dataset.value=b;b.className&&(d.className+=" "+b.className)}this.root.appendChild(d);m||d.addEventListener("click",g);c.autoopen&&d.addEventListener("mouseenter",f);return d};y.prototype.close=function(a,b){this.root.parentNode&&this.root.parentNode.removeChild(this.root);this.parentMenu&&!b&&(this.parentMenu.lock=!1,this.parentMenu.current_submenu= +null,void 0===a?this.parentMenu.close():a&&!y.isCursorOverElement(a,this.parentMenu.root)&&y.trigger(this.parentMenu.root,"mouseleave",a));this.current_submenu&&this.current_submenu.close(a,!0);this.root.closing_timer&&clearTimeout(this.root.closing_timer)};y.trigger=function(a,b,c,f){var g=document.createEvent("CustomEvent");g.initCustomEvent(b,!0,!0,c);g.srcElement=f;a.dispatchEvent?a.dispatchEvent(g):a.__events&&a.__events.dispatchEvent(g);return g};y.prototype.getTopMenu=function(){return this.options.parentMenu? +this.options.parentMenu.getTopMenu():this};y.prototype.getFirstEvent=function(){return this.options.parentMenu?this.options.parentMenu.getFirstEvent():this.options.event};y.isCursorOverElement=function(a,b){var c=a.pageX,f=a.pageY,g=b.getBoundingClientRect();return g?f>g.top&&fg.left&&ca?b:cthis.size[0]-n.NODE_TITLE_HEIGHT&&0>a[1]){var c=this;setTimeout(function(){b.openSubgraph(c.subgraph)},10)}};h.prototype.onSubgraphNewGlobalInput=function(d,a){this.addInput(d,a)};h.prototype.onSubgraphRenamedGlobalInput=function(d,a){var b=this.findInputSlot(d);-1!=b&&(this.getInputInfo(b).name=a)};h.prototype.onSubgraphTypeChangeGlobalInput=function(d, +a){var b=this.findInputSlot(d);-1!=b&&(this.getInputInfo(b).type=a)};h.prototype.onSubgraphNewGlobalOutput=function(d,a){this.addOutput(d,a)};h.prototype.onSubgraphRenamedGlobalOutput=function(d,a){var b=this.findOutputSlot(d);-1!=b&&(this.getOutputInfo(b).name=a)};h.prototype.onSubgraphTypeChangeGlobalOutput=function(d,a){var b=this.findOutputSlot(d);-1!=b&&(this.getOutputInfo(b).type=a)};h.prototype.getExtraMenuOptions=function(d){var a=this;return[{content:"Open",callback:function(){d.openSubgraph(a.subgraph)}}]}; +h.prototype.onResize=function(d){d[1]+=20};h.prototype.onExecute=function(){if(this.inputs)for(var d=0;de[1]))return this.old_y=d.canvasY,this.captureInput(!0),this.mouse_captured=!0};p.prototype.onMouseMove=function(d){if(this.mouse_captured){var e=this.old_y-d.canvasY;d.shiftKey&&(e*=10);if(d.metaKey||d.altKey)e*=0.1;this.old_y=d.canvasY;d=this._remainder+e/p.pixels_threshold;this._remainder=d%1;d=Math.clamp(this.properties.value+(d|0)*this.properties.step,this.properties.min,this.properties.max);this.properties.value=d;this.graph._version++; +this.setDirtyCanvas(!0)}};p.prototype.onMouseUp=function(d,e){200>d.click_time&&(this.properties.value=Math.clamp(this.properties.value+(e[1]>0.5*this.size[1]?-1:1)*this.properties.step,this.properties.min,this.properties.max),this.graph._version++,this.setDirtyCanvas(!0));this.mouse_captured&&(this.mouse_captured=!1,this.captureInput(!1))};u.registerNodeType("widget/number",p);d.title="Knob";d.desc="Circular controller";d.widgets=[{name:"increase",text:"+",type:"minibutton"},{name:"decrease",text:"-", +type:"minibutton"}];d.prototype.onAdded=function(){this.value=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min);this.imgbg=this.loadImage("imgs/knob_bg.png");this.imgfg=this.loadImage("imgs/knob_fg.png")};d.prototype.onDrawImageKnob=function(d){if(this.imgfg&&this.imgfg.width){var e=0.5*this.imgbg.width,a=this.size[0]/this.imgfg.width;d.save();d.translate(0,20);d.scale(a,a);d.drawImage(this.imgbg,0,0);d.translate(e,e);d.rotate(2*this.value*Math.PI*6/8+10*Math.PI/ +8);d.translate(-e,-e);d.drawImage(this.imgfg,0,0);d.restore();this.title&&(d.font="bold 16px Criticized,Tahoma",d.fillStyle="rgba(100,100,100,0.8)",d.textAlign="center",d.fillText(this.title.toUpperCase(),0.5*this.size[0],18),d.textAlign="left")}};d.prototype.onDrawVectorKnob=function(d){if(this.imgfg&&this.imgfg.width){d.lineWidth=1;d.strokeStyle=this.mouseOver?"#FFF":"#AAA";d.fillStyle="#000";d.beginPath();d.arc(0.5*this.size[0],0.5*this.size[1]+10,0.5*this.properties.size,0,2*Math.PI,!0);d.stroke(); +0d.canvasY-this.pos[1]||u.distance([d.canvasX,d.canvasY],[this.pos[0]+this.center[0],this.pos[1]+this.center[1]])>this.radius)return!1;this.oldmouse=[d.canvasX-this.pos[0],d.canvasY-this.pos[1]];this.captureInput(!0); +return!0}};d.prototype.onMouseMove=function(d){if(this.oldmouse){d=[d.canvasX-this.pos[0],d.canvasY-this.pos[1]];var e=this.value,e=e-0.01*(d[1]-this.oldmouse[1]);1e&&(e=0);this.value=e;this.properties.value=this.properties.min+(this.properties.max-this.properties.min)*this.value;this.oldmouse=d;this.setDirtyCanvas(!0)}};d.prototype.onMouseUp=function(d){this.oldmouse&&(this.oldmouse=null,this.captureInput(!1))};d.prototype.onMouseLeave=function(d){};d.prototype.onPropertyChanged=function(d, +e){if("wcolor"==d)this.properties[d]=e;else if("size"==d)e=parseInt(e),this.properties[d]=e,this.size=[e+4,e+24],this.setDirtyCanvas(!0,!0);else if("min"==d||"max"==d||"value"==d)this.properties[d]=parseFloat(e);else return!1;return!0};u.registerNodeType("widget/knob",d);s.title="Internal Slider";s.prototype.onPropertyChanged=function(d,e){"value"==d&&(this.slider.value=e)};s.prototype.onExecute=function(){this.setOutputData(0,this.properties.value)};u.registerNodeType("widget/internal_slider",s); +r.title="H.Slider";r.desc="Linear slider controller";r.prototype.onAdded=function(){this.value=0.5;this.imgfg=this.loadImage("imgs/slider_fg.png")};r.prototype.onDrawVectorial=function(d){this.imgfg&&this.imgfg.width&&(d.lineWidth=1,d.strokeStyle=this.mouseOver?"#FFF":"#AAA",d.fillStyle="#000",d.beginPath(),d.rect(2,0,this.size[0]-4,20),d.stroke(),d.fillStyle=this.properties.wcolor,d.beginPath(),d.rect(2+(this.size[0]-4-20)*this.value,0,20,20),d.fill())};r.prototype.onDrawImage=function(d){this.imgfg&& +this.imgfg.width&&(d.lineWidth=1,d.fillStyle="#000",d.fillRect(2,9,this.size[0]-4,2),d.strokeStyle="#333",d.beginPath(),d.moveTo(2,9),d.lineTo(this.size[0]-4,9),d.stroke(),d.strokeStyle="#AAA",d.beginPath(),d.moveTo(2,11),d.lineTo(this.size[0]-4,11),d.stroke(),d.drawImage(this.imgfg,2+(this.size[0]-4)*this.value-0.5*this.imgfg.width,0.5*-this.imgfg.height+10))};r.prototype.onDrawForeground=function(d){this.onDrawImage(d)};r.prototype.onExecute=function(){this.properties.value=this.properties.min+ +(this.properties.max-this.properties.min)*this.value;this.setOutputData(0,this.properties.value);this.boxcolor=u.colorToString([this.value,this.value,this.value])};r.prototype.onMouseDown=function(d){if(0>d.canvasY-this.pos[1])return!1;this.oldmouse=[d.canvasX-this.pos[0],d.canvasY-this.pos[1]];this.captureInput(!0);return!0};r.prototype.onMouseMove=function(d){if(this.oldmouse){d=[d.canvasX-this.pos[0],d.canvasY-this.pos[1]];var e=this.value,e=e+(d[0]-this.oldmouse[0])/this.size[0];1e&& +(e=0);this.value=e;this.oldmouse=d;this.setDirtyCanvas(!0)}};r.prototype.onMouseUp=function(d){this.oldmouse=null;this.captureInput(!1)};r.prototype.onMouseLeave=function(d){};r.prototype.onPropertyChanged=function(d,e){if("wcolor"==d)this.properties[d]=e;else return!1;return!0};u.registerNodeType("widget/hslider",r);t.title="Progress";t.desc="Shows data in linear progress";t.prototype.onExecute=function(){var d=this.getInputData(0);void 0!=d&&(this.properties.value=d)};t.prototype.onDrawForeground= +function(d){d.lineWidth=1;d.fillStyle=this.properties.wcolor;var e=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min),e=Math.min(1,e),e=Math.max(0,e);d.fillRect(2,2,(this.size[0]-4)*e,this.size[1]-4)};u.registerNodeType("widget/progress",t);y.title="Text";y.desc="Shows the input value";y.widgets=[{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}];y.prototype.onDrawForeground= +function(d){d.fillStyle=this.properties.color;var e=this.properties.value;this.properties.glowSize?(d.shadowColor=this.properties.color,d.shadowOffsetX=0,d.shadowOffsetY=0,d.shadowBlur=this.properties.glowSize):d.shadowColor="transparent";var a=this.properties.fontsize;d.textAlign=this.properties.align;d.font=a.toString()+"px "+this.properties.font;this.str="number"==typeof e?e.toFixed(this.properties.decimals):e;if("string"==typeof this.str){var e=this.str.split("\\n"),b;for(b in e)d.fillText(e[b], +"left"==this.properties.align?15:this.size[0]-15,-0.15*a+a*(parseInt(b)+1))}d.shadowColor="transparent";this.last_ctx=d;d.textAlign="left"};y.prototype.onExecute=function(){var d=this.getInputData(0);null!=d&&(this.properties.value=d)};y.prototype.resize=function(){if(this.last_ctx){var d=this.str.split("\\n");this.last_ctx.font=this.properties.fontsize+"px "+this.properties.font;var e=0,a;for(a in d){var b=this.last_ctx.measureText(d[a]).width;ed?h.xbox.axes.lx:0,this._left_axis[1]=Math.abs(h.xbox.axes.ly)>d?h.xbox.axes.ly:0,this._right_axis[0]=Math.abs(h.xbox.axes.rx)>d?h.xbox.axes.rx:0,this._right_axis[1]=Math.abs(h.xbox.axes.ry)>d?h.xbox.axes.ry:0,this._triggers[0]=Math.abs(h.xbox.axes.ltrigger)>d?h.xbox.axes.ltrigger:0,this._triggers[1]=Math.abs(h.xbox.axes.rtrigger)>d?h.xbox.axes.rtrigger:0);if(this.outputs)for(d= +0;de;e++)if(d[e]){e=d[e];d=this.xbox_mapping;d||(d=this.xbox_mapping= +{axes:[],buttons:{},hat:""});d.axes.lx=e.axes[0];d.axes.ly=e.axes[1];d.axes.rx=e.axes[2];d.axes.ry=e.axes[3];d.axes.ltrigger=e.buttons[6].value;d.axes.rtrigger=e.buttons[7].value;for(var h=0;h","string",{values:g.values});this.size=[60,40]}function l(){this.addInput("inc","number");this.addOutput("total","number");this.addProperty("increment",1);this.addProperty("value",0)}function q(){this.addInput("v","number");this.addOutput("sin","number");this.addProperty("amplitude",1);this.addProperty("offset",0);this.bgImageUrl="nodes/imgs/icon-sin.png"} +function z(){this.addInput("x","number");this.addInput("y","number");this.addOutput("","number");this.properties={x:1,y:1,formula:"x+y"};this.addWidget("toggle","allow",x.allow_scripts,function(a){x.allow_scripts=a});this._func=null}function A(){this.addInput("vec2","vec2");this.addOutput("x","number");this.addOutput("y","number")}function B(){this.addInputs([["x","number"],["y","number"]]);this.addOutput("vec2","vec2");this.properties={x:0,y:0};this._data=new Float32Array(2)}function w(){this.addInput("vec3", +"vec3");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number")}function C(){this.addInputs([["x","number"],["y","number"],["z","number"]]);this.addOutput("vec3","vec3");this.properties={x:0,y:0,z:0};this._data=new Float32Array(3)}function E(){this.addInput("vec4","vec4");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number");this.addOutput("w","number")}function F(){this.addInputs([["x","number"],["y","number"],["z","number"],["w","number"]]); +this.addOutput("vec4","vec4");this.properties={x:0,y:0,z:0,w:0};this._data=new Float32Array(4)}var x=v.LiteGraph;e.title="Converter";e.desc="type A to type B";e.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a&&this.outputs)for(var b=0;bb&&(this._current=0);for(var c=a=0;cb&&(b=1);this.properties.samples=Math.round(b);var c=this._values;this._values=new Float32Array(this.properties.samples);c.length<=this._values.length?this._values.set(c):this._values.set(c.subarray(0,this._values.length))};x.registerNodeType("math/average",a);b.title="TendTo";b.desc="moves the output value always closer to the input";b.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=0);var b=this.properties.factor; +this._value=null==this._value?a:this._value*(1-b)+a*b;this.setOutputData(0,this._value)};x.registerNodeType("math/tendTo",b);c.values="+-*/%^".split("");c.title="Operation";c.desc="Easy math operators";c["@OP"]={type:"enum",title:"operation",values:c.values};c.prototype.getTitle=function(){return"A "+this.properties.OP+" B"};c.prototype.setValue=function(a){"string"==typeof a&&(a=parseFloat(a));this.properties.value=a};c.prototype.onExecute=function(){var a=this.getInputData(0),b=this.getInputData(1); +null!=a?this.properties.A=a:a=this.properties.A;null!=b?this.properties.B=b:b=this.properties.B;var c=0;switch(this.properties.OP){case "+":c=a+b;break;case "-":c=a-b;break;case "x":case "X":case "*":c=a*b;break;case "/":c=a/b;break;case "%":c=a%b;break;case "^":c=Math.pow(a,b);break;default:console.warn("Unknown operation: "+this.properties.OP)}this.setOutputData(0,c)};c.prototype.onDrawBackground=function(a){this.flags.collapsed||(a.font="40px Arial",a.fillStyle="#CCC",a.textAlign="center",a.fillText(this.properties.OP, +0.5*this.size[0],0.35*this.size[1]+x.NODE_TITLE_HEIGHT),a.textAlign="left")};x.registerNodeType("math/operation",c);f.title="Compare";f.desc="compares between two values";f.prototype.onExecute=function(){var a=this.getInputData(0),b=this.getInputData(1);void 0!==a?this.properties.A=a:a=this.properties.A;void 0!==b?this.properties.B=b:b=this.properties.B;for(var c=0,d=this.outputs.length;cB":value=a>b;break;case "A=B":value=a>=b}this.setOutputData(c,value)}}};f.prototype.onGetOutputs=function(){return[["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]};x.registerNodeType("math/compare",f);x.registerSearchboxExtra("math/compare","==",{outputs:[["A==B","boolean"]],title:"A==B"});x.registerSearchboxExtra("math/compare","!=",{outputs:[["A!=B","boolean"]], +title:"A!=B"});x.registerSearchboxExtra("math/compare",">",{outputs:[["A>B","boolean"]],title:"A>B"});x.registerSearchboxExtra("math/compare","<",{outputs:[["A=",{outputs:[["A>=B","boolean"]],title:"A>=B"});x.registerSearchboxExtra("math/compare","<=",{outputs:[["A<=B","boolean"]],title:"A<=B"});g.values="> < == != <= >=".split(" ");g["@OP"]={type:"enum",title:"operation",values:g.values};g.title="Condition";g.desc="evaluates condition between A and B"; +g.prototype.onExecute=function(){var a=this.getInputData(0);void 0===a?a=this.properties.A:this.properties.A=a;var b=this.getInputData(1);void 0===b?b=this.properties.B:this.properties.B=b;var c=!0;switch(this.properties.OP){case ">":c=a>b;break;case "<":c=a=":c=a>=b}this.setOutputData(0,c)};x.registerNodeType("math/condition",g);l.title="Accumulate";l.desc="Increments a value every time";l.prototype.onExecute=function(){null=== +this.properties.value&&(this.properties.value=0);var a=this.getInputData(0);this.properties.value=null!==a?this.properties.value+a:this.properties.value+this.properties.increment;this.setOutputData(0,this.properties.value)};x.registerNodeType("math/accumulate",l);q.title="Trigonometry";q.desc="Sin Cos Tan";q.filter="shader";q.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=0);var b=this.properties.amplitude,c=this.findInputSlot("amplitude");-1!=c&&(b=this.getInputData(c));var d= +this.properties.offset,c=this.findInputSlot("offset");-1!=c&&(d=this.getInputData(c));for(var c=0,f=this.outputs.length;cXY";A.desc="vector 2 to components";A.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]))};x.registerNodeType("math3d/vec2-to-xyz",A);B.title="XY->Vec2";B.desc="components to vector2";B.prototype.onExecute=function(){var a=this.getInputData(0); +null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this._data;c[0]=a;c[1]=b;this.setOutputData(0,c)};x.registerNodeType("math3d/xy-to-vec2",B);w.title="Vec3->XYZ";w.desc="vector 3 to components";w.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]))};x.registerNodeType("math3d/vec3-to-xyz",w);C.title="XYZ->Vec3";C.desc="components to vector3";C.prototype.onExecute= +function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);var d=this._data;d[0]=a;d[1]=b;d[2]=c;this.setOutputData(0,d)};x.registerNodeType("math3d/xyz-to-vec3",C);E.title="Vec4->XYZW";E.desc="vector 4 to components";E.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]),this.setOutputData(3, +a[3]))};x.registerNodeType("math3d/vec4-to-xyzw",E);F.title="XYZW->Vec4";F.desc="components to vector4";F.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.x);var b=this.getInputData(1);null==b&&(b=this.properties.y);var c=this.getInputData(2);null==c&&(c=this.properties.z);var d=this.getInputData(3);null==d&&(d=this.properties.w);var f=this._data;f[0]=a;f[1]=b;f[2]=c;f[3]=d;this.setOutputData(0,f)};x.registerNodeType("math3d/xyzw-to-vec4",F);v.glMatrix&&(v=function(){this.addOutput("quat", +"quat");this.properties={x:0,y:0,z:0,w:1};this._value=quat.create()},v.title="Quaternion",v.desc="quaternion",v.prototype.onExecute=function(){this._value[0]=this.properties.x;this._value[1]=this.properties.y;this._value[2]=this.properties.z;this._value[3]=this.properties.w;this.setOutputData(0,this._value)},x.registerNodeType("math3d/quaternion",v),v=function(){this.addInputs([["degrees","number"],["axis","vec3"]]);this.addOutput("quat","quat");this.properties={angle:90,axis:vec3.fromValues(0,1, +0)};this._value=quat.create()},v.title="Rotation",v.desc="quaternion rotation",v.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle);var b=this.getInputData(1);null==b&&(b=this.properties.axis);a=quat.setAxisAngle(this._value,b,0.0174532925*a);this.setOutputData(0,a)},x.registerNodeType("math3d/rotation",v),v=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},v.title="Rot. Vec3",v.desc= +"rotate a point",v.prototype.onExecute=function(){var a=this.getInputData(0);null==a&&(a=this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a):this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))},x.registerNodeType("math3d/rotate_vec3",v),v=function(){this.addInputs([["A","quat"],["B","quat"]]);this.addOutput("A*B","quat");this._value=quat.create()},v.title="Mult. Quat",v.desc="rotate quaternion",v.prototype.onExecute=function(){var a=this.getInputData(0);if(null!= +a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(this._value,a,b),this.setOutputData(0,a))}},x.registerNodeType("math3d/mult-quat",v),v=function(){this.addInputs([["A","quat"],["B","quat"],["factor","number"]]);this.addOutput("slerp","quat");this.addProperty("factor",0.5);this._value=quat.create()},v.title="Quat Slerp",v.desc="quaternion spherical interpolation",v.prototype.onExecute=function(){var a=this.getInputData(0);if(null!=a){var b=this.getInputData(1);if(null!=b){var c=this.properties.factor; +null!=this.getInputData(2)&&(c=this.getInputData(2));a=quat.slerp(this._value,a,b,c);this.setOutputData(0,a)}}},x.registerNodeType("math3d/quat-slerp",v))})(this); +(function(v){function e(){this.addInput("sel","number");this.addInput("A");this.addInput("B");this.addInput("C");this.addInput("D");this.addOutput("out");this.selected=0}function h(){this.properties={sequence:"A,B,C"};this.addInput("index","number");this.addInput("seq");this.addOutput("out");this.index=0;this.values=this.properties.sequence.split(",")}var p=v.LiteGraph;e.title="Selector";e.desc="selects an output";e.prototype.onDrawBackground=function(d){if(!this.flags.collapsed){d.fillStyle="#AFB"; +var e=(this.selected+1)*p.NODE_SLOT_HEIGHT+2;d.beginPath();d.moveTo(30,e);d.lineTo(30,e+p.NODE_SLOT_HEIGHT);d.lineTo(24,e+0.5*p.NODE_SLOT_HEIGHT);d.fill()}};e.prototype.onExecute=function(){var d=this.getInputData(0);null==d&&(d=0);this.selected=d=Math.round(d)%(this.inputs.length-1);d=this.getInputData(d+1);void 0!==d&&this.setOutputData(0,d)};e.prototype.onGetInputs=function(){return[["E",0],["F",0],["G",0],["H",0]]};p.registerNodeType("logic/selector",e);h.title="Sequence";h.desc="select one element from a sequence from a string"; +h.prototype.onPropertyChanged=function(d,e){"sequence"==d&&(this.values=e.split(","))};h.prototype.onExecute=function(){var d=this.getInputData(1);d&&d!=this.current_sequence&&(this.values=d.split(","),this.current_sequence=d);d=this.getInputData(0);null==d&&(d=0);this.index=d=Math.round(d)%this.values.length;this.setOutputData(0,this.values[d])};p.registerNodeType("logic/sequence",h)})(this); +(function(v){function e(){this.addInput("A","Number");this.addInput("B","Number");this.addInput("C","Number");this.addInput("D","Number");this.values=[[],[],[],[]];this.properties={scale:2}}function h(){this.addOutput("frame","image");this.properties={url:""}}function p(){this.addInput("f","number");this.addOutput("Color","color");this.properties={colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"}}function d(){this.addInput("","image,canvas");this.size=[200,200]}function s(){this.addInputs([["img1", +"image"],["img2","image"],["fade","number"]]);this.addOutput("","image");this.properties={fade:0.5,width:512,height:512}}function r(){this.addInput("","image");this.addOutput("","image");this.properties={width:256,height:256,x:0,y:0,scale:1};this.size=[50,20]}function t(){this.addInput("clear",m.ACTION);this.addOutput("","canvas");this.properties={width:512,height:512,autoclear:!0};this.canvas=document.createElement("canvas");this.ctx=this.canvas.getContext("2d")}function y(){this.addInput("canvas", +"canvas");this.addInput("img","image,canvas");this.addInput("x","number");this.addInput("y","number");this.properties={x:0,y:0,opacity:1}}function k(){this.addInput("canvas","canvas");this.addInput("x","number");this.addInput("y","number");this.addInput("w","number");this.addInput("h","number");this.properties={x:0,y:0,w:10,h:10,color:"white",opacity:1}}function u(){this.addInput("t","number");this.addOutputs([["frame","image"],["t","number"],["d","number"]]);this.properties={url:"",use_proxy:!0}} +function n(){this.addOutput("Webcam","image");this.properties={facingMode:"user"};this.boxcolor="black";this.frame=0}var m=v.LiteGraph;e.title="Plot";e.desc="Plots data over time";e.colors=["#FFF","#F99","#9F9","#99F"];e.prototype.onExecute=function(a){if(!this.flags.collapsed){a=this.size;for(var b=0;4>b;++b){var c=this.getInputData(b);if(null!=c){var d=this.values[b];d.push(c);d.length>a[0]&&d.shift()}}}};e.prototype.onDrawBackground=function(a){if(!this.flags.collapsed){var b=this.size,c=0.5*b[1]/ +this.properties.scale,d=e.colors,g=0.5*b[1];a.fillStyle="#000";a.fillRect(0,0,b[0],b[1]);a.strokeStyle="#555";a.beginPath();a.moveTo(0,g);a.lineTo(b[0],g);a.stroke();if(this.inputs)for(var l=0;4>l;++l){var h=this.values[l];if(this.inputs[l]&&this.inputs[l].link){a.strokeStyle=d[l];a.beginPath();var k=h[0]*c*-1+g;a.moveTo(0,Math.clamp(k,0,b[1]));for(var m=1;mb&&(b=0);if(0!=a.length){var c=[0,0,0];if(0==b)c=a[0];else if(1==b)c=a[a.length-1];else{var d=(a.length-1)*b,b=a[Math.floor(d)],a=a[Math.floor(d)+1],d=d-Math.floor(d);c[0]=b[0]* +(1-d)+a[0]*d;c[1]=b[1]*(1-d)+a[1]*d;c[2]=b[2]*(1-d)+a[2]*d}for(var g in c)c[g]/=255;this.boxcolor=colorToString(c);this.setOutputData(0,c)}};m.registerNodeType("color/palette",p);d.title="Frame";d.desc="Frame viewerew";d.widgets=[{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}];d.prototype.onDrawBackground=function(a){this.frame&&!this.flags.collapsed&&a.drawImage(this.frame,0,0,this.size[0],this.size[1])};d.prototype.onExecute=function(){this.frame=this.getInputData(0); +this.setDirtyCanvas(!0)};d.prototype.onWidget=function(a,b){if("resize"==b.name&&this.frame){var c=this.frame.width,d=this.frame.height;c||null==this.frame.videoWidth||(c=this.frame.videoWidth,d=this.frame.videoHeight);c&&d&&(this.size=[c,d]);this.setDirtyCanvas(!0,!0)}else"view"==b.name&&this.show()};d.prototype.show=function(){showElement&&this.frame&&showElement(this.frame)};m.registerNodeType("graphics/frame",d);s.title="Image fade";s.desc="Fades between images";s.widgets=[{name:"resizeA",text:"Resize to A", +type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}];s.prototype.onAdded=function(){this.createCanvas();var a=this.canvas.getContext("2d");a.fillStyle="#000";a.fillRect(0,0,this.properties.width,this.properties.height)};s.prototype.createCanvas=function(){this.canvas=document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height};s.prototype.onExecute=function(){var a=this.canvas.getContext("2d");this.canvas.width=this.canvas.width; +var b=this.getInputData(0);null!=b&&a.drawImage(b,0,0,this.canvas.width,this.canvas.height);b=this.getInputData(2);null==b?b=this.properties.fade:this.properties.fade=b;a.globalAlpha=b;b=this.getInputData(1);null!=b&&a.drawImage(b,0,0,this.canvas.width,this.canvas.height);a.globalAlpha=1;this.setOutputData(0,this.canvas);this.setDirtyCanvas(!0)};m.registerNodeType("graphics/imagefade",s);r.title="Crop";r.desc="Crop Image";r.prototype.onAdded=function(){this.createCanvas()};r.prototype.createCanvas= +function(){this.canvas=document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height};r.prototype.onExecute=function(){var a=this.getInputData(0);a&&(a.width?(this.canvas.getContext("2d").drawImage(a,-this.properties.x,-this.properties.y,a.width*this.properties.scale,a.height*this.properties.scale),this.setOutputData(0,this.canvas)):this.setOutputData(0,null))};r.prototype.onDrawBackground=function(a){this.flags.collapsed||this.canvas&&a.drawImage(this.canvas, +0,0,this.canvas.width,this.canvas.height,0,0,this.size[0],this.size[1])};r.prototype.onPropertyChanged=function(a,b){this.properties[a]=b;"scale"==a?(this.properties[a]=parseFloat(b),0==this.properties[a]&&(this.trace("Error in scale"),this.properties[a]=1)):this.properties[a]=parseInt(b);this.createCanvas();return!0};m.registerNodeType("graphics/cropImage",r);t.title="Canvas";t.desc="Canvas to render stuff";t.prototype.onExecute=function(){var a=this.canvas,b=this.properties.width|0,c=this.properties.height| +0;a.width!=b&&(a.width=b);a.height!=c&&(a.height=c);this.properties.autoclear&&this.ctx.clearRect(0,0,a.width,a.height);this.setOutputData(0,a)};t.prototype.onAction=function(a,b){"clear"==a&&this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)};m.registerNodeType("graphics/canvas",t);y.title="DrawImage";y.desc="Draws image into a canvas";y.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=this.getInputOrProperty("img");if(b){var c=this.getInputOrProperty("x"),d=this.getInputOrProperty("y"); +a.getContext("2d").drawImage(b,c,d)}}};m.registerNodeType("graphics/drawImage",y);k.title="DrawRectangle";k.desc="Draws rectangle in canvas";k.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=this.getInputOrProperty("x"),c=this.getInputOrProperty("y"),d=this.getInputOrProperty("w"),g=this.getInputOrProperty("h");a.getContext("2d").fillRect(b,c,d,g)}};m.registerNodeType("graphics/drawRectangle",k);u.title="Video";u.desc="Video playback";u.widgets=[{name:"play",text:"PLAY",type:"minibutton"}, +{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}];u.prototype.onExecute=function(){if(this.properties.url&&(this.properties.url!=this._video_url&&this.loadVideo(this.properties.url),this._video&&0!=this._video.width)){var a=this.getInputData(0);a&&0<=a&&1>=a&&(this._video.currentTime=a*this._video.duration,this._video.pause());this._video.dirty=!0;this.setOutputData(0,this._video);this.setOutputData(1,this._video.currentTime); +this.setOutputData(2,this._video.duration);this.setDirtyCanvas(!0)}};u.prototype.onStart=function(){this.play()};u.prototype.onStop=function(){this.stop()};u.prototype.loadVideo=function(a){this._video_url=a;this.properties.use_proxy&&"http"==a.substr(0,4)&&m.proxy&&(a=m.proxy+a.substr(a.indexOf(":")+3));this._video=document.createElement("video");this._video.src=a;this._video.type="type=video/mp4";this._video.muted=!0;this._video.autoplay=!0;var b=this;this._video.addEventListener("loadedmetadata", +function(a){b.trace("Duration: "+this.duration+" seconds");b.trace("Size: "+this.videoWidth+","+this.videoHeight);b.setDirtyCanvas(!0);this.width=this.videoWidth;this.height=this.videoHeight});this._video.addEventListener("progress",function(a){});this._video.addEventListener("error",function(a){console.log("Error loading video: "+this.src);b.trace("Error loading video: "+this.src);if(this.error)switch(this.error.code){case this.error.MEDIA_ERR_ABORTED:b.trace("You stopped the video.");break;case this.error.MEDIA_ERR_NETWORK:b.trace("Network error - please try again later."); +break;case this.error.MEDIA_ERR_DECODE:b.trace("Video is broken..");break;case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED:b.trace("Sorry, your browser can't play this video.")}});this._video.addEventListener("ended",function(a){b.trace("Ended.");this.play()})};u.prototype.onPropertyChanged=function(a,b){this.properties[a]=b;"url"==a&&""!=b&&this.loadVideo(b);return!0};u.prototype.play=function(){this._video&&this._video.play()};u.prototype.playPause=function(){this._video&&(this._video.paused?this.play(): +this.pause())};u.prototype.stop=function(){this._video&&(this._video.pause(),this._video.currentTime=0)};u.prototype.pause=function(){this._video&&(this.trace("Video paused"),this._video.pause())};u.prototype.onWidget=function(a,b){};m.registerNodeType("graphics/video",u);n.title="Webcam";n.desc="Webcam image";n.prototype.openStream=function(){function a(a){console.log("Webcam rejected",a);b._webcam_stream=!1;b.boxcolor="red";b.trigger("stream_error")}if(navigator.getUserMedia){this._waiting_confirmation= +!0;navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:this.properties.facingMode}}).then(this.streamReady.bind(this))["catch"](a);var b=this}};n.prototype.closeStream=function(){if(this._webcam_stream){var a=this._webcam_stream.getTracks();if(a.length)for(var b=0;b=this.size[1]||!this.properties.show||!this._video||(a.save(),a.drawImage(this._video,0,0,this.size[0],this.size[1]),a.restore())};n.prototype.onGetOutputs=function(){return[["width","number"],["height","number"],["stream_ready",m.EVENT],["stream_closed",m.EVENT],["stream_error",m.EVENT]]};m.registerNodeType("graphics/webcam",n)})(this); +(function(v){var e=v.LiteGraph;v.LGraphTexture=null;if("undefined"!=typeof GL){LGraphCanvas.link_type_colors.Texture="#AEF";var h=function(){this.addOutput("Texture","Texture");this.properties={name:"",filter:!0};this.size=[h.image_preview_size,h.image_preview_size]};v.LGraphTexture=h;h.title="Texture";h.desc="Texture";h.widgets_info={name:{widget:"texture"},filter:{widget:"checkbox"}};h.loadTextureCallback=null;h.image_preview_size=256;h.PASS_THROUGH=1;h.COPY=2;h.LOW=3;h.HIGH=4;h.REUSE=5;h.DEFAULT= +2;h.MODE_VALUES={"pass through":h.PASS_THROUGH,copy:h.COPY,low:h.LOW,high:h.HIGH,reuse:h.REUSE,"default":h.DEFAULT};h.getTexturesContainer=function(){return gl.textures};h.loadTexture=function(a,b){b=b||{};var c=a;"http://"==c.substr(0,7)&&e.proxy&&(c=e.proxy+c.substr(7));return h.getTexturesContainer()[a]=GL.Texture.fromURL(c,b)};h.getTexture=function(a){var b=this.getTexturesContainer();if(!b)throw"Cannot load texture, container of textures not found";b=b[a];return!b&&a&&":"!=a[0]?this.loadTexture(a): +b};h.getTargetTexture=function(a,b,c){if(!a)throw"LGraphTexture.getTargetTexture expects a reference texture";var d=null;switch(c){case h.LOW:d=gl.UNSIGNED_BYTE;break;case h.HIGH:d=gl.HIGH_PRECISION_FORMAT;break;case h.REUSE:return a;default:d=a?a.type:gl.UNSIGNED_BYTE}b&&b.width==a.width&&b.height==a.height&&b.type==d||(b=new GL.Texture(a.width,a.height,{type:d,format:gl.RGBA,filter:gl.LINEAR}));return b};h.getTextureType=function(a,b){var c=b?b.type:gl.UNSIGNED_BYTE;switch(a){case h.HIGH:c=gl.HIGH_PRECISION_FORMAT; +break;case h.LOW:c=gl.UNSIGNED_BYTE}return c};h.getNoiseTexture=function(){if(this._noise_texture)return this._noise_texture;for(var a=new Uint8Array(1048576),b=0;1048576>b;++b)a[b]=255*Math.random();return this._noise_texture=a=GL.Texture.fromMemory(512,512,a,{format:gl.RGBA,wrap:gl.REPEAT,filter:gl.NEAREST})};h.prototype.onDropFile=function(a,b,c){if(a){var d=null;"string"==typeof a?d=GL.Texture.fromURL(a):-1!=b.toLowerCase().indexOf(".dds")?d=GL.Texture.fromDDSInMemory(a):(a=new Blob([c]),a=URL.createObjectURL(a), +d=GL.Texture.fromURL(a));this._drop_texture=d;this.properties.name=b}else this._drop_texture=null,this.properties.name=""};h.prototype.getExtraMenuOptions=function(a){var b=this;if(this._drop_texture)return[{content:"Clear",callback:function(){b._drop_texture=null;b.properties.name=""}}]};h.prototype.onExecute=function(){var a=null;this.isOutputConnected(1)&&(a=this.getInputData(0));!a&&this._drop_texture&&(a=this._drop_texture);!a&&this.properties.name&&(a=h.getTexture(this.properties.name));if(a){this._last_tex= +a;!1===this.properties.filter?a.setParameter(gl.TEXTURE_MAG_FILTER,gl.NEAREST):a.setParameter(gl.TEXTURE_MAG_FILTER,gl.LINEAR);this.setOutputData(0,a);for(var b=1;b=this.size[1]))if(this._drop_texture&&a.webgl)a.drawImage(this._drop_texture,0,0,this.size[0],this.size[1]);else{if(this._last_preview_tex!=this._last_tex)if(a.webgl)this._canvas=this._last_tex;else{var b=h.generateLowResTexturePreview(this._last_tex);if(!b)return;this._last_preview_tex=this._last_tex;this._canvas=cloneCanvas(b)}this._canvas&&(a.save(),a.webgl||(a.translate(0,this.size[1]),a.scale(1,-1)),a.drawImage(this._canvas,0,0,this.size[0],this.size[1]),a.restore())}};h.generateLowResTexturePreview= +function(a){if(!a)return null;var b=h.image_preview_size,c=a;if(a.format==gl.DEPTH_COMPONENT)return null;if(a.width>b||a.height>b)c=this._preview_temp_tex,this._preview_temp_tex||(this._preview_temp_tex=c=new GL.Texture(b,b,{minFilter:gl.NEAREST})),a.copyTo(c);a=this._preview_canvas;a||(this._preview_canvas=a=createCanvas(b,b));c&&c.toCanvas(a);return a};h.prototype.getResources=function(a){a[this.properties.name]=GL.Texture;return a};h.prototype.onGetInputs=function(){return[["in","Texture"]]};h.prototype.onGetOutputs= +function(){return[["width","number"],["height","number"],["aspect","number"]]};e.registerNodeType("texture/texture",h);var p=function(){this.addInput("Texture","Texture");this.properties={flipY:!1};this.size=[h.image_preview_size,h.image_preview_size]};p.title="Preview";p.desc="Show a texture in the graph canvas";p.allow_preview=!1;p.prototype.onDrawBackground=function(a){if(!this.flags.collapsed&&(a.webgl||p.allow_preview)){var b=this.getInputData(0);if(b){var c=null,c=!b.handle&&a.webgl?b:h.generateLowResTexturePreview(b); +a.save();this.properties.flipY&&(a.translate(0,this.size[1]),a.scale(1,-1));a.drawImage(c,0,0,this.size[0],this.size[1]);a.restore()}}};e.registerNodeType("texture/preview",p);var d=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={name:""}};d.title="Save";d.desc="Save a texture in the repository";d.prototype.onExecute=function(){var a=this.getInputData(0);a&&(this.properties.name&&(h.storeTexture?h.storeTexture(this.properties.name,a):h.getTexturesContainer()[this.properties.name]= +a),this.setOutputData(0,a))};e.registerNodeType("texture/save",d);var s=function(){this.addInput("Texture","Texture");this.addInput("TextureB","Texture");this.addInput("value","number");this.addOutput("Texture","Texture");this.help="

pixelcode must be vec3

\t\t\t

uvcode must be vec2, is optional

\t\t\t

uv: tex. coords

color: texture

colorB: textureB

time: scene time

value: input value

"; +this.properties={value:1,uvcode:"",pixelcode:"color + colorB * value",precision:h.DEFAULT}};s.widgets_info={uvcode:{widget:"textarea",height:100},pixelcode:{widget:"textarea",height:100},precision:{widget:"combo",values:h.MODE_VALUES}};s.title="Operation";s.desc="Texture shader operation";s.prototype.getExtraMenuOptions=function(a){var b=this;return[{content:b.properties.show?"Hide Texture":"Show Texture",callback:function(){b.properties.show=!b.properties.show}}]};s.prototype.onDrawBackground=function(a){this.flags.collapsed|| +20>=this.size[1]||!this.properties.show||!this._tex||this._tex.gl!=a||(a.save(),a.drawImage(this._tex,0,0,this.size[0],this.size[1]),a.restore())};s.prototype.onExecute=function(){var a=this.getInputData(0);if(this.isOutputConnected(0))if(this.properties.precision===h.PASS_THROUGH)this.setOutputData(0,a);else{var b=this.getInputData(1);if(this.properties.uvcode||this.properties.pixelcode){var c=512,d=512;a?(c=a.width,d=a.height):b&&(c=b.width,d=b.height);var f=h.getTextureType(this.properties.precision, +a);this._tex=a||this._tex?h.getTargetTexture(a||this._tex,this._tex,this.properties.precision):new GL.Texture(c,d,{type:f,format:gl.RGBA,filter:gl.LINEAR});f="";this.properties.uvcode&&(f="uv = "+this.properties.uvcode,-1!=this.properties.uvcode.indexOf(";")&&(f=this.properties.uvcode));var g="";this.properties.pixelcode&&(g="result = "+this.properties.pixelcode,-1!=this.properties.pixelcode.indexOf(";")&&(g=this.properties.pixelcode));var e=this._shader;if(!e||this._shader_code!=f+"|"+g){try{this._shader= +new GL.Shader(Shader.SCREEN_VERTEX_SHADER,s.pixel_shader,{UV_CODE:f,PIXEL_CODE:g}),this.boxcolor="#00FF00"}catch(l){console.log("Error compiling shader: ",l);this.boxcolor="#FF0000";return}this.boxcolor="#FF0000";this._shader_code=f+"|"+g;e=this._shader}if(e){this.boxcolor="green";var k=this.getInputData(2);null!=k?this.properties.value=k:k=parseFloat(this.properties.value);var m=this.graph.getTime();this._tex.drawTo(function(){gl.disable(gl.DEPTH_TEST);gl.disable(gl.CULL_FACE);gl.disable(gl.BLEND); +a&&a.bind(0);b&&b.bind(1);var f=Mesh.getScreenQuad();e.uniforms({u_texture:0,u_textureB:1,value:k,texSize:[c,d],time:m}).draw(f)});this.setOutputData(0,this._tex)}else this.boxcolor="red"}}};s.pixel_shader="precision highp float;\n\t\t\t\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform vec2 texSize;\n\t\t\tuniform float time;\n\t\t\tuniform float value;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 uv = v_coord;\n\t\t\t\tUV_CODE;\n\t\t\t\tvec4 color4 = texture2D(u_texture, uv);\n\t\t\t\tvec3 color = color4.rgb;\n\t\t\t\tvec4 color4B = texture2D(u_textureB, uv);\n\t\t\t\tvec3 colorB = color4B.rgb;\n\t\t\t\tvec3 result = color;\n\t\t\t\tfloat alpha = 1.0;\n\t\t\t\tPIXEL_CODE;\n\t\t\t\tgl_FragColor = vec4(result, alpha);\n\t\t\t}\n\t\t\t"; +e.registerNodeType("texture/operation",s);var r=function(){this.addOutput("out","Texture");this.properties={code:"",width:512,height:512,precision:h.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}};r.title="Shader";r.desc="Texture shader";r.widgets_info={code:{type:"code"},precision:{widget:"combo",values:h.MODE_VALUES}};r.prototype.onPropertyChanged= +function(a,b){if("code"==a){var c=this.getShader();if(c){var d=c.uniformInfo;if(this.inputs)for(var f={},g=0;g lumaMax))\n\t\t\t\t\tcolor = vec4(rgbA, 1.0);\n\t\t\t\telse\n\t\t\t\t\tcolor = vec4(rgbB, 1.0);\n\t\t\t\tif(u_igamma != 1.0)\n\t\t\t\t\tcolor.xyz = pow( color.xyz, vec3(u_igamma) );\n\t\t\t\treturn color;\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\t\t\t}\n\t\t\t"; -k.gamma_pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform float u_igamma;\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = texture2D( u_texture, v_coord);\n\t\t\t\tcolor.xyz = pow(color.xyz, vec3(u_igamma) );\n\t\t\t gl_FragColor = color;\n\t\t\t}\n\t\t\t";h.registerNodeType("texture/toviewport",k);d=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={size:0,generate_mipmaps:!1, -precision:f.DEFAULT}};d.title="Copy";d.desc="Copy Texture";d.widgets_info={size:{widget:"combo",values:[0,32,64,128,256,512,1024,2048]},precision:{widget:"combo",values:f.MODE_VALUES}};d.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)){if(a){var b=a.width,c=a.height;0!=this.properties.size&&(c=b=this.properties.size);var d=this._temp_texture,e=a.type;this.properties.precision===f.LOW?e=gl.UNSIGNED_BYTE:this.properties.precision===f.HIGH&& -(e=gl.HIGH_PRECISION_FORMAT);d&&d.width==b&&d.height==c&&d.type==e||(d=gl.LINEAR,this.properties.generate_mipmaps&&isPowerOfTwo(b)&&isPowerOfTwo(c)&&(d=gl.LINEAR_MIPMAP_LINEAR),this._temp_texture=new GL.Texture(b,c,{type:e,format:gl.RGBA,minFilter:d,magFilter:gl.LINEAR}));a.copyTo(this._temp_texture);this.properties.generate_mipmaps&&(this._temp_texture.bind(0),gl.generateMipmap(this._temp_texture.texture_type),this._temp_texture.unbind(0))}this.setOutputData(0,this._temp_texture)}};h.registerNodeType("texture/copy", -d);var m=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={iterations:1,generate_mipmaps:!1,precision:f.DEFAULT}};m.title="Downsample";m.desc="Downsample Texture";m.widgets_info={iterations:{type:"number",step:1,precision:0,min:1},precision:{widget:"combo",values:f.MODE_VALUES}};m.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)&&a&&a.texture_type===GL.TEXTURE_2D){var b=m._shader;b||(m._shader= -b=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,m.pixel_shader));var c=a.width|0,d=a.height|0,e=a.type;this.properties.precision===f.LOW?e=gl.UNSIGNED_BYTE:this.properties.precision===f.HIGH&&(e=gl.HIGH_PRECISION_FORMAT);var g=this.properties.iterations||1,l=a,h=null,k=[],a={type:e,format:a.format},e=vec2.create(),n={u_offset:e};this._texture&&GL.Texture.releaseTemporary(this._texture);for(var p=0;p>1||0;d=d>>1||0;h=GL.Texture.getTemporary(c,d,a);k.push(h);l.setParameter(GL.TEXTURE_MAG_FILTER, -GL.NEAREST);l.copyTo(h,b,n);if(1==c&&1==d)break;l=h}this._texture=k.pop();for(p=0;pd;++d)c[d]=Math.random();b._shader.uniforms({u_samples_a:c.subarray(0,16),u_samples_b:c.subarray(16,32)})}d=this._temp_texture;c=gl.UNSIGNED_BYTE;a.type!=c&&(c=gl.FLOAT);d&&d.type==c||(this._temp_texture=new GL.Texture(1,1,{type:c,format:gl.RGBA,filter:gl.NEAREST})); -var e=b._shader,g=this._uniforms;g.u_mipmap_offset=this.properties.mipmap_offset;this._temp_texture.drawTo(function(){a.toViewport(e,g)});this.setOutputData(0,this._temp_texture);if(this.isOutputConnected(1)||this.isOutputConnected(2))if(d=this._temp_texture.getPixels()){var f=this._luminance,c=this._temp_texture.type;f.set(d);c==gl.UNSIGNED_BYTE?vec4.scale(f,f,1/255):c!=GL.HALF_FLOAT&&c!=GL.HALF_FLOAT_OES||vec4.scale(f,f,1/65025);this.setOutputData(1,f);this.setOutputData(2,(f[0]+f[1]+f[2])/3)}}}; -b.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tuniform mat4 u_samples_a;\n\t\t\tuniform mat4 u_samples_b;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform float u_mipmap_offset;\n\t\t\tvarying vec2 v_coord;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = vec4(0.0);\n\t\t\t\tfor(int i = 0; i < 4; ++i)\n\t\t\t\t\tfor(int j = 0; j < 4; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t\t}\n\t\t\t gl_FragColor = color * 0.03125;\n\t\t\t}\n\t\t\t"; -h.registerNodeType("texture/average",b);d=function(){this.addInput("Image","image");this.addOutput("","Texture");this.properties={}};d.title="Image to Texture";d.desc="Uploads an image to the GPU";d.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=a.videoWidth||a.width,c=a.videoHeight||a.height;if(a.gltexture)this.setOutputData(0,a.gltexture);else{var d=this._temp_texture;d&&d.width==b&&d.height==c||(this._temp_texture=new GL.Texture(b,c,{format:gl.RGBA,filter:gl.LINEAR}));try{this._temp_texture.uploadImage(a)}catch(e){console.error("image comes from an unsafe location, cannot be uploaded to webgl: "+ -e);return}this.setOutputData(0,this._temp_texture)}}};h.registerNodeType("texture/imageToTexture",d);var p=function(){this.addInput("Texture","Texture");this.addInput("LUT","Texture");this.addInput("Intensity","number");this.addOutput("","Texture");this.properties={intensity:1,precision:f.DEFAULT,texture:null};p._shader||(p._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,p.pixel_shader))};p.widgets_info={texture:{widget:"texture"},precision:{widget:"combo",values:f.MODE_VALUES}};p.title="LUT";p.desc= -"Apply LUT to Texture";p.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===f.PASS_THROUGH)this.setOutputData(0,a);else if(a){var b=this.getInputData(1);b||(b=f.getTexture(this.properties.texture));if(b){b.bind(0);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D, -null);var c=this.properties.intensity;this.isInputConnected(2)&&(this.properties.intensity=c=this.getInputData(2));this._tex=f.getTargetTexture(a,this._tex,this.properties.precision);this._tex.drawTo(function(){b.bind(1);a.toViewport(p._shader,{u_texture:0,u_textureB:1,u_amount:c})});this.setOutputData(0,this._tex)}else this.setOutputData(0,a)}}};p.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform float u_amount;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\t lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\t\t\t\t mediump float blueColor = textureColor.b * 63.0;\n\t\t\t\t mediump vec2 quad1;\n\t\t\t\t quad1.y = floor(floor(blueColor) / 8.0);\n\t\t\t\t quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\t\t\t\t mediump vec2 quad2;\n\t\t\t\t quad2.y = floor(ceil(blueColor) / 8.0);\n\t\t\t\t quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\t\t\t\t highp vec2 texPos1;\n\t\t\t\t texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t highp vec2 texPos2;\n\t\t\t\t texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\t\t\t\t lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\t\t\t\t lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\t\t\t\t gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\t\t\t}\n\t\t\t"; -h.registerNodeType("texture/LUT",p);var a=function(){this.addInput("Texture","Texture");this.addOutput("R","Texture");this.addOutput("G","Texture");this.addOutput("B","Texture");this.addOutput("A","Texture");this.properties={};a._shader||(a._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,a.pixel_shader))};a.title="Texture to Channels";a.desc="Split texture channels";a.prototype.onExecute=function(){var b=this.getInputData(0);if(b){this._channels||(this._channels=Array(4));for(var c=0,d=0;4>d;d++)this.isOutputConnected(d)? -(this._channels[d]&&this._channels[d].width==b.width&&this._channels[d].height==b.height&&this._channels[d].type==b.type||(this._channels[d]=new GL.Texture(b.width,b.height,{type:b.type,format:gl.RGBA,filter:gl.LINEAR})),c++):this._channels[d]=null;if(c){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);for(var e=Mesh.getScreenQuad(),g=a._shader,f=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],d=0;4>d;d++)this._channels[d]&&(this._channels[d].drawTo(function(){b.bind(0);g.uniforms({u_texture:0,u_mask:f[d]}).draw(e)}), -this.setOutputData(d,this._channels[d]))}}};a.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec4 u_mask;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\t\t\t}\n\t\t\t";h.registerNodeType("texture/textureChannels",a);var c=function(){this.addInput("R","Texture");this.addInput("G","Texture");this.addInput("B","Texture");this.addInput("A", -"Texture");this.addOutput("Texture","Texture");this.properties={};c._shader||(c._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,c.pixel_shader))};c.title="Channels to Texture";c.desc="Split texture channels";c.prototype.onExecute=function(){var a=[this.getInputData(0),this.getInputData(1),this.getInputData(2),this.getInputData(3)];if(a[0]&&a[1]&&a[2]&&a[3]){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),d=c._shader;this._tex=f.getTargetTexture(a[0],this._tex);this._tex.drawTo(function(){a[0].bind(0); -a[1].bind(1);a[2].bind(2);a[3].bind(3);d.uniforms({u_textureR:0,u_textureG:1,u_textureB:2,u_textureA:3}).draw(b)});this.setOutputData(0,this._tex)}};c.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureR;\n\t\t\tuniform sampler2D u_textureG;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( \t\t\t\t\t\ttexture2D(u_textureR, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureG, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureB, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureA, v_coord).r);\n\t\t\t}\n\t\t\t"; -h.registerNodeType("texture/channelsTexture",c);d=function(){this.addOutput("Texture","Texture");this._tex_color=vec4.create();this.properties={color:vec4.create(),precision:f.DEFAULT}};d.title="Color";d.desc="Generates a 1x1 texture with a constant color";d.widgets_info={precision:{widget:"combo",values:f.MODE_VALUES}};d.prototype.onDrawBackground=function(a){var b=this.properties.color;a.fillStyle="rgb("+Math.floor(255*Math.clamp(b[0],0,1))+","+Math.floor(255*Math.clamp(b[1],0,1))+","+Math.floor(255* -Math.clamp(b[2],0,1))+")";this.flags.collapsed?this.boxcolor=a.fillStyle:a.fillRect(0,0,this.size[0],this.size[1])};d.prototype.onExecute=function(){var a=this.properties.precision==f.HIGH?f.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._tex&&this._tex.type==a||(this._tex=new GL.Texture(1,1,{format:gl.RGBA,type:a,minFilter:gl.NEAREST}));a=this.properties.color;if(this.inputs)for(var b=0;b 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\t\t\t}\n\t\t\t"; -h.registerNodeType("texture/edges",g);var l=function(){this.addInput("Texture","Texture");this.addInput("Distance","number");this.addInput("Range","number");this.addOutput("Texture","Texture");this.properties={distance:100,range:50,only_depth:!1,high_precision:!1};this._uniforms={u_texture:0,u_distance:100,u_range:50,u_camera_planes:null}};l.title="Depth Range";l.desc="Generates a texture with a depth range";l.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0); +k.gamma_pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform float u_igamma;\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = texture2D( u_texture, v_coord);\n\t\t\t\tcolor.xyz = pow(color.xyz, vec3(u_igamma) );\n\t\t\t gl_FragColor = color;\n\t\t\t}\n\t\t\t";e.registerNodeType("texture/toviewport",k);d=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={size:0,generate_mipmaps:!1, +precision:h.DEFAULT}};d.title="Copy";d.desc="Copy Texture";d.widgets_info={size:{widget:"combo",values:[0,32,64,128,256,512,1024,2048]},precision:{widget:"combo",values:h.MODE_VALUES}};d.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)){if(a){var b=a.width,c=a.height;0!=this.properties.size&&(c=b=this.properties.size);var d=this._temp_texture,f=a.type;this.properties.precision===h.LOW?f=gl.UNSIGNED_BYTE:this.properties.precision===h.HIGH&& +(f=gl.HIGH_PRECISION_FORMAT);d&&d.width==b&&d.height==c&&d.type==f||(d=gl.LINEAR,this.properties.generate_mipmaps&&isPowerOfTwo(b)&&isPowerOfTwo(c)&&(d=gl.LINEAR_MIPMAP_LINEAR),this._temp_texture=new GL.Texture(b,c,{type:f,format:gl.RGBA,minFilter:d,magFilter:gl.LINEAR}));a.copyTo(this._temp_texture);this.properties.generate_mipmaps&&(this._temp_texture.bind(0),gl.generateMipmap(this._temp_texture.texture_type),this._temp_texture.unbind(0))}this.setOutputData(0,this._temp_texture)}};e.registerNodeType("texture/copy", +d);var u=function(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={iterations:1,generate_mipmaps:!1,precision:h.DEFAULT}};u.title="Downsample";u.desc="Downsample Texture";u.widgets_info={iterations:{type:"number",step:1,precision:0,min:1},precision:{widget:"combo",values:h.MODE_VALUES}};u.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)&&a&&a.texture_type===GL.TEXTURE_2D){var b=u._shader;b||(u._shader= +b=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,u.pixel_shader));var c=a.width|0,d=a.height|0,f=a.type;this.properties.precision===h.LOW?f=gl.UNSIGNED_BYTE:this.properties.precision===h.HIGH&&(f=gl.HIGH_PRECISION_FORMAT);var g=this.properties.iterations||1,e=a,l=null,k=[],a={type:f,format:a.format},f=vec2.create(),m={u_offset:f};this._texture&&GL.Texture.releaseTemporary(this._texture);for(var q=0;q>1||0;d=d>>1||0;l=GL.Texture.getTemporary(c,d,a);k.push(l);e.setParameter(GL.TEXTURE_MAG_FILTER, +GL.NEAREST);e.copyTo(l,b,m);if(1==c&&1==d)break;e=l}this._texture=k.pop();for(q=0;qc;++c)b[c]=Math.random();n._shader.uniforms({u_samples_a:b.subarray(0,16),u_samples_b:b.subarray(16,32)})}c=this._temp_texture;b=gl.UNSIGNED_BYTE;a.type!=b&&(b=gl.FLOAT);c&&c.type==b||(this._temp_texture=new GL.Texture(1,1,{type:b,format:gl.RGBA,filter:gl.NEAREST})); +var d=n._shader,f=this._uniforms;f.u_mipmap_offset=this.properties.mipmap_offset;this._temp_texture.drawTo(function(){a.toViewport(d,f)});this.setOutputData(0,this._temp_texture);if(this.isOutputConnected(1)||this.isOutputConnected(2))if(c=this._temp_texture.getPixels()){var g=this._luminance,b=this._temp_texture.type;g.set(c);b==gl.UNSIGNED_BYTE?vec4.scale(g,g,1/255):b!=GL.HALF_FLOAT&&b!=GL.HALF_FLOAT_OES||vec4.scale(g,g,1/65025);this.setOutputData(1,g);this.setOutputData(2,(g[0]+g[1]+g[2])/3)}}}; +n.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tuniform mat4 u_samples_a;\n\t\t\tuniform mat4 u_samples_b;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform float u_mipmap_offset;\n\t\t\tvarying vec2 v_coord;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = vec4(0.0);\n\t\t\t\tfor(int i = 0; i < 4; ++i)\n\t\t\t\t\tfor(int j = 0; j < 4; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t\t\tcolor += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t\t}\n\t\t\t gl_FragColor = color * 0.03125;\n\t\t\t}\n\t\t\t"; +e.registerNodeType("texture/average",n);d=function(){this.addInput("Image","image");this.addOutput("","Texture");this.properties={}};d.title="Image to Texture";d.desc="Uploads an image to the GPU";d.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=a.videoWidth||a.width,c=a.videoHeight||a.height;if(a.gltexture)this.setOutputData(0,a.gltexture);else{var d=this._temp_texture;d&&d.width==b&&d.height==c||(this._temp_texture=new GL.Texture(b,c,{format:gl.RGBA,filter:gl.LINEAR}));try{this._temp_texture.uploadImage(a)}catch(f){console.error("image comes from an unsafe location, cannot be uploaded to webgl: "+ +f);return}this.setOutputData(0,this._temp_texture)}}};e.registerNodeType("texture/imageToTexture",d);var m=function(){this.addInput("Texture","Texture");this.addInput("LUT","Texture");this.addInput("Intensity","number");this.addOutput("","Texture");this.properties={intensity:1,precision:h.DEFAULT,texture:null};m._shader||(m._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,m.pixel_shader))};m.widgets_info={texture:{widget:"texture"},precision:{widget:"combo",values:h.MODE_VALUES}};m.title="LUT";m.desc= +"Apply LUT to Texture";m.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===h.PASS_THROUGH)this.setOutputData(0,a);else if(a){var b=this.getInputData(1);b||(b=h.getTexture(this.properties.texture));if(b){b.bind(0);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D, +null);var c=this.properties.intensity;this.isInputConnected(2)&&(this.properties.intensity=c=this.getInputData(2));this._tex=h.getTargetTexture(a,this._tex,this.properties.precision);this._tex.drawTo(function(){b.bind(1);a.toViewport(m._shader,{u_texture:0,u_textureB:1,u_amount:c})});this.setOutputData(0,this._tex)}else this.setOutputData(0,a)}}};m.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform float u_amount;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\t lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\t\t\t\t mediump float blueColor = textureColor.b * 63.0;\n\t\t\t\t mediump vec2 quad1;\n\t\t\t\t quad1.y = floor(floor(blueColor) / 8.0);\n\t\t\t\t quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\t\t\t\t mediump vec2 quad2;\n\t\t\t\t quad2.y = floor(ceil(blueColor) / 8.0);\n\t\t\t\t quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\t\t\t\t highp vec2 texPos1;\n\t\t\t\t texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t highp vec2 texPos2;\n\t\t\t\t texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t\t texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t\t lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\t\t\t\t lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\t\t\t\t lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\t\t\t\t gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\t\t\t}\n\t\t\t"; +e.registerNodeType("texture/LUT",m);var a=function(){this.addInput("Texture","Texture");this.addOutput("R","Texture");this.addOutput("G","Texture");this.addOutput("B","Texture");this.addOutput("A","Texture");this.properties={};a._shader||(a._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,a.pixel_shader))};a.title="Texture to Channels";a.desc="Split texture channels";a.prototype.onExecute=function(){var b=this.getInputData(0);if(b){this._channels||(this._channels=Array(4));for(var c=0,d=0;4>d;d++)this.isOutputConnected(d)? +(this._channels[d]&&this._channels[d].width==b.width&&this._channels[d].height==b.height&&this._channels[d].type==b.type||(this._channels[d]=new GL.Texture(b.width,b.height,{type:b.type,format:gl.RGBA,filter:gl.LINEAR})),c++):this._channels[d]=null;if(c){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);for(var f=Mesh.getScreenQuad(),g=a._shader,e=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],d=0;4>d;d++)this._channels[d]&&(this._channels[d].drawTo(function(){b.bind(0);g.uniforms({u_texture:0,u_mask:e[d]}).draw(f)}), +this.setOutputData(d,this._channels[d]))}}};a.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec4 u_mask;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\t\t\t}\n\t\t\t";e.registerNodeType("texture/textureChannels",a);var b=function(){this.addInput("R","Texture");this.addInput("G","Texture");this.addInput("B","Texture");this.addInput("A", +"Texture");this.addOutput("Texture","Texture");this.properties={};b._shader||(b._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,b.pixel_shader))};b.title="Channels to Texture";b.desc="Split texture channels";b.prototype.onExecute=function(){var a=[this.getInputData(0),this.getInputData(1),this.getInputData(2),this.getInputData(3)];if(a[0]&&a[1]&&a[2]&&a[3]){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var c=Mesh.getScreenQuad(),d=b._shader;this._tex=h.getTargetTexture(a[0],this._tex);this._tex.drawTo(function(){a[0].bind(0); +a[1].bind(1);a[2].bind(2);a[3].bind(3);d.uniforms({u_textureR:0,u_textureG:1,u_textureB:2,u_textureA:3}).draw(c)});this.setOutputData(0,this._tex)}};b.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureR;\n\t\t\tuniform sampler2D u_textureG;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = vec4( \t\t\t\t\t\ttexture2D(u_textureR, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureG, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureB, v_coord).r,\t\t\t\t\t\ttexture2D(u_textureA, v_coord).r);\n\t\t\t}\n\t\t\t"; +e.registerNodeType("texture/channelsTexture",b);d=function(){this.addOutput("Texture","Texture");this._tex_color=vec4.create();this.properties={color:vec4.create(),precision:h.DEFAULT}};d.title="Color";d.desc="Generates a 1x1 texture with a constant color";d.widgets_info={precision:{widget:"combo",values:h.MODE_VALUES}};d.prototype.onDrawBackground=function(a){var b=this.properties.color;a.fillStyle="rgb("+Math.floor(255*Math.clamp(b[0],0,1))+","+Math.floor(255*Math.clamp(b[1],0,1))+","+Math.floor(255* +Math.clamp(b[2],0,1))+")";this.flags.collapsed?this.boxcolor=a.fillStyle:a.fillRect(0,0,this.size[0],this.size[1])};d.prototype.onExecute=function(){var a=this.properties.precision==h.HIGH?h.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._tex&&this._tex.type==a||(this._tex=new GL.Texture(1,1,{format:gl.RGBA,type:a,minFilter:gl.NEAREST}));a=this.properties.color;if(this.inputs)for(var b=0;b 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\t\t\t}\n\t\t\t"; +e.registerNodeType("texture/edges",g);var l=function(){this.addInput("Texture","Texture");this.addInput("Distance","number");this.addInput("Range","number");this.addOutput("Texture","Texture");this.properties={distance:100,range:50,only_depth:!1,high_precision:!1};this._uniforms={u_texture:0,u_distance:100,u_range:50,u_camera_planes:null}};l.title="Depth Range";l.desc="Generates a texture with a depth range";l.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0); if(a){var b=gl.UNSIGNED_BYTE;this.properties.high_precision&&(b=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==b&&this._temp_texture.width==a.width&&this._temp_texture.height==a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:b,format:gl.RGBA,filter:gl.LINEAR}));var c=this._uniforms,b=this.properties.distance;this.isInputConnected(1)&&(b=this.getInputData(1),this.properties.distance=b);var d=this.properties.range;this.isInputConnected(2)&& -(d=this.getInputData(2),this.properties.range=d);c.u_distance=b;c.u_range=d;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad();l._shader||(l._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,l.pixel_shader),l._shader_onlydepth=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,l.pixel_shader,{ONLY_DEPTH:""}));var g=this.properties.only_depth?l._shader_onlydepth:l._shader,b=null,b=a.near_far_planes?a.near_far_planes:window.LS&&LS.Renderer._main_camera?LS.Renderer._main_camera._uniforms.u_camera_planes: -[0.1,1E3];c.u_camera_planes=b;this._temp_texture.drawTo(function(){a.bind(0);g.uniforms(c).draw(e)});this._temp_texture.near_far_planes=b;this.setOutputData(0,this._temp_texture)}}};l.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_distance;\n\t\t\tuniform float u_range;\n\t\t\t\n\t\t\tfloat LinearDepth()\n\t\t\t{\n\t\t\t\tfloat zNear = u_camera_planes.x;\n\t\t\t\tfloat zFar = u_camera_planes.y;\n\t\t\t\tfloat depth = texture2D(u_texture, v_coord).x;\n\t\t\t\tdepth = depth * 2.0 - 1.0;\n\t\t\t\treturn zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tfloat depth = LinearDepth();\n\t\t\t\t#ifdef ONLY_DEPTH\n\t\t\t\t gl_FragColor = vec4(depth);\n\t\t\t\t#else\n\t\t\t\t\tfloat diff = abs(depth * u_camera_planes.y - u_distance);\n\t\t\t\t\tfloat dof = 1.0;\n\t\t\t\t\tif(diff <= u_range)\n\t\t\t\t\t\tdof = diff / u_range;\n\t\t\t\t gl_FragColor = vec4(dof);\n\t\t\t\t#endif\n\t\t\t}\n\t\t\t"; -h.registerNodeType("texture/depth_range",l);var n=function(){this.addInput("Texture","Texture");this.addInput("Iterations","number");this.addInput("Intensity","number");this.addOutput("Blurred","Texture");this.properties={intensity:1,iterations:1,preserve_aspect:!1,scale:[1,1],precision:f.DEFAULT}};n.title="Blur";n.desc="Blur a texture";n.widgets_info={precision:{widget:"combo",values:f.MODE_VALUES}};n.max_iterations=20;n.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b= -this._final_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(b=this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));var c=this.properties.iterations;this.isInputConnected(1)&&(c=this.getInputData(1),this.properties.iterations=c);c=Math.min(Math.floor(c),n.max_iterations);if(0==c)this.setOutputData(0,a);else{var d=this.properties.intensity;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.intensity=d);var e=h.camera_aspect; -e||void 0===window.gl||(e=gl.canvas.height/gl.canvas.width);e||(e=1);var e=this.properties.preserve_aspect?e:1,g=this.properties.scale||[1,1];a.applyBlur(e*g[0],g[1],d,b);for(a=1;a>=1;1<(c|0)&&(c>>=1);if(2>b)break;k=l[q]=GL.Texture.getTemporary(b,c,d);p[0]=1/m.width;p[1]=1/m.height;m.blit(k,h.uniforms(g));m=k}this.isOutputConnected(2)&&(b=this._average_texture,b&&b.type==a.type&&b.format==a.format||(b=this._average_texture=new GL.Texture(1,1,{type:a.type,format:a.format,filter:gl.LINEAR})),p[0]=1/m.width,p[1]=1/m.height,g.u_intensity= -t,g.u_delta=1,m.blit(b,h.uniforms(g)),this.setOutputData(2,b));gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);g.u_intensity=this.getInputOrProperty("persistence");g.u_delta=0.5;for(q-=2;0<=q;q--)k=l[q],l[q]=null,p[0]=1/m.width,p[1]=1/m.height,m.blit(k,h.uniforms(g)),GL.Texture.releaseTemporary(m),m=k;gl.disable(gl.BLEND);this.isOutputConnected(1)&&(l=this._glow_texture,l&&l.width==a.width&&l.height==a.height&&l.type==e&&l.format==a.format||(l=this._glow_texture=new GL.Texture(a.width,a.height,{type:e, -format:a.format,filter:gl.LINEAR})),m.blit(l),this.setOutputData(1,l));if(this.isOutputConnected(0)){l=this._final_texture;l&&l.width==a.width&&l.height==a.height&&l.type==e&&l.format==a.format||(l=this._final_texture=new GL.Texture(a.width,a.height,{type:e,format:a.format,filter:gl.LINEAR}));var r=this.getInputData(1),s=this.getInputOrProperty("dirt_factor");g.u_intensity=t;h=r?y._dirt_final_shader:y._final_shader;h||(h=r?y._dirt_final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,y.final_pixel_shader, -{USE_DIRT:""}):y._final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,y.final_pixel_shader));l.drawTo(function(){a.bind(0);m.bind(1);r&&(h.setUniform("u_dirt_factor",s),h.setUniform("u_dirt_texture",r.bind(2)));h.toViewport(g)});this.setOutputData(0,l)}GL.Texture.releaseTemporary(m)}};y.cut_pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_threshold;\n\t\tvoid main() {\n\t\t\tgl_FragColor = max( texture2D( u_texture, v_coord ) - vec4( u_threshold ), vec4(0.0) );\n\t\t}"; -y.scale_pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec2 u_texel_size;\n\t\tuniform float u_delta;\n\t\tuniform float u_intensity;\n\t\t\n\t\tvec4 sampleBox(vec2 uv) {\n\t\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\t\tvec4 s = texture2D( u_texture, uv + o.xy ) + texture2D( u_texture, uv + o.zy) + texture2D( u_texture, uv + o.xw) + texture2D( u_texture, uv + o.zw);\n\t\t\treturn s * 0.25;\n\t\t}\n\t\tvoid main() {\n\t\t\tgl_FragColor = u_intensity * sampleBox( v_coord );\n\t\t}"; -y.final_pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_glow_texture;\n\t\t#ifdef USE_DIRT\n\t\t\tuniform sampler2D u_dirt_texture;\n\t\t#endif\n\t\tuniform vec2 u_texel_size;\n\t\tuniform float u_delta;\n\t\tuniform float u_intensity;\n\t\tuniform float u_dirt_factor;\n\t\t\n\t\tvec4 sampleBox(vec2 uv) {\n\t\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\t\tvec4 s = texture2D( u_glow_texture, uv + o.xy ) + texture2D( u_glow_texture, uv + o.zy) + texture2D( u_glow_texture, uv + o.xw) + texture2D( u_glow_texture, uv + o.zw);\n\t\t\treturn s * 0.25;\n\t\t}\n\t\tvoid main() {\n\t\t\tvec4 glow = sampleBox( v_coord );\n\t\t\t#ifdef USE_DIRT\n\t\t\t\tglow = mix( glow, glow * texture2D( u_dirt_texture, v_coord ), u_dirt_factor );\n\t\t\t#endif\n\t\t\tgl_FragColor = texture2D( u_texture, v_coord ) + u_intensity * glow;\n\t\t}"; -h.registerNodeType("texture/glow",y);var C=function(){this.addInput("Texture","Texture");this.addOutput("Filtered","Texture");this.properties={intensity:1,radius:5}};C.title="Kuwahara Filter";C.desc="Filters a texture giving an artistic oil canvas painting";C.max_radius=10;C._shaders=[];C.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b=this._temp_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(this._temp_texture=new GL.Texture(a.width, -a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));b=this.properties.radius;b=Math.min(Math.floor(b),C.max_radius);if(0==b)this.setOutputData(0,a);else{var c=this.properties.intensity,d=h.camera_aspect;d||void 0===window.gl||(d=gl.canvas.height/gl.canvas.width);d||(d=1);d=this.properties.preserve_aspect?d:1;C._shaders[b]||(C._shaders[b]=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,C.pixel_shader,{RADIUS:b.toFixed(0)}));var e=C._shaders[b],g=GL.Mesh.getScreenQuad();a.bind(0);this._temp_texture.drawTo(function(){e.uniforms({u_texture:0, -u_intensity:c,u_resolution:[a.width,a.height],u_iResolution:[1/a.width,1/a.height]}).draw(g)});this.setOutputData(0,this._temp_texture)}}};C.pixel_shader="\n\tprecision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform float u_intensity;\n\tuniform vec2 u_resolution;\n\tuniform vec2 u_iResolution;\n\t#ifndef RADIUS\n\t\t#define RADIUS 7\n\t#endif\n\tvoid main() {\n\t\n\t\tconst int radius = RADIUS;\n\t\tvec2 fragCoord = v_coord;\n\t\tvec2 src_size = u_iResolution;\n\t\tvec2 uv = v_coord;\n\t\tfloat n = float((radius + 1) * (radius + 1));\n\t\tint i;\n\t\tint j;\n\t\tvec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0);\n\t\tvec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0);\n\t\tvec3 c;\n\t\t\n\t\tfor (int j = -radius; j <= 0; ++j) {\n\t\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm0 += c;\n\t\t\t\ts0 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (int j = -radius; j <= 0; ++j) {\n\t\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm1 += c;\n\t\t\t\ts1 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (int j = 0; j <= radius; ++j) {\n\t\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm2 += c;\n\t\t\t\ts2 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (int j = 0; j <= radius; ++j) {\n\t\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm3 += c;\n\t\t\t\ts3 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfloat min_sigma2 = 1e+2;\n\t\tm0 /= n;\n\t\ts0 = abs(s0 / n - m0 * m0);\n\t\t\n\t\tfloat sigma2 = s0.r + s0.g + s0.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m0, 1.0);\n\t\t}\n\t\t\n\t\tm1 /= n;\n\t\ts1 = abs(s1 / n - m1 * m1);\n\t\t\n\t\tsigma2 = s1.r + s1.g + s1.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m1, 1.0);\n\t\t}\n\t\t\n\t\tm2 /= n;\n\t\ts2 = abs(s2 / n - m2 * m2);\n\t\t\n\t\tsigma2 = s2.r + s2.g + s2.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m2, 1.0);\n\t\t}\n\t\t\n\t\tm3 /= n;\n\t\ts3 = abs(s3 / n - m3 * m3);\n\t\t\n\t\tsigma2 = s3.r + s3.g + s3.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m3, 1.0);\n\t\t}\n\t}\n\t"; -h.registerNodeType("texture/kuwahara",C);d=function(){this.addOutput("Webcam","Texture");this.properties={texture_name:"",facingMode:"user"};this.boxcolor="black";this.version=0};d.title="Webcam";d.desc="Webcam texture";d.prototype.openStream=function(){function a(c){console.log("Webcam rejected",c);b._webcam_stream=!1;b.boxcolor="red";b.trigger("stream_error")}if(navigator.getUserMedia){this._waiting_confirmation=!0;navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:this.properties.facingMode}}).then(this.streamReady.bind(this))["catch"](a); +(d=this.getInputData(2),this.properties.range=d);c.u_distance=b;c.u_range=d;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var f=Mesh.getScreenQuad();l._shader||(l._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,l.pixel_shader),l._shader_onlydepth=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,l.pixel_shader,{ONLY_DEPTH:""}));var g=this.properties.only_depth?l._shader_onlydepth:l._shader,b=null,b=a.near_far_planes?a.near_far_planes:window.LS&&LS.Renderer._main_camera?LS.Renderer._main_camera._uniforms.u_camera_planes: +[0.1,1E3];c.u_camera_planes=b;this._temp_texture.drawTo(function(){a.bind(0);g.uniforms(c).draw(f)});this._temp_texture.near_far_planes=b;this.setOutputData(0,this._temp_texture)}}};l.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_distance;\n\t\t\tuniform float u_range;\n\t\t\t\n\t\t\tfloat LinearDepth()\n\t\t\t{\n\t\t\t\tfloat zNear = u_camera_planes.x;\n\t\t\t\tfloat zFar = u_camera_planes.y;\n\t\t\t\tfloat depth = texture2D(u_texture, v_coord).x;\n\t\t\t\tdepth = depth * 2.0 - 1.0;\n\t\t\t\treturn zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tfloat depth = LinearDepth();\n\t\t\t\t#ifdef ONLY_DEPTH\n\t\t\t\t gl_FragColor = vec4(depth);\n\t\t\t\t#else\n\t\t\t\t\tfloat diff = abs(depth * u_camera_planes.y - u_distance);\n\t\t\t\t\tfloat dof = 1.0;\n\t\t\t\t\tif(diff <= u_range)\n\t\t\t\t\t\tdof = diff / u_range;\n\t\t\t\t gl_FragColor = vec4(dof);\n\t\t\t\t#endif\n\t\t\t}\n\t\t\t"; +e.registerNodeType("texture/depth_range",l);var q=function(){this.addInput("Texture","Texture");this.addInput("Iterations","number");this.addInput("Intensity","number");this.addOutput("Blurred","Texture");this.properties={intensity:1,iterations:1,preserve_aspect:!1,scale:[1,1],precision:h.DEFAULT}};q.title="Blur";q.desc="Blur a texture";q.widgets_info={precision:{widget:"combo",values:h.MODE_VALUES}};q.max_iterations=20;q.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b= +this._final_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(b=this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));var c=this.properties.iterations;this.isInputConnected(1)&&(c=this.getInputData(1),this.properties.iterations=c);c=Math.min(Math.floor(c),q.max_iterations);if(0==c)this.setOutputData(0,a);else{var d=this.properties.intensity;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.intensity=d);var f=e.camera_aspect; +f||void 0===window.gl||(f=gl.canvas.height/gl.canvas.width);f||(f=1);var f=this.properties.preserve_aspect?f:1,g=this.properties.scale||[1,1];a.applyBlur(f*g[0],g[1],d,b);for(a=1;a>=1;1<(c|0)&&(c>>=1);if(2>b)break;k=e[p]=GL.Texture.getTemporary(b,c,d);n[0]=1/m.width;n[1]=1/m.height;m.blit(k,l.uniforms(g));m=k}this.isOutputConnected(2)&&(b=this._average_texture,b&&b.type==a.type&&b.format==a.format||(b=this._average_texture=new GL.Texture(1,1,{type:a.type,format:a.format,filter:gl.LINEAR})),n[0]=1/m.width,n[1]=1/m.height,g.u_intensity= +r,g.u_delta=1,m.blit(b,l.uniforms(g)),this.setOutputData(2,b));gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);g.u_intensity=this.getInputOrProperty("persistence");g.u_delta=0.5;for(p-=2;0<=p;p--)k=e[p],e[p]=null,n[0]=1/m.width,n[1]=1/m.height,m.blit(k,l.uniforms(g)),GL.Texture.releaseTemporary(m),m=k;gl.disable(gl.BLEND);this.isOutputConnected(1)&&(e=this._glow_texture,e&&e.width==a.width&&e.height==a.height&&e.type==f&&e.format==a.format||(e=this._glow_texture=new GL.Texture(a.width,a.height,{type:f, +format:a.format,filter:gl.LINEAR})),m.blit(e),this.setOutputData(1,e));if(this.isOutputConnected(0)){e=this._final_texture;e&&e.width==a.width&&e.height==a.height&&e.type==f&&e.format==a.format||(e=this._final_texture=new GL.Texture(a.width,a.height,{type:f,format:a.format,filter:gl.LINEAR}));var s=this.getInputData(1),t=this.getInputOrProperty("dirt_factor");g.u_intensity=r;l=s?z._dirt_final_shader:z._final_shader;l||(l=s?z._dirt_final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,z.final_pixel_shader, +{USE_DIRT:""}):z._final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,z.final_pixel_shader));e.drawTo(function(){a.bind(0);m.bind(1);s&&(l.setUniform("u_dirt_factor",t),l.setUniform("u_dirt_texture",s.bind(2)));l.toViewport(g)});this.setOutputData(0,e)}GL.Texture.releaseTemporary(m)}};z.cut_pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_threshold;\n\t\tvoid main() {\n\t\t\tgl_FragColor = max( texture2D( u_texture, v_coord ) - vec4( u_threshold ), vec4(0.0) );\n\t\t}"; +z.scale_pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec2 u_texel_size;\n\t\tuniform float u_delta;\n\t\tuniform float u_intensity;\n\t\t\n\t\tvec4 sampleBox(vec2 uv) {\n\t\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\t\tvec4 s = texture2D( u_texture, uv + o.xy ) + texture2D( u_texture, uv + o.zy) + texture2D( u_texture, uv + o.xw) + texture2D( u_texture, uv + o.zw);\n\t\t\treturn s * 0.25;\n\t\t}\n\t\tvoid main() {\n\t\t\tgl_FragColor = u_intensity * sampleBox( v_coord );\n\t\t}"; +z.final_pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_glow_texture;\n\t\t#ifdef USE_DIRT\n\t\t\tuniform sampler2D u_dirt_texture;\n\t\t#endif\n\t\tuniform vec2 u_texel_size;\n\t\tuniform float u_delta;\n\t\tuniform float u_intensity;\n\t\tuniform float u_dirt_factor;\n\t\t\n\t\tvec4 sampleBox(vec2 uv) {\n\t\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\t\tvec4 s = texture2D( u_glow_texture, uv + o.xy ) + texture2D( u_glow_texture, uv + o.zy) + texture2D( u_glow_texture, uv + o.xw) + texture2D( u_glow_texture, uv + o.zw);\n\t\t\treturn s * 0.25;\n\t\t}\n\t\tvoid main() {\n\t\t\tvec4 glow = sampleBox( v_coord );\n\t\t\t#ifdef USE_DIRT\n\t\t\t\tglow = mix( glow, glow * texture2D( u_dirt_texture, v_coord ), u_dirt_factor );\n\t\t\t#endif\n\t\t\tgl_FragColor = texture2D( u_texture, v_coord ) + u_intensity * glow;\n\t\t}"; +e.registerNodeType("texture/glow",z);var A=function(){this.addInput("Texture","Texture");this.addOutput("Filtered","Texture");this.properties={intensity:1,radius:5}};A.title="Kuwahara Filter";A.desc="Filters a texture giving an artistic oil canvas painting";A.max_radius=10;A._shaders=[];A.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b=this._temp_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(this._temp_texture=new GL.Texture(a.width, +a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));b=this.properties.radius;b=Math.min(Math.floor(b),A.max_radius);if(0==b)this.setOutputData(0,a);else{var c=this.properties.intensity,d=e.camera_aspect;d||void 0===window.gl||(d=gl.canvas.height/gl.canvas.width);d||(d=1);d=this.properties.preserve_aspect?d:1;A._shaders[b]||(A._shaders[b]=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,A.pixel_shader,{RADIUS:b.toFixed(0)}));var f=A._shaders[b],g=GL.Mesh.getScreenQuad();a.bind(0);this._temp_texture.drawTo(function(){f.uniforms({u_texture:0, +u_intensity:c,u_resolution:[a.width,a.height],u_iResolution:[1/a.width,1/a.height]}).draw(g)});this.setOutputData(0,this._temp_texture)}}};A.pixel_shader="\n\tprecision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform float u_intensity;\n\tuniform vec2 u_resolution;\n\tuniform vec2 u_iResolution;\n\t#ifndef RADIUS\n\t\t#define RADIUS 7\n\t#endif\n\tvoid main() {\n\t\n\t\tconst int radius = RADIUS;\n\t\tvec2 fragCoord = v_coord;\n\t\tvec2 src_size = u_iResolution;\n\t\tvec2 uv = v_coord;\n\t\tfloat n = float((radius + 1) * (radius + 1));\n\t\tint i;\n\t\tint j;\n\t\tvec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0);\n\t\tvec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0);\n\t\tvec3 c;\n\t\t\n\t\tfor (int j = -radius; j <= 0; ++j) {\n\t\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm0 += c;\n\t\t\t\ts0 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (int j = -radius; j <= 0; ++j) {\n\t\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm1 += c;\n\t\t\t\ts1 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (int j = 0; j <= radius; ++j) {\n\t\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm2 += c;\n\t\t\t\ts2 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (int j = 0; j <= radius; ++j) {\n\t\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\t\tm3 += c;\n\t\t\t\ts3 += c * c;\n\t\t\t}\n\t\t}\n\t\t\n\t\tfloat min_sigma2 = 1e+2;\n\t\tm0 /= n;\n\t\ts0 = abs(s0 / n - m0 * m0);\n\t\t\n\t\tfloat sigma2 = s0.r + s0.g + s0.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m0, 1.0);\n\t\t}\n\t\t\n\t\tm1 /= n;\n\t\ts1 = abs(s1 / n - m1 * m1);\n\t\t\n\t\tsigma2 = s1.r + s1.g + s1.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m1, 1.0);\n\t\t}\n\t\t\n\t\tm2 /= n;\n\t\ts2 = abs(s2 / n - m2 * m2);\n\t\t\n\t\tsigma2 = s2.r + s2.g + s2.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m2, 1.0);\n\t\t}\n\t\t\n\t\tm3 /= n;\n\t\ts3 = abs(s3 / n - m3 * m3);\n\t\t\n\t\tsigma2 = s3.r + s3.g + s3.b;\n\t\tif (sigma2 < min_sigma2) {\n\t\t\tmin_sigma2 = sigma2;\n\t\t\tgl_FragColor = vec4(m3, 1.0);\n\t\t}\n\t}\n\t"; +e.registerNodeType("texture/kuwahara",A);d=function(){this.addOutput("Webcam","Texture");this.properties={texture_name:"",facingMode:"user"};this.boxcolor="black";this.version=0};d.title="Webcam";d.desc="Webcam texture";d.prototype.openStream=function(){function a(c){console.log("Webcam rejected",c);b._webcam_stream=!1;b.boxcolor="red";b.trigger("stream_error")}if(navigator.getUserMedia){this._waiting_confirmation=!0;navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:this.properties.facingMode}}).then(this.streamReady.bind(this))["catch"](a); var b=this}};d.prototype.closeStream=function(){if(this._webcam_stream){var a=this._webcam_stream.getTracks();if(a.length)for(var b=0;b=this.size[1]||!this._video||(a.save(),a.webgl?this._video_texture&&a.drawImage(this._video_texture,0,0,this.size[0], this.size[1]):a.drawImage(this._video,0,0,this.size[0],this.size[1]),a.restore())};d.prototype.onExecute=function(){null!=this._webcam_stream||this._waiting_confirmation||this.openStream();if(this._video&&this._video.videoWidth){var a=this._video.videoWidth,b=this._video.videoHeight,c=this._video_texture;c&&c.width==a&&c.height==b||(this._video_texture=new GL.Texture(a,b,{format:gl.RGB,filter:gl.LINEAR}));this._video_texture.uploadImage(this._video);this._video_texture.version=++this.version;this.properties.texture_name&& -(f.getTexturesContainer()[this.properties.texture_name]=this._video_texture);this.setOutputData(0,this._video_texture);for(a=1;a=this.size[1]||a.webgl&&(gl.meshes.cube||(gl.meshes.cube=GL.Mesh.cube({size:1})))};h.registerNodeType("texture/cubemap",d)}})(this); -(function(v){var h=v.LiteGraph;if("undefined"!=typeof GL){var f=function(){this.addInput("Texture","Texture");this.addInput("Aberration","number");this.addInput("Distortion","number");this.addInput("Blur","number");this.addOutput("Texture","Texture");this.properties={aberration:1,distortion:1,blur:1,precision:LGraphTexture.DEFAULT};f._shader||(f._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,f.pixel_shader),f._texture=new GL.Texture(3,1,{format:gl.RGB,wrap:gl.CLAMP_TO_EDGE,magFilter:gl.LINEAR, -minFilter:gl.LINEAR,pixel_data:[255,0,0,0,255,0,0,0,255]}))};f.title="Lens";f.desc="Camera Lens distortion";f.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};f.prototype.onExecute=function(){var d=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,d);else if(d){this._tex=LGraphTexture.getTargetTexture(d,this._tex,this.properties.precision);var h=this.properties.aberration;this.isInputConnected(1)&&(h=this.getInputData(1), -this.properties.aberration=h);var q=this.properties.distortion;this.isInputConnected(2)&&(q=this.getInputData(2),this.properties.distortion=q);var k=this.properties.blur;this.isInputConnected(3)&&(k=this.getInputData(3),this.properties.blur=k);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var m=Mesh.getScreenQuad(),b=f._shader;this._tex.drawTo(function(){d.bind(0);b.uniforms({u_texture:0,u_aberration:h,u_distortion:q,u_blur:k}).draw(m)});this.setOutputData(0,this._tex)}};f.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_aberration;\n\t\t\tuniform float u_distortion;\n\t\t\tuniform float u_blur;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 coord = v_coord;\n\t\t\t\tfloat dist = distance(vec2(0.5), coord);\n\t\t\t\tvec2 dist_coord = coord - vec2(0.5);\n\t\t\t\tfloat percent = 1.0 + ((0.5 - dist) / 0.5) * u_distortion;\n\t\t\t\tdist_coord *= percent;\n\t\t\t\tcoord = dist_coord + vec2(0.5);\n\t\t\t\tvec4 color = texture2D(u_texture,coord, u_blur * dist);\n\t\t\t\tcolor.r = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0+0.01*u_aberration), u_blur * dist ).r;\n\t\t\t\tcolor.b = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0-0.01*u_aberration), u_blur * dist ).b;\n\t\t\t\tgl_FragColor = color;\n\t\t\t}\n\t\t\t"; -h.registerNodeType("fx/lens",f);v.LGraphFXLens=f;var q=function(){this.addInput("Texture","Texture");this.addInput("Blurred","Texture");this.addInput("Mask","Texture");this.addInput("Threshold","number");this.addOutput("Texture","Texture");this.properties={shape:"",size:10,alpha:1,threshold:1,high_precision:!1}};q.title="Bokeh";q.desc="applies an Bokeh effect";q.widgets_info={shape:{widget:"texture"}};q.prototype.onExecute=function(){var d=this.getInputData(0),f=this.getInputData(1),h=this.getInputData(2); -if(d&&h&&this.properties.shape){f||(f=d);var k=LGraphTexture.getTexture(this.properties.shape);if(k){var m=this.properties.threshold;this.isInputConnected(3)&&(m=this.getInputData(3),this.properties.threshold=m);var b=gl.UNSIGNED_BYTE;this.properties.high_precision&&(b=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==b&&this._temp_texture.width==d.width&&this._temp_texture.height==d.height||(this._temp_texture=new GL.Texture(d.width,d.height,{type:b,format:gl.RGBA, -filter:gl.LINEAR}));var p=q._first_shader;p||(p=q._first_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,q._first_pixel_shader));var a=q._second_shader;a||(a=q._second_shader=new GL.Shader(q._second_vertex_shader,q._second_pixel_shader));var c=this._points_mesh;c&&c._width==d.width&&c._height==d.height&&2==c._spacing||(c=this.createPointsMesh(d.width,d.height,2));var e=Mesh.getScreenQuad(),r=this.properties.size,g=this.properties.alpha;gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){d.bind(0); -f.bind(1);h.bind(2);p.uniforms({u_texture:0,u_texture_blur:1,u_mask:2,u_texsize:[d.width,d.height]}).draw(e)});this._temp_texture.drawTo(function(){gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);d.bind(0);k.bind(3);a.uniforms({u_texture:0,u_mask:2,u_shape:3,u_alpha:g,u_threshold:m,u_pointSize:r,u_itexsize:[1/d.width,1/d.height]}).draw(c,gl.POINTS)});this.setOutputData(0,this._temp_texture)}}else this.setOutputData(0,d)};q.prototype.createPointsMesh=function(d,f,h){for(var k=Math.round(d/h),m=Math.round(f/ -h),b=new Float32Array(k*m*2),p=-1,a=2/d*h,c=2/f*h,e=0;e=this.size[1]||a.webgl&&(gl.meshes.cube||(gl.meshes.cube=GL.Mesh.cube({size:1})))};e.registerNodeType("texture/cubemap",d)}})(this); +(function(v){var e=v.LiteGraph;if("undefined"!=typeof GL){var h=function(){this.addInput("Texture","Texture");this.addInput("Aberration","number");this.addInput("Distortion","number");this.addInput("Blur","number");this.addOutput("Texture","Texture");this.properties={aberration:1,distortion:1,blur:1,precision:LGraphTexture.DEFAULT};h._shader||(h._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,h.pixel_shader),h._texture=new GL.Texture(3,1,{format:gl.RGB,wrap:gl.CLAMP_TO_EDGE,magFilter:gl.LINEAR, +minFilter:gl.LINEAR,pixel_data:[255,0,0,0,255,0,0,0,255]}))};h.title="Lens";h.desc="Camera Lens distortion";h.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};h.prototype.onExecute=function(){var d=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,d);else if(d){this._tex=LGraphTexture.getTargetTexture(d,this._tex,this.properties.precision);var e=this.properties.aberration;this.isInputConnected(1)&&(e=this.getInputData(1), +this.properties.aberration=e);var p=this.properties.distortion;this.isInputConnected(2)&&(p=this.getInputData(2),this.properties.distortion=p);var k=this.properties.blur;this.isInputConnected(3)&&(k=this.getInputData(3),this.properties.blur=k);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var s=Mesh.getScreenQuad(),n=h._shader;this._tex.drawTo(function(){d.bind(0);n.uniforms({u_texture:0,u_aberration:e,u_distortion:p,u_blur:k}).draw(s)});this.setOutputData(0,this._tex)}};h.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_aberration;\n\t\t\tuniform float u_distortion;\n\t\t\tuniform float u_blur;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 coord = v_coord;\n\t\t\t\tfloat dist = distance(vec2(0.5), coord);\n\t\t\t\tvec2 dist_coord = coord - vec2(0.5);\n\t\t\t\tfloat percent = 1.0 + ((0.5 - dist) / 0.5) * u_distortion;\n\t\t\t\tdist_coord *= percent;\n\t\t\t\tcoord = dist_coord + vec2(0.5);\n\t\t\t\tvec4 color = texture2D(u_texture,coord, u_blur * dist);\n\t\t\t\tcolor.r = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0+0.01*u_aberration), u_blur * dist ).r;\n\t\t\t\tcolor.b = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0-0.01*u_aberration), u_blur * dist ).b;\n\t\t\t\tgl_FragColor = color;\n\t\t\t}\n\t\t\t"; +e.registerNodeType("fx/lens",h);v.LGraphFXLens=h;var p=function(){this.addInput("Texture","Texture");this.addInput("Blurred","Texture");this.addInput("Mask","Texture");this.addInput("Threshold","number");this.addOutput("Texture","Texture");this.properties={shape:"",size:10,alpha:1,threshold:1,high_precision:!1}};p.title="Bokeh";p.desc="applies an Bokeh effect";p.widgets_info={shape:{widget:"texture"}};p.prototype.onExecute=function(){var d=this.getInputData(0),e=this.getInputData(1),h=this.getInputData(2); +if(d&&h&&this.properties.shape){e||(e=d);var k=LGraphTexture.getTexture(this.properties.shape);if(k){var s=this.properties.threshold;this.isInputConnected(3)&&(s=this.getInputData(3),this.properties.threshold=s);var n=gl.UNSIGNED_BYTE;this.properties.high_precision&&(n=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==n&&this._temp_texture.width==d.width&&this._temp_texture.height==d.height||(this._temp_texture=new GL.Texture(d.width,d.height,{type:n,format:gl.RGBA, +filter:gl.LINEAR}));var m=p._first_shader;m||(m=p._first_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,p._first_pixel_shader));var a=p._second_shader;a||(a=p._second_shader=new GL.Shader(p._second_vertex_shader,p._second_pixel_shader));var b=this._points_mesh;b&&b._width==d.width&&b._height==d.height&&2==b._spacing||(b=this.createPointsMesh(d.width,d.height,2));var c=Mesh.getScreenQuad(),f=this.properties.size,g=this.properties.alpha;gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){d.bind(0); +e.bind(1);h.bind(2);m.uniforms({u_texture:0,u_texture_blur:1,u_mask:2,u_texsize:[d.width,d.height]}).draw(c)});this._temp_texture.drawTo(function(){gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);d.bind(0);k.bind(3);a.uniforms({u_texture:0,u_mask:2,u_shape:3,u_alpha:g,u_threshold:s,u_pointSize:f,u_itexsize:[1/d.width,1/d.height]}).draw(b,gl.POINTS)});this.setOutputData(0,this._temp_texture)}}else this.setOutputData(0,d)};p.prototype.createPointsMesh=function(d,e,h){for(var k=Math.round(d/h),p=Math.round(e/ +h),n=new Float32Array(k*p*2),m=-1,a=2/d*h,b=2/e*h,c=0;c=h.NOTEON||b<=h.NOTEOFF)this.channel=d&15};Object.defineProperty(h.prototype,"velocity",{get:function(){return this.cmd==h.NOTEON?this.data[2]: --1},set:function(d){this.data[2]=d},enumerable:!0});h.notes="A A# B C C# D D# E F F# G G#".split(" ");h.prototype.getPitch=function(){return 440*Math.pow(2,(this.data[1]-69)/12)};h.computePitch=function(d){return 440*Math.pow(2,(d-69)/12)};h.prototype.getCC=function(){return this.data[1]};h.prototype.getCCValue=function(){return this.data[2]};h.prototype.getPitchBend=function(){return this.data[1]+(this.data[2]<<7)-8192};h.computePitchBend=function(d,b){return d+(b<<7)-8192};h.prototype.setCommandFromString= -function(d){this.cmd=h.computeCommandFromString(d)};h.computeCommandFromString=function(d){if(!d)return 0;if(d&&d.constructor===Number)return d;d=d.toUpperCase();switch(d){case "NOTE ON":case "NOTEON":return h.NOTEON;case "NOTE OFF":case "NOTEOFF":return h.NOTEON;case "KEY PRESSURE":case "KEYPRESSURE":return h.KEYPRESSURE;case "CONTROLLER CHANGE":case "CONTROLLERCHANGE":case "CC":return h.CONTROLLERCHANGE;case "PROGRAM CHANGE":case "PROGRAMCHANGE":case "PC":return h.PROGRAMCHANGE;case "CHANNEL PRESSURE":case "CHANNELPRESSURE":return h.CHANNELPRESSURE; -case "PITCH BEND":case "PITCHBEND":return h.PITCHBEND;case "TIME TICK":case "TIMETICK":return h.TIMETICK;default:return Number(d)}};h.toNoteString=function(d){var b;b=(d-21)%12;0>b&&(b=12+b);return h.notes[b]+Math.floor((d-24)/12+1)};h.prototype.toString=function(){var d=""+this.channel+". ";switch(this.cmd){case h.NOTEON:d+="NOTEON "+h.toNoteString(this.data[1]);break;case h.NOTEOFF:d+="NOTEOFF "+h.toNoteString(this.data[1]);break;case h.CONTROLLERCHANGE:d+="CC "+this.data[1]+" "+this.data[2];break; -case h.PROGRAMCHANGE:d+="PC "+this.data[1];break;case h.PITCHBEND:d+="PITCHBEND "+this.getPitchBend();break;case h.KEYPRESSURE:d+="KEYPRESS "+this.data[1]}return d};h.prototype.toHexString=function(){for(var d="",b=0;bthis.properties.max_value||this.trigger("on_midi",b)};k.registerNodeType("midi/filter",t);w.title="MIDIEvent";w.desc="Create a MIDI Event";w.prototype.onAction=function(d,b){"assign"==d?(this.properties.channel=b.channel,this.properties.cmd=b.cmd,this.properties.value1= -b.data[1],this.properties.value2=b.data[2]):(b=new h,b.channel=this.properties.channel,this.properties.cmd&&this.properties.cmd.constructor===String?b.setCommandFromString(this.properties.cmd):b.cmd=this.properties.cmd,b.data[0]=b.cmd|b.channel,b.data[1]=Number(this.properties.value1),b.data[2]=Number(this.properties.value2),this.trigger("on_midi",b))};w.prototype.onExecute=function(){var d=this.properties;if(this.outputs)for(var b=0;b=e.NOTEON||c<=e.NOTEOFF)this.channel=a&15};Object.defineProperty(e.prototype,"velocity",{get:function(){return this.cmd==e.NOTEON?this.data[2]:-1},set:function(a){this.data[2]=a},enumerable:!0});e.notes="A A# B C C# D D# E F F# G G#".split(" ");e.note_to_index={A:0,"A#":1,B:2,C:3,"C#":4,D:5,"D#":6,E:7,F:8,"F#":9,G:10,"G#":11};Object.defineProperty(e.prototype,"note",{get:function(){return this.cmd!=e.NOTEON?-1:e.toNoteString(this.data[1],!0)},set:function(a){throw"notes cannot be assigned this way, must modify the data[1]"; +},enumerable:!0});Object.defineProperty(e.prototype,"octave",{get:function(){return this.cmd!=e.NOTEON?-1:Math.floor((this.data[1]-24)/12+1)},set:function(a){throw"octave cannot be assigned this way, must modify the data[1]";},enumerable:!0});e.prototype.getPitch=function(){return 440*Math.pow(2,(this.data[1]-69)/12)};e.computePitch=function(a){return 440*Math.pow(2,(a-69)/12)};e.prototype.getCC=function(){return this.data[1]};e.prototype.getCCValue=function(){return this.data[2]};e.prototype.getPitchBend= +function(){return this.data[1]+(this.data[2]<<7)-8192};e.computePitchBend=function(a,c){return a+(c<<7)-8192};e.prototype.setCommandFromString=function(a){this.cmd=e.computeCommandFromString(a)};e.computeCommandFromString=function(a){if(!a)return 0;if(a&&a.constructor===Number)return a;a=a.toUpperCase();switch(a){case "NOTE ON":case "NOTEON":return e.NOTEON;case "NOTE OFF":case "NOTEOFF":return e.NOTEON;case "KEY PRESSURE":case "KEYPRESSURE":return e.KEYPRESSURE;case "CONTROLLER CHANGE":case "CONTROLLERCHANGE":case "CC":return e.CONTROLLERCHANGE; +case "PROGRAM CHANGE":case "PROGRAMCHANGE":case "PC":return e.PROGRAMCHANGE;case "CHANNEL PRESSURE":case "CHANNELPRESSURE":return e.CHANNELPRESSURE;case "PITCH BEND":case "PITCHBEND":return e.PITCHBEND;case "TIME TICK":case "TIMETICK":return e.TIMETICK;default:return Number(a)}};e.toNoteString=function(a,c){a=Math.round(a);var d,g=Math.floor((a-24)/12+1);d=(a-21)%12;0>d&&(d=12+d);return e.notes[d]+(c?"":g)};e.NoteStringToPitch=function(a){a=a.toUpperCase();var c=a[0],d=4;"#"==a[1]?(c+="#",2this.properties.max_value||this.trigger("on_midi",c)};a.registerNodeType("midi/filter",r);t.title="MIDIEvent";t.desc="Create a MIDI Event";t.prototype.onAction=function(a,c){"assign"==a?(this.properties.channel=c.channel,this.properties.cmd=c.cmd,this.properties.value1=c.data[1],this.properties.value2=c.data[2]):(c=this.midi_event,c.channel=this.properties.channel,this.properties.cmd&& +this.properties.cmd.constructor===String?c.setCommandFromString(this.properties.cmd):c.cmd=this.properties.cmd,c.data[0]=c.cmd|c.channel,c.data[1]=Number(this.properties.value1),c.data[2]=Number(this.properties.value2),this.trigger("on_midi",c))};t.prototype.onExecute=function(){var a=this.properties;if(this.inputs)for(var c=0;ca;++a)this.valid_notes[a]=-1!=this.notes_pitches.indexOf(a);for(a=0;12>a;++a)if(this.valid_notes[a])this.offset_notes[a]=0;else for(var c=1;12>c;++c){if(this.valid_notes[(a-c)%12]){this.offset_notes[a]=-c;break}if(this.valid_notes[(a+c)%12]){this.offset_notes[a]=c;break}}};n.prototype.onAction=function(a,c){this.midi_event.setup(c.data); +this.midi_event.data[1]+=this.offset_notes[e.note_to_index[c.note]];this.trigger("out",this.midi_event)};n.prototype.onExecute=function(){var a=this.getInputData(1);null!=a&&a!=this._current_scale&&this.processScale(a)};a.registerNodeType("midi/quantize",n);m.title="MIDI Play";m.desc="Plays a MIDI note";m.prototype.onAction=function(a,c){if(this.instrument){var d=c.note;d&&"undefined"!=d&&d.constructor===String&&(this.instrument.play(d,c.octave,this.properties.duration,this.properties.volume),this.trigger("note", +c))}};m.prototype.onExecute=function(){var a=this.getInputData(1);null!=a&&(this.properties.volume=a);a=this.getInputData(2);null!=a&&(this.properties.duration=a)};a.registerNodeType("midi/play",m)})(this); +(function(v){function e(){this.properties={src:"",gain:0.5,loop:!0,autoplay:!0,playbackRate:1};this._loading_audio=!1;this._audiobuffer=null;this._audionodes=[];this._last_sourcenode=null;this.addOutput("out","audio");this.addInput("gain","number");this.audionode=g.getAudioContext().createGain();this.audionode.graphnode=this;this.audionode.gain.value=this.properties.gain;this.properties.src&&this.loadSound(this.properties.src)}function h(){this.properties={gain:0.5};this._audionodes=[];this._media_stream= +null;this.addOutput("out","audio");this.addInput("gain","number");this.audionode=g.getAudioContext().createGain();this.audionode.graphnode=this;this.audionode.gain.value=this.properties.gain}function p(){this.properties={fftSize:2048,minDecibels:-100,maxDecibels:-10,smoothingTimeConstant:0.5};this.audionode=g.getAudioContext().createAnalyser();this.audionode.graphnode=this;this.audionode.fftSize=this.properties.fftSize;this.audionode.minDecibels=this.properties.minDecibels;this.audionode.maxDecibels= +this.properties.maxDecibels;this.audionode.smoothingTimeConstant=this.properties.smoothingTimeConstant;this.addInput("in","audio");this.addOutput("freqs","array");this.addOutput("samples","array");this._time_bin=this._freq_bin=null}function d(){this.properties={gain:1};this.audionode=g.getAudioContext().createGain();this.addInput("in","audio");this.addInput("gain","number");this.addOutput("out","audio")}function s(){this.properties={impulse_src:"",normalize:!0};this.audionode=g.getAudioContext().createConvolver(); +this.addInput("in","audio");this.addOutput("out","audio")}function r(){this.properties={threshold:-50,knee:40,ratio:12,reduction:-20,attack:0,release:0.25};this.audionode=g.getAudioContext().createDynamicsCompressor();this.addInput("in","audio");this.addOutput("out","audio")}function t(){this.properties={};this.audionode=g.getAudioContext().createWaveShaper();this.addInput("in","audio");this.addInput("shape","waveshape");this.addOutput("out","audio")}function y(){this.properties={gain1:0.5,gain2:0.5}; this.audionode=g.getAudioContext().createGain();this.audionode1=g.getAudioContext().createGain();this.audionode1.gain.value=this.properties.gain1;this.audionode2=g.getAudioContext().createGain();this.audionode2.gain.value=this.properties.gain2;this.audionode1.connect(this.audionode);this.audionode2.connect(this.audionode);this.addInput("in1","audio");this.addInput("in1 gain","number");this.addInput("in2","audio");this.addInput("in2 gain","number");this.addOutput("out","audio")}function k(){this.properties= -{delayTime:0.5};this.audionode=g.getAudioContext().createDelay(10);this.audionode.delayTime.value=this.properties.delayTime;this.addInput("in","audio");this.addInput("time","number");this.addOutput("out","audio")}function m(){this.properties={frequency:350,detune:0,Q:1};this.addProperty("type","lowpass","enum",{values:"lowpass highpass bandpass lowshelf highshelf peaking notch allpass".split(" ")});this.audionode=g.getAudioContext().createBiquadFilter();this.addInput("in","audio");this.addOutput("out", -"audio")}function b(){this.properties={frequency:440,detune:0,type:"sine"};this.addProperty("type","sine","enum",{values:["sine","square","sawtooth","triangle","custom"]});this.audionode=g.getAudioContext().createOscillator();this.addOutput("out","audio")}function p(){this.properties={continuous:!0,mark:-1};this.addInput("data","array");this.addInput("mark","number");this.size=[300,200];this._last_buffer=null}function a(){this.properties={band:440,amplitude:1};this.addInput("freqs","array");this.addOutput("signal", -"number")}function c(){if(!c.default_code){var a=c.default_function.toString(),b=a.indexOf("{")+1,d=a.lastIndexOf("}");c.default_code=a.substr(b,d-b)}this.properties={code:c.default_code};a=g.getAudioContext();a.createScriptProcessor?this.audionode=a.createScriptProcessor(4096,1,1):(console.warn("ScriptProcessorNode deprecated"),this.audionode=a.createGain());this.processCode();c._bypass_function||(c._bypass_function=this.audionode.onaudioprocess);this.addInput("in","audio");this.addOutput("out", -"audio")}function e(){this.audionode=g.getAudioContext().destination;this.addInput("in","audio")}var s=v.LiteGraph,g={};v.LGAudio=g;g.getAudioContext=function(){if(!this._audio_context){window.AudioContext=window.AudioContext||window.webkitAudioContext;if(!window.AudioContext)return console.error("AudioContext not supported by browser"),null;this._audio_context=new AudioContext;this._audio_context.onmessage=function(a){console.log("msg",a)};this._audio_context.onended=function(a){console.log("ended", -a)};this._audio_context.oncomplete=function(a){console.log("complete",a)}}return this._audio_context};g.connect=function(a,b){try{a.connect(b)}catch(c){console.warn("LGraphAudio:",c)}};g.disconnect=function(a,b){try{a.disconnect(b)}catch(c){console.warn("LGraphAudio:",c)}};g.changeAllAudiosConnections=function(a,b){if(a.inputs)for(var c=0;c=this.size[0]&&(e=this.size[0]-1),a.strokeStyle="red",a.beginPath(),a.moveTo(e,d),a.lineTo(e,0),a.stroke())}};p.title="Visualization";p.desc="Audio Visualization";s.registerNodeType("audio/visualization",p);a.prototype.onExecute=function(){if(this._freqs=this.getInputData(0)){var a=this.properties.band,b=this.getInputData(1);void 0!==b&&(a=b);b=g.getAudioContext().sampleRate/this._freqs.length; -b=a/b*2;b>=this._freqs.length?b=this._freqs[this._freqs.length-1]:(a=b|0,b-=a,b=this._freqs[a]*(1-b)+this._freqs[a+1]*b);this.setOutputData(0,b/255*this.properties.amplitude)}};a.prototype.onGetInputs=function(){return[["band","number"]]};a.title="Signal";a.desc="extract the signal of some frequency";s.registerNodeType("audio/signal",a);c.prototype.onAdded=function(a){a.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback)};c["@code"]={widget:"code"};c.prototype.onStart=function(){this.audionode.onaudioprocess= -this._callback};c.prototype.onStop=function(){this.audionode.onaudioprocess=c._bypass_function};c.prototype.onPause=function(){this.audionode.onaudioprocess=c._bypass_function};c.prototype.onUnpause=function(){this.audionode.onaudioprocess=this._callback};c.prototype.onExecute=function(){};c.prototype.onRemoved=function(){this.audionode.onaudioprocess=c._bypass_function};c.prototype.processCode=function(){try{this._script=new new Function("properties",this.properties.code)(this.properties),this._old_code= -this.properties.code,this._callback=this._script.onaudioprocess}catch(a){console.error("Error in onaudioprocess code",a),this._callback=c._bypass_function,this.audionode.onaudioprocess=this._callback}};c.prototype.onPropertyChanged=function(a,b){"code"==a&&(this.properties.code=b,this.processCode(),this.graph&&this.graph.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback))};c.default_function=function(){this.onaudioprocess=function(a){var b=a.inputBuffer;a=a.outputBuffer; -for(var c=0;c=this.size[0]&&(f=this.size[0]-1),a.strokeStyle="red",a.beginPath(),a.moveTo(f,d),a.lineTo(f,0),a.stroke())}};m.title="Visualization";m.desc="Audio Visualization";f.registerNodeType("audio/visualization",m);a.prototype.onExecute=function(){if(this._freqs=this.getInputData(0)){var a=this.properties.band,b=this.getInputData(1);void 0!==b&&(a=b);b=g.getAudioContext().sampleRate/this._freqs.length; +b=a/b*2;b>=this._freqs.length?b=this._freqs[this._freqs.length-1]:(a=b|0,b-=a,b=this._freqs[a]*(1-b)+this._freqs[a+1]*b);this.setOutputData(0,b/255*this.properties.amplitude)}};a.prototype.onGetInputs=function(){return[["band","number"]]};a.title="Signal";a.desc="extract the signal of some frequency";f.registerNodeType("audio/signal",a);b.prototype.onAdded=function(a){a.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback)};b["@code"]={widget:"code"};b.prototype.onStart=function(){this.audionode.onaudioprocess= +this._callback};b.prototype.onStop=function(){this.audionode.onaudioprocess=b._bypass_function};b.prototype.onPause=function(){this.audionode.onaudioprocess=b._bypass_function};b.prototype.onUnpause=function(){this.audionode.onaudioprocess=this._callback};b.prototype.onExecute=function(){};b.prototype.onRemoved=function(){this.audionode.onaudioprocess=b._bypass_function};b.prototype.processCode=function(){try{this._script=new new Function("properties",this.properties.code)(this.properties),this._old_code= +this.properties.code,this._callback=this._script.onaudioprocess}catch(a){console.error("Error in onaudioprocess code",a),this._callback=b._bypass_function,this.audionode.onaudioprocess=this._callback}};b.prototype.onPropertyChanged=function(a,b){"code"==a&&(this.properties.code=b,this.processCode(),this.graph&&this.graph.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback))};b.default_function=function(){this.onaudioprocess=function(a){var b=a.inputBuffer;a=a.outputBuffer; +for(var c=0;c + + - + diff --git a/demo/js/code.js b/demo/js/code.js index 1b93a3752..a2252aa51 100644 --- a/demo/js/code.js +++ b/demo/js/code.js @@ -5,6 +5,10 @@ window.graphcanvas = editor.graphcanvas; window.graph = editor.graph; window.addEventListener("resize", function() { editor.graphcanvas.resize(); } ); window.addEventListener("keydown", editor.graphcanvas.processKey.bind(editor.graphcanvas) ); +window.onbeforeunload = function(){ + var data = JSON.stringify( graph.serialize() ); + localStorage.setItem("litegraphg demo backup", data ); +} //create scene selector var elem = document.createElement("span"); @@ -18,6 +22,8 @@ select.addEventListener("change", function(e){ if(url) graph.load( url ); + else if(option.callback) + option.callback(); else graph.clear(); }); @@ -37,7 +43,10 @@ elem.querySelector("#load").addEventListener("click",function(){ function addDemo( name, url ) { var option = document.createElement("option"); - option.dataset["url"] = url; + if(url.constructor === String) + option.dataset["url"] = url; + else + option.callback = url; option.innerHTML = name; select.appendChild( option ); } @@ -48,6 +57,14 @@ addDemo("Benchmark", "examples/benchmark.json"); addDemo("Audio", "examples/audio.json"); addDemo("Audio Delay", "examples/audio_delay.json"); addDemo("Audio Reverb", "examples/audio_reverb.json"); +addDemo("MIDI Generation", "examples/midi_generation.json"); +addDemo("autobackup", function(){ + var data = localStorage.getItem("litegraphg demo backup"); + if(!data) + return; + var graph_data = JSON.parse(data); + graph.configure( graph_data ); +}); diff --git a/demo/js/demos.js b/demo/js/demos.js index 48e5ffc0c..83d2183c8 100644 --- a/demo/js/demos.js +++ b/demo/js/demos.js @@ -191,7 +191,7 @@ function TestSlotsNode() this.addInput("C","number"); this.addOutput("A","number"); this.addOutput("B","number"); - this.flags = { horizontal: true }; + this.horizontal = true; this.size = [100,40]; } diff --git a/demo/js/libs/audiosynth.js b/demo/js/libs/audiosynth.js new file mode 100644 index 000000000..beb0cc53d --- /dev/null +++ b/demo/js/libs/audiosynth.js @@ -0,0 +1,356 @@ +var Synth, AudioSynth, AudioSynthInstrument; +!function(){ + + var URL = window.URL || window.webkitURL; + var Blob = window.Blob; + + if(!URL || !Blob) { + throw new Error('This browser does not support AudioSynth'); + } + + var _encapsulated = false; + var AudioSynthInstance = null; + var pack = function(c,arg){ return [new Uint8Array([arg, arg >> 8]), new Uint8Array([arg, arg >> 8, arg >> 16, arg >> 24])][c]; }; + var setPrivateVar = function(n,v,w,e){Object.defineProperty(this,n,{value:v,writable:!!w,enumerable:!!e});}; + var setPublicVar = function(n,v,w){setPrivateVar.call(this,n,v,w,true);}; + AudioSynthInstrument = function AudioSynthInstrument(){this.__init__.apply(this,arguments);}; + var setPriv = setPrivateVar.bind(AudioSynthInstrument.prototype); + var setPub = setPublicVar.bind(AudioSynthInstrument.prototype); + setPriv('__init__', function(a,b,c) { + if(!_encapsulated) { throw new Error('AudioSynthInstrument can only be instantiated from the createInstrument method of the AudioSynth object.'); } + setPrivateVar.call(this, '_parent', a); + setPublicVar.call(this, 'name', b); + setPrivateVar.call(this, '_soundID', c); + }); + setPub('play', function(note, octave, duration,volume) { + return this._parent.play(this._soundID, note, octave, duration, volume); + }); + setPub('generate', function(note, octave, duration) { + return this._parent.generate(this._soundID, note, octave, duration); + }); + AudioSynth = function AudioSynth(){if(AudioSynthInstance instanceof AudioSynth){return AudioSynthInstance;}else{ this.__init__(); return this; }}; + setPriv = setPrivateVar.bind(AudioSynth.prototype); + setPub = setPublicVar.bind(AudioSynth.prototype); + setPriv('_debug',false,true); + setPriv('_bitsPerSample',16); + setPriv('_channels',1); + setPriv('_sampleRate',44100,true); + setPub('setSampleRate', function(v) { + this._sampleRate = Math.max(Math.min(v|0,44100), 4000); + this._clearCache(); + return this._sampleRate; + }); + setPub('getSampleRate', function() { return this._sampleRate; }); + setPriv('_volume',32768,true); + setPub('setVolume', function(v) { + v = parseFloat(v); if(isNaN(v)) { v = 0; } + v = Math.round(v*32768); + this._volume = Math.max(Math.min(v|0,32768), 0); + this._clearCache(); + return this._volume; + }); + setPub('getVolume', function() { return Math.round(this._volume/32768*10000)/10000; }); + setPriv('_notes',{'C':261.63,'C#':277.18,'D':293.66,'D#':311.13,'E':329.63,'F':346.23,'F#':369.99,'G':392.00,'G#':415.30,'A':440.00,'A#':466.16,'B':493.88}); + setPriv('_fileCache',[],true); + setPriv('_temp',{},true); + setPriv('_sounds',[],true); + setPriv('_mod',[function(i,s,f,x){return Math.sin((2 * Math.PI)*(i/s)*f+x);}]); + setPriv('_resizeCache', function() { + var f = this._fileCache; + var l = this._sounds.length; + while(f.length> 8; + + } + + for (; i !== decayLen; i++) { + + val = volume * Math.pow((1-((i-(sampleRate*attack))/(sampleRate*(time-attack)))),dampen) * waveFunc.call(waveBind, i, sampleRate, frequency, volume); + + data[i << 1] = val; + data[(i << 1) + 1] = val >> 8; + + } + + var out = [ + 'RIFF', + pack(1, 4 + (8 + 24/* chunk 1 length */) + (8 + 8/* chunk 2 length */)), // Length + 'WAVE', + // chunk 1 + 'fmt ', // Sub-chunk identifier + pack(1, 16), // Chunk length + pack(0, 1), // Audio format (1 is linear quantization) + pack(0, channels), + pack(1, sampleRate), + pack(1, sampleRate * channels * bitsPerSample / 8), // Byte rate + pack(0, channels * bitsPerSample / 8), + pack(0, bitsPerSample), + // chunk 2 + 'data', // Sub-chunk identifier + pack(1, data.length * channels * bitsPerSample / 8), // Chunk length + data + ]; + var blob = new Blob(out, {type: 'audio/wav'}); + var dataURI = URL.createObjectURL(blob); + this._fileCache[sound][octave-1][note][time] = dataURI; + if(this._debug) { console.log((new Date).valueOf() - t, 'ms to generate'); } + return dataURI; + } + }); + setPub('play', function(sound, note, octave, duration, volume) { + var src = this.generate( sound, note, octave, duration ); + var audio = new Audio(src); + if(volume != null) + { + if(volume <= 0) + return true; + audio.volume = volume > 1 ? 1 : volume; + } + audio.play(); + return true; + }); + setPub('debug', function() { this._debug = true; }); + setPub('createInstrument', function(sound) { + var n = 0; + var found = false; + if(typeof(sound)=='string') { + for(var i=0;i=(valueTable.length-1)?0:playVal+1] + valueTable[playVal]) * 0.5; + + if(playVal>=Math.floor(period)) { + if(playVal=p_hundredth) { + // Reset + resetPlay = true; + valueTable[playVal+1] = (valueTable[0] + valueTable[playVal+1]) * 0.5; + vars.periodCount++; + } + } else { + resetPlay = true; + } + } + + var _return = valueTable[playVal]; + if(resetPlay) { vars.playVal = 0; } else { vars.playVal++; } + + return _return; + + } + } +}, +{ + name: 'edm', + attack: function() { return 0.002; }, + dampen: function() { return 1; }, + wave: function(i, sampleRate, frequency) { + var base = this.modulate[0]; + var mod = this.modulate.slice(1); + return mod[0]( + i, + sampleRate, + frequency, + mod[9]( + i, + sampleRate, + frequency, + mod[2]( + i, + sampleRate, + frequency, + Math.pow(base(i, sampleRate, frequency, 0), 3) + + Math.pow(base(i, sampleRate, frequency, 0.5), 5) + + Math.pow(base(i, sampleRate, frequency, 1), 7) + ) + ) + + mod[8]( + i, + sampleRate, + frequency, + base(i, sampleRate, frequency, 1.75) + ) + ); + } +}); diff --git a/package.json b/package.json index 006a61f04..f32290d4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "litegraph.js", - "version": "0.6.0", + "version": "0.7.0", "description": "A graph node editor similar to PD or UDK Blueprints, it works in a HTML5 Canvas and allow to exported graphs to be included in applications.", "main": "build/litegraph.js", "directories": { @@ -28,13 +28,13 @@ }, "homepage": "https://github.com/kriffe/litegraph.js#readme", "devDependencies": { - "express": "^4.16.2", + "express": "^4.16.4", "google-closure-compiler": "^20171112.0.0", - "grunt": "^1.0.1", + "grunt": "^1.0.3", "grunt-cli": "^1.2.0", "grunt-closure-tools": "^1.0.0", "grunt-contrib-concat": "^1.0.1", - "nodemon": "^1.14.7", + "nodemon": "^1.18.9", "rimraf": "^2.6.2" } } diff --git a/src/litegraph.js b/src/litegraph.js index 865b29ca6..66aba3096 100755 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -1719,11 +1719,16 @@ LGraph.prototype.onNodeTrace = function(node, msg, color) input|output: every connection + { name:string, type:string, pos: [x,y]=Optional, direction: "input"|"output", links: Array }); - flags: + general properties: + clip_area: if you render outside the node, it will be cliped + unsafe_execution: not allowed for safe execution + skip_repeated_outputs: when adding new outputs, it wont show if there is one already connected + resizable: if set to false it wont be resizable with the mouse + + horizontal: slots are distributed horizontally + + widgets_up: widgets start from the top of the node + + flags object: + + collapsed: if it is collapsed supported callbacks: + onAdded: when added to graph @@ -2168,13 +2173,16 @@ LGraphNode.prototype.getInputOrProperty = function( name ) return this.properties ? this.properties[name] : null; for(var i = 0, l = this.inputs.length; i < l; ++i) - if(name == this.inputs[i].name) + { + var input_info = this.inputs[i]; + if(name == input_info.name && input_info.link != null) { - var link_id = this.inputs[i].link; - var link = this.graph.links[ link_id ]; - return link ? link.data : null; + var link = this.graph.links[ input_info.link ]; + if(link) + return link.data; } - return this.properties[name]; + } + return this.properties[ name ]; } @@ -3985,7 +3993,7 @@ LGraphCanvas.prototype.processMouseDown = function(e) if(!this.connecting_node && !node.flags.collapsed && !this.live_mode) { //Search for corner for resize - if( !skip_action && node.flags.resizable !== false && isInsideRectangle( e.canvasX, e.canvasY, node.pos[0] + node.size[0] - 5, node.pos[1] + node.size[1] - 5 ,10,10 )) + if( !skip_action && node.resizable !== false && isInsideRectangle( e.canvasX, e.canvasY, node.pos[0] + node.size[0] - 5, node.pos[1] + node.size[1] - 5 ,10,10 )) { this.resizing_node = node; this.canvas.style.cursor = "se-resize"; @@ -5535,6 +5543,8 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) var shape = node._shape || LiteGraph.BOX_SHAPE; var size = temp_vec2; temp_vec2.set( node.size ); + var horizontal = node.horizontal || node.flags.horizontal; + if( node.flags.collapsed ) { ctx.font = this.inner_text_font; @@ -5544,7 +5554,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) size[1] = 0; } - if( node.flags.clip_area ) //Start clipping + if( node.clip_area ) //Start clipping { ctx.save(); ctx.beginPath(); @@ -5562,7 +5572,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) ctx.shadowColor = "transparent"; //connection slots - ctx.textAlign = node.flags.horizontal ? "center" : "left"; + ctx.textAlign = horizontal ? "center" : "left"; ctx.font = this.inner_text_font; var render_text = this.scale > 0.6; @@ -5597,8 +5607,12 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) ctx.beginPath(); - if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) { - ctx.rect((pos[0] - 6) + 0.5, (pos[1] - 5) + 0.5, 14, 10); + if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) + { + if (horizontal) + ctx.rect((pos[0] - 5) + 0.5, (pos[1] - 8) + 0.5, 10, 14); + 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); @@ -5617,7 +5631,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(text) { ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR; - if( node.flags.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); @@ -5629,7 +5643,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(this.connecting_node) ctx.globalAlpha = 0.4 * editor_alpha; - ctx.textAlign = node.flags.horizontal ? "center" : "right"; + ctx.textAlign = horizontal ? "center" : "right"; ctx.strokeStyle = "black"; if(node.outputs) for(var i = 0; i < node.outputs.length; i++) @@ -5646,8 +5660,12 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) ctx.beginPath(); //ctx.rect( node.size[0] - 14,i*14,10,10); - if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) { - ctx.rect((pos[0] - 6) + 0.5,(pos[1] - 5) + 0.5,14,10); + if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) + { + if( horizontal ) + ctx.rect((pos[0] - 5) + 0.5,(pos[1] - 8) + 0.5,10,14); + 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); @@ -5672,7 +5690,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(text) { ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR; - if( node.flags.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); @@ -5685,7 +5703,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) if(node.widgets) { - if( node.flags.horizontal || node.flags.widgets_up ) + if( horizontal || node.widgets_up ) max_y = 2; this.drawNodeWidgets( node, max_y, ctx, (this.node_widget && this.node_widget[0] == node) ? this.node_widget[1] : null ); } @@ -5726,7 +5744,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) { var x = 0; var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center - if( node.flags.horizontal ) + if( horizontal ) { x = node._collapsed_width * 0.5; y = -LiteGraph.NODE_TITLE_HEIGHT; @@ -5750,7 +5768,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) { var x = node._collapsed_width; var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center - if( node.flags.horizontal ) + if( horizontal ) { x = node._collapsed_width * 0.5; y = 0; @@ -5773,7 +5791,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx ) } } - if(node.flags.clip_area) + if(node.clip_area) ctx.restore(); ctx.globalAlpha = 1.0; @@ -5869,30 +5887,33 @@ LGraphCanvas.prototype.drawNodeShape = function( node, ctx, size, fgcolor, bgcol } //title box - if (shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CIRCLE_SHAPE || shape == LiteGraph.CARD_SHAPE) + if(node.flags.render_box !== false) { - if( this.scale > 0.5 ) + if (shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CIRCLE_SHAPE || shape == LiteGraph.CARD_SHAPE) { - ctx.fillStyle = "black"; + if( this.scale > 0.5 ) + { + ctx.fillStyle = "black"; + ctx.beginPath(); + ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.5,0,Math.PI*2); + ctx.fill(); + } + + ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; ctx.beginPath(); - ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.5,0,Math.PI*2); + ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.4,0,Math.PI*2); ctx.fill(); } - - ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; - ctx.beginPath(); - ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.4,0,Math.PI*2); - ctx.fill(); - } - else - { - if( this.scale > 0.5 ) + else { - ctx.fillStyle = "black"; - ctx.fillRect(4,-title_height + 4,title_height - 8,title_height - 8); + if( this.scale > 0.5 ) + { + ctx.fillStyle = "black"; + ctx.fillRect(4,-title_height + 4,title_height - 8,title_height - 8); + } + ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; + ctx.fillRect(5,-title_height + 5,title_height - 10,title_height - 10); } - ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR; - ctx.fillRect(5,-title_height + 5,title_height - 10,title_height - 10); } ctx.globalAlpha = old_alpha; @@ -6341,6 +6362,7 @@ LGraphCanvas.prototype.drawNodeWidgets = function( node, posY, ctx, active_widge ctx.fillText( w.value, width - 40, y + H*0.7 ); } break; + case "string": case "text": ctx.textAlign = "left"; ctx.strokeStyle = "#AAA"; @@ -6463,6 +6485,7 @@ LGraphCanvas.prototype.processNodeWidgets = function( node, pos, event, active_w setTimeout( function(){ w.callback( w.value, that, node, pos ); }, 20 ); } break; + case "string": case "text": if( event.type == "mousedown" ) this.prompt( "Value", w.value, (function(v){ this.value = v; if(w.callback) w.callback(v, that, node ); }).bind(w), event ); diff --git a/src/nodes/base.js b/src/nodes/base.js index 270a04a56..c5823ff63 100755 --- a/src/nodes/base.js +++ b/src/nodes/base.js @@ -334,36 +334,55 @@ LiteGraph.registerNodeType("graph/output", GlobalOutput); //Constant -function Constant() +function ConstantNumber() { this.addOutput("value","number"); this.addProperty( "value", 1.0 ); - this.editable = { property:"value", type:"number" }; } -Constant.title = "Const"; -Constant.desc = "Constant value"; +ConstantNumber.title = "Const Number"; +ConstantNumber.desc = "Constant number"; - -Constant.prototype.setValue = function(v) -{ - if( typeof(v) == "string") v = parseFloat(v); - this.properties["value"] = v; - this.setDirtyCanvas(true); -}; - -Constant.prototype.onExecute = function() +ConstantNumber.prototype.onExecute = function() { this.setOutputData(0, parseFloat( this.properties["value"] ) ); } -Constant.prototype.onDrawBackground = function(ctx) +ConstantNumber.prototype.onDrawBackground = function(ctx) { //show the current value this.outputs[0].label = this.properties["value"].toFixed(3); } -LiteGraph.registerNodeType("basic/const", Constant); +LiteGraph.registerNodeType("basic/const", ConstantNumber); + +function ConstantString() +{ + this.addOutput("","string"); + this.addProperty( "value", "" ); + this.widget = this.addWidget("text","value","", this.setValue.bind(this) ); + this.widgets_up = true; +} + +ConstantString.title = "Const String"; +ConstantString.desc = "Constant string"; + +ConstantString.prototype.setValue = function(v) +{ + this.properties.value = v; +} + +ConstantString.prototype.onPropertyChanged = function(name,value) +{ + this.widget.value = value; +} + +ConstantString.prototype.onExecute = function() +{ + this.setOutputData(0, this.properties["value"] ); +} + +LiteGraph.registerNodeType("basic/string", ConstantString ); //Watch a value in the editor diff --git a/src/nodes/events.js b/src/nodes/events.js index a87d024ce..275fcf690 100644 --- a/src/nodes/events.js +++ b/src/nodes/events.js @@ -20,6 +20,39 @@ LogEvent.prototype.onAction = function( action, param ) LiteGraph.registerNodeType("events/log", LogEvent ); +//Sequencer for events +function Sequencer() +{ + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addInput("", LiteGraph.ACTION); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.addOutput("", LiteGraph.EVENT); + this.size = [120,30]; + this.flags = { horizontal: true, render_box: false }; +} + +Sequencer.title = "Sequencer"; +Sequencer.desc = "Trigger events when an event arrives"; + +Sequencer.prototype.getTitle = function() { return ""; } + +Sequencer.prototype.onAction = function( action, param ) +{ + if(this.outputs) + for(var i = 0; i < this.outputs.length; ++i) + this.triggerSlot( i, param ); +} + +LiteGraph.registerNodeType("events/sequencer", Sequencer ); + //Filter events function FilterEvent() { @@ -59,6 +92,52 @@ FilterEvent.prototype.onAction = function( action, param ) LiteGraph.registerNodeType("events/filter", FilterEvent ); + +//Show value inside the debug console +function EventCounter() +{ + this.addInput("inc", LiteGraph.ACTION); + this.addInput("dec", LiteGraph.ACTION); + this.addInput("reset", LiteGraph.ACTION); + this.addOutput("change", LiteGraph.EVENT); + this.addOutput("num", "number"); + this.num = 0; +} + +EventCounter.title = "Counter"; +EventCounter.desc = "Counts events"; + +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); +} + +EventCounter.prototype.onDrawBackground = function(ctx) +{ + if(this.flags.collapsed) + return; + ctx.fillStyle = "#AAA"; + ctx.font = "20px Arial"; + ctx.textAlign = "center"; + ctx.fillText( this.num, this.size[0] * 0.5, this.size[1] * 0.5 ); +} + + +EventCounter.prototype.onExecute = function() +{ + this.setOutputData(1,this.num); +} + +LiteGraph.registerNodeType("events/counter", EventCounter ); + //Show value inside the debug console function DelayEvent() { @@ -142,15 +221,19 @@ TimerEvent.prototype.onDrawBackground = function() TimerEvent.prototype.onExecute = function() { var dt = this.graph.elapsed_time * 1000; //in ms + + var trigger = this.time == 0; + this.time += dt; this.last_interval = Math.max(1, this.getInputOrProperty("interval") | 0); - if( this.time < this.last_interval || isNaN(this.last_interval) ) + if( !trigger && ( this.time < this.last_interval || isNaN(this.last_interval)) ) { 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 ); diff --git a/src/nodes/image.js b/src/nodes/graphics.js similarity index 87% rename from src/nodes/image.js rename to src/nodes/graphics.js index 3759b5f36..1a96cc254 100755 --- a/src/nodes/image.js +++ b/src/nodes/graphics.js @@ -98,6 +98,8 @@ GraphicsImage.prototype.onAdded = function() GraphicsImage.prototype.onDrawBackground = function(ctx) { + 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]); } @@ -244,7 +246,7 @@ LiteGraph.registerNodeType("color/palette", ColorPalette ); function ImageFrame() { - this.addInput("","image"); + this.addInput("","image,canvas"); this.size = [200,200]; } @@ -255,7 +257,7 @@ ImageFrame.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"vie ImageFrame.prototype.onDrawBackground = function(ctx) { - if(this.frame) + if(this.frame && !this.flags.collapsed) ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]); } @@ -298,86 +300,6 @@ LiteGraph.registerNodeType("graphics/frame", ImageFrame ); -/* -LiteGraph.registerNodeType("visualization/graph", { - desc: "Shows a graph of the inputs", - - inputs: [["",0],["",0],["",0],["",0]], - size: [200,200], - properties: {min:-1,max:1,bgColor:"#000"}, - onDrawBackground: function(ctx) - { - var colors = ["#FFF","#FAA","#AFA","#AAF"]; - - if(this.properties.bgColor != null && this.properties.bgColor != "") - { - ctx.fillStyle="#000"; - ctx.fillRect(2,2,this.size[0] - 4, this.size[1]-4); - } - - if(this.data) - { - var min = this.properties["min"]; - var max = this.properties["max"]; - - for(var i in this.data) - { - var data = this.data[i]; - if(!data) continue; - - if(this.getInputInfo(i) == null) continue; - - ctx.strokeStyle = colors[i]; - ctx.beginPath(); - - var d = data.length / this.size[0]; - for(var j = 0; j < data.length; j += d) - { - var value = data[ Math.floor(j) ]; - value = (value - min) / (max - min); - if (value > 1.0) value = 1.0; - else if(value < 0) value = 0; - - if(j == 0) - ctx.moveTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); - else - ctx.lineTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value); - } - - ctx.stroke(); - } - } - - //ctx.restore(); - }, - - onExecute: function() - { - if(!this.data) this.data = []; - - for(var i in this.inputs) - { - var value = this.getInputData(i); - - if(typeof(value) == "number") - { - value = value ? value : 0; - if(!this.data[i]) - this.data[i] = []; - this.data[i].push(value); - - if(this.data[i].length > (this.size[1] - 4)) - this.data[i] = this.data[i].slice(1,this.data[i].length); - } - else - this.data[i] = value; - } - - if(this.data.length) - this.setDirtyCanvas(true); - } - }); -*/ function ImageFade() { @@ -509,6 +431,105 @@ ImageCrop.prototype.onPropertyChanged = function(name,value) LiteGraph.registerNodeType("graphics/cropImage", ImageCrop ); +//CANVAS stuff + +function CanvasNode() +{ + this.addInput("clear", LiteGraph.ACTION ); + this.addOutput("","canvas"); + this.properties = {width:512,height:512,autoclear:true}; + + this.canvas = document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); +} + +CanvasNode.title = "Canvas"; +CanvasNode.desc = "Canvas to render stuff"; + +CanvasNode.prototype.onExecute = function() +{ + 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(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") + this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height); +} + +LiteGraph.registerNodeType("graphics/canvas", CanvasNode ); + +function DrawImageNode() +{ + this.addInput("canvas", "canvas" ); + this.addInput("img", "image,canvas" ); + this.addInput("x", "number" ); + this.addInput("y", "number" ); + this.properties = {x:0,y:0,opacity:1}; +} + +DrawImageNode.title = "DrawImage"; +DrawImageNode.desc = "Draws image into a canvas"; + +DrawImageNode.prototype.onExecute = function() +{ + var canvas = this.getInputData(0); + if(!canvas) + return; + + var img = this.getInputOrProperty("img"); + if(!img) + return; + + var x = this.getInputOrProperty("x"); + var y = this.getInputOrProperty("y"); + var ctx = canvas.getContext("2d"); + ctx.drawImage( img, x, y ); +} + +LiteGraph.registerNodeType("graphics/drawImage", DrawImageNode ); + + +function DrawRectangleNode() +{ + this.addInput("canvas", "canvas" ); + this.addInput("x", "number" ); + this.addInput("y", "number" ); + this.addInput("w", "number" ); + this.addInput("h", "number" ); + this.properties = { x:0,y:0,w:10,h:10,color:"white",opacity:1 }; +} + +DrawRectangleNode.title = "DrawRectangle"; +DrawRectangleNode.desc = "Draws rectangle in canvas"; + +DrawRectangleNode.prototype.onExecute = function() +{ + var canvas = this.getInputData(0); + if(!canvas) + return; + + var x = this.getInputOrProperty("x"); + var y = this.getInputOrProperty("y"); + var w = this.getInputOrProperty("w"); + var h = this.getInputOrProperty("h"); + var ctx = canvas.getContext("2d"); + ctx.fillRect( x, y, w, h ); +} + +LiteGraph.registerNodeType("graphics/drawRectangle", DrawRectangleNode ); + + function ImageVideo() { diff --git a/src/nodes/logic.js b/src/nodes/logic.js index c629fdaab..9687c9025 100755 --- a/src/nodes/logic.js +++ b/src/nodes/logic.js @@ -3,39 +3,92 @@ var LiteGraph = global.LiteGraph; function Selector() { - this.addInput("sel","boolean"); - this.addOutput("value","number"); - this.properties = { A:0, B:1 }; - this.size = [60,20]; + this.addInput("sel","number"); + this.addInput("A"); + this.addInput("B"); + this.addInput("C"); + this.addInput("D"); + this.addOutput("out"); + + this.selected = 0; } Selector.title = "Selector"; -Selector.desc = "outputs A if selector is true, B if selector is false"; +Selector.desc = "selects an output"; + +Selector.prototype.onDrawBackground = function(ctx) +{ + if(this.flags.collapsed) + return; + ctx.fillStyle = "#AFB"; + var y = (this.selected + 1) * LiteGraph.NODE_SLOT_HEIGHT + 2; + ctx.beginPath(); + ctx.moveTo(30, y); + ctx.lineTo(30, y+LiteGraph.NODE_SLOT_HEIGHT); + ctx.lineTo(24, y+LiteGraph.NODE_SLOT_HEIGHT*0.5); + ctx.fill(); +} Selector.prototype.onExecute = function() { - var cond = this.getInputData(0); - if(cond === undefined) - return; - - for(var i = 1; i < this.inputs.length; i++) - { - var input = this.inputs[i]; - var v = this.getInputData(i); - if(v === undefined) - continue; - this.properties[input.name] = v; - } - - var A = this.properties.A; - var B = this.properties.B; - this.setOutputData(0, cond ? A : B ); + var sel = this.getInputData(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 ); } Selector.prototype.onGetInputs = function() { - return [["A",0],["B",0]]; + return [["E",0],["F",0],["G",0],["H",0]]; } LiteGraph.registerNodeType("logic/selector", Selector); + + +function Sequence() +{ + this.properties = { + sequence: "A,B,C" + }; + this.addInput("index","number"); + this.addInput("seq"); + this.addOutput("out"); + + this.index = 0; + this.values = this.properties.sequence.split(","); +} + +Sequence.title = "Sequence"; +Sequence.desc = "select one element from a sequence from a string"; + +Sequence.prototype.onPropertyChanged = function(name,value) +{ + if(name == "sequence") + { + this.values = value.split(","); + } +} + +Sequence.prototype.onExecute = function() +{ + var seq = this.getInputData(1); + if(seq && seq != this.current_sequence) + { + this.values = seq.split(","); + this.current_sequence = seq; + } + var index = this.getInputData(0); + if(index == null) + index = 0; + this.index = index = Math.round(index) % this.values.length; + + this.setOutputData( 0, this.values[ index ] ); +} + + +LiteGraph.registerNodeType("logic/sequence", Sequence ); + })(this); \ No newline at end of file diff --git a/src/nodes/math.js b/src/nodes/math.js index b323452ac..52b5291c6 100755 --- a/src/nodes/math.js +++ b/src/nodes/math.js @@ -81,6 +81,23 @@ Bypass.prototype.onExecute = function() LiteGraph.registerNodeType("math/bypass", Bypass ); +function ToNumber() +{ + this.addInput("in"); + this.addOutput("out"); +} + +ToNumber.title = "to Number"; +ToNumber.desc = "Cast to number"; + +ToNumber.prototype.onExecute = function() +{ + var v = this.getInputData(0); + this.setOutputData(0, Number(v) ); +} + +LiteGraph.registerNodeType("math/to_number", ToNumber ); + function MathRange() { diff --git a/src/nodes/midi.js b/src/nodes/midi.js index 1c6888727..9211d4c28 100644 --- a/src/nodes/midi.js +++ b/src/nodes/midi.js @@ -6,16 +6,17 @@ function MIDIEvent( data ) { this.channel = 0; this.cmd = 0; + this.data = new Uint32Array(3); if(data) this.setup(data) - else - this.data = [0,0,0]; } +LiteGraph.MIDIEvent = MIDIEvent; + MIDIEvent.prototype.setup = function( raw_data ) { - this.data = raw_data; + this.data.set(raw_data); var midiStatus = raw_data[0]; this.status = midiStatus; @@ -50,6 +51,32 @@ Object.defineProperty( MIDIEvent.prototype, "velocity", { }); MIDIEvent.notes = ["A","A#","B","C","C#","D","D#","E","F","F#","G","G#"]; +MIDIEvent.note_to_index = {"A":0,"A#":1,"B":2,"C":3,"C#":4,"D":5,"D#":6,"E":7,"F":8,"F#":9,"G":10,"G#":11}; + +Object.defineProperty( MIDIEvent.prototype, "note", { + get: function() { + if(this.cmd != MIDIEvent.NOTEON) + return -1; + return MIDIEvent.toNoteString( this.data[1], true ); + }, + set: function(v) { + throw("notes cannot be assigned this way, must modify the data[1]"); + }, + enumerable: true +}); + +Object.defineProperty( MIDIEvent.prototype, "octave", { + get: function() { + if(this.cmd != MIDIEvent.NOTEON) + return -1; + var octave = this.data[1] - 24; + return Math.floor(octave / 12 + 1); + }, + set: function(v) { + throw("octave cannot be assigned this way, must modify the data[1]"); + }, + enumerable: true +}); //returns HZs MIDIEvent.prototype.getPitch = function() @@ -121,14 +148,39 @@ MIDIEvent.computeCommandFromString = function( str ) } } -MIDIEvent.toNoteString = function(d) +//transform from a pitch number to string like "C4" +MIDIEvent.toNoteString = function( d, skip_octave ) { + d = Math.round(d); //in case it has decimals var note = d - 21; - var octave = d - 24; + var octave = Math.floor((d - 24) / 12 + 1); note = note % 12; if(note < 0) note = 12 + note; - return MIDIEvent.notes[ note ] + Math.floor(octave / 12 + 1); + return MIDIEvent.notes[ note ] + (skip_octave ? "" : octave); +} + +MIDIEvent.NoteStringToPitch = function(str) +{ + str = str.toUpperCase(); + var note = str[0]; + var octave = 4; + + if(str[1] == "#") + { + note += "#"; + if( str.length > 2 ) + octave = Number( str[2] ); + } + else + { + if( str.length > 1 ) + octave = Number( str[1] ); + } + var pitch = MIDIEvent.note_to_index[note]; + if(pitch == null) + return null; + return ((octave - 1) * 12) + pitch + 21; } MIDIEvent.prototype.toString = function() @@ -482,7 +534,7 @@ LGMIDIOut.prototype.getPropertyInfo = function(name) LGMIDIOut.prototype.onAction = function(event, midi_event ) { - console.log(midi_event); + //console.log(midi_event); if(!this._midi) return; if(event == "send") @@ -581,7 +633,7 @@ function LGMIDIEvent() { this.properties = { channel: 0, - cmd: "CC", + cmd: 144, //0x90 value1: 1, value2: 1 }; @@ -589,6 +641,8 @@ function LGMIDIEvent() this.addInput( "send", LiteGraph.EVENT ); this.addInput( "assign", LiteGraph.EVENT ); this.addOutput( "on_midi", LiteGraph.EVENT ); + + this.midi_event = new MIDIEvent(); } LGMIDIEvent.title = "MIDIEvent"; @@ -606,7 +660,7 @@ LGMIDIEvent.prototype.onAction = function( event, midi_event ) } //send - var midi_event = new MIDIEvent(); + var midi_event = this.midi_event; midi_event.channel = this.properties.channel; if(this.properties.cmd && this.properties.cmd.constructor === String) midi_event.setCommandFromString( this.properties.cmd ); @@ -615,6 +669,7 @@ LGMIDIEvent.prototype.onAction = function( event, midi_event ) 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); + this.trigger("on_midi",midi_event); } @@ -622,6 +677,28 @@ LGMIDIEvent.prototype.onExecute = function() { var props = this.properties; + if(this.inputs) + { + for(var i = 0; i < this.inputs.length; ++i) + { + var input = this.inputs[i]; + if(input.link == -1) + continue; + switch (input.name) + { + case "note": + var v = this.getInputData(i); + if(v != null) + { + if(v.constructor === String) + v = MIDIEvent.NoteStringToPitch(v); + this.properties.value1 = (v|0)%255; + } + break; + } + } + } + if(this.outputs) { for(var i = 0; i < this.outputs.length; ++i) @@ -657,6 +734,9 @@ LGMIDIEvent.prototype.onPropertyChanged = function(name,value) this.properties.cmd = MIDIEvent.computeCommandFromString( value ); } +LGMIDIEvent.prototype.onGetInputs = function() { + return [ ["note","number"] ]; +} LGMIDIEvent.prototype.onGetOutputs = function() { return [ @@ -701,6 +781,232 @@ LGMIDICC.prototype.onExecute = function() LiteGraph.registerNodeType("midi/cc", LGMIDICC); +function LGMIDIGenerator() +{ + this.addInput( "generate", LiteGraph.ACTION ); + this.addInput( "scale", "string" ); + this.addInput( "octave", "number" ); + this.addOutput( "note", LiteGraph.EVENT ); + this.properties = { + notes: "A,A#,B,C,C#,D,D#,E,F,F#,G,G#", + octave: 2, + mode: "sequence" + }; + + this.notes_pitches = LGMIDIGenerator.processScale( this.properties.notes ); + this.sequence_index = 0; +} + +LGMIDIGenerator.title = "MIDI Generator"; +LGMIDIGenerator.desc = "Generates a random MIDI note"; + +LGMIDIGenerator.processScale = function(scale) +{ + var notes = scale.split(","); + for(var i = 0; i < notes.length; ++i) + notes[i] = MIDIEvent.note_to_index[ notes[i] ] || 0; + return notes; +} + +LGMIDIGenerator.prototype.onPropertyChanged = function(name,value) +{ + 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; + + var scale = this.getInputData(1); + if(scale) + this.notes_pitches = LGMIDIGenerator.processScale( scale ); +} + +LGMIDIGenerator.prototype.onAction = function( event, midi_event ) +{ + //var range = this.properties.max - this.properties.min; + //var pitch = this.properties.min + ((Math.random() * range)|0); + var pitch = 0; + var range = this.notes_pitches.length; + + if( this.properties.mode == "sequence" ) + { + var index = this.sequence_index = (this.sequence_index + 1) % range; + pitch = this.notes_pitches[ index ] + ( (this.properties.octave-1) * 12) + 33; + } + else if( this.properties.mode == "random" ) + { + var index = Math.floor(Math.random()*range); + pitch = this.notes_pitches[ index ] + ( (this.properties.octave-1) * 12) + 33; + } + var note = new MIDIEvent(); + note.setup([ MIDIEvent.NOTEON, pitch, 10 ]); + this.trigger("note", note); +} + + +LiteGraph.registerNodeType("midi/generator", LGMIDIGenerator); + +function LGMIDITranspose() +{ + this.properties = { + amount: 0 + }; + this.addInput( "in", LiteGraph.ACTION ); + this.addInput( "amount", "number" ); + this.addOutput( "out", LiteGraph.EVENT ); + + this.midi_event = new MIDIEvent(); +} + +LGMIDITranspose.title = "MIDI Transpose"; +LGMIDITranspose.desc = "Transpose a MIDI note"; + +LGMIDITranspose.prototype.onAction = function( event, midi_event ) +{ + this.midi_event.setup( midi_event.data ); + this.midi_event.data[1] = Math.round( this.midi_event.data[1] + this.properties.amount ); + this.trigger("out", this.midi_event ); +} + +LGMIDITranspose.prototype.onExecute = function() +{ + var amount = this.getInputData(1); + if(amount!= null) + this.properties.amount = amount; +} + +LiteGraph.registerNodeType("midi/transpose", LGMIDITranspose); + + +function LGMIDIQuantize() +{ + this.properties = { + scale: "A,A#,B,C,C#,D,D#,E,F,F#,G,G#" + }; + this.addInput( "note", LiteGraph.ACTION ); + this.addInput( "scale", "string" ); + this.addOutput( "out", LiteGraph.EVENT ); + + this.valid_notes = new Array(12); + this.offset_notes = new Array(12); + this.processScale( this.properties.scale ); + this.midi_event = new MIDIEvent(); +} + +LGMIDIQuantize.title = "MIDI Quantize Pitch"; +LGMIDIQuantize.desc = "Transpose a MIDI note tp fit an scale"; + +LGMIDIQuantize.prototype.onPropertyChanged = function(name,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) + 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; + continue; + } + for(var j = 1; j < 12; ++j) + { + if( this.valid_notes[ (i - j)%12 ] ) + { + this.offset_notes[i] = -j; + break; + } + if( this.valid_notes[ (i + j)%12 ] ) + { + this.offset_notes[i] = j; + break; + } + } + } +} + +LGMIDIQuantize.prototype.onAction = function( event, midi_event ) +{ + this.midi_event.setup( midi_event.data ); + var note = midi_event.note; + var index = MIDIEvent.note_to_index[ note ]; + var offset = this.offset_notes[index]; + this.midi_event.data[1] += offset; + this.trigger("out", this.midi_event ); +} + +LGMIDIQuantize.prototype.onExecute = function() +{ + var scale = this.getInputData(1); + if(scale != null && scale != this._current_scale ) + this.processScale( scale ); +} + +LiteGraph.registerNodeType("midi/quantize", LGMIDIQuantize); + + +function LGMIDIPlay() +{ + this.properties = { + volume: 0.5, + duration: 1 + }; + this.addInput( "note", LiteGraph.ACTION ); + this.addInput( "volume", "number" ); + this.addInput( "duration", "number" ); + this.addOutput( "note", LiteGraph.EVENT ); + + if(typeof(AudioSynth) == "undefined") + { + console.error("Audiosynth.js not included, LGMidiPlay requires that library"); + this.boxcolor = "red"; + } + else + { + var Synth = this.synth = new AudioSynth(); + this.instrument = Synth.createInstrument('piano'); + } +} + +LGMIDIPlay.title = "MIDI Play"; +LGMIDIPlay.desc = "Plays a MIDI note"; + +LGMIDIPlay.prototype.onAction = function( event, midi_event ) +{ + if(!this.instrument) + return; + var note = midi_event.note; //C# + if( !note || note == "undefined" || note.constructor !== String ) + return; + this.instrument.play( note, midi_event.octave, this.properties.duration, this.properties.volume ); + this.trigger("note", midi_event ); +} + +LGMIDIPlay.prototype.onExecute = function() +{ + var volume = this.getInputData(1); + if(volume != null) + this.properties.volume = volume; + + var duration = this.getInputData(2); + if(duration != null) + this.properties.duration = duration; +} + +LiteGraph.registerNodeType("midi/play", LGMIDIPlay); + + function now() { return window.performance.now() } diff --git a/utils/deploy_files.txt b/utils/deploy_files.txt index a85bbecb8..23524f697 100755 --- a/utils/deploy_files.txt +++ b/utils/deploy_files.txt @@ -5,7 +5,7 @@ ../src/nodes/input.js ../src/nodes/math.js ../src/nodes/logic.js -../src/nodes/image.js +../src/nodes/graphics.js ../src/nodes/gltextures.js ../src/nodes/glfx.js ../src/nodes/midi.js