Animate Rhino Viewport with Rhino Python?

SR 14 here… (5.14.522.8390, 22-May-17) (on Win 8.1)

Works for me on Rhino 5.14 Windows 10

Version 5 SR14 64-bit
(5.14.522.8390, 22/05/2017)

1 Like

Thanks for all your rigorous testing, @clement, @Helvetosaur, @ivelin.peychev and @Dancergraham.
Keep in mind though that it runs indeed, however nothing really happens for me in the viewport.

I’ve compared @clement’s script with the code available from the RhinoCommon (Rhino for Mac) API 5.1, and everything seems to be available.

The rs.Prompt() doesn’t seem to work though. It raises no errors, but it doesn’t print anything either to the command history. I’ve substituted it with a print statement, and now the frame count is output. More on this later, though.

rs.Sleep() seems to work, however there seems to be something wrong with the “rhythm” at which different code parts are executed.

@clement’s proposed code for reference:

import rhinoscriptsyntax as rs
import scriptcontext
import System
import Rhino

class MyConduit(Rhino.Display.DisplayConduit):
    def __init__(self, index, points):
        self.index = index
        self.points = points

    def PostDrawObjects(self, e):
        e.Display.DrawPoint(self.points[self.index], System.Drawing.Color.Red)

def DoSomething():

    crv_id = rs.GetObject("Select a curve", 4, True, False)
    if not crv_id: return

    points = rs.DivideCurve(crv_id, 100, False, True)

    conduit = MyConduit(0, points)
    conduit.Enabled = True

    for i in xrange(len(points)):
        if scriptcontext.escape_test(False): break

        #rs.Prompt("Frame {}".format(i)) # does not work somehow
        print "Frame {}".format(i) # this works instead

        conduit.index = i
        scriptcontext.doc.Views.ActiveView.Redraw()

        rs.Sleep(25)

    conduit.Enabled = False

DoSomething()

The for loop of the DoSomething() method, as I understand, should be responsible for the iterative part, the frame-by-frame viewport animation, since it increments the index attribute of the conduit object, and redraws the active Rhino view, which invokes the PostDrawObjects(), which should draw the current point. Finally, the script sleeps for 25ms each iteration, until it continues.

However, when I run the script in Rhino, it obviously first asks for the input curve. I select a curve and the viewport freezes for the amount of time that the code needs to run 100 iterations with 100 x 25 ms pauses and then all the frames are printed at once to the command history.

My guess is that there’s a problem with the iterative approach, maybe Rhino for Mac doesn’t support iterative redraws of the active viewport?

Really? I wonder what’s different? I thought it might be a difference between Win 8.1 and Win 10, so I installed V5 on my Win 10 machine and it errors out with the same message… :thinking:

Could it be something to do with the Dropbox folder you’re using? Other scripts in the folder overloading functions???

This was one of the first questions I asked on this forum. rs.Prompt() will only display something if the command is still active. If the command runs without interruption and then you invoke rs.Prompt() nothing will be displayed. Use prompt when you’re waiting for user input.

1 Like

This sounds like something stops redraw during the running of the command. :thinking:
Check your graphics card. I do not know how macs work but I assume you also have multiple GPUs. The one integrated in the processor chip and an external one. Check your configuration and update drivers.

Hi @diff-arch, i have a suspicion which might be related to the multi document possibilities on mac. What happens if you replace this line in the code:

scriptcontext.doc.Views.ActiveView.Redraw()

with this one, targeting the ActiveDoc:

scriptcontext.doc.ActiveDoc.Views.ActiveView.Redraw()

or this, which trys to redraw all views at once

scriptcontext.doc.ActiveDoc.Views.Redraw()

To me it looks like that the script just runs on Win & Mac, but on Mac the redraw fails as you discovered.

_
c.

1 Like

Hi @Helvetosaur, looking at the Exception dialog, it seems that you have an ImportError not an error in the script code. What do you get on this system if you just run:

import scriptcontext
import rhinoscriptsyntax as rs
print "Hello World" 

