Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inputs are not updated before actions #66

Open
Lachee opened this issue Apr 24, 2019 · 6 comments
Open

Inputs are not updated before actions #66

Lachee opened this issue Apr 24, 2019 · 6 comments

Comments

@Lachee
Copy link

Lachee commented Apr 24, 2019

example

The input data of connected nodes are not updated until after the onAction event. I have even tried moving the trigger to after I set the output data of the node.

Lachee Console Node

//Show value inside the debug console
function LConsole()
{
	//this.mode = LiteGraph.ON_EVENT;
	this.size = [80,30];
	this.addInput("log", LiteGraph.EVENT);
    this.addInput("cnt", 0, { label: "Message"});
    this.cnt = "";
}

LConsole.title = "Lachee Console";
LConsole.desc = "Show value inside the console";

LConsole.prototype.onAction = function(action, param)
{
    console.log("Action:", action );
    console.log("Params:", param );
    console.log("Self:", this );
    console.log("CNT: " + this.cnt );
    console.log("A: ", this.getInputData(0));
    console.log("B: ", this.getInputData(1));	
    
	this.inputs[1].label = this.cnt;
}

LConsole.prototype.onExecute = function()
{
    if (this.inputs[1])
        this.cnt = this.getInputData(1);
}

LConsole.prototype.onDrawBackground = function(ctx)
{
	//show the current value
	this.inputs[1].label = this.cnt;
}

LiteGraph.registerNodeType("basic/lconsole", LConsole );

On Message Node

function OnMessageEvent()
{
	this.addOutput("on_message", LiteGraph.EVENT);
	this.addOutput("author", 0);
    this.addOutput("content", 0);
    this.author = "Lachee";
    this.content = ".ping";
    this.triggered = false;
    this.clonable = false;
    this.resizable = false;
    this.color = LGraphCanvas.node_colors.purple.color;
    this.bgcolor = LGraphCanvas.node_colors.purple.bgcolor;
}

OnMessageEvent.title = "On Message";
OnMessageEvent.desc = "Occurs when a message is sent";

OnMessageEvent.on_color = "#AAA";
OnMessageEvent.off_color = "#222";


OnMessageEvent.prototype.onStart = function() {}

OnMessageEvent.prototype.onDrawBackground = function()
{
	this.boxcolor = this.triggered ? OnMessageEvent.on_color : OnMessageEvent.off_color;
	this.triggered = false;
}

OnMessageEvent.prototype.onExecute = function()
{
	var dt = this.graph.elapsed_time * 1000; //in ms
	var trigger = message_queue.length != 0;

    if (trigger)
    {
        console.log("TRIGGER");
        this.setOutputData(1, "Lachee");
        this.setOutputData(2, message_queue[0]);
        this.trigger("on_message", message_queue[0]);
        message_queue = [];
        this.triggered = true;
    }
}
@jagenjo
Copy link
Owner

jagenjo commented Apr 24, 2019

Yes, this is a problem of the current architecture.

Nodes onExecute is executed constantly (when the runStep method is called for the graph), but onAction is executed when the event is triggered, and it propagates, but it only calls onAction, not onExecute.

This means that there are two separate flows of execution, the constant onExecute (the data flow) and the propagated from an event (the event flow).

So if you want to blend data using both simultaneously you will have to run the whole graph before triggering the event, which is not very efficient (all nodes will be executed) but it would solve the problem:

node.onAction = function(event,param){
    this.setOutputData(0,"data")
    this.graph.runStep(); //make that data flow 
    this.trigger(0); //trigger event
}

Let me know if that works for you

@Lachee
Copy link
Author

Lachee commented Apr 24, 2019

Its unfortunate that the flow separates. I would have assumed getInputData would have forced a fetch if required, but I suppose there is no easy way to do that.

I have tried the this.graph.runStep();, however all my attempts has either cause it to not work or cause a infinite loop 😕

@jagenjo
Copy link
Owner

jagenjo commented Apr 24, 2019

I will research on the topic this week, I could create a function that executes from Node triggering the event to the node receiving the event.

Ask me about it in one week

@jagenjo
Copy link
Owner

jagenjo commented Apr 24, 2019

Its unfortunate that the flow separates. I would have assumed getInputData would have forced a fetch if required, but I suppose there is no easy way to do that.

That could be done, but fetching the input data from a previous node wouldnt solve it if that data passes through several nodes. The only solution is to force the data to flow between two nodes.

@atlasan
Copy link
Contributor

atlasan commented Jan 2, 2021

I have a early stage solution for this, currently in debug but promising.

Just for triggered/actioned nodes, I'm calling a refreshAncestors function that read the ancestors tree and execute the nodes, ensuring that all the data needed is updated. There are some checks to prevent recursions and double-execution.
https://github.com/atlasan/litegraph.js/blob/cbd9813d8234d4b4688c0746a8cfd8dd380b7659/src/litegraph.js#L3608
https://github.com/atlasan/litegraph.js/blob/cbd9813d8234d4b4688c0746a8cfd8dd380b7659/src/litegraph.js#L3096

@DiegoBM
Copy link
Contributor

DiegoBM commented Mar 10, 2021

Was this ever implemented? It would be interesting to be able to execute backwards the inputs of the event nodes, so that they can get fresh values without needing to run the entire tree. From what I understand, that's what Blueprints does. In the end most javascript applications will be more event-based than frame-based

cesaryuan pushed a commit to cesaryuan/litegraph.js-original that referenced this issue Sep 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants