Skip to content

Commit 1f3b786

Browse files
author
tamat
committed
actions/events are executed deferred now to ensure data flow, can be toggled
1 parent 35e768d commit 1f3b786

8 files changed

Lines changed: 948 additions & 416 deletions

File tree

build/litegraph.core.js

Lines changed: 107 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
catch_exceptions: true,
9999
throw_errors: true,
100100
allow_scripts: false, //if set to true some nodes like Formula would be allowed to evaluate code that comes from unsafe sources (like node configuration), which could lead to exploits
101+
use_deferred_actions: true, //executes actions during the graph execution flow
101102
registered_node_types: {}, //nodetypes by string
102103
node_types_by_file_extension: {}, //used for dropping files in the canvas
103104
Nodes: {}, //node types by classname
@@ -327,6 +328,55 @@
327328
}
328329
},
329330

331+
/**
332+
* Create a new nodetype by passing an object with some properties
333+
* like onCreate, inputs:Array, outputs:Array, properties, onExecute
334+
* @method buildNodeClassFromObject
335+
* @param {String} name node name with namespace (p.e.: 'math/sum')
336+
* @param {Object} object methods expected onCreate, inputs, outputs, properties, onExecute
337+
*/
338+
buildNodeClassFromObject: function(
339+
name,
340+
object
341+
) {
342+
var ctor_code = "";
343+
if(object.inputs)
344+
for(var i=0; i < object.inputs.length; ++i)
345+
{
346+
var _name = object.inputs[i][0];
347+
var _type = object.inputs[i][1];
348+
if(_type && _type.constructor === String)
349+
_type = '"'+_type+'"';
350+
ctor_code += "this.addInput('"+_name+"',"+_type+");\n";
351+
}
352+
if(object.outputs)
353+
for(var i=0; i < object.outputs.length; ++i)
354+
{
355+
var _name = object.outputs[i][0];
356+
var _type = object.outputs[i][1];
357+
if(_type && _type.constructor === String)
358+
_type = '"'+_type+'"';
359+
ctor_code += "this.addOutput('"+_name+"',"+_type+");\n";
360+
}
361+
if(object.properties)
362+
for(var i in object.properties)
363+
{
364+
var prop = object.properties[i];
365+
if(prop && prop.constructor === String)
366+
prop = '"'+prop+'"';
367+
ctor_code += "this.addProperty('"+i+"',"+prop+");\n";
368+
}
369+
ctor_code += "if(this.onCreate)this.onCreate()";
370+
var classobj = Function(ctor_code);
371+
for(var i in object)
372+
if(i!="inputs" && i!="outputs" && i!="properties")
373+
classobj.prototype[i] = object[i];
374+
classobj.title = object.title || name.split("/").pop();
375+
classobj.desc = object.desc || "Generated from object";
376+
this.registerNodeType(name, classobj);
377+
return classobj;
378+
},
379+
330380
/**
331381
* Create a new nodetype by passing a function, it wraps it with a proper class and generates inputs according to the parameters of the function.
332382
* Useful to wrap simple methods that do not require properties, and that only process some input to generate an output.
@@ -346,20 +396,31 @@
346396
) {
347397
var params = Array(func.length);
348398
var code = "";
349-
var names = LiteGraph.getParameterNames(func);
350-
for (var i = 0; i < names.length; ++i) {
351-
code +=
352-
"this.addInput('" +
353-
names[i] +
354-
"'," +
355-
(param_types && param_types[i]
356-
? "'" + param_types[i] + "'"
357-
: "0") +
358-
");\n";
399+
if(param_types !== null) //null means no inputs
400+
{
401+
var names = LiteGraph.getParameterNames(func);
402+
for (var i = 0; i < names.length; ++i) {
403+
var type = 0;
404+
if(param_types)
405+
{
406+
//type = param_types[i] != null ? "'" + param_types[i] + "'" : "0";
407+
if( param_types[i] != null && param_types[i].constructor === String )
408+
type = "'" + param_types[i] + "'" ;
409+
else if( param_types[i] != null )
410+
type = param_types[i];
411+
}
412+
code +=
413+
"this.addInput('" +
414+
names[i] +
415+
"'," +
416+
type +
417+
");\n";
418+
}
359419
}
420+
if(return_type !== null) //null means no output
360421
code +=
361422
"this.addOutput('out'," +
362-
(return_type ? "'" + return_type + "'" : 0) +
423+
(return_type != null ? (return_type.constructor === String ? "'" + return_type + "'" : return_type) : 0) +
363424
");\n";
364425
if (properties) {
365426
code +=
@@ -376,6 +437,7 @@
376437
this.setOutputData(0, r);
377438
};
378439
this.registerNodeType(name, classobj);
440+
return classobj;
379441
},
380442

381443
/**
@@ -3142,6 +3204,13 @@
31423204
// enable this to give the event an ID
31433205
if (!options.action_call) options.action_call = this.id+"_exec_"+Math.floor(Math.random()*9999);
31443206

3207+
if(this._waiting_actions && this._waiting_actions.length)
3208+
for(var i = 0; i < this._waiting_actions.length;++i)
3209+
{
3210+
var p = this._waiting_actions[i];
3211+
this.onAction(p[0],p[1],p[2],p[3],p[4]);
3212+
}
3213+
31453214
this.graph.nodes_executing[this.id] = true; //.push(this.id);
31463215

31473216
this.onExecute(param, options);
@@ -3155,6 +3224,14 @@
31553224
this.graph.nodes_executedAction[this.id] = options.action_call;
31563225
}
31573226
}
3227+
else {
3228+
if(this._waiting_actions && this._waiting_actions.length)
3229+
for(var i = 0; i < this._waiting_actions.length;++i)
3230+
{
3231+
var p = this._waiting_actions[i];
3232+
this.onAction(p[0],p[1],p[2],p[3],p[4]);
3233+
}
3234+
}
31583235
this.execute_triggered = 2; // the nFrames it will be used (-- each step), means "how old" is the event
31593236
if(this.onAfterExecuteNode) this.onAfterExecuteNode(param, options); // callback
31603237
};
@@ -3165,7 +3242,7 @@
31653242
* @param {String} action name
31663243
* @param {*} param
31673244
*/
3168-
LGraphNode.prototype.actionDo = function(action, param, options) {
3245+
LGraphNode.prototype.actionDo = function(action, param, options, action_slot ) {
31693246
options = options || {};
31703247
if (this.onAction){
31713248

@@ -3174,7 +3251,7 @@
31743251

31753252
this.graph.nodes_actioning[this.id] = (action?action:"actioning"); //.push(this.id);
31763253

3177-
this.onAction(action, param, options);
3254+
this.onAction(action, param, options, action_slot);
31783255

31793256
this.graph.nodes_actioning[this.id] = false; //.pop();
31803257

@@ -3282,8 +3359,19 @@
32823359
if (!options.action_call) options.action_call = this.id+"_act_"+Math.floor(Math.random()*9999);
32833360
//pass the action name
32843361
var target_connection = node.inputs[link_info.target_slot];
3285-
// wrap node.onAction(target_connection.name, param);
3286-
node.actionDo(target_connection.name, param, options);
3362+
3363+
//instead of executing them now, it will be executed in the next graph loop, to ensure data flow
3364+
if(LiteGraph.use_deferred_actions)
3365+
{
3366+
if(!node._waiting_actions)
3367+
node._waiting_actions = [];
3368+
node._waiting_actions.push([target_connection.name, param, options, link_info.target_slot]);
3369+
}
3370+
else
3371+
{
3372+
// wrap node.onAction(target_connection.name, param);
3373+
node.actionDo( target_connection.name, param, options, link_info.target_slot );
3374+
}
32873375
}
32883376
}
32893377
};
@@ -5646,7 +5734,7 @@ LGraphNode.prototype.executeAction = function(action)
56465734

56475735
//Keyboard ******************
56485736
this._key_callback = this.processKey.bind(this);
5649-
5737+
canvas.setAttribute("tabindex",1); //otherwise key events are ignored
56505738
canvas.addEventListener("keydown", this._key_callback, true);
56515739
document.addEventListener("keyup", this._key_callback, true); //in document, otherwise it doesn't fire keyup
56525740

@@ -7150,6 +7238,8 @@ LGraphNode.prototype.executeAction = function(action)
71507238

71517239
for (var i = 0; i < selected_nodes_array.length; ++i) {
71527240
var node = selected_nodes_array[i];
7241+
if(node.clonable === false)
7242+
continue;
71537243
var cloned = node.clone();
71547244
if(!cloned)
71557245
{
@@ -11540,6 +11630,7 @@ LGraphNode.prototype.executeAction = function(action)
1154011630
//ESC
1154111631
dialog.close();
1154211632
} else if (e.keyCode == 13) {
11633+
refreshHelper();
1154311634
if (selected) {
1154411635
select(selected.innerHTML);
1154511636
} else if (first) {

0 commit comments

Comments
 (0)