“True” if recomputation is finished python

I have a gh python script that computes a while. :wink: Once the solution is finished and the geometry is visible in the viewport i would need a trigger like a “True” to start another component.

How can I check if the Grasshopper Solution is finished and Rhino is “idle” in a simple way?

Right now I try to initialize the “output” in the beginning of the script to “False”, then compute it and replace the output with the new geometry. Unfortunatly the trigger is too fast and is not waiting for the finished representation in the viewport. Therefore it renders the “old” state of the geometry one frame before.

There are events associated with the beginning and end of solutions. GH_Document.SolutionStart and GH_Document.SolutionEnd.

Another way to do something after the current solution ends is to schedule a solution -say- 10 milliseconds after the current solution finished using GH_Document.ScheduleSolution. You provide a callback to the schedule, and when the next solution kicks off (probably your scheduled one if it’s quick, or maybe someone beat you to the punch) you expire some object and that object will run again.

Conceptually:

bool _cleanUpSolution;
data _resultOfHardWork;

SolveInstance()
{
  if (_cleanupSolution)
    AnyCleanupActionsThatNeedToHappen();
  else
    StartTheHardWork(); // Presumably this takes time on some other thread.
  
    output = _resultOfHardWork;
  _cleanupSolution = false;
}

void HardWorkIsDone()
{
  _resultOfHardWork = newData;
  OnPingDocument.ScheduleSolution(10, ScheduleCallback);
}

void ScheduleCallback(GH_Document document)
{
  _cleanupSolution = true;
  this.ExpireSolution(false);
}
1 Like

Thank you David. Thats excellent info. I was hoping that there might be a very simple “if Rhino Viewport is redrawn” approach without the grasshopper eventhandlers. In my case it is clearly Rhino that has not redrawn the new state of geometry yet. My “True” output from Grasshopper works perfectly fine. Basically the script updates a geometry and trigger a rendering. So the actual geometry in the rhino viewport has to be the latest one. In my script GH sends a “GO” to a renderscript and this script is immedatly starting the rendering without waiting for the Rhinoviewport to update. So its always One Frame off…

Does “SolutionEnd” inlcude the Redraw of the Rhino VIewport?

There is no guarantee about whether the viewport will redraw before or after the SolutionEnd event.

Why not just make it sleep for a few seconds, it should not have a serious impact if the whole process is long.

import time
s = 5 # seconds to sleep
time.sleep(s)
# then start the rendering

Thank you guys. I already tried that time method. Basically I have two Python modules. Once the first one has generated the geometry, the second one kicks of a render. The problem is that the geomerty of module one is not drawn yet and so the render sees nothing.

A timer in the second “render python” module was my first idea, too. Suprisingly the redraw of the canvas is only triggered AFTER that timer is finished, so when the whole grashopper solution is solved (including the timer)

Therefore i stuck with that issue and i can not see a solution from within GH itself to trigger a render once the solution is truly finished and redrawn in the viewports.

What I am looking for is a “Feedback” from Rhino to GH that the Geometry was recieved and is now visible in the viewport and Rhino is idle. After that “Ready” Trigger, my second pythonscript should kick off the render.

Oh wait, when I read what you experience I remembered someone saying that time.sleep() is in fact locking/making rhino sleep. So, it after the first script it hits time.sleep() then it proceeds to the redraw. Why don’t you try to make the second script delay by making python count to 100ms or whatever time it needs to wait.

I have tried that as well. It feels like the Rhino viewport redraw is only tiggered after the whole GH solution is finished. So no matter where i put this break, I can not capture the actual solution of GH as it is not drawn yet.

Please find a very simplified version attached. This script basically tries to capture the viewport once you change the x count. The jpg is saved on the current desktop. If you move that slider around you will see that it is very often the “last” version of the geometry and not what is currently visible in viewport.

ak_render_trigger_demo.gh (9.2 KB)

if you put a datadam like so:

set the delay to 1 or 2 secs it seems to do it.

it actualy waits for 1st script, puts the result in a buffer, waits 1 sec and passes it to the 2nd script

Nice. Thanks Ivelin. That helps already a lot. Depending on the time it takes to redraw the solution this delay may differ. So i still hope there is a way to basically have a kind of “Rhino has the latest GH state” trigger instead of that fixed timer.

Thanks again! That solves my problem in the short term for sure!

1 Like

You can try temp baking using python then put the snapshot script at the end. But that’s an idea never tried it.
Basically you should hide GH display in Rhino and wait for the bake. You can use pipeline to feed Rhino geometry directly to the snapshot script and if None, don’t take snapshot:

image

Update:
I saw this component in HUMAN, might as well be useful.

There are also auto-baking components there as far as I know. Never tried any of them, though.

Good Idea. The problem is that i need it in the script. I am trying to render out with Vray and therefore have to have a Vray geometry node in the end. I guess baking is not an option then.

With this you can put it back in GH.
But if it works only by using the datadam than better use that to avoid additional processing.

Hi David. Sorry for bothering you again for that topic, but i can not find a good solution for this and the topic has a lot of potential.

Would it be possible to attach a very basic example of a grashopper script that simply loops from 0 - 100 and captures a screenshot of each solution? The important thing would be that the end of the solution itself triggers the screenshot and once the screenshot is capured, it tiggers the next iteration. That woud be super helpful and i think it might help a lot of people that trying to capture a lot of iterations.

All other solutions I found so far are pretty weak, asyncron and unstable.

Hi,

I might have gotten your problem wrong, but I remeber watching this as en excersie where multiple gh python componets are used and one starts after the previous one has finished. It is also all set up to render an animation. Maybe it can help you in someway.

Thank you very much for your help. The solution was to “decouple” my one pythonscript into three seperate pieces. Timer, Geometry Creation and Rendering. The trick was to not “connect” these components via wires but insteadt trigger them seqentially one after another by initiating a “SolitionEnd” as David was hinting at. This way after every iteration the solition is “finished” from a GH point of view and the Rhino Viewport gets an updated state, ready for rendering. This rendering then triggers the timer and so on. Its pretty stable for now and is perfectly synchronous but took me forever to get it up and running that way. The basic problem with a “timer” component is that GH essentialy wants to finalize the loop first before it triggers a rhino refresh. So the renderloop has to be “outside” of the canvas to get intermediate results or the solition has be “ended” by code as in my case. Both solution are difficult to wrap your head around and some additional nodes that provides easy access to this “SolutionEnd” functionality would be supercool.

1 Like

Hey @ak3d do you have some kind of minimal working example you could share? I’m curious to see how this works. Undoubtedly someone is going to come across this thread googling your issue at some point :wink:

Hi,
I’m running into the same situation. Did end up with a good solution?