From f74bf4109e84194b1622bcb9ef3976df8a0f49e5 Mon Sep 17 00:00:00 2001 From: tamat Date: Fri, 18 May 2018 14:50:49 +0200 Subject: [PATCH] foo --- build/litegraph.js | 274 +++++++++++++++++++++++++++-- build/litegraph.min.js | 223 +++++++++++------------ demo/index.html | 4 +- demo/{ => js}/code.js | 0 demo/{demo.js => js/demos.js} | 0 doc/classes/LGraph.html | 6 +- doc/data.json | 2 +- doc/files/.._src_litegraph.js.html | 12 +- src/litegraph.js | 12 +- src/nodes/glfx.js | 123 ++++++++++++- src/nodes/gltextures.js | 139 ++++++++++++++- 11 files changed, 649 insertions(+), 146 deletions(-) rename demo/{ => js}/code.js (100%) rename demo/{demo.js => js/demos.js} (100%) diff --git a/build/litegraph.js b/build/litegraph.js index 2c2d00fef..db73c14f2 100644 --- a/build/litegraph.js +++ b/build/litegraph.js @@ -86,7 +86,7 @@ var LiteGraph = global.LiteGraph = { console.log("Node registered: " + type); var categories = type.split("/"); - var classname = base_class.constructor.name; + var classname = base_class.name; var pos = type.lastIndexOf("/"); base_class.category = type.substr(0,pos); @@ -1028,7 +1028,7 @@ LGraph.prototype.findNodesByType = function(type) /** * Returns a list of nodes that matches a name -* @method findNodesByName +* @method findNodesByTitle * @param {String} name the name of the node to search * @return {Array} a list with all the nodes with this name */ @@ -1239,7 +1239,7 @@ LGraph.prototype.removeGlobalOutput = function(name) LGraph.prototype.setInputData = function(name,value) { - var nodes = this.findNodesByName( name ); + var nodes = this.findNodesByTitle( name ); for(var i = 0, l = nodes.length; i < l; ++i) nodes[i].setValue(value); } @@ -1253,7 +1253,7 @@ LGraph.prototype.setInputData = function(name,value) LGraph.prototype.getOutputData = function(name) { - var n = this.findNodesByName(name); + var n = this.findNodesByTitle(name); if(n.length) return m[0].getValue(); return null; @@ -1263,14 +1263,14 @@ LGraph.prototype.getOutputData = function(name) LGraph.prototype.triggerInput = function(name,value) { - var nodes = this.findNodesByName(name); + var nodes = this.findNodesByTitle(name); for(var i = 0; i < nodes.length; ++i) nodes[i].onTrigger(value); } LGraph.prototype.setCallback = function(name,func) { - var nodes = this.findNodesByName(name); + var nodes = this.findNodesByTitle(name); for(var i = 0; i < nodes.length; ++i) nodes[i].setTrigger(func); } @@ -11794,7 +11794,8 @@ if(typeof(GL) != "undefined") shader.uniforms( uniforms ).draw(mesh); }); - this.setOutputData(0, this._temp_texture); + this._temp_texture.near_far_planes = planes; + this.setOutputData(0, this._temp_texture ); } LGraphTextureDepthRange.pixel_shader = "precision highp float;\n\ @@ -12211,6 +12212,141 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam ); + //simple exposition, but plan to expand it to support different gamma curves + function LGraphExposition() + { + this.addInput("in","Texture"); + this.addInput("exp","number"); + this.addOutput("out","Texture"); + this.properties = { exposition: 1, precision: LGraphTexture.LOW }; + } + + LGraphExposition.title = "Exposition"; + LGraphExposition.desc = "Controls texture exposition"; + + LGraphExposition.widgets_info = { + "exposition": { widget:"slider", min:0,max:3 }, + "precision": { widget:"combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphExposition.prototype.onExecute = function() + { + var tex = this.getInputData(0); + if(!tex) + return; + + if(!this.isOutputConnected(0)) + return; //saves work + + var temp = this._temp_texture; + if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) + temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + + var shader = LGraphExposition._shader; + if(!shader) + shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphExposition.pixel_shader ); + + var exp = this.properties.exposition; + var exp_input = this.getInputData(1); + if(exp_input != null) + exp = this.properties.exposition = exp_input; + + //apply shader + temp.drawTo(function(){ + gl.disable( gl.DEPTH_TEST ); + tex.bind(0); + var mesh = GL.Mesh.getScreenQuad(); + shader.uniforms({ u_texture: 0, u_exposition: exp }).draw(mesh); + }); + + this.setOutputData(0,temp); + } + + LGraphExposition.pixel_shader = "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float u_exposition;\n\ + \n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord );\n\ + gl_FragColor = vec4( color.xyz * u_exposition, color.a );\n\ + }"; + + LiteGraph.registerNodeType("texture/exposition", LGraphExposition ); + + + + function LGraphToneMapping() + { + this.addInput("in","Texture"); + this.addOutput("out","Texture"); + this.properties = { precision: LGraphTexture.LOW }; + } + + LGraphToneMapping.title = "Tone Mapping"; + LGraphToneMapping.desc = "Applies Tone Mapping algorithm"; + + LGraphToneMapping.prototype.onExecute = function() + { + var tex = this.getInputData(0); + if(!tex) + return; + + if(!this.isOutputConnected(0)) + return; //saves work + + var temp = this._temp_texture; + + if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) + temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + + + //apply shader + + + + this.setOutputData(0,this._temp_texture); + } + + LGraphToneMapping.pixel_shader = "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float scale;\n\ + uniform float averageLum;\n\ + uniform vec3 lumwhite2;\n\ + vec3 RGB2xyY (vec3 rgb)\n\ + {\n\ + const mat3 RGB2XYZ = mat3(0.4124, 0.3576, 0.1805,\n\ + 0.2126, 0.7152, 0.0722,\n\ + 0.0193, 0.1192, 0.9505);\n\ + vec3 XYZ = RGB2XYZ * rgb;\n\ + \n\ + float f = (XYZ.x + XYZ.y + XYZ.z);\n\ + return vec3(XYZ.x / f,\n\ + XYZ.y / f,\n\ + XYZ.y);\n\ + }\n\ + \n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord ).xyz;\n\ + vec3 rgb = color.xyz;\n\ + //Ld - this part of the code is the same for both versions\n\ + float lum = dot(rgb, vec3(0.2126f, 0.7152f, 0.0722f));\n\ + float L = (scale / averageLum) * lum;\n\ + float Ld = (L * (1.0 + L / lumwhite2)) / (1.0 + L);\n\ + //first\n\ + //vec3 xyY = RGB2xyY(rgb);\n\ + //xyY.z *= Ld;\n\ + //rgb = xyYtoRGB(xyY);\n\ + //second\n\ + rgb = (rgb / lum) * Ld;\n\ + gl_FragColor = vec4( rgb, color.a );\n\ + }"; + + + //LiteGraph.registerNodeType("texture/tonemapping", LGraphToneMapping ); + + function LGraphTextureMatte() { this.addInput("in","Texture"); @@ -12287,6 +12423,7 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ LiteGraph.registerNodeType("texture/matte", LGraphTextureMatte ); + //*********************************** //Cubemap reader (to pass a cubemap to a node that requires cubemaps and no images) function LGraphCubemap() @@ -12373,7 +12510,7 @@ if(typeof(GL) != "undefined") if(!LGraphFXLens._shader) { - LGraphFXLens._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphFXLens.pixel_shader ); + LGraphFXLens._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphFXLens.pixel_shader ); LGraphFXLens._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] }); } } @@ -12466,7 +12603,120 @@ if(typeof(GL) != "undefined") */ LiteGraph.registerNodeType("fx/lens", LGraphFXLens ); - window.LGraphFXLens = LGraphFXLens; + global.LGraphFXLens = LGraphFXLens; + + /* not working yet + function LGraphDepthOfField() + { + this.addInput("Color","Texture"); + this.addInput("Linear Depth","Texture"); + this.addInput("Camera","camera"); + this.addOutput("Texture","Texture"); + this.properties = { high_precision: false }; + } + + LGraphDepthOfField.title = "Depth Of Field"; + LGraphDepthOfField.desc = "Applies a depth of field effect"; + + LGraphDepthOfField.prototype.onExecute = function() + { + var tex = this.getInputData(0); + var depth = this.getInputData(1); + var camera = this.getInputData(2); + + if(!tex || !depth || !camera) + { + this.setOutputData(0, tex); + return; + } + + var precision = gl.UNSIGNED_BYTE; + if(this.properties.high_precision) + precision = gl.half_float_ext ? gl.HALF_FLOAT_OES : gl.FLOAT; + if(!this._temp_texture || this._temp_texture.type != precision || + this._temp_texture.width != tex.width || this._temp_texture.height != tex.height) + this._temp_texture = new GL.Texture( tex.width, tex.height, { type: precision, format: gl.RGBA, filter: gl.LINEAR }); + + var shader = LGraphDepthOfField._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphDepthOfField._pixel_shader ); + + var screen_mesh = Mesh.getScreenQuad(); + + gl.disable( gl.DEPTH_TEST ); + gl.disable( gl.BLEND ); + + var camera_position = camera.getEye(); + var focus_point = camera.getCenter(); + var distance = vec3.distance( camera_position, focus_point ); + var far = camera.far; + var focus_range = distance * 0.5; + + this._temp_texture.drawTo( function() { + tex.bind(0); + depth.bind(1); + shader.uniforms({u_texture:0, u_depth_texture:1, u_resolution: [1/tex.width, 1/tex.height], u_far: far, u_focus_point: distance, u_focus_scale: focus_range }).draw(screen_mesh); + }); + + this.setOutputData(0, this._temp_texture); + } + + //from http://tuxedolabs.blogspot.com.es/2018/05/bokeh-depth-of-field-in-single-pass.html + LGraphDepthOfField._pixel_shader = "\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture; //Image to be processed\n\ + uniform sampler2D u_depth_texture; //Linear depth, where 1.0 == far plane\n\ + uniform vec2 u_iresolution; //The size of a pixel: vec2(1.0/width, 1.0/height)\n\ + uniform float u_far; // Far plane\n\ + uniform float u_focus_point;\n\ + uniform float u_focus_scale;\n\ + \n\ + const float GOLDEN_ANGLE = 2.39996323;\n\ + const float MAX_BLUR_SIZE = 20.0;\n\ + const float RAD_SCALE = 0.5; // Smaller = nicer blur, larger = faster\n\ + \n\ + float getBlurSize(float depth, float focusPoint, float focusScale)\n\ + {\n\ + float coc = clamp((1.0 / focusPoint - 1.0 / depth)*focusScale, -1.0, 1.0);\n\ + return abs(coc) * MAX_BLUR_SIZE;\n\ + }\n\ + \n\ + vec3 depthOfField(vec2 texCoord, float focusPoint, float focusScale)\n\ + {\n\ + float centerDepth = texture2D(u_depth_texture, texCoord).r * u_far;\n\ + float centerSize = getBlurSize(centerDepth, focusPoint, focusScale);\n\ + vec3 color = texture2D(u_texture, v_coord).rgb;\n\ + float tot = 1.0;\n\ + \n\ + float radius = RAD_SCALE;\n\ + for (float ang = 0.0; ang < 100.0; ang += GOLDEN_ANGLE)\n\ + {\n\ + vec2 tc = texCoord + vec2(cos(ang), sin(ang)) * u_iresolution * radius;\n\ + \n\ + vec3 sampleColor = texture2D(u_texture, tc).rgb;\n\ + float sampleDepth = texture2D(u_depth_texture, tc).r * u_far;\n\ + float sampleSize = getBlurSize( sampleDepth, focusPoint, focusScale );\n\ + if (sampleDepth > centerDepth)\n\ + sampleSize = clamp(sampleSize, 0.0, centerSize*2.0);\n\ + \n\ + float m = smoothstep(radius-0.5, radius+0.5, sampleSize);\n\ + color += mix(color/tot, sampleColor, m);\n\ + tot += 1.0;\n\ + radius += RAD_SCALE/radius;\n\ + if(radius>=MAX_BLUR_SIZE)\n\ + return color / tot;\n\ + }\n\ + return color / tot;\n\ + }\n\ + void main()\n\ + {\n\ + gl_FragColor = vec4( depthOfField( v_coord, u_focus_point, u_focus_scale ), 1.0 );\n\ + //gl_FragColor = vec4( texture2D(u_depth_texture, v_coord).r );\n\ + }\n\ + "; + + LiteGraph.registerNodeType("fx/DOF", LGraphDepthOfField ); + global.LGraphDepthOfField = LGraphDepthOfField; + */ //******************************************************* @@ -12667,7 +12917,7 @@ if(typeof(GL) != "undefined") LiteGraph.registerNodeType("fx/bokeh", LGraphFXBokeh ); - window.LGraphFXBokeh = LGraphFXBokeh; + global.LGraphFXBokeh = LGraphFXBokeh; //************************************************ @@ -12736,7 +12986,7 @@ if(typeof(GL) != "undefined") gl.disable( gl.BLEND ); gl.disable( gl.DEPTH_TEST ); var mesh = Mesh.getScreenQuad(); - var camera = window.LS ? LS.Renderer._current_camera : null; + var camera = global.LS ? LS.Renderer._current_camera : null; if(camera) camera_planes = [LS.Renderer._current_camera.near, LS.Renderer._current_camera.far]; else @@ -12836,7 +13086,7 @@ if(typeof(GL) != "undefined") LiteGraph.registerNodeType("fx/generic", LGraphFXGeneric ); - window.LGraphFXGeneric = LGraphFXGeneric; + global.LGraphFXGeneric = LGraphFXGeneric; // Vigneting ************************************ diff --git a/build/litegraph.min.js b/build/litegraph.min.js index 5109b7b17..aa2d9e9d2 100755 --- a/build/litegraph.min.js +++ b/build/litegraph.min.js @@ -6,21 +6,21 @@ var h=document.createElement("div");h.className="litegraph litecontextmenu litem this.root=h;if(b.title){var k=document.createElement("div");k.className="litemenu-title";k.innerHTML=b.title;h.appendChild(k)}var k=0,d;for(d in a){var n=a.constructor==Array?a[d]:d;null!=n&&n.constructor!==String&&(n=void 0===n.content?String(n):n.content);this.addItem(n,a[d],b);k++}h.addEventListener("mouseleave",function(a){c.lock||c.close(a)});d=document;b.event&&(d=b.event.target.ownerDocument);d||(d=document);d.body.appendChild(h);k=b.left||0;d=b.top||0;if(b.event){k=b.event.pageX-10;d=b.event.pageY- 10;b.title&&(d-=20);b.parentMenu&&(k=b.parentMenu.root.getBoundingClientRect(),k=k.left+k.width);var n=document.body.getBoundingClientRect(),e=h.getBoundingClientRect();k>n.width-e.width-10&&(k=n.width-e.width-10);d>n.height-e.height-10&&(d=n.height-e.height-10)}h.style.left=k+"px";h.style.top=d+"px"}var d=q.LiteGraph={NODE_TITLE_HEIGHT:16,NODE_SLOT_HEIGHT:15,NODE_WIDTH:140,NODE_MIN_WIDTH:50,NODE_COLLAPSED_RADIUS:10,NODE_COLLAPSED_WIDTH:80,CANVAS_GRID_SIZE:10,NODE_TITLE_COLOR:"#222",NODE_DEFAULT_COLOR:"#999", NODE_DEFAULT_BGCOLOR:"#444",NODE_DEFAULT_BOXCOLOR:"#AEF",NODE_DEFAULT_SHAPE:"box",MAX_NUMBER_OF_NODES:1E3,DEFAULT_POSITION:[100,100],node_images_path:"",VALID_SHAPES:["box","round"],BOX_SHAPE:1,ROUND_SHAPE:2,CIRCLE_SHAPE:3,INPUT:1,OUTPUT:2,EVENT:-1,ACTION:-1,ALWAYS:0,ON_EVENT:1,NEVER:2,ON_TRIGGER:3,proxy:null,debug:!1,throw_errors:!0,allow_scripts:!0,registered_node_types:{},node_types_by_file_extension:{},Nodes:{},registerNodeType:function(a,b){if(!b.prototype)throw"Cannot register a simple object, it must be a class with a prototype"; -b.type=a;d.debug&&console.log("Node registered: "+a);a.split("/");var c=b.constructor.name,h=a.lastIndexOf("/");b.category=a.substr(0,h);b.title||(b.title=c);if(b.prototype)for(var k in f.prototype)b.prototype[k]||(b.prototype[k]=f.prototype[k]);Object.defineProperty(b.prototype,"shape",{set:function(a){switch(a){case "box":this._shape=d.BOX_SHAPE;break;case "round":this._shape=d.ROUND_SHAPE;break;case "circle":this._shape=d.CIRCLE_SHAPE;break;default:this._shape=a}},get:function(a){return this._shape}, -enumerable:!0});this.registered_node_types[a]=b;b.constructor.name&&(this.Nodes[c]=b);b.prototype.onPropertyChange&&console.warn("LiteGraph node class "+a+" has onPropertyChange method, it must be called onPropertyChanged with d at the end");if(b.supported_extensions)for(k in b.supported_extensions)this.node_types_by_file_extension[b.supported_extensions[k].toLowerCase()]=b},wrapFunctionAsNode:function(a,b,c,h){for(var k=Array(b.length),r="",n=d.getParameterNames(b),e=0;en&&(n=k.size[0]),e+=k.size[1]+a;b+=n+a}this.setDirtyCanvas(!0,!0)};g.prototype.getTime=function(){return this.globaltime};g.prototype.getFixedTime=function(){return this.fixedtime};g.prototype.getElapsedTime=function(){return this.elapsed_time};g.prototype.sendEventToAllNodes=function(a,b,c){c=c||d.ALWAYS;var h=this._nodes_in_order?this._nodes_in_order:this._nodes;if(h)for(var k=0,e=h.length;k=d.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&&this.pos[1]-h-cb)return!0;return!1};f.prototype.getSlotInPosition= function(a,b){if(this.inputs)for(var c=0,h=this.inputs.length;c=this.outputs.length)return d.debug&&console.log("Connect: Error, slot number not found"),!1;b&&b.constructor=== @@ -100,8 +100,8 @@ e.prototype.selectNode=function(a,b){null==a?this.deselectAllNodes():this.select d.selected=!1}}this.selected_nodes={};this.highlighted_links={};this.setDirty(!0)}};e.prototype.deleteSelectedNodes=function(){for(var a in this.selected_nodes)this.graph.remove(this.selected_nodes[a]);this.selected_nodes={};this.highlighted_links={};this.setDirty(!0)};e.prototype.centerOnNode=function(a){this.offset[0]=-a.pos[0]-0.5*a.size[0]+0.5*this.canvas.width/this.scale;this.offset[1]=-a.pos[1]-0.5*a.size[1]+0.5*this.canvas.height/this.scale;this.setDirty(!0,!0)};e.prototype.adjustMouseEvent= function(a){var b=this.canvas.getBoundingClientRect();a.localX=a.pageX-b.left;a.localY=a.pageY-b.top;a.canvasX=a.localX/this.scale-this.offset[0];a.canvasY=a.localY/this.scale-this.offset[1]};e.prototype.setZoom=function(a,b){b||(b=[0.5*this.canvas.width,0.5*this.canvas.height]);var c=this.convertOffsetToCanvas(b);this.scale=a;this.scale>this.max_zoom?this.scale=this.max_zoom:this.scalec-this.graph._last_trigger_time)&& +e.prototype.bringToFront=function(a){var b=this.graph._nodes.indexOf(a);-1!=b&&(this.graph._nodes.splice(b,1),this.graph._nodes.push(a))};e.prototype.sendToBack=function(a){var b=this.graph._nodes.indexOf(a);-1!=b&&(this.graph._nodes.splice(b,1),this.graph._nodes.unshift(a))};var r=new Float32Array(4);e.prototype.computeVisibleNodes=function(a,b){var c=b||[];c.length=0;a=a||this.graph._nodes;for(var d=0,k=a.length;dc-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}};e.prototype.drawFrontCanvas=function(){this.ctx||(this.ctx=this.bgcanvas.getContext("2d"));var a=this.ctx;if(a){a.start2D&&a.start2D();var b=this.canvas;a.restore();a.setTransform(1,0,0,1,0,0);this.dirty_area&&(a.save(),a.beginPath(),a.rect(this.dirty_area[0],this.dirty_area[1],this.dirty_area[2],this.dirty_area[3]),a.clip());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;cc&&0.01>b.editor_alpha&&(clearInterval(d),1>c&&(b.live_mode=!0));1"+ +new d.ContextMenu(b,{event:c,callback:k,parentMenu:g},n);return!1},parentMenu:h},n);return!1};e.onMenuCollapseAll=function(){};e.onMenuNodeEdit=function(){};e.showMenuNodeOptionalInputs=function(a,b,c,h,k){function l(a,b,c){k&&(a.callback&&a.callback.call(n,k,a,b,c),a.value&&(k.addInput(a.value[0],a.value[1],a.value[2]),k.setDirtyCanvas(!0,!0)))}if(k){var n=this;a=e.active_canvas.getCanvasWindow();b=k.optional_inputs;k.onGetInputs&&(b=k.onGetInputs());var f=[];if(b)for(var g in b){var r=b[g];if(r){var p= +r[0];r[2]&&r[2].label&&(p=r[2].label);p={content:p,value:r};r[1]==d.ACTION&&(p.className="event");f.push(p)}else f.push(null)}this.onMenuNodeInputs&&(f=this.onMenuNodeInputs(f));if(f.length)return new d.ContextMenu(f,{event:c,callback:l,parentMenu:h,node:k},a),!1}};e.showMenuNodeOptionalOutputs=function(a,b,c,h,k){function l(a,b,c){if(k&&(a.callback&&a.callback.call(n,k,a,b,c),a.value))if(c=a.value[1],!c||c.constructor!==Object&&c.constructor!==Array)k.addOutput(a.value[0],a.value[1],a.value[2]), +k.setDirtyCanvas(!0,!0);else{a=[];for(var e in c)a.push({content:e,value:c[e]});new d.ContextMenu(a,{event:b,callback:l,parentMenu:h,node:k});return!1}}if(k){var n=this;a=e.active_canvas.getCanvasWindow();b=k.optional_outputs;k.onGetOutputs&&(b=k.onGetOutputs());var f=[];if(b)for(var g in b){var r=b[g];if(!r)f.push(null);else if(!k.flags||!k.flags.skip_repeated_outputs||-1==k.findOutputSlot(r[0])){var p=r[0];r[2]&&r[2].label&&(p=r[2].label);p={content:p,value:r};r[1]==d.EVENT&&(p.className="event"); +f.push(p)}}this.onMenuNodeOutputs&&(f=this.onMenuNodeOutputs(f));if(f.length)return new d.ContextMenu(f,{event:c,callback:l,parentMenu:h,node:k},a),!1}};e.onShowMenuNodeProperties=function(a,b,c,h,k){function l(a,b,c,d){k&&(b=this.getBoundingClientRect(),n.showEditPropertyValue(k,a.value,{position:[b.left,b.top]}))}if(k&&k.properties){var n=e.active_canvas;b=n.getCanvasWindow();var f=[],g;for(g in k.properties)a=void 0!==k.properties[g]?k.properties[g]:" ",a=e.decodeHTML(a),f.push({content:""+ g+""+a+"",value:g});if(f.length)return new d.ContextMenu(f,{event:c,callback:l,parentMenu:h,allow_html:!0,node:k},b),!1}};e.decodeHTML=function(a){var b=document.createElement("div");b.innerText=a;return b.innerHTML};e.onResizeNode=function(a,b,c,d,e){e&&(e.size=e.computeSize(),e.setDirtyCanvas(!0,!0))};e.onShowTitleEditor=function(a,b,c,d,k){function l(){k.title=f.value;n.parentNode.removeChild(n);k.setDirtyCanvas(!0,!0)}var n=document.createElement("div"); n.className="graphdialog";n.innerHTML="Title";var f=n.querySelector("input");f&&(f.value=k.title,f.addEventListener("keydown",function(a){13==a.keyCode&&(l(),a.preventDefault(),a.stopPropagation())}));a=e.active_canvas.canvas;b=a.getBoundingClientRect();d=c=-20;b&&(c-=b.left,d-=b.top);event?(n.style.left=event.pageX+c+"px",n.style.top=event.pageY+d+"px"):(n.style.left=0.5*a.width+c+"px",n.style.top=0.5*a.height+ -d+"px");n.querySelector("button").addEventListener("click",l);a.parentNode.appendChild(n)};e.prototype.showEditPropertyValue=function(a,b,c){function d(){e(y.value)}function e(c){"number"==typeof a.properties[b]&&(c=Number(c));a.properties[b]=c;if(a.onPropertyChanged)a.onPropertyChanged(b,c);w.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]);var n=null;a.getPropertyInfo&&(n=a.getPropertyInfo(b));if(a.properties_info)for(var f= -0;f";else if("enum"==l&&n.values){g=""}else"boolean"==l&&(g="");var w=this.createDialog(""+b+""+g+"",c);if("enum"==l&&n.values){var y=w.querySelector("select");y.addEventListener("change",function(a){e(a.target.value)})}else if("boolean"==l)(y=w.querySelector("input"))&&y.addEventListener("click",function(a){e(!!y.checked)});else if(y=w.querySelector("input"))y.value=void 0!==a.properties[b]?a.properties[b]:"",y.addEventListener("keydown",function(a){13==a.keyCode&&(d(),a.preventDefault(), -a.stopPropagation())});w.querySelector("button").addEventListener("click",d)}};e.prototype.createDialog=function(a,b){b=b||{};var c=document.createElement("div");c.className="graphdialog";c.innerHTML=a;var d=this.canvas.getBoundingClientRect(),e=-20,l=-20;d&&(e-=d.left,l-=d.top);b.position?(e+=b.position[0],l+=b.position[1]):b.event?(e+=b.event.pageX,l+=b.event.pageY):(e+=0.5*this.canvas.width,l+=0.5*this.canvas.height);c.style.left=e+"px";c.style.top=l+"px";this.canvas.parentNode.appendChild(c); +d+"px");n.querySelector("button").addEventListener("click",l);a.parentNode.appendChild(n)};e.prototype.showEditPropertyValue=function(a,b,c){function d(){e(x.value)}function e(c){"number"==typeof a.properties[b]&&(c=Number(c));a.properties[b]=c;if(a.onPropertyChanged)a.onPropertyChanged(b,c);p.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]);var n=null;a.getPropertyInfo&&(n=a.getPropertyInfo(b));if(a.properties_info)for(var f= +0;f";else if("enum"==l&&n.values){g=""}else"boolean"==l&&(g="");var p=this.createDialog(""+b+""+g+"",c);if("enum"==l&&n.values){var x=p.querySelector("select");x.addEventListener("change",function(a){e(a.target.value)})}else if("boolean"==l)(x=p.querySelector("input"))&&x.addEventListener("click",function(a){e(!!x.checked)});else if(x=p.querySelector("input"))x.value=void 0!==a.properties[b]?a.properties[b]:"",x.addEventListener("keydown",function(a){13==a.keyCode&&(d(),a.preventDefault(), +a.stopPropagation())});p.querySelector("button").addEventListener("click",d)}};e.prototype.createDialog=function(a,b){b=b||{};var c=document.createElement("div");c.className="graphdialog";c.innerHTML=a;var d=this.canvas.getBoundingClientRect(),e=-20,l=-20;d&&(e-=d.left,l-=d.top);b.position?(e+=b.position[0],l+=b.position[1]):b.event?(e+=b.event.pageX,l+=b.event.pageY):(e+=0.5*this.canvas.width,l+=0.5*this.canvas.height);c.style.left=e+"px";c.style.top=l+"px";this.canvas.parentNode.appendChild(c); c.close=function(){this.parentNode&&this.parentNode.removeChild(this)};return c};e.onMenuNodeCollapse=function(a,b,c,d,e){e.flags.collapsed=!e.flags.collapsed;e.setDirtyCanvas(!0,!0)};e.onMenuNodePin=function(a,b,c,d,e){e.pin()};e.onMenuNodeMode=function(a,b,c,e,l){new d.ContextMenu(["Always","On Event","On Trigger","Never"],{event:c,callback:function(a){if(l)switch(a){case "On Event":l.mode=d.ON_EVENT;break;case "On Trigger":l.mode=d.ON_TRIGGER;break;case "Never":l.mode=d.NEVER;break;default:l.mode= d.ALWAYS}},parentMenu:e,node:l});return!1};e.onMenuNodeColors=function(a,b,c,l,k){if(!k)throw"no node for color";b=[];for(var f in e.node_colors)a=e.node_colors[f],a={value:f,content:""+f+""},b.push(a);new d.ContextMenu(b,{event:c,callback:function(a){k&&(a=e.node_colors[a.value])&&(k.color=a.color,k.bgcolor=a.bgcolor,k.setDirtyCanvas(!0))},parentMenu:l,node:k});return!1};e.onMenuNodeShapes=function(a,b,c,e,l){if(!l)throw"no node passed"; new d.ContextMenu(d.VALID_SHAPES,{event:c,callback:function(a){l&&(l.shape=a,l.setDirtyCanvas(!0))},parentMenu:e,node:l});return!1};e.onMenuNodeRemove=function(a,b,c,d,e){if(!e)throw"no node passed";!1!=e.removable&&(e.graph.remove(e),e.setDirtyCanvas(!0,!0))};e.onMenuNodeClone=function(a,b,c,d,e){!1!=e.clonable&&(a=e.clone())&&(a.pos=[e.pos[0]+5,e.pos[1]+5],e.graph.add(a),e.setDirtyCanvas(!0,!0))};e.node_colors={red:{color:"#FAA",bgcolor:"#944"},green:{color:"#AFA",bgcolor:"#494"},blue:{color:"#AAF", @@ -158,7 +158,7 @@ window.requestAnimationFrame||(window.requestAnimationFrame=window.webkitRequest this.subgraph.onGlobalOutputRenamed=this.onSubgraphRenamedGlobalOutput.bind(this);this.subgraph.onGlobalOutputTypeChanged=this.onSubgraphTypeChangeGlobalOutput.bind(this);this.bgcolor="#663"}function e(){var a="input_"+(1E3*Math.random()).toFixed();this.addOutput(a,null);this.properties={name:a,type:null};var b=this;Object.defineProperty(this.properties,"name",{get:function(){return a},set:function(c){if(""!=c){var d=b.getOutputInfo(0);d.name!=c&&(d.name=c,b.graph&&b.graph.renameGlobalInput(a,c), a=c)}},enumerable:!0});Object.defineProperty(this.properties,"type",{get:function(){return b.outputs[0].type},set:function(c){b.outputs[0].type=c;b.graph&&b.graph.changeGlobalInputType(a,b.outputs[0].type)},enumerable:!0})}function t(){var a="output_"+(1E3*Math.random()).toFixed();this.addInput(a,null);this.properties={name:a,type:null};var b=this;Object.defineProperty(this.properties,"name",{get:function(){return a},set:function(c){if(""!=c){var d=b.getInputInfo(0);d.name!=c&&(d.name=c,b.graph&& b.graph.renameGlobalOutput(a,c),a=c)}},enumerable:!0});Object.defineProperty(this.properties,"type",{get:function(){return b.inputs[0].type},set:function(c){b.inputs[0].type=c;b.graph&&b.graph.changeGlobalInputType(a,b.inputs[0].type)},enumerable:!0})}function p(){this.addOutput("value","number");this.addProperty("value",1);this.editable={property:"value",type:"number"}}function u(){this.size=[60,20];this.addInput("value",0,{label:""});this.addOutput("value",0,{label:""});this.addProperty("value", -"")}function v(){this.addInput("in",0);this.addOutput("out",0);this.size=[40,20]}function d(){this.mode=l.ON_EVENT;this.size=[60,20];this.addProperty("msg","");this.addInput("log",l.EVENT);this.addInput("msg",0)}function s(){this.size=[60,20];this.addProperty("onExecute","");this.addInput("in","");this.addInput("in2","");this.addOutput("out","");this.addOutput("out2","");this._func=null}var l=q.LiteGraph;g.title="Time";g.desc="Time";g.prototype.onExecute=function(){this.setOutputData(0,1E3*this.graph.globaltime); +"")}function v(){this.addInput("in",0);this.addOutput("out",0);this.size=[40,20]}function d(){this.mode=l.ON_EVENT;this.size=[60,20];this.addProperty("msg","");this.addInput("log",l.EVENT);this.addInput("msg",0)}function r(){this.size=[60,20];this.addProperty("onExecute","");this.addInput("in","");this.addInput("in2","");this.addOutput("out","");this.addOutput("out2","");this._func=null}var l=q.LiteGraph;g.title="Time";g.desc="Time";g.prototype.onExecute=function(){this.setOutputData(0,1E3*this.graph.globaltime); this.setOutputData(1,this.graph.globaltime)};l.registerNodeType("basic/time",g);f.title="Subgraph";f.desc="Graph inside a node";f.prototype.onSubgraphNewGlobalInput=function(a,b){this.addInput(a,b)};f.prototype.onSubgraphRenamedGlobalInput=function(a,b){var c=this.findInputSlot(a);-1!=c&&(this.getInputInfo(c).name=b)};f.prototype.onSubgraphTypeChangeGlobalInput=function(a,b){var c=this.findInputSlot(a);-1!=c&&(this.getInputInfo(c).type=b)};f.prototype.onSubgraphNewGlobalOutput=function(a,b){this.addOutput(a, b)};f.prototype.onSubgraphRenamedGlobalOutput=function(a,b){var c=this.findOutputSlot(a);-1!=c&&(this.getOutputInfo(c).name=b)};f.prototype.onSubgraphTypeChangeGlobalOutput=function(a,b){var c=this.findOutputSlot(a);-1!=c&&(this.getOutputInfo(c).type=b)};f.prototype.getExtraMenuOptions=function(a){var b=this;return[{content:"Open",callback:function(){a.openSubgraph(b.subgraph)}}]};f.prototype.onExecute=function(){if(this.inputs)for(var a=0;a","string",{values:k.values}); -this.size=[60,40]}function r(){this.addInput("inc","number");this.addOutput("total","number");this.addProperty("increment",1);this.addProperty("value",0)}function n(){this.addInput("v","number");this.addOutput("sin","number");this.addProperty("amplitude",1);this.addProperty("offset",0);this.bgImageUrl="nodes/imgs/icon-sin.png"}function A(){this.addInput("vec2","vec2");this.addOutput("x","number");this.addOutput("y","number")}function z(){this.addInputs([["x","number"],["y","number"]]);this.addOutput("vec2", -"vec2");this.properties={x:0,y:0};this._data=new Float32Array(2)}function B(){this.addInput("vec3","vec3");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number")}function w(){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 y(){this.addInput("vec4","vec4");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number");this.addOutput("w", -"number")}function D(){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=q.LiteGraph;g.title="Converter";g.desc="type A to type B";g.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",b);c.values="+-*/%^".split("");c.title="Operation";c.desc="Easy math operators";c["@OP"]={type:"enum",title:"operation",values:c.values};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; +this.size=[60,40]}function s(){this.addInput("inc","number");this.addOutput("total","number");this.addProperty("increment",1);this.addProperty("value",0)}function n(){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("vec2","vec2");this.addOutput("x","number");this.addOutput("y","number")}function y(){this.addInputs([["x","number"],["y","number"]]);this.addOutput("vec2", +"vec2");this.properties={x:0,y:0};this._data=new Float32Array(2)}function C(){this.addInput("vec3","vec3");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number")}function A(){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 x(){this.addInput("vec4","vec4");this.addOutput("x","number");this.addOutput("y","number");this.addOutput("z","number");this.addOutput("w", +"number")}function B(){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 w=q.LiteGraph;g.title="Converter";g.desc="type A to type B";g.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))};w.registerNodeType("math/average",b);c.values="+-*/%^".split("");c.title="Operation";c.desc="Easy math operators";c["@OP"]={type:"enum",title:"operation",values:c.values};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="black",a.textAlign="center",a.fillText(this.properties.OP,0.5*this.size[0],0.5* -this.size[1]+x.NODE_TITLE_HEIGHT),a.textAlign="left")};x.registerNodeType("math/operation",c);h.title="Compare";h.desc="compares between two values";h.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)}}};h.prototype.onGetOutputs=function(){return[["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]};x.registerNodeType("math/compare",h);k.values="> < == != <= >=".split(" ");k["@OP"]={type:"enum",title:"operation",values:k.values};k.title="Condition";k.desc="evaluates condition between A and B";k.prototype.onExecute=function(){var a= -this.getInputData(0);void 0===a?a=this.properties.A:this.properties.A=a;var b=this.getInputData(1);void 0===b?b=this.properties.B:this.properties.B=b;var c=!0;switch(this.properties.OP){case ">":c=a>b;break;case "<":c=a=":c=a>=b}this.setOutputData(0,c)};x.registerNodeType("math/condition",k);r.title="Accumulate";r.desc="Increments a value every time";r.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",r);n.title="Trigonometry";n.desc="Sin Cos Tan";n.filter="shader";n.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, +this.size[1]+w.NODE_TITLE_HEIGHT),a.textAlign="left")};w.registerNodeType("math/operation",c);h.title="Compare";h.desc="compares between two values";h.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)}}};h.prototype.onGetOutputs=function(){return[["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]};w.registerNodeType("math/compare",h);k.values="> < == != <= >=".split(" ");k["@OP"]={type:"enum",title:"operation",values:k.values};k.title="Condition";k.desc="evaluates condition between A and B";k.prototype.onExecute=function(){var a= +this.getInputData(0);void 0===a?a=this.properties.A:this.properties.A=a;var b=this.getInputData(1);void 0===b?b=this.properties.B:this.properties.B=b;var c=!0;switch(this.properties.OP){case ">":c=a>b;break;case "<":c=a=":c=a>=b}this.setOutputData(0,c)};w.registerNodeType("math/condition",k);s.title="Accumulate";s.desc="Increments a value every time";s.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)};w.registerNodeType("math/accumulate",s);n.title="Trigonometry";n.desc="Sin Cos Tan";n.filter="shader";n.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,e=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);z.title="XY->Vec2";z.desc="components to vector2";z.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",z);B.title="Vec3->XYZ";B.desc="vector 3 to components";B.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",B);w.title="XYZ->Vec3";w.desc="components to vector3";w.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",w);y.title="Vec4->XYZW";y.desc="vector 4 to components"; -y.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",y);D.title="XYZW->Vec4";D.desc="components to vector4";D.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 e=this._data;e[0]=a;e[1]=b;e[2]=c;e[3]=d;this.setOutputData(0,e)};x.registerNodeType("math3d/xyzw-to-vec4",D);q.glMatrix&&(q=function(){this.addOutput("quat","quat");this.properties={x:0,y:0,z:0,w:1};this._value=quat.create()},q.title="Quaternion",q.desc="quaternion",q.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",q),q=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()},q.title="Rotation",q.desc="quaternion rotation",q.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",q),q=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},q.title="Rot. Vec3",q.desc="rotate a point",q.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",q),q=function(){this.addInputs([["A","quat"], -["B","quat"]]);this.addOutput("A*B","quat");this._value=quat.create()},q.title="Mult. Quat",q.desc="rotate quaternion",q.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",q),q=function(){this.addInputs([["A","quat"],["B","quat"],["factor","number"]]);this.addOutput("slerp","quat");this.addProperty("factor",0.5);this._value=quat.create()},q.title= -"Quat Slerp",q.desc="quaternion spherical interpolation",q.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",q))})(this); +function(){return[["sin","number"],["cos","number"],["tan","number"],["asin","number"],["acos","number"],["atan","number"]]};w.registerNodeType("math/trigonometry",n);if(void 0!=typeof math){var D=function(){this.addInputs("x","number");this.addInputs("y","number");this.addOutputs("","number");this.properties={x:1,y:1,formula:"x+y"}};D.title="Formula";D.desc="Compute safe formula";D.prototype.onExecute=function(){var a=this.getInputData(0),b=this.getInputData(1);null!=a?this.properties.x=a:a=this.properties.x; +null!=b?this.properties.y=b:b=this.properties.y;a=math.eval(this.properties.formula,{x:a,y:b,T:this.graph.globaltime});this.setOutputData(0,a)};D.prototype.onDrawBackground=function(){this.outputs[0].label=this.properties.formula};D.prototype.onGetOutputs=function(){return[["A-B","number"],["A*B","number"],["A/B","number"]]};w.registerNodeType("math/formula",D)}z.title="Vec2->XY";z.desc="vector 2 to components";z.prototype.onExecute=function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0, +a[0]),this.setOutputData(1,a[1]))};w.registerNodeType("math3d/vec2-to-xyz",z);y.title="XY->Vec2";y.desc="components to vector2";y.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)};w.registerNodeType("math3d/xy-to-vec2",y);C.title="Vec3->XYZ";C.desc="vector 3 to components";C.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]))};w.registerNodeType("math3d/vec3-to-xyz",C);A.title="XYZ->Vec3";A.desc="components to vector3";A.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)};w.registerNodeType("math3d/xyz-to-vec3",A);x.title="Vec4->XYZW";x.desc="vector 4 to components"; +x.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]))};w.registerNodeType("math3d/vec4-to-xyzw",x);B.title="XYZW->Vec4";B.desc="components to vector4";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 d=this.getInputData(3); +null==d&&(d=this.properties.w);var e=this._data;e[0]=a;e[1]=b;e[2]=c;e[3]=d;this.setOutputData(0,e)};w.registerNodeType("math3d/xyzw-to-vec4",B);q.glMatrix&&(q=function(){this.addOutput("quat","quat");this.properties={x:0,y:0,z:0,w:1};this._value=quat.create()},q.title="Quaternion",q.desc="quaternion",q.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)}, +w.registerNodeType("math3d/quaternion",q),q=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()},q.title="Rotation",q.desc="quaternion rotation",q.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)}, +w.registerNodeType("math3d/rotation",q),q=function(){this.addInputs([["vec3","vec3"],["quat","quat"]]);this.addOutput("result","vec3");this.properties={vec:[0,0,1]}},q.title="Rot. Vec3",q.desc="rotate a point",q.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))},w.registerNodeType("math3d/rotate_vec3",q),q=function(){this.addInputs([["A","quat"], +["B","quat"]]);this.addOutput("A*B","quat");this._value=quat.create()},q.title="Mult. Quat",q.desc="rotate quaternion",q.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))}},w.registerNodeType("math3d/mult-quat",q),q=function(){this.addInputs([["A","quat"],["B","quat"],["factor","number"]]);this.addOutput("slerp","quat");this.addProperty("factor",0.5);this._value=quat.create()},q.title= +"Quat Slerp",q.desc="quaternion spherical interpolation",q.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)}}},w.registerNodeType("math3d/quat-slerp",q))})(this); (function(q){function g(){this.addInput("sel","boolean");this.addOutput("value","number");this.properties={A:0,B:1};this.size=[60,20]}q=q.LiteGraph;g.title="Selector";g.desc="outputs A if selector is true, B if selector is false";g.prototype.onExecute=function(){var f=this.getInputData(0);if(void 0!==f){for(var e=1;e>1||0;d=d>>1||0;h=GL.Texture.getTemporary(c,d,a);g.push(h);l.setParameter(GL.TEXTURE_MAG_FILTER, -GL.NEAREST);l.copyTo(h,b,k);if(1==c&&1==d)break;l=h}this._texture=g.pop();for(u=0;u>1||0;d=d>>1||0;h=GL.Texture.getTemporary(c,d,a);g.push(h);l.setParameter(GL.TEXTURE_MAG_FILTER, +GL.NEAREST);l.copyTo(h,b,k);if(1==c&&1==d)break;l=h}this._texture=g.pop();for(p=0;pc;++c)b[c]=Math.random();l._shader.uniforms({u_samples_a:b.subarray(0,16),u_samples_b:b.subarray(16,32)})}b=this._temp_texture;c=this.properties.low_precision?gl.UNSIGNED_BYTE:a.type;b&&b.type==c||(this._temp_texture=new GL.Texture(1,1,{type:c,format:gl.RGBA,filter:gl.NEAREST}));var d=l._shader,e=this._uniforms;e.u_mipmap_offset=this.properties.mipmap_offset;this._temp_texture.drawTo(function(){a.toViewport(d,e)});this.setOutputData(0,this._temp_texture)}}; l.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"; g.registerNodeType("texture/average",l);q=function(){this.addInput("Image","image");this.addOutput("","Texture");this.properties={}};q.title="Image to Texture";q.desc="Uploads an image to the GPU";q.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"); @@ -307,48 +307,51 @@ values:[32,64,128,256,512]};h.prototype.onExecute=function(){gl.disable(gl.BLEND c);vec3.copy(l.u_colorB,d);c=parseInt(this.properties.texture_size);this._tex&&this._tex.width==c||(this._tex=new GL.Texture(c,c,{format:gl.RGB,filter:gl.LINEAR}));this._tex.drawTo(function(){b.uniforms(l).draw(a)});this.setOutputData(0,this._tex)};h.prototype.onGetInputs=function(){return[["angle","number"],["scale","number"]]};h.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform float u_angle;\n\t\t\tuniform float u_scale;\n\t\t\tuniform vec3 u_colorA;\n\t\t\tuniform vec3 u_colorB;\n\t\t\t\n\t\t\tvec2 rotate(vec2 v, float angle)\n\t\t\t{\n\t\t\t\tvec2 result;\n\t\t\t\tfloat _cos = cos(angle);\n\t\t\t\tfloat _sin = sin(angle);\n\t\t\t\tresult.x = v.x * _cos - v.y * _sin;\n\t\t\t\tresult.y = v.x * _sin + v.y * _cos;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tvoid main() {\n\t\t\t\tfloat f = (rotate(u_scale * (v_coord - vec2(0.5)), u_angle) + vec2(0.5)).x;\n\t\t\t\tvec3 color = mix(u_colorA,u_colorB,clamp(f,0.0,1.0));\n\t\t\t gl_FragColor = vec4(color,1.0);\n\t\t\t}\n\t\t\t"; g.registerNodeType("texture/gradient",h);var k=function(){this.addInput("A","Texture");this.addInput("B","Texture");this.addInput("Mixer","Texture");this.addOutput("Texture","Texture");this.properties={precision:f.DEFAULT};k._shader||(k._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,k.pixel_shader))};k.title="Mix";k.desc="Generates a texture mixing two textures";k.widgets_info={precision:{widget:"combo",values:f.MODE_VALUES}};k.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),c=this.getInputData(2);if(a&&b&&c){this._tex=f.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var d=Mesh.getScreenQuad(),e=k._shader;this._tex.drawTo(function(){a.bind(0);b.bind(1);c.bind(2);e.uniforms({u_textureA:0,u_textureB:1,u_textureMix:2}).draw(d)});this.setOutputData(0,this._tex)}}};k.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_textureA;\n\t\t\tuniform sampler2D u_textureB;\n\t\t\tuniform sampler2D u_textureMix;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), texture2D(u_textureMix, v_coord) );\n\t\t\t}\n\t\t\t"; -g.registerNodeType("texture/mix",k);var r=function(){this.addInput("Tex.","Texture");this.addOutput("Edges","Texture");this.properties={invert:!0,factor:1,precision:f.DEFAULT};r._shader||(r._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,r.pixel_shader))};r.title="Edges";r.desc="Detects edges";r.widgets_info={precision:{widget:"combo",values:f.MODE_VALUES}};r.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){this._tex=f.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),c=r._shader,d=this.properties.invert,e=this.properties.factor;this._tex.drawTo(function(){a.bind(0);c.uniforms({u_texture:0,u_isize:[1/a.width,1/a.height],u_factor:e,u_invert:d?1:0}).draw(b)});this.setOutputData(0,this._tex)}}};r.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_isize;\n\t\t\tuniform int u_invert;\n\t\t\tuniform float u_factor;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 center = texture2D(u_texture, v_coord);\n\t\t\t\tvec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\t\t\t\tvec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\t\t\t\tvec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\t\t\t\tvec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\t\t\t\tvec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\t\t\t\tdiff *= u_factor;\n\t\t\t\tif(u_invert == 1)\n\t\t\t\t\tdiff.xyz = vec3(1.0) - diff.xyz;\n\t\t\t gl_FragColor = vec4( diff.xyz, center.a );\n\t\t\t}\n\t\t\t"; -g.registerNodeType("texture/edges",r);var n=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}};n.title="Depth Range";n.desc="Generates a texture with a depth range";n.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0); +g.registerNodeType("texture/mix",k);var s=function(){this.addInput("Tex.","Texture");this.addOutput("Edges","Texture");this.properties={invert:!0,factor:1,precision:f.DEFAULT};s._shader||(s._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,s.pixel_shader))};s.title="Edges";s.desc="Detects edges";s.widgets_info={precision:{widget:"combo",values:f.MODE_VALUES}};s.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){this._tex=f.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),c=s._shader,d=this.properties.invert,e=this.properties.factor;this._tex.drawTo(function(){a.bind(0);c.uniforms({u_texture:0,u_isize:[1/a.width,1/a.height],u_factor:e,u_invert:d?1:0}).draw(b)});this.setOutputData(0,this._tex)}}};s.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_isize;\n\t\t\tuniform int u_invert;\n\t\t\tuniform float u_factor;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 center = texture2D(u_texture, v_coord);\n\t\t\t\tvec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\t\t\t\tvec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\t\t\t\tvec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\t\t\t\tvec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\t\t\t\tvec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\t\t\t\tdiff *= u_factor;\n\t\t\t\tif(u_invert == 1)\n\t\t\t\t\tdiff.xyz = vec3(1.0) - diff.xyz;\n\t\t\t gl_FragColor = vec4( diff.xyz, center.a );\n\t\t\t}\n\t\t\t"; +g.registerNodeType("texture/edges",s);var n=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}};n.title="Depth Range";n.desc="Generates a texture with a depth range";n.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();n._shader||(n._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,n.pixel_shader),n._shader_onlydepth=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,n.pixel_shader,{ONLY_DEPTH:""}));var f=this.properties.only_depth?n._shader_onlydepth:n._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);f.uniforms(c).draw(e)});this.setOutputData(0,this._temp_texture)}}};n.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"; -g.registerNodeType("texture/depth_range",n);var A=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]}};A.title="Blur";A.desc="Blur a texture";A.max_iterations=20;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}),this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));b=this.properties.iterations;this.isInputConnected(1)&&(b=this.getInputData(1),this.properties.iterations=b);b=Math.min(Math.floor(b),A.max_iterations);if(0==b)this.setOutputData(0,a);else{var c=this.properties.intensity;this.isInputConnected(2)&&(c=this.getInputData(2),this.properties.intensity= -c);var d=g.camera_aspect;d||void 0===window.gl||(d=gl.canvas.height/gl.canvas.width);d||(d=1);for(var d=this.properties.preserve_aspect?d:1,e=this.properties.scale||[1,1],f=0;f=this.size[1]|| !this._video||(a.save(),a.webgl?this._temp_texture&&a.drawImage(this._temp_texture,0,0,this.size[0],this.size[1]):(a.translate(0,this.size[1]),a.scale(1,-1),a.drawImage(this._video,0,0,this.size[0],this.size[1])),a.restore())};q.prototype.onExecute=function(){null!=this._webcam_stream||this._waiting_confirmation||this.openStream();if(this._video&&this._video.videoWidth){var a=this._video.videoWidth,b=this._video.videoHeight,c=this._temp_texture;c&&c.width==a&&c.height==b||(this._temp_texture=new GL.Texture(a, -b,{format:gl.RGB,filter:gl.LINEAR}));this._temp_texture.uploadImage(this._video);this.properties.texture_name&&(f.getTexturesContainer()[this.properties.texture_name]=this._temp_texture);this.setOutputData(0,this._temp_texture)}};g.registerNodeType("texture/webcam",q);var B=function(){this.addInput("in","Texture");this.addOutput("out","Texture");this.properties={key_color:vec3.fromValues(0,1,0),threshold:0.8,slope:0.2,precision:f.DEFAULT};B._shader||(B._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER, -B.pixel_shader))};B.title="Matte";B.desc="Extracts background";B.widgets_info={key_color:{widget:"color"},precision:{widget:"combo",values:f.MODE_VALUES}};B.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){this._tex=f.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);this._uniforms||(this._uniforms={u_texture:0,u_key_color:this.properties.key_color, -u_threshold:1,u_slope:1});var b=this._uniforms,c=Mesh.getScreenQuad(),d=B._shader;b.u_key_color=this.properties.key_color;b.u_threshold=this.properties.threshold;b.u_slope=this.properties.slope;this._tex.drawTo(function(){a.bind(0);d.uniforms(b).draw(c)});this.setOutputData(0,this._tex)}}};B.pixel_shader="precision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec3 u_key_color;\n\t\t\tuniform float u_threshold;\n\t\t\tuniform float u_slope;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec3 color = texture2D( u_texture, v_coord ).xyz;\n\t\t\t\tfloat diff = length( normalize(color) - normalize(u_key_color) );\n\t\t\t\tfloat edge = u_threshold * (1.0 - u_slope);\n\t\t\t\tfloat alpha = smoothstep( edge, u_threshold, diff);\n\t\t\t\tgl_FragColor = vec4( color, alpha );\n\t\t\t}"; -g.registerNodeType("texture/matte",B);q=function(){this.addOutput("Cubemap","Cubemap");this.properties={name:""};this.size=[f.image_preview_size,f.image_preview_size]};q.title="Cubemap";q.prototype.onDropFile=function(a,b,c){a?(this._drop_texture="string"==typeof a?GL.Texture.fromURL(a):GL.Texture.fromDDSInMemory(a),this.properties.name=b):(this._drop_texture=null,this.properties.name="")};q.prototype.onExecute=function(){if(this._drop_texture)this.setOutputData(0,this._drop_texture);else if(this.properties.name){var a= +b,{format:gl.RGB,filter:gl.LINEAR}));this._temp_texture.uploadImage(this._video);this.properties.texture_name&&(f.getTexturesContainer()[this.properties.texture_name]=this._temp_texture);this.setOutputData(0,this._temp_texture)}};g.registerNodeType("texture/webcam",q);var C=function(){this.addInput("in","Texture");this.addInput("exp","number");this.addOutput("out","Texture");this.properties={exposition:1,precision:f.LOW}};C.title="Exposition";C.desc="Controls texture exposition";C.widgets_info={exposition:{widget:"slider", +min:0,max:3},precision:{widget:"combo",values:f.MODE_VALUES}};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||(b=this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));var c=C._shader;c||(c=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,C.pixel_shader));var d=this.properties.exposition,e=this.getInputData(1);null!=e&&(d=this.properties.exposition= +e);b.drawTo(function(){gl.disable(gl.DEPTH_TEST);a.bind(0);var b=GL.Mesh.getScreenQuad();c.uniforms({u_texture:0,u_exposition:d}).draw(b)});this.setOutputData(0,b)}};C.pixel_shader="precision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform float u_exposition;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 color = texture2D( u_texture, v_coord );\n\t\t\t\tgl_FragColor = vec4( color.xyz * u_exposition, color.a );\n\t\t\t}";g.registerNodeType("texture/exposition", +C);var A=function(){this.addInput("in","Texture");this.addOutput("out","Texture");this.properties={key_color:vec3.fromValues(0,1,0),threshold:0.8,slope:0.2,precision:f.DEFAULT};A._shader||(A._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,A.pixel_shader))};A.title="Matte";A.desc="Extracts background";A.widgets_info={key_color:{widget:"color"},precision:{widget:"combo",values:f.MODE_VALUES}};A.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){this._tex=f.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);this._uniforms||(this._uniforms={u_texture:0,u_key_color:this.properties.key_color,u_threshold:1,u_slope:1});var b=this._uniforms,c=Mesh.getScreenQuad(),d=A._shader;b.u_key_color=this.properties.key_color;b.u_threshold=this.properties.threshold;b.u_slope=this.properties.slope;this._tex.drawTo(function(){a.bind(0);d.uniforms(b).draw(c)}); +this.setOutputData(0,this._tex)}}};A.pixel_shader="precision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec3 u_key_color;\n\t\t\tuniform float u_threshold;\n\t\t\tuniform float u_slope;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec3 color = texture2D( u_texture, v_coord ).xyz;\n\t\t\t\tfloat diff = length( normalize(color) - normalize(u_key_color) );\n\t\t\t\tfloat edge = u_threshold * (1.0 - u_slope);\n\t\t\t\tfloat alpha = smoothstep( edge, u_threshold, diff);\n\t\t\t\tgl_FragColor = vec4( color, alpha );\n\t\t\t}"; +g.registerNodeType("texture/matte",A);q=function(){this.addOutput("Cubemap","Cubemap");this.properties={name:""};this.size=[f.image_preview_size,f.image_preview_size]};q.title="Cubemap";q.prototype.onDropFile=function(a,b,c){a?(this._drop_texture="string"==typeof a?GL.Texture.fromURL(a):GL.Texture.fromDDSInMemory(a),this.properties.name=b):(this._drop_texture=null,this.properties.name="")};q.prototype.onExecute=function(){if(this._drop_texture)this.setOutputData(0,this._drop_texture);else if(this.properties.name){var a= f.getTexture(this.properties.name);a&&(this._last_tex=a,this.setOutputData(0,a))}};q.prototype.onDrawBackground=function(a){this.flags.collapsed||20>=this.size[1]||a.webgl&&(gl.meshes.cube||(gl.meshes.cube=GL.Mesh.cube({size:1})))};g.registerNodeType("texture/cubemap",q)}})(this); -(function(q){var g=q.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(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, +(function(q){var g=q.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 e=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,e);else if(e){this._tex=LGraphTexture.getTargetTexture(e,this._tex,this.properties.precision);var g=this.properties.aberration;this.isInputConnected(1)&&(g=this.getInputData(1), this.properties.aberration=g);var d=this.properties.distortion;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.distortion=d);var p=this.properties.blur;this.isInputConnected(3)&&(p=this.getInputData(3),this.properties.blur=p);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var l=Mesh.getScreenQuad(),a=f._shader;this._tex.drawTo(function(){e.bind(0);a.uniforms({u_texture:0,u_aberration:g,u_distortion:d,u_blur:p}).draw(l)});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"; -g.registerNodeType("fx/lens",f);window.LGraphFXLens=f;var e=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}};e.title="Bokeh";e.desc="applies an Bokeh effect";e.widgets_info={shape:{widget:"texture"}};e.prototype.onExecute=function(){var f=this.getInputData(0),g=this.getInputData(1),d=this.getInputData(2); +g.registerNodeType("fx/lens",f);q.LGraphFXLens=f;var e=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}};e.title="Bokeh";e.desc="applies an Bokeh effect";e.widgets_info={shape:{widget:"texture"}};e.prototype.onExecute=function(){var f=this.getInputData(0),g=this.getInputData(1),d=this.getInputData(2); if(f&&d&&this.properties.shape){g||(g=f);var p=LGraphTexture.getTexture(this.properties.shape);if(p){var l=this.properties.threshold;this.isInputConnected(3)&&(l=this.getInputData(3),this.properties.threshold=l);var a=gl.UNSIGNED_BYTE;this.properties.high_precision&&(a=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==a&&this._temp_texture.width==f.width&&this._temp_texture.height==f.height||(this._temp_texture=new GL.Texture(f.width,f.height,{type:a,format:gl.RGBA, filter:gl.LINEAR}));var b=e._first_shader;b||(b=e._first_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,e._first_pixel_shader));var c=e._second_shader;c||(c=e._second_shader=new GL.Shader(e._second_vertex_shader,e._second_pixel_shader));var h=this._points_mesh;h&&h._width==f.width&&h._height==f.height&&2==h._spacing||(h=this.createPointsMesh(f.width,f.height,2));var k=Mesh.getScreenQuad(),t=this.properties.size,n=this.properties.alpha;gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){f.bind(0); g.bind(1);d.bind(2);b.uniforms({u_texture:0,u_texture_blur:1,u_mask:2,u_texsize:[f.width,f.height]}).draw(k)});this._temp_texture.drawTo(function(){gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);f.bind(0);p.bind(3);c.uniforms({u_texture:0,u_mask:2,u_shape:3,u_alpha:n,u_threshold:l,u_pointSize:t,u_itexsize:[1/f.width,1/f.height]}).draw(h,gl.POINTS)});this.setOutputData(0,this._temp_texture)}}else this.setOutputData(0,f)};e.prototype.createPointsMesh=function(e,f,d){for(var g=Math.round(e/d),l=Math.round(f/ -d),a=new Float32Array(g*l*2),b=-1,c=2/e*d,h=2/f*d,k=0;k=g.NOTEON||a<=g.NOTEOFF)this.channel=d&15};Object.defineProperty(g.prototype,"velocity",{get:function(){return this.cmd==g.NOTEON?this.data[2]: +(function(q){function g(d){this.cmd=this.channel=0;d?this.setup(d):this.data=[0,0,0]}function f(d,a){navigator.requestMIDIAccess?(this.on_ready=d,this.state={note:[],cc:[]},navigator.requestMIDIAccess().then(this.onMIDISuccess.bind(this),this.onMIDIFailure.bind(this))):(this.error="not suppoorted",a?a("Not supported"):console.error("MIDI NOT SUPPORTED, enable by chrome://flags"))}function e(){this.addOutput("on_midi",r.EVENT);this.addOutput("out","midi");this.properties={port:0};this._current_midi_event= +this._last_midi_event=null;var d=this;new f(function(a){d._midi=a;if(d._waiting)d.onStart();d._waiting=!1})}function t(){this.addInput("send",r.EVENT);this.properties={port:0};var d=this;new f(function(a){d._midi=a})}function p(){this.addInput("on_midi",r.EVENT);this._str="";this.size=[200,40]}function u(){this.properties={channel:-1,cmd:-1,min_value:-1,max_value:-1};this.addInput("in",r.EVENT);this.addOutput("on_midi",r.EVENT)}function v(){this.properties={channel:0,cmd:"CC",value1:1,value2:1};this.addInput("send", +r.EVENT);this.addInput("assign",r.EVENT);this.addOutput("on_midi",r.EVENT)}function d(){this.properties={cc:1,value:0};this.addOutput("value","number")}var r=q.LiteGraph;g.prototype.setup=function(d){this.data=d;this.status=d=d[0];var a=d&240;this.cmd=240<=d?d:a;this.cmd==g.NOTEON&&0==this.velocity&&(this.cmd=g.NOTEOFF);this.cmd_str=g.commands[this.cmd]||"";if(a>=g.NOTEON||a<=g.NOTEOFF)this.channel=d&15};Object.defineProperty(g.prototype,"velocity",{get:function(){return this.cmd==g.NOTEON?this.data[2]: -1},set:function(d){this.data[2]=d},enumerable:!0});g.notes="A A# B C C# D D# E F F# G G#".split(" ");g.prototype.getPitch=function(){return 440*Math.pow(2,(this.data[1]-69)/12)};g.computePitch=function(d){return 440*Math.pow(2,(d-69)/12)};g.prototype.getCC=function(){return this.data[1]};g.prototype.getCCValue=function(){return this.data[2]};g.prototype.getPitchBend=function(){return this.data[1]+(this.data[2]<<7)-8192};g.computePitchBend=function(d,a){return d+(a<<7)-8192};g.prototype.setCommandFromString= function(d){this.cmd=g.computeCommandFromString(d)};g.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 g.NOTEON;case "NOTE OFF":case "NOTEOFF":return g.NOTEON;case "KEY PRESSURE":case "KEYPRESSURE":return g.KEYPRESSURE;case "CONTROLLER CHANGE":case "CONTROLLERCHANGE":case "CC":return g.CONTROLLERCHANGE;case "PROGRAM CHANGE":case "PROGRAMCHANGE":case "PC":return g.PROGRAMCHANGE;case "CHANNEL PRESSURE":case "CHANNELPRESSURE":return g.CHANNELPRESSURE; case "PITCH BEND":case "PITCHBEND":return g.PITCHBEND;case "TIME TICK":case "TIMETICK":return g.TIMETICK;default:return Number(d)}};g.toNoteString=function(d){var a;a=(d-21)%12;0>a&&(a=12+a);return g.notes[a]+Math.floor((d-24)/12+1)};g.prototype.toString=function(){var d=""+this.channel+". ";switch(this.cmd){case g.NOTEON:d+="NOTEON "+g.toNoteString(this.data[1]);break;case g.NOTEOFF:d+="NOTEOFF "+g.toNoteString(this.data[1]);break;case g.CONTROLLERCHANGE:d+="CC "+this.data[1]+" "+this.data[2];break; @@ -358,48 +361,48 @@ case g.PROGRAMCHANGE:d+="PC "+this.data[1];break;case g.PITCHBEND:d+="PITCHBEND function(d){console.error("Failed to get MIDI access - "+d)};f.prototype.openInputPort=function(d,a){var b=this.input_ports.get("input-"+d);if(!b)return!1;f.input=this;var c=this;b.onmidimessage=function(b){var d=new g(b.data);c.updateState(d);a&&a(b.data,d);if(f.on_message)f.on_message(b.data,d)};console.log("port open: ",b);return!0};f.parseMsg=function(d){};f.prototype.updateState=function(d){switch(d.cmd){case g.NOTEON:this.state.note[d.value1|0]=d.value2;break;case g.NOTEOFF:this.state.note[d.value1| 0]=0;break;case g.CONTROLLERCHANGE:this.state.cc[d.getCC()]=d.getCCValue()}};f.prototype.sendMIDI=function(d,a){if(a){var b=this.output_ports.get("output-"+d);b&&(f.output=this,a.constructor===g?b.send(a.data):b.send(a))}};e.MIDIInterface=f;e.title="MIDI Input";e.desc="Reads MIDI from a input port";e.prototype.getPropertyInfo=function(d){if(this._midi&&"port"==d){d={};for(var a=0;athis.properties.max_value||this.trigger("on_midi",a)};s.registerNodeType("midi/filter",u);v.title="MIDIEvent";v.desc="Create a MIDI Event";v.prototype.onAction=function(d,a){"assign"==d?(this.properties.channel=a.channel,this.properties.cmd=a.cmd,this.properties.value1= +this._last_midi_event,a=0;athis.properties.max_value||this.trigger("on_midi",a)};r.registerNodeType("midi/filter",u);v.title="MIDIEvent";v.desc="Create a MIDI Event";v.prototype.onAction=function(d,a){"assign"==d?(this.properties.channel=a.channel,this.properties.cmd=a.cmd,this.properties.value1= a.data[1],this.properties.value2=a.data[2]):(a=new g,a.channel=this.properties.channel,this.properties.cmd&&this.properties.cmd.constructor===String?a.setCommandFromString(this.properties.cmd):a.cmd=this.properties.cmd,a.data[0]=a.cmd|a.channel,a.data[1]=Number(this.properties.value1),a.data[2]=Number(this.properties.value2),this.trigger("on_midi",a))};v.prototype.onExecute=function(){var d=this.properties;if(this.outputs)for(var a=0;a=this.size[0]&&(e=this.size[0]-1),a.strokeStyle="red",a.beginPath(),a.moveTo(e,d),a.lineTo(e,0),a.stroke())}};a.title="Visualization";a.desc="Audio Visualization";k.registerNodeType("audio/visualization", -a);b.prototype.onExecute=function(){if(this._freqs=this.getInputData(0)){var a=this.properties.band,b=this.getInputData(1);void 0!==b&&(a=b);b=r.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)}};b.prototype.onGetInputs=function(){return[["band","number"]]};b.title="Signal";b.desc="extract the signal of some frequency";k.registerNodeType("audio/signal", +s.createAudioNodeWrapper(l);l.title="Oscillator";l.desc="Oscillator";k.registerNodeType("audio/oscillator",l);a.prototype.onExecute=function(){this._last_buffer=this.getInputData(0);var a=this.getInputData(1);void 0!==a&&(this.properties.mark=a);this.setDirtyCanvas(!0,!1)};a.prototype.onDrawForeground=function(a){if(this._last_buffer){var b=this._last_buffer,c=b.length/this.size[0],d=this.size[1];a.fillStyle="black";a.fillRect(0,0,this.size[0],this.size[1]);a.strokeStyle="white";a.beginPath();var e= +0;if(this.properties.continuous){a.moveTo(e,d);for(var f=0;f=this.size[0]&&(e=this.size[0]-1),a.strokeStyle="red",a.beginPath(),a.moveTo(e,d),a.lineTo(e,0),a.stroke())}};a.title="Visualization";a.desc="Audio Visualization";k.registerNodeType("audio/visualization", +a);b.prototype.onExecute=function(){if(this._freqs=this.getInputData(0)){var a=this.properties.band,b=this.getInputData(1);void 0!==b&&(a=b);b=s.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)}};b.prototype.onGetInputs=function(){return[["band","number"]]};b.title="Signal";b.desc="extract the signal of some frequency";k.registerNodeType("audio/signal", b);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 - - + + diff --git a/demo/code.js b/demo/js/code.js similarity index 100% rename from demo/code.js rename to demo/js/code.js diff --git a/demo/demo.js b/demo/js/demos.js similarity index 100% rename from demo/demo.js rename to demo/js/demos.js diff --git a/doc/classes/LGraph.html b/doc/classes/LGraph.html index b7416a56c..d69a3600b 100644 --- a/doc/classes/LGraph.html +++ b/doc/classes/LGraph.html @@ -175,7 +175,7 @@
  • - findNodesByName + findNodesByTitle
  • @@ -594,8 +594,8 @@ -
    -

    findNodesByName

    +
    +

    findNodesByTitle

    (
      diff --git a/doc/data.json b/doc/data.json index 57ea0a337..3a2b4a2e3 100644 --- a/doc/data.json +++ b/doc/data.json @@ -497,7 +497,7 @@ "line": 1027, "description": "Returns a list of nodes that matches a name", "itemtype": "method", - "name": "findNodesByName", + "name": "findNodesByTitle", "params": [ { "name": "name", diff --git a/doc/files/.._src_litegraph.js.html b/doc/files/.._src_litegraph.js.html index 0eda72bcf..dee241dd4 100644 --- a/doc/files/.._src_litegraph.js.html +++ b/doc/files/.._src_litegraph.js.html @@ -170,7 +170,7 @@ var LiteGraph = global.LiteGraph = { console.log("Node registered: " + type); var categories = type.split("/"); - var classname = base_class.constructor.name; + var classname = base_class.name; var pos = type.lastIndexOf("/"); base_class.category = type.substr(0,pos); @@ -1112,7 +1112,7 @@ LGraph.prototype.findNodesByType = function(type) /** * Returns a list of nodes that matches a name -* @method findNodesByName +* @method findNodesByTitle * @param {String} name the name of the node to search * @return {Array} a list with all the nodes with this name */ @@ -1323,7 +1323,7 @@ LGraph.prototype.removeGlobalOutput = function(name) LGraph.prototype.setInputData = function(name,value) { - var nodes = this.findNodesByName( name ); + var nodes = this.findNodesByTitle( name ); for(var i = 0, l = nodes.length; i < l; ++i) nodes[i].setValue(value); } @@ -1337,7 +1337,7 @@ LGraph.prototype.setInputData = function(name,value) LGraph.prototype.getOutputData = function(name) { - var n = this.findNodesByName(name); + var n = this.findNodesByTitle(name); if(n.length) return m[0].getValue(); return null; @@ -1347,14 +1347,14 @@ LGraph.prototype.getOutputData = function(name) LGraph.prototype.triggerInput = function(name,value) { - var nodes = this.findNodesByName(name); + var nodes = this.findNodesByTitle(name); for(var i = 0; i < nodes.length; ++i) nodes[i].onTrigger(value); } LGraph.prototype.setCallback = function(name,func) { - var nodes = this.findNodesByName(name); + var nodes = this.findNodesByTitle(name); for(var i = 0; i < nodes.length; ++i) nodes[i].setTrigger(func); } diff --git a/src/litegraph.js b/src/litegraph.js index 4b03238ce..90d35b48c 100755 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -84,7 +84,7 @@ var LiteGraph = global.LiteGraph = { console.log("Node registered: " + type); var categories = type.split("/"); - var classname = base_class.constructor.name; + var classname = base_class.name; var pos = type.lastIndexOf("/"); base_class.category = type.substr(0,pos); @@ -1026,7 +1026,7 @@ LGraph.prototype.findNodesByType = function(type) /** * Returns a list of nodes that matches a name -* @method findNodesByName +* @method findNodesByTitle * @param {String} name the name of the node to search * @return {Array} a list with all the nodes with this name */ @@ -1237,7 +1237,7 @@ LGraph.prototype.removeGlobalOutput = function(name) LGraph.prototype.setInputData = function(name,value) { - var nodes = this.findNodesByName( name ); + var nodes = this.findNodesByTitle( name ); for(var i = 0, l = nodes.length; i < l; ++i) nodes[i].setValue(value); } @@ -1251,7 +1251,7 @@ LGraph.prototype.setInputData = function(name,value) LGraph.prototype.getOutputData = function(name) { - var n = this.findNodesByName(name); + var n = this.findNodesByTitle(name); if(n.length) return m[0].getValue(); return null; @@ -1261,14 +1261,14 @@ LGraph.prototype.getOutputData = function(name) LGraph.prototype.triggerInput = function(name,value) { - var nodes = this.findNodesByName(name); + var nodes = this.findNodesByTitle(name); for(var i = 0; i < nodes.length; ++i) nodes[i].onTrigger(value); } LGraph.prototype.setCallback = function(name,func) { - var nodes = this.findNodesByName(name); + var nodes = this.findNodesByTitle(name); for(var i = 0; i < nodes.length; ++i) nodes[i].setTrigger(func); } diff --git a/src/nodes/glfx.js b/src/nodes/glfx.js index 66ca105a4..14b467137 100755 --- a/src/nodes/glfx.js +++ b/src/nodes/glfx.js @@ -17,7 +17,7 @@ if(typeof(GL) != "undefined") if(!LGraphFXLens._shader) { - LGraphFXLens._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphFXLens.pixel_shader ); + LGraphFXLens._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphFXLens.pixel_shader ); LGraphFXLens._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] }); } } @@ -110,7 +110,120 @@ if(typeof(GL) != "undefined") */ LiteGraph.registerNodeType("fx/lens", LGraphFXLens ); - window.LGraphFXLens = LGraphFXLens; + global.LGraphFXLens = LGraphFXLens; + + /* not working yet + function LGraphDepthOfField() + { + this.addInput("Color","Texture"); + this.addInput("Linear Depth","Texture"); + this.addInput("Camera","camera"); + this.addOutput("Texture","Texture"); + this.properties = { high_precision: false }; + } + + LGraphDepthOfField.title = "Depth Of Field"; + LGraphDepthOfField.desc = "Applies a depth of field effect"; + + LGraphDepthOfField.prototype.onExecute = function() + { + var tex = this.getInputData(0); + var depth = this.getInputData(1); + var camera = this.getInputData(2); + + if(!tex || !depth || !camera) + { + this.setOutputData(0, tex); + return; + } + + var precision = gl.UNSIGNED_BYTE; + if(this.properties.high_precision) + precision = gl.half_float_ext ? gl.HALF_FLOAT_OES : gl.FLOAT; + if(!this._temp_texture || this._temp_texture.type != precision || + this._temp_texture.width != tex.width || this._temp_texture.height != tex.height) + this._temp_texture = new GL.Texture( tex.width, tex.height, { type: precision, format: gl.RGBA, filter: gl.LINEAR }); + + var shader = LGraphDepthOfField._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphDepthOfField._pixel_shader ); + + var screen_mesh = Mesh.getScreenQuad(); + + gl.disable( gl.DEPTH_TEST ); + gl.disable( gl.BLEND ); + + var camera_position = camera.getEye(); + var focus_point = camera.getCenter(); + var distance = vec3.distance( camera_position, focus_point ); + var far = camera.far; + var focus_range = distance * 0.5; + + this._temp_texture.drawTo( function() { + tex.bind(0); + depth.bind(1); + shader.uniforms({u_texture:0, u_depth_texture:1, u_resolution: [1/tex.width, 1/tex.height], u_far: far, u_focus_point: distance, u_focus_scale: focus_range }).draw(screen_mesh); + }); + + this.setOutputData(0, this._temp_texture); + } + + //from http://tuxedolabs.blogspot.com.es/2018/05/bokeh-depth-of-field-in-single-pass.html + LGraphDepthOfField._pixel_shader = "\n\ + precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture; //Image to be processed\n\ + uniform sampler2D u_depth_texture; //Linear depth, where 1.0 == far plane\n\ + uniform vec2 u_iresolution; //The size of a pixel: vec2(1.0/width, 1.0/height)\n\ + uniform float u_far; // Far plane\n\ + uniform float u_focus_point;\n\ + uniform float u_focus_scale;\n\ + \n\ + const float GOLDEN_ANGLE = 2.39996323;\n\ + const float MAX_BLUR_SIZE = 20.0;\n\ + const float RAD_SCALE = 0.5; // Smaller = nicer blur, larger = faster\n\ + \n\ + float getBlurSize(float depth, float focusPoint, float focusScale)\n\ + {\n\ + float coc = clamp((1.0 / focusPoint - 1.0 / depth)*focusScale, -1.0, 1.0);\n\ + return abs(coc) * MAX_BLUR_SIZE;\n\ + }\n\ + \n\ + vec3 depthOfField(vec2 texCoord, float focusPoint, float focusScale)\n\ + {\n\ + float centerDepth = texture2D(u_depth_texture, texCoord).r * u_far;\n\ + float centerSize = getBlurSize(centerDepth, focusPoint, focusScale);\n\ + vec3 color = texture2D(u_texture, v_coord).rgb;\n\ + float tot = 1.0;\n\ + \n\ + float radius = RAD_SCALE;\n\ + for (float ang = 0.0; ang < 100.0; ang += GOLDEN_ANGLE)\n\ + {\n\ + vec2 tc = texCoord + vec2(cos(ang), sin(ang)) * u_iresolution * radius;\n\ + \n\ + vec3 sampleColor = texture2D(u_texture, tc).rgb;\n\ + float sampleDepth = texture2D(u_depth_texture, tc).r * u_far;\n\ + float sampleSize = getBlurSize( sampleDepth, focusPoint, focusScale );\n\ + if (sampleDepth > centerDepth)\n\ + sampleSize = clamp(sampleSize, 0.0, centerSize*2.0);\n\ + \n\ + float m = smoothstep(radius-0.5, radius+0.5, sampleSize);\n\ + color += mix(color/tot, sampleColor, m);\n\ + tot += 1.0;\n\ + radius += RAD_SCALE/radius;\n\ + if(radius>=MAX_BLUR_SIZE)\n\ + return color / tot;\n\ + }\n\ + return color / tot;\n\ + }\n\ + void main()\n\ + {\n\ + gl_FragColor = vec4( depthOfField( v_coord, u_focus_point, u_focus_scale ), 1.0 );\n\ + //gl_FragColor = vec4( texture2D(u_depth_texture, v_coord).r );\n\ + }\n\ + "; + + LiteGraph.registerNodeType("fx/DOF", LGraphDepthOfField ); + global.LGraphDepthOfField = LGraphDepthOfField; + */ //******************************************************* @@ -311,7 +424,7 @@ if(typeof(GL) != "undefined") LiteGraph.registerNodeType("fx/bokeh", LGraphFXBokeh ); - window.LGraphFXBokeh = LGraphFXBokeh; + global.LGraphFXBokeh = LGraphFXBokeh; //************************************************ @@ -380,7 +493,7 @@ if(typeof(GL) != "undefined") gl.disable( gl.BLEND ); gl.disable( gl.DEPTH_TEST ); var mesh = Mesh.getScreenQuad(); - var camera = window.LS ? LS.Renderer._current_camera : null; + var camera = global.LS ? LS.Renderer._current_camera : null; if(camera) camera_planes = [LS.Renderer._current_camera.near, LS.Renderer._current_camera.far]; else @@ -480,7 +593,7 @@ if(typeof(GL) != "undefined") LiteGraph.registerNodeType("fx/generic", LGraphFXGeneric ); - window.LGraphFXGeneric = LGraphFXGeneric; + global.LGraphFXGeneric = LGraphFXGeneric; // Vigneting ************************************ diff --git a/src/nodes/gltextures.js b/src/nodes/gltextures.js index cb7afc40a..5ada8018a 100755 --- a/src/nodes/gltextures.js +++ b/src/nodes/gltextures.js @@ -1912,7 +1912,8 @@ if(typeof(GL) != "undefined") shader.uniforms( uniforms ).draw(mesh); }); - this.setOutputData(0, this._temp_texture); + this._temp_texture.near_far_planes = planes; + this.setOutputData(0, this._temp_texture ); } LGraphTextureDepthRange.pixel_shader = "precision highp float;\n\ @@ -2329,6 +2330,141 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam ); + //simple exposition, but plan to expand it to support different gamma curves + function LGraphExposition() + { + this.addInput("in","Texture"); + this.addInput("exp","number"); + this.addOutput("out","Texture"); + this.properties = { exposition: 1, precision: LGraphTexture.LOW }; + } + + LGraphExposition.title = "Exposition"; + LGraphExposition.desc = "Controls texture exposition"; + + LGraphExposition.widgets_info = { + "exposition": { widget:"slider", min:0,max:3 }, + "precision": { widget:"combo", values: LGraphTexture.MODE_VALUES } + }; + + LGraphExposition.prototype.onExecute = function() + { + var tex = this.getInputData(0); + if(!tex) + return; + + if(!this.isOutputConnected(0)) + return; //saves work + + var temp = this._temp_texture; + if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) + temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + + var shader = LGraphExposition._shader; + if(!shader) + shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphExposition.pixel_shader ); + + var exp = this.properties.exposition; + var exp_input = this.getInputData(1); + if(exp_input != null) + exp = this.properties.exposition = exp_input; + + //apply shader + temp.drawTo(function(){ + gl.disable( gl.DEPTH_TEST ); + tex.bind(0); + var mesh = GL.Mesh.getScreenQuad(); + shader.uniforms({ u_texture: 0, u_exposition: exp }).draw(mesh); + }); + + this.setOutputData(0,temp); + } + + LGraphExposition.pixel_shader = "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float u_exposition;\n\ + \n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord );\n\ + gl_FragColor = vec4( color.xyz * u_exposition, color.a );\n\ + }"; + + LiteGraph.registerNodeType("texture/exposition", LGraphExposition ); + + + + function LGraphToneMapping() + { + this.addInput("in","Texture"); + this.addOutput("out","Texture"); + this.properties = { precision: LGraphTexture.LOW }; + } + + LGraphToneMapping.title = "Tone Mapping"; + LGraphToneMapping.desc = "Applies Tone Mapping algorithm"; + + LGraphToneMapping.prototype.onExecute = function() + { + var tex = this.getInputData(0); + if(!tex) + return; + + if(!this.isOutputConnected(0)) + return; //saves work + + var temp = this._temp_texture; + + if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) + temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR }); + + + //apply shader + + + + this.setOutputData(0,this._temp_texture); + } + + LGraphToneMapping.pixel_shader = "precision highp float;\n\ + varying vec2 v_coord;\n\ + uniform sampler2D u_texture;\n\ + uniform float scale;\n\ + uniform float averageLum;\n\ + uniform vec3 lumwhite2;\n\ + vec3 RGB2xyY (vec3 rgb)\n\ + {\n\ + const mat3 RGB2XYZ = mat3(0.4124, 0.3576, 0.1805,\n\ + 0.2126, 0.7152, 0.0722,\n\ + 0.0193, 0.1192, 0.9505);\n\ + vec3 XYZ = RGB2XYZ * rgb;\n\ + \n\ + float f = (XYZ.x + XYZ.y + XYZ.z);\n\ + return vec3(XYZ.x / f,\n\ + XYZ.y / f,\n\ + XYZ.y);\n\ + }\n\ + \n\ + void main() {\n\ + vec4 color = texture2D( u_texture, v_coord ).xyz;\n\ + vec3 rgb = color.xyz;\n\ + //Ld - this part of the code is the same for both versions\n\ + float lum = dot(rgb, vec3(0.2126f, 0.7152f, 0.0722f));\n\ + float L = (scale / averageLum) * lum;\n\ + float Ld = (L * (1.0 + L / lumwhite2)) / (1.0 + L);\n\ + //first\n\ + //vec3 xyY = RGB2xyY(rgb);\n\ + //xyY.z *= Ld;\n\ + //rgb = xyYtoRGB(xyY);\n\ + //second\n\ + rgb = (rgb / lum) * Ld;\n\ + gl_FragColor = vec4( rgb, color.a );\n\ + }"; + + + //LiteGraph.registerNodeType("texture/tonemapping", LGraphToneMapping ); + + function LGraphTextureMatte() { this.addInput("in","Texture"); @@ -2405,6 +2541,7 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\ LiteGraph.registerNodeType("texture/matte", LGraphTextureMatte ); + //*********************************** //Cubemap reader (to pass a cubemap to a node that requires cubemaps and no images) function LGraphCubemap()