first commit

This commit is contained in:
tamat
2013-09-26 19:40:42 +02:00
commit a0b689da2b
46 changed files with 13015 additions and 0 deletions

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (C) 2013 by Javi Agenjo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

17
README.md Normal file
View File

@@ -0,0 +1,17 @@
# litegraph.js
A library to create graphs similar to PD. Nodes can be programmed easily and it includes an editor to construct the graphs.
More info comming soon
Utils
-----
It includes several commands in the utils folder to generate doc, check errors and build minifyed version.
Feedback
--------
You can write any feedback to javi.agenjo@gmail.com

5711
build/litegraph.js Normal file

File diff suppressed because it is too large Load Diff

191
build/litegraph.min.js vendored Normal file
View File

@@ -0,0 +1,191 @@
var LiteGraph={NODE_TITLE_HEIGHT:16,NODE_SLOT_HEIGHT:15,NODE_WIDTH:140,NODE_MIN_WIDTH:50,NODE_COLLAPSED_RADIUS:10,CANVAS_GRID_SIZE:10,NODE_DEFAULT_COLOR:"#888",NODE_DEFAULT_BGCOLOR:"#333",NODE_DEFAULT_BOXCOLOR:"#AEF",NODE_DEFAULT_SHAPE:"box",MAX_NUMBER_OF_NODES:1E3,DEFAULT_POSITION:[100,100],node_images_path:"",debug:!1,registered_node_types:{},graphs:[],registerNodeType:function(a,b){b.type=a;LiteGraph.debug&&console.log("Node registered: "+a);a.split("/");var c=a.lastIndexOf("/");b.category=a.substr(0,
c);if(b.prototype)for(var d in LGraphNode.prototype)b.prototype[d]||(b.prototype[d]=LGraphNode.prototype[d]);this.registered_node_types[a]=b},createNode:function(a,b,c){var d=this.registered_node_types[a];if(!d)return LiteGraph.debug&&console.log('GraphNode type "'+a+'" not registered.'),null;var e=d.prototype||d;b=b||e.title||d.title||a;var f=null;if(d.prototype)f=new d(b);else{f=new LGraphNode(b);f.inputs=[];f.outputs=[];for(var g in e)if("inputs"==g)for(var h in e[g])f.addInput(e[g][h][0],e[g][h][1],
e[g][h][2]);else if("outputs"==g)for(h in e[g])f.addOutput(e[g][h][0],e[g][h][1],e[g][h][2]);else f[g]=e[g].concat?e[g].concat():"object"==typeof e[g]?jQuery.extend({},e[g]):e[g];d.size&&(f.size=d.size.concat())}f.type=a;f.name||(f.name=b);f.flags||(f.flags={});f.size||(f.size=f.computeSize());f.pos||(f.pos=LiteGraph.DEFAULT_POSITION.concat());if(c)for(g in c)f[g]=c[g];return f},getNodeType:function(a){return this.registered_node_types[a]},getNodeTypesInCategory:function(a){var b=[],c;for(c in this.registered_node_types)""==
a?null==this.registered_node_types[c].category&&b.push(this.registered_node_types[c]):this.registered_node_types[c].category==a&&b.push(this.registered_node_types[c]);return b},getNodeTypesCategories:function(){var a={"":1},b;for(b in this.registered_node_types)this.registered_node_types[b].category&&!this.registered_node_types[b].skip_list&&(a[this.registered_node_types[b].category]=1);var c=[];for(b in a)c.push(b);return c},reloadNodes:function(a){var b=document.getElementsByTagName("script"),c=
[],d;for(d in b)c.push(b[d]);b=document.getElementsByTagName("head")[0];a=document.location.href+a;for(d in c){var e=c[d].src;if(e&&e.substr(0,a.length)==a)try{LiteGraph.debug&&console.log("Reloading: "+e);var f=document.createElement("script");f.type="text/javascript";f.src=e;b.appendChild(f);b.removeChild(c[d])}catch(g){if(LiteGraph.throw_errors)throw g;LiteGraph.debug&&console.log("Error while reloading "+e)}}for(d in LiteGraph.graphs)for(var h in LiteGraph.graphs[d].nodes)if(a=LiteGraph.graphs[d].nodes[h],
c=LiteGraph.getNodeType(n.type))for(var k in c)"function"==typeof c[k]&&(a[k]=c[k]);LiteGraph.debug&&console.log("Nodes reloaded")}};function LGraph(){LiteGraph.debug&&console.log("Graph created");this.canvas=null;LiteGraph.graphs.push(this);this.clear()}LGraph.STATUS_STOPPED=1;LGraph.STATUS_RUNNING=2;
LGraph.prototype.clear=function(){this.stop();this.status=LGraph.STATUS_STOPPED;this.last_node_id=0;this.nodes=[];this.nodes_by_id={};this.last_link_id=0;this.links={};this.iteration=0;this.config={canvas_offset:[0,0],canvas_scale:1};this.fixedtime=this.runningtime=this.globaltime=0;this.elapsed_time=this.fixedtime_lapse=0.01;this.starttime=0;this.graph={};this.debug=!0;this.change();this.canvas&&this.canvas.clear()};
LGraph.prototype.run=function(a){if(this.status!=LGraph.STATUS_RUNNING){this.status=LGraph.STATUS_RUNNING;if(this.onPlayEvent)this.onPlayEvent();this.sendEventToAllNodes("onStart");this.starttime=(new Date).getTime();var b=this;this.execution_timer_id=setInterval(function(){b.runStep(1)},a||1E3)}};
LGraph.prototype.stop=function(){if(this.status!=LGraph.STATUS_STOPPED){this.status=LGraph.STATUS_STOPPED;if(this.onStopEvent)this.onStopEvent();null!=this.execution_timer_id&&clearInterval(this.execution_timer_id);this.execution_timer_id=null;this.sendEventToAllNodes("onStop")}};
LGraph.prototype.runStep=function(a){a=a||1;var b=(new Date).getTime();this.globaltime=0.001*(b-this.starttime);try{for(var c=0;c<a;c++)if(this.sendEventToAllNodes("onExecute"),this.fixedtime+=this.fixedtime_lapse,this.onExecuteStep)this.onExecuteStep();if(this.onAfterExecute)this.onAfterExecute();this.errors_in_execution=!1}catch(d){this.errors_in_execution=!0;if(LiteGraph.throw_errors)throw d;LiteGraph.debug&&console.log("Error during execution: "+d);this.stop()}a=(new Date).getTime()-b;0==a&&(a=
1);this.elapsed_time=0.001*a;this.globaltime+=0.001*a;this.iteration+=1};
LGraph.prototype.computeExecutionOrder=function(){var a=[],b=[],c={},d={},e={},f;for(f in this.nodes){var g=this.nodes[f];c[g.id]=g;var h=0;if(g.inputs)for(var k=0,l=g.inputs.length;k<l;k++)g.inputs[k]&&null!=g.inputs[k].link&&(h+=1);0==h?b.push(g):e[g.id]=h}for(;0!=b.length;)if(g=b.shift(),a.push(g),delete c[g.id],g.outputs)for(f=0;f<g.outputs.length;f++)if(h=g.outputs[f],null!=h&&null!=h.links&&0!=h.links.length)for(k=0;k<h.links.length;k++)if(l=h.links[k],!d[l[0]]){var p=this.getNodeById(l[3]);
null==p?d[l[0]]=!0:(d[l[0]]=!0,e[p.id]-=1,0==e[p.id]&&b.push(p))}for(f in c)a.push(c[f]);a.length!=this.nodes.length&&LiteGraph.debug&&console.log("something went wrong, nodes missing");for(f in a)a[f].order=f;return a};LGraph.prototype.getTime=function(){return this.globaltime};LGraph.prototype.getFixedTime=function(){return this.fixedtime};LGraph.prototype.getElapsedTime=function(){return this.elapsed_time};
LGraph.prototype.sendEventToAllNodes=function(a,b){var c=this.nodes_in_order?this.nodes_in_order:this.nodes,d;for(d in c)if(c[d][a])c[d][a](b)};
LGraph.prototype.add=function(a){if(a&&(-1==a.id||null==this.nodes_by_id[a.id])){if(this.nodes.length>=LiteGraph.MAX_NUMBER_OF_NODES)throw"LiteGraph: max number of nodes attached";if(null==a.id||-1==a.id)a.id=this.last_node_id++;a.graph=this;this.nodes.push(a);this.nodes_by_id[a.id]=a;if(a.onInit)a.onInit();this.config.align_to_grid&&a.alignToGrid();this.updateExecutionOrder();this.canvas&&(this.canvas.dirty_canvas=!0);this.change();return a}};
LGraph.prototype.remove=function(a){if(null!=this.nodes_by_id[a.id]){if(a.inputs)for(var b=0;b<a.inputs.length;b++){var c=a.inputs[b];null!=c.link&&a.disconnectInput(b)}if(a.outputs)for(b=0;b<a.outputs.length;b++)c=a.outputs[b],null!=c.links&&c.links.length&&a.disconnectOutput(b);a.id=-1;if(a.onDelete)a.onDelete();this.canvas&&(this.canvas.selected_nodes[a.id]&&delete this.canvas.selected_nodes[a.id],this.canvas.node_dragged==a&&(this.canvas.node_dragged=null));b=this.nodes.indexOf(a);-1!=b&&this.nodes.splice(b,
1);delete this.nodes_by_id[a.id];this.canvas&&this.canvas.setDirty(!0,!0);this.change();this.updateExecutionOrder()}};LGraph.prototype.getNodeById=function(a){return null==a?null:this.nodes_by_id[a]};LGraph.prototype.findNodesByType=function(a){var b=[],c;for(c in this.nodes)this.nodes[c].type==a&&b.push(this.nodes[c]);return b};LGraph.prototype.findNodesByName=function(a){var b=[],c;for(c in this.nodes)this.nodes[c].name==a&&b.push(a);return b};
LGraph.prototype.getNodeOnPos=function(a,b,c){c=c||this.nodes;for(var d=c.length-1;0<=d;d--){var e=c[d];if(e.isPointInsideNode(a,b))return e}return null};LGraph.prototype.setInputData=function(a,b){var c=this.findNodesByName(a),d;for(d in c)c[d].setValue(b)};LGraph.prototype.getOutputData=function(a){return this.findNodesByName(a).length?m[0].getValue():null};LGraph.prototype.triggerInput=function(a,b){var c=this.findNodesByName(a),d;for(d in c)c[d].onTrigger(b)};
LGraph.prototype.setCallback=function(a,b){var c=this.findNodesByName(a),d;for(d in c)c[d].setTrigger(b)};LGraph.prototype.onConnectionChange=function(){this.updateExecutionOrder()};LGraph.prototype.updateExecutionOrder=function(){this.nodes_in_order=this.computeExecutionOrder()};LGraph.prototype.isLive=function(){return this.canvas?this.canvas.live_mode:!1};LGraph.prototype.change=function(){LiteGraph.debug&&console.log("Graph changed");if(this.on_change)this.on_change(this)};
LGraph.prototype.serialize=function(){var a=[],b;for(b in this.nodes)a.push(this.nodes[b].objectivize());return JSON.stringify({graph:this.graph,iteration:this.iteration,frame:this.frame,last_node_id:this.last_node_id,last_link_id:this.last_link_id,config:this.config,nodes:a})};
LGraph.prototype.unserialize=function(a,b){b||this.clear();var c=JSON.parse(a),d=c.nodes,e;for(e in c)this[e]=c[e];c=!1;this.nodes=[];for(e in d){var f=d[e],g=LiteGraph.createNode(f.type,f.name);g?(g.copyFromObject(f),this.add(g)):(LiteGraph.debug&&console.log("Node not found: "+f.type),c=!0)}this.canvas&&this.canvas.draw(!0,!0);return c};LGraph.prototype.onNodeTrace=function(a,b,c){if(this.canvas)this.canvas.onNodeTrace(a,b,c)};
function LGraphNode(a){this.name=a||"Unnamed";this.size=[LiteGraph.NODE_WIDTH,60];this.graph=null;this.pos=[10,10];this.id=-1;this.type=null;this.inputs=[];this.outputs=[];this.connections=[];this.data=null;this.flags={}}
LGraphNode.prototype.objectivize=function(){var a={id:this.id,name:this.name,type:this.type,pos:this.pos,size:this.size,data:this.data,properties:jQuery.extend({},this.properties),flags:jQuery.extend({},this.flags),inputs:this.inputs,outputs:this.outputs};a.type||(a.type=this.constructor.type);this.color&&(a.color=this.color);this.bgcolor&&(a.bgcolor=this.bgcolor);this.boxcolor&&(a.boxcolor=this.boxcolor);this.shape&&(a.shape=this.shape);return a};
LGraphNode.prototype.reducedObjectivize=function(){var a=this.objectivize(),b=LiteGraph.getNodeType(a.type);b.name==a.name&&delete a.name;b.size&&compareObjects(a.size,b.size)&&delete a.size;b.properties&&compareObjects(a.properties,b.properties)&&delete a.properties;return a};LGraphNode.prototype.serialize=function(){if(this.onSerialize)this.onSerialize();return JSON.stringify(this.reducedObjectivize())};
LGraphNode.prototype.setOutputData=function(a,b){if(this.outputs&&-1<a&&a<this.outputs.length&&this.outputs[a]&&null!=this.outputs[a].links)for(var c=0;c<this.outputs[a].links.length;c++)this.graph.links[this.outputs[a].links[c][0]]=b};LGraphNode.prototype.getInputData=function(a){return this.inputs?a<this.inputs.length&&null!=this.inputs[a].link?this.graph.links[this.inputs[a].link[0]]:null:null};
LGraphNode.prototype.getInputInfo=function(a){return this.inputs?a<this.inputs.length?this.inputs[a]:null:null};LGraphNode.prototype.getOutputInfo=function(a){return this.outputs?a<this.outputs.length?this.outputs[a]:null:null};LGraphNode.prototype.getOutputNodes=function(a){if(!this.outputs||0==this.outputs.length)return null;if(a<this.outputs.length){a=this.outputs[a];for(var b=[],c=0;c<a.length;c++)b.push(this.graph.getNodeById(a.links[c][3]));return b}return null};
LGraphNode.prototype.triggerOutput=function(a,b){var c=this.getOutputNode(a);if(c&&c.onTrigger)c.onTrigger(b)};LGraphNode.prototype.addOutput=function(a,b,c){a={name:a,type:b,links:null};if(c)for(var d in c)a[d]=c[d];this.outputs||(this.outputs=[]);this.outputs.push(a);this.size=this.computeSize()};LGraphNode.prototype.removeOutput=function(a){this.disconnectOutput(a);this.outputs.splice(a,1);this.size=this.computeSize()};
LGraphNode.prototype.addInput=function(a,b,c){a={name:a,type:b,link:null};if(c)for(var d in c)a[d]=c[d];this.inputs||(this.inputs=[]);this.inputs.push(a);this.size=this.computeSize()};LGraphNode.prototype.removeInput=function(a){this.disconnectInput(a);this.inputs.splice(a,1);this.size=this.computeSize()};LGraphNode.prototype.addConnection=function(a,b,c,d){this.connections.push({name:a,type:b,pos:c,direction:d,links:null})};
LGraphNode.prototype.computeSize=function(a){a=Math.max(this.inputs?this.inputs.length:1,this.outputs?this.outputs.length:1);var b=[0,0];b[1]=14*a+6;b[0]=this.inputs&&0!=this.inputs.length&&this.outputs&&0!=this.outputs.length?LiteGraph.NODE_WIDTH:0.5*LiteGraph.NODE_WIDTH;return b};LGraphNode.prototype.getBounding=function(){return new Float32Array([this.pos[0]-4,this.pos[1]-LGraph.NODE_TITLE_HEIGHT,this.pos[0]+this.size[0]+4,this.pos[1]+this.size[1]+LGraph.NODE_TITLE_HEIGHT])};
LGraphNode.prototype.isPointInsideNode=function(a,b){var c=this.graph.isLive()?0:20;if(this.flags.collapsed){if(distance([a,b],[this.pos[0]+0.5*this.size[0],this.pos[1]+0.5*this.size[1]])<LiteGraph.NODE_COLLAPSED_RADIUS)return!0}else if(this.pos[0]-4<a&&this.pos[0]+this.size[0]+4>a&&this.pos[1]-c<b&&this.pos[1]+this.size[1]>b)return!0;return!1};LGraphNode.prototype.findInputSlot=function(a){if(!this.inputs)return-1;for(var b=0,c=this.inputs.length;b<c;++b)if(a==this.inputs[b].name)return b;return-1};
LGraphNode.prototype.findOutputSlot=function(a){if(!this.outputs)return-1;for(var b=0,c=this.outputs.length;b<c;++b)if(a==this.outputs[b].name)return b;return-1};
LGraphNode.prototype.connect=function(a,b,c){if(a.constructor===String){if(a=this.findOutputSlot(a),-1==a)return LiteGraph.debug&&console.log("Connect: Error, no slot of name "+a),!1}else if(!this.outputs||a>=this.outputs.length)return LiteGraph.debug&&console.log("Connect: Error, slot number not found"),!1;if(b==this)return!1;if(c.constructor===String){if(c=b.findInputSlot(c),-1==c)return LiteGraph.debug&&console.log("Connect: Error, no slot of name "+c),!1}else if(!b.inputs||c>=b.inputs.length)return LiteGraph.debug&&
console.log("Connect: Error, slot number not found"),!1;-1!=c&&null!=b.inputs[c].link&&b.disconnectInput(c);var d=this.outputs[a];if(-1==c)null==d.links&&(d.links=[]),d.links.push({id:b.id,slot:-1});else if(0==d.type||0==b.inputs[c].type||d.type==b.inputs[c].type)a=[this.graph.last_link_id++,this.id,a,b.id,c],null==d.links&&(d.links=[]),d.links.push(a),b.inputs[c].link=a,this.setDirtyCanvas(!1,!0),this.graph.onConnectionChange();return!0};
LGraphNode.prototype.disconnectOutput=function(a,b){if(a.constructor===String){if(a=this.findOutputSlot(a),-1==a)return LiteGraph.debug&&console.log("Connect: Error, no slot of name "+a),!1}else if(!this.outputs||a>=this.outputs.length)return LiteGraph.debug&&console.log("Connect: Error, slot number not found"),!1;var c=this.outputs[a];if(!c.links||0==c.links.length)return!1;if(b)for(var d=0,e=c.links.length;d<e;d++){var f=c.links[d];if(f[3]==b.id){c.links.splice(d,1);b.inputs[f[4]].link=null;delete this.graph.links[f[0]];
break}}else{d=0;for(e=c.links.length;d<e;d++)if(f=c.links[d],b=this.graph.getNodeById(f[3]))b.inputs[f[4]].link=null;c.links=null}this.setDirtyCanvas(!1,!0);this.graph.onConnectionChange();return!0};
LGraphNode.prototype.disconnectInput=function(a){if(a.constructor===String){if(a=this.findInputSlot(a),-1==a)return LiteGraph.debug&&console.log("Connect: Error, no slot of name "+a),!1}else if(!this.inputs||a>=this.inputs.length)return LiteGraph.debug&&console.log("Connect: Error, slot number not found"),!1;if(!this.inputs[a])return!1;var b=this.inputs[a].link;this.inputs[a].link=null;a=this.graph.getNodeById(b[1]);if(!a)return!1;a=a.outputs[b[2]];if(!a||!a.links||0==a.links.length)return!1;for(var c=
0,d=a.links.length;c<d;c++)if(b=a.links[c],b[3]==this.id){a.links.splice(c,1);break}this.setDirtyCanvas(!1,!0);this.graph.onConnectionChange();return!0};
LGraphNode.prototype.getConnectionPos=function(a,b){return this.flags.collapsed?[this.pos[0]+0.5*this.size[0],this.pos[1]+0.5*this.size[1]]:a&&-1==b?[this.pos[0]+10,this.pos[1]+10]:a&&this.inputs.length>b&&this.inputs[b].pos?[this.pos[0]+this.inputs[b].pos[0],this.pos[1]+this.inputs[b].pos[1]]:!a&&this.outputs.length>b&&this.outputs[b].pos?[this.pos[0]+this.outputs[b].pos[0],this.pos[1]+this.outputs[b].pos[1]]:a?[this.pos[0],this.pos[1]+10+b*LiteGraph.NODE_SLOT_HEIGHT]:[this.pos[0]+this.size[0]+1,
this.pos[1]+10+b*LiteGraph.NODE_SLOT_HEIGHT]};
LGraphNode.prototype.draw=function(a,b){var c=this.color||LiteGraph.NODE_DEFAULT_COLOR,d=!0;if(this.flags.skip_title_render||this.graph.isLive())d=!1;this.mouseOver&&(d=!0);this.selected||(b.render_shadows?(a.shadowColor="#111",a.shadowOffsetX=2,a.shadowOffsetY=2,a.shadowBlur=4):a.shadowColor="transparent");if(b.live_mode){if(!this.flags.collapsed){a.shadowColor="transparent";if(this.onDrawBackground)this.onDrawBackground(a);if(this.onDrawForeground)this.onDrawForeground(a)}}else if(this.flags.collapsed)this.onDrawCollapsed&&!1!=
this.onDrawCollapsed(a)||this.drawNodeCollapsed(a,c,this.bgcolor);else{this.flags.clip_area&&(a.save(),null==this.shape||"box"==this.shape?(a.beginPath(),a.rect(0,0,this.size[0],this.size[1])):"round"==this.shape?a.roundRect(0,0,this.size[0],this.size[1],10):"circle"==this.shape&&(a.beginPath(),a.arc(0.5*this.size[0],0.5*this.size[1],0.5*this.size[0],0,2*Math.PI)),a.clip());this.drawNodeShape(a,c,this.bgcolor,!d,this.selected);a.shadowColor="transparent";a.textAlign="left";a.font="12px Arial";d=0.6<
this.graph.config.canvas_scale;if(this.inputs)for(var e=0;e<this.inputs.length;e++){var f=this.inputs[e];a.globalAlpha=1;null!=b.connecting_node&&0!=b.connecting_output.type&&0!=this.inputs[e].type&&b.connecting_output.type!=this.inputs[e].type&&(a.globalAlpha=0.4);a.fillStyle=null!=f.link?"#7F7":"#AAA";var g=this.getConnectionPos(!0,e);g[0]-=this.pos[0];g[1]-=this.pos[1];a.beginPath();a.arc(g[0],g[1],4,0,2*Math.PI);a.fill();d&&(f=null!=f.label?f.label:f.name)&&(a.fillStyle=c,a.fillText(f,g[0]+10,
g[1]+5))}b.connecting_node&&(a.globalAlpha=0.4);a.lineWidth=1;a.textAlign="right";a.strokeStyle="black";if(this.outputs)for(e=0;e<this.outputs.length;e++)if(f=this.outputs[e],g=this.getConnectionPos(!1,e),g[0]-=this.pos[0],g[1]-=this.pos[1],a.fillStyle=f.links&&f.links.length?"#7F7":"#AAA",a.beginPath(),a.arc(g[0],g[1],4,0,2*Math.PI),a.fill(),a.stroke(),d&&(f=null!=f.label?f.label:f.name))a.fillStyle=c,a.fillText(f,g[0]-10,g[1]+5);a.textAlign="left";a.globalAlpha=1;if(this.onDrawForeground)this.onDrawForeground(a);
this.flags.clip_area&&a.restore()}};
LGraphNode.prototype.drawNodeShape=function(a,b,c,d,e){a.strokeStyle=b||LiteGraph.NODE_DEFAULT_COLOR;a.fillStyle=c||LiteGraph.NODE_DEFAULT_BGCOLOR;c=LiteGraph.NODE_TITLE_HEIGHT;null==this.shape||"box"==this.shape?(e&&(a.strokeStyle="#CCC",a.strokeRect(-0.5,d?-0.5:-c+-0.5,this.size[0]+2,d?this.size[1]+2:this.size[1]+c+2),a.strokeStyle=b),a.beginPath(),a.rect(0.5,d?0.5:-c+0.5,this.size[0],d?this.size[1]:this.size[1]+c)):"round"==this.shape?a.roundRect(0,d?0:-c,this.size[0],d?this.size[1]:this.size[1]+
c,10):"circle"==this.shape&&(a.beginPath(),a.arc(0.5*this.size[0],0.5*this.size[1],0.5*this.size[0],0,2*Math.PI));a.fill();a.shadowColor="transparent";a.stroke();this.bgImage&&this.bgImage.width&&a.drawImage(this.bgImage,0.5*(this.size[0]-this.bgImage.width),0.5*(this.size[1]-this.bgImage.height));this.bgImageUrl&&!this.bgImage&&(this.bgImage=this.loadImage(this.bgImageUrl));if(this.onDrawBackground)this.onDrawBackground(a);d||(a.fillStyle=b||LiteGraph.NODE_DEFAULT_COLOR,null==this.shape||"box"==
this.shape?(a.fillRect(0,-c,this.size[0],c),a.stroke()):"round"==this.shape&&(a.roundRect(0,-c,this.size[0],c,10,0),a.fill(),a.stroke()),a.fillStyle=this.boxcolor||LiteGraph.NODE_DEFAULT_BOXCOLOR,a.beginPath(),"round"==this.shape?a.arc(0.5*c,-0.5*c,0.5*(c-6),0,2*Math.PI):a.rect(3,-c+3,c-6,c-6),a.fill(),a.font="bold 12px Arial",""!=this.name&&0.8<this.graph.config.canvas_scale&&(a.fillStyle="#222",a.fillText(this.name,16,13-c)))};
LGraphNode.prototype.drawNodeCollapsed=function(a,b,c){a.strokeStyle=b||LiteGraph.NODE_DEFAULT_COLOR;a.fillStyle=c||LiteGraph.NODE_DEFAULT_BGCOLOR;b=LiteGraph.NODE_COLLAPSED_RADIUS;"circle"==this.shape?(a.beginPath(),a.arc(0.5*this.size[0],0.5*this.size[1],b,0,2*Math.PI),a.fill(),a.shadowColor="rgba(0,0,0,0)",a.stroke(),a.fillStyle=this.boxcolor||LiteGraph.NODE_DEFAULT_BOXCOLOR,a.beginPath(),a.arc(0.5*this.size[0],0.5*this.size[1],0.5*b,0,2*Math.PI)):"round"==this.shape?(a.beginPath(),a.roundRect(0.5*
this.size[0]-b,0.5*this.size[1]-b,2*b,2*b,5),a.fill(),a.shadowColor="rgba(0,0,0,0)",a.stroke(),a.fillStyle=this.boxcolor||LiteGraph.NODE_DEFAULT_BOXCOLOR,a.beginPath(),a.roundRect(0.5*this.size[0]-0.5*b,0.5*this.size[1]-0.5*b,b,b,2)):(a.beginPath(),a.rect(0.5*this.size[0]-b,0.5*this.size[1]-b,2*b,2*b),a.fill(),a.shadowColor="rgba(0,0,0,0)",a.stroke(),a.fillStyle=this.boxcolor||LiteGraph.NODE_DEFAULT_BOXCOLOR,a.beginPath(),a.rect(0.5*this.size[0]-0.5*b,0.5*this.size[1]-0.5*b,b,b));a.fill()};
LGraphNode.prototype.alignToGrid=function(){this.pos[0]=LiteGraph.CANVAS_GRID_SIZE*Math.round(this.pos[0]/LiteGraph.CANVAS_GRID_SIZE);this.pos[1]=LiteGraph.CANVAS_GRID_SIZE*Math.round(this.pos[1]/LiteGraph.CANVAS_GRID_SIZE)};LGraphNode.prototype.copyFromObject=function(a,b){for(var c in a)(!b||"outputs"!=c&&"inputs"!=c)&&"console"!=c&&null!=a[c]&&(this[c]=a[c].concat?a[c].concat():"object"==typeof a[c]?jQuery.extend({},a[c]):a[c])};
LGraphNode.prototype.clone=function(){var a=LiteGraph.createNode(this.type);a.size=this.size.concat();if(this.inputs)for(var b=0,c=this.inputs.length;b<c;++b)-1==a.findInputSlot(this.inputs[b].name)&&a.addInput(this.inputs[b].name,this.inputs[b].type);if(this.outputs)for(b=0,c=this.outputs.length;b<c;++b)-1==a.findOutputSlot(this.outputs[b].name)&&a.addOutput(this.outputs[b].name,this.outputs[b].type);return a};
LGraphNode.prototype.trace=function(a){this.console||(this.console=[]);this.console.push(a);this.graph.onNodeTrace(this,a)};LGraphNode.prototype.setDirtyCanvas=function(a,b){this.graph&&this.graph.canvas&&(a&&(this.graph.canvas.dirty_canvas=!0),b&&(this.graph.canvas.dirty_bgcanvas=!0))};LGraphNode.prototype.loadImage=function(a){var b=new Image;b.src=LiteGraph.node_images_path+a;b.ready=!1;var c=this;b.onload=function(){this.ready=!0;c.setDirtyCanvas(!0)};return b};
LGraphNode.prototype.executeAction=function(a){if(""==a)return!1;if(-1!=a.indexOf(";")||-1!=a.indexOf("}"))return this.trace("Error: Action contains unsafe characters"),!1;var b=a.split("(")[0];if("function"!=typeof this[b])return this.trace("Error: Action not found on node: "+b),!1;try{b=eval,eval=null,(new Function("with(this) { "+a+"}")).call(this),eval=b}catch(c){return this.trace("Error executing action {"+a+"} :"+c),!1}return!0};
LGraphNode.prototype.captureInput=function(a){this.graph&&this.graph.canvas&&(a||this.graph.canvas.node_capturing_input==this)&&(this.graph.canvas.node_capturing_input=a?this:null,this.graph.debug&&console.log(this.name+": Capturing input "+(a?"ON":"OFF")))};LGraphNode.prototype.collapse=function(){this.flags.collapsed=this.flags.collapsed?!1:!0;this.setDirtyCanvas(!0,!0)};LGraphNode.prototype.pin=function(){this.flags.pinned=this.flags.pinned?!1:!0};
LGraphNode.prototype.localToScreen=function(a,b){return[(a+this.pos[0])*this.graph.config.canvas_scale+this.graph.config.canvas_offset[0],(b+this.pos[1])*this.graph.config.canvas_scale+this.graph.config.canvas_offset[1]]};
function LGraphCanvas(a,b){if(void 0===b)throw"No graph assigned";"undefined"!=typeof window&&(window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}());if(this.graph=b)b.canvas=this;this.setCanvas(a);this.clear();this.startRendering()}LGraphCanvas.link_type_colors={number:"#AAC",node:"#DCA"};LGraphCanvas.link_width=2;
LGraphCanvas.prototype.clear=function(){this.fps=this.render_time=this.last_draw_time=this.frame=0;this.selected_nodes={};this.connecting_node=this.node_capturing_input=this.node_over=this.node_dragged=null;this.highquality_render=!0;this.pause_rendering=!1;this.dirty_bgcanvas=this.dirty_canvas=this.render_shadows=!0;this.dirty_area=null;this.render_only_selected=!0;this.live_mode=!1;this.allow_dragnodes=this.allow_dragcanvas=this.show_info=!0;this.node_in_panel=null;this.last_mouse=[0,0];this.last_mouseclick=
0;if(this.onClear)this.onClear()};LGraphCanvas.prototype.setGraph=function(a){if(this.graph!=a){this.clear();this.graph&&(this.graph.canvas=null);if(this.graph=a)this.graph.canvas=this;this.setDirty(!0,!0)}};LGraphCanvas.prototype.resize=function(a,b){if(this.canvas.width!=a||this.canvas.height!=b)this.canvas.width=a,this.canvas.height=b,this.bgcanvas.width=this.canvas.width,this.bgcanvas.height=this.canvas.height,this.setDirty(!0,!0)};
LGraphCanvas.prototype.setCanvas=function(a){var b=this;"string"==typeof a&&(a=document.getElementById(a));if(null==a)throw"Error creating LiteGraph canvas: Canvas not found";if(a!=this.canvas){this.canvas=a;this.canvas.className+=" lgraphcanvas";this.canvas.data=this;this.bgcanvas=null;this.bgcanvas||(this.bgcanvas=document.createElement("canvas"),this.bgcanvas.width=this.canvas.width,this.bgcanvas.height=this.canvas.height);if(null==this.canvas.getContext)throw"This browser doesnt support Canvas";
this.ctx=this.canvas.getContext("2d");this.bgctx=this.bgcanvas.getContext("2d");this._mousemove_callback=this.processMouseMove.bind(this);this._mouseup_callback=this.processMouseUp.bind(this);this.canvas.addEventListener("mousedown",this.processMouseDown.bind(this));this.canvas.addEventListener("mousemove",this._mousemove_callback);this.canvas.addEventListener("contextmenu",function(a){a.preventDefault();return!1});this.canvas.addEventListener("mousewheel",this.processMouseWheel.bind(this),!1);this.canvas.addEventListener("DOMMouseScroll",
this.processMouseWheel.bind(this),!1);this.canvas.addEventListener("touchstart",this.touchHandler,!0);this.canvas.addEventListener("touchmove",this.touchHandler,!0);this.canvas.addEventListener("touchend",this.touchHandler,!0);this.canvas.addEventListener("touchcancel",this.touchHandler,!0);this.canvas.addEventListener("keydown",function(a){b.processKeyDown(a)});this.canvas.addEventListener("keyup",function(a){b.processKeyUp(a)})}};
LGraphCanvas.prototype.setDirty=function(a,b){a&&(this.dirty_canvas=!0);b&&(this.dirty_bgcanvas=!0)};LGraphCanvas.prototype.startRendering=function(){function a(){this.pause_rendering||this.draw();this.is_rendering&&window.requestAnimFrame(a.bind(this))}this.is_rendering||(this.is_rendering=!0,a.call(this))};LGraphCanvas.prototype.stopRendering=function(){this.is_rendering=!1};
LGraphCanvas.prototype.processMouseDown=function(a){if(this.graph){this.adjustMouseEvent(a);this.canvas.removeEventListener("mousemove",this._mousemove_callback);document.addEventListener("mousemove",this._mousemove_callback);document.addEventListener("mouseup",this._mouseup_callback);var b=this.graph.getNodeOnPos(a.canvasX,a.canvasY,this.visible_nodes);if(1==a.which){if(!a.shiftKey){var c=[],d;for(d in this.selected_nodes)this.selected_nodes[d]!=b&&c.push(this.selected_nodes[d]);for(d in c)this.processNodeDeselected(c[d])}c=
!1;if(b){this.live_mode||b.flags.pinned||this.bringToFront(b);var e=!1;if(!this.connecting_node&&!b.flags.collapsed&&!this.live_mode){if(b.outputs){d=0;for(var f=b.outputs.length;d<f;++d){var g=b.outputs[d],h=b.getConnectionPos(!1,d);if(isInsideRectangle(a.canvasX,a.canvasY,h[0]-10,h[1]-5,20,10)){this.connecting_node=b;this.connecting_output=g;this.connecting_pos=b.getConnectionPos(!1,d);this.connecting_slot=d;e=!0;break}}}if(b.inputs)for(d=0,f=b.inputs.length;d<f;++d)g=b.inputs[d],h=b.getConnectionPos(!0,
d),isInsideRectangle(a.canvasX,a.canvasY,h[0]-10,h[1]-5,20,10)&&g.link&&(b.disconnectInput(d),e=this.dirty_bgcanvas=!0);!e&&isInsideRectangle(a.canvasX,a.canvasY,b.pos[0]+b.size[0]-5,b.pos[1]+b.size[1]-5,5,5)&&(this.resizing_node=b,this.canvas.style.cursor="se-resize",e=!0)}if(!e){d=!1;if(300>(new Date).getTime()-this.last_mouseclick&&this.selected_nodes[b.id]){if(b.onDblClick)b.onDblClick(a);this.processNodeDblClicked(b);d=!0}b.onMouseDown&&b.onMouseDown(a)?d=!0:this.live_mode&&(d=c=!0);d||(this.allow_dragnodes&&
(this.node_dragged=b),this.selected_nodes[b.id]||this.processNodeSelected(b,a));this.dirty_canvas=!0}}else c=!0;c&&this.allow_dragcanvas&&(this.dragging_canvas=!0)}else 2!=a.which&&3==a.which&&this.processContextualMenu(b,a);this.last_mouse[0]=a.localX;this.last_mouse[1]=a.localY;this.last_mouseclick=(new Date).getTime();this.canvas_mouse=[a.canvasX,a.canvasY];this.graph.change();(!document.activeElement||"input"!=document.activeElement.nodeName.toLowerCase()&&"textarea"!=document.activeElement.nodeName.toLowerCase())&&
a.preventDefault();a.stopPropagation();return!1}};
LGraphCanvas.prototype.processMouseMove=function(a){if(this.graph){this.adjustMouseEvent(a);var b=[a.localX,a.localY],c=[b[0]-this.last_mouse[0],b[1]-this.last_mouse[1]];this.last_mouse=b;this.canvas_mouse=[a.canvasX,a.canvasY];if(this.dragging_canvas)this.graph.config.canvas_offset[0]+=c[0]/this.graph.config.canvas_scale,this.graph.config.canvas_offset[1]+=c[1]/this.graph.config.canvas_scale,this.dirty_bgcanvas=this.dirty_canvas=!0;else{this.connecting_node&&(this.dirty_canvas=!0);var b=this.graph.getNodeOnPos(a.canvasX,
a.canvasY,this.visible_nodes),d;for(d in this.graph.nodes)if(this.graph.nodes[d].mouseOver&&b!=this.graph.nodes[d]){this.graph.nodes[d].mouseOver=!1;if(this.node_over&&this.node_over.onMouseLeave)this.node_over.onMouseLeave(a);this.node_over=null;this.dirty_canvas=!0}if(b){if(!b.mouseOver&&(b.mouseOver=!0,this.node_over=b,this.dirty_canvas=!0,b.onMouseEnter))b.onMouseEnter(a);if(b.onMouseMove)b.onMouseMove(a);if(this.connecting_node){var e=this._highlight_input||[0,0],f=this.isOverNodeInput(b,a.canvasX,
a.canvasY,e);if(-1!=f&&b.inputs[f]){if(f=b.inputs[f].type,f==this.connecting_output.type||"*"==f||"*"==this.connecting_output.type)this._highlight_input=e}else this._highlight_input=null}isInsideRectangle(a.canvasX,a.canvasY,b.pos[0]+b.size[0]-5,b.pos[1]+b.size[1]-5,5,5)?this.canvas.style.cursor="se-resize":this.canvas.style.cursor=null}else this.canvas.style.cursor=null;if(this.node_capturing_input&&this.node_capturing_input!=b&&this.node_capturing_input.onMouseMove)this.node_capturing_input.onMouseMove(a);
if(this.node_dragged&&!this.live_mode){for(d in this.selected_nodes)b=this.selected_nodes[d],b.pos[0]+=c[0]/this.graph.config.canvas_scale,b.pos[1]+=c[1]/this.graph.config.canvas_scale,b.pos[0]=Math.round(b.pos[0]),b.pos[1]=Math.round(b.pos[1]);this.dirty_bgcanvas=this.dirty_canvas=!0}this.resizing_node&&!this.live_mode&&(this.resizing_node.size[0]+=c[0]/this.graph.config.canvas_scale,this.resizing_node.size[1]+=c[1]/this.graph.config.canvas_scale,c=Math.max(this.resizing_node.inputs?this.resizing_node.inputs.length:
0,this.resizing_node.outputs?this.resizing_node.outputs.length:0),this.resizing_node.size[1]<c*LiteGraph.NODE_SLOT_HEIGHT+4&&(this.resizing_node.size[1]=c*LiteGraph.NODE_SLOT_HEIGHT+4),this.resizing_node.size[0]<LiteGraph.NODE_MIN_WIDTH&&(this.resizing_node.size[0]=LiteGraph.NODE_MIN_WIDTH),this.canvas.style.cursor="se-resize",this.dirty_bgcanvas=this.dirty_canvas=!0)}a.preventDefault();a.stopPropagation();return!1}};
LGraphCanvas.prototype.processMouseUp=function(a){if(this.graph){document.removeEventListener("mousemove",this._mousemove_callback,!0);this.canvas.addEventListener("mousemove",this._mousemove_callback,!0);document.removeEventListener("mouseup",this._mouseup_callback,!0);this.adjustMouseEvent(a);if(1==a.which)if(this.connecting_node){this.dirty_bgcanvas=this.dirty_canvas=!0;var b=this.graph.getNodeOnPos(a.canvasX,a.canvasY,this.visible_nodes);if(b)if("node"==this.connecting_output.type)this.connecting_node.connect(this.connecting_slot,
b,-1);else{var c=this.isOverNodeInput(b,a.canvasX,a.canvasY);-1!=c&&this.connecting_node.connect(this.connecting_slot,b,c)}this.connecting_node=this.connecting_pos=this.connecting_output=null;this.connecting_slot=-1}else if(this.resizing_node)this.dirty_bgcanvas=this.dirty_canvas=!0,this.resizing_node=null;else if(this.node_dragged)this.dirty_bgcanvas=this.dirty_canvas=!0,this.graph.config.align_to_grid&&this.node_dragged.alignToGrid(),this.node_dragged=null;else{this.dirty_canvas=!0;this.dragging_canvas=
!1;if(this.node_over&&this.node_over.onMouseUp)this.node_over.onMouseUp(a);if(this.node_capturing_input&&this.node_capturing_input.onMouseUp)this.node_capturing_input.onMouseUp(a)}else 2==a.which?(this.dirty_canvas=!0,this.dragging_canvas=!1):3==a.which&&(this.dirty_canvas=!0,this.dragging_canvas=!1);this.graph.change();a.stopPropagation();a.preventDefault();return!1}};
LGraphCanvas.prototype.isOverNodeInput=function(a,b,c,d){if(a.inputs)for(var e=0,f=a.inputs.length;e<f;++e){var g=a.getConnectionPos(!0,e);if(isInsideRectangle(b,c,g[0]-10,g[1]-5,20,10))return d&&(d[0]=g[0],d[1]=g[1]),e}return-1};
LGraphCanvas.prototype.processKeyDown=function(a){if(this.graph){var b=!1;65==a.keyCode&&a.ctrlKey&&(this.selectAllNodes(),b=!0);46!=a.keyCode&&8!=a.keyCode||this.deleteSelectedNodes();if(this.selected_nodes)for(var c in this.selected_nodes)if(this.selected_nodes[c].onKeyDown)this.selected_nodes[c].onKeyDown(a);this.graph.change();if(b)return a.preventDefault(),!1}};
LGraphCanvas.prototype.processKeyUp=function(a){if(this.graph){if(this.selected_nodes)for(var b in this.selected_nodes)if(this.selected_nodes[b].onKeyUp)this.selected_nodes[b].onKeyUp(a);this.graph.change()}};
LGraphCanvas.prototype.processMouseWheel=function(a){if(this.graph&&this.allow_dragcanvas){var b=null!=a.wheelDeltaY?a.wheelDeltaY:-60*a.detail;this.adjustMouseEvent(a);var c=this.graph.config.canvas_scale;0<b?c*=1.1:0>b&&(c*=1/1.1);this.setZoom(c,[a.localX,a.localY]);this.graph.change();a.preventDefault();return!1}};
LGraphCanvas.prototype.processNodeSelected=function(a,b){a.selected=!0;if(a.onSelected)a.onSelected();b&&b.shiftKey||(this.selected_nodes={});this.selected_nodes[a.id]=a;this.dirty_canvas=!0;if(this.onNodeSelected)this.onNodeSelected(a)};LGraphCanvas.prototype.processNodeDeselected=function(a){a.selected=!1;if(a.onDeselected)a.onDeselected();delete this.selected_nodes[a.id];if(this.onNodeDeselected)this.onNodeDeselected();this.dirty_canvas=!0};
LGraphCanvas.prototype.processNodeDblClicked=function(a){if(this.onShowNodePanel)this.onShowNodePanel(a);if(this.onNodeDblClicked)this.onNodeDblClicked(a);this.setDirty(!0)};LGraphCanvas.prototype.selectNode=function(a){this.deselectAllNodes();if(a){if(!a.selected&&a.onSelected)a.onSelected();a.selected=!0;this.selected_nodes[a.id]=a;this.setDirty(!0)}};
LGraphCanvas.prototype.selectAllNodes=function(){for(var a in this.graph.nodes){var b=this.graph.nodes[a];if(!b.selected&&b.onSelected)b.onSelected();b.selected=!0;this.selected_nodes[this.graph.nodes[a].id]=b}this.setDirty(!0)};LGraphCanvas.prototype.deselectAllNodes=function(){for(var a in this.selected_nodes){var b=this.selected_nodes;if(b.onDeselected)b.onDeselected();b.selected=!1}this.selected_nodes={};this.setDirty(!0)};
LGraphCanvas.prototype.deleteSelectedNodes=function(){for(var a in this.selected_nodes)this.graph.remove(this.selected_nodes[a]);this.selected_nodes={};this.setDirty(!0)};LGraphCanvas.prototype.centerOnNode=function(a){this.graph.config.canvas_offset[0]=-a.pos[0]-0.5*a.size[0]+0.5*this.canvas.width/this.graph.config.canvas_scale;this.graph.config.canvas_offset[1]=-a.pos[1]-0.5*a.size[1]+0.5*this.canvas.height/this.graph.config.canvas_scale;this.setDirty(!0,!0)};
LGraphCanvas.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.graph.config.canvas_scale-this.graph.config.canvas_offset[0];a.canvasY=a.localY/this.graph.config.canvas_scale-this.graph.config.canvas_offset[1]};
LGraphCanvas.prototype.setZoom=function(a,b){b||(b=[0.5*this.canvas.width,0.5*this.canvas.height]);var c=this.convertOffsetToCanvas(b);this.graph.config.canvas_scale=a;4<this.graph.config.canvas_scale?this.graph.config.canvas_scale=4:0.1>this.graph.config.canvas_scale&&(this.graph.config.canvas_scale=0.1);var d=this.convertOffsetToCanvas(b),c=[d[0]-c[0],d[1]-c[1]];this.graph.config.canvas_offset[0]+=c[0];this.graph.config.canvas_offset[1]+=c[1];this.dirty_bgcanvas=this.dirty_canvas=!0};
LGraphCanvas.prototype.convertOffsetToCanvas=function(a){return[a[0]/this.graph.config.canvas_scale-this.graph.config.canvas_offset[0],a[1]/this.graph.config.canvas_scale-this.graph.config.canvas_offset[1]]};LGraphCanvas.prototype.convertCanvasToOffset=function(a){return[(a[0]+this.graph.config.canvas_offset[0])*this.graph.config.canvas_scale,(a[1]+this.graph.config.canvas_offset[1])*this.graph.config.canvas_scale]};
LGraphCanvas.prototype.convertEventToCanvas=function(a){var b=this.canvas.getClientRects()[0];return this.convertOffsetToCanvas([a.pageX-b.left,a.pageY-b.top])};LGraphCanvas.prototype.bringToFront=function(a){var b=this.graph.nodes.indexOf(a);-1!=b&&(this.graph.nodes.splice(b,1),this.graph.nodes.push(a))};LGraphCanvas.prototype.sendToBack=function(a){var b=this.graph.nodes.indexOf(a);-1!=b&&(this.graph.nodes.splice(b,1),this.graph.nodes.unshift(a))};
LGraphCanvas.prototype.computeVisibleNodes=function(){var a=[],b;for(b in this.graph.nodes){var c=this.graph.nodes[b];(!this.live_mode||c.onDrawBackground||c.onDrawForeground)&&overlapBounding(this.visible_area,c.getBounding())&&a.push(c)}return a};
LGraphCanvas.prototype.draw=function(a,b){var c=(new Date).getTime();this.render_time=0.001*(c-this.last_draw_time);this.last_draw_time=c;if(this.graph){var c=[-this.graph.config.canvas_offset[0],-this.graph.config.canvas_offset[1]],d=[c[0]+this.canvas.width/this.graph.config.canvas_scale,c[1]+this.canvas.height/this.graph.config.canvas_scale];this.visible_area=new Float32Array([c[0],c[1],d[0],d[1]])}(this.dirty_bgcanvas||b)&&this.drawBgcanvas();(this.dirty_canvas||a)&&this.drawFrontCanvas();this.fps=
this.render_time?1/this.render_time:0;this.frame+=1};
LGraphCanvas.prototype.drawFrontCanvas=function(){var a=this.ctx,b=this.canvas;a.restore();a.setTransform(1,0,0,1,0,0);this.dirty_area&&(a.save(),a.beginPath(),a.rect(this.dirty_area[0],this.dirty_area[1],this.dirty_area[2],this.dirty_area[3]),a.clip());a.clearRect(0,0,b.width,b.height);a.drawImage(this.bgcanvas,0,0);this.show_info&&(a.font="10px Arial",a.fillStyle="#888",this.graph?(a.fillText("T: "+this.graph.globaltime.toFixed(2)+"s",5,13),a.fillText("I: "+this.graph.iteration,5,26),a.fillText("F: "+
this.frame,5,39),a.fillText("FPS:"+this.fps.toFixed(2),5,52)):a.fillText("No graph selected",5,13));if(this.graph){a.save();a.scale(this.graph.config.canvas_scale,this.graph.config.canvas_scale);a.translate(this.graph.config.canvas_offset[0],this.graph.config.canvas_offset[1]);this.visible_nodes=b=this.computeVisibleNodes();for(var c in b){var d=b[c];a.save();a.translate(d.pos[0],d.pos[1]);d.draw(a,this);a.restore()}this.graph.config.links_ontop&&(this.live_mode||this.drawConnections(a));null!=this.connecting_pos&&
(a.lineWidth=LGraphCanvas.link_width,a.fillStyle="node"==this.connecting_output.type?"#F85":"#AFA",a.strokeStyle=a.fillStyle,this.renderLink(a,this.connecting_pos,[this.canvas_mouse[0],this.canvas_mouse[1]]),a.beginPath(),a.arc(this.connecting_pos[0],this.connecting_pos[1],4,0,2*Math.PI),a.fill(),a.fillStyle="#ffcc00",this._highlight_input&&(a.beginPath(),a.arc(this._highlight_input[0],this._highlight_input[1],6,0,2*Math.PI),a.fill()));a.restore()}this.dirty_area&&a.restore();this.dirty_canvas=!1};
LGraphCanvas.prototype.drawBgcanvas=function(){var a=this.bgcanvas,b=this.bgctx;a.width=a.width;b.restore();b.setTransform(1,0,0,1,0,0);if(this.graph){b.save();b.scale(this.graph.config.canvas_scale,this.graph.config.canvas_scale);b.translate(this.graph.config.canvas_offset[0],this.graph.config.canvas_offset[1]);if(this.background_image&&0.5<this.graph.config.canvas_scale){b.globalAlpha=1-0.5/this.graph.config.canvas_scale;b.webkitImageSmoothingEnabled=b.mozImageSmoothingEnabled=b.imageSmoothingEnabled=
!1;if(!this._bg_img||this._bg_img.name!=this.background_image){this._bg_img=new Image;this._bg_img.name=this.background_image;this._bg_img.src=this.background_image;var c=this;this._bg_img.onload=function(){c.draw(!0,!0)}}var d=null;this._bg_img!=this._pattern_img&&0<this._bg_img.width?(d=b.createPattern(this._bg_img,"repeat"),this._pattern_img=this._bg_img,this._pattern=d):d=this._pattern;d&&(b.fillStyle=d,b.fillRect(this.visible_area[0],this.visible_area[1],this.visible_area[2]-this.visible_area[0],
this.visible_area[3]-this.visible_area[1]),b.fillStyle="transparent");b.globalAlpha=1}b.strokeStyle="#235";b.strokeRect(0,0,a.width,a.height);this.live_mode||this.drawConnections(b);b.restore()}this.dirty_bgcanvas=!1;this.dirty_canvas=!0};LGraphCanvas.link_colors=["#AAC","#ACA","#CAA"];
LGraphCanvas.prototype.drawConnections=function(a){a.lineWidth=LGraphCanvas.link_width;a.fillStyle="#AAA";a.strokeStyle="#AAA";for(var b in this.graph.nodes){var c=this.graph.nodes[b];if(c.inputs&&c.inputs.length)for(var d in c.inputs){var e=c.inputs[d];if(e&&e.link){var f=e.link,e=this.graph.getNodeById(f[1]);if(null!=e){var g=f[2],f=null,f=-1==g?[e.pos[0]+10,e.pos[1]+10]:e.getConnectionPos(!1,g),e=LGraphCanvas.link_type_colors[c.inputs[d].type];null==e&&(e=LGraphCanvas.link_colors[c.id%LGraphCanvas.link_colors.length]);
a.fillStyle=a.strokeStyle=e;this.renderLink(a,f,c.getConnectionPos(!0,d))}}}}};
LGraphCanvas.prototype.renderLink=function(a,b,c){if(this.highquality_render){var d=distance(b,c);a.beginPath();a.moveTo(b[0],b[1]);a.bezierCurveTo(b[0]+0.25*d,b[1],c[0]-0.25*d,c[1],c[0],c[1]);a.stroke();0.6<this.graph.config.canvas_scale&&(d=this.computeConnectionPoint(b,c,0.5),b=this.computeConnectionPoint(b,c,0.51),c=0,c=-Math.atan2(b[0]-d[0],b[1]-d[1]),a.save(),a.translate(d[0],d[1]),a.rotate(c),a.beginPath(),a.moveTo(-5,-5),a.lineTo(0,5),a.lineTo(5,-5),a.fill(),a.restore())}else a.beginPath(),
a.moveTo(b[0],b[1]),a.lineTo(c[0],c[1]),a.stroke()};LGraphCanvas.prototype.computeConnectionPoint=function(a,b,c){var d=distance(a,b),e=[a[0]+0.25*d,a[1]],d=[b[0]-0.25*d,b[1]],f=(1-c)*(1-c)*(1-c),g=3*(1-c)*(1-c)*c,h=3*(1-c)*c*c;c*=c*c;return[f*a[0]+g*e[0]+h*d[0]+c*b[0],f*a[1]+g*e[1]+h*d[1]+c*b[1]]};LGraphCanvas.prototype.resizeCanvas=function(a,b){this.canvas.width=a;b&&(this.canvas.height=b);this.bgcanvas.width=this.canvas.width;this.bgcanvas.height=this.canvas.height;this.draw(!0,!0)};
LGraphCanvas.prototype.switchLiveMode=function(){this.live_mode=!this.live_mode;this.dirty_bgcanvas=this.dirty_canvas=!0};LGraphCanvas.prototype.onNodeSelectionChange=function(a){};
LGraphCanvas.prototype.touchHandler=function(a){var b=a.changedTouches[0],c="";switch(a.type){case "touchstart":c="mousedown";break;case "touchmove":c="mousemove";break;case "touchend":c="mouseup";break;default:return}var d=document.createEvent("MouseEvent");d.initMouseEvent(c,!0,!0,window,1,b.screenX,b.screenY,b.clientX,b.clientY,!1,!1,!1,!1,0,null);b.target.dispatchEvent(d);a.preventDefault()};
LGraphCanvas.onMenuAdd=function(a,b,c,d,e){function f(a,b){var c=LiteGraph.createNode(a.value);c&&(c.pos=d.convertEventToCanvas(e),d.graph.add(c))}a=LiteGraph.getNodeTypesCategories();var g={},h;for(h in a)a[h]&&(g[h]={value:a[h],content:a[h],is_menu:!0});var k=LiteGraph.createContextualMenu(g,{event:b,callback:function(a,b){var c=LiteGraph.getNodeTypesInCategory(a.value),d=[],e;for(e in c)d.push({content:c[e].title,value:c[e].type});LiteGraph.createContextualMenu(d,{event:b,callback:f,from:k});return!1},
from:c});return!1};LGraphCanvas.onMenuCollapseAll=function(){};LGraphCanvas.onMenuNodeEdit=function(){};LGraphCanvas.onMenuNodeInputs=function(a,b,c){function d(b){a&&a.addInput(b.value[0],b.value[1],b.value[2])}if(a){var e=a.optional_inputs;a.onGetInputs&&(e=a.onGetInputs());if(e){var f=[],g;for(g in e){var h=e[g],k=h[0];h[2]&&h[2].label&&(k=h[2].label);f.push({content:k,value:h})}LiteGraph.createContextualMenu(f,{event:b,callback:d,from:c})}return!1}};
LGraphCanvas.onMenuNodeOutputs=function(a,b,c){function d(b){a&&a.addOutput(b.value[0],b.value[1])}if(a){var e=a.optional_outputs;a.onGetOutputs&&(e=a.onGetOutputs());if(e){var f=[],g;for(g in e)-1==a.findOutputSlot(e[g][0])&&f.push({content:e[g][0],value:e[g]});f.length&&LiteGraph.createContextualMenu(f,{event:b,callback:d,from:c})}return!1}};LGraphCanvas.onMenuNodeCollapse=function(a){a.flags.collapsed=!a.flags.collapsed;a.graph.canvas.setDirty(!0,!0)};
LGraphCanvas.onMenuNodeColors=function(a,b,c){var d=[],e;for(e in LGraphCanvas.node_colors){var f=LGraphCanvas.node_colors[e];d.push({value:e,content:"<span style='display: block; color:"+f.color+"; background-color:"+f.bgcolor+"'>"+e+"</span>"})}LiteGraph.createContextualMenu(d,{event:b,callback:function(b){a&&(b=LGraphCanvas.node_colors[b.value])&&(a.color=b.color,a.bgcolor=b.bgcolor,a.graph.canvas.setDirty(!0))},from:c});return!1};
LGraphCanvas.onMenuNodeShapes=function(a,b){LiteGraph.createContextualMenu(["box","round","circle"],{event:b,callback:function(b){a&&(a.shape=b,a.graph.canvas.setDirty(!0))}});return!1};LGraphCanvas.onMenuNodeRemove=function(a){!1!=a.removable&&(a.graph.remove(a),a.graph.canvas.setDirty(!0,!0))};LGraphCanvas.onMenuNodeClone=function(a){if(!1!=a.clonable){var b=a.clone();b&&(b.pos=[a.pos[0]+5,a.pos[1]+5],a.graph.add(b),a.graph.canvas.setDirty(!0,!0))}};
LGraphCanvas.node_colors={red:{color:"#FAA",bgcolor:"#A44"},green:{color:"#AFA",bgcolor:"#4A4"},blue:{color:"#AAF",bgcolor:"#44A"},white:{color:"#FFF",bgcolor:"#AAA"}};LGraphCanvas.prototype.getCanvasMenuOptions=function(){return[{content:"Add Node",is_menu:!0,callback:LGraphCanvas.onMenuAdd}]};
LGraphCanvas.prototype.getNodeMenuOptions=function(a){var b=[{content:"Inputs",is_menu:!0,disabled:!0,callback:LGraphCanvas.onMenuNodeInputs},{content:"Outputs",is_menu:!0,disabled:!0,callback:LGraphCanvas.onMenuNodeOutputs},null,{content:"Collapse",callback:LGraphCanvas.onMenuNodeCollapse},{content:"Colors",is_menu:!0,callback:LGraphCanvas.onMenuNodeColors},{content:"Shapes",is_menu:!0,callback:LGraphCanvas.onMenuNodeShapes},null,{content:"Clone",callback:LGraphCanvas.onMenuNodeClone},null,{content:"Remove",
callback:LGraphCanvas.onMenuNodeRemove}];!1==a.clonable&&(b[7].disabled=!0);!1==a.removable&&(b[9].disabled=!0);a.onGetInputs&&a.onGetInputs().length&&(b[0].disabled=!1);a.onGetOutputs&&a.onGetOutputs().length&&(b[1].disabled=!1);return b};LGraphCanvas.prototype.processContextualMenu=function(a,b){var c=this,d=LiteGraph.createContextualMenu(a?this.getNodeMenuOptions(a):this.getCanvasMenuOptions(),{event:b,callback:function(e,f){if(e&&e.callback)return e.callback(a,f,d,c,b)}})};
CanvasRenderingContext2D.prototype.roundRect=function(a,b,c,d,e,f){void 0===e&&(e=5);void 0===f&&(f=e);this.beginPath();this.moveTo(a+e,b);this.lineTo(a+c-e,b);this.quadraticCurveTo(a+c,b,a+c,b+e);this.lineTo(a+c,b+d-f);this.quadraticCurveTo(a+c,b+d,a+c-f,b+d);this.lineTo(a+f,b+d);this.quadraticCurveTo(a,b+d,a,b+d-f);this.lineTo(a,b+e);this.quadraticCurveTo(a,b,a+e,b)};function compareObjects(a,b){for(var c in a)if(a[c]!=b[c])return!1;return!0}
function distance(a,b){return Math.sqrt((b[0]-a[0])*(b[0]-a[0])+(b[1]-a[1])*(b[1]-a[1]))}function colorToString(a){return"rgba("+Math.round(255*a[0]).toFixed()+","+Math.round(255*a[1]).toFixed()+","+Math.round(255*a[2]).toFixed()+","+(4==a.length?a[3].toFixed(2):"1.0")+")"}function isInsideRectangle(a,b,c,d,e,f){return c<a&&c+e>a&&d<b&&d+f>b?!0:!1}function growBounding(a,b,c){b<a[0]?a[0]=b:b>a[2]&&(a[2]=b);c<a[1]?a[1]=c:c>a[3]&&(a[3]=c)}
function isInsideBounding(a,b){return a[0]<b[0][0]||a[1]<b[0][1]||a[0]>b[1][0]||a[1]>b[1][1]?!1:!0}function overlapBounding(a,b){return a[0]>b[2]||a[1]>b[3]||a[2]<b[0]||a[3]<b[1]?!1:!0}function hex2num(a){"#"==a.charAt(0)&&(a=a.slice(1));a=a.toUpperCase();for(var b=Array(3),c=0,d,e,f=0;6>f;f+=2)d="0123456789ABCDEF".indexOf(a.charAt(f)),e="0123456789ABCDEF".indexOf(a.charAt(f+1)),b[c]=16*d+e,c++;return b}
function num2hex(a){for(var b="#",c,d,e=0;3>e;e++)c=a[e]/16,d=a[e]%16,b+="0123456789ABCDEF".charAt(c)+"0123456789ABCDEF".charAt(d);return b}
LiteGraph.createContextualMenu=function(a,b){function c(a){var c=!0;b.callback&&(a=b.callback.call(d,this.data,a),void 0!=a&&(c=a));c&&LiteGraph.closeAllContextualMenus()}this.options=b=b||{};b.from||LiteGraph.closeAllContextualMenus();var d=document.createElement("div");d.className="litecontextualmenu litemenubar-panel";this.root=d;var e=d.style;e.minWidth="100px";e.minHeight="20px";e.position="fixed";e.top="100px";e.left="100px";e.color="#AAF";e.padding="2px";e.borderBottom="2px solid #AAF";e.backgroundColor=
"#444";d.addEventListener("contextmenu",function(a){a.preventDefault();return!1});for(var f in a){var e=a[f],g=document.createElement("div");g.className="litemenu-entry";null==e?g.className="litemenu-entry separator":(e.is_menu&&(g.className+=" submenu"),e.disabled&&(g.className+=" disabled"),g.style.cursor="pointer",g.dataset.value="string"==typeof e?e:e.value,g.data=e,g.innerHTML="string"==typeof e?a.constructor==Array?a[f]:f:e.content?e.content:f,g.addEventListener("click",c));d.appendChild(g)}d.addEventListener("mouseover",
function(a){this.mouse_inside=!0});d.addEventListener("mouseout",function(a){for(a=a.toElement;a!=this&&a!=document;)a=a.parentNode;a!=this&&(this.mouse_inside=!1,this.block_close||this.closeMenu())});document.body.appendChild(d);f=d.getClientRects()[0];b.from&&(b.from.block_close=!0);var h=b.left||0,e=b.top||0;b.event&&(h=b.event.pageX-10,e=b.event.pageY-10,b.left&&(h=b.left),g=document.body.getClientRects()[0],b.from&&(h=b.from.getClientRects()[0],h=h.left+h.width),h>g.width-f.width-10&&(h=g.width-
f.width-10),e>g.height-f.height-10&&(e=g.height-f.height-10));d.style.left=h+"px";d.style.top=e+"px";d.closeMenu=function(){b.from&&(b.from.block_close=!1,b.from.mouse_inside||b.from.closeMenu());this.parentNode&&document.body.removeChild(this)};return d};LiteGraph.closeAllContextualMenus=function(){var a=document.querySelectorAll(".litecontextualmenu");if(a.length){for(var b=[],c=0;c<a.length;c++)b.push(a[c]);for(c in b)b[c].parentNode&&b[c].parentNode.removeChild(b[c])}};
LiteGraph.extendClass=function(a,b){for(var c in a)b[c]=a[c];if(a.prototype)for(c in a.prototype)b.prototype[c]=a.prototype[c]};
LiteGraph.registerNodeType("basic/const",{title:"Const",desc:"Constant",outputs:[["value","number"]],properties:{value:1},editable:{property:"value",type:"number"},setValue:function(a){"string"==typeof a&&(a=parseFloat(a));this.properties.value=a;this.setDirtyCanvas(!0)},onExecute:function(){this.setOutputData(0,parseFloat(this.properties.value))},onDrawBackground:function(a){this.outputs[0].label=this.properties.value.toFixed(3)},onWidget:function(a,b){"value"==b.name&&this.setValue(b.value)}});
LiteGraph.registerNodeType("math/rand",{title:"Rand",desc:"Random number",outputs:[["value","number"]],properties:{min:0,max:1},size:[60,20],onExecute:function(){var a=this.properties.min,b=this.properties.max;this._last_v=Math.random()*(b-a)+a;this.setOutputData(0,this._last_v)},onDrawBackground:function(a){this.outputs[0].label=this._last_v?this._last_v.toFixed(3):"?"}});
LiteGraph.registerNodeType("math/clamp",{title:"Clamp",desc:"Clamp number between min and max",inputs:[["in","number"]],outputs:[["out","number"]],size:[60,20],properties:{min:0,max:1},onExecute:function(){var a=this.getInputData(0);null!=a&&(a=Math.max(this.properties.min,a),a=Math.min(this.properties.max,a),this.setOutputData(0,a))}});
LiteGraph.registerNodeType("math/abs",{title:"Abs",desc:"Absolute",inputs:[["in","number"]],outputs:[["out","number"]],size:[60,20],onExecute:function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,Math.abs(a))}});LiteGraph.registerNodeType("math/floor",{title:"Floor",desc:"Floor number to remove fractional part",inputs:[["in","number"]],outputs:[["out","number"]],size:[60,20],onExecute:function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a|1)}});
LiteGraph.registerNodeType("math/frac",{title:"Frac",desc:"Returns fractional part",inputs:[["in","number"]],outputs:[["out","number"]],size:[60,20],onExecute:function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a%1)}});
LiteGraph.registerNodeType("basic/watch",{title:"Watch",desc:"Show value",size:[60,20],inputs:[["value",0,{label:""}]],outputs:[["value",0,{label:""}]],properties:{value:""},onExecute:function(){this.properties.value=this.getInputData(0);this.setOutputData(0,this.properties.value)},onDrawBackground:function(a){this.inputs[0]&&null!=this.properties.value&&(this.inputs[0].label=this.properties.value.constructor===Number?this.properties.value.toFixed(3):this.properties.value)}});
LiteGraph.registerNodeType("math/scale",{title:"Scale",desc:"1 - value",inputs:[["value","number",{label:""}]],outputs:[["value","number",{label:""}]],size:[70,20],properties:{factor:1},onExecute:function(){var a=this.getInputData(0);null!=a&&this.setOutputData(0,a*this.properties.factor)}});
LiteGraph.registerNodeType("math/operation",{title:"Operation",desc:"Easy math operators",inputs:[["A","number"],["B","number"]],outputs:[["A+B","number"]],size:[80,20],properties:{A:1,B:1},setValue:function(a){"string"==typeof a&&(a=parseFloat(a));this.properties.value=a;this.setDirtyCanvas(!0)},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;for(var c=0,d=this.outputs.length;c<
d;++c){var e=this.outputs[c];if(e.links&&e.links.length){switch(e.name){case "A+B":value=a+b;break;case "A-B":value=a-b;break;case "A*B":value=a*b;break;case "A/B":value=a/b}this.setOutputData(c,value)}}},onGetOutputs:function(){return[["A-B","number"],["A*B","number"],["A/B","number"]]}});
LiteGraph.registerNodeType("math/compare",{title:"Compare",desc:"compares between two values",inputs:[["A","number"],["B","number"]],outputs:[["A==B","number"],["A!=B","number"]],properties:{A:0,B:0},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;for(var c=0,d=this.outputs.length;c<d;++c){var e=this.outputs[c];if(e.links&&e.links.length){switch(e.name){case "A==B":value=a==b;break;
case "A!=B":value=a!=b;break;case "A>B":value=a>b;break;case "A<B":value=a<b;break;case "A<=B":value=a<=b;break;case "A>=B":value=a>=b}this.setOutputData(c,value)}}},onGetOutputs:function(){return[["A==B","number"],["A!=B","number"],["A>B","number"],["A<B","number"],["A>=B","number"],["A<=B","number"]]}});
window.math&&LiteGraph.registerNodeType("math/formula",{title:"Formula",desc:"Compute safe formula",inputs:[["x","number"],["y","number"]],outputs:[["","number"]],properties:{x:1,y:1,formula:"x+y"},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)},onDrawBackground:function(){this.outputs[0].label=
this.properties.formula},onGetOutputs:function(){return[["A-B","number"],["A*B","number"],["A/B","number"]]}});
LiteGraph.registerNodeType("math/trigonometry",{title:"Trigonometry",desc:"Sin Cos Tan",bgImageUrl:"nodes/imgs/icon-sin.png",inputs:[["v","number"]],outputs:[["sin","number"]],properties:{amplitude:1},size:[100,20],onExecute:function(){for(var a=this.getInputData(0),b=this.properties.amplitude,c=0,d=this.outputs.length;c<d;++c){switch(this.outputs[c].name){case "sin":value=Math.sin(a);break;case "cos":value=Math.cos(a);break;case "tan":value=Math.tan(a);break;case "asin":value=Math.asin(a);break;
case "acos":value=Math.acos(a);break;case "atan":value=Math.atan(a)}this.setOutputData(c,b*value)}},onGetOutputs:function(){return[["sin","number"],["cos","number"],["tan","number"],["asin","number"],["acos","number"],["atan","number"]]}});
window.glMatrix&&(LiteGraph.registerNodeType("math3d/vec3-to-xyz",{title:"Vec3->XYZ",desc:"vector 3 to components",inputs:[["vec3","vec3"]],outputs:[["x","number"],["y","number"],["z","number"]],onExecute:function(){var a=this.getInputData(0);null!=a&&(this.setOutputData(0,a[0]),this.setOutputData(1,a[1]),this.setOutputData(2,a[2]))}}),LiteGraph.registerNodeType("math3d/xyz-to-vec3",{title:"XYZ->Vec3",desc:"components to vector3",inputs:[["x","number"],["y","number"],["z","number"]],outputs:[["vec3",
"vec3"]],onExecute:function(){var a=this.getInputData(0);null==a&&(a=0);var b=this.getInputData(1);null==b&&(b=0);var c=this.getInputData(2);null==c&&(c=0);this.setOutputData(0,vec3.fromValues(a,b,c))}}),LiteGraph.registerNodeType("math3d/rotation",{title:"Rotation",desc:"rotation quaternion",inputs:[["degrees","number"],["axis","vec3"]],outputs:[["quat","quat"]],properties:{angle:90,axis:[0,1,0]},onExecute:function(){var a=this.getInputData(0);null==a&&(a=this.properties.angle);var b=this.getInputData(1);
null==b&&(b=this.properties.axis);a=quat.setAxisAngle(quat.create(),b,0.0174532925*a);this.setOutputData(0,a)}}),LiteGraph.registerNodeType("math3d/rotate_vec3",{title:"Rot. Vec3",desc:"rotate a point",inputs:[["vec3","vec3"],["quat","quat"]],outputs:[["result","vec3"]],properties:{vec:[0,0,1]},onExecute:function(){var a=this.getInputData(0);null==a&&(a=this.properties.vec);var b=this.getInputData(1);null==b?this.setOutputData(a):this.setOutputData(0,vec3.transformQuat(vec3.create(),a,b))}}),LiteGraph.registerNodeType("math3d/mult-quat",
{title:"Mult. Quat",desc:"rotate quaternion",inputs:[["A","quat"],["B","quat"]],outputs:[["A*B","quat"]],onExecute:function(){var a=this.getInputData(0);if(null!=a){var b=this.getInputData(1);null!=b&&(a=quat.multiply(quat.create(),a,b),this.setOutputData(0,a))}}}));
LiteGraph.registerNodeType("widget/knob",{title:"Knob",desc:"Circular controller",size:[64,84],outputs:[["","number"]],properties:{min:0,max:1,value:0.5,wcolor:"#7AF",size:50},widgets:[{name:"increase",text:"+",type:"minibutton"},{name:"decrease",text:"-",type:"minibutton"}],onInit:function(){this.value=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min);this.imgbg=this.loadImage("imgs/knob_bg.png");this.imgfg=this.loadImage("imgs/knob_fg.png")},onDrawImageKnob:function(a){if(this.imgfg&&
this.imgfg.width){var b=0.5*this.imgbg.width,c=this.size[0]/this.imgfg.width;a.save();a.translate(0,20);a.scale(c,c);a.drawImage(this.imgbg,0,0);a.translate(b,b);a.rotate(12*this.value*Math.PI/8+10*Math.PI/8);a.translate(-b,-b);a.drawImage(this.imgfg,0,0);a.restore();a.font="bold 16px Criticized,Tahoma";a.fillStyle="rgba(100,100,100,0.8)";a.textAlign="center";a.fillText(this.name.toUpperCase(),0.5*this.size[0],18);a.textAlign="left"}},onDrawVectorKnob:function(a){if(this.imgfg&&this.imgfg.width){a.lineWidth=
1;a.strokeStyle=this.mouseOver?"#FFF":"#AAA";a.fillStyle="#000";a.beginPath();a.arc(0.5*this.size[0],0.5*this.size[1]+10,0.5*this.properties.size,0,2*Math.PI,!0);a.stroke();0<this.value&&(a.strokeStyle=this.properties.wcolor,a.lineWidth=0.2*this.properties.size,a.beginPath(),a.arc(0.5*this.size[0],0.5*this.size[1]+10,0.35*this.properties.size,-0.5*Math.PI+2*Math.PI*this.value,-0.5*Math.PI,!0),a.stroke(),a.lineWidth=1);a.font=0.2*this.properties.size+"px Arial";a.fillStyle="#AAA";a.textAlign="center";
var b=this.properties.value;"number"==typeof b&&(b=b.toFixed(2));a.fillText(b,0.5*this.size[0],0.65*this.size[1]);a.textAlign="left"}},onDrawBackground:function(a){this.onDrawImageKnob(a)},onExecute:function(){this.setOutputData(0,this.properties.value);this.boxcolor=colorToString([this.value,this.value,this.value])},onMouseDown:function(a){if(this.imgfg&&this.imgfg.width){this.center=[0.5*this.size[0],0.5*this.size[1]+20];this.radius=0.5*this.size[0];if(20>a.canvasY-this.pos[1]||distance([a.canvasX,
a.canvasY],[this.pos[0]+this.center[0],this.pos[1]+this.center[1]])>this.radius)return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0);return!0}},onMouseMove:function(a){if(this.oldmouse){a=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];var b=this.value,b=b-0.01*(a[1]-this.oldmouse[1]);1<b?b=1:0>b&&(b=0);this.value=b;this.properties.value=this.properties.min+(this.properties.max-this.properties.min)*this.value;this.oldmouse=a;this.setDirtyCanvas(!0)}},onMouseUp:function(a){this.oldmouse&&
(this.oldmouse=null,this.captureInput(!1))},onMouseLeave:function(a){},onWidget:function(a,b){if("increase"==b.name)this.onPropertyChange("size",this.properties.size+10);else if("decrease"==b.name)this.onPropertyChange("size",this.properties.size-10)},onPropertyChange:function(a,b){if("wcolor"==a)this.properties[a]=b;else if("size"==a)b=parseInt(b),this.properties[a]=b,this.size=[b+4,b+24],this.setDirtyCanvas(!0,!0);else if("min"==a||"max"==a||"value"==a)this.properties[a]=parseFloat(b);else return!1;
return!0}});
LiteGraph.registerNodeType("widget/hslider",{title:"H.Slider",desc:"Linear slider controller",size:[160,26],outputs:[["","number"]],properties:{wcolor:"#7AF",min:0,max:1,value:0.5},onInit:function(){this.value=0.5;this.imgfg=this.loadImage("imgs/slider_fg.png")},onDrawVectorial:function(a){this.imgfg&&this.imgfg.width&&(a.lineWidth=1,a.strokeStyle=this.mouseOver?"#FFF":"#AAA",a.fillStyle="#000",a.beginPath(),a.rect(2,0,this.size[0]-4,20),a.stroke(),a.fillStyle=this.properties.wcolor,a.beginPath(),a.rect(2+
(this.size[0]-4-20)*this.value,0,20,20),a.fill())},onDrawImage:function(a){this.imgfg&&this.imgfg.width&&(a.lineWidth=1,a.fillStyle="#000",a.fillRect(2,9,this.size[0]-4,2),a.strokeStyle="#333",a.beginPath(),a.moveTo(2,9),a.lineTo(this.size[0]-4,9),a.stroke(),a.strokeStyle="#AAA",a.beginPath(),a.moveTo(2,11),a.lineTo(this.size[0]-4,11),a.stroke(),a.drawImage(this.imgfg,2+(this.size[0]-4)*this.value-0.5*this.imgfg.width,0.5*-this.imgfg.height+10))},onDrawBackground:function(a){this.onDrawImage(a)},
onExecute:function(){this.properties.value=this.properties.min+(this.properties.max-this.properties.min)*this.value;this.setOutputData(0,this.properties.value);this.boxcolor=colorToString([this.value,this.value,this.value])},onMouseDown:function(a){if(0>a.canvasY-this.pos[1])return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0);return!0},onMouseMove:function(a){if(this.oldmouse){a=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];var b=this.value,b=b+(a[0]-this.oldmouse[0])/
this.size[0];1<b?b=1:0>b&&(b=0);this.value=b;this.oldmouse=a;this.setDirtyCanvas(!0)}},onMouseUp:function(a){this.oldmouse=null;this.captureInput(!1)},onMouseLeave:function(a){},onPropertyChange:function(a,b){if("wcolor"==a)this.properties[a]=b;else return!1;return!0}});
LiteGraph.registerNodeType("widget/kpad",{title:"KPad",desc:"bidimensional slider",size:[200,200],outputs:[["x","number"],["y","number"]],properties:{x:0,y:0,borderColor:"#333",bgcolorTop:"#444",bgcolorBottom:"#000",shadowSize:1,borderRadius:2},createGradient:function(a){this.lineargradient=a.createLinearGradient(0,0,0,this.size[1]);this.lineargradient.addColorStop(0,this.properties.bgcolorTop);this.lineargradient.addColorStop(1,this.properties.bgcolorBottom)},onDrawBackground:function(a){this.lineargradient||
this.createGradient(a);a.lineWidth=1;a.strokeStyle=this.properties.borderColor;a.fillStyle=this.lineargradient;a.shadowColor="#000";a.shadowOffsetX=0;a.shadowOffsetY=0;a.shadowBlur=this.properties.shadowSize;a.roundRect(0,0,this.size[0],this.size[1],this.properties.shadowSize);a.fill();a.shadowColor="rgba(0,0,0,0)";a.stroke();a.fillStyle="#A00";a.fillRect(this.size[0]*this.properties.x-5,this.size[1]*this.properties.y-5,10,10)},onWidget:function(a,b){"update"==b.name&&(this.lineargradient=null,this.setDirtyCanvas(!0))},
onExecute:function(){this.setOutputData(0,this.properties.x);this.setOutputData(1,this.properties.y)},onMouseDown:function(a){if(0>a.canvasY-this.pos[1])return!1;this.oldmouse=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]];this.captureInput(!0);return!0},onMouseMove:function(a){this.oldmouse&&(a=[a.canvasX-this.pos[0],a.canvasY-this.pos[1]],this.properties.x=a[0]/this.size[0],this.properties.y=a[1]/this.size[1],1<this.properties.x?this.properties.x=1:0>this.properties.x&&(this.properties.x=0),1<this.properties.y?
this.properties.y=1:0>this.properties.y&&(this.properties.y=0),this.oldmouse=a,this.setDirtyCanvas(!0))},onMouseUp:function(a){this.oldmouse&&(this.oldmouse=null,this.captureInput(!1))},onMouseLeave:function(a){}});
LiteGraph.registerNodeType("widget/button",{title:"Button",desc:"A send command button",widgets:[{name:"test",text:"Test Button",type:"button"}],size:[100,40],properties:{text:"clickme",command:"",color:"#7AF",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",fontsize:"16"},outputs:[["M","module"]],createGradient:function(a){this.lineargradient=a.createLinearGradient(0,0,0,this.size[1]);this.lineargradient.addColorStop(0,this.properties.bgcolorTop);this.lineargradient.addColorStop(1,this.properties.bgcolorBottom)},
drawVectorShape:function(a){a.fillStyle=this.mouseOver?this.properties.color:"#AAA";this.clicking&&(a.fillStyle="#FFF");a.strokeStyle="#AAA";a.roundRect(5,5,this.size[0]-10,this.size[1]-10,4);a.stroke();this.mouseOver&&a.fill();a.fillStyle=this.mouseOver?"#000":"#AAA";a.font="bold "+this.properties.fontsize+"px Criticized,Tahoma";a.textAlign="center";a.fillText(this.properties.text,0.5*this.size[0],0.5*this.size[1]+0.5*parseInt(this.properties.fontsize));a.textAlign="left"},drawBevelShape:function(a){a.shadowColor=
"#000";a.shadowOffsetX=0;a.shadowOffsetY=0;a.shadowBlur=this.properties.shadowSize;this.lineargradient||this.createGradient(a);a.fillStyle=this.mouseOver?this.properties.color:this.lineargradient;this.clicking&&(a.fillStyle="#444");a.strokeStyle="#FFF";a.roundRect(5,5,this.size[0]-10,this.size[1]-10,4);a.fill();a.shadowColor="rgba(0,0,0,0)";a.stroke();a.fillStyle=this.mouseOver?"#000":"#444";a.font="bold "+this.properties.fontsize+"px Century Gothic";a.textAlign="center";a.fillText(this.properties.text,
0.5*this.size[0],0.5*this.size[1]+0.4*parseInt(this.properties.fontsize));a.textAlign="left"},onDrawBackground:function(a){this.drawBevelShape(a)},clickButton:function(){var a=this.getOutputModule(0);if(this.properties.command&&""!=this.properties.command)a.executeAction(this.properties.command)||this.trace("Error executing action in other module");else if(a&&a.onTrigger)a.onTrigger()},onMouseDown:function(a){if(2>a.canvasY-this.pos[1])return!1;this.clickButton();return this.clicking=!0},onMouseUp:function(a){this.clicking=
!1},onExecute:function(){},onWidget:function(a,b){"test"==b.name&&this.clickButton()},onPropertyChange:function(a,b){this.properties[a]=b;return!0}});
LiteGraph.registerNodeType("widget/progress",{title:"Progress",desc:"Shows data in linear progress",size:[160,26],inputs:[["","number"]],properties:{min:0,max:1,value:0,wcolor:"#AAF"},onExecute:function(){var a=this.getInputData(0);void 0!=a&&(this.properties.value=a)},onDrawBackground:function(a){a.lineWidth=1;a.fillStyle=this.properties.wcolor;var b=(this.properties.value-this.properties.min)/(this.properties.max-this.properties.min),b=Math.min(1,b),b=Math.max(0,b);a.fillRect(2,2,(this.size[0]-
4)*b,this.size[1]-4)}});
LiteGraph.registerNodeType("widget/text",{title:"Text",desc:"Shows the input value",widgets:[{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}],inputs:[["",0]],properties:{value:"...",font:"Arial",fontsize:18,color:"#AAA",align:"left",glowSize:0,decimals:1},onDrawBackground:function(a){a.fillStyle=this.properties.color;var b=this.properties.value;this.properties.glowSize?(a.shadowColor=this.properties.color,
a.shadowOffsetX=0,a.shadowOffsetY=0,a.shadowBlur=this.properties.glowSize):a.shadowColor="transparent";var c=this.properties.fontsize;a.textAlign=this.properties.align;a.font=c.toString()+"px "+this.properties.font;this.str="number"==typeof b?b.toFixed(this.properties.decimals):b;if("string"==typeof this.str){var b=this.str.split("\\n"),d;for(d in b)a.fillText(b[d],"left"==this.properties.align?15:this.size[0]-15,-0.15*c+c*(parseInt(d)+1))}a.shadowColor="transparent";this.last_ctx=a;a.textAlign="left"},
onExecute:function(){var a=this.getInputData(0);this.properties.value=null!=a?a:"";this.setDirtyCanvas(!0)},resize:function(){if(this.last_ctx){var a=this.str.split("\\n");this.last_ctx.font=this.properties.fontsize+"px "+this.properties.font;var b=0,c;for(c in a){var d=this.last_ctx.measureText(a[c]).width;b<d&&(b=d)}this.size[0]=b+20;this.size[1]=4+a.length*this.properties.fontsize;this.setDirtyCanvas(!0)}},onWidget:function(a,b){"resize"==b.name?this.resize():"led_text"==b.name?(this.properties.font=
"Digital",this.properties.glowSize=4,this.setDirtyCanvas(!0)):"normal_text"==b.name&&(this.properties.font="Arial",this.setDirtyCanvas(!0))},onPropertyChange:function(a,b){this.properties[a]=b;this.str="number"==typeof b?b.toFixed(3):b;return!0}});
LiteGraph.registerNodeType("widget/panel",{title:"Panel",desc:"Non interactive panel",widgets:[{name:"update",text:"Update",type:"button"}],size:[200,100],properties:{borderColor:"#ffffff",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",shadowSize:2,borderRadius:3},createGradient:function(a){""==this.properties.bgcolorTop||""==this.properties.bgcolorBottom?this.lineargradient=0:(this.lineargradient=a.createLinearGradient(0,0,0,this.size[1]),this.lineargradient.addColorStop(0,this.properties.bgcolorTop),
this.lineargradient.addColorStop(1,this.properties.bgcolorBottom))},onDrawBackground:function(a){null==this.lineargradient&&this.createGradient(a);this.lineargradient&&(a.lineWidth=1,a.strokeStyle=this.properties.borderColor,a.fillStyle=this.lineargradient,this.properties.shadowSize?(a.shadowColor="#000",a.shadowOffsetX=0,a.shadowOffsetY=0,a.shadowBlur=this.properties.shadowSize):a.shadowColor="transparent",a.roundRect(0,0,this.size[0]-1,this.size[1]-1,this.properties.shadowSize),a.fill(),a.shadowColor=
"transparent",a.stroke())},onWidget:function(a,b){"update"==b.name&&(this.lineargradient=null,this.setDirtyCanvas(!0))}});
LiteGraph.registerNodeType("color/palette",{title:"Palette",desc:"Generates a color",inputs:[["f","number"]],outputs:[["Color","color"]],properties:{colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"},onExecute:function(){var a=[];null!=this.properties.colorA&&a.push(hex2num(this.properties.colorA));null!=this.properties.colorB&&a.push(hex2num(this.properties.colorB));null!=this.properties.colorC&&a.push(hex2num(this.properties.colorC));null!=this.properties.colorD&&a.push(hex2num(this.properties.colorD));
var b=this.getInputData(0);null==b&&(b=0.5);1<b?b=1:0>b&&(b=0);if(0!=a.length){var c=[0,0,0];if(0==b)c=a[0];else if(1==b)c=a[a.length-1];else{var d=(a.length-1)*b,b=a[Math.floor(d)],a=a[Math.floor(d)+1],d=d-Math.floor(d);c[0]=b[0]*(1-d)+a[0]*d;c[1]=b[1]*(1-d)+a[1]*d;c[2]=b[2]*(1-d)+a[2]*d}for(var e in c)c[e]/=255;this.boxcolor=colorToString(c);this.setOutputData(0,c)}}});
LiteGraph.registerNodeType("graphics/frame",{title:"Frame",desc:"Frame viewerew",inputs:[["","image"]],size:[200,200],widgets:[{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}],onDrawBackground:function(a){this.frame&&a.drawImage(this.frame,0,0,this.size[0],this.size[1])},onExecute:function(){this.frame=this.getInputData(0);this.setDirtyCanvas(!0)},onWidget:function(a,b){if("resize"==b.name&&this.frame){var c=this.frame.width,d=this.frame.height;c||null==
this.frame.videoWidth||(c=this.frame.videoWidth,d=this.frame.videoHeight);c&&d&&(this.size=[c,d]);this.setDirtyCanvas(!0,!0)}else"view"==b.name&&this.show()},show:function(){showElement&&this.frame&&showElement(this.frame)}});
LiteGraph.registerNodeType("visualization/graph",{desc:"Shows a graph of the inputs",inputs:[["",0],["",0],["",0],["",0]],size:[200,200],properties:{min:-1,max:1,bgColor:"#000"},onDrawBackground:function(a){var b=["#FFF","#FAA","#AFA","#AAF"];null!=this.properties.bgColor&&""!=this.properties.bgColor&&(a.fillStyle="#000",a.fillRect(2,2,this.size[0]-4,this.size[1]-4));if(this.data){var c=this.properties.min,d=this.properties.max,e;for(e in this.data){var f=this.data[e];if(f&&null!=this.getInputInfo(e)){a.strokeStyle=
b[e];a.beginPath();for(var g=f.length/this.size[0],h=0;h<f.length;h+=g){var k=f[Math.floor(h)],k=(k-c)/(d-c);1<k?k=1:0>k&&(k=0);0==h?a.moveTo(h/g,this.size[1]-5-(this.size[1]-10)*k):a.lineTo(h/g,this.size[1]-5-(this.size[1]-10)*k)}a.stroke()}}}},onExecute:function(){this.data||(this.data=[]);for(var a in this.inputs){var b=this.getInputData(a);"number"==typeof b?(b=b?b:0,this.data[a]||(this.data[a]=[]),this.data[a].push(b),this.data[a].length>this.size[1]-4&&(this.data[a]=this.data[a].slice(1,this.data[a].length))):
this.data[a]=b}this.data.length&&this.setDirtyCanvas(!0)}});
LiteGraph.registerNodeType("graphics/supergraph",{title:"Supergraph",desc:"Shows a nice circular graph",inputs:[["x","number"],["y","number"],["c","color"]],outputs:[["","image"]],widgets:[{name:"clear_alpha",text:"Clear Alpha",type:"minibutton"},{name:"clear_color",text:"Clear color",type:"minibutton"}],properties:{size:256,bgcolor:"#000",lineWidth:1},bgcolor:"#000",flags:{allow_fastrender:!0},onLoad:function(){this.createCanvas()},createCanvas:function(){this.canvas=document.createElement("canvas");
this.canvas.width=this.properties.size;this.canvas.height=this.properties.size;this.oldpos=null;this.clearCanvas(!0)},onExecute:function(){var a=this.getInputData(0),b=this.getInputData(1),c=this.getInputData(2);if(null!=a||null!=b){a||(a=0);b||(b=0);var a=0.95*a,b=0.95*b,d=this.properties.size;d==this.canvas.width&&d==this.canvas.height||this.createCanvas();if(this.oldpos){var e=this.canvas.getContext("2d");null==c?c="rgba(255,255,255,0.5)":"object"==typeof c&&(c=colorToString(c));e.strokeStyle=
c;e.beginPath();e.moveTo(this.oldpos[0],this.oldpos[1]);this.oldpos=[(0.5*a+0.5)*d,(0.5*b+0.5)*d];e.lineTo(this.oldpos[0],this.oldpos[1]);e.stroke();this.canvas.dirty=!0;this.setOutputData(0,this.canvas)}else this.oldpos=[(0.5*a+0.5)*d,(0.5*b+0.5)*d]}},clearCanvas:function(a){var b=this.canvas.getContext("2d");a?(b.clearRect(0,0,this.canvas.width,this.canvas.height),this.trace("Clearing alpha")):(b.fillStyle=this.properties.bgcolor,b.fillRect(0,0,this.canvas.width,this.canvas.height))},onWidget:function(a,
b){"clear_color"==b.name?this.clearCanvas(!1):"clear_alpha"==b.name&&this.clearCanvas(!0)},onPropertyChange:function(a,b){if("size"==a)this.properties.size=parseInt(b),this.createCanvas();else if("bgcolor"==a)this.properties.bgcolor=b,this.createCanvas();else if("lineWidth"==a)this.properties.lineWidth=parseInt(b),this.canvas.getContext("2d").lineWidth=this.properties.lineWidth;else return!1;return!0}});
LiteGraph.registerNodeType("graphics/imagefade",{title:"Image fade",desc:"Fades between images",inputs:[["img1","image"],["img2","image"],["fade","number"]],outputs:[["","image"]],properties:{fade:0.5,width:512,height:512},widgets:[{name:"resizeA",text:"Resize to A",type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}],onLoad:function(){this.createCanvas();var a=this.canvas.getContext("2d");a.fillStyle="#000";a.fillRect(0,0,this.properties.width,this.properties.height)},createCanvas:function(){this.canvas=
document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height},onExecute:function(){var a=this.canvas.getContext("2d");this.canvas.width=this.canvas.width;var b=this.getInputData(0);null!=b&&a.drawImage(b,0,0,this.canvas.width,this.canvas.height);b=this.getInputData(2);null==b?b=this.properties.fade:this.properties.fade=b;a.globalAlpha=b;b=this.getInputData(1);null!=b&&a.drawImage(b,0,0,this.canvas.width,this.canvas.height);a.globalAlpha=1;this.setOutputData(0,
this.canvas);this.setDirtyCanvas(!0)}});
LiteGraph.registerNodeType("graphics/image",{title:"Image",desc:"Image loader",inputs:[],outputs:[["frame","image"]],properties:{url:""},widgets:[{name:"load",text:"Load",type:"button"}],onLoad:function(){""!=this.properties.url&&null==this.img&&this.loadImage(this.properties.url)},onStart:function(){},onExecute:function(){this.img||(this.boxcolor="#000");this.img&&this.img.width?this.setOutputData(0,this.img):this.setOutputData(0,null);this.img.dirty&&(this.img.dirty=!1)},onPropertyChange:function(a,
b){this.properties[a]=b;"url"==a&&""!=b&&this.loadImage(b);return!0},loadImage:function(a){if(""==a)this.img=null;else{this.trace("loading image...");this.img=document.createElement("img");this.img.src="miniproxy.php?url="+a;this.boxcolor="#F95";var b=this;this.img.onload=function(){b.trace("Image loaded, size: "+b.img.width+"x"+b.img.height);this.dirty=!0;b.boxcolor="#9F9";b.setDirtyCanvas(!0)}}},onWidget:function(a,b){"load"==b.name&&this.loadImage(this.properties.url)}});
LiteGraph.registerNodeType("graphics/cropImage",{title:"Crop",desc:"Crop Image",inputs:[["","image"]],outputs:[["","image"]],properties:{width:256,height:256,x:0,y:0,scale:1},size:[50,20],onLoad:function(){this.createCanvas()},createCanvas:function(){this.canvas=document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height},onExecute:function(){var a=this.getInputData(0);a&&(a.width?(this.canvas.getContext("2d").drawImage(a,-this.properties.x,-this.properties.y,
a.width*this.properties.scale,a.height*this.properties.scale),this.setOutputData(0,this.canvas)):this.setOutputData(0,null))},onPropertyChange:function(a,b){this.properties[a]=b;"scale"==a?(this.properties[a]=parseFloat(b),0==this.properties[a]&&(this.trace("Error in scale"),this.properties[a]=1)):this.properties[a]=parseInt(b);this.createCanvas();return!0}});
LiteGraph.registerNodeType("graphics/video",{title:"Video",desc:"Video playback",inputs:[["t","number"]],outputs:[["frame","image"],["t","number"],["d","number"]],properties:{url:""},widgets:[{name:"play",text:"PLAY",type:"minibutton"},{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}],onClick:function(a){if(this.video&&20>distance([a.canvasX,a.canvasY],[this.pos[0]+55,this.pos[1]+40]))return this.play(),!0},onKeyDown:function(a){32==
a.keyCode&&this.playPause()},onLoad:function(){""!=this.properties.url&&this.loadVideo(this.properties.url)},play:function(){this.video&&(this.trace("Video playing"),this.video.play())},playPause:function(){this.video&&(this.video.paused?this.play():this.pause())},stop:function(){this.video&&(this.trace("Video stopped"),this.video.pause(),this.video.currentTime=0)},pause:function(){this.video&&(this.trace("Video paused"),this.video.pause())},onExecute:function(){if(this.video){var a=this.getInputData(0);
a&&0<=a&&1>=a&&(this.video.currentTime=a*this.video.duration,this.video.pause());this.video.dirty=!0;this.setOutputData(0,this.video);this.setOutputData(1,this.video.currentTime);this.setOutputData(2,this.video.duration);this.setDirtyCanvas(!0)}},onStart:function(){},onStop:function(){this.pause()},loadVideo:function(a){this.video=document.createElement("video");a?this.video.src=a:(this.video.src="modules/data/video.webm",this.properties.url=this.video.src);this.video.type="type=video/mp4";this.video.muted=
!0;this.video.autoplay=!1;var b=this;this.video.addEventListener("loadedmetadata",function(a){b.trace("Duration: "+b.video.duration+" seconds");b.trace("Size: "+b.video.videoWidth+","+b.video.videoHeight);b.setDirtyCanvas(!0);this.width=this.videoWidth;this.height=this.videoHeight});this.video.addEventListener("progress",function(a){});this.video.addEventListener("error",function(a){b.trace("Error loading video: "+this.src);if(this.error)switch(this.error.code){case this.error.MEDIA_ERR_ABORTED:b.trace("You stopped the video.");
break;case this.error.MEDIA_ERR_NETWORK:b.trace("Network error - please try again later.");break;case this.error.MEDIA_ERR_DECODE:b.trace("Video is broken..");break;case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED:b.trace("Sorry, your browser can't play this video.")}});this.video.addEventListener("ended",function(a){b.trace("Ended.");this.play()})},onPropertyChange:function(a,b){this.properties[a]=b;"url"==a&&""!=b&&this.loadVideo(b);return!0},onWidget:function(a,b){"demo"==b.name?this.loadVideo():"play"==
b.name&&this.video&&this.playPause();"stop"==b.name?this.stop():"mute"==b.name&&this.video&&(this.video.muted=!this.video.muted)}});

