How can we do modelling works when running a 'backgroud' script?


#1

Hi all,

I am wondering, is that possible to have a ‘background script’ running when we are doing some modeling works?
For example, in the RhinoPythonPrimer 101, Page27, there is a script can constantly update the time and display on screen. But when this ‘time script’ is running, we cannot do modeling works smoothly. I cannot click and select any object. Even try to pan the view is not smoothly( maybe because of the ‘rs.sleep’ causing stop for the entire rhino).
I know that we can do some modeling work using button. But can we have a better way to let a script running at the ‘background’ without affecting our modeling experience? Grasshopper seems like an option. But I am more interested in resolve in Rhino or RhinoPython.

Appreciate for any suggestion,

Jack

P27.py (682 Bytes)


(Dale Fugier) #2

Sorry no. Rhino is not a multi-threaded application. Python scripts run in the same “thread” as Rhino. You can think of running a script like running any other command…

– Dale


#3

Thanks for your reply dale. Is there some way can achieve similar things like this?
I know that when you are running a python script, you can still run another script which been made to be a button.
Can we use event handler to achieve it? I am not sure how does event handler works… does it work like some objects waiting for events – when some events happen then it starts to do something?
It is just my imagination…

Thanks for any hint,

Jack


#4

Depending on the concrete scenario, Grasshopper would definitely be a pretty straight forward way of doing something like this (i.e. have a script iteratively execute, either using the Grasshopper Timer or through code).


#5

Hi Anders,

Thanks for your advice, will give it a shot.


#6

Here’s a very basic example using the timer (you can code a GHpython component to update itself in the same manner if this is a requirement):

160427_ViewportClock_GHPy_GHTimer.gh (4.0 KB)


#7

Cool, thanks Anders!


#8

Also check out the sleep Function
RhinoScript
http://developer.rhino3d.com/api/rhinoscript/utility_methods/sleep.htm
RhinoPython
http://developer.rhino3d.com/api/RhinoScriptSyntax/win/#utility-Sleep


#9

Thanks Tom!


#10

Sleep is the function that is used in the original script. It is what locks up the interface (that said, if you set it to a smaller interval, this might not be an issue for you).


#11

Is there any other syntax similar to rs.sleep but won’t freeze the whole rhino so I can do the modelling work smoothly? In other word, any syntax like timer that can trigger the script to run again but between the gap it won’t freeze rhino?


(Willem Derks) #12

Shot in the dark:

pythons time.sleep in the time module maybe?

-Willem


#13

That’ll also lock up the Rhino UI. You’ll need to run it in another thread that won’t affect Rhino in the same way. The easiest/fastest method for doing this would be through Grasshopper (like in the example I posted above), but I’m sure there are also other (not so simply) solutions for achieving this. It is difficult to provide any concrete advice without the full scope of the modelling problem though.


#14

@Jack_Zeng,

you might also subscribe to an idle event which does not fire when Rhino is busy. Below is a simplified example script which shows the current time in the statusbar, run it again to turn it OFF.

import Rhino
import scriptcontext
from datetime import datetime

def MyIdleEvent(sender, e):
    message = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    Rhino.UI.StatusBar.SetMessagePane(message)

def DoSomething():
    key_idle = "MyIdleEvent"
    if scriptcontext.sticky.has_key(key_idle):
        print "Time display OFF"
        Rhino.RhinoApp.Idle -= scriptcontext.sticky[key_idle]
        scriptcontext.sticky.Remove(key_idle)
    else:
        print "Time display ON"
        scriptcontext.sticky[key_idle] = eval(key_idle)
        Rhino.RhinoApp.Idle += eval(key_idle)
        
if __name__=="__main__":
    DoSomething()

I have not tried how it behaves if more complex scripts are fired from the event. In general try to leave the event as fast as possible, the event fires often !

c.


#15

Thank you clement, I think I need to learn a little bit of sticky to understand how it works.
Cheers!


#16

Yes, you are right.

Here is an example, if I would like to let rhino objects (like 2D people and trees) always facing to the camera when I am modeling (just like SketchUp). I would prefer to let it run as an ‘background script’ so I can still do manual modeling or run other scripts.
The reason why I prefer to achieve it in rhino because I can use those 2D objects already exists in rhino and I can easily scale them, adjust location, change trees’ color, texture etc. But if I do it in grasshopper then it is not so easy for me to modify the 2D objects…
Attached a script I just done using ‘rs.sleep’ method for this example – but it is not ideal – it freezes rhino every second…and I cannot run other scripts when this script is running.

Thanks for your help :slight_smile:

Background Script.3dm (627.8 KB)
Background Script.py (1.7 KB)

Jack


#17

@Jack_Zeng,

another way without using your own events or GH is to write your script so it collects the billboard surfaces without selection, eg. by name and then does the update whenever the script is run. To run the script, you might just add it to Rhino’s idle processor and set the idle time to whatever value you like:

c.


#18

That’s a terrific idea. Didn’t even know about this feature, thanks!


#19

Hi clement, this is definitely dark arts!!
I have give it a shot but fail to trigger the idle processor…
The way I did was copying the whole script into the box just like making a custom button.
But after I click ‘OK’ and wait – then not thing happen…

I have check my script and run it using python and it works, so I think it must be something missing on the idle processor ( I have check ‘Enable…’ and set the ‘time’ to 1 as well ).
Could you help to explain a bit more about using idle processor?

Another query is, when I run my script using Python, the mouse turns to be a kind of status as it is within a command and I cannot select other object or do other modeling works. Not sure which line causes this issue… do you have any idea? Guess even though the idle processor works this issue will still exists.

Auto-Facing Objects.py (1.6 KB)
Auto-Facing Objects.3dm (623.7 KB)

Many thanks,

Jack


#20

@Jack_Zeng,

are you testing in Rhino 5 or Rhino WIP ? When i try to run your script from within the python editor in Rhino 5, i get this error in line 2:

Message: 'LightException' object has no attribute 'components'

Trying to run your script in Rhino 6 WIP, i get this:

Some general tips before i make an example:

  1. Error tracking: If your script runs fine from the python editor and nothing happens when running it using the idle processor, your script must be set up so it prints out what is missing. Error checking is the key to good scripting. Try your script in an empty scene and see what happens if no billboard objects are in the document…sounds silly but you always have to think about whatever case which can happen when things are just missing.

  2. Canceling with ESC using scriptcontext.escape_test cannot not work using events or the idle processor. Your script will continue to be run as often as the event fires. You have to write your script so it can be canceled by stopping the event when certain conditions are not met. Using the idle processor means that you have almost no way to stop the processor from within the script undless you are able to remove the script from the the processor or stop the processor by scripting the _Options command using this macro:

_-Options _IdleProcessor _Enabled=No _EnterEnd

  1. To use the idle processor i would suggest to start with a very basic example to find out if this works at all. Save a script to your harddrive. Do not paste the whole scriptcode into the “Commands to run” field. Run the script as shown in my post above to see if the script is fired by the idle processor. An example would be such a simple script:

print "HelloWorld"

Saved that under C:\ or whereever you want eg. by naming it “IdleProcessorTest.py” and in the dialog of the idle processor use this macro so your script can be found when run:

! _-RunPythonScript C:\IdleProcessorTest.py"

Enable the idle processor by checking the “Enable idle Processing” toggle, and set the time to 1 second. Do you get something ? Using Rhino 6 WIP, i do not get the “HelloWorld” string printed. @dale I guess this is a bug, running a script in Rhino 5 using the idle processor works fine.

c.