From 217d35348be97691a62cc84555f33e8d61308bd3 Mon Sep 17 00:00:00 2001 From: tamat Date: Thu, 24 Apr 2014 23:11:30 +0200 Subject: [PATCH] links system changed --- build/litegraph.js | 186 ++++++++++++++++++--------------------- build/litegraph.min.js | 40 +++++---- css/litegraph-editor.css | 39 +++++++- demo/imgs/icon-load.png | Bin 0 -> 1339 bytes demo/imgs/icon-save.png | Bin 0 -> 1339 bytes demo/index.html | 47 ---------- src/litegraph-editor.js | 74 ++++++++++++---- src/litegraph.js | 186 ++++++++++++++++++--------------------- 8 files changed, 288 insertions(+), 284 deletions(-) create mode 100644 demo/imgs/icon-load.png create mode 100644 demo/imgs/icon-save.png diff --git a/build/litegraph.js b/build/litegraph.js index fe597ccbd..a8c6aacfb 100644 --- a/build/litegraph.js +++ b/build/litegraph.js @@ -25,7 +25,7 @@ var LiteGraph = { NODE_DEFAULT_BOXCOLOR: "#AEF", NODE_DEFAULT_SHAPE: "box", MAX_NUMBER_OF_NODES: 1000, //avoid infinite loops - DEFAULT_POSITION: [100,100], + DEFAULT_POSITION: [100,100],//default node position node_images_path: "", debug: false, @@ -87,45 +87,6 @@ var LiteGraph = { var node = new base_class( name ); - /* - if (base_class.prototype) //is a class - { - node = new base_class(name); - } - else - { - node = new LGraphNode(name); - node.inputs = []; - node.outputs = []; - - //add inputs and outputs - for (var i in prototype) - { - if(i == "inputs") - { - for(var j in prototype[i]) - node.addInput( prototype[i][j][0],prototype[i][j][1], prototype[i][j][2] ); - } - else if(i == "outputs") - { - for(var j in prototype[i]) - node.addOutput( prototype[i][j][0],prototype[i][j][1], prototype[i][j][2] ); - } - else - { - if( prototype[i].concat ) //array - node[i] = prototype[i].concat(); - else if (typeof(prototype[i]) == 'object') - node[i] = LiteGraph.cloneObject(prototype[i]); //slow but safe - else - node[i] = prototype[i]; - } - } - //set size - if(base_class.size) node.size = base_class.size.concat(); //save size - } - */ - node.type = type; if(!node.title) node.title = title; if(!node.flags) node.flags = {}; @@ -299,7 +260,7 @@ LGraph.prototype.clear = function() //links this.last_link_id = 0; - this.links = {}; + this.links = {}; //container with all the links //iterations this.iteration = 0; @@ -513,20 +474,22 @@ LGraph.prototype.computeExecutionOrder = function() //for every connection for(var j = 0; j < output.links.length; j++) { - var link = output.links[j]; + var link_id = output.links[j]; + var link = this.links[link_id]; + if(!link) continue; //already visited link (ignore it) - if(visited_links[ link[0] ]) + if(visited_links[ link.id ]) continue; - var target_node = this.getNodeById( link[3] ); + var target_node = this.getNodeById( link.target_id ); if(target_node == null) { - visited_links[ link[0] ] = true; + visited_links[ link.id ] = true; continue; } - visited_links[link[0]] = true; //mark as visited + visited_links[link.id] = true; //mark as visited remaining_links[target_node.id] -= 1; //reduce the number of links remaining if (remaining_links[target_node.id] == 0) S.push(target_node); //if no more links, then add to Starters array @@ -617,7 +580,7 @@ LGraph.prototype.sendActionToCanvas = function(action, params) * @param {LGraphNode} node the instance of the node */ -LGraph.prototype.add = function(node) +LGraph.prototype.add = function(node, skip_compute_order) { if(!node || (node.id != -1 && this._nodes_by_id[node.id] != null)) return; //already added @@ -645,8 +608,9 @@ LGraph.prototype.add = function(node) if(this.config.align_to_grid) node.alignToGrid(); - - this.updateExecutionOrder(); + + if(!skip_compute_order) + this.updateExecutionOrder(); if(this.onNodeAdded) this.onNodeAdded(node); @@ -928,6 +892,11 @@ LGraph.prototype.serialize = function() for (var i in this._nodes) nodes_info.push( this._nodes[i].serialize() ); + //remove data from links, we dont want to store it + for (var i in this.links) + this.links[i].data = null; + + var data = { graph: this.graph, @@ -935,6 +904,7 @@ LGraph.prototype.serialize = function() frame: this.frame, last_node_id: this.last_node_id, last_link_id: this.last_link_id, + links: LiteGraph.cloneObject( this.links ), config: this.config, nodes: nodes_info @@ -967,8 +937,8 @@ LGraph.prototype.configure = function(data, keep_old) for (var i in nodes) { var n_info = nodes[i]; //stored info - var n = LiteGraph.createNode( n_info.type, n_info.title ); - if(!n) + var node = LiteGraph.createNode( n_info.type, n_info.title ); + if(!node) { if(LiteGraph.debug) console.log("Node not found: " + n_info.type); @@ -976,10 +946,12 @@ LGraph.prototype.configure = function(data, keep_old) continue; } - n.configure(n_info); - this.add(n); + node.id = n_info.id; //id it or it will create a new id + this.add(node, true); //add before configure, otherwise configure cannot create links + node.configure(n_info); } + this.updateExecutionOrder(); this.setDirtyCanvas(true,true); return error; } @@ -1050,7 +1022,7 @@ function LGraphNode(title) } /** -* configure a node from an object +* configure a node from an object containing the serialized info * @method configure */ LGraphNode.prototype.configure = function(info) @@ -1061,39 +1033,38 @@ LGraphNode.prototype.configure = function(info) if(info[j] == null) continue; - else if( info[j].concat ) //array - this[j] = info[j].concat(); else if (typeof(info[j]) == 'object') //object this[j] = LiteGraph.cloneObject(info[j], this[j] || {} ); else //value this[j] = info[j]; } -} -/* Copy all the info from one object to this node (used for serialization) */ -LGraphNode.prototype.copyFromObject = function(info, ignore_connections) -{ - var outputs = null; - var inputs = null; - var properties = null; - var local_data = null; - - for (var j in info) + //FOR LEGACY, PLEASE REMOVE ON NEXT VERSION + for(var i in this.inputs) { - if(ignore_connections && (j == "outputs" || j == "inputs")) + var input = this.inputs[i]; + if(!input.link || !input.link.length ) continue; - - if(j == "console") continue; - - if(info[j] == null) + var link = input.link; + if(typeof(link) != "object") continue; - else if( info[j].concat ) //array - this[j] = info[j].concat(); - else if (typeof(info[j]) == 'object') //object - this[j] = LiteGraph.cloneObject(info[j]); - else //value - this[j] = info[j]; + input.link = link[0]; + this.graph.links[ link[0] ] = { id: link[0], origin_id: link[1], origin_slot: link[2], target_id: link[3], target_slot: link[4] }; } + for(var i in this.outputs) + { + var output = this.outputs[i]; + if(!output.links || output.links.length == 0) + continue; + for(var j in output.links) + { + var link = output.links[j]; + if(typeof(link) != "object") + continue; + output.links[j] = link[0]; + } + } + } /** @@ -1194,7 +1165,10 @@ LGraphNode.prototype.setOutputData = function(slot,data) if(slot > -1 && slot < this.outputs.length && this.outputs[slot] && this.outputs[slot].links != null) { for(var i = 0; i < this.outputs[slot].links.length; i++) - this.graph.links[ this.outputs[slot].links[i][0] ] = data; + { + var link_id = this.outputs[slot].links[i]; + this.graph.links[ link_id ].data = data; + } } } @@ -1208,7 +1182,7 @@ LGraphNode.prototype.getInputData = function(slot) { if(!this.inputs) return null; if(slot < this.inputs.length && this.inputs[slot].link != null) - return this.graph.links[ this.inputs[slot].link[0] ]; + return this.graph.links[ this.inputs[slot].link ].data; return null; } @@ -1280,7 +1254,7 @@ LGraphNode.prototype.getOutputNodes = function(slot) var output = this.outputs[slot]; var r = []; for(var i = 0; i < output.length; i++) - r.push( this.graph.getNodeById( output.links[i][3] )); + r.push( this.graph.getNodeById( output.links[i].target_id )); return r; } return null; @@ -1453,7 +1427,7 @@ LGraphNode.prototype.getBounding = function() */ LGraphNode.prototype.isPointInsideNode = function(x,y) { - var margin_top = this.graph.isLive() ? 0 : 20; + var margin_top = this.graph && this.graph.isLive() ? 0 : 20; if(this.flags.collapsed) { //if ( distance([x,y], [this.pos[0] + this.size[0]*0.5, this.pos[1] + this.size[1]*0.5]) < LiteGraph.NODE_COLLAPSED_RADIUS) @@ -1552,12 +1526,14 @@ LGraphNode.prototype.connect = function(slot, node, target_slot) output.type == node.inputs[target_slot].type) //same type { //info: link structure => [ 0:link_id, 1:start_node_id, 2:start_slot, 3:end_node_id, 4:end_slot ] - var link = [ this.graph.last_link_id++, this.id, slot, node.id, target_slot ]; + //var link = [ this.graph.last_link_id++, this.id, slot, node.id, target_slot ]; + var link = { id: this.graph.last_link_id++, origin_id: this.id, origin_slot: slot, target_id: node.id, target_slot: target_slot }; + this.graph.links[ link.id ] = link; //connect if( output.links == null ) output.links = []; - output.links.push(link); - node.inputs[target_slot].link = link; + output.links.push( link.id ); + node.inputs[target_slot].link = link.id; this.setDirtyCanvas(false,true); this.graph.onConnectionChange(); @@ -1600,13 +1576,15 @@ LGraphNode.prototype.disconnectOutput = function(slot, target_node) { for(var i = 0, l = output.links.length; i < l; i++) { - var link = output.links[i]; + var link_id = output.links[i]; + var link_info = this.graph.links[ link_id ]; + //is the link we are searching for... - if( link[3] == target_node.id ) + if( link_info.target_id == target_node.id ) { output.links.splice(i,1); //remove here - target_node.inputs[ link[4] ].link = null; //remove there - delete this.graph.links[link[0]]; //remove the link from the links pool + target_node.inputs[ link_info.target_slot ].link = null; //remove there + delete this.graph.links[ link_id ]; //remove the link from the links pool break; } } @@ -1615,10 +1593,12 @@ LGraphNode.prototype.disconnectOutput = function(slot, target_node) { for(var i = 0, l = output.links.length; i < l; i++) { - var link = output.links[i]; - var target_node = this.graph.getNodeById( link[3] ); + var link_id = output.links[i]; + var link_info = this.graph.links[ link_id ]; + + var target_node = this.graph.getNodeById( link_info.target_id ); if(target_node) - target_node.inputs[ link[4] ].link = null; //remove other side link + target_node.inputs[ link_info.target_slot ].link = null; //remove other side link } output.links = null; } @@ -1656,21 +1636,24 @@ LGraphNode.prototype.disconnectInput = function(slot) var input = this.inputs[slot]; if(!input) return false; - var link = this.inputs[slot].link; + var link_id = this.inputs[slot].link; this.inputs[slot].link = null; //remove other side - var node = this.graph.getNodeById( link[1] ); + var link_info = this.graph.links[ link_id ]; + var node = this.graph.getNodeById( link_info.origin_id ); if(!node) return false; - var output = node.outputs[ link[2] ]; + var output = node.outputs[ link_info.origin_slot ]; if(!output || !output.links || output.links.length == 0) return false; + //check outputs for(var i = 0, l = output.links.length; i < l; i++) { - var link = output.links[i]; - if( link[3] == this.id ) + var link_id = output.links[i]; + var link_info = this.graph.links[ link_id ]; + if( link_info.target_id == this.id ) { output.links.splice(i,1); break; @@ -3438,12 +3421,15 @@ LGraphCanvas.prototype.drawConnections = function(ctx) for(var i in node.inputs) { var input = node.inputs[i]; - if(!input || !input.link ) continue; - var link = input.link; + if(!input || input.link == null) + continue; + var link_id = input.link; + var link = this.graph.links[ link_id ]; + if(!link) continue; - var start_node = this.graph.getNodeById( link[1] ); + var start_node = this.graph.getNodeById( link.origin_id ); if(start_node == null) continue; - var start_node_slot = link[2]; + var start_node_slot = link.origin_slot; var start_node_slotpos = null; if(start_node_slot == -1) diff --git a/build/litegraph.min.js b/build/litegraph.min.js index eb3b7c41d..2e9a65eed 100644 --- a/build/litegraph.min.js +++ b/build/litegraph.min.js @@ -9,37 +9,39 @@ LGraph.prototype.start=function(a){if(this.status!=LGraph.STATUS_RUNNING){this.s 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=window.performance.now();this.globaltime=0.001*(b-this.starttime);try{for(var c=0;c=LiteGraph.MAX_NUMBER_OF_NODES)throw"LiteGraph: max number of nodes in a graph reached";if(null==a.id||-1==a.id)a.id=this.last_node_id++;a.graph=this;this._nodes.push(a);this._nodes_by_id[a.id]=a;if(a.onAdded)a.onAdded();this.config.align_to_grid&&a.alignToGrid();this.updateExecutionOrder();if(this.onNodeAdded)this.onNodeAdded(a);this.setDirtyCanvas(!0);this.change();return a}}; +LGraph.prototype.add=function(a,b){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 in a graph reached";if(null==a.id||-1==a.id)a.id=this.last_node_id++;a.graph=this;this._nodes.push(a);this._nodes_by_id[a.id]=a;if(a.onAdded)a.onAdded();this.config.align_to_grid&&a.alignToGrid();b||this.updateExecutionOrder();if(this.onNodeAdded)this.onNodeAdded(a);this.setDirtyCanvas(!0);this.change();return a}}; LGraph.prototype.remove=function(a){if(null!=this._nodes_by_id[a.id]&&!a.ignore_remove){if(a.inputs)for(var b=0;ba&&this.pos[1]-cb)return!0;return!1}; +LGraphNode.prototype.isPointInsideNode=function(a,b){var c=this.graph&&this.graph.isLive()?0:20;if(this.flags.collapsed){if(isInsideRectangle(a,b,this.pos[0],this.pos[1]-LiteGraph.NODE_TITLE_HEIGHT,LiteGraph.NODE_COLLAPSED_WIDTH,LiteGraph.NODE_TITLE_HEIGHT))return!0}else if(this.pos[0]-4a&&this.pos[1]-cb)return!0;return!1}; LGraphNode.prototype.findInputSlot=function(a){if(!this.inputs)return-1;for(var b=0,c=this.inputs.length;b=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=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=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=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;b=this.graph.links[b];a=this.graph.getNodeById(b.origin_id);if(!a)return!1;a=a.outputs[b.origin_slot];if(!a||!a.links|| +0==a.links.length)return!1;for(var c=0,d=a.links.length;cb&&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.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.clone=function(){var a=LiteGraph.createNode(this.type);a.size=this.size.concat();if(this.inputs)for(var b=0,c=this.inputs.length;bb[1]?0:Math.PI;a.save();a.translate(d[0],d[1]);a.rotate(f);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]]}; diff --git a/css/litegraph-editor.css b/css/litegraph-editor.css index 4147d4b87..905f5c804 100644 --- a/css/litegraph-editor.css +++ b/css/litegraph-editor.css @@ -102,7 +102,6 @@ background-color: #3F3F3F; /*box-shadow: 0 0 3px black;*/ padding: 4px 10px; - line-height: 20px; cursor: pointer; transition: all 1s; -moz-transition: all 1s; @@ -131,6 +130,12 @@ .litegraph-editor button img { margin: -4px; vertical-align: top; + opacity: 0.8; + transition: all 1s; +} + +.litegraph-editor button:hover img { + opacity: 1; } .litegraph-editor .header button { @@ -185,3 +190,35 @@ background-image: url('../demo/imgs/load-progress-full.png'); } +.litegraph-editor .dialog { + position: absolute; + top: 50%; + left: 50%; + margin-top: -150px; + margin-left: -200px; + + background-color: #151515; + + min-width: 400px; + min-height: 300px; + box-shadow: 0 0 2px black; +} + +.litegraph-editor .dialog .dialog-header, .litegraph-editor .dialog .dialog-footer{ + height: 40px; +} + +.litegraph-editor .dialog .dialog-header .dialog-title { + font: 20px 'Arial'; + margin: 4px; + padding: 4px 10px; + display:inline-block; +} + +.litegraph-editor .dialog .dialog-content { + height: calc( 100% - 40px ); + width: calc( 100% - 10px ); + background-color: black; + margin: 4px; + display:inline-block; +} \ No newline at end of file diff --git a/demo/imgs/icon-load.png b/demo/imgs/icon-load.png new file mode 100644 index 0000000000000000000000000000000000000000..4ab6e4e0e4f7653d9f37c776abe20565dc87db32 GIT binary patch literal 1339 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y>2=9ZF3nBND}m`vf$6m{Fu$;xZcyn zF{I+wo9X+#4+jVwpRE+ct#rfjN~p{3l0uP3OBP?MKM+}1T3-Bt|H7qxT{Vfc`Jr?2?q2=M>DAwL?td?ijIx`)F;y?&#D#jX zHI1nOY^s0%FyCqPF5r?oDjCYlvBB~1^l0bf8+KZ@Gg&a$-oI02we7ABCE!<;KP?Edlv?ht;^+qs@4`Ow@Ar?&K(-B7)^zq#~k9LIdEs~ziR z*v5#Mt+Q1+Z@QILR;eI<$Brb4J4c?p3}AXxw^ZC9O~JvCd7pAo=}M`N&AJ~_D++9z zeb1fb;#H9~(DcX)d@e2gn`_ylXN|u_+#1-k6bgd`9t1G;1q&3oaPDAz#~@z*RqBb0 zie=A=`~6ud-j^QlFk@icx`bUw*jUa(WNC{_g;jXG^GgpV=gg1#!G#+PX0vshFXqzY zI{hKff<5dY*9`txpDSw$7|;1wtyl3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFjeHsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rfIL(9V zO~LIJN1S@~fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tXWnl#xpQ5uJ?3t45_&F zX8K;g!v+G!go zx`Ltnfz+M}wx47aE-=KpZC^Jd`Ae=;0ON9nv~ObFJ4M48KQB1HDLVegCZPaU=4tbJ zTl_aQ^c|a-ceUi&Laq#nZ+Ai+bi93LPCoJAL@0ysKJ{lmRtCv5RUbb2wRHKcf=|~E z2843X4%Vpijn%w2r>Q}AZo^Yej)++|&WG^zIKJ#Je!x8?cUPh}%U9lmd#~(Jo}Okh zNoKC$4F$8c@nQ$sA8GVWO1`Z9LFM9!?N7L_bXK4F|JQPb=05w^lMI4<9v#%@{CV)L z#G9;r?z?n3c&ENOv*AnjgUb(;&qQ@acRffo*rIz>@2tnvDe5h0TYPhm=QeLP5Ag4~ z&v?Jh^6egdl|RdZnM^;-`rg_iEa38C$sPq3{uuqG#g;K%t0VJ{o;>mIu;3rAE)G)^*Ii!f{HUwS3j3^P6
- -
diff --git a/src/litegraph-editor.js b/src/litegraph-editor.js index ef027c804..690238f95 100644 --- a/src/litegraph-editor.js +++ b/src/litegraph-editor.js @@ -21,6 +21,8 @@ function Editor(container_id, options) graph.onAfterExecute = function() { graphcanvas.draw(true) }; //add stuff + this.addToolsButton("loadsession_button","Load","imgs/icon-load.png", this.onLoadButton.bind(this), ".tools-left" ); + this.addToolsButton("savesession_button","Save","imgs/icon-save.png", this.onSaveButton.bind(this), ".tools-left" ); this.addLoadCounter(); this.addToolsButton("playnode_button","Play","imgs/icon-play.png", this.onPlayButton.bind(this), ".tools-right" ); this.addToolsButton("playstepnode_button","Step","imgs/icon-playstep.png", this.onPlayStepButton.bind(this), ".tools-right" ); @@ -64,30 +66,51 @@ Editor.prototype.addToolsButton = function(id,name,icon_url, callback, container { if(!container) container = ".tools"; - var button = document.createElement("button"); + var button = this.createButton(name, icon_url); button.id = id; - button.innerHTML = " "+name+""; button.addEventListener("click", callback); this.root.querySelector(container).appendChild(button); - } -Editor.prototype.goFullscreen = function() -{ - if(this.root.requestFullscreen) - this.root.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - else if(this.root.mozRequestFullscreen) - this.root.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - else if(this.root.webkitRequestFullscreen) - this.root.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - else - throw("Fullscreen not supported"); - var self = this; - setTimeout(function() { - self.graphcanvas.resize(); - },100); +Editor.prototype.createPanel = function(title, options) +{ + + var root = document.createElement("div"); + root.className = "dialog"; + root.innerHTML = "
"+title+"
"; + root.header = root.querySelector(".dialog-header"); + root.content = root.querySelector(".dialog-content"); + root.footer = root.querySelector(".dialog-footer"); + + + return root; +} + +Editor.prototype.createButton = function(name, icon_url) +{ + var button = document.createElement("button"); + if(icon_url) + button.innerHTML = " "; + button.innerHTML += name; + return button; +} + +Editor.prototype.onLoadButton = function() +{ + var panel = this.createPanel("Load session"); + var close = this.createButton("Close"); + close.style.float = "right"; + close.addEventListener("click", function() { panel.parentNode.removeChild( panel ); }); + panel.header.appendChild(close); + panel.content.innerHTML = "test"; + + this.root.appendChild(panel); +} + +Editor.prototype.onSaveButton = function() +{ } Editor.prototype.onPlayButton = function() @@ -124,6 +147,23 @@ Editor.prototype.onLiveButton = function() button.innerHTML = !is_live_mode ? " Live" : " Edit" ; } +Editor.prototype.goFullscreen = function() +{ + if(this.root.requestFullscreen) + this.root.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + else if(this.root.mozRequestFullscreen) + this.root.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + else if(this.root.webkitRequestFullscreen) + this.root.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + else + throw("Fullscreen not supported"); + + var self = this; + setTimeout(function() { + self.graphcanvas.resize(); + },100); +} + Editor.prototype.onFullscreenButton = function() { this.goFullscreen(); diff --git a/src/litegraph.js b/src/litegraph.js index aae3b65ce..14ec5732f 100644 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -24,7 +24,7 @@ var LiteGraph = { NODE_DEFAULT_BOXCOLOR: "#AEF", NODE_DEFAULT_SHAPE: "box", MAX_NUMBER_OF_NODES: 1000, //avoid infinite loops - DEFAULT_POSITION: [100,100], + DEFAULT_POSITION: [100,100],//default node position node_images_path: "", debug: false, @@ -86,45 +86,6 @@ var LiteGraph = { var node = new base_class( name ); - /* - if (base_class.prototype) //is a class - { - node = new base_class(name); - } - else - { - node = new LGraphNode(name); - node.inputs = []; - node.outputs = []; - - //add inputs and outputs - for (var i in prototype) - { - if(i == "inputs") - { - for(var j in prototype[i]) - node.addInput( prototype[i][j][0],prototype[i][j][1], prototype[i][j][2] ); - } - else if(i == "outputs") - { - for(var j in prototype[i]) - node.addOutput( prototype[i][j][0],prototype[i][j][1], prototype[i][j][2] ); - } - else - { - if( prototype[i].concat ) //array - node[i] = prototype[i].concat(); - else if (typeof(prototype[i]) == 'object') - node[i] = LiteGraph.cloneObject(prototype[i]); //slow but safe - else - node[i] = prototype[i]; - } - } - //set size - if(base_class.size) node.size = base_class.size.concat(); //save size - } - */ - node.type = type; if(!node.title) node.title = title; if(!node.flags) node.flags = {}; @@ -298,7 +259,7 @@ LGraph.prototype.clear = function() //links this.last_link_id = 0; - this.links = {}; + this.links = {}; //container with all the links //iterations this.iteration = 0; @@ -512,20 +473,22 @@ LGraph.prototype.computeExecutionOrder = function() //for every connection for(var j = 0; j < output.links.length; j++) { - var link = output.links[j]; + var link_id = output.links[j]; + var link = this.links[link_id]; + if(!link) continue; //already visited link (ignore it) - if(visited_links[ link[0] ]) + if(visited_links[ link.id ]) continue; - var target_node = this.getNodeById( link[3] ); + var target_node = this.getNodeById( link.target_id ); if(target_node == null) { - visited_links[ link[0] ] = true; + visited_links[ link.id ] = true; continue; } - visited_links[link[0]] = true; //mark as visited + visited_links[link.id] = true; //mark as visited remaining_links[target_node.id] -= 1; //reduce the number of links remaining if (remaining_links[target_node.id] == 0) S.push(target_node); //if no more links, then add to Starters array @@ -616,7 +579,7 @@ LGraph.prototype.sendActionToCanvas = function(action, params) * @param {LGraphNode} node the instance of the node */ -LGraph.prototype.add = function(node) +LGraph.prototype.add = function(node, skip_compute_order) { if(!node || (node.id != -1 && this._nodes_by_id[node.id] != null)) return; //already added @@ -644,8 +607,9 @@ LGraph.prototype.add = function(node) if(this.config.align_to_grid) node.alignToGrid(); - - this.updateExecutionOrder(); + + if(!skip_compute_order) + this.updateExecutionOrder(); if(this.onNodeAdded) this.onNodeAdded(node); @@ -927,6 +891,11 @@ LGraph.prototype.serialize = function() for (var i in this._nodes) nodes_info.push( this._nodes[i].serialize() ); + //remove data from links, we dont want to store it + for (var i in this.links) + this.links[i].data = null; + + var data = { graph: this.graph, @@ -934,6 +903,7 @@ LGraph.prototype.serialize = function() frame: this.frame, last_node_id: this.last_node_id, last_link_id: this.last_link_id, + links: LiteGraph.cloneObject( this.links ), config: this.config, nodes: nodes_info @@ -966,8 +936,8 @@ LGraph.prototype.configure = function(data, keep_old) for (var i in nodes) { var n_info = nodes[i]; //stored info - var n = LiteGraph.createNode( n_info.type, n_info.title ); - if(!n) + var node = LiteGraph.createNode( n_info.type, n_info.title ); + if(!node) { if(LiteGraph.debug) console.log("Node not found: " + n_info.type); @@ -975,10 +945,12 @@ LGraph.prototype.configure = function(data, keep_old) continue; } - n.configure(n_info); - this.add(n); + node.id = n_info.id; //id it or it will create a new id + this.add(node, true); //add before configure, otherwise configure cannot create links + node.configure(n_info); } + this.updateExecutionOrder(); this.setDirtyCanvas(true,true); return error; } @@ -1049,7 +1021,7 @@ function LGraphNode(title) } /** -* configure a node from an object +* configure a node from an object containing the serialized info * @method configure */ LGraphNode.prototype.configure = function(info) @@ -1060,39 +1032,38 @@ LGraphNode.prototype.configure = function(info) if(info[j] == null) continue; - else if( info[j].concat ) //array - this[j] = info[j].concat(); else if (typeof(info[j]) == 'object') //object this[j] = LiteGraph.cloneObject(info[j], this[j] || {} ); else //value this[j] = info[j]; } -} -/* Copy all the info from one object to this node (used for serialization) */ -LGraphNode.prototype.copyFromObject = function(info, ignore_connections) -{ - var outputs = null; - var inputs = null; - var properties = null; - var local_data = null; - - for (var j in info) + //FOR LEGACY, PLEASE REMOVE ON NEXT VERSION + for(var i in this.inputs) { - if(ignore_connections && (j == "outputs" || j == "inputs")) + var input = this.inputs[i]; + if(!input.link || !input.link.length ) continue; - - if(j == "console") continue; - - if(info[j] == null) + var link = input.link; + if(typeof(link) != "object") continue; - else if( info[j].concat ) //array - this[j] = info[j].concat(); - else if (typeof(info[j]) == 'object') //object - this[j] = LiteGraph.cloneObject(info[j]); - else //value - this[j] = info[j]; + input.link = link[0]; + this.graph.links[ link[0] ] = { id: link[0], origin_id: link[1], origin_slot: link[2], target_id: link[3], target_slot: link[4] }; } + for(var i in this.outputs) + { + var output = this.outputs[i]; + if(!output.links || output.links.length == 0) + continue; + for(var j in output.links) + { + var link = output.links[j]; + if(typeof(link) != "object") + continue; + output.links[j] = link[0]; + } + } + } /** @@ -1193,7 +1164,10 @@ LGraphNode.prototype.setOutputData = function(slot,data) if(slot > -1 && slot < this.outputs.length && this.outputs[slot] && this.outputs[slot].links != null) { for(var i = 0; i < this.outputs[slot].links.length; i++) - this.graph.links[ this.outputs[slot].links[i][0] ] = data; + { + var link_id = this.outputs[slot].links[i]; + this.graph.links[ link_id ].data = data; + } } } @@ -1207,7 +1181,7 @@ LGraphNode.prototype.getInputData = function(slot) { if(!this.inputs) return null; if(slot < this.inputs.length && this.inputs[slot].link != null) - return this.graph.links[ this.inputs[slot].link[0] ]; + return this.graph.links[ this.inputs[slot].link ].data; return null; } @@ -1279,7 +1253,7 @@ LGraphNode.prototype.getOutputNodes = function(slot) var output = this.outputs[slot]; var r = []; for(var i = 0; i < output.length; i++) - r.push( this.graph.getNodeById( output.links[i][3] )); + r.push( this.graph.getNodeById( output.links[i].target_id )); return r; } return null; @@ -1452,7 +1426,7 @@ LGraphNode.prototype.getBounding = function() */ LGraphNode.prototype.isPointInsideNode = function(x,y) { - var margin_top = this.graph.isLive() ? 0 : 20; + var margin_top = this.graph && this.graph.isLive() ? 0 : 20; if(this.flags.collapsed) { //if ( distance([x,y], [this.pos[0] + this.size[0]*0.5, this.pos[1] + this.size[1]*0.5]) < LiteGraph.NODE_COLLAPSED_RADIUS) @@ -1551,12 +1525,14 @@ LGraphNode.prototype.connect = function(slot, node, target_slot) output.type == node.inputs[target_slot].type) //same type { //info: link structure => [ 0:link_id, 1:start_node_id, 2:start_slot, 3:end_node_id, 4:end_slot ] - var link = [ this.graph.last_link_id++, this.id, slot, node.id, target_slot ]; + //var link = [ this.graph.last_link_id++, this.id, slot, node.id, target_slot ]; + var link = { id: this.graph.last_link_id++, origin_id: this.id, origin_slot: slot, target_id: node.id, target_slot: target_slot }; + this.graph.links[ link.id ] = link; //connect if( output.links == null ) output.links = []; - output.links.push(link); - node.inputs[target_slot].link = link; + output.links.push( link.id ); + node.inputs[target_slot].link = link.id; this.setDirtyCanvas(false,true); this.graph.onConnectionChange(); @@ -1599,13 +1575,15 @@ LGraphNode.prototype.disconnectOutput = function(slot, target_node) { for(var i = 0, l = output.links.length; i < l; i++) { - var link = output.links[i]; + var link_id = output.links[i]; + var link_info = this.graph.links[ link_id ]; + //is the link we are searching for... - if( link[3] == target_node.id ) + if( link_info.target_id == target_node.id ) { output.links.splice(i,1); //remove here - target_node.inputs[ link[4] ].link = null; //remove there - delete this.graph.links[link[0]]; //remove the link from the links pool + target_node.inputs[ link_info.target_slot ].link = null; //remove there + delete this.graph.links[ link_id ]; //remove the link from the links pool break; } } @@ -1614,10 +1592,12 @@ LGraphNode.prototype.disconnectOutput = function(slot, target_node) { for(var i = 0, l = output.links.length; i < l; i++) { - var link = output.links[i]; - var target_node = this.graph.getNodeById( link[3] ); + var link_id = output.links[i]; + var link_info = this.graph.links[ link_id ]; + + var target_node = this.graph.getNodeById( link_info.target_id ); if(target_node) - target_node.inputs[ link[4] ].link = null; //remove other side link + target_node.inputs[ link_info.target_slot ].link = null; //remove other side link } output.links = null; } @@ -1655,21 +1635,24 @@ LGraphNode.prototype.disconnectInput = function(slot) var input = this.inputs[slot]; if(!input) return false; - var link = this.inputs[slot].link; + var link_id = this.inputs[slot].link; this.inputs[slot].link = null; //remove other side - var node = this.graph.getNodeById( link[1] ); + var link_info = this.graph.links[ link_id ]; + var node = this.graph.getNodeById( link_info.origin_id ); if(!node) return false; - var output = node.outputs[ link[2] ]; + var output = node.outputs[ link_info.origin_slot ]; if(!output || !output.links || output.links.length == 0) return false; + //check outputs for(var i = 0, l = output.links.length; i < l; i++) { - var link = output.links[i]; - if( link[3] == this.id ) + var link_id = output.links[i]; + var link_info = this.graph.links[ link_id ]; + if( link_info.target_id == this.id ) { output.links.splice(i,1); break; @@ -3437,12 +3420,15 @@ LGraphCanvas.prototype.drawConnections = function(ctx) for(var i in node.inputs) { var input = node.inputs[i]; - if(!input || !input.link ) continue; - var link = input.link; + if(!input || input.link == null) + continue; + var link_id = input.link; + var link = this.graph.links[ link_id ]; + if(!link) continue; - var start_node = this.graph.getNodeById( link[1] ); + var start_node = this.graph.getNodeById( link.origin_id ); if(start_node == null) continue; - var start_node_slot = link[2]; + var start_node_slot = link.origin_slot; var start_node_slotpos = null; if(start_node_slot == -1)