42
css/litegraph.css Normal file
View File

@@ -0,0 +1,42 @@
/* this CSS contains only the basic CSS needed to run the app and use it */
.lgraphcanvas {
cursor: crosshair;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
.litecontextualmenu {
padding: 4px;
min-width: 100px;
}
.litemenu-entry {
padding-left: 20px;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
.litemenu-entry.disabled {
opacity: 0.3;
}
.litemenu-entry.submenu {
border-right: 2px solid #EEE;
}
.litemenu-entry:hover {
background-color: #555;
}
.litemenu-entry.separator {
background-color: #111;
border-bottom: 1px solid #666;
height: 1px;
width: calc( 100% - 20px );
-moz-width: calc( 100% - 20px );
-webkit-width: calc( 100% - 20px );
}

547
demo/code.js Normal file
View File

@@ -0,0 +1,547 @@
var graph = null;
var graphcanvas = null;
$(window).load(function() {
var id = null;
if ($.getUrlVar("id") != null)
id = parseInt($.getUrlVar("id"));
else if (self.document.location.hash)
id = parseInt( self.document.location.hash.substr(1) );
$("#settings_button").click( function() { $("#settings-panel").toggle(); });
$("#addnode_button").click( function() { onShowNodes() });
$("#deletenode_button").click( function() { onDeleteNode() });
$("#clonenode_button").click( function() { onCloneNode() });
$("#playnode_button").click( function() {
if(graph.status == LGraph.STATUS_STOPPED)
{
$(this).html("<img src='imgs/icon-stop.png'/> Stop");
graph.run(1);
}
else
{
$(this).html("<img src='imgs/icon-play.png'/> Play");
graph.stop();
}
});
$("#playstepnode_button").click( function() {
graph.runStep(1);
graphcanvas.draw(true,true);
});
$("#playfastnode_button").click( function() {
graph.runStep(5000);
graphcanvas.draw(true,true);
});
$("#collapsenode_button").click( function() {
/*
for(var i in graphcanvas.nodes_selected)
graphcanvas.nodes_selected[i].collapse();
*/
if( graphcanvas.node_in_panel )
graphcanvas.node_in_panel.collapse();
graphcanvas.draw();
});
$("#pinnode_button").click( function() {
if( graphcanvas.node_in_panel )
graphcanvas.node_in_panel.pin();
});
$("#sendtobacknode_button").click( function() {
if( graphcanvas.node_in_panel )
graphcanvas.sendToBack( graphcanvas.node_in_panel );
graphcanvas.draw(true);
});
$("#confirm-createnode_button").click(function() {
var element = $(".node-type.selected")[0];
var name = element.data;
var n = LiteGraph.createNode(name);
graph.add(n);
n.pos = graphcanvas.convertOffsetToCanvas([30,30]);
graphcanvas.draw(true,true);
$("#modal-blocking-box").hide();
$("#nodes-browser").hide();
});
$("#cancel-createnode_button").click(function() {
$("#modal-blocking-box").hide();
$("#nodes-browser").hide();
});
$("#close-area_button").click(function() {
$("#modal-blocking-box").hide();
$("#data-visor").hide();
});
$("#confirm-loadsession_button").click(function() {
var element = $(".session-item.selected")[0];
var info = element.data;
var str = localStorage.getItem("graph_session_" + info.id );
graph.stop();
graph.unserialize(str);
graphcanvas.draw(true,true);
$("#modal-blocking-box").hide();
$("#sessions-browser").hide();
});
$("#cancel-loadsession_button").click(function() {
$("#modal-blocking-box").hide();
$("#sessions-browser").hide();
});
$("#livemode_button").click( function() {
graphcanvas.switchLiveMode();
graphcanvas.draw();
var url = graphcanvas.live_mode ? "imgs/gauss_bg_medium.jpg" : "imgs/gauss_bg.jpg";
$("#livemode_button").html(!graphcanvas.live_mode ? "<img src='imgs/icon-record.png'/> Live" : "<img src='imgs/icon-gear.png'/> Edit" );
//$("canvas").css("background-image","url('"+url+"')");
});
$("#newsession_button").click( function() {
$("#main-area").hide();
graph.clear();
graphcanvas.draw();
$("#main-area").show();
});
$("#savesession_button").click( function() {
onSaveSession();
});
$("#loadsession_button").click( function() {
onLoadSession();
});
$("#cancelsession-dialog_button").click(function()
{
$("#modal-blocking-box").hide();
$("#savesession-dialog").hide();
});
$("#savesession-dialog_button").click(function()
{
var name = $("#session-name-input").val();
var desc = $("#session-description-input").val();
saveSession(name,desc);
$("#modal-blocking-box").hide();
$("#savesession-dialog").hide();
});
$("#closepanel_button").click(function()
{
graphcanvas.showNodePanel(null);
});
$("#maximize_button").click(function()
{
if($("#main").width() != window.innerWidth)
{
$("#main").width( (window.innerWidth).toString() + "px");
$("#main").height( (window.innerHeight - 40).toString() + "px");
graphcanvas.resizeCanvas(window.innerWidth,window.innerHeight - 100);
}
else
{
$("#main").width("800px");
$("#main").height("660px");
graphcanvas.resizeCanvas(800,600);
}
});
$("#resetscale_button").click(function()
{
graph.config.canvas_scale = 1.0;
graphcanvas.draw(true,true);
});
$("#resetpos_button").click(function()
{
graph.config.canvas_offset = [0,0];
graphcanvas.draw(true,true);
});
$(".nodecolorbutton").click(function()
{
if( graphcanvas.node_in_panel )
{
graphcanvas.node_in_panel.color = this.getAttribute("data-color");
graphcanvas.node_in_panel.bgcolor = this.getAttribute("data-bgcolor");
}
graphcanvas.draw(true,true);
});
if ("onhashchange" in window) // does the browser support the hashchange event?
{
window.onhashchange = function () {
var h = window.location.hash.substr(1);
//action
return false;
}
}
LiteGraph.node_images_path = "../nodes_data/";
graph = new LGraph();
graphcanvas = new LGraphCanvas("graphcanvas",graph);
graphcanvas.background_image = "imgs/grid.png";
graph.onAfterExecute = function() { graphcanvas.draw(true) };
demo();
graph.onPlayEvent = function()
{
$("#playnode_button").addClass("playing");
$("#playnode_button").removeClass("stopped");
}
graph.onStopEvent = function()
{
$("#playnode_button").addClass("stopped");
$("#playnode_button").removeClass("playing");
}
graphcanvas.draw();
//update load counter
setInterval(function() {
$("#cpuload .fgload").width( (2*graph.elapsed_time) * 90);
if(graph.status == LGraph.STATUS_RUNNING)
$("#gpuload .fgload").width( (graphcanvas.render_time*10) * 90);
else
$("#gpuload .fgload").width( 4 );
},200);
//LiteGraph.run(100);
});
function onShowNodes()
{
$("#nodes-list").empty();
for (var i in LiteGraph.registered_node_types)
{
var node = LiteGraph.registered_node_types[i];
var categories = node.category.split("/");
//create categories and find the propper one
var root = $("#nodes-list")[0];
for(var i in categories)
{
var result = $(root).find("#node-category_" + categories[i] + " .container");
if (result.length == 0)
{
var element = document.createElement("div");
element.id = "node-category_" + categories[i];
element.className = "node-category";
element.data = categories[i];
element.innerHTML = "<strong class='title'>"+categories[i]+"</strong>";
root.appendChild(element);
$(element).find(".title").click(function(e){
var element = $("#node-category_" + this.parentNode.data + " .container");
$(element[0]).toggle();
});
var container = document.createElement("div");
container.className = "container";
element.appendChild(container);
root = container;
}
else
root = result[0];
}
//create entry
var type = node.type;
var element = document.createElement("div");
element.innerHTML = "<strong>"+node.title+"</strong> " + (node.desc? node.desc : "");
element.className = "node-type";
element.id = "node-type-" + node.name;
element.data = type;
root.appendChild(element);
}
$(".node-type").click( function() {
$(".node-type.selected").removeClass("selected");
$(this).addClass("selected");
$("#confirm-createnode_button").attr("disabled",false);
});
$(".node-type").dblclick( function() {
$("#confirm-createnode_button").click();
});
$("#confirm-createnode_button").attr("disabled",true);
$("#modal-blocking-box").show();
$("#nodes-browser").show();
}
function onDeleteNode()
{
if(!graphcanvas.node_in_panel) return;
graph.remove( graphcanvas.node_in_panel );
graphcanvas.draw();
$("#node-panel").hide();
graphcanvas.node_in_panel = null;
}
function onCloneNode()
{
if(!graphcanvas.node_in_panel) return;
var n = graphcanvas.node_in_panel.clone();
n.pos[0] += 10;
n.pos[1] += 10;
graph.add(n);
graphcanvas.draw();
}
function onSaveSession()
{
if(graph.session["name"])
$("#session-name-input").val(graph.session["name"]);
if(graph.session["description"])
$("#session-desc-input").val(graph.session["description"]);
$("#modal-blocking-box").show();
$("#savesession-dialog").show();
//var str = LiteGraph.serialize();
//localStorage.setItem("graph_session",str);
}
function saveSession(name,desc)
{
desc = desc || "";
graph.session["name"] = name;
graph.session["description"] = desc;
if(!graph.session["id"])
graph.session["id"] = new Date().getTime();
var str = graph.serializeSession();
localStorage.setItem("graph_session_" + graph.session["id"],str);
var sessions_str = localStorage.getItem("node_sessions");
var sessions = [];
if(sessions_str)
sessions = JSON.parse(sessions_str);
var pos = -1;
for(var i = 0; i < sessions.length; i++)
if( sessions[i].id == graph.session["id"] && sessions[i].name == name)
{
pos = i;
break;
}
if(pos != -1)
{
//already on the list
}
else
{
var current_session = {name:name, desc:desc, id:graph.session["id"]};
sessions.unshift(current_session);
localStorage.setItem("graph_sessions", JSON.stringify(sessions));
}
}
function onLoadSession()
{
$("#sessions-browser-list").empty();
$("#modal-blocking-box").show();
$("#sessions-browser").show();
var sessions_str = localStorage.getItem("graph_sessions");
var sessions = [];
if(sessions_str)
sessions = JSON.parse(sessions_str);
for(var i in sessions)
{
var element = document.createElement("div");
element.className = "session-item";
element.data = sessions[i];
$(element).html("<strong>"+sessions[i].name+"</strong><span>"+sessions[i].desc+"</span><span class='delete_session'>x</span>");
$("#sessions-browser-list").append(element);
}
$(".session-item").click( function() {
$(".session-item.selected").removeClass("selected");
$(this).addClass("selected");
$("#confirm-loadsession_button").attr("disabled",false);
});
$(".session-item").dblclick( function() {
$("#confirm-loadsession_button").click();
});
$(".delete_session").click(function(e) {
var root = $(this).parent();
var info = root[0].data;
var sessions_str = localStorage.getItem("graph_sessions");
var sessions = [];
if(sessions_str)
sessions = JSON.parse(sessions_str);
var pos = -1;
for(var i = 0; i < sessions.length; i++)
if( sessions[i].id == info.id )
{
pos = i;
break;
}
if(pos != -1)
{
sessions.splice(pos,1);
localStorage.setItem("graph_sessions", JSON.stringify(sessions));
}
root.remove();
});
$("#confirm-loadsession_button").attr("disabled",true);
/*
LiteGraph.stop();
var str = localStorage.getItem("graph_session");
LiteGraph.unserialize(str);
LiteGraph.draw();
*/
}
function onShagraph()
{
}
function showImage(data)
{
var img = new Image();
img.src = data;
$("#data-visor .content").empty();
$("#data-visor .content").append(img);
$("#modal-blocking-box").show();
$("#data-visor").show();
}
function showElement(data)
{
setTimeout(function(){
$("#data-visor .content").empty();
$("#data-visor .content").append(data);
$("#modal-blocking-box").show();
$("#data-visor").show();
},100);
}
// ********* SEEDED RANDOM ******************************
function RandomNumberGenerator(seed)
{
if (typeof(seed) == 'undefined')
{
var d = new Date();
this.seed = 2345678901 + (d.getSeconds() * 0xFFFFFF) + (d.getMinutes() * 0xFFFF);
}
else
this.seed = seed;
this.A = 48271;
this.M = 2147483647;
this.Q = this.M / this.A;
this.R = this.M % this.A;
this.oneOverM = 1.0 / this.M;
this.next = nextRandomNumber;
return this;
}
function nextRandomNumber(){
var hi = this.seed / this.Q;
var lo = this.seed % this.Q;
var test = this.A * lo - this.R * hi;
if(test > 0){
this.seed = test;
} else {
this.seed = test + this.M;
}
return (this.seed * this.oneOverM);
}
var RAND_GEN = RandomNumberGenerator(0);
function RandomSeed(s) { RAND_GEN = RandomNumberGenerator(s); };
function myrand(Min, Max){
return Math.round((Max-Min) * RAND_GEN.next() + Min);
}
function myrandom() { return myrand(0,100000) / 100000; }
// @format (hex|rgb|null) : Format to return, default is integer
function random_color(format)
{
var rint = Math.round(0xffffff * myrandom());
switch(format)
{
case 'hex':
return ('#0' + rint.toString(16)).replace(/^#0([0-9a-f]{6})$/i, '#$1');
break;
case 'rgb':
return 'rgb(' + (rint >> 16) + ',' + (rint >> 8 & 255) + ',' + (rint & 255) + ')';
break;
default:
return rint;
break;
}
}
$.extend({
getUrlVars: function(){
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
},
getUrlVar: function(name){
return $.getUrlVars()[name];
}
});
function trace(a)
{
if(typeof(console) == "object")
console.log(a);
}

114
demo/demo.js Normal file
View File

@@ -0,0 +1,114 @@
/* EXAMPLE ***************************
reModular.registerModuleType("name", {
title: "",
desc: "",
inputs: [["","type"]],
outputs: [["","type"]],
properties: {"varname":""},
widgets: [{name:"name",text:"text to show",type:"button"}],
size: [200,220],
onLoad: function()
{
},
onDrawBackground: function(ctx)
{
if(this.img)
ctx.drawImage(this.img, 0,20,this.size[0],this.size[1]-20);
},
onExecute: function()
{
this.img = this.getInputData(0);
reModular.dirty_canvas = true;
},
onPropertyChange: function(name,value)
{
this.properties[name] = value;
return true; //block default behaviour
},
onWidget: function(e,widget)
{
if(widget.name == "resize")
{
}
},
});
*/
function demo()
{
multiConnection();
}
function multiConnection()
{
var node_const_A = LiteGraph.createNode("basic/const");
node_const_A.pos = [200,200];
graph.add(node_const_A);
node_const_A.setValue(4);
var node_const_B = LiteGraph.createNode("basic/const");
node_const_B.pos = [200,300];
graph.add(node_const_B);
node_const_B.setValue(10);
var node_math = LiteGraph.createNode("math/operation");
node_math.pos = [400,200];
node_math.addOutput("A*B");
graph.add(node_math);
var node_watch = LiteGraph.createNode("basic/watch");
node_watch.pos = [700,200];
graph.add(node_watch);
var node_watch2 = LiteGraph.createNode("basic/watch");
node_watch2.pos = [700,300];
graph.add(node_watch2);
node_const_A.connect(0,node_math,0 );
node_const_B.connect(0,node_math,1 );
node_math.connect(0,node_watch,0 );
node_math.connect(0,node_watch2,0 );
}
function sortTest()
{
var rand = LiteGraph.createNode("math/rand",null, {pos: [10,100] });
graph.add(rand);
var nodes = [];
for(var i = 4; i >= 1; i--)
{
var n = LiteGraph.createNode("basic/watch",null, {pos: [i * 120,100] });
graph.add(n);
nodes[i-1] = n;
}
rand.connect(0, nodes[0], 0);
for(var i = 0; i < nodes.length - 1; i++)
nodes[i].connect(0,nodes[i+1], 0);
}
function benchmark()
{
var num_nodes = 500;
var consts = [];
for(var i = 0; i < num_nodes; i++)
{
var n = LiteGraph.createNode("math/rand",null, {pos: [(2000 * Math.random())|0, (2000 * Math.random())|0] });
graph.add(n);
consts.push(n);
}
var watches = [];
for(var i = 0; i < num_nodes; i++)
{
var n = LiteGraph.createNode("basic/watch",null, {pos: [(2000 * Math.random())|0, (2000 * Math.random())|0] });
graph.add(n);
watches.push(n);
}
for(var i = 0; i < num_nodes; i++)
consts[ (Math.random() * consts.length)|0 ].connect(0, watches[ (Math.random() * watches.length)|0 ], 0 );
}

BIN
demo/imgs/grid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

BIN
demo/imgs/icon-edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

BIN
demo/imgs/icon-gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

BIN
demo/imgs/icon-maximize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

BIN
demo/imgs/icon-play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

BIN
demo/imgs/icon-playstep.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

BIN
demo/imgs/icon-record.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

BIN
demo/imgs/icon-stop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
demo/imgs/play-icons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

70
demo/index.html Normal file
View File

@@ -0,0 +1,70 @@
<!-- Javi Agenjo (@tamat) on 31/9/2011 -->
<!DOCTYPE html>
<html><head>
<title>LiteGraph</title>
<!--<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">-->
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="../css/litegraph.css">
</head>
<body>
<div id="main">
<div id="header">
<h1>LiteGraph <span>by tamat</span></h1>
<div id="loadmeter" class="headerpanel">
<div id="cpuload">
<strong>CPU</strong> <div class="bgload"><div class="fgload"></div></div>
</div>
<div id="gpuload">
<strong>GFX</strong> <div class="bgload"><div class="fgload"></div></div>
</div>
</div>
<div class="tools">
<button id="playnode_button" title="Control+P"><img src='imgs/icon-play.png'/> Play</button>
<button id="playstepnode_button"><img src='imgs/icon-playstep.png'/> Step</button>
<button id="livemode_button"><img src='imgs/icon-record.png'/> Live</button>
<button id="maximize_button"><img src='imgs/icon-maximize.png'/></button>
</div>
</div>
<div id="content">
<div id="editor" class="section">
<canvas id="graphcanvas" width="1000" height="500" tabindex=10></canvas>
</div>
<div id="modules" class="section" style="display:none">
<div id="modules-list" class="modules-list-container">
</div>
<div class="list-buttons">
<button id="confirm-createmodule_button" class="button">Create</button>
<button id="cancel-createmodule_button" class="button">Cancel</button>
</div>
</div>
</div>
<div id="footer">
<div id="tools-left" class="tools">
<button id="code_dec_button">-</button>
<button id="code_inc_button">+</button>
</div>
<div id="tools-right" class="tools">
<button id="help_button">Help</button>
</div>
</div>
</div>
<script type="text/javascript" src="../external/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="../src/litegraph.js"></script>
<script type="text/javascript" src="../src/nodes/basicnodes.js"></script>
<script type="text/javascript" src="../src/nodes/uinodes.js"></script>
<script type="text/javascript" src="../src/nodes/imagenodes.js"></script>
<script type="text/javascript" src="demo.js"></script>
<script type="text/javascript" src="code.js"></script>
</body>
</html>

387
demo/style.css Normal file
View File

@@ -0,0 +1,387 @@
html,body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
background-color: #333;
color: #EEE;
font: 14px Tahoma;
}
h1 {
font-family: "Metro Light",Tahoma;
color: #DDD;
font-size: 28px;
padding-left: 10px;
/*text-shadow: 0 1px 1px #333, 0 -1px 1px #777;*/
margin: 0;
font-weight: normal;
}
h1 span {
font-family: "Arial";
font-size: 14px;
font-weight: normal;
color: #AAA;
}
h2 {
font-family: "Metro Light";
padding: 5px;
margin-left: 10px;
}
#main {
width: 1000px;
min-height: 540px;
margin: auto;
background-color: #222;
/*border-radius: 10px;*/
}
#main.fullscreen {
width: 100%;
height: 100%;
}
#header, #footer {
position: relative;
height: 40px;
background-color: #333;
/*border-radius: 10px 10px 0 0;*/
}
.tools, #tools-left, #tools-right {
position: absolute;
top: 2px;
right: 0px;
vertical-align: top;
margin: 2px 5px 0 0px;
}
#header button {
height: 32px;
vertical-align: top;
}
#footer button {
/*font-size: 16px;*/
}
#tools-left {
right: auto;
left: 4px;
}
#footer {
height: 40px;
position: relative;
/*border-radius: 0 0 10px 10px;*/
}
#status {
position: absolute;
top: 10px;
right: 10px;
color: #FAA;
font-size: 18px;
padding: 5px;
/*border-radius: 5px;*/
width: -moz-calc( 50% - 30px);
min-height: 30px;
overflow: hidden;
background-color: #644;
}
#help-message {
padding: 2px;
font-size: 0.8em;
background-color: #464;
/*border-radius: 2px;*/
}
#content {
position: relative;
min-height: 500px;
overflow: hidden;
}
.fullscreen #content {
min-height: -moz-calc(100% - 80px);
min-height: -webkit-calc(100% - 80px);
min-height: calc(100% - 80px);
}
.info-section p {
padding-left: 20px;
margin: 2px;
}
.info-section strong {
color: #FEA;
}
#visual {
position: absolute;
top: 0;
left: 0;
background-color: black;
width: 100%;
height: 100%;
}
button {
/*font-family: "Metro Light";*/
color: #CCC;
font-size: 20px;
min-width: 30px;
/*border-radius: 0.3em;*/
border: 0 solid #666;
background-color: #3F3F3F;
/*box-shadow: 0 0 3px black;*/
padding: 4px 10px;
line-height: 20px;
cursor: pointer;
transition: all 1s;
-moz-transition: all 1s;
-webkit-transition: all 0.4s;
}
button:hover {
background-color: #999;
color: #FFF;
transition: all 1s;
-moz-transition: all 1s;
-webkit-transition: all 0.4s;
}
button:active {
background-color: white;
}
button.fixed {
position: absolute;
top: 5px;
right: 5px;
font-size: 1.2em;
}
button img {
margin: -4px;
vertical-align: top;
}
#play_button {
background-color: #446;
margin-right: 30px;
}
#play_button:hover {
background-color: #AAF;
}
.item-list .item {
margin: 5px;
padding: 5px;
font-size: 1.2em;
background-color: transparent;
color: #999;
padding-left: 5px;
transition: background-color 300ms, color 300ms, padding-left 300ms;
-moz-transition: background-color 300ms, color 300ms, padding-left 300ms;
-webkit-transition: background-color 300ms, color 300ms, padding-left 300ms;
}
.item-list .item:hover {
background-color: #33A;
/*border-radius: 4px;*/
color: white;
padding-left: 15px;
transition: background-color 300ms, color 300ms, padding-left 300ms;
-moz-transition: background-color 300ms, color 300ms, padding-left 300ms;
-webkit-transition: background-color 300ms, color 300ms, padding-left 300ms;
cursor: pointer;
}
#gallery .item-list .item:hover {
background-color: #A83;
}
.item-list .item strong {
display: inline-block;
width: 200px;
}
.form label {
font-size: 1.2em;
width: 200px;
display: inline-block;
text-align: right;
}
label {
font-weight: bold;
color: #AAF;
}
input,textarea {
color: #EEE;
background-color: #555;
font-size: 1.2em;
border: 1px solid black;
/*border-radius: 4px;*/
padding: 2px;
/*box-shadow: inset 0 0 3px #333; */
font-family: Verdana;
width: 250px;
}
textarea {
vertical-align: top;
}
#block-app {
width:100%;
height:100%;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0,0,0,0.5);
text-align: center;
z-index: 6;
}
#block-app span {
display: block;
font-size: 30px;
margin: auto;
margin-top: 300px;
}
#block-app span a {
display: inline-block;
/*border-radius: 4px;*/
text-decoration: none;
color: black;
background-color: red;
padding: 0 4px 0 4px;
}
::-webkit-scrollbar {
height: 12px;
width: 6px;
background: #222;
}
::-webkit-scrollbar-thumb {
background: rgba(200,200,200,0.4);
}
::-webkit-scrollbar-corner {
background: #766;
}
#editor {
position: relative;
width: 50%;
height: 100%;
display: inline-block;
margin: 0;
padding: 0;
}
#editor .toolsbar {
width: 100%;
height: 30px;
background-color: #262626;
margin: 0;
padding: 0;
}
#editor .toolsbar button {
padding: 2px;
padding-left: 10px;
padding-right: 10px;
margin: 3px 0 0 3px;
}
#editor .toolsbar button.enabled {
background-color: #66A;
}
#world {
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 100%;
}
#worldcanvas {
background-color: #343;
}
.popup {
position: absolute;
top: 0;
background-color: rgba(50,50,90,0.8);
width: 100%;
height: 100%;
}
.popup .header, .nodepanel .header {
width: 100%;
height: 30px;
font-size: 20px;
padding: 2px;
}
#help {
color: #eee;
}
#help p {
margin: 10px;
}
#loadmeter {
font-family: "Tahoma";
display: inline-block;
position: absolute;
top: 0;
left: 300px;
color: #AAA;
font-size: 12px;
border-radius: 2px;
width: 130px;
margin: 3px;
padding: 2px;
vertical-align: top;
}
#loadmeter strong {
vertical-align: top;
padding: 3px;
width: 30px;
display: inline-block;
line-height: 8px;
}
#cpuload .bgload, #gpuload .bgload {
display: inline-block;
width: 90px;
height: 15px;
background-image: url('imgs/load-progress-empty.png');
}
#cpuload .fgload, #gpuload .fgload {
display: inline-block;
width: 4px;
height: 15px;
max-width: 90px;
background-image: url('imgs/load-progress-full.png');
}

