Merge branch 'master' into pr/41

This commit is contained in:
Javi Agenjo
2018-06-08 19:19:29 +02:00
23 changed files with 3528 additions and 10750 deletions

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
package-lock=false

7316
build/litegraph.min.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,8 @@
<script type="text/javascript" src="../src/nodes/audio.js"></script>
<script type="text/javascript" src="../src/nodes/network.js"></script>
<script type="text/javascript" src="demo.js"></script>
<script type="text/javascript" src="code.js"></script>
<script type="text/javascript" src="js/demos.js"></script>
<script type="text/javascript" src="js/code.js"></script>
</body>
</html>

100
demo/code.js → demo/js/code.js Executable file → Normal file
View File

@@ -1,50 +1,50 @@
LiteGraph.node_images_path = "../nodes_data/";
var editor = new LiteGraph.Editor("main");
window.graphcanvas = editor.graphcanvas;
window.graph = editor.graph;
window.addEventListener("resize", function() { editor.graphcanvas.resize(); } );
window.addEventListener("keydown", editor.graphcanvas.processKey.bind(editor.graphcanvas) );
//create scene selector
var elem = document.createElement("span");
elem.className = "selector";
elem.innerHTML = "Demo <select><option>Empty</option></select> <button id='save'>Save</button><button id='load'>Load</button>";
editor.tools.appendChild(elem);
var select = elem.querySelector("select");
select.addEventListener("change", function(e){
var option = this.options[this.selectedIndex];
var url = option.dataset["url"];
if(url)
graph.load( url );
else
graph.clear();
});
elem.querySelector("#save").addEventListener("click",function(){
console.log("saved");
localStorage.setItem( "graphdemo_save", JSON.stringify( graph.serialize() ) );
});
elem.querySelector("#load").addEventListener("click",function(){
var data = localStorage.getItem( "graphdemo_save" );
if(data)
graph.configure( JSON.parse( data ) );
console.log("loaded");
});
function addDemo( name, url )
{
var option = document.createElement("option");
option.dataset["url"] = url;
option.innerHTML = name;
select.appendChild( option );
}
//some examples
addDemo("Audio", "examples/audio.json");
addDemo("Audio Delay", "examples/audio_delay.json");
addDemo("Audio Reverb", "examples/audio_reverb.json");
LiteGraph.node_images_path = "../nodes_data/";
var editor = new LiteGraph.Editor("main");
window.graphcanvas = editor.graphcanvas;
window.graph = editor.graph;
window.addEventListener("resize", function() { editor.graphcanvas.resize(); } );
window.addEventListener("keydown", editor.graphcanvas.processKey.bind(editor.graphcanvas) );
//create scene selector
var elem = document.createElement("span");
elem.className = "selector";
elem.innerHTML = "Demo <select><option>Empty</option></select> <button id='save'>Save</button><button id='load'>Load</button>";
editor.tools.appendChild(elem);
var select = elem.querySelector("select");
select.addEventListener("change", function(e){
var option = this.options[this.selectedIndex];
var url = option.dataset["url"];
if(url)
graph.load( url );
else
graph.clear();
});
elem.querySelector("#save").addEventListener("click",function(){
console.log("saved");
localStorage.setItem( "graphdemo_save", JSON.stringify( graph.serialize() ) );
});
elem.querySelector("#load").addEventListener("click",function(){
var data = localStorage.getItem( "graphdemo_save" );
if(data)
graph.configure( JSON.parse( data ) );
console.log("loaded");
});
function addDemo( name, url )
{
var option = document.createElement("option");
option.dataset["url"] = url;
option.innerHTML = name;
select.appendChild( option );
}
//some examples
addDemo("Audio", "examples/audio.json");
addDemo("Audio Delay", "examples/audio_delay.json");
addDemo("Audio Reverb", "examples/audio_reverb.json");

158
demo/demo.js → demo/js/demos.js Executable file → Normal file
View File

@@ -1,80 +1,80 @@
function demo()
{
multiConnection();
}
function multiConnection()
{
var node_button = LiteGraph.createNode("widget/button");
node_button.pos = [100,400];
graph.add(node_button);
var node_console = LiteGraph.createNode("basic/console");
node_console.pos = [400,400];
graph.add(node_console);
node_button.connect(0, node_console );
var node_const_A = LiteGraph.createNode("basic/const");
node_const_A.pos = [200,200];
graph.add(node_const_A);
node_const_A.setValue(4.5);
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];
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 = 200;
var nodes = [];
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);
nodes.push(n);
}
for(var i = 0; i < nodes.length; i++)
nodes[ (Math.random() * nodes.length)|0 ].connect(0, nodes[ (Math.random() * nodes.length)|0 ], 0 );
function demo()
{
multiConnection();
}
function multiConnection()
{
var node_button = LiteGraph.createNode("widget/button");
node_button.pos = [100,400];
graph.add(node_button);
var node_console = LiteGraph.createNode("basic/console");
node_console.pos = [400,400];
graph.add(node_console);
node_button.connect(0, node_console );
var node_const_A = LiteGraph.createNode("basic/const");
node_const_A.pos = [200,200];
graph.add(node_const_A);
node_const_A.setValue(4.5);
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];
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 = 200;
var nodes = [];
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);
nodes.push(n);
}
for(var i = 0; i < nodes.length; i++)
nodes[ (Math.random() * nodes.length)|0 ].connect(0, nodes[ (Math.random() * nodes.length)|0 ], 0 );
}

View File

@@ -85,7 +85,7 @@
<div class="foundat">
Defined in: <a href="../files/.._src_litegraph.js.html#l6083"><code>..&#x2F;src&#x2F;litegraph.js:6083</code></a>
Defined in: <a href="../files/.._src_litegraph.js.html#l6207"><code>..&#x2F;src&#x2F;litegraph.js:6207</code></a>
</div>
@@ -123,7 +123,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l6083"><code>..&#x2F;src&#x2F;litegraph.js:6083</code></a>
<a href="../files/.._src_litegraph.js.html#l6207"><code>..&#x2F;src&#x2F;litegraph.js:6207</code></a>
</p>

File diff suppressed because it is too large Load Diff

View File

@@ -85,7 +85,7 @@
<div class="foundat">
Defined in: <a href="../files/.._src_litegraph.js.html#l3203"><code>..&#x2F;src&#x2F;litegraph.js:3203</code></a>
Defined in: <a href="../files/.._src_litegraph.js.html#l3325"><code>..&#x2F;src&#x2F;litegraph.js:3325</code></a>
</div>
@@ -126,7 +126,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l3203"><code>..&#x2F;src&#x2F;litegraph.js:3203</code></a>
<a href="../files/.._src_litegraph.js.html#l3325"><code>..&#x2F;src&#x2F;litegraph.js:3325</code></a>
</p>
@@ -254,7 +254,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2852"><code>..&#x2F;src&#x2F;litegraph.js:2852</code></a>
<a href="../files/.._src_litegraph.js.html#l2974"><code>..&#x2F;src&#x2F;litegraph.js:2974</code></a>
</p>
@@ -291,7 +291,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2949"><code>..&#x2F;src&#x2F;litegraph.js:2949</code></a>
<a href="../files/.._src_litegraph.js.html#l3071"><code>..&#x2F;src&#x2F;litegraph.js:3071</code></a>
</p>
@@ -342,7 +342,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l3219"><code>..&#x2F;src&#x2F;litegraph.js:3219</code></a>
<a href="../files/.._src_litegraph.js.html#l3341"><code>..&#x2F;src&#x2F;litegraph.js:3341</code></a>
</p>
@@ -388,7 +388,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2922"><code>..&#x2F;src&#x2F;litegraph.js:2922</code></a>
<a href="../files/.._src_litegraph.js.html#l3044"><code>..&#x2F;src&#x2F;litegraph.js:3044</code></a>
</p>
@@ -441,7 +441,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2966"><code>..&#x2F;src&#x2F;litegraph.js:2966</code></a>
<a href="../files/.._src_litegraph.js.html#l3088"><code>..&#x2F;src&#x2F;litegraph.js:3088</code></a>
</p>
@@ -495,7 +495,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2891"><code>..&#x2F;src&#x2F;litegraph.js:2891</code></a>
<a href="../files/.._src_litegraph.js.html#l3013"><code>..&#x2F;src&#x2F;litegraph.js:3013</code></a>
</p>
@@ -542,7 +542,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l3233"><code>..&#x2F;src&#x2F;litegraph.js:3233</code></a>
<a href="../files/.._src_litegraph.js.html#l3355"><code>..&#x2F;src&#x2F;litegraph.js:3355</code></a>
</p>
@@ -573,7 +573,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l3257"><code>..&#x2F;src&#x2F;litegraph.js:3257</code></a>
<a href="../files/.._src_litegraph.js.html#l3379"><code>..&#x2F;src&#x2F;litegraph.js:3379</code></a>
</p>

View File