And why is it pointing to a dropbox folder ? Have you put your modules there ?
_
c.

I just threw the script in there so I have access to it from my other computers (like the mac).

All my scripts (thousands) are stored in various folders in Dropbox. I call them all via aliases/buttons. Never had a problem.

Checking here though, I pulled it out of Dropbox and put it on the desktop - and now it runs in V5. So what is it about this particular script that causes it to fail in V5 (not in V6) when it is in Dropbox?

Hi Mitch, sorry i have no idea why this happens but it seems to be caused by line 3 in my script which just calls:

import rhinoscriptsyntax as rs

Have you moved our syntax files to dropbox too ? The layer.py file is listed under a dropbox dir.
_

c.

Nope, not at all. They are in the default location, haven’t touched them…

I am just reading the dropbox path from the traceback you posted above. If you have it working now in V5 (Win) all is well.

_
c.

@clement Thanks for your reply. I’ve tried both new commands, but nothing changes. The script runs without errors, but nothing happens in the viewport. :frowning:
scriptcontext.doc.ActiveDoc.Views.ActiveView.Redraw() seems to run slightly faster than the other two options, though.

@ivelin.peychev Thanks, I did not know that about rs.Prompt().
Yes, most modern macs have a discrete and a dedicated GPU. When Rhino is running, the dedicated GPU is also running. Haha, there is no configuration and the drivers are updated by regular Apple system updates. In that regard, macOS and Windows are very different from each other. :wink:

@diff-arch, you might try if dynamic conduits fail too on your system. There is an example file named CustomGetPoint.py but i have no idea where it is located on a mac so i’ll attach it.

CustomGetPoint.py (1.6 KB)
_
c.

Hi @clement, thanks for attaching the script. I’ve run it and it seems to work.

Here’s what I see:


Should there be any animated stuff happening that I’m not producing with my mouse?
(The green line was drawn by me.)

@diff-arch, no it looks like this sample is working, The red lines and the arc is drawn in a dynamic conduit. To track down the initial problem of drawing the point animated you might try three more things:

After you have the points from rs.DivideCurve() use rs.AddPoints(points) to verify the points exist and can be added to the document.

Events (like PostDrawObjects) do not fire exceptions on windows, it might be the same on mac. To see possible errors, you could add this:

def PostDrawObjects(self, e):
    try:
        e.Display.DrawPoint(self.points[self.index], self.color)
    except Exception as ex:
        print ex

If this gives no errors on the command line while you run it, i would like to find out if the animated point is probably clipped away. You can run this python example from the help file and select a nurbs sphere in Wireframe display mode when it asks for it. Do you see a polygon mesh wireframe made of the nurbs sphere while the “press <Enter> to continue” prompt is waiting for the Enter key press ?

_
c.

1 Like

With the added code, the points are indeed created in the viewport. They appear to generated all at once, “after” the script has run (or, i guess, at the last moment of the active script).

I’ve added the “try-except” block, but no exceptions are raised. I’ve tried the three afore mentioned redraw variations.

Yes, the blue mesh sphere appears after selecting the nurbs sphere, until I confirm with “Enter”, which makes it vanish again (which seems to be normal from what I get from the code).

Your help has been tremendous so far, clement. Thank you very much! Have a nice week-end.

Good, you can remove that now. (Actually the points are added to the document, but this was just for testing purposes to see if the points are there).

Good. So we can exclude problems in the conduit code.

That is interesting. The only diffences are that it sets up a bounding box for the conduit, uses doc.Views.Redraw() for the redraw and draws in the PreDrawObjects event… Please try if you see a change with this one: Conduit_AnimatePoint.py (1.7 KB)

_
c.

1 Like

Unfortunately, this one doesn’t work either. Do you think it might have to do with the for loop and the speed that it runs at? Since that’s the only difference between the scripts right. The mesh sphere one has much more time to display the mesh, for instance, as nothing is animated. Maybe the for loop and the sleep method don’t pair well.