BIN
external/Basica.otf vendored Normal file

Binary file not shown.

BIN
external/Criticized.otf vendored Normal file

Binary file not shown.

BIN
external/DS-Digital.otf vendored Normal file

Binary file not shown.

BIN
external/beat.otf vendored Normal file

Binary file not shown.

18
external/jquery-1.6.2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

54
index.html Normal file
View File

@@ -0,0 +1,54 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<!--
<meta property="og:title" content="GameEditor" />
<meta property="og:description" content="GameEditor for simple games" />
<meta property="og:image" content="" />
-->
<title>litegraph.js</title>
<link type="text/css" rel="stylesheet" media="all" href="https://github.com/assets/github-c066013be20516a6aae45467044fa109f18bd0c6.css">
<link type="text/css" rel="stylesheet" media="all" href="https://github.com/assets/github2-97081caeb5890bc349a9ff52de33ac5ba1a4b6cc.css">
<link type="text/css" rel="stylesheet" media="all" href="https://github.com/assets/styleguide-4a2ef42768c9e616cf8022dec2fe99290430ac2c.css">
<link rel="stylesheet" type="text/css" href="style.css" />
<style type='text/css'>
</style>
</head>
<body>
<div id="wrap">
<div id="main">
<div id="content" class="markdown-body">
<h1>litegraph.js</h1>
<p>Litegraph.js is a library that allows to create modular graphs on the web, similar to PureData.</p>
<p>Graphs can be used to create workflows, image processing, audio, or any kind of network of modules interacting with each other.</p>
<p>Some of the main features:</p>
<ul>
<li>Automatic sorting of modules according to basic rules.</li>
<li>Dynamic number of input/outputs per module.</li>
<li>Persistence, graphs can be serialized in a JSON.</li>
<li>Optimized render in a HTML5 Canvas (supports hundres of modules on the screen).</li>
<li>Allows to run the graphs without the need of the canvas (standalone mode).</li>
<li>Simple API. It is very easy to create new modules.</li>
<li>Edit and Live mode, (in live mode only modules with widgets are rendered.</li>
<li>Contextual menu in the editor.</li>
</ul>
<h2>Usage</h2>
<h2>Examples</h2>
<ul>
<li><a href="demo">Module editor</a></li>
</ul>
<h2>Documentation</h2>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

BIN
nodes_data/imgs/knob_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
nodes_data/imgs/knob_fg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

3593
src/litegraph.js Normal file

File diff suppressed because it is too large Load Diff

738
src/nodes/basicnodes.js Normal file
View File

@@ -0,0 +1,738 @@
//basic nodes
LiteGraph.registerNodeType("basic/const",{
title: "Const",
desc: "Constant",
outputs: [["value","number"]],
properties: {value:1.0},
editable: { property:"value", type:"number" },
setValue: function(v)
{
if( typeof(v) == "string") v = parseFloat(v);
this.properties["value"] = v;
this.setDirtyCanvas(true);
},
onExecute: function()
{
this.setOutputData(0, parseFloat( this.properties["value"] ) );
},
onDrawBackground: function(ctx)
{
//show the current value
this.outputs[0].label = this.properties["value"].toFixed(3);
},
onWidget: function(e,widget)
{
if(widget.name == "value")
this.setValue(widget.value);
}
});
LiteGraph.registerNodeType("math/rand",{
title: "Rand",
desc: "Random number",
outputs: [["value","number"]],
properties: {min:0,max:1},
size: [60,20],
onExecute: function()
{
var min = this.properties.min;
var max = this.properties.max;
this._last_v = Math.random() * (max-min) + min;
this.setOutputData(0, this._last_v );
},
onDrawBackground: function(ctx)
{
//show the current value
if(this._last_v)
this.outputs[0].label = this._last_v.toFixed(3);
else
this.outputs[0].label = "?";
}
});
LiteGraph.registerNodeType("math/clamp",{
title: "Clamp",
desc: "Clamp number between min and max",
inputs: [["in","number"]],
outputs: [["out","number"]],
size: [60,20],
properties: {min:0,max:1},
onExecute: function()
{
var v = this.getInputData(0);
if(v == null) return;
v = Math.max(this.properties.min,v);
v = Math.min(this.properties.max,v);
this.setOutputData(0, v );
}
});
LiteGraph.registerNodeType("math/abs",{
title: "Abs",
desc: "Absolute",
inputs: [["in","number"]],
outputs: [["out","number"]],
size: [60,20],
onExecute: function()
{
var v = this.getInputData(0);
if(v == null) return;
this.setOutputData(0, Math.abs(v) );
}
});
LiteGraph.registerNodeType("math/floor",{
title: "Floor",
desc: "Floor number to remove fractional part",
inputs: [["in","number"]],
outputs: [["out","number"]],
size: [60,20],
onExecute: function()
{
var v = this.getInputData(0);
if(v == null) return;
this.setOutputData(0, v|1 );
}
});
LiteGraph.registerNodeType("math/frac",{
title: "Frac",
desc: "Returns fractional part",
inputs: [["in","number"]],
outputs: [["out","number"]],
size: [60,20],
onExecute: function()
{
var v = this.getInputData(0);
if(v == null) return;
this.setOutputData(0, v%1 );
}
});
LiteGraph.registerNodeType("basic/watch", {
title: "Watch",
desc: "Show value",
size: [60,20],
inputs: [["value",0,{label:""}]],
outputs: [["value",0,{label:""}]],
properties: {value:""},
onExecute: function()
{
this.properties.value = this.getInputData(0);
this.setOutputData(0, this.properties.value);
},
onDrawBackground: function(ctx)
{
//show the current value
if(this.inputs[0] && this.properties["value"] != null)
{
if (this.properties["value"].constructor === Number )
this.inputs[0].label = this.properties["value"].toFixed(3);
else
this.inputs[0].label = this.properties["value"];
}
}
});
LiteGraph.registerNodeType("math/scale",{
title: "Scale",
desc: "1 - value",
inputs: [["value","number",{label:""}]],
outputs: [["value","number",{label:""}]],
size:[70,20],
properties: {"factor":1},
onExecute: function()
{
var value = this.getInputData(0);
if(value != null)
this.setOutputData(0, value * this.properties.factor );
}
});
LiteGraph.registerNodeType("math/operation",{
title: "Operation",
desc: "Easy math operators",
inputs: [["A","number"],["B","number"]],
outputs: [["A+B","number"]],
size: [80,20],
//optional_inputs: [["start","number"]],
properties: {A:1.0, B:1.0},
setValue: function(v)
{
if( typeof(v) == "string") v = parseFloat(v);
this.properties["value"] = v;
this.setDirtyCanvas(true);
},
onExecute: function()
{
var A = this.getInputData(0);
var B = this.getInputData(1);
if(A!=null)
this.properties["A"] = A;
else
A = this.properties["A"];
if(B!=null)
this.properties["B"] = B;
else
B = this.properties["B"];
for(var i = 0, l = this.outputs.length; i < l; ++i)
{
var output = this.outputs[i];
if(!output.links || !output.links.length)
continue;
switch( output.name )
{
case "A+B": value = A+B; break;
case "A-B": value = A-B; break;
case "A*B": value = A*B; break;
case "A/B": value = A/B; break;
}
this.setOutputData(i, value );
}
},
onGetOutputs: function()
{
return [["A-B","number"],["A*B","number"],["A/B","number"]];
}
});
LiteGraph.registerNodeType("math/compare",{
title: "Compare",
desc: "compares between two values",
inputs: [["A","number"],["B","number"]],
outputs: [["A==B","number"],["A!=B","number"]],
properties:{A:0,B:0},
onExecute: function()
{
var A = this.getInputData(0);
var B = this.getInputData(1);
if(A!=null)
this.properties["A"] = A;
else
A = this.properties["A"];
if(B!=null)
this.properties["B"] = B;
else
B = this.properties["B"];
for(var i = 0, l = this.outputs.length; i < l; ++i)
{
var output = this.outputs[i];
if(!output.links || !output.links.length)
continue;
switch( output.name )
{
case "A==B": value = A==B; break;
case "A!=B": value = A!=B; break;
case "A>B": value = A>B; break;
case "A<B": value = A<B; break;
case "A<=B": value = A<=B; break;
case "A>=B": value = A>=B; break;
}
this.setOutputData(i, value );
}
},
onGetOutputs: function()
{
return [["A==B","number"],["A!=B","number"],["A>B","number"],["A<B","number"],["A>=B","number"],["A<=B","number"]];
}
});
if(window.math) //math library for safe math operations without eval
LiteGraph.registerNodeType("math/formula",{
title: "Formula",
desc: "Compute safe formula",
inputs: [["x","number"],["y","number"]],
outputs: [["","number"]],
properties: {x:1.0, y:1.0, formula:"x+y"},
onExecute: function()
{
var x = this.getInputData(0);
var y = this.getInputData(1);
if(x != null)
this.properties["x"] = x;
else
x = this.properties["x"];
if(y!=null)
this.properties["y"] = y;
else
y = this.properties["y"];
var f = this.properties["formula"];
var value = math.eval(f,{x:x,y:y,T: this.graph.globaltime });
this.setOutputData(0, value );
},
onDrawBackground: function()
{
var f = this.properties["formula"];
this.outputs[0].label = f;
},
onGetOutputs: function()
{
return [["A-B","number"],["A*B","number"],["A/B","number"]];
}
});
LiteGraph.registerNodeType("math/trigonometry",{
title: "Trigonometry",
desc: "Sin Cos Tan",
bgImageUrl: "nodes/imgs/icon-sin.png",
inputs: [["v","number"]],
outputs: [["sin","number"]],
properties: {amplitude:1.0},
size:[100,20],
onExecute: function()
{
var v = this.getInputData(0);
var amp = this.properties["amplitude"];
for(var i = 0, l = this.outputs.length; i < l; ++i)
{
var output = this.outputs[i];
switch( output.name )
{
case "sin": value = Math.sin(v); break;
case "cos": value = Math.cos(v); break;
case "tan": value = Math.tan(v); break;
case "asin": value = Math.asin(v); break;
case "acos": value = Math.acos(v); break;
case "atan": value = Math.atan(v); break;
}
this.setOutputData(i, amp * value );
}
},
onGetOutputs: function()
{
return [["sin","number"],["cos","number"],["tan","number"],["asin","number"],["acos","number"],["atan","number"]];
}
});
//if glMatrix is installed...
if(window.glMatrix)
{
LiteGraph.registerNodeType("math3d/vec3-to-xyz",{
title: "Vec3->XYZ",
desc: "vector 3 to components",
inputs: [["vec3","vec3"]],
outputs: [["x","number"],["y","number"],["z","number"]],
onExecute: function()
{
var v = this.getInputData(0);
if(v == null) return;
this.setOutputData( 0, v[0] );
this.setOutputData( 1, v[1] );
this.setOutputData( 2, v[2] );
}
});
LiteGraph.registerNodeType("math3d/xyz-to-vec3",{
title: "XYZ->Vec3",
desc: "components to vector3",
inputs: [["x","number"],["y","number"],["z","number"]],
outputs: [["vec3","vec3"]],
onExecute: function()
{
var x = this.getInputData(0);
if(x == null) x = 0;
var y = this.getInputData(1);
if(y == null) y = 0;
var z = this.getInputData(2);
if(z == null) z = 0;
this.setOutputData( 0, vec3.fromValues(x,y,z) );
}
});
LiteGraph.registerNodeType("math3d/rotation",{
title: "Rotation",
desc: "rotation quaternion",
inputs: [["degrees","number"],["axis","vec3"]],
outputs: [["quat","quat"]],
properties: {angle:90.0, axis:[0,1,0]},
onExecute: function()
{
var angle = this.getInputData(0);
if(angle == null) angle = this.properties.angle;
var axis = this.getInputData(1);
if(axis == null) axis = this.properties.axis;
var R = quat.setAxisAngle(quat.create(), axis, angle * 0.0174532925 );
this.setOutputData( 0, R );
}
});
LiteGraph.registerNodeType("math3d/rotate_vec3",{
title: "Rot. Vec3",
desc: "rotate a point",
inputs: [["vec3","vec3"],["quat","quat"]],
outputs: [["result","vec3"]],
properties: {vec:[0,0,1]},
onExecute: function()
{
var vec = this.getInputData(0);
if(vec == null) vec = this.properties.vec;
var quat = this.getInputData(1);
if(quat == null)
this.setOutputData(vec);
else
this.setOutputData( 0, vec3.transformQuat( vec3.create(), vec, quat ) );
}
});
LiteGraph.registerNodeType("math3d/mult-quat",{
title: "Mult. Quat",
desc: "rotate quaternion",
inputs: [["A","quat"],["B","quat"]],
outputs: [["A*B","quat"]],
onExecute: function()
{
var A = this.getInputData(0);
if(A == null) return;
var B = this.getInputData(1);
if(B == null) return;
var R = quat.multiply(quat.create(), A,B);
this.setOutputData( 0, R );
}
});
} //glMatrix
/*
LiteGraph.registerNodeType("math/sinusoid",{
title: "Sin",
desc: "Sinusoidal value generator",
bgImageUrl: "nodes/imgs/icon-sin.png",
inputs: [["f",'number'],["q",'number'],["a",'number'],["t",'number']],
outputs: [["",'number']],
properties: {amplitude:1.0, freq: 1, phase:0},
onExecute: function()
{
var f = this.getInputData(0);
if(f != null)
this.properties["freq"] = f;
var q = this.getInputData(1);
if(q != null)
this.properties["phase"] = q;
var a = this.getInputData(2);
if(a != null)
this.properties["amplitude"] = a;
var t = this.graph.getFixedTime();
if(this.getInputData(3) != null)
t = this.getInputData(3);
// t = t/(2*Math.PI); t = (t-Math.floor(t))*(2*Math.PI);
var v = this.properties["amplitude"] * Math.sin((2*Math.PI) * t * this.properties["freq"] + this.properties["phase"]);
this.setOutputData(0, v );
},
onDragBackground: function(ctx)
{
this.boxcolor = colorToString(v > 0 ? [0.5,0.8,1,0.5] : [0,0,0,0.5]);
this.setDirtyCanvas(true);
},
});
*/
/*
LiteGraph.registerNodeType("basic/number",{
title: "Number",
desc: "Fixed number output",
outputs: [["","number"]],
color: "#66A",
bgcolor: "#336",
widgets: [{name:"value",text:"Value",type:"input",property:"value"}],
properties: {value:1.0},
setValue: function(v)
{
if( typeof(v) == "string") v = parseFloat(v);
this.properties["value"] = v;
this.setDirtyCanvas(true);
},
onExecute: function()
{
this.outputs[0].name = this.properties["value"].toString();
this.setOutputData(0, this.properties["value"]);
},
onWidget: function(e,widget)
{
if(widget.name == "value")
this.setValue(widget.value);
}
});
LiteGraph.registerNodeType("basic/string",{
title: "String",
desc: "Fixed string output",
outputs: [["","string"]],
color: "#66A",
bgcolor: "#336",
widgets: [{name:"value",text:"Value",type:"input"}],
properties: {value:"..."},
setValue: function(v)
{
this.properties["value"] = v;
this.setDirtyCanvas(true);
},
onExecute: function()
{
this.outputs[0].name = this.properties["value"].toString();
this.setOutputData(0, this.properties["value"]);
},
onWidget: function(e,widget)
{
if(widget.name == "value")
this.setValue(widget.value);
}
});
LiteGraph.registerNodeType("basic/trigger",{
title: "Trigger",
desc: "Triggers node action",
inputs: [["!0","number"]],
outputs: [["M","node"]],
properties: {triggerName:null},
onExecute: function()
{
if( this.getInputData(0) )
{
var m = this.getOutputNode(0);
if(m && m.onTrigger)
m.onTrigger();
if(m && this.properties.triggerName && typeof(m[this.properties.triggerName]) == "function")
m[this.properties.triggerName].call(m);
}
}
});
LiteGraph.registerNodeType("basic/switch",{
title: "Switch",
desc: "Switch between two inputs",
inputs: [["i","number"],["A",0],["B",0]],
outputs: [["",0]],
onExecute: function()
{
var f = this.getInputData(0);
if(f)
{
f = Math.round(f)+1;
if(f < 1) f = 1;
if(f > 2) f = 2;
this.setOutputData(0, this.getInputData(f) );
}
else
this.setOutputData(0, null);
}
});
// System vars *********************************
LiteGraph.registerNodeType("session/info",{
title: "Time",
desc: "Seconds since start",
outputs: [["secs",'number']],
properties: {scale:1.0},
onExecute: function()
{
this.setOutputData(0, this.session.getTime() * this.properties.scale);
}
});
LiteGraph.registerNodeType("system/fixedtime",{
title: "F.Time",
desc: "Constant time value",
outputs: [["secs",'number']],
properties: {scale:1.0},
onExecute: function()
{
this.setOutputData(0, this.session.getFixedTime() * this.properties.scale);
}
});
LiteGraph.registerNodeType("system/elapsedtime",{
title: "Elapsed",
desc: "Seconds elapsed since last execution",
outputs: [["secs",'number']],
properties: {scale:1.0},
onExecute: function()
{
this.setOutputData(0, this.session.getElapsedTime() * this.properties.scale);
}
});
LiteGraph.registerNodeType("system/iterations",{
title: "Iterations",
desc: "Number of iterations (executions)",
outputs: [["",'number']],
onExecute: function()
{
this.setOutputData(0, this.session.iterations );
}
});
LiteGraph.registerNodeType("system/trace",{
desc: "Outputs input to browser's console",
inputs: [["",0]],
onExecute: function()
{
var data = this.getInputData(0);
if(data)
trace("DATA: "+data);
}
});
/*
LiteGraph.registerNodeType("math/not",{
title: "Not",
desc: "0 -> 1 or 0 -> 1",
inputs: [["A",'number']],
outputs: [["!A",'number']],
size: [60,22],
onExecute: function()
{
var v = this.getInputData(0);
if(v != null)
this.setOutputData(0, v ? 0 : 1);
}
});
// Nodes for network in and out
LiteGraph.registerNodeType("network/general/network_input",{
title: "N.Input",
desc: "Network Input",
outputs: [["",0]],
color: "#00ff96",
bgcolor: "#004327",
setValue: function(v)
{
this.value = v;
},
onExecute: function()
{
this.setOutputData(0, this.value);
}
});
LiteGraph.registerNodeType("network/general/network_output",{
title: "N.Output",
desc: "Network output",
inputs: [["",0]],
color: "#a8ff00",
bgcolor: "#293e00",
properties: {value:null},
getValue: function()
{
return this.value;
},
onExecute: function()
{
this.value = this.getOutputData(0);
}
});
LiteGraph.registerNodeType("network/network_trigger",{
title: "N.Trigger",
desc: "Network input trigger",
outputs: [["",0]],
color: "#ff9000",
bgcolor: "#522e00",
onTrigger: function(v)
{
this.triggerOutput(0,v);
},
});
LiteGraph.registerNodeType("network/network_callback",{
title: "N.Callback",
desc: "Network callback output.",
outputs: [["",0]],
color: "#6A6",
bgcolor: "#363",
setTrigger: function(func)
{
this.callback = func;
},
onTrigger: function(v)
{
if(this.callback)
this.callback(v);
},
});
*/

692
src/nodes/imagenodes.js Normal file
View File

@@ -0,0 +1,692 @@
LiteGraph.registerNodeType("color/palette",{
title: "Palette",
desc: "Generates a color",
inputs: [["f","number"]],
outputs: [["Color","color"]],
properties: {colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"},
onExecute: function()
{
var c = [];
if (this.properties.colorA != null)
c.push( hex2num( this.properties.colorA ) );
if (this.properties.colorB != null)
c.push( hex2num( this.properties.colorB ) );
if (this.properties.colorC != null)
c.push( hex2num( this.properties.colorC ) );
if (this.properties.colorD != null)
c.push( hex2num( this.properties.colorD ) );
var f = this.getInputData(0);
if(f == null) f = 0.5;
if (f > 1.0)
f = 1.0;
else if (f < 0.0)
f = 0.0;
if(c.length == 0)
return;
var result = [0,0,0];
if(f == 0)
result = c[0];
else if(f == 1)
result = c[ c.length - 1];
else
{
var pos = (c.length - 1)* f;
var c1 = c[ Math.floor(pos) ];
var c2 = c[ Math.floor(pos)+1 ];
var t = pos - Math.floor(pos);
result[0] = c1[0] * (1-t) + c2[0] * (t);
result[1] = c1[1] * (1-t) + c2[1] * (t);
result[2] = c1[2] * (1-t) + c2[2] * (t);
}
/*
c[0] = 1.0 - Math.abs( Math.sin( 0.1 * reModular.getTime() * Math.PI) );
c[1] = Math.abs( Math.sin( 0.07 * reModular.getTime() * Math.PI) );
c[2] = Math.abs( Math.sin( 0.01 * reModular.getTime() * Math.PI) );
*/
for(var i in result)
result[i] /= 255;
this.boxcolor = colorToString(result);
this.setOutputData(0, result);
}
});
LiteGraph.registerNodeType("graphics/frame", {
title: "Frame",
desc: "Frame viewerew",
inputs: [["","image"]],
size: [200,200],
widgets: [{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}],
onDrawBackground: function(ctx)
{
if(this.frame)
ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]);
},
onExecute: function()
{
this.frame = this.getInputData(0);
this.setDirtyCanvas(true);
},
onWidget: function(e,widget)
{
if(widget.name == "resize" && this.frame)
{
var width = this.frame.width;
var height = this.frame.height;
if(!width && this.frame.videoWidth != null )
{
width = this.frame.videoWidth;
height = this.frame.videoHeight;
}
if(width && height)
this.size = [width, height];
this.setDirtyCanvas(true,true);
}
else if(widget.name == "view")
this.show();
},
show: function()
{
//var str = this.canvas.toDataURL("image/png");
if(showElement && this.frame)
showElement(this.frame);
}
});
LiteGraph.registerNodeType("visualization/graph", {
desc: "Shows a graph of the inputs",
inputs: [["",0],["",0],["",0],["",0]],
size: [200,200],
properties: {min:-1,max:1,bgColor:"#000"},
onDrawBackground: function(ctx)
{
/*
ctx.save();
ctx.beginPath();
ctx.rect(2,2,this.size[0] - 4, this.size[1]-4);
ctx.clip();
//*/
var colors = ["#FFF","#FAA","#AFA","#AAF"];
if(this.properties.bgColor != null && this.properties.bgColor != "")
{
ctx.fillStyle="#000";
ctx.fillRect(2,2,this.size[0] - 4, this.size[1]-4);
}
if(this.data)
{
var min = this.properties["min"];
var max = this.properties["max"];
for(var i in this.data)
{
var data = this.data[i];
if(!data) continue;
if(this.getInputInfo(i) == null) continue;
ctx.strokeStyle = colors[i];
ctx.beginPath();
var d = data.length / this.size[0];
for(var j = 0; j < data.length; j += d)
{
var value = data[ Math.floor(j) ];
value = (value - min) / (max - min);
if (value > 1.0) value = 1.0;
else if(value < 0) value = 0;
if(j == 0)
ctx.moveTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value);
else
ctx.lineTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value);
}
ctx.stroke();
}
}
//*/
//ctx.restore();
},
onExecute: function()
{
if(!this.data) this.data = [];
for(var i in this.inputs)
{
var value = this.getInputData(i);
if(typeof(value) == "number")
{
value = value ? value : 0;
if(!this.data[i])
this.data[i] = [];
this.data[i].push(value);
if(this.data[i].length > (this.size[1] - 4))
this.data[i] = this.data[i].slice(1,this.data[i].length);
}
else
this.data[i] = value;
}
if(this.data.length)
this.setDirtyCanvas(true);
}
});
LiteGraph.registerNodeType("graphics/supergraph", {
title: "Supergraph",
desc: "Shows a nice circular graph",
inputs: [["x","number"],["y","number"],["c","color"]],
outputs: [["","image"]],
widgets: [{name:"clear_alpha",text:"Clear Alpha",type:"minibutton"},{name:"clear_color",text:"Clear color",type:"minibutton"}],
properties: {size:256,bgcolor:"#000",lineWidth:1},
bgcolor: "#000",
flags: {allow_fastrender:true},
onLoad: function()
{
this.createCanvas();
},
createCanvas: function()
{
this.canvas = document.createElement("canvas");
this.canvas.width = this.properties["size"];
this.canvas.height = this.properties["size"];
this.oldpos = null;
this.clearCanvas(true);
},
onExecute: function()
{
var x = this.getInputData(0);
var y = this.getInputData(1);
var c = this.getInputData(2);
if(x == null && y == null) return;
if(!x) x = 0;
if(!y) y = 0;
x*= 0.95;
y*= 0.95;
var size = this.properties["size"];
if(size != this.canvas.width || size != this.canvas.height)
this.createCanvas();
if (!this.oldpos)
{
this.oldpos = [ (x * 0.5 + 0.5) * size, (y*0.5 + 0.5) * size];
return;
}
var ctx = this.canvas.getContext("2d");
if(c == null)
c = "rgba(255,255,255,0.5)";
else if(typeof(c) == "object") //array
c = colorToString(c);
//stroke line
ctx.strokeStyle = c;
ctx.beginPath();
ctx.moveTo( this.oldpos[0], this.oldpos[1] );
this.oldpos = [ (x * 0.5 + 0.5) * size, (y*0.5 + 0.5) * size];
ctx.lineTo( this.oldpos[0], this.oldpos[1] );
ctx.stroke();
this.canvas.dirty = true;
this.setOutputData(0,this.canvas);
},
clearCanvas: function(alpha)
{
var ctx = this.canvas.getContext("2d");
if(alpha)
{
ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
this.trace("Clearing alpha");
}
else
{
ctx.fillStyle = this.properties["bgcolor"];
ctx.fillRect(0,0,this.canvas.width,this.canvas.height);
}
},
onWidget: function(e,widget)
{
if(widget.name == "clear_color")
{
this.clearCanvas(false);
}
else if(widget.name == "clear_alpha")
{
this.clearCanvas(true);
}
},
onPropertyChange: function(name,value)
{
if(name == "size")
{
this.properties["size"] = parseInt(value);
this.createCanvas();
}
else if(name == "bgcolor")
{
this.properties["bgcolor"] = value;
this.createCanvas();
}
else if(name == "lineWidth")
{
this.properties["lineWidth"] = parseInt(value);
this.canvas.getContext("2d").lineWidth = this.properties["lineWidth"];
}
else
return false;
return true;
}
});
LiteGraph.registerNodeType("graphics/imagefade", {
title: "Image fade",
desc: "Fades between images",
inputs: [["img1","image"],["img2","image"],["fade","number"]],
outputs: [["","image"]],
properties: {fade:0.5,width:512,height:512},
widgets: [{name:"resizeA",text:"Resize to A",type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}],
onLoad: function()
{
this.createCanvas();
var ctx = this.canvas.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect(0,0,this.properties["width"],this.properties["height"]);
},
createCanvas: function()
{
this.canvas = document.createElement("canvas");
this.canvas.width = this.properties["width"];
this.canvas.height = this.properties["height"];
},
onExecute: function()
{
var ctx = this.canvas.getContext("2d");
this.canvas.width = this.canvas.width;
var A = this.getInputData(0);
if (A != null)
{
ctx.drawImage(A,0,0,this.canvas.width, this.canvas.height);
}
var fade = this.getInputData(2);
if(fade == null)
fade = this.properties["fade"];
else
this.properties["fade"] = fade;
ctx.globalAlpha = fade;
var B = this.getInputData(1);
if (B != null)
{
ctx.drawImage(B,0,0,this.canvas.width, this.canvas.height);
}
ctx.globalAlpha = 1.0;
this.setOutputData(0,this.canvas);
this.setDirtyCanvas(true);
}
});
LiteGraph.registerNodeType("graphics/image", {
title: "Image",
desc: "Image loader",
inputs: [],
outputs: [["frame","image"]],
properties: {"url":""},
widgets: [{name:"load",text:"Load",type:"button"}],
onLoad: function()
{
if(this.properties["url"] != "" && this.img == null)
{
this.loadImage(this.properties["url"]);
}
},
onStart: function()
{
},
onExecute: function()
{
if(!this.img)
this.boxcolor = "#000";
if(this.img && this.img.width)
this.setOutputData(0,this.img);
else
this.setOutputData(0,null);
if(this.img.dirty)
this.img.dirty = false;
},
onPropertyChange: function(name,value)
{
this.properties[name] = value;
if (name == "url" && value != "")
this.loadImage(value);
return true;
},
loadImage: function(url)
{
if(url == "")
{
this.img = null;
return;
}
this.trace("loading image...");
this.img = document.createElement("img");
this.img.src = "miniproxy.php?url=" + url;
this.boxcolor = "#F95";
var that = this;
this.img.onload = function()
{
that.trace("Image loaded, size: " + that.img.width + "x" + that.img.height );
this.dirty = true;
that.boxcolor = "#9F9";
that.setDirtyCanvas(true);
}
},
onWidget: function(e,widget)
{
if(widget.name == "load")
{
this.loadImage(this.properties["url"]);
}
}
});
LiteGraph.registerNodeType("graphics/cropImage", {
title: "Crop",
desc: "Crop Image",
inputs: [["","image"]],
outputs: [["","image"]],
properties: {width:256,height:256,x:0,y:0,scale:1.0 },
size: [50,20],
onLoad: function()
{
this.createCanvas();
},
createCanvas: function()
{
this.canvas = document.createElement("canvas");
this.canvas.width = this.properties["width"];
this.canvas.height = this.properties["height"];
},
onExecute: function()
{
var input = this.getInputData(0);
if(!input) return;
if(input.width)
{
var ctx = this.canvas.getContext("2d");
ctx.drawImage(input, -this.properties["x"],-this.properties["y"], input.width * this.properties["scale"], input.height * this.properties["scale"]);
this.setOutputData(0,this.canvas);
}
else
this.setOutputData(0,null);
},
onPropertyChange: function(name,value)
{
this.properties[name] = value;
if(name == "scale")
{
this.properties[name] = parseFloat(value);
if(this.properties[name] == 0)
{
this.trace("Error in scale");
this.properties[name] = 1.0;
}
}
else
this.properties[name] = parseInt(value);
this.createCanvas();
return true;
}
});
LiteGraph.registerNodeType("graphics/video", {
title: "Video",
desc: "Video playback",
inputs: [["t","number"]],
outputs: [["frame","image"],["t","number"],["d","number"]],
properties: {"url":""},
widgets: [{name:"play",text:"PLAY",type:"minibutton"},{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}],
onClick: function(e)
{
if(!this.video) return;
//press play
if( distance( [e.canvasX,e.canvasY], [ this.pos[0] + 55, this.pos[1] + 40] ) < 20 )
{
this.play();
return true;
}
},
onKeyDown: function(e)
{
if(e.keyCode == 32)
this.playPause();
},
onLoad: function()
{
if(this.properties.url != "")
this.loadVideo(this.properties.url);
},
play: function()
{
if(this.video)
{
this.trace("Video playing");
this.video.play();
}
},
playPause: function()
{
if(this.video)
{
if(this.video.paused)
this.play();
else
this.pause();
}
},
stop: function()
{
if(this.video)
{
this.trace("Video stopped");
this.video.pause();
this.video.currentTime = 0;
}
},
pause: function()
{
if(this.video)
{
this.trace("Video paused");
this.video.pause();
}
},
onExecute: function()
{
if(!this.video)
return;
var t = this.getInputData(0);
if(t && t >= 0 && t <= 1.0)
{
this.video.currentTime = t * this.video.duration;
this.video.pause();
}
this.video.dirty = true;
this.setOutputData(0,this.video);
this.setOutputData(1,this.video.currentTime);
this.setOutputData(2,this.video.duration);
this.setDirtyCanvas(true);
},
onStart: function()
{
//this.play();
},
onStop: function()
{
this.pause();
},
loadVideo: function(url)
{
this.video = document.createElement("video");
if(url)
this.video.src = url;
else
{
this.video.src = "modules/data/video.webm";
this.properties.url = this.video.src;
}
this.video.type = "type=video/mp4";
//this.video.loop = true; //not work in FF
this.video.muted = true;
this.video.autoplay = false;
//if(reModular.status == "running") this.play();
var that = this;
this.video.addEventListener("loadedmetadata",function(e) {
//onload
that.trace("Duration: " + that.video.duration + " seconds");
that.trace("Size: " + that.video.videoWidth + "," + that.video.videoHeight);
that.setDirtyCanvas(true);
this.width = this.videoWidth;
this.height = this.videoHeight;
});
this.video.addEventListener("progress",function(e) {
//onload
//that.trace("loading...");
});
this.video.addEventListener("error",function(e) {
that.trace("Error loading video: " + this.src);
if (this.error) {
switch (this.error.code) {
case this.error.MEDIA_ERR_ABORTED:
that.trace("You stopped the video.");
break;
case this.error.MEDIA_ERR_NETWORK:
that.trace("Network error - please try again later.");
break;
case this.error.MEDIA_ERR_DECODE:
that.trace("Video is broken..");
break;
case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
that.trace("Sorry, your browser can't play this video.");
break;
}
}
});
this.video.addEventListener("ended",function(e) {
that.trace("Ended.");
this.play();
});
//$("body").append(this.video);
},
onPropertyChange: function(name,value)
{
this.properties[name] = value;
if (name == "url" && value != "")
this.loadVideo(value);
return true;
},
onWidget: function(e,widget)
{
if(widget.name == "demo")
{
this.loadVideo();
}
else if(widget.name == "play")
{
if(this.video)
this.playPause();
}
if(widget.name == "stop")
{
this.stop();
}
else if(widget.name == "mute")
{
if(this.video)
this.video.muted = !this.video.muted;
}
}
});