@@ -85,7 +85,7 @@
<div class="foundat">
Defined in: <a href="../files/.._src_litegraph.js.html#l1487"><code>..&#x2F;src&#x2F;litegraph.js:1487</code></a>
Defined in: <a href="../files/.._src_litegraph.js.html#l1535"><code>..&#x2F;src&#x2F;litegraph.js:1535</code></a>
</div>
@@ -180,6 +180,10 @@
<li class="index-item method">
<a href="#method_getInputData">getInputData</a>
</li>
<li class="index-item method">
<a href="#method_getInputDataByName">getInputDataByName</a>
</li>
<li class="index-item method">
<a href="#method_getInputInfo">getInputInfo</a>
@@ -188,6 +192,10 @@
<li class="index-item method">
<a href="#method_getInputNode">getInputNode</a>
</li>
<li class="index-item method">
<a href="#method_getInputOrProperty">getInputOrProperty</a>
</li>
<li class="index-item method">
<a href="#method_getOutputData">getOutputData</a>
@@ -208,6 +216,10 @@
<li class="index-item method">
<a href="#method_getTitle">getTitle</a>
</li>
<li class="index-item method">
<a href="#method_isAnyOutputConnected">isAnyOutputConnected</a>
</li>
<li class="index-item method">
<a href="#method_isInputConnected">isInputConnected</a>
@@ -293,7 +305,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2161"><code>..&#x2F;src&#x2F;litegraph.js:2161</code></a>
<a href="../files/.._src_litegraph.js.html#l2276"><code>..&#x2F;src&#x2F;litegraph.js:2276</code></a>
</p>
@@ -385,7 +397,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2098"><code>..&#x2F;src&#x2F;litegraph.js:2098</code></a>
<a href="../files/.._src_litegraph.js.html#l2213"><code>..&#x2F;src&#x2F;litegraph.js:2213</code></a>
</p>
@@ -460,7 +472,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2122"><code>..&#x2F;src&#x2F;litegraph.js:2122</code></a>
<a href="../files/.._src_litegraph.js.html#l2237"><code>..&#x2F;src&#x2F;litegraph.js:2237</code></a>
</p>
@@ -520,7 +532,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2036"><code>..&#x2F;src&#x2F;litegraph.js:2036</code></a>
<a href="../files/.._src_litegraph.js.html#l2151"><code>..&#x2F;src&#x2F;litegraph.js:2151</code></a>
</p>
@@ -595,7 +607,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2059"><code>..&#x2F;src&#x2F;litegraph.js:2059</code></a>
<a href="../files/.._src_litegraph.js.html#l2174"><code>..&#x2F;src&#x2F;litegraph.js:2174</code></a>
</p>
@@ -658,7 +670,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2010"><code>..&#x2F;src&#x2F;litegraph.js:2010</code></a>
<a href="../files/.._src_litegraph.js.html#l2125"><code>..&#x2F;src&#x2F;litegraph.js:2125</code></a>
</p>
@@ -737,7 +749,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2745"><code>..&#x2F;src&#x2F;litegraph.js:2745</code></a>
<a href="../files/.._src_litegraph.js.html#l2860"><code>..&#x2F;src&#x2F;litegraph.js:2860</code></a>
</p>
@@ -777,7 +789,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2182"><code>..&#x2F;src&#x2F;litegraph.js:2182</code></a>
<a href="../files/.._src_litegraph.js.html#l2297"><code>..&#x2F;src&#x2F;litegraph.js:2297</code></a>
</p>
@@ -833,7 +845,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1542"><code>..&#x2F;src&#x2F;litegraph.js:1542</code></a>
<a href="../files/.._src_litegraph.js.html#l1590"><code>..&#x2F;src&#x2F;litegraph.js:1590</code></a>
</p>
@@ -879,7 +891,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2335"><code>..&#x2F;src&#x2F;litegraph.js:2335</code></a>
<a href="../files/.._src_litegraph.js.html#l2450"><code>..&#x2F;src&#x2F;litegraph.js:2450</code></a>
</p>
@@ -967,7 +979,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2543"><code>..&#x2F;src&#x2F;litegraph.js:2543</code></a>
<a href="../files/.._src_litegraph.js.html#l2658"><code>..&#x2F;src&#x2F;litegraph.js:2658</code></a>
</p>
@@ -1036,7 +1048,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2453"><code>..&#x2F;src&#x2F;litegraph.js:2453</code></a>
<a href="../files/.._src_litegraph.js.html#l2568"><code>..&#x2F;src&#x2F;litegraph.js:2568</code></a>
</p>
@@ -1113,7 +1125,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2304"><code>..&#x2F;src&#x2F;litegraph.js:2304</code></a>
<a href="../files/.._src_litegraph.js.html#l2419"><code>..&#x2F;src&#x2F;litegraph.js:2419</code></a>
</p>
@@ -1179,7 +1191,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2320"><code>..&#x2F;src&#x2F;litegraph.js:2320</code></a>
<a href="../files/.._src_litegraph.js.html#l2435"><code>..&#x2F;src&#x2F;litegraph.js:2435</code></a>
</p>
@@ -1239,7 +1251,7 @@
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2233"><code>..&#x2F;src&#x2F;litegraph.js:2233</code></a>
<a href="../files/.._src_litegraph.js.html#l2348"><code>..&#x2F;src&#x2F;litegraph.js:2348</code></a>
</p>
@@ -1292,7 +1304,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2611"><code>..&#x2F;src&#x2F;litegraph.js:2611</code></a>
<a href="../files/.._src_litegraph.js.html#l2726"><code>..&#x2F;src&#x2F;litegraph.js:2726</code></a>
</p>
@@ -1372,7 +1384,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1775"><code>..&#x2F;src&#x2F;litegraph.js:1775</code></a>
<a href="../files/.._src_litegraph.js.html#l1833"><code>..&#x2F;src&#x2F;litegraph.js:1833</code></a>
</p>
@@ -1380,7 +1392,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
</div>
<div class="description">
<p>retrieves the input data (data traveling through the connection) from one slot</p>
<p>Retrieves the input data (data traveling through the connection) from one slot</p>
</div>
@@ -1423,6 +1435,85 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
</div>
</div>
<div id="method_getInputDataByName" class="method item">
<h3 class="name"><code>getInputDataByName</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code>slot_name</code>
</li>
<li class="arg">
<code>force_update</code>
</li>
</ul><span class="paren">)</span>
</div>
<span class="returns-inline">
<span class="type"></span>
</span>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1869"><code>..&#x2F;src&#x2F;litegraph.js:1869</code></a>
</p>
</div>
<div class="description">
<p>Retrieves the input data from one slot using its name instead of slot number</p>
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name">slot_name</code>
<span class="type">String</span>
<div class="param-description">
</div>
</li>
<li class="param">
<code class="param-name">force_update</code>
<span class="type">Boolean</span>
<div class="param-description">
<p>if set to true it will force the connected node of this slot to output data into this link</p>
</div>
</li>
</ul>
</div>
<div class="returns">
<h4>Returns:</h4>
<div class="returns-description">
<span class="type"></span>:
<p>data or if it is not connected returns null</p>
</div>
</div>
</div>
<div id="method_getInputInfo" class="method item">
<h3 class="name"><code>getInputInfo</code></h3>
@@ -1448,7 +1539,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1824"><code>..&#x2F;src&#x2F;litegraph.js:1824</code></a>
<a href="../files/.._src_litegraph.js.html#l1898"><code>..&#x2F;src&#x2F;litegraph.js:1898</code></a>
</p>
@@ -1513,7 +1604,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1839"><code>..&#x2F;src&#x2F;litegraph.js:1839</code></a>
<a href="../files/.._src_litegraph.js.html#l1913"><code>..&#x2F;src&#x2F;litegraph.js:1913</code></a>
</p>
@@ -1553,6 +1644,71 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
</div>
</div>
<div id="method_getInputOrProperty" class="method item">
<h3 class="name"><code>getInputOrProperty</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code>name</code>
</li>
</ul><span class="paren">)</span>
</div>
<span class="returns-inline">
<span class="type"></span>
</span>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1935"><code>..&#x2F;src&#x2F;litegraph.js:1935</code></a>
</p>
</div>
<div class="description">
<p>returns the value of an input with this name, otherwise checks if there is a property with that name</p>
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name">name</code>
<span class="type">String</span>
<div class="param-description">
</div>
</li>
</ul>
</div>
<div class="returns">
<h4>Returns:</h4>
<div class="returns-description">
<span class="type"></span>:
<p>value</p>
</div>
</div>
</div>
<div id="method_getOutputData" class="method item">
<h3 class="name"><code>getOutputData</code></h3>
@@ -1578,7 +1734,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1860"><code>..&#x2F;src&#x2F;litegraph.js:1860</code></a>
<a href="../files/.._src_litegraph.js.html#l1959"><code>..&#x2F;src&#x2F;litegraph.js:1959</code></a>
</p>
@@ -1643,7 +1799,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1878"><code>..&#x2F;src&#x2F;litegraph.js:1878</code></a>
<a href="../files/.._src_litegraph.js.html#l1977"><code>..&#x2F;src&#x2F;litegraph.js:1977</code></a>
</p>
@@ -1708,7 +1864,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1907"><code>..&#x2F;src&#x2F;litegraph.js:1907</code></a>
<a href="../files/.._src_litegraph.js.html#l2022"><code>..&#x2F;src&#x2F;litegraph.js:2022</code></a>
</p>
@@ -1774,7 +1930,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2273"><code>..&#x2F;src&#x2F;litegraph.js:2273</code></a>
<a href="../files/.._src_litegraph.js.html#l2388"><code>..&#x2F;src&#x2F;litegraph.js:2388</code></a>
</p>
@@ -1840,7 +1996,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1726"><code>..&#x2F;src&#x2F;litegraph.js:1726</code></a>
<a href="../files/.._src_litegraph.js.html#l1784"><code>..&#x2F;src&#x2F;litegraph.js:1784</code></a>
</p>
@@ -1855,6 +2011,47 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
</div>
<div id="method_isAnyOutputConnected" class="method item">
<h3 class="name"><code>isAnyOutputConnected</code></h3>
<span class="paren">()</span>
<span class="returns-inline">
<span class="type">Boolean</span>
</span>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2006"><code>..&#x2F;src&#x2F;litegraph.js:2006</code></a>
</p>
</div>
<div class="description">
<p>tells you if there is any connection in the output slots</p>
</div>
<div class="returns">
<h4>Returns:</h4>
<div class="returns-description">
<span class="type">Boolean</span>:
</div>
</div>
</div>
<div id="method_isInputConnected" class="method item">
<h3 class="name"><code>isInputConnected</code></h3>
@@ -1880,7 +2077,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1811"><code>..&#x2F;src&#x2F;litegraph.js:1811</code></a>
<a href="../files/.._src_litegraph.js.html#l1885"><code>..&#x2F;src&#x2F;litegraph.js:1885</code></a>
</p>
@@ -1943,7 +2140,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1894"><code>..&#x2F;src&#x2F;litegraph.js:1894</code></a>
<a href="../files/.._src_litegraph.js.html#l1993"><code>..&#x2F;src&#x2F;litegraph.js:1993</code></a>
</p>
@@ -2009,7 +2206,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2249"><code>..&#x2F;src&#x2F;litegraph.js:2249</code></a>
<a href="../files/.._src_litegraph.js.html#l2364"><code>..&#x2F;src&#x2F;litegraph.js:2364</code></a>
</p>
@@ -2073,7 +2270,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2758"><code>..&#x2F;src&#x2F;litegraph.js:2758</code></a>
<a href="../files/.._src_litegraph.js.html#l2873"><code>..&#x2F;src&#x2F;litegraph.js:2873</code></a>
</p>
@@ -2110,7 +2307,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2147"><code>..&#x2F;src&#x2F;litegraph.js:2147</code></a>
<a href="../files/.._src_litegraph.js.html#l2262"><code>..&#x2F;src&#x2F;litegraph.js:2262</code></a>
</p>
@@ -2163,7 +2360,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l2084"><code>..&#x2F;src&#x2F;litegraph.js:2084</code></a>
<a href="../files/.._src_litegraph.js.html#l2199"><code>..&#x2F;src&#x2F;litegraph.js:2199</code></a>
</p>
@@ -2210,7 +2407,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1638"><code>..&#x2F;src&#x2F;litegraph.js:1638</code></a>
<a href="../files/.._src_litegraph.js.html#l1690"><code>..&#x2F;src&#x2F;litegraph.js:1690</code></a>
</p>
@@ -2250,7 +2447,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1739"><code>..&#x2F;src&#x2F;litegraph.js:1739</code></a>
<a href="../files/.._src_litegraph.js.html#l1797"><code>..&#x2F;src&#x2F;litegraph.js:1797</code></a>
</p>
@@ -2307,7 +2504,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1714"><code>..&#x2F;src&#x2F;litegraph.js:1714</code></a>
<a href="../files/.._src_litegraph.js.html#l1772"><code>..&#x2F;src&#x2F;litegraph.js:1772</code></a>
</p>
@@ -2347,7 +2544,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1940"><code>..&#x2F;src&#x2F;litegraph.js:1940</code></a>
<a href="../files/.._src_litegraph.js.html#l2055"><code>..&#x2F;src&#x2F;litegraph.js:2055</code></a>
</p>
@@ -2414,7 +2611,7 @@ bounding is: [topleft_cornerx, topleft_cornery, width, height]</p>
<div class="meta">
<p>
Defined in
<a href="../files/.._src_litegraph.js.html#l1963"><code>..&#x2F;src&#x2F;litegraph.js:1963</code></a>
<a href="../files/.._src_litegraph.js.html#l2078"><code>..&#x2F;src&#x2F;litegraph.js:2078</code></a>
</p>

View File

