The Solve step is completely different from Draw step. This is how Grasshopper (and for what it is worth any other application that computes and draws e.g. game engines) work.
Grasshopper 1 is not asynchronous therefore Solve step can not halt the execution of the main thread, that also draws the rest of the UI. During the solve you can only Invalidate the UI. The redrawing of the UI actually happens when you have returned the control from the Solve call.
Here is what I would suggest:
- Run the solve on a non-ui thread.
- On every solve, update current mesh on the script instance,
- Use a GH trigger to call a recompute / redraw on the component every 500ms or so
TrainingExample.gh (6.2 KB)
import System
import System.Drawing as SD
import Rhino
import Rhino.Geometry as G
import Grasshopper
import Grasshopper.Kernel as GHK
import threading
import time
def main_solve():
for r in range(10, 20):
# wait represents compute work
Rhino.RhinoApp.WriteLine("computing mesh")
time.sleep(1)
sphere = G.Sphere(G.Point3d.Origin, r)
MyComponent.CURRENT_MESH = G.Mesh.CreateFromSphere(sphere, 10, 10)
Rhino.RhinoApp.WriteLine("computed mesh")
Rhino.RhinoApp.WriteLine("computed completed")
class MyComponent(Grasshopper.Kernel.GH_ScriptInstance):
SOVLE_STARTED = False
CURRENT_MESH = None
def RunScript(self):
# outputing a point to get gh to call draw methods
if MyComponent.SOVLE_STARTED:
return ("Training in Progress", G.Point3d.Origin)
MyComponent.SOVLE_STARTED = True
threading.Thread(target=main_solve).start()
return ("Training in Progress", G.Point3d.Origin)
@property
def ClippingBox(self):
return G.BoundingBox(-25, -25, -25, 25, 25, 25)
def DrawViewportMeshes(self, args: GHK.GH_PreviewMeshArgs):
d = args.Display
if MyComponent.CURRENT_MESH:
d.DrawMeshWires(MyComponent.CURRENT_MESH, SD.Color.Red, 2)
Now this could be executed from the main script editor as well. Not sure if you want this in GH but I made the example in Grasshopper. I can make a standalone editor example as well if you want.