685
src/nodes/uinodes.js Normal file
View File

@@ -0,0 +1,685 @@
//widgets
LiteGraph.registerNodeType("widget/knob",{
title: "Knob",
desc: "Circular controller",
size: [64,84],
outputs: [["",'number']],
properties: {min:0,max:1,value:0.5,wcolor:"#7AF",size:50},
widgets: [{name:"increase",text:"+",type:"minibutton"},{name:"decrease",text:"-",type:"minibutton"}],
onInit: function()
{
this.value = (this.properties["value"] - this.properties["min"]) / (this.properties["max"] - this.properties["min"]);
this.imgbg = this.loadImage("imgs/knob_bg.png");
this.imgfg = this.loadImage("imgs/knob_fg.png");
},
onDrawImageKnob: function(ctx)
{
if(!this.imgfg || !this.imgfg.width) return;
var d = this.imgbg.width*0.5;
var scale = this.size[0] / this.imgfg.width;
ctx.save();
ctx.translate(0,20);
ctx.scale(scale,scale);
ctx.drawImage(this.imgbg,0,0);
//ctx.drawImage(this.imgfg,0,20);
ctx.translate(d,d);
ctx.rotate(this.value * (Math.PI*2) * 6/8 + Math.PI * 10/8);
//ctx.rotate(this.value * (Math.PI*2));
ctx.translate(-d,-d);
ctx.drawImage(this.imgfg,0,0);
ctx.restore();
ctx.font = "bold 16px Criticized,Tahoma";
ctx.fillStyle="rgba(100,100,100,0.8)";
ctx.textAlign = "center";
ctx.fillText(this.name.toUpperCase(), this.size[0] * 0.5, 18 );
ctx.textAlign = "left";
},
onDrawVectorKnob: function(ctx)
{
if(!this.imgfg || !this.imgfg.width) return;
//circle around
ctx.lineWidth = 1;
ctx.strokeStyle= this.mouseOver ? "#FFF" : "#AAA";
ctx.fillStyle="#000";
ctx.beginPath();
ctx.arc(this.size[0] * 0.5,this.size[1] * 0.5 + 10,this.properties.size * 0.5,0,Math.PI*2,true);
ctx.stroke();
if(this.value > 0)
{
ctx.strokeStyle=this.properties["wcolor"];
ctx.lineWidth = (this.properties.size * 0.2);
ctx.beginPath();
ctx.arc(this.size[0] * 0.5,this.size[1] * 0.5 + 10,this.properties.size * 0.35,Math.PI * -0.5 + Math.PI*2 * this.value,Math.PI * -0.5,true);
ctx.stroke();
ctx.lineWidth = 1;
}
ctx.font = (this.properties.size * 0.2) + "px Arial";
ctx.fillStyle="#AAA";
ctx.textAlign = "center";
var str = this.properties["value"];
if(typeof(str) == 'number')
str = str.toFixed(2);
ctx.fillText(str,this.size[0] * 0.5,this.size[1]*0.65);
ctx.textAlign = "left";
},
onDrawBackground: function(ctx)
{
this.onDrawImageKnob(ctx);
},
onExecute: function()
{
this.setOutputData(0, this.properties["value"] );
this.boxcolor = colorToString([this.value,this.value,this.value]);
},
onMouseDown: function(e)
{
if(!this.imgfg || !this.imgfg.width) return;
//this.center = [this.imgbg.width * 0.5, this.imgbg.height * 0.5 + 20];
//this.radius = this.imgbg.width * 0.5;
this.center = [this.size[0] * 0.5, this.size[1] * 0.5 + 20];
this.radius = this.size[0] * 0.5;
if(e.canvasY - this.pos[1] < 20 || distance([e.canvasX,e.canvasY],[this.pos[0] + this.center[0],this.pos[1] + this.center[1]]) > this.radius)
return false;
this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ];
this.captureInput(true);
/*
var tmp = this.localToScreenSpace(0,0);
this.trace(tmp[0] + "," + tmp[1]); */
return true;
},
onMouseMove: function(e)
{
if(!this.oldmouse) return;
var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ];
var v = this.value;
v -= (m[1] - this.oldmouse[1]) * 0.01;
if(v > 1.0) v = 1.0;
else if(v < 0.0) v = 0.0;
this.value = v;
this.properties["value"] = this.properties["min"] + (this.properties["max"] - this.properties["min"]) * this.value;
this.oldmouse = m;
this.setDirtyCanvas(true);
},
onMouseUp: function(e)
{
if(this.oldmouse)
{
this.oldmouse = null;
this.captureInput(false);
}
},
onMouseLeave: function(e)
{
//this.oldmouse = null;
},
onWidget: function(e,widget)
{
if(widget.name=="increase")
this.onPropertyChange("size", this.properties.size + 10);
else if(widget.name=="decrease")
this.onPropertyChange("size", this.properties.size - 10);
},
onPropertyChange: function(name,value)
{
if(name=="wcolor")
this.properties[name] = value;
else if(name=="size")
{
value = parseInt(value);
this.properties[name] = value;
this.size = [value+4,value+24];
this.setDirtyCanvas(true,true);
}
else if(name=="min" || name=="max" || name=="value")
{
this.properties[name] = parseFloat(value);
}
else
return false;
return true;
}
});
LiteGraph.registerNodeType("widget/hslider",{
title: "H.Slider",
desc: "Linear slider controller",
size: [160,26],
outputs: [["",'number']],
properties: {wcolor:"#7AF",min:0,max:1,value:0.5},
onInit: function()
{
this.value = 0.5;
this.imgfg = this.loadImage("imgs/slider_fg.png");
},
onDrawVectorial: function(ctx)
{
if(!this.imgfg || !this.imgfg.width) return;
//border
ctx.lineWidth = 1;
ctx.strokeStyle= this.mouseOver ? "#FFF" : "#AAA";
ctx.fillStyle="#000";
ctx.beginPath();
ctx.rect(2,0,this.size[0]-4,20);
ctx.stroke();
ctx.fillStyle=this.properties["wcolor"];
ctx.beginPath();
ctx.rect(2+(this.size[0]-4-20)*this.value,0, 20,20);
ctx.fill();
},
onDrawImage: function(ctx)
{
if(!this.imgfg || !this.imgfg.width) return;
//border
ctx.lineWidth = 1;
ctx.fillStyle="#000";
ctx.fillRect(2,9,this.size[0]-4,2);
ctx.strokeStyle= "#333";
ctx.beginPath();
ctx.moveTo(2,9);
ctx.lineTo(this.size[0]-4,9);
ctx.stroke();
ctx.strokeStyle= "#AAA";
ctx.beginPath();
ctx.moveTo(2,11);
ctx.lineTo(this.size[0]-4,11);
ctx.stroke();
ctx.drawImage(this.imgfg, 2+(this.size[0]-4)*this.value - this.imgfg.width*0.5,-this.imgfg.height*0.5 + 10);
},
onDrawBackground: function(ctx)
{
this.onDrawImage(ctx);
},
onExecute: function()
{
this.properties["value"] = this.properties["min"] + (this.properties["max"] - this.properties["min"]) * this.value;
this.setOutputData(0, this.properties["value"] );
this.boxcolor = colorToString([this.value,this.value,this.value]);
},
onMouseDown: function(e)
{
if(e.canvasY - this.pos[1] < 0)
return false;
this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ];
this.captureInput(true);
return true;
},
onMouseMove: function(e)
{
if(!this.oldmouse) return;
var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ];
var v = this.value;
var delta = (m[0] - this.oldmouse[0]);
v += delta / this.size[0];
if(v > 1.0) v = 1.0;
else if(v < 0.0) v = 0.0;
this.value = v;
this.oldmouse = m;
this.setDirtyCanvas(true);
},
onMouseUp: function(e)
{
this.oldmouse = null;
this.captureInput(false);
},
onMouseLeave: function(e)
{
//this.oldmouse = null;
},
onPropertyChange: function(name,value)
{
if(name=="wcolor")
this.properties[name] = value;
else
return false;
return true;
}
});
LiteGraph.registerNodeType("widget/kpad",{
title: "KPad",
desc: "bidimensional slider",
size: [200,200],
outputs: [["x",'number'],["y",'number']],
properties:{x:0,y:0,borderColor:"#333",bgcolorTop:"#444",bgcolorBottom:"#000",shadowSize:1, borderRadius:2},
createGradient: function(ctx)
{
this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]);
this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]);
this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]);
},
onDrawBackground: function(ctx)
{
if(!this.lineargradient)
this.createGradient(ctx);
ctx.lineWidth = 1;
ctx.strokeStyle = this.properties["borderColor"];
//ctx.fillStyle = "#ebebeb";
ctx.fillStyle = this.lineargradient;
ctx.shadowColor = "#000";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = this.properties["shadowSize"];
ctx.roundRect(0,0,this.size[0],this.size[1],this.properties["shadowSize"]);
ctx.fill();
ctx.shadowColor = "rgba(0,0,0,0)";
ctx.stroke();
ctx.fillStyle = "#A00";
ctx.fillRect(this.size[0] * this.properties["x"] - 5, this.size[1] * this.properties["y"] - 5,10,10);
},
onWidget: function(e,widget)
{
if(widget.name == "update")
{
this.lineargradient = null;
this.setDirtyCanvas(true);
}
},
onExecute: function()
{
this.setOutputData(0, this.properties["x"] );
this.setOutputData(1, this.properties["y"] );
},
onMouseDown: function(e)
{
if(e.canvasY - this.pos[1] < 0)
return false;
this.oldmouse = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ];
this.captureInput(true);
return true;
},
onMouseMove: function(e)
{
if(!this.oldmouse) return;
var m = [ e.canvasX - this.pos[0], e.canvasY - this.pos[1] ];
this.properties.x = m[0] / this.size[0];
this.properties.y = m[1] / this.size[1];
if(this.properties.x > 1.0) this.properties.x = 1.0;
else if(this.properties.x < 0.0) this.properties.x = 0.0;
if(this.properties.y > 1.0) this.properties.y = 1.0;
else if(this.properties.y < 0.0) this.properties.y = 0.0;
this.oldmouse = m;
this.setDirtyCanvas(true);
},
onMouseUp: function(e)
{
if(this.oldmouse)
{
this.oldmouse = null;
this.captureInput(false);
}
},
onMouseLeave: function(e)
{
//this.oldmouse = null;
}
});
LiteGraph.registerNodeType("widget/button", {
title: "Button",
desc: "A send command button",
widgets: [{name:"test",text:"Test Button",type:"button"}],
size: [100,40],
properties:{text:"clickme",command:"",color:"#7AF",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",fontsize:"16"},
outputs:[["M","module"]],
createGradient: function(ctx)
{
this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]);
this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]);
this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]);
},
drawVectorShape: function(ctx)
{
ctx.fillStyle = this.mouseOver ? this.properties["color"] : "#AAA";
if(this.clicking)
ctx.fillStyle = "#FFF";
ctx.strokeStyle = "#AAA";
ctx.roundRect(5,5,this.size[0] - 10,this.size[1] - 10,4);
ctx.stroke();
if(this.mouseOver)
ctx.fill();
//ctx.fillRect(5,20,this.size[0] - 10,this.size[1] - 30);
ctx.fillStyle = this.mouseOver ? "#000" : "#AAA";
ctx.font = "bold " + this.properties["fontsize"] + "px Criticized,Tahoma";
ctx.textAlign = "center";
ctx.fillText(this.properties["text"],this.size[0]*0.5,this.size[1]*0.5 + 0.5*parseInt(this.properties["fontsize"]));
ctx.textAlign = "left";
},
drawBevelShape: function(ctx)
{
ctx.shadowColor = "#000";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = this.properties["shadowSize"];
if(!this.lineargradient)
this.createGradient(ctx);
ctx.fillStyle = this.mouseOver ? this.properties["color"] : this.lineargradient;
if(this.clicking)
ctx.fillStyle = "#444";
ctx.strokeStyle = "#FFF";
ctx.roundRect(5,5,this.size[0] - 10,this.size[1] - 10,4);
ctx.fill();
ctx.shadowColor = "rgba(0,0,0,0)";
ctx.stroke();
ctx.fillStyle = this.mouseOver ? "#000" : "#444";
ctx.font = "bold " + this.properties["fontsize"] + "px Century Gothic";
ctx.textAlign = "center";
ctx.fillText(this.properties["text"],this.size[0]*0.5,this.size[1]*0.5 + 0.40*parseInt(this.properties["fontsize"]));
ctx.textAlign = "left";
},
onDrawBackground: function(ctx)
{
this.drawBevelShape(ctx);
},
clickButton: function()
{
var module = this.getOutputModule(0);
if(this.properties["command"] && this.properties["command"] != "")
{
if (! module.executeAction(this.properties["command"]) )
this.trace("Error executing action in other module");
}
else if(module && module.onTrigger)
{
module.onTrigger();
}
},
onMouseDown: function(e)
{
if(e.canvasY - this.pos[1] < 2)
return false;
this.clickButton();
this.clicking = true;
return true;
},
onMouseUp: function(e)
{
this.clicking = false;
},
onExecute: function()
{
},
onWidget: function(e,widget)
{
if(widget.name == "test")
{
this.clickButton();
}
},
onPropertyChange: function(name,value)
{
this.properties[name] = value;
return true;
}
});
LiteGraph.registerNodeType("widget/progress",{
title: "Progress",
desc: "Shows data in linear progress",
size: [160,26],
inputs: [["",'number']],
properties: {min:0,max:1,value:0,wcolor:"#AAF"},
onExecute: function()
{
var v = this.getInputData(0);
if( v != undefined )
this.properties["value"] = v;
},
onDrawBackground: function(ctx)
{
//border
ctx.lineWidth = 1;
ctx.fillStyle=this.properties.wcolor;
var v = (this.properties.value - this.properties.min) / (this.properties.max - this.properties.min);
v = Math.min(1,v);
v = Math.max(0,v);
ctx.fillRect(2,2,(this.size[0]-4)*v,this.size[1]-4);
}
});
LiteGraph.registerNodeType("widget/text", {
title: "Text",
desc: "Shows the input value",
widgets: [{name:"resize",text:"Resize box",type:"button"},{name:"led_text",text:"LED",type:"minibutton"},{name:"normal_text",text:"Normal",type:"minibutton"}],
inputs: [["",0]],
properties:{value:"...",font:"Arial", fontsize:18, color:"#AAA", align:"left", glowSize:0, decimals:1},
onDrawBackground: function(ctx)
{
//ctx.fillStyle="#000";
//ctx.fillRect(0,0,100,60);
ctx.fillStyle = this.properties["color"];
var v = this.properties["value"];
if(this.properties["glowSize"])
{
ctx.shadowColor = this.properties["color"];
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = this.properties["glowSize"];
}
else
ctx.shadowColor = "transparent";
var fontsize = this.properties["fontsize"];
ctx.textAlign = this.properties["align"];
ctx.font = fontsize.toString() + "px " + this.properties["font"];
this.str = typeof(v) == 'number' ? v.toFixed(this.properties["decimals"]) : v;
if( typeof(this.str) == 'string')
{
var lines = this.str.split("\\n");
for(var i in lines)
ctx.fillText(lines[i],this.properties["align"] == "left" ? 15 : this.size[0] - 15, fontsize * -0.15 + fontsize * (parseInt(i)+1) );
}
ctx.shadowColor = "transparent";
this.last_ctx = ctx;
ctx.textAlign = "left";
},
onExecute: function()
{
var v = this.getInputData(0);
if(v != null)
this.properties["value"] = v;
else
this.properties["value"] = "";
this.setDirtyCanvas(true);
},
resize: function()
{
if(!this.last_ctx) return;
var lines = this.str.split("\\n");
this.last_ctx.font = this.properties["fontsize"] + "px " + this.properties["font"];
var max = 0;
for(var i in lines)
{
var w = this.last_ctx.measureText(lines[i]).width;
if(max < w) max = w;
}
this.size[0] = max + 20;
this.size[1] = 4 + lines.length * this.properties["fontsize"];
this.setDirtyCanvas(true);
},
onWidget: function(e,widget)
{
if(widget.name == "resize")
this.resize();
else if (widget.name == "led_text")
{
this.properties["font"] = "Digital";
this.properties["glowSize"] = 4;
this.setDirtyCanvas(true);
}
else if (widget.name == "normal_text")
{
this.properties["font"] = "Arial";
this.setDirtyCanvas(true);
}
},
onPropertyChange: function(name,value)
{
this.properties[name] = value;
this.str = typeof(value) == 'number' ? value.toFixed(3) : value;
//this.resize();
return true;
}
});
LiteGraph.registerNodeType("widget/panel", {
title: "Panel",
desc: "Non interactive panel",
widgets: [{name:"update",text:"Update",type:"button"}],
size: [200,100],
properties:{borderColor:"#ffffff",bgcolorTop:"#f0f0f0",bgcolorBottom:"#e0e0e0",shadowSize:2, borderRadius:3},
createGradient: function(ctx)
{
if(this.properties["bgcolorTop"] == "" || this.properties["bgcolorBottom"] == "")
{
this.lineargradient = 0;
return;
}
this.lineargradient = ctx.createLinearGradient(0,0,0,this.size[1]);
this.lineargradient.addColorStop(0,this.properties["bgcolorTop"]);
this.lineargradient.addColorStop(1,this.properties["bgcolorBottom"]);
},
onDrawBackground: function(ctx)
{
if(this.lineargradient == null)
this.createGradient(ctx);
if(!this.lineargradient)
return;
ctx.lineWidth = 1;
ctx.strokeStyle = this.properties["borderColor"];
//ctx.fillStyle = "#ebebeb";
ctx.fillStyle = this.lineargradient;
if(this.properties["shadowSize"])
{
ctx.shadowColor = "#000";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = this.properties["shadowSize"];
}
else
ctx.shadowColor = "transparent";
ctx.roundRect(0,0,this.size[0]-1,this.size[1]-1,this.properties["shadowSize"]);
ctx.fill();
ctx.shadowColor = "transparent";
ctx.stroke();
},
onWidget: function(e,widget)
{
if(widget.name == "update")
{
this.lineargradient = null;
this.setDirtyCanvas(true);
}
}
});