@@ -52,7 +52,7 @@
"plugin_for": [],
"extension_for": [],
"file": "../src/litegraph.js",
"line": 1487,
"line": 1535,
"description": "Base Class for all the node type classes",
"params": [
{
@@ -71,7 +71,7 @@
"plugin_for": [],
"extension_for": [],
"file": "../src/litegraph.js",
"line": 3203,
"line": 3325,
"description": "marks as dirty the canvas, this way it will be rendered again",
"is_constructor": 1,
"params": [
@@ -102,7 +102,7 @@
"plugin_for": [],
"extension_for": [],
"file": "../src/litegraph.js",
"line": 6083,
"line": 6207,
"description": "ContextMenu from LiteGUI",
"is_constructor": 1,
"params": [
@@ -497,7 +497,7 @@
"line": 1027,
"description": "Returns a list of nodes that matches a name",
"itemtype": "method",
"name": "findNodesByName",
"name": "findNodesByTitle",
"params": [
{
"name": "name",
@@ -542,19 +542,24 @@
},
{
"file": "../src/litegraph.js",
"line": 1230,
"description": "Assigns a value to all the nodes that matches this name. This is used to create global variables of the node that\ncan be easily accesed from the outside of the graph",
"line": 1065,
"description": "Tell this graph it has a global graph input of this type",
"itemtype": "method",
"name": "setInputData",
"name": "addGlobalInput",
"params": [
{
"name": "name",
"description": "the name of the node",
"description": "",
"type": "String"
},
{
"name": "type",
"description": "",
"type": "String"
},
{
"name": "value",
"description": "value to assign to this node",
"description": "[optional]",
"type": "*"
}
],
@@ -562,26 +567,264 @@
},
{
"file": "../src/litegraph.js",
"line": 1245,
"description": "Returns the value of the first node with this name. This is used to access global variables of the graph from the outside",
"line": 1083,
"description": "Assign a data to the global graph input",
"itemtype": "method",
"name": "setGlobalInputData",
"params": [
{
"name": "name",
"description": "",
"type": "String"
},
{
"name": "data",
"description": "",
"type": "*"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1097,
"description": "Assign a data to the global graph input (same as setGlobalInputData)",
"itemtype": "method",
"name": "setInputData",
"params": [
{
"name": "name",
"description": "the name of the node",
"description": "",
"type": "String"
},
{
"name": "data",
"description": "",
"type": "*"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1106,
"description": "Returns the current value of a global graph input",
"itemtype": "method",
"name": "getGlobalInputData",
"params": [
{
"name": "name",
"description": "",
"type": "String"
}
],
"return": {
"description": "value of the node",
"description": "the data",
"type": "*"
},
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1285,
"line": 1120,
"description": "Changes the name of a global graph input",
"itemtype": "method",
"name": "renameGlobalInput",
"params": [
{
"name": "old_name",
"description": "",
"type": "String"
},
{
"name": "new_name",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1150,
"description": "Changes the type of a global graph input",
"itemtype": "method",
"name": "changeGlobalInputType",
"params": [
{
"name": "name",
"description": "",
"type": "String"
},
{
"name": "type",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1169,
"description": "Removes a global graph input",
"itemtype": "method",
"name": "removeGlobalInput",
"params": [
{
"name": "name",
"description": "",
"type": "String"
},
{
"name": "type",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1190,
"description": "Creates a global graph output",
"itemtype": "method",
"name": "addGlobalOutput",
"params": [
{
"name": "name",
"description": "",
"type": "String"
},
{
"name": "type",
"description": "",
"type": "String"
},
{
"name": "value",
"description": "",
"type": "*"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1208,
"description": "Assign a data to the global output",
"itemtype": "method",
"name": "setGlobalOutputData",
"params": [
{
"name": "name",
"description": "",
"type": "String"
},
{
"name": "value",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1222,
"description": "Returns the current value of a global graph output",
"itemtype": "method",
"name": "getGlobalOutputData",
"params": [
{
"name": "name",
"description": "",
"type": "String"
}
],
"return": {
"description": "the data",
"type": "*"
},
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1236,
"description": "Returns the current value of a global graph output (sames as getGlobalOutputData)",
"itemtype": "method",
"name": "getOutputData",
"params": [
{
"name": "name",
"description": "",
"type": "String"
}
],
"return": {
"description": "the data",
"type": "*"
},
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1245,
"description": "Renames a global graph output",
"itemtype": "method",
"name": "renameGlobalOutput",
"params": [
{
"name": "old_name",
"description": "",
"type": "String"
},
{
"name": "new_name",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1272,
"description": "Changes the type of a global graph output",
"itemtype": "method",
"name": "changeGlobalOutputType",
"params": [
{
"name": "name",
"description": "",
"type": "String"
},
{
"name": "type",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1291,
"description": "Removes a global graph output",
"itemtype": "method",
"name": "removeGlobalOutput",
"params": [
{
"name": "name",
"description": "",
"type": "String"
}
],
"class": "LGraph"
},
{
"file": "../src/litegraph.js",
"line": 1333,
"description": "returns if the graph is in live mode",
"itemtype": "method",
"name": "isLive",
@@ -589,7 +832,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1322,
"line": 1370,
"description": "Creates a Object containing all the info about this graph, it can be serialized",
"itemtype": "method",
"name": "serialize",
@@ -601,7 +844,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1355,
"line": 1403,
"description": "Configure a graph from a JSON string",
"itemtype": "method",
"name": "configure",
@@ -616,7 +859,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1542,
"line": 1590,
"description": "configure a node from an object containing the serialized info",
"itemtype": "method",
"name": "configure",
@@ -624,7 +867,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1638,
"line": 1690,
"description": "serialize the content",
"itemtype": "method",
"name": "serialize",
@@ -632,7 +875,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1714,
"line": 1772,
"description": "serialize and stringify",
"itemtype": "method",
"name": "toString",
@@ -640,7 +883,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1726,
"line": 1784,
"description": "get the title string",
"itemtype": "method",
"name": "getTitle",
@@ -648,7 +891,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1739,
"line": 1797,
"description": "sets the output data",
"itemtype": "method",
"name": "setOutputData",
@@ -668,8 +911,8 @@
},
{
"file": "../src/litegraph.js",
"line": 1775,
"description": "retrieves the input data (data traveling through the connection) from one slot",
"line": 1833,
"description": "Retrieves the input data (data traveling through the connection) from one slot",
"itemtype": "method",
"name": "getInputData",
"params": [
@@ -692,7 +935,31 @@
},
{
"file": "../src/litegraph.js",
"line": 1811,
"line": 1869,
"description": "Retrieves the input data from one slot using its name instead of slot number",
"itemtype": "method",
"name": "getInputDataByName",
"params": [
{
"name": "slot_name",
"description": "",
"type": "String"
},
{
"name": "force_update",
"description": "if set to true it will force the connected node of this slot to output data into this link",
"type": "Boolean"
}
],
"return": {
"description": "data or if it is not connected returns null",
"type": "*"
},
"class": "LGraphNode"
},
{
"file": "../src/litegraph.js",
"line": 1885,
"description": "tells you if there is a connection in one input slot",
"itemtype": "method",
"name": "isInputConnected",
@@ -711,7 +978,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1824,
"line": 1898,
"description": "tells you info about an input connection (which node, type, etc)",
"itemtype": "method",
"name": "getInputInfo",
@@ -730,7 +997,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1839,
"line": 1913,
"description": "returns the node connected in the input slot",
"itemtype": "method",
"name": "getInputNode",
@@ -749,7 +1016,26 @@
},
{
"file": "../src/litegraph.js",
"line": 1860,
"line": 1935,
"description": "returns the value of an input with this name, otherwise checks if there is a property with that name",
"itemtype": "method",
"name": "getInputOrProperty",
"params": [
{
"name": "name",
"description": "",
"type": "String"
}
],
"return": {
"description": "value",
"type": "*"
},
"class": "LGraphNode"
},
{
"file": "../src/litegraph.js",
"line": 1959,
"description": "tells you the last output data that went in that slot",
"itemtype": "method",
"name": "getOutputData",
@@ -768,7 +1054,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1878,
"line": 1977,
"description": "tells you info about an output connection (which node, type, etc)",
"itemtype": "method",
"name": "getOutputInfo",
@@ -787,7 +1073,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1894,
"line": 1993,
"description": "tells you if there is a connection in one output slot",
"itemtype": "method",
"name": "isOutputConnected",
@@ -806,7 +1092,19 @@
},
{
"file": "../src/litegraph.js",
"line": 1907,
"line": 2006,
"description": "tells you if there is any connection in the output slots",
"itemtype": "method",
"name": "isAnyOutputConnected",
"return": {
"description": "",
"type": "Boolean"
},
"class": "LGraphNode"
},
{
"file": "../src/litegraph.js",
"line": 2022,
"description": "retrieves all the nodes connected to this output slot",
"itemtype": "method",
"name": "getOutputNodes",
@@ -825,7 +1123,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1940,
"line": 2055,
"description": "Triggers an event in this node, this will trigger any output with the same name",
"itemtype": "method",
"name": "trigger",
@@ -845,7 +1143,7 @@
},
{
"file": "../src/litegraph.js",
"line": 1963,
"line": 2078,
"description": "Triggers an slot event in this node",
"itemtype": "method",
"name": "triggerSlot",
@@ -865,7 +1163,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2010,
"line": 2125,
"description": "add a new property to this node",
"itemtype": "method",
"name": "addProperty",
@@ -895,7 +1193,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2036,
"line": 2151,
"description": "add a new output slot to use in this node",
"itemtype": "method",
"name": "addOutput",
@@ -920,7 +1218,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2059,
"line": 2174,
"description": "add a new output slot to use in this node",
"itemtype": "method",
"name": "addOutputs",
@@ -935,7 +1233,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2084,
"line": 2199,
"description": "remove an existing output slot",
"itemtype": "method",
"name": "removeOutput",
@@ -950,7 +1248,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2098,
"line": 2213,
"description": "add a new input slot to use in this node",
"itemtype": "method",
"name": "addInput",
@@ -975,7 +1273,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2122,
"line": 2237,
"description": "add several new input slots in this node",
"itemtype": "method",
"name": "addInputs",
@@ -990,7 +1288,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2147,
"line": 2262,
"description": "remove an existing input slot",
"itemtype": "method",
"name": "removeInput",
@@ -1005,7 +1303,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2161,
"line": 2276,
"description": "add an special connection to this node (used for special kinds of graphs)",
"itemtype": "method",
"name": "addConnection",
@@ -1035,7 +1333,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2182,
"line": 2297,
"description": "computes the size of a node according to its inputs and output slots",
"itemtype": "method",
"name": "computeSize",
@@ -1054,7 +1352,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2233,
"line": 2348,
"description": "returns the bounding of the object, used for rendering purposes\nbounding is: [topleft_cornerx, topleft_cornery, width, height]",
"itemtype": "method",
"name": "getBounding",
@@ -1066,7 +1364,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2249,
"line": 2364,
"description": "checks if a point is inside the shape of a node",
"itemtype": "method",
"name": "isPointInsideNode",
@@ -1090,7 +1388,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2273,
"line": 2388,
"description": "checks if a point is inside a node slot, and returns info about which slot",
"itemtype": "method",
"name": "getSlotInPosition",
@@ -1114,7 +1412,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2304,
"line": 2419,
"description": "returns the input slot with a given name (used for dynamic slots), -1 if not found",
"itemtype": "method",
"name": "findInputSlot",
@@ -1133,7 +1431,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2320,
"line": 2435,
"description": "returns the output slot with a given name (used for dynamic slots), -1 if not found",
"itemtype": "method",
"name": "findOutputSlot",
@@ -1152,7 +1450,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2335,
"line": 2450,
"description": "connect this node output to the input of another node",
"itemtype": "method",
"name": "connect",
@@ -1181,7 +1479,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2453,
"line": 2568,
"description": "disconnect one output to an specific node",
"itemtype": "method",
"name": "disconnectOutput",
@@ -1205,7 +1503,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2543,
"line": 2658,
"description": "disconnect one input",
"itemtype": "method",
"name": "disconnectInput",
@@ -1224,7 +1522,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2611,
"line": 2726,
"description": "returns the center of a connection point in canvas coords",
"itemtype": "method",
"name": "getConnectionPos",
@@ -1248,7 +1546,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2745,
"line": 2860,
"description": "Collapse the node to make it smaller on the canvas",
"itemtype": "method",
"name": "collapse",
@@ -1256,7 +1554,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2758,
"line": 2873,
"description": "Forces the node to do not move or realign on Z",
"itemtype": "method",
"name": "pin",
@@ -1264,7 +1562,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2852,
"line": 2974,
"description": "clears all the data inside",
"itemtype": "method",
"name": "clear",
@@ -1272,7 +1570,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2891,
"line": 3013,
"description": "assigns a graph, you can reasign graphs to the same canvas",
"itemtype": "method",
"name": "setGraph",
@@ -1287,7 +1585,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2922,
"line": 3044,
"description": "opens a graph contained inside a node in the current graph",
"itemtype": "method",
"name": "openSubgraph",
@@ -1302,7 +1600,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2949,
"line": 3071,
"description": "closes a subgraph contained inside a node",
"itemtype": "method",
"name": "closeSubgraph",
@@ -1317,7 +1615,7 @@
},
{
"file": "../src/litegraph.js",
"line": 2966,
"line": 3088,
"description": "assigns a canvas",
"itemtype": "method",
"name": "setCanvas",
@@ -1332,7 +1630,7 @@
},
{
"file": "../src/litegraph.js",
"line": 3219,
"line": 3341,
"description": "Used to attach the canvas in a popup",
"itemtype": "method",
"name": "getCanvasWindow",
@@ -1344,7 +1642,7 @@
},
{
"file": "../src/litegraph.js",
"line": 3233,
"line": 3355,
"description": "starts rendering the content of the canvas when needed",
"itemtype": "method",
"name": "startRendering",
@@ -1352,7 +1650,7 @@
},
{
"file": "../src/litegraph.js",
"line": 3257,
"line": 3379,
"description": "stops rendering the content of the canvas (to save resources)",
"itemtype": "method",
"name": "stopRendering",

View File

@@ -170,7 +170,7 @@ var LiteGraph = global.LiteGraph = {
console.log(&quot;Node registered: &quot; + type);
var categories = type.split(&quot;/&quot;);
var classname = base_class.constructor.name;
var classname = base_class.name;
var pos = type.lastIndexOf(&quot;/&quot;);
base_class.category = type.substr(0,pos);
@@ -184,7 +184,7 @@ var LiteGraph = global.LiteGraph = {
for(var i in LGraphNode.prototype)
if(!base_class.prototype[i])
base_class.prototype[i] = LGraphNode.prototype[i];
Object.defineProperty( base_class.prototype, &quot;shape&quot;,{
set: function(v) {
switch(v)
@@ -291,7 +291,7 @@ var LiteGraph = global.LiteGraph = {
var node = new base_class( title );
node.type = type;
if(!node.title) node.title = title;
if(!node.title &amp;&amp; title) node.title = title;
if(!node.properties) node.properties = {};
if(!node.properties_info) node.properties_info = [];
if(!node.flags) node.flags = {};
@@ -421,7 +421,7 @@ var LiteGraph = global.LiteGraph = {
if( !type_a || //generic output
!type_b || //generic input
type_a == type_b || //same type (is valid for triggers)
type_a == LiteGraph.EVENT &amp;&amp; type_b == LiteGraph.ACTION )
type_a == LiteGraph.EVENT &amp;&amp; type_b == LiteGraph.ACTION )
return true;
type_a = type_a.toLowerCase();
@@ -431,9 +431,9 @@ var LiteGraph = global.LiteGraph = {
var supported_types_a = type_a.split(&quot;,&quot;);
var supported_types_b = type_b.split(&quot;,&quot;);
for(var i = 0; i &lt; supported_types_a.length; ++i)
for(var j = 0; j &lt; supported_types_b.length; ++j)
if( supported_types_a[i] == supported_types_b[i] )
for(var i = 0; i &lt; supported_types_a.length; ++i)
for(var j = 0; j &lt; supported_types_b.length; ++j)
if( supported_types_a[i] == supported_types_b[j] )
return true;
return false;
}
@@ -524,7 +524,7 @@ LGraph.prototype.clear = function()
this.catch_errors = true;
//globals
//subgraph_data
this.global_inputs = {};
this.global_outputs = {};
@@ -1112,7 +1112,7 @@ LGraph.prototype.findNodesByType = function(type)
/**
* Returns a list of nodes that matches a name
* @method findNodesByName
* @method findNodesByTitle
* @param {String} name the name of the node to search
* @return {Array} a list with all the nodes with this name
*/
@@ -1134,7 +1134,6 @@ LGraph.prototype.findNodesByTitle = function(title)
* @param {Array} nodes_list a list with all the nodes to search from, by default is all the nodes in the graph
* @return {Array} a list with all the nodes that intersect this coordinate
*/
LGraph.prototype.getNodeOnPos = function(x,y, nodes_list)
{
nodes_list = nodes_list || this._nodes;
@@ -1149,7 +1148,13 @@ LGraph.prototype.getNodeOnPos = function(x,y, nodes_list)
// ********** GLOBALS *****************
//Tell this graph has a global input of this type
/**
* Tell this graph it has a global graph input of this type
* @method addGlobalInput
* @param {String} name
* @param {String} type
* @param {*} value [optional]
*/
LGraph.prototype.addGlobalInput = function(name, type, value)
{
this.global_inputs[name] = { name: name, type: type, value: value };
@@ -1161,7 +1166,12 @@ LGraph.prototype.addGlobalInput = function(name, type, value)
this.onGlobalsChange();
}
//assign a data to the global input
/**
* Assign a data to the global graph input
* @method setGlobalInputData
* @param {String} name
* @param {*} data
*/
LGraph.prototype.setGlobalInputData = function(name, data)
{
var input = this.global_inputs[name];
@@ -1170,7 +1180,21 @@ LGraph.prototype.setGlobalInputData = function(name, data)
input.value = data;
}
//assign a data to the global input
/**
* Assign a data to the global graph input (same as setGlobalInputData)
* @method setInputData
* @param {String} name
* @param {*} data
*/
LGraph.prototype.setInputData = LGraph.prototype.setGlobalInputData;
/**
* Returns the current value of a global graph input
* @method getGlobalInputData
* @param {String} name
* @return {*} the data
*/
LGraph.prototype.getGlobalInputData = function(name)
{
var input = this.global_inputs[name];
@@ -1179,7 +1203,12 @@ LGraph.prototype.getGlobalInputData = function(name)
return input.value;
}
//rename the global input
/**
* Changes the name of a global graph input
* @method renameGlobalInput
* @param {String} old_name
* @param {String} new_name
*/
LGraph.prototype.renameGlobalInput = function(old_name, name)
{
if(name == old_name)
@@ -1204,6 +1233,12 @@ LGraph.prototype.renameGlobalInput = function(old_name, name)
this.onGlobalsChange();
}
/**
* Changes the type of a global graph input
* @method changeGlobalInputType
* @param {String} name
* @param {String} type
*/
LGraph.prototype.changeGlobalInputType = function(name, type)
{
if(!this.global_inputs[name])
@@ -1217,6 +1252,12 @@ LGraph.prototype.changeGlobalInputType = function(name, type)
this.onGlobalInputTypeChanged(name, type);
}
/**
* Removes a global graph input
* @method removeGlobalInput
* @param {String} name
* @param {String} type
*/
LGraph.prototype.removeGlobalInput = function(name)
{
if(!this.global_inputs[name])
@@ -1232,7 +1273,13 @@ LGraph.prototype.removeGlobalInput = function(name)
return true;
}
/**
* Creates a global graph output
* @method addGlobalOutput
* @param {String} name
* @param {String} type
* @param {*} value
*/
LGraph.prototype.addGlobalOutput = function(name, type, value)
{
this.global_outputs[name] = { name: name, type: type, value: value };
@@ -1244,7 +1291,12 @@ LGraph.prototype.addGlobalOutput = function(name, type, value)
this.onGlobalsChange();
}
//assign a data to the global output
/**
* Assign a data to the global output
* @method setGlobalOutputData
* @param {String} name
* @param {String} value
*/
LGraph.prototype.setGlobalOutputData = function(name, value)
{
var output = this.global_outputs[ name ];
@@ -1253,7 +1305,12 @@ LGraph.prototype.setGlobalOutputData = function(name, value)
output.value = value;
}
//assign a data to the global input
/**
* Returns the current value of a global graph output
* @method getGlobalOutputData
* @param {String} name
* @return {*} the data
*/
LGraph.prototype.getGlobalOutputData = function(name)
{
var output = this.global_outputs[name];
@@ -1262,8 +1319,21 @@ LGraph.prototype.getGlobalOutputData = function(name)
return output.value;
}
/**
* Returns the current value of a global graph output (sames as getGlobalOutputData)
* @method getOutputData
* @param {String} name
* @return {*} the data
*/
LGraph.prototype.getOutputData = LGraph.prototype.getGlobalOutputData;
//rename the global output
/**
* Renames a global graph output
* @method renameGlobalOutput
* @param {String} old_name
* @param {String} new_name
*/
LGraph.prototype.renameGlobalOutput = function(old_name, name)
{
if(!this.global_outputs[old_name])
@@ -1285,6 +1355,12 @@ LGraph.prototype.renameGlobalOutput = function(old_name, name)
this.onGlobalsChange();
}
/**
* Changes the type of a global graph output
* @method changeGlobalOutputType
* @param {String} name
* @param {String} type
*/
LGraph.prototype.changeGlobalOutputType = function(name, type)
{
if(!this.global_outputs[name])
@@ -1298,6 +1374,11 @@ LGraph.prototype.changeGlobalOutputType = function(name, type)
this.onGlobalOutputTypeChanged(name, type);
}
/**
* Removes a global graph output
* @method removeGlobalOutput
* @param {String} name
*/
LGraph.prototype.removeGlobalOutput = function(name)
{
if(!this.global_outputs[name])
@@ -1312,49 +1393,16 @@ LGraph.prototype.removeGlobalOutput = function(name)
return true;
}
/**
* Assigns a value to all the nodes that matches this name. This is used to create global variables of the node that
* can be easily accesed from the outside of the graph
* @method setInputData
* @param {String} name the name of the node
* @param {*} value value to assign to this node
*/
LGraph.prototype.setInputData = function(name,value)
{
var nodes = this.findNodesByName( name );
for(var i = 0, l = nodes.length; i &lt; l; ++i)
nodes[i].setValue(value);
}
/**
* Returns the value of the first node with this name. This is used to access global variables of the graph from the outside
* @method setInputData
* @param {String} name the name of the node
* @return {*} value of the node
*/
LGraph.prototype.getOutputData = function(name)
{
var n = this.findNodesByName(name);
if(n.length)
return m[0].getValue();
return null;
}
//This feature is not finished yet, is to create graphs where nodes are not executed unless a trigger message is received
LGraph.prototype.triggerInput = function(name,value)
{
var nodes = this.findNodesByName(name);
var nodes = this.findNodesByTitle(name);
for(var i = 0; i &lt; nodes.length; ++i)
nodes[i].onTrigger(value);
}
LGraph.prototype.setCallback = function(name,func)
{
var nodes = this.findNodesByName(name);
var nodes = this.findNodesByTitle(name);
for(var i = 0; i &lt; nodes.length; ++i)
nodes[i].setTrigger(func);
}
@@ -1578,7 +1626,7 @@ LGraph.prototype.onNodeTrace = function(node, msg, color)
function LGraphNode(title)
{
this._ctor();
this._ctor(title);
}
global.LGraphNode = LiteGraph.LGraphNode = LGraphNode;
@@ -1650,6 +1698,7 @@ LGraphNode.prototype.configure = function(info)
if(info[j] == null)
continue;
else if (typeof(info[j]) == &#x27;object&#x27;) //object
{
if(this[j] &amp;&amp; this[j].configure)
@@ -1661,6 +1710,9 @@ LGraphNode.prototype.configure = function(info)
this[j] = info[j];
}
if(!info.title)
this.title = this.constructor.title;
if(this.onConnectionsChange)
{
if(this.inputs)
@@ -1728,25 +1780,31 @@ LGraphNode.prototype.configure = function(info)
LGraphNode.prototype.serialize = function()
{
//clear outputs last data (because data in connections is never serialized but stored inside the outputs info)
if(this.outputs)
for(var i = 0; i &lt; this.outputs.length; i++)
delete this.outputs[i]._data;
//create serialization object
var o = {
id: this.id,
title: this.title,
type: this.type,
pos: this.pos,
size: this.size,
data: this.data,
flags: LiteGraph.cloneObject(this.flags),
inputs: this.inputs,
outputs: this.outputs,
mode: this.mode
};
if(this.inputs)
o.inputs = this.inputs;
if(this.outputs)
{
//clear outputs last data (because data in connections is never serialized but stored inside the outputs info)
for(var i = 0; i &lt; this.outputs.length; i++)
delete this.outputs[i]._data;
o.outputs = this.outputs;
}
if( this.title &amp;&amp; this.title != this.constructor.title )
o.title = this.title;
if(this.properties)
o.properties = LiteGraph.cloneObject(this.properties);
@@ -1859,7 +1917,7 @@ LGraphNode.prototype.setOutputData = function(slot, data)
}
/**
* retrieves the input data (data traveling through the connection) from one slot
* Retrieves the input data (data traveling through the connection) from one slot
* @method getInputData
* @param {number} slot
* @param {boolean} force_update if set to true it will force the connected node of this slot to output data into this link
@@ -1878,10 +1936,10 @@ LGraphNode.prototype.getInputData = function( slot, force_update )
if(!link) //bug: weird case but it happens sometimes
return null;
//used to extract data from the incomming connection
if(!force_update)
return link.data;
//special case: used to extract data from the incomming connection before the graph has been executed
var node = this.graph.getNodeById( link.origin_id );
if(!node)
return link.data;
@@ -1894,6 +1952,22 @@ LGraphNode.prototype.getInputData = function( slot, force_update )
return link.data;
}
/**
* Retrieves the input data from one slot using its name instead of slot number
* @method getInputDataByName
* @param {String} slot_name
* @param {boolean} force_update if set to true it will force the connected node of this slot to output data into this link
* @return {*} data or if it is not connected returns null
*/
LGraphNode.prototype.getInputDataByName = function( slot_name, force_update )
{
var slot = this.findInputSlot( slot_name );
if( slot == -1 )
return null;
return this.getInputData( slot, force_update );
}
/**
* tells you if there is a connection in one input slot
* @method isInputConnected
@@ -1943,6 +2017,31 @@ LGraphNode.prototype.getInputNode = function( slot )
return this.graph.getNodeById( link_info.origin_id );
}
/**
* returns the value of an input with this name, otherwise checks if there is a property with that name
* @method getInputOrProperty
* @param {string} name
* @return {*} value
*/
LGraphNode.prototype.getInputOrProperty = function( name )
{
if(!this.inputs || !this.inputs.length)
return this.properties ? this.properties[name] : null;
for(var i = 0, l = this.inputs.length; i &lt; l; ++i)
if(name == this.inputs[i].name)
{
var link_id = this.inputs[i].link;
var link = this.graph.links[ link_id ];
return link ? link.data : null;
}
return this.properties[name];
}
/**
* tells you the last output data that went in that slot
* @method getOutputData
@@ -1986,10 +2085,26 @@ LGraphNode.prototype.getOutputInfo = function(slot)
LGraphNode.prototype.isOutputConnected = function(slot)
{
if(!this.outputs)
return null;
return false;
return (slot &lt; this.outputs.length &amp;&amp; this.outputs[slot].links &amp;&amp; this.outputs[slot].links.length);
}
/**
* tells you if there is any connection in the output slots
* @method isAnyOutputConnected
* @return {boolean}
*/
LGraphNode.prototype.isAnyOutputConnected = function()
{
if(!this.outputs)
return false;
for(var i = 0; i &lt; this.outputs.length; ++i)
if( this.outputs[i].links &amp;&amp; this.outputs[i].links.length )
return true;
return false;
}
/**
* retrieves all the nodes connected to this output slot
* @method getOutputNodes
@@ -2893,6 +3008,12 @@ function LGraphCanvas( canvas, graph, options )
this.title_text_font = &quot;bold 14px Arial&quot;;
this.inner_text_font = &quot;normal 12px Arial&quot;;
this.default_link_color = &quot;#AAC&quot;;
this.default_connection_color = {
input_off: &quot;#AAB&quot;,
input_on: &quot;#7F7&quot;,
output_off: &quot;#AAB&quot;,
output_on: &quot;#7F7&quot;
};
this.highquality_render = true;
this.editor_alpha = 1; //used for transition
@@ -2910,6 +3031,7 @@ function LGraphCanvas( canvas, graph, options )
this.dragging_rectangle = null;
this.always_render_background = false;
this.render_canvas_area = true;
this.render_connections_shadows = false; //too much cpu
this.render_connections_border = true;
this.render_curved_connections = true;
@@ -3133,7 +3255,7 @@ LGraphCanvas.prototype.bindEvents = function()
var canvas = this.canvas;
var ref_window = this.getCanvasWindow();
var document = ref_window.document; //hack used when moving canvas between windows
var document = ref_window.document; //hack used when moving canvas between windows
this._mousedown_callback = this.processMouseDown.bind(this);
this._mousewheel_callback = this.processMouseWheel.bind(this);
@@ -4623,8 +4745,10 @@ LGraphCanvas.prototype.drawBackCanvas = function()
//ctx.fillRect( this.visible_area[0] + 10, this.visible_area[1] + 10, this.visible_area[2] - 20, this.visible_area[3] - 20);
//bg
ctx.strokeStyle = &quot;#235&quot;;
ctx.strokeRect(0,0,canvas.width,canvas.height);
if (this.render_canvas_area) {
ctx.strokeStyle = &quot;#235&quot;;
ctx.strokeRect(0,0,canvas.width,canvas.height);
}
if(this.render_connections_shadows)
{
@@ -4776,7 +4900,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
if ( this.connecting_node &amp;&amp; LiteGraph.isValidConnection( slot.type &amp;&amp; out_slot.type ) )
ctx.globalAlpha = 0.4 * editor_alpha;
ctx.fillStyle = slot.link != null ? &quot;#7F7&quot; : &quot;#AAA&quot;;
ctx.fillStyle = slot.link != null ? this.default_connection_color.input_on : this.default_connection_color.input_off;
var pos = node.getConnectionPos(true,i);
pos[0] -= node.pos[0];
@@ -4820,7 +4944,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
pos[0] -= node.pos[0];
pos[1] -= node.pos[1];
ctx.fillStyle = slot.links &amp;&amp; slot.links.length ? &quot;#7F7&quot; : &quot;#AAA&quot;;
ctx.fillStyle = slot.links &amp;&amp; slot.links.length ? this.default_connection_color.output_on : this.default_connection_color.output_off;
ctx.beginPath();
//ctx.rect( node.size[0] - 14,i*14,10,10);
@@ -6013,7 +6137,7 @@ LGraphCanvas.prototype.processContextMenu = function( node, event )
if( slot_info )
slot_info.label = input.value;
that.setDirty(true);
}
}
dialog.close();
});
}
@@ -6525,15 +6649,18 @@ LiteGraph.extendClass = function ( target, origin )
}
}
LiteGraph.getParameterNames = function(func) {
//used to create nodes from wrapping functions
LiteGraph.getParameterNames = function(func) {
return (func + &#x27;&#x27;)
.replace(/[/][/].*$/mg,&#x27;&#x27;) // strip single-line comments
.replace(/\s+/g, &#x27;&#x27;) // strip white space
.replace(/[/][*][^/*]*[*][/]/g, &#x27;&#x27;) // strip multi-line comments /**/
.split(&#x27;){&#x27;, 1)[0].replace(/^[^(]*[(]/, &#x27;&#x27;) // extract the parameters
.replace(/=[^,]+/g, &#x27;&#x27;) // strip any ES6 defaults
.split(&#x27;){&#x27;, 1)[0].replace(/^[^(]*[(]/, &#x27;&#x27;) // extract the parameters
.replace(/=[^,]+/g, &#x27;&#x27;) // strip any ES6 defaults
.split(&#x27;,&#x27;).filter(Boolean); // split &amp; filter [&quot;&quot;]
}
}
Math.clamp = function(v,a,b) { return (a &gt; v ? a : (b &lt; v ? b : v)); }
if( typeof(window) != &quot;undefined&quot; &amp;&amp; !window[&quot;requestAnimationFrame&quot;] )
{

View File

@@ -12,7 +12,8 @@ module.exports = function (grunt) {
'src/nodes/gltextures.js',
'src/nodes/glfx.js',
'src/nodes/midi.js',
'src/nodes/audio.js'
'src/nodes/audio.js',
'src/nodes/network.js'
],
concat: {
build: {
@@ -20,9 +21,6 @@ module.exports = function (grunt) {
dest: 'build/litegraph.js'
}
},
clean: {
build: {src: ['build/*']}
},
closureCompiler: {
options: {
@@ -42,28 +40,8 @@ module.exports = function (grunt) {
}
})
// grunt.registerTask('buildPackage', function () {
// var pkg = grunt.config.data.pkg
// var newPackage = {
// version: pkg.version,
// name: 'litegraph.js', //* Static name without ogranisation
// main: 'litegraph.js',
// description: pkg.description,
// dependencies: pkg.dependencies,
// author: pkg.author,
// license: 'MIT',
// scripts: {
// }
// }
// grunt.file.write('build/package.json', JSON.stringify(newPackage, undefined, 2))
// })
grunt.loadNpmTasks('grunt-contrib-concat')
grunt.loadNpmTasks('grunt-contrib-copy')
grunt.loadNpmTasks('grunt-closure-tools')
grunt.loadNpmTasks('grunt-contrib-clean')
grunt.registerTask('build', ['concat:build', 'closureCompiler'])
}

View File

@@ -26,6 +26,18 @@ Slots have the next information:
To retrieve the data traveling through a link you can call node.getInputData or node.getOutputData
### Define your Graph Node
When creating a class for a graph node here are some useful points:
- The constructor should create the default inputs and outputs (use ```addInput``` and ```addOutput```)
- Properties that can be edited are stored in ```this.properties = {};```
- the ```onExecute``` is the method that will be called when the graph is executed
- you can catch if a property was changed defining a ```onPropertyChanged```
- you must register your node using ```LiteGraph.registerNodeType("type/name", MyGraphNodeClass );```
- you can alter the default priority of execution by defining the ```MyGraphNodeClass.priority``` (default is 0)
- you can overwrite how the node is rendered using the ```onDrawBackground``` and ```onDrawForeground```
## Integration

3367
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "litegraph.js",
"version": "0.3.0",
"version": "0.6.0",
"description": "A graph node editor similar to PD or UDK Blueprints, it works in a HTML5 Canvas and allow to exported graphs to be included in applications.",
"main": "build/litegraph.js",
"directories": {
@@ -8,9 +8,9 @@
},
"private": false,
"scripts": {
"prebuild": "grunt clean:build",
"prebuild": "rimraf build",
"build": "grunt build",
"start": "npx nodemon utils/server.js",
"start": "nodemon utils/server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@@ -31,10 +31,10 @@
"express": "^4.16.2",
"google-closure-compiler": "^20171112.0.0",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-closure-tools": "^1.0.0",
"grunt-contrib-clean": "^1.1.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-copy": "^1.0.0",
"nodemon": "^1.14.7"
"nodemon": "^1.14.7",
"rimraf": "^2.6.2"
}
}

View File

@@ -84,7 +84,7 @@ var LiteGraph = global.LiteGraph = {
console.log("Node registered: " + type);
var categories = type.split("/");
var classname = base_class.constructor.name;
var classname = base_class.name;
var pos = type.lastIndexOf("/");
base_class.category = type.substr(0,pos);
@@ -205,7 +205,7 @@ var LiteGraph = global.LiteGraph = {
var node = new base_class( title );
node.type = type;
if(!node.title) node.title = title;
if(!node.title && title) node.title = title;
if(!node.properties) node.properties = {};
if(!node.properties_info) node.properties_info = [];
if(!node.flags) node.flags = {};
@@ -336,7 +336,10 @@ var LiteGraph = global.LiteGraph = {
!type_b || //generic input
type_a == type_b || //same type (is valid for triggers)
type_a == LiteGraph.EVENT && type_b == LiteGraph.ACTION )
return true;
return true;
type_a = String(type_a) //* Enforce string type to handle toLowerCase call (-1 number not ok)
type_b = String(type_b)
type_a = type_a.toLowerCase();
type_b = type_b.toLowerCase();
@@ -438,7 +441,7 @@ LGraph.prototype.clear = function()
this.catch_errors = true;
//globals
//subgraph_data
this.global_inputs = {};
this.global_outputs = {};
@@ -726,8 +729,23 @@ LGraph.prototype.computeExecutionOrder = function( only_onExecute, set_level )
if( L.length != this._nodes.length && LiteGraph.debug )
console.warn("something went wrong, nodes missing");
var l = L.length;
//save order number in the node
for(var i = 0; i < L.length; ++i)
for(var i = 0; i < l; ++i)
L[i].order = i;
//sort now by priority
L = L.sort(function(A,B){
var Ap = A.constructor.priority || A.priority || 0;
var Bp = B.constructor.priority || B.priority || 0;
if(Ap == Bp)
return A.order - B.order;
return Ap - Bp;
});
//save order number in the node, again...
for(var i = 0; i < l; ++i)
L[i].order = i;
return L;
@@ -1026,7 +1044,7 @@ LGraph.prototype.findNodesByType = function(type)
/**
* Returns a list of nodes that matches a name
* @method findNodesByName
* @method findNodesByTitle
* @param {String} name the name of the node to search
* @return {Array} a list with all the nodes with this name
*/
@@ -1048,7 +1066,6 @@ LGraph.prototype.findNodesByTitle = function(title)
* @param {Array} nodes_list a list with all the nodes to search from, by default is all the nodes in the graph
* @return {Array} a list with all the nodes that intersect this coordinate
*/
LGraph.prototype.getNodeOnPos = function(x,y, nodes_list)
{
nodes_list = nodes_list || this._nodes;
@@ -1063,7 +1080,13 @@ LGraph.prototype.getNodeOnPos = function(x,y, nodes_list)
// ********** GLOBALS *****************
//Tell this graph has a global input of this type
/**
* Tell this graph it has a global graph input of this type
* @method addGlobalInput
* @param {String} name
* @param {String} type
* @param {*} value [optional]
*/
LGraph.prototype.addGlobalInput = function(name, type, value)
{
this.global_inputs[name] = { name: name, type: type, value: value };
@@ -1075,7 +1098,12 @@ LGraph.prototype.addGlobalInput = function(name, type, value)
this.onGlobalsChange();
}
//assign a data to the global input
/**
* Assign a data to the global graph input
* @method setGlobalInputData
* @param {String} name
* @param {*} data
*/
LGraph.prototype.setGlobalInputData = function(name, data)
{
var input = this.global_inputs[name];
@@ -1084,7 +1112,21 @@ LGraph.prototype.setGlobalInputData = function(name, data)
input.value = data;
}
//assign a data to the global input
/**
* Assign a data to the global graph input (same as setGlobalInputData)
* @method setInputData
* @param {String} name
* @param {*} data
*/
LGraph.prototype.setInputData = LGraph.prototype.setGlobalInputData;
/**
* Returns the current value of a global graph input
* @method getGlobalInputData
* @param {String} name
* @return {*} the data
*/
LGraph.prototype.getGlobalInputData = function(name)
{
var input = this.global_inputs[name];
@@ -1093,7 +1135,12 @@ LGraph.prototype.getGlobalInputData = function(name)
return input.value;
}
//rename the global input
/**
* Changes the name of a global graph input
* @method renameGlobalInput
* @param {String} old_name
* @param {String} new_name
*/
LGraph.prototype.renameGlobalInput = function(old_name, name)
{
if(name == old_name)
@@ -1118,6 +1165,12 @@ LGraph.prototype.renameGlobalInput = function(old_name, name)
this.onGlobalsChange();
}
/**
* Changes the type of a global graph input
* @method changeGlobalInputType
* @param {String} name
* @param {String} type
*/
LGraph.prototype.changeGlobalInputType = function(name, type)
{
if(!this.global_inputs[name])
@@ -1131,6 +1184,12 @@ LGraph.prototype.changeGlobalInputType = function(name, type)
this.onGlobalInputTypeChanged(name, type);
}
/**
* Removes a global graph input
* @method removeGlobalInput
* @param {String} name
* @param {String} type
*/
LGraph.prototype.removeGlobalInput = function(name)
{
if(!this.global_inputs[name])
@@ -1146,7 +1205,13 @@ LGraph.prototype.removeGlobalInput = function(name)
return true;
}
/**
* Creates a global graph output
* @method addGlobalOutput
* @param {String} name
* @param {String} type
* @param {*} value
*/
LGraph.prototype.addGlobalOutput = function(name, type, value)
{
this.global_outputs[name] = { name: name, type: type, value: value };
@@ -1158,7 +1223,12 @@ LGraph.prototype.addGlobalOutput = function(name, type, value)
this.onGlobalsChange();
}
//assign a data to the global output
/**
* Assign a data to the global output
* @method setGlobalOutputData
* @param {String} name
* @param {String} value
*/
LGraph.prototype.setGlobalOutputData = function(name, value)
{
var output = this.global_outputs[ name ];
@@ -1167,7 +1237,12 @@ LGraph.prototype.setGlobalOutputData = function(name, value)
output.value = value;
}
//assign a data to the global input
/**
* Returns the current value of a global graph output
* @method getGlobalOutputData
* @param {String} name
* @return {*} the data
*/
LGraph.prototype.getGlobalOutputData = function(name)
{
var output = this.global_outputs[name];
@@ -1176,8 +1251,21 @@ LGraph.prototype.getGlobalOutputData = function(name)
return output.value;
}
/**
* Returns the current value of a global graph output (sames as getGlobalOutputData)
* @method getOutputData
* @param {String} name
* @return {*} the data
*/
LGraph.prototype.getOutputData = LGraph.prototype.getGlobalOutputData;
//rename the global output
/**
* Renames a global graph output
* @method renameGlobalOutput
* @param {String} old_name
* @param {String} new_name
*/
LGraph.prototype.renameGlobalOutput = function(old_name, name)
{
if(!this.global_outputs[old_name])
@@ -1199,6 +1287,12 @@ LGraph.prototype.renameGlobalOutput = function(old_name, name)
this.onGlobalsChange();
}
/**
* Changes the type of a global graph output
* @method changeGlobalOutputType
* @param {String} name
* @param {String} type
*/
LGraph.prototype.changeGlobalOutputType = function(name, type)
{
if(!this.global_outputs[name])
@@ -1212,6 +1306,11 @@ LGraph.prototype.changeGlobalOutputType = function(name, type)
this.onGlobalOutputTypeChanged(name, type);
}
/**
* Removes a global graph output
* @method removeGlobalOutput
* @param {String} name
*/
LGraph.prototype.removeGlobalOutput = function(name)
{
if(!this.global_outputs[name])
@@ -1226,49 +1325,16 @@ LGraph.prototype.removeGlobalOutput = function(name)
return true;
}
/**
* Assigns a value to all the nodes that matches this name. This is used to create global variables of the node that
* can be easily accesed from the outside of the graph
* @method setInputData
* @param {String} name the name of the node
* @param {*} value value to assign to this node
*/
LGraph.prototype.setInputData = function(name,value)
{
var nodes = this.findNodesByName( name );
for(var i = 0, l = nodes.length; i < l; ++i)
nodes[i].setValue(value);
}
/**
* Returns the value of the first node with this name. This is used to access global variables of the graph from the outside
* @method setInputData
* @param {String} name the name of the node
* @return {*} value of the node
*/
LGraph.prototype.getOutputData = function(name)
{
var n = this.findNodesByName(name);
if(n.length)
return m[0].getValue();
return null;
}
//This feature is not finished yet, is to create graphs where nodes are not executed unless a trigger message is received
LGraph.prototype.triggerInput = function(name,value)
{
var nodes = this.findNodesByName(name);
var nodes = this.findNodesByTitle(name);
for(var i = 0; i < nodes.length; ++i)
nodes[i].onTrigger(value);
}
LGraph.prototype.setCallback = function(name,func)
{
var nodes = this.findNodesByName(name);
var nodes = this.findNodesByTitle(name);
for(var i = 0; i < nodes.length; ++i)
nodes[i].setTrigger(func);
}
@@ -1492,7 +1558,7 @@ LGraph.prototype.onNodeTrace = function(node, msg, color)
function LGraphNode(title)
{
this._ctor();
this._ctor(title);
}
global.LGraphNode = LiteGraph.LGraphNode = LGraphNode;
@@ -1564,6 +1630,7 @@ LGraphNode.prototype.configure = function(info)
if(info[j] == null)
continue;
else if (typeof(info[j]) == 'object') //object
{
if(this[j] && this[j].configure)
@@ -1575,6 +1642,9 @@ LGraphNode.prototype.configure = function(info)
this[j] = info[j];
}
if(!info.title)
this.title = this.constructor.title;
if(this.onConnectionsChange)
{
if(this.inputs)
@@ -1642,25 +1712,31 @@ LGraphNode.prototype.configure = function(info)
LGraphNode.prototype.serialize = function()
{
//clear outputs last data (because data in connections is never serialized but stored inside the outputs info)
if(this.outputs)
for(var i = 0; i < this.outputs.length; i++)
delete this.outputs[i]._data;
//create serialization object
var o = {
id: this.id,
title: this.title,
type: this.type,
pos: this.pos,
size: this.size,
data: this.data,
flags: LiteGraph.cloneObject(this.flags),
inputs: this.inputs,
outputs: this.outputs,
mode: this.mode
};
if(this.inputs)
o.inputs = this.inputs;
if(this.outputs)
{
//clear outputs last data (because data in connections is never serialized but stored inside the outputs info)
for(var i = 0; i < this.outputs.length; i++)
delete this.outputs[i]._data;
o.outputs = this.outputs;
}
if( this.title && this.title != this.constructor.title )
o.title = this.title;
if(this.properties)
o.properties = LiteGraph.cloneObject(this.properties);
@@ -1773,7 +1849,7 @@ LGraphNode.prototype.setOutputData = function(slot, data)
}
/**
* retrieves the input data (data traveling through the connection) from one slot
* Retrieves the input data (data traveling through the connection) from one slot
* @method getInputData
* @param {number} slot
* @param {boolean} force_update if set to true it will force the connected node of this slot to output data into this link
@@ -1792,10 +1868,10 @@ LGraphNode.prototype.getInputData = function( slot, force_update )
if(!link) //bug: weird case but it happens sometimes
return null;
//used to extract data from the incomming connection
if(!force_update)
return link.data;
//special case: used to extract data from the incomming connection before the graph has been executed
var node = this.graph.getNodeById( link.origin_id );
if(!node)
return link.data;
@@ -1808,6 +1884,22 @@ LGraphNode.prototype.getInputData = function( slot, force_update )
return link.data;
}
/**
* Retrieves the input data from one slot using its name instead of slot number
* @method getInputDataByName
* @param {String} slot_name
* @param {boolean} force_update if set to true it will force the connected node of this slot to output data into this link
* @return {*} data or if it is not connected returns null
*/
LGraphNode.prototype.getInputDataByName = function( slot_name, force_update )
{
var slot = this.findInputSlot( slot_name );
if( slot == -1 )
return null;
return this.getInputData( slot, force_update );
}
/**
* tells you if there is a connection in one input slot
* @method isInputConnected
@@ -1857,6 +1949,31 @@ LGraphNode.prototype.getInputNode = function( slot )
return this.graph.getNodeById( link_info.origin_id );
}
/**
* returns the value of an input with this name, otherwise checks if there is a property with that name
* @method getInputOrProperty
* @param {string} name
* @return {*} value
*/
LGraphNode.prototype.getInputOrProperty = function( name )
{
if(!this.inputs || !this.inputs.length)
return this.properties ? this.properties[name] : null;
for(var i = 0, l = this.inputs.length; i < l; ++i)
if(name == this.inputs[i].name)
{
var link_id = this.inputs[i].link;
var link = this.graph.links[ link_id ];
return link ? link.data : null;
}
return this.properties[name];
}
/**
* tells you the last output data that went in that slot
* @method getOutputData
@@ -1900,10 +2017,26 @@ LGraphNode.prototype.getOutputInfo = function(slot)
LGraphNode.prototype.isOutputConnected = function(slot)
{
if(!this.outputs)
return null;
return false;
return (slot < this.outputs.length && this.outputs[slot].links && this.outputs[slot].links.length);
}
/**
* tells you if there is any connection in the output slots
* @method isAnyOutputConnected
* @return {boolean}
*/
LGraphNode.prototype.isAnyOutputConnected = function()
{
if(!this.outputs)
return false;
for(var i = 0; i < this.outputs.length; ++i)
if( this.outputs[i].links && this.outputs[i].links.length )
return true;
return false;
}
/**
* retrieves all the nodes connected to this output slot
* @method getOutputNodes
@@ -2810,10 +2943,10 @@ function LGraphCanvas( canvas, graph, options )
this.node_title_color = LiteGraph.NODE_TITLE_COLOR;
this.default_link_color = "#AAC";
this.default_connection_color = {
input_off: "#AAC",
input_off: "#AAB",
input_on: "#7F7",
output_off: "#AAC",
output_on: "#7F7",
output_off: "#AAB",
output_on: "#7F7"
};
this.highquality_render = true;
@@ -6160,6 +6293,17 @@ function ContextMenu( values, options )
}
}, true);
function on_mouse_wheel(e)
{
var pos = parseInt( root.style.top );
root.style.top = (pos + e.deltaY * 0.1).toFixed() + "px";
e.preventDefault();
return true;
}
root.addEventListener("wheel", on_mouse_wheel, true);
root.addEventListener("mousewheel", on_mouse_wheel, true);
this.root = root;
@@ -6453,6 +6597,7 @@ LiteGraph.extendClass = function ( target, origin )
}
}
//used to create nodes from wrapping functions
LiteGraph.getParameterNames = function(func) {
return (func + '')
.replace(/[/][/].*$/mg,'') // strip single-line comments
@@ -6463,6 +6608,8 @@ LiteGraph.getParameterNames = function(func) {
.split(',').filter(Boolean); // split & filter [""]
}
Math.clamp = function(v,a,b) { return (a > v ? a : (b < v ? b : v)); }
if( typeof(window) != "undefined" && !window["requestAnimationFrame"] )
{
window.requestAnimationFrame = window.webkitRequestAnimationFrame ||

View File

@@ -40,7 +40,6 @@ function Subgraph()
this.subgraph.onGlobalOutputRenamed = this.onSubgraphRenamedGlobalOutput.bind(this);
this.subgraph.onGlobalOutputTypeChanged = this.onSubgraphTypeChangeGlobalOutput.bind(this);
this.bgcolor = "#663";
}
@@ -236,6 +235,8 @@ function GlobalOutput()
this.addInput(output_name, null);
this._value = null;
this.properties = {name: output_name, type: null };
var that = this;
@@ -270,7 +271,7 @@ function GlobalOutput()
});
}
GlobalOutput.title = "Ouput";
GlobalOutput.title = "Output";
GlobalOutput.desc = "Output of the graph";
GlobalOutput.prototype.onAdded = function()
@@ -278,9 +279,15 @@ GlobalOutput.prototype.onAdded = function()
var name = this.graph.addGlobalOutput( this.properties.name, this.properties.type );
}
GlobalOutput.prototype.getValue = function()
{
return this._value;
}
GlobalOutput.prototype.onExecute = function()
{
this.graph.setGlobalOutputData( this.properties.name, this.getInputData(0) );
this._value = this.getInputData(0);
this.graph.setGlobalOutputData( this.properties.name, this._value );
}
LiteGraph.registerNodeType("graph/output", GlobalOutput);

View File

@@ -17,7 +17,7 @@ if(typeof(GL) != "undefined")
if(!LGraphFXLens._shader)
{
LGraphFXLens._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphFXLens.pixel_shader );
LGraphFXLens._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphFXLens.pixel_shader );
LGraphFXLens._texture = new GL.Texture(3,1,{ format: gl.RGB, wrap: gl.CLAMP_TO_EDGE, magFilter: gl.LINEAR, minFilter: gl.LINEAR, pixel_data: [255,0,0, 0,255,0, 0,0,255] });
}
}
@@ -110,7 +110,120 @@ if(typeof(GL) != "undefined")
*/
LiteGraph.registerNodeType("fx/lens", LGraphFXLens );
window.LGraphFXLens = LGraphFXLens;
global.LGraphFXLens = LGraphFXLens;
/* not working yet
function LGraphDepthOfField()
{
this.addInput("Color","Texture");
this.addInput("Linear Depth","Texture");
this.addInput("Camera","camera");
this.addOutput("Texture","Texture");
this.properties = { high_precision: false };
}
LGraphDepthOfField.title = "Depth Of Field";
LGraphDepthOfField.desc = "Applies a depth of field effect";
LGraphDepthOfField.prototype.onExecute = function()
{
var tex = this.getInputData(0);
var depth = this.getInputData(1);
var camera = this.getInputData(2);
if(!tex || !depth || !camera)
{
this.setOutputData(0, tex);
return;
}
var precision = gl.UNSIGNED_BYTE;
if(this.properties.high_precision)
precision = gl.half_float_ext ? gl.HALF_FLOAT_OES : gl.FLOAT;
if(!this._temp_texture || this._temp_texture.type != precision ||
this._temp_texture.width != tex.width || this._temp_texture.height != tex.height)
this._temp_texture = new GL.Texture( tex.width, tex.height, { type: precision, format: gl.RGBA, filter: gl.LINEAR });
var shader = LGraphDepthOfField._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphDepthOfField._pixel_shader );
var screen_mesh = Mesh.getScreenQuad();
gl.disable( gl.DEPTH_TEST );
gl.disable( gl.BLEND );
var camera_position = camera.getEye();
var focus_point = camera.getCenter();
var distance = vec3.distance( camera_position, focus_point );
var far = camera.far;
var focus_range = distance * 0.5;
this._temp_texture.drawTo( function() {
tex.bind(0);
depth.bind(1);
shader.uniforms({u_texture:0, u_depth_texture:1, u_resolution: [1/tex.width, 1/tex.height], u_far: far, u_focus_point: distance, u_focus_scale: focus_range }).draw(screen_mesh);
});
this.setOutputData(0, this._temp_texture);
}
//from http://tuxedolabs.blogspot.com.es/2018/05/bokeh-depth-of-field-in-single-pass.html
LGraphDepthOfField._pixel_shader = "\n\
precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture; //Image to be processed\n\
uniform sampler2D u_depth_texture; //Linear depth, where 1.0 == far plane\n\
uniform vec2 u_iresolution; //The size of a pixel: vec2(1.0/width, 1.0/height)\n\
uniform float u_far; // Far plane\n\
uniform float u_focus_point;\n\
uniform float u_focus_scale;\n\
\n\
const float GOLDEN_ANGLE = 2.39996323;\n\
const float MAX_BLUR_SIZE = 20.0;\n\
const float RAD_SCALE = 0.5; // Smaller = nicer blur, larger = faster\n\
\n\
float getBlurSize(float depth, float focusPoint, float focusScale)\n\
{\n\
float coc = clamp((1.0 / focusPoint - 1.0 / depth)*focusScale, -1.0, 1.0);\n\
return abs(coc) * MAX_BLUR_SIZE;\n\
}\n\
\n\
vec3 depthOfField(vec2 texCoord, float focusPoint, float focusScale)\n\
{\n\
float centerDepth = texture2D(u_depth_texture, texCoord).r * u_far;\n\
float centerSize = getBlurSize(centerDepth, focusPoint, focusScale);\n\
vec3 color = texture2D(u_texture, v_coord).rgb;\n\
float tot = 1.0;\n\
\n\
float radius = RAD_SCALE;\n\
for (float ang = 0.0; ang < 100.0; ang += GOLDEN_ANGLE)\n\
{\n\
vec2 tc = texCoord + vec2(cos(ang), sin(ang)) * u_iresolution * radius;\n\
\n\
vec3 sampleColor = texture2D(u_texture, tc).rgb;\n\
float sampleDepth = texture2D(u_depth_texture, tc).r * u_far;\n\
float sampleSize = getBlurSize( sampleDepth, focusPoint, focusScale );\n\
if (sampleDepth > centerDepth)\n\
sampleSize = clamp(sampleSize, 0.0, centerSize*2.0);\n\
\n\
float m = smoothstep(radius-0.5, radius+0.5, sampleSize);\n\
color += mix(color/tot, sampleColor, m);\n\
tot += 1.0;\n\
radius += RAD_SCALE/radius;\n\
if(radius>=MAX_BLUR_SIZE)\n\
return color / tot;\n\
}\n\
return color / tot;\n\
}\n\
void main()\n\
{\n\
gl_FragColor = vec4( depthOfField( v_coord, u_focus_point, u_focus_scale ), 1.0 );\n\
//gl_FragColor = vec4( texture2D(u_depth_texture, v_coord).r );\n\
}\n\
";
LiteGraph.registerNodeType("fx/DOF", LGraphDepthOfField );
global.LGraphDepthOfField = LGraphDepthOfField;
*/
//*******************************************************
@@ -311,7 +424,7 @@ if(typeof(GL) != "undefined")
LiteGraph.registerNodeType("fx/bokeh", LGraphFXBokeh );
window.LGraphFXBokeh = LGraphFXBokeh;
global.LGraphFXBokeh = LGraphFXBokeh;
//************************************************
@@ -380,7 +493,7 @@ if(typeof(GL) != "undefined")
gl.disable( gl.BLEND );
gl.disable( gl.DEPTH_TEST );
var mesh = Mesh.getScreenQuad();
var camera = window.LS ? LS.Renderer._current_camera : null;
var camera = global.LS ? LS.Renderer._current_camera : null;
if(camera)
camera_planes = [LS.Renderer._current_camera.near, LS.Renderer._current_camera.far];
else
@@ -480,7 +593,7 @@ if(typeof(GL) != "undefined")
LiteGraph.registerNodeType("fx/generic", LGraphFXGeneric );
window.LGraphFXGeneric = LGraphFXGeneric;
global.LGraphFXGeneric = LGraphFXGeneric;
// Vigneting ************************************

View File

@@ -99,6 +99,18 @@ if(typeof(GL) != "undefined")
return target;
}
LGraphTexture.getTextureType = function( precision, ref_texture )
{
var type = ref_texture ? ref_texture.type : gl.UNSIGNED_BYTE;
switch( precision )
{
case LGraphTexture.LOW: type = gl.UNSIGNED_BYTE; break;
case LGraphTexture.HIGH: type = gl.HIGH_PRECISION_FORMAT; break;
}
return type;
}
LGraphTexture.getNoiseTexture = function()
{
if(this._noise_texture)
@@ -455,33 +467,24 @@ if(typeof(GL) != "undefined")
var width = 512;
var height = 512;
var type = gl.UNSIGNED_BYTE;
if(tex)
{
width = tex.width;
height = tex.height;
type = tex.type;
}
else if (texB)
{
width = texB.width;
height = texB.height;
type = texB.type;
}
var type = LGraphTexture.getTextureType( this.properties.precision, tex );
if(!tex && !this._tex )
this._tex = new GL.Texture( width, height, { type: this.precision === LGraphTexture.LOW ? gl.UNSIGNED_BYTE : gl.HIGH_PRECISION_FORMAT, format: gl.RGBA, filter: gl.LINEAR });
this._tex = new GL.Texture( width, height, { type: type, format: gl.RGBA, filter: gl.LINEAR });
else
this._tex = LGraphTexture.getTargetTexture( tex || this._tex, this._tex, this.properties.precision );
/*
if(this.properties.low_precision)
type = gl.UNSIGNED_BYTE;
if(!this._tex || this._tex.width != width || this._tex.height != height || this._tex.type != type )
this._tex = new GL.Texture( width, height, { type: type, format: gl.RGBA, filter: gl.LINEAR });
*/
var uvcode = "";
if(this.properties.uvcode)
{
@@ -578,9 +581,10 @@ if(typeof(GL) != "undefined")
function LGraphTextureShader()
{
this.addOutput("Texture","Texture");
this.properties = {code:"", width: 512, height: 512};
this.properties = {code:"", width: 512, height: 512, precision: LGraphTexture.DEFAULT };
this.properties.code = "\nvoid main() {\n vec2 uv = v_coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n";
this._uniforms = { texSize: vec2.create(), time: time };
}
LGraphTextureShader.title = "Shader";
@@ -713,16 +717,25 @@ if(typeof(GL) != "undefined")
shader.setUniform( info.name, data );
}
var uniforms = this._uniforms;
var type = LGraphTexture.getTextureType( this.properties.precision );
//render to texture
if(!this._tex || this._tex.width != this.properties.width || this._tex.height != this.properties.height )
this._tex = new GL.Texture( this.properties.width, this.properties.height, { format: gl.RGBA, filter: gl.LINEAR });
var w = this.properties.width|0;
var h = this.properties.height|0;
uniforms.texSize[0] = w;
uniforms.texSize[1] = h;
if(!this._tex || this._tex.type != type || this._tex.width != w || this._tex.height != h )
this._tex = new GL.Texture( w, h, { type: type, format: gl.RGBA, filter: gl.LINEAR });
var tex = this._tex;
var time = this.graph.getTime();
tex.drawTo(function() {
shader.uniforms({texSize: [tex.width, tex.height], time: time}).draw( Mesh.getScreenQuad() );
tex.drawTo(function() {
shader.uniforms( uniforms ).draw( GL.Mesh.getScreenQuad() );
});
this.setOutputData(0, this._tex);
this.setOutputData( 0, this._tex );
}
LGraphTextureShader.pixel_shader = "precision highp float;\n\
@@ -1243,10 +1256,13 @@ if(typeof(GL) != "undefined")
function LGraphTextureAverage()
{
this.addInput("Texture","Texture");
this.addOutput("","Texture");
this.addOutput("tex","Texture");
this.addOutput("avg","vec4");
this.addOutput("lum","number");
this.properties = { mipmap_offset: 0, low_precision: false };
this._uniforms = { u_texture: 0, u_mipmap_offset: this.properties.mipmap_offset };
this._luminance = new Float32Array(4);
}
LGraphTextureAverage.title = "Average";
@@ -1258,7 +1274,7 @@ if(typeof(GL) != "undefined")
if(!tex)
return;
if(!this.isOutputConnected(0))
if(!this.isOutputConnected(0) && !this.isOutputConnected(1) && !this.isOutputConnected(2))
return; //saves work
if(!LGraphTextureAverage._shader)
@@ -1272,7 +1288,10 @@ if(typeof(GL) != "undefined")
}
var temp = this._temp_texture;
var type = this.properties.low_precision ? gl.UNSIGNED_BYTE : tex.type;
var type = gl.UNSIGNED_BYTE;
if(tex.type != type) //force floats, half floats cannot be read with gl.readPixels
type = gl.FLOAT;
if(!temp || temp.type != type )
this._temp_texture = new GL.Texture( 1, 1, { type: type, format: gl.RGBA, filter: gl.NEAREST });
@@ -1284,6 +1303,24 @@ if(typeof(GL) != "undefined")
});
this.setOutputData(0,this._temp_texture);
if(this.isOutputConnected(1) || this.isOutputConnected(2))
{
var pixel = this._temp_texture.getPixels();
if(pixel)
{
var v = this._luminance;
var type = this._temp_texture.type;
v.set( pixel );
if(type == gl.UNSIGNED_BYTE)
vec4.scale( v,v, 1/255 );
else if(type == GL.HALF_FLOAT || type == GL.HALF_FLOAT_OES)
vec4.scale( v,v, 1/(255*255) ); //is this correct?
this.setOutputData(1,v);
this.setOutputData(2,(v[0] + v[1] + v[2]) / 3);
}
}
}
LGraphTextureAverage.pixel_shader = "precision highp float;\n\
@@ -1347,7 +1384,7 @@ if(typeof(GL) != "undefined")
}
catch(err)
{
console.error("image comes from an unsafe location, cannot be uploaded to webgl");
console.error("image comes from an unsafe location, cannot be uploaded to webgl: " + err);
return;
}
@@ -1371,12 +1408,12 @@ if(typeof(GL) != "undefined")
}
LGraphTextureLUT.widgets_info = {
"texture": { widget:"texture"},
"precision": { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphTextureLUT.title = "LUT";
LGraphTextureLUT.desc = "Apply LUT to Texture";
LGraphTextureLUT.widgets_info = {"texture": { widget:"texture"} };
LGraphTextureLUT.prototype.onExecute = function()
{
@@ -1391,7 +1428,8 @@ if(typeof(GL) != "undefined")
return;
}
if(!tex) return;
if(!tex)
return;
var lut_tex = this.getInputData(1);
@@ -1766,7 +1804,7 @@ if(typeof(GL) != "undefined")
this.addInput("Tex.","Texture");
this.addOutput("Edges","Texture");
this.properties = { invert: true, factor: 1, precision: LGraphTexture.DEFAULT };
this.properties = { invert: true, threshold: false, factor: 1, precision: LGraphTexture.DEFAULT };
if(!LGraphTextureEdges._shader)
LGraphTextureEdges._shader = new GL.Shader( Shader.SCREEN_VERTEX_SHADER, LGraphTextureEdges.pixel_shader );
@@ -1803,10 +1841,11 @@ if(typeof(GL) != "undefined")
var shader = LGraphTextureEdges._shader;
var invert = this.properties.invert;
var factor = this.properties.factor;
var threshold = this.properties.threshold ? 1 : 0;
this._tex.drawTo( function() {
tex.bind(0);
shader.uniforms({u_texture:0, u_isize:[1/tex.width,1/tex.height], u_factor: factor, u_invert: invert ? 1 : 0}).draw(mesh);
shader.uniforms({u_texture:0, u_isize:[1/tex.width,1/tex.height], u_factor: factor, u_threshold: threshold, u_invert: invert ? 1 : 0}).draw(mesh);
});
this.setOutputData(0, this._tex);
@@ -1819,6 +1858,7 @@ if(typeof(GL) != "undefined")
uniform vec2 u_isize;\n\
uniform int u_invert;\n\
uniform float u_factor;\n\
uniform float u_threshold;\n\
\n\
void main() {\n\
vec4 center = texture2D(u_texture, v_coord);\n\
@@ -1830,7 +1870,10 @@ if(typeof(GL) != "undefined")
diff *= u_factor;\n\
if(u_invert == 1)\n\
diff.xyz = vec3(1.0) - diff.xyz;\n\
gl_FragColor = vec4( diff.xyz, center.a );\n\
if( u_threshold == 0.0 )\n\
gl_FragColor = vec4( diff.xyz, center.a );\n\
else\n\
gl_FragColor = vec4( diff.x > 0.5 ? 1.0 : 0.0, diff.y > 0.5 ? 1.0 : 0.0, diff.z > 0.5 ? 1.0 : 0.0, center.a );\n\
}\n\
";
@@ -1912,7 +1955,8 @@ if(typeof(GL) != "undefined")
shader.uniforms( uniforms ).draw(mesh);
});
this.setOutputData(0, this._temp_texture);
this._temp_texture.near_far_planes = planes;
this.setOutputData(0, this._temp_texture );
}
LGraphTextureDepthRange.pixel_shader = "precision highp float;\n\
@@ -1955,12 +1999,16 @@ if(typeof(GL) != "undefined")
this.addInput("Iterations","number");
this.addInput("Intensity","number");
this.addOutput("Blurred","Texture");
this.properties = { intensity: 1, iterations: 1, preserve_aspect: false, scale:[1,1] };
this.properties = { intensity: 1, iterations: 1, preserve_aspect: false, scale:[1,1], precision: LGraphTexture.DEFAULT };
}
LGraphTextureBlur.title = "Blur";
LGraphTextureBlur.desc = "Blur a texture";
LGraphTextureBlur.widgets_info = {
precision: { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphTextureBlur.max_iterations = 20;
LGraphTextureBlur.prototype.onExecute = function()
@@ -1972,13 +2020,13 @@ if(typeof(GL) != "undefined")
if(!this.isOutputConnected(0))
return; //saves work
var temp = this._temp_texture;
var temp = this._final_texture;
if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type )
{
//we need two textures to do the blurring
this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
this._final_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
//this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
temp = this._final_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
}
//iterations
@@ -2010,18 +2058,15 @@ if(typeof(GL) != "undefined")
aspect = 1;
aspect = this.properties.preserve_aspect ? aspect : 1;
var start_texture = tex;
var scale = this.properties.scale || [1,1];
var origin = start_texture;
for(var i = 0; i < iterations; ++i)
{
origin.applyBlur( aspect * scale[0] * i, scale[1] * i, intensity, this._temp_texture, this._final_texture );
origin = this._final_texture;
}
tex.applyBlur( aspect * scale[0], scale[1], intensity, temp );
for(var i = 1; i < iterations; ++i)
temp.applyBlur( aspect * scale[0] * (i+1), scale[1] * (i+1), intensity );
this.setOutputData(0, this._final_texture);
this.setOutputData(0, temp );
}
/*
LGraphTextureBlur.pixel_shader = "precision highp float;\n\
precision highp float;\n\
varying vec2 v_coord;\n\
@@ -2041,12 +2086,237 @@ if(typeof(GL) != "undefined")
sum += texture2D(u_texture, v_coord + u_offset * 2.0) * 0.12/0.98;\n\
sum += texture2D(u_texture, v_coord + u_offset * 1.0) * 0.15/0.98;\n\
gl_FragColor = u_intensity * sum;\n\
/*gl_FragColor.a = center.a*/;\n\
}\n\
";
*/
LiteGraph.registerNodeType("texture/blur", LGraphTextureBlur );
// Texture Glow *****************************************
//based in https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/
function LGraphTextureGlow()
{
this.addInput("in","Texture");
this.addInput("dirt","Texture");
this.addOutput("out","Texture");
this.addOutput("glow","Texture");
this.properties = { enabled: true, intensity: 1, persistence: 0.99, iterations:16, threshold:0, scale: 1, dirt_factor: 0.5, precision: LGraphTexture.DEFAULT };
this._textures = [];
this._uniforms = { u_intensity: 1, u_texture: 0, u_glow_texture: 1, u_threshold: 0, u_texel_size: vec2.create() };
}
LGraphTextureGlow.title = "Glow";
LGraphTextureGlow.desc = "Filters a texture giving it a glow effect";
LGraphTextureGlow.weights = new Float32Array( [0.5,0.4,0.3,0.2] );
LGraphTextureGlow.widgets_info = {
"iterations": { type:"number", min: 0, max: 16, step: 1, precision: 0 },
"threshold": { type:"number", min: 0, max: 10, step: 0.01, precision: 2 },
"precision": { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphTextureGlow.prototype.onGetInputs = function(){
return [["enabled","boolean"],["threshold","number"],["intensity","number"],["persistence","number"],["iterations","number"],["dirt_factor","number"]];
}
LGraphTextureGlow.prototype.onGetOutputs = function(){
return [["average","Texture"]];
}
LGraphTextureGlow.prototype.onExecute = function()
{
var tex = this.getInputData(0);
if(!tex)
return;
if(!this.isAnyOutputConnected())
return; //saves work
if(this.properties.precision === LGraphTexture.PASS_THROUGH || this.getInputOrProperty("enabled" ) === false )
{
this.setOutputData(0,tex);
return;
}
var width = tex.width;
var height = tex.height;
var texture_info = { format: tex.format, type: tex.type, minFilter: GL.LINEAR, magFilter: GL.LINEAR, wrap: gl.CLAMP_TO_EDGE };
var type = LGraphTexture.getTextureType( this.properties.precision, tex );
var uniforms = this._uniforms;
var textures = this._textures;
//cut
var shader = LGraphTextureGlow._cut_shader;
if(!shader)
shader = LGraphTextureGlow._cut_shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureGlow.cut_pixel_shader );
gl.disable( gl.DEPTH_TEST );
gl.disable( gl.BLEND );
uniforms.u_threshold = this.getInputOrProperty("threshold");
var currentDestination = textures[0] = GL.Texture.getTemporary( width, height, texture_info );
tex.blit( currentDestination, shader.uniforms(uniforms) );
var currentSource = currentDestination;
var iterations = this.getInputOrProperty("iterations");
iterations = Math.clamp( iterations, 1, 16) | 0;
var texel_size = uniforms.u_texel_size;
var intensity = this.getInputOrProperty("intensity");
uniforms.u_intensity = 1;
uniforms.u_delta = this.properties.scale; //1
//downscale/upscale shader
var shader = LGraphTextureGlow._shader;
if(!shader)
shader = LGraphTextureGlow._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureGlow.scale_pixel_shader );
var i = 1;
//downscale
for (;i < iterations; i++) {
width = width>>1;
if( (height|0) > 1 )
height = height>>1;
if( width < 2 )
break;
currentDestination = textures[i] = GL.Texture.getTemporary( width, height, texture_info );
texel_size[0] = 1 / currentSource.width; texel_size[1] = 1 / currentSource.height;
currentSource.blit( currentDestination, shader.uniforms(uniforms) );
currentSource = currentDestination;
}
//average
if(this.isOutputConnected(2))
{
var average_texture = this._average_texture;
if(!average_texture || average_texture.type != tex.type || average_texture.format != tex.format )
average_texture = this._average_texture = new GL.Texture( 1, 1, { type: tex.type, format: tex.format, filter: gl.LINEAR });
texel_size[0] = 1 / currentSource.width; texel_size[1] = 1 / currentSource.height;
uniforms.u_intensity = intensity;
uniforms.u_delta = 1;
currentSource.blit( average_texture, shader.uniforms(uniforms) );
this.setOutputData( 2, average_texture );
}
//upscale and blend
gl.enable( gl.BLEND );
gl.blendFunc( gl.ONE, gl.ONE );
uniforms.u_intensity = this.getInputOrProperty("persistence");
uniforms.u_delta = 0.5;
for (i -= 2; i >= 0; i--) // i-=2 => -1 to point to last element in array, -1 to go to texture above
{
currentDestination = textures[i];
textures[i] = null;
texel_size[0] = 1 / currentSource.width; texel_size[1] = 1 / currentSource.height;
currentSource.blit( currentDestination, shader.uniforms(uniforms) );
GL.Texture.releaseTemporary( currentSource );
currentSource = currentDestination;
}
gl.disable( gl.BLEND );
//glow
if(this.isOutputConnected(1))
{
var glow_texture = this._glow_texture;
if(!glow_texture || glow_texture.width != tex.width || glow_texture.height != tex.height || glow_texture.type != type || glow_texture.format != tex.format )
glow_texture = this._glow_texture = new GL.Texture( tex.width, tex.height, { type: type, format: tex.format, filter: gl.LINEAR });
currentSource.blit( glow_texture );
this.setOutputData( 1, glow_texture);
}
//final composition
if(this.isOutputConnected(0))
{
var final_texture = this._final_texture;
if(!final_texture || final_texture.width != tex.width || final_texture.height != tex.height || final_texture.type != type || final_texture.format != tex.format )
final_texture = this._final_texture = new GL.Texture( tex.width, tex.height, { type: type, format: tex.format, filter: gl.LINEAR });
var dirt_texture = this.getInputData(1);
var dirt_factor = this.getInputOrProperty("dirt_factor");
uniforms.u_intensity = intensity;
shader = dirt_texture ? LGraphTextureGlow._dirt_final_shader : LGraphTextureGlow._final_shader;
if(!shader)
{
if(dirt_texture)
shader = LGraphTextureGlow._dirt_final_shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureGlow.final_pixel_shader, { USE_DIRT: "" } );
else
shader = LGraphTextureGlow._final_shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureGlow.final_pixel_shader );
}
final_texture.drawTo( function(){
tex.bind(0);
currentSource.bind(1);
if(dirt_texture)
{
shader.setUniform( "u_dirt_factor", dirt_factor );
shader.setUniform( "u_dirt_texture", dirt_texture.bind(2) );
}
shader.toViewport( uniforms );
});
this.setOutputData( 0, final_texture );
}
GL.Texture.releaseTemporary( currentSource );
}
LGraphTextureGlow.cut_pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture;\n\
uniform float u_threshold;\n\
void main() {\n\
gl_FragColor = max( texture2D( u_texture, v_coord ) - vec4( u_threshold ), vec4(0.0) );\n\
}"
LGraphTextureGlow.scale_pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture;\n\
uniform vec2 u_texel_size;\n\
uniform float u_delta;\n\
uniform float u_intensity;\n\
\n\
vec4 sampleBox(vec2 uv) {\n\
vec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\
vec4 s = texture2D( u_texture, uv + o.xy ) + texture2D( u_texture, uv + o.zy) + texture2D( u_texture, uv + o.xw) + texture2D( u_texture, uv + o.zw);\n\
return s * 0.25;\n\
}\n\
void main() {\n\
gl_FragColor = u_intensity * sampleBox( v_coord );\n\
}"
LGraphTextureGlow.final_pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture;\n\
uniform sampler2D u_glow_texture;\n\
#ifdef USE_DIRT\n\
uniform sampler2D u_dirt_texture;\n\
#endif\n\
uniform vec2 u_texel_size;\n\
uniform float u_delta;\n\
uniform float u_intensity;\n\
uniform float u_dirt_factor;\n\
\n\
vec4 sampleBox(vec2 uv) {\n\
vec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\
vec4 s = texture2D( u_glow_texture, uv + o.xy ) + texture2D( u_glow_texture, uv + o.zy) + texture2D( u_glow_texture, uv + o.xw) + texture2D( u_glow_texture, uv + o.zw);\n\
return s * 0.25;\n\
}\n\
void main() {\n\
vec4 glow = sampleBox( v_coord );\n\
#ifdef USE_DIRT\n\
glow = mix( glow, glow * texture2D( u_dirt_texture, v_coord ), u_dirt_factor );\n\
#endif\n\
gl_FragColor = texture2D( u_texture, v_coord ) + u_intensity * glow;\n\
}"
LiteGraph.registerNodeType("texture/glow", LGraphTextureGlow );
// Texture Blur *****************************************
function LGraphTextureKuwaharaFilter()
{
@@ -2268,12 +2538,18 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\
LGraphTextureWebcam.prototype.onRemoved = function()
{
if(this._webcam_stream)
if(!this._webcam_stream)
return;
var video_streams = this._webcam_stream.getVideoTracks();
if(video_streams.length)
{
this._webcam_stream.stop();
this._webcam_stream = null;
this._video = null;
var webcam = video_streams[0];
webcam.stop();
}
this._webcam_stream = null;
this._video = null;
}
LGraphTextureWebcam.prototype.onDrawBackground = function(ctx)
@@ -2329,15 +2605,432 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\
LiteGraph.registerNodeType("texture/webcam", LGraphTextureWebcam );
//from https://github.com/spite/Wagner
function LGraphLensFX()
{
this.addInput("in","Texture");
this.addInput("f","number");
this.addOutput("out","Texture");
this.properties = { enabled: true, factor: 1, precision: LGraphTexture.LOW };
this._uniforms = { u_texture: 0, u_factor: 1 };
}
LGraphLensFX.title = "Lens FX";
LGraphLensFX.desc = "distortion and chromatic aberration";
LGraphLensFX.widgets_info = {
"precision": { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphLensFX.prototype.onGetInputs = function() { return [["enabled","boolean"]]; }
LGraphLensFX.prototype.onExecute = function()
{
var tex = this.getInputData(0);
if(!tex)
return;
if(!this.isOutputConnected(0))
return; //saves work
if(this.properties.precision === LGraphTexture.PASS_THROUGH || this.getInputOrProperty("enabled" ) === false )
{
this.setOutputData(0, tex );
return;
}
var temp = this._temp_texture;
if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type )
temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
var shader = LGraphLensFX._shader;
if(!shader)
shader = LGraphLensFX._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphLensFX.pixel_shader );
var factor = this.getInputData(1);
if(factor == null)
factor = this.properties.factor;
var uniforms = this._uniforms;
uniforms.u_factor = factor;
//apply shader
gl.disable( gl.DEPTH_TEST );
temp.drawTo(function(){
tex.bind(0);
shader.uniforms(uniforms).draw( GL.Mesh.getScreenQuad() );
});
this.setOutputData(0,temp);
}
LGraphLensFX.pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture;\n\
uniform float u_factor;\n\
vec2 barrelDistortion(vec2 coord, float amt) {\n\
vec2 cc = coord - 0.5;\n\
float dist = dot(cc, cc);\n\
return coord + cc * dist * amt;\n\
}\n\
\n\
float sat( float t )\n\
{\n\
return clamp( t, 0.0, 1.0 );\n\
}\n\
\n\
float linterp( float t ) {\n\
return sat( 1.0 - abs( 2.0*t - 1.0 ) );\n\
}\n\
\n\
float remap( float t, float a, float b ) {\n\
return sat( (t - a) / (b - a) );\n\
}\n\
\n\
vec4 spectrum_offset( float t ) {\n\
vec4 ret;\n\
float lo = step(t,0.5);\n\
float hi = 1.0-lo;\n\
float w = linterp( remap( t, 1.0/6.0, 5.0/6.0 ) );\n\
ret = vec4(lo,1.0,hi, 1.) * vec4(1.0-w, w, 1.0-w, 1.);\n\
\n\
return pow( ret, vec4(1.0/2.2) );\n\
}\n\
\n\
const float max_distort = 2.2;\n\
const int num_iter = 12;\n\
const float reci_num_iter_f = 1.0 / float(num_iter);\n\
\n\
void main()\n\
{ \n\
vec2 uv=v_coord;\n\
vec4 sumcol = vec4(0.0);\n\
vec4 sumw = vec4(0.0); \n\
for ( int i=0; i<num_iter;++i )\n\
{\n\
float t = float(i) * reci_num_iter_f;\n\
vec4 w = spectrum_offset( t );\n\
sumw += w;\n\
sumcol += w * texture2D( u_texture, barrelDistortion(uv, .6 * max_distort*t * u_factor ) );\n\
}\n\
gl_FragColor = sumcol / sumw;\n\
}";
LiteGraph.registerNodeType("texture/lensfx", LGraphLensFX );
//simple exposition, but plan to expand it to support different gamma curves
function LGraphExposition()
{
this.addInput("in","Texture");
this.addInput("exp","number");
this.addOutput("out","Texture");
this.properties = { exposition: 1, precision: LGraphTexture.LOW };
this._uniforms = { u_texture: 0, u_exposition: exp };
}
LGraphExposition.title = "Exposition";
LGraphExposition.desc = "Controls texture exposition";
LGraphExposition.widgets_info = {
"exposition": { widget:"slider", min:0,max:3 },
"precision": { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphExposition.prototype.onExecute = function()
{
var tex = this.getInputData(0);
if(!tex)
return;
if(!this.isOutputConnected(0))
return; //saves work
var temp = this._temp_texture;
if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type )
temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
var shader = LGraphExposition._shader;
if(!shader)
shader = LGraphExposition._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphExposition.pixel_shader );
var exp = this.properties.exposition;
var exp_input = this.getInputData(1);
if(exp_input != null)
exp = this.properties.exposition = exp_input;
var uniforms = this._uniforms;
//apply shader
temp.drawTo(function(){
gl.disable( gl.DEPTH_TEST );
tex.bind(0);
shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad());
});
this.setOutputData(0,temp);
}
LGraphExposition.pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture;\n\
uniform float u_exposition;\n\
\n\
void main() {\n\
vec4 color = texture2D( u_texture, v_coord );\n\
gl_FragColor = vec4( color.xyz * u_exposition, color.a );\n\
}";
LiteGraph.registerNodeType("texture/exposition", LGraphExposition );
function LGraphToneMapping()
{
this.addInput("in","Texture");
this.addInput("avg","number");
this.addOutput("out","Texture");
this.properties = { enabled: true, scale:1, gamma: 1, average_lum: 1, lum_white: 1, precision: LGraphTexture.LOW };
this._uniforms = {
u_texture: 0,
u_lumwhite2: 1,
u_igamma: 1,
u_scale: 1,
u_average_lum: 1
};
}
LGraphToneMapping.title = "Tone Mapping";
LGraphToneMapping.desc = "Applies Tone Mapping to convert from high to low";
LGraphToneMapping.widgets_info = {
"precision": { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphToneMapping.prototype.onGetInputs = function() {
return [["enabled","boolean"]];
}
LGraphToneMapping.prototype.onExecute = function()
{
var tex = this.getInputData(0);
if(!tex)
return;
if(!this.isOutputConnected(0))
return; //saves work
if(this.properties.precision === LGraphTexture.PASS_THROUGH || this.getInputOrProperty("enabled" ) === false )
{
this.setOutputData(0, tex );
return;
}
var temp = this._temp_texture;
if(!temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type )
temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR });
//apply shader
var shader = LGraphToneMapping._shader;
if(!shader)
shader = LGraphToneMapping._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphToneMapping.pixel_shader );
var avg = this.getInputData(1);
if(avg != null)
this.properties.average_lum = avg;
var uniforms = this._uniforms;
uniforms.u_lumwhite2 = this.properties.lum_white * this.properties.lum_white;
uniforms.u_scale = this.properties.scale;
uniforms.u_average_lum = this.properties.average_lum;
uniforms.u_igamma = 1/this.properties.gamma;
//apply shader
gl.disable( gl.DEPTH_TEST );
temp.drawTo(function(){
tex.bind(0);
shader.uniforms(uniforms).draw( GL.Mesh.getScreenQuad() );
});
this.setOutputData(0,this._temp_texture);
}
LGraphToneMapping.pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform sampler2D u_texture;\n\
uniform float u_scale;\n\
uniform float u_average_lum;\n\
uniform float u_lumwhite2;\n\
uniform float u_igamma;\n\
vec3 RGB2xyY (vec3 rgb)\n\
{\n\
const mat3 RGB2XYZ = mat3(0.4124, 0.3576, 0.1805,\n\
0.2126, 0.7152, 0.0722,\n\
0.0193, 0.1192, 0.9505);\n\
vec3 XYZ = RGB2XYZ * rgb;\n\
\n\
float f = (XYZ.x + XYZ.y + XYZ.z);\n\
return vec3(XYZ.x / f,\n\
XYZ.y / f,\n\
XYZ.y);\n\
}\n\
\n\
void main() {\n\
vec4 color = texture2D( u_texture, v_coord );\n\
vec3 rgb = color.xyz;\n\
//Ld - this part of the code is the same for both versions\n\
float lum = dot(rgb, vec3(0.2126, 0.7152, 0.0722));\n\
float L = (u_scale / u_average_lum) * lum;\n\
float Ld = (L * (1.0 + L / u_lumwhite2)) / (1.0 + L);\n\
//first\n\
//vec3 xyY = RGB2xyY(rgb);\n\
//xyY.z *= Ld;\n\
//rgb = xyYtoRGB(xyY);\n\
//second\n\
rgb = (rgb / lum) * Ld;\n\
rgb = pow( rgb, vec3( u_igamma ) );\n\
gl_FragColor = vec4( rgb, color.a );\n\
}";
LiteGraph.registerNodeType("texture/tonemapping", LGraphToneMapping );
function LGraphTexturePerlin()
{
this.addOutput("out","Texture");
this.properties = { width: 512, height: 512, seed:0, persistence: 0.1, octaves: 8, scale: 1, offset: [0,0], amplitude: 1, precision: LGraphTexture.DEFAULT };
this._key = 0;
this._uniforms = { u_persistence: 0.1, u_seed: 0, u_offset: vec2.create(), u_scale: 1, u_viewport: vec2.create() };
}
LGraphTexturePerlin.title = "Perlin";
LGraphTexturePerlin.desc = "Generates a perlin noise texture";
LGraphTexturePerlin.widgets_info = {
precision: { widget:"combo", values: LGraphTexture.MODE_VALUES },
width: { type: "Number", precision: 0, step: 1 },
height: { type: "Number", precision: 0, step: 1 },
octaves: { type: "Number", precision: 0, step: 1, min: 1, max: 50 }
};
LGraphTexturePerlin.prototype.onExecute = function()
{
if(!this.isOutputConnected(0))
return; //saves work
var w = this.properties.width|0;
var h = this.properties.height|0;
if(w == 0) w = gl.viewport_data[2]; //0 means default
if(h == 0) h = gl.viewport_data[3]; //0 means default
var type = LGraphTexture.getTextureType( this.properties.precision );
var temp = this._temp_texture;
if(!temp || temp.width != w || temp.height != h || temp.type != type )
temp = this._temp_texture = new GL.Texture( w, h, { type: type, format: gl.RGB, filter: gl.LINEAR });
//reusing old
var key = w + h + type + this.properties.persistence + this.properties.octaves + this.properties.scale + this.properties.seed + this.properties.offset[0] + this.properties.offset[1] + this.properties.amplitude;
if(key == this._key)
{
this.setOutputData( 0, temp );
return;
}
this._key = key;
//gather uniforms
var uniforms = this._uniforms;
uniforms.u_persistence = this.properties.persistence;
uniforms.u_octaves = this.properties.octaves;
uniforms.u_offset[0] = this.properties.offset[0];
uniforms.u_offset[1] = this.properties.offset[1];
uniforms.u_scale = this.properties.scale;
uniforms.u_amplitude = this.properties.amplitude;
uniforms.u_viewport[0] = w;
uniforms.u_viewport[1] = h;
uniforms.u_seed = this.properties.seed * 128;
//render
var shader = LGraphTexturePerlin._shader;
if(!shader)
shader = LGraphTexturePerlin._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTexturePerlin.pixel_shader );
gl.disable( gl.BLEND );
gl.disable( gl.DEPTH_TEST );
temp.drawTo( function() {
shader.uniforms( uniforms ).draw( GL.Mesh.getScreenQuad() );
});
this.setOutputData( 0, temp );
}
LGraphTexturePerlin.pixel_shader = "precision highp float;\n\
varying vec2 v_coord;\n\
uniform vec2 u_offset;\n\
uniform float u_scale;\n\
uniform float u_persistence;\n\
uniform int u_octaves;\n\
uniform float u_amplitude;\n\
uniform vec2 u_viewport;\n\
uniform float u_seed;\n\
#define M_PI 3.14159265358979323846\n\
\n\
float rand(vec2 c){ return fract(sin(dot(c.xy ,vec2( 12.9898 + u_seed,78.233 + u_seed))) * 43758.5453); }\n\
\n\
float noise(vec2 p, float freq ){\n\
float unit = u_viewport.x/freq;\n\
vec2 ij = floor(p/unit);\n\
vec2 xy = mod(p,unit)/unit;\n\
//xy = 3.*xy*xy-2.*xy*xy*xy;\n\
xy = .5*(1.-cos(M_PI*xy));\n\
float a = rand((ij+vec2(0.,0.)));\n\
float b = rand((ij+vec2(1.,0.)));\n\
float c = rand((ij+vec2(0.,1.)));\n\
float d = rand((ij+vec2(1.,1.)));\n\
float x1 = mix(a, b, xy.x);\n\
float x2 = mix(c, d, xy.x);\n\
return mix(x1, x2, xy.y);\n\
}\n\
\n\
float pNoise(vec2 p, int res){\n\
float persistance = u_persistence;\n\
float n = 0.;\n\
float normK = 0.;\n\
float f = 4.;\n\
float amp = 1.0;\n\
int iCount = 0;\n\
for (int i = 0; i<50; i++){\n\
n+=amp*noise(p, f);\n\
f*=2.;\n\
normK+=amp;\n\
amp*=persistance;\n\
if (iCount >= res)\n\
break;\n\
iCount++;\n\
}\n\
float nf = n/normK;\n\
return nf*nf*nf*nf;\n\
}\n\
void main() {\n\
vec2 uv = v_coord * u_scale * u_viewport + u_offset * u_scale;\n\
vec4 color = vec4( pNoise( uv, u_octaves ) * u_amplitude );\n\
gl_FragColor = color;\n\
}";
LiteGraph.registerNodeType("texture/perlin", LGraphTexturePerlin );
function LGraphTextureMatte()
{
this.addInput("in","Texture");
this.addOutput("out","Texture");
this.properties = { key_color: vec3.fromValues(0.,1.,0.), threshold: 0.8, slope: 0.2, precision: LGraphTexture.DEFAULT };
if(!LGraphTextureMatte._shader)
LGraphTextureMatte._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureMatte.pixel_shader );
}
LGraphTextureMatte.title = "Matte";
@@ -2375,6 +3068,8 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\
var mesh = Mesh.getScreenQuad();
var shader = LGraphTextureMatte._shader;
if(!shader)
shader = LGraphTextureMatte._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureMatte.pixel_shader );
uniforms.u_key_color = this.properties.key_color;
uniforms.u_threshold = this.properties.threshold;
@@ -2405,6 +3100,7 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\
LiteGraph.registerNodeType("texture/matte", LGraphTextureMatte );
//***********************************
//Cubemap reader (to pass a cubemap to a node that requires cubemaps and no images)
function LGraphCubemap()

View File

@@ -1,9 +1,80 @@
(function(global){
var LiteGraph = global.LiteGraph;
function GraphicsPlot()
{
this.addInput("A","Number");
this.addInput("B","Number");
this.addInput("C","Number");
this.addInput("D","Number");
this.values = [[],[],[],[]];
this.properties = { scale: 2 };
}
GraphicsPlot.title = "Plot";
GraphicsPlot.desc = "Plots data over time";
GraphicsPlot.colors = ["#FFF","#F99","#9F9","#99F"];
GraphicsPlot.prototype.onExecute = function(ctx)
{
if(this.flags.collapsed)
return;
var size = this.size;
for(var i = 0; i < 4; ++i)
{
var v = this.getInputData(i);
if(v == null)
continue;
var values = this.values[i];
values.push(v);
if(values.length > size[0])
values.shift();
}
}
GraphicsPlot.prototype.onDrawBackground = function(ctx)
{
if(this.flags.collapsed)
return;
var size = this.size;
var scale = 0.5 * size[1] / this.properties.scale;
var colors = GraphicsPlot.colors;
var offset = size[1] * 0.5;
ctx.fillStyle = "#000";
ctx.fillRect(0,0, size[0],size[1]);
ctx.strokeStyle = "#555";
ctx.beginPath();
ctx.moveTo(0, offset);
ctx.lineTo(size[0], offset);
ctx.stroke();
for(var i = 0; i < 4; ++i)
{
var values = this.values[i];
ctx.strokeStyle = colors[i];
ctx.beginPath();
var v = values[0] * scale * -1 + offset;
ctx.moveTo(0, Math.clamp( v, 0, size[1]) );
for(var j = 1; j < values.length && j < size[0]; ++j)
{
var v = values[j] * scale * -1 + offset;
ctx.lineTo( j, Math.clamp( v, 0, size[1]) );
}
ctx.stroke();
}
}
LiteGraph.registerNodeType("graphics/plot", GraphicsPlot);
function GraphicsImage()
{
this.inputs = [];
this.addOutput("frame","image");
this.properties = {"url":""};
}
@@ -60,11 +131,8 @@ GraphicsImage.prototype.loadImage = function( url, callback )
this.img = document.createElement("img");
if(url.substr(0,7) == "http://")
{
if(LiteGraph.proxy) //proxy external files
url = LiteGraph.proxy + url.substr(7);
}
if(url.substr(0,4) == "http" && LiteGraph.proxy)
url = LiteGraph.proxy + url.substr( url.indexOf(":") + 3 );
this.img.src = url;
this.boxcolor = "#F95";
@@ -443,7 +511,7 @@ function ImageVideo()
{
this.addInput("t","number");
this.addOutputs([["frame","image"],["t","number"],["d","number"]]);
this.properties = {"url":""};
this.properties = { url:"", use_proxy: true };
}
ImageVideo.title = "Video";
@@ -489,6 +557,9 @@ ImageVideo.prototype.loadVideo = function(url)
{
this._video_url = url;
if(this.properties.use_proxy && url.substr(0,4) == "http" && LiteGraph.proxy )
url = LiteGraph.proxy + url.substr( url.indexOf(":") + 3 );
this._video = document.createElement("video");
this._video.src = url;
this._video.type = "type=video/mp4";

View File

@@ -59,6 +59,63 @@ var LiteGraph = global.LiteGraph;
LiteGraph.registerNodeType("widget/button", WidgetButton );
function WidgetToggle()
{
this.addInput( "", "boolean" );
this.addOutput( "v", "boolean" );
this.addOutput( "e", LiteGraph.EVENT );
this.properties = { font: "", value: false };
this.size = [124,64];
}
WidgetToggle.title = "Toggle";
WidgetToggle.desc = "Toggles between true or false";
WidgetToggle.prototype.onDrawForeground = function(ctx)
{
if(this.flags.collapsed)
return;
var size = this.size[1] * 0.5;
var margin = 0.25;
var h = this.size[1] * 0.8;
ctx.fillStyle = "#AAA";
ctx.fillRect(10, h - size,size,size);
ctx.fillStyle = this.properties.value ? "#AEF" : "#000";
ctx.fillRect(10+size*margin,h - size + size*margin,size*(1-margin*2),size*(1-margin*2));
ctx.textAlign = "left";
ctx.font = this.properties.font || ((size * 0.8).toFixed(0) + "px Arial");
ctx.fillStyle = "#AAA";
ctx.fillText( this.title, size + 20, h * 0.85 );
ctx.textAlign = "left";
}
WidgetToggle.prototype.onExecute = function()
{
var v = this.getInputData(0);
if( v != null )
this.properties.value = v;
this.setOutputData( 0, this.properties.value );
}
WidgetToggle.prototype.onMouseDown = function(e, local_pos)
{
if(local_pos[0] > 1 && local_pos[1] > 1 && local_pos[0] < (this.size[0] - 2) && local_pos[1] < (this.size[1] - 2) )
{
this.properties.value = !this.properties.value;
this.trigger( "clicked", this.properties.value );
return true;
}
}
LiteGraph.registerNodeType("widget/toggle", WidgetToggle );
/* Knob ****************/
function WidgetKnob()

View File

@@ -375,7 +375,7 @@ MathScale.prototype.onExecute = function()
LiteGraph.registerNodeType("math/scale", MathScale );
//Math clamp
//Math Average
function MathAverageFilter()
{
this.addInput("in","number");
@@ -426,6 +426,35 @@ MathAverageFilter.prototype.onPropertyChanged = function( name, value )
LiteGraph.registerNodeType("math/average", MathAverageFilter );
//Math
function MathTendTo()
{
this.addInput("in","number");
this.addOutput("out","number");
this.addProperty( "factor", 0.1 );
this.size = [60,20];
this._value = null;
}
MathTendTo.title = "TendTo";
MathTendTo.desc = "moves the output value always closer to the input";
MathTendTo.prototype.onExecute = function()
{
var v = this.getInputData(0);
if(v == null)
v = 0;
var f = this.properties.factor;
if(this._value == null)
this._value = v;
else
this._value = this._value * (1 - f) + v * f;
this.setOutputData( 0, this._value );
}
LiteGraph.registerNodeType("math/tendTo", MathTendTo );
//Math operation
function MathOperation()
{

View File

@@ -1,8 +1,6 @@
const express = require('express')
const app = express()
// app.get('/hello', (req, res) => res.send('Hello World!'))
app.use('/css', express.static('css'))
app.use('/src', express.static('src'))
app.use('/external', express.static('external'))