13
style.css Normal file
View File

@@ -0,0 +1,13 @@
body { background-color: #DDD; }
h1 {
margin: 0;
}
#wrap {
margin: auto;
width: 800px;
min-height: 400px;
padding: 1em;
background-color: white;
box-shadow: 0 0 2px #333;
}

2
utils/build.sh Executable file
View File

@@ -0,0 +1,2 @@
python builder.py deploy_files.txt -o ../build/litegraph.min.js -o2 ../build/litegraph.js
chmod a+rw ../build/*

91
utils/builder.py Normal file
View File

@@ -0,0 +1,91 @@
#!/usr/bin/python
import re, os, sys, time, tempfile, shutil
import argparse
from datetime import date
compiler_path = "/usr/local/bin/compiler.jar"
root_path = "./"
#arguments
parser = argparse.ArgumentParser(description='Deploy a JS app creating a minifyed version checking for errors.')
parser.add_argument('input_file',
help='the path to the file with a list of all the JS files')
parser.add_argument('-o', dest='output_file', action='store',
default=None,
help='Specify an output for the minifyed version')
parser.add_argument('-o2', dest='fullcode_output_file', action='store',
default=None,
help='Specify an output for the full code version')
#parser.add_argument('output_file',
# help='the filename where to save the min version')
parser.add_argument('--all', dest='all_files', action='store_const',
const=True, default=False,
help='Compile all JS files individually first.')
parser.add_argument('--nomin', dest='no_minify', action='store_const',
const=True, default=False,
help='Do not minify the JS file')
args = parser.parse_args()
check_files_individually = args.all_files
output_file = args.output_file
fullcode_output_file = args.fullcode_output_file
no_minify = args.no_minify
root_path = "./" + os.path.dirname(args.input_file) + "/"
sys.stderr.write(" + Root folder: " + root_path + "\n")
def packJSCode(files):
f1, fullcode_path = tempfile.mkstemp() #create temporary file
data = "//packer version\n"
for filename in files:
filename = filename.strip()
if len(filename) == 0 or filename[0] == "#":
continue
sys.stderr.write(" + Processing... " + filename + " " )
src_file = root_path + filename
if os.path.exists(src_file) == False:
sys.stderr.write('\033[91m'+"JS File not found"+'\033[0m\n')
continue
data += open(src_file).read() + "\n"
if check_files_individually:
os.system("java -jar %s --js %s --js_output_file %s" % (compiler_path, src_file, "temp.js") )
sys.stderr.write('\033[92m' + "OK\n" + '\033[0m')
os.write(f1,data)
os.close(f1)
#print " + Compiling all..."
#os.system("java -jar %s --js %s --js_output_file %s" % (compiler_path, fullcode_path, output_file) )
#print " * Done"
return fullcode_path
def compileAndMinify(input_path, output_path):
print " + Compiling and minifying..."
if output_path != None:
os.system("java -jar %s --js %s --js_output_file %s" % (compiler_path, input_path, output_path) )
sys.stderr.write(" * Stored in " + output_path + "\n");
else:
os.system("java -jar %s --js %s" % (compiler_path, input_path) )
#load project info
if os.path.exists(args.input_file) == False:
sys.stderr.write("\033[91m Error, input file not found: " + args.input_file + "\033[0m\n")
exit(0)
js_files = open(args.input_file).read().splitlines()
fullcode_path = packJSCode(js_files)
if fullcode_output_file != None:
shutil.copy2(fullcode_path, fullcode_output_file)
sys.stderr.write(" * Fullcode Stored in " + fullcode_output_file + "\n");
if not no_minify:
compileAndMinify( fullcode_path, output_file )

4
utils/deploy_files.txt Normal file
View File

@@ -0,0 +1,4 @@
../src/litegraph.js
../src/nodes/basicnodes.js
../src/nodes/uinodes.js
../src/nodes/imagenodes.js

1
utils/generate_doc.sh Executable file
View File

@@ -0,0 +1 @@
yuidoc ../src -o ../doc

2
utils/pack.sh Executable file
View File

@@ -0,0 +1,2 @@
python builder.py deploy_files.txt -o ../build/litescene.min.js -o2 ../build/litescene.js --nomin
chmod a+rw ../build/*

24
utils/temp.js Normal file
View File

@@ -0,0 +1,24 @@
LiteGraph.registerNodeType("color/palette",{title:"Palette",desc:"Generates a color",inputs:[["f","number"]],outputs:[["Color","color"]],properties:{colorA:"#444444",colorB:"#44AAFF",colorC:"#44FFAA",colorD:"#FFFFFF"},onExecute:function(){var a=[];null!=this.properties.colorA&&a.push(hex2num(this.properties.colorA));null!=this.properties.colorB&&a.push(hex2num(this.properties.colorB));null!=this.properties.colorC&&a.push(hex2num(this.properties.colorC));null!=this.properties.colorD&&a.push(hex2num(this.properties.colorD));
var b=this.getInputData(0);null==b&&(b=0.5);1<b?b=1:0>b&&(b=0);if(0!=a.length){var c=[0,0,0];if(0==b)c=a[0];else if(1==b)c=a[a.length-1];else{var d=(a.length-1)*b,b=a[Math.floor(d)],a=a[Math.floor(d)+1],d=d-Math.floor(d);c[0]=b[0]*(1-d)+a[0]*d;c[1]=b[1]*(1-d)+a[1]*d;c[2]=b[2]*(1-d)+a[2]*d}for(var e in c)c[e]/=255;this.boxcolor=colorToString(c);this.setOutputData(0,c)}}});
LiteGraph.registerNodeType("graphics/frame",{title:"Frame",desc:"Frame viewerew",inputs:[["","image"]],size:[200,200],widgets:[{name:"resize",text:"Resize box",type:"button"},{name:"view",text:"View Image",type:"button"}],onDrawBackground:function(a){this.frame&&a.drawImage(this.frame,0,0,this.size[0],this.size[1])},onExecute:function(){this.frame=this.getInputData(0);this.setDirtyCanvas(!0)},onWidget:function(a,b){if("resize"==b.name&&this.frame){var c=this.frame.width,d=this.frame.height;c||null==
this.frame.videoWidth||(c=this.frame.videoWidth,d=this.frame.videoHeight);c&&d&&(this.size=[c,d]);this.setDirtyCanvas(!0,!0)}else"view"==b.name&&this.show()},show:function(){showElement&&this.frame&&showElement(this.frame)}});
LiteGraph.registerNodeType("visualization/graph",{desc:"Shows a graph of the inputs",inputs:[["",0],["",0],["",0],["",0]],size:[200,200],properties:{min:-1,max:1,bgColor:"#000"},onDrawBackground:function(a){var b=["#FFF","#FAA","#AFA","#AAF"];null!=this.properties.bgColor&&""!=this.properties.bgColor&&(a.fillStyle="#000",a.fillRect(2,2,this.size[0]-4,this.size[1]-4));if(this.data){var c=this.properties.min,d=this.properties.max,e;for(e in this.data){var h=this.data[e];if(h&&null!=this.getInputInfo(e)){a.strokeStyle=
b[e];a.beginPath();for(var k=h.length/this.size[0],g=0;g<h.length;g+=k){var f=h[Math.floor(g)],f=(f-c)/(d-c);1<f?f=1:0>f&&(f=0);0==g?a.moveTo(g/k,this.size[1]-5-(this.size[1]-10)*f):a.lineTo(g/k,this.size[1]-5-(this.size[1]-10)*f)}a.stroke()}}}},onExecute:function(){this.data||(this.data=[]);for(var a in this.inputs){var b=this.getInputData(a);"number"==typeof b?(b=b?b:0,this.data[a]||(this.data[a]=[]),this.data[a].push(b),this.data[a].length>this.size[1]-4&&(this.data[a]=this.data[a].slice(1,this.data[a].length))):
this.data[a]=b}this.data.length&&this.setDirtyCanvas(!0)}});
LiteGraph.registerNodeType("graphics/supergraph",{title:"Supergraph",desc:"Shows a nice circular graph",inputs:[["x","number"],["y","number"],["c","color"]],outputs:[["","image"]],widgets:[{name:"clear_alpha",text:"Clear Alpha",type:"minibutton"},{name:"clear_color",text:"Clear color",type:"minibutton"}],properties:{size:256,bgcolor:"#000",lineWidth:1},bgcolor:"#000",flags:{allow_fastrender:!0},onLoad:function(){this.createCanvas()},createCanvas:function(){this.canvas=document.createElement("canvas");
this.canvas.width=this.properties.size;this.canvas.height=this.properties.size;this.oldpos=null;this.clearCanvas(!0)},onExecute:function(){var a=this.getInputData(0),b=this.getInputData(1),c=this.getInputData(2);if(null!=a||null!=b){a||(a=0);b||(b=0);var a=0.95*a,b=0.95*b,d=this.properties.size;d==this.canvas.width&&d==this.canvas.height||this.createCanvas();if(this.oldpos){var e=this.canvas.getContext("2d");null==c?c="rgba(255,255,255,0.5)":"object"==typeof c&&(c=colorToString(c));e.strokeStyle=
c;e.beginPath();e.moveTo(this.oldpos[0],this.oldpos[1]);this.oldpos=[(0.5*a+0.5)*d,(0.5*b+0.5)*d];e.lineTo(this.oldpos[0],this.oldpos[1]);e.stroke();this.canvas.dirty=!0;this.setOutputData(0,this.canvas)}else this.oldpos=[(0.5*a+0.5)*d,(0.5*b+0.5)*d]}},clearCanvas:function(a){var b=this.canvas.getContext("2d");a?(b.clearRect(0,0,this.canvas.width,this.canvas.height),this.trace("Clearing alpha")):(b.fillStyle=this.properties.bgcolor,b.fillRect(0,0,this.canvas.width,this.canvas.height))},onWidget:function(a,
b){"clear_color"==b.name?this.clearCanvas(!1):"clear_alpha"==b.name&&this.clearCanvas(!0)},onPropertyChange:function(a,b){if("size"==a)this.properties.size=parseInt(b),this.createCanvas();else if("bgcolor"==a)this.properties.bgcolor=b,this.createCanvas();else if("lineWidth"==a)this.properties.lineWidth=parseInt(b),this.canvas.getContext("2d").lineWidth=this.properties.lineWidth;else return!1;return!0}});
LiteGraph.registerNodeType("graphics/imagefade",{title:"Image fade",desc:"Fades between images",inputs:[["img1","image"],["img2","image"],["fade","number"]],outputs:[["","image"]],properties:{fade:0.5,width:512,height:512},widgets:[{name:"resizeA",text:"Resize to A",type:"button"},{name:"resizeB",text:"Resize to B",type:"button"}],onLoad:function(){this.createCanvas();var a=this.canvas.getContext("2d");a.fillStyle="#000";a.fillRect(0,0,this.properties.width,this.properties.height)},createCanvas:function(){this.canvas=
document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height},onExecute:function(){var a=this.canvas.getContext("2d");this.canvas.width=this.canvas.width;var b=this.getInputData(0);null!=b&&a.drawImage(b,0,0,this.canvas.width,this.canvas.height);b=this.getInputData(2);null==b?b=this.properties.fade:this.properties.fade=b;a.globalAlpha=b;b=this.getInputData(1);null!=b&&a.drawImage(b,0,0,this.canvas.width,this.canvas.height);a.globalAlpha=1;this.setOutputData(0,
this.canvas);this.setDirtyCanvas(!0)}});
LiteGraph.registerNodeType("graphics/image",{title:"Image",desc:"Image loader",inputs:[],outputs:[["frame","image"]],properties:{url:""},widgets:[{name:"load",text:"Load",type:"button"}],onLoad:function(){""!=this.properties.url&&null==this.img&&this.loadImage(this.properties.url)},onStart:function(){},onExecute:function(){this.img||(this.boxcolor="#000");this.img&&this.img.width?this.setOutputData(0,this.img):this.setOutputData(0,null);this.img.dirty&&(this.img.dirty=!1)},onPropertyChange:function(a,
b){this.properties[a]=b;"url"==a&&""!=b&&this.loadImage(b);return!0},loadImage:function(a){if(""==a)this.img=null;else{this.trace("loading image...");this.img=document.createElement("img");this.img.src="miniproxy.php?url="+a;this.boxcolor="#F95";var b=this;this.img.onload=function(){b.trace("Image loaded, size: "+b.img.width+"x"+b.img.height);this.dirty=!0;b.boxcolor="#9F9";b.setDirtyCanvas(!0)}}},onWidget:function(a,b){"load"==b.name&&this.loadImage(this.properties.url)}});
LiteGraph.registerNodeType("graphics/cropImage",{title:"Crop",desc:"Crop Image",inputs:[["","image"]],outputs:[["","image"]],properties:{width:256,height:256,x:0,y:0,scale:1},size:[50,20],onLoad:function(){this.createCanvas()},createCanvas:function(){this.canvas=document.createElement("canvas");this.canvas.width=this.properties.width;this.canvas.height=this.properties.height},onExecute:function(){var a=this.getInputData(0);a&&(a.width?(this.canvas.getContext("2d").drawImage(a,-this.properties.x,-this.properties.y,
a.width*this.properties.scale,a.height*this.properties.scale),this.setOutputData(0,this.canvas)):this.setOutputData(0,null))},onPropertyChange:function(a,b){this.properties[a]=b;"scale"==a?(this.properties[a]=parseFloat(b),0==this.properties[a]&&(this.trace("Error in scale"),this.properties[a]=1)):this.properties[a]=parseInt(b);this.createCanvas();return!0}});
LiteGraph.registerNodeType("graphics/video",{title:"Video",desc:"Video playback",inputs:[["t","number"]],outputs:[["frame","image"],["t","number"],["d","number"]],properties:{url:""},widgets:[{name:"play",text:"PLAY",type:"minibutton"},{name:"stop",text:"STOP",type:"minibutton"},{name:"demo",text:"Demo video",type:"button"},{name:"mute",text:"Mute video",type:"button"}],onClick:function(a){if(this.video&&20>distance([a.canvasX,a.canvasY],[this.pos[0]+55,this.pos[1]+40]))return this.play(),!0},onKeyDown:function(a){32==
a.keyCode&&this.playPause()},onLoad:function(){""!=this.properties.url&&this.loadVideo(this.properties.url)},play:function(){this.video&&(this.trace("Video playing"),this.video.play())},playPause:function(){this.video&&(this.video.paused?this.play():this.pause())},stop:function(){this.video&&(this.trace("Video stopped"),this.video.pause(),this.video.currentTime=0)},pause:function(){this.video&&(this.trace("Video paused"),this.video.pause())},onExecute:function(){if(this.video){var a=this.getInputData(0);
a&&0<=a&&1>=a&&(this.video.currentTime=a*this.video.duration,this.video.pause());this.video.dirty=!0;this.setOutputData(0,this.video);this.setOutputData(1,this.video.currentTime);this.setOutputData(2,this.video.duration);this.setDirtyCanvas(!0)}},onStart:function(){},onStop:function(){this.pause()},loadVideo:function(a){this.video=document.createElement("video");a?this.video.src=a:(this.video.src="modules/data/video.webm",this.properties.url=this.video.src);this.video.type="type=video/mp4";this.video.muted=
!0;this.video.autoplay=!1;var b=this;this.video.addEventListener("loadedmetadata",function(a){b.trace("Duration: "+b.video.duration+" seconds");b.trace("Size: "+b.video.videoWidth+","+b.video.videoHeight);b.setDirtyCanvas(!0);this.width=this.videoWidth;this.height=this.videoHeight});this.video.addEventListener("progress",function(a){});this.video.addEventListener("error",function(a){b.trace("Error loading video: "+this.src);if(this.error)switch(this.error.code){case this.error.MEDIA_ERR_ABORTED:b.trace("You stopped the video.");
break;case this.error.MEDIA_ERR_NETWORK:b.trace("Network error - please try again later.");break;case this.error.MEDIA_ERR_DECODE:b.trace("Video is broken..");break;case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED:b.trace("Sorry, your browser can't play this video.")}});this.video.addEventListener("ended",function(a){b.trace("Ended.");this.play()})},onPropertyChange:function(a,b){this.properties[a]=b;"url"==a&&""!=b&&this.loadVideo(b);return!0},onWidget:function(a,b){"demo"==b.name?this.loadVideo():"play"==
b.name&&this.video&&this.playPause();"stop"==b.name?this.stop():"mute"==b.name&&this.video&&(this.video.muted=!this.video.muted)}});