Need to set Advanced Options in script runtime

Hi All,

In several instances I ran into a problem where I need to change some of the Advanced Options via script during script runtime (and then restore them). Based on @stevebaer’s sample, the setting can be changed like this:

    import Rhino
    settings = Rhino.PlugIns.PlugIn.GetPluginSettings(Rhino.RhinoApp.CurrentRhinoId, False)
    s = settings.GetChild("Options").GetChild("General")
    s.SetBool("MiddleMouseViewManipulationMode",False)

The problem is, this only works after the script ends and I really need to make it work while the script is still running. Otherwise it kind of defeats the purpose of being able to access it.
I have tried using SaveSettings() or RaiseOnPlugInSettingsSavedEvent() but I can’t make it work.

Any suggestions how to effectively have these settings changed and updated while the script code is running ?

thank you,

–jarek

Hello @Jarek,

I do not know Python well. but in csharp I sometimes encounter this phenomenon.
This is often because it runs on different threads or on different stacks of events (it must be the same thing in python.)

I resolve this either with a RhinoApp.Wait () or with a function executed via RhinoApp.InvokeOnUiThread

But I do not know the correspondence with python, I hope it can help.
-jmv

hi @kitjmv,

thanks for the insight. I have tried both but it doesn’t seem to help. Either I do it wrong, or there is something else that controls the Advanced Options to refresh. I really hope there is a way to do this as I have several of them that would be super helpful to be able to toggle during script runtime.

Here is the sample of how I tried to use your suggestions (please note, to actually see the difference in that setting changing to 3, you need to have SkylightShadows ON, and the shadows quality in current display mode set to very low - then, once setting is switchted to 3, Skylight shadows become very grainy…). Just a tip how to visually test if it worked.

import Rhino
import rhinoscriptsyntax as rs

def setdegradation(intDegLevel):
    print "setting to 3"
    settings = Rhino.PlugIns.PlugIn.GetPluginSettings(Rhino.RhinoApp.CurrentRhinoId, False)
    s = settings.GetChild("Options").GetChild("OpenGL")
    s.SetInteger("SkylightShadowResolutionScale", intDegLevel)
    Rhino.PlugIns.PlugIn.SavePluginSettings(Rhino.RhinoApp.CurrentRhinoId)
    Rhino.RhinoApp.Wait()
    rs.Sleep(1000)

Rhino.RhinoApp.InvokeOnUiThread(setdegradation(3))

print "setting to 1"
settings = Rhino.PlugIns.PlugIn.GetPluginSettings(Rhino.RhinoApp.CurrentRhinoId, False)
s = settings.GetChild("Options").GetChild("OpenGL")
s.SetInteger("SkylightShadowResolutionScale", 1)
Rhino.PlugIns.PlugIn.SavePluginSettings(Rhino.RhinoApp.CurrentRhinoId)
Rhino.RhinoApp.Wait()
rs.Sleep(1000) 

Any other ideas? :slight_smile:

thank you,

–jarek

Oh,
I think Rhino.PlugIns.PlugIn.SavePluginSettings write the settings to the disk and it does not update the settings … (I guess) Yes GetChild return a Rhino.PersistentSettings you have no effect because you work on disk.

@Jarek why you don’t use Rhino.ApplicationSettings.OpenGLSettings ?

As far as I can tell this particular OpenGL setting is only accessible via Advanced Options; in RhinoCommon only AA setting is under Rhino.ApplicationSettings.OpenGLSettings
https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_ApplicationSettings_OpenGLSettings.htm

Now that I see what we use only saved on disc, it makes sense that it doesn’t update, but it all does right after the script ends. So something is forcing it to update. I am looking for that “something” to trigger it while the script runs.

As I mentioned in the first post,I was also trying SaveSettings or RaiseOnPlugInSettingsSavedEvent () but no luck.

hmm…

@stevebaer probably knows best what is currently possible and what isn’t wrt changing advanced settings and when they start affecting Rhino.

Yeah, a while ago regarding this question and ability to update from script he wrote:

But I am clinging to the “Probably” part… :thinking: also if this is not possible, wouldn’t it be nice if it was? Otherwise why bother being able to change these settings within the script. I ran into this on several separate issues I am trying to solve and would be really helpful if we could do that.

@Jarek have you test Rhino.PlugIns.PlugIn.FlushSettingsSavedQueue() ?
-jmv

I did, tried anything that looked remotely relevant with no luck so far. Thanks!

@Jarek it works for me

import Rhino
import rhinoscriptsyntax as rs

def setdegradation(level):
    settings = Rhino.PlugIns.PlugIn.GetPluginSettings(Rhino.RhinoApp.CurrentRhinoId, False)
    s = settings.GetChild("Options").GetChild("OpenGL")
    s.SetInteger("AntialiasMode", level)
    Rhino.PlugIns.PlugIn.SavePluginSettings( Rhino.RhinoApp.CurrentRhinoId)
    rs.Sleep(1000)


print "setting to -6"
setdegradation(-6)
Rhino.PlugIns.PlugIn.RaiseOnPlugInSettingsSavedEvent()
Rhino.RhinoDoc.ActiveDoc.Views.Redraw()

print "setting to 3"
setdegradation(3)
Rhino.PlugIns.PlugIn.RaiseOnPlugInSettingsSavedEvent()
Rhino.RhinoDoc.ActiveDoc.Views.Redraw()

its the combination of : push the stack of settings changes (with RaiseOnPlugInSettingsSavedEvent()) and refresh the view (Redraw())

-jmv

1 Like

@kitjmv - that works! thanks for your persistence :slight_smile:
Looks like the rs.sleep(1000) is also needed (or at least 400 over here) for the saved settings to ‘register’, otherwise it doesn’t work. So it is a combo of a few methods to make it update.

Great, I will test the other Advanced Options I had problems in the past as well. The Skylight Shadows degradation works well:

And here is the test code:

    import Rhino
    import rhinoscriptsyntax as rs

    def setdegradation(level):
        settings = Rhino.PlugIns.PlugIn.GetPluginSettings(Rhino.RhinoApp.CurrentRhinoId, False)
        s = settings.GetChild("Options").GetChild("OpenGL")
        s.SetInteger("SkylightShadowResolutionScale", level)
        Rhino.PlugIns.PlugIn.SavePluginSettings( Rhino.RhinoApp.CurrentRhinoId)
        rs.Sleep(1000)

    print "Degradation set to 3"
    setdegradation(3)
    Rhino.PlugIns.PlugIn.RaiseOnPlugInSettingsSavedEvent()
    Rhino.RhinoDoc.ActiveDoc.Views.Redraw()

    rs.Command("_TestMaxSpeed _Enter")

    print "Degradation set to 2"
    setdegradation(2)
    Rhino.PlugIns.PlugIn.RaiseOnPlugInSettingsSavedEvent()
    Rhino.RhinoDoc.ActiveDoc.Views.Redraw()

    rs.Command("_TestMaxSpeed _Enter")

    print "Degradation set to 1"
    setdegradation(1)
    Rhino.PlugIns.PlugIn.RaiseOnPlugInSettingsSavedEvent()
    Rhino.RhinoDoc.ActiveDoc.Views.Redraw()

    rs.Command("_TestMaxSpeed _Enter")

Much appreciated!

–jarek

Wow, that’s one heck of a hack. Great job guys; I was scratching over this one in silence for a while

I’d fix the typo from Dergatation to Degradation. But cool stuff :slight_smile:

1 Like

done

Hello @Jarek

Well, we were lucky and your question relates to my current personal projects. But happy if it helped you.

Just to understand.
The problem is still in the queue of events (here the parameters queue changed)

and what helped me is the documentation of RaiseOnPlugInSettingsSavedEvent:

# Raise any pending OnPlugInSettingsSaved events, the events are normally
# queued while a command is running and and fired while Rhino is in an
# idle state.  Calling this method will raise any pending changed events
# regardless of Rhino's current idle state or if a command is running.

So all that forces Rhino to go in Idle “should work”.

However, it seems that Python integration has a strange behavior with the Idle event (or RaiseOnPlugInSettingsSavedEvent).

Test this code

import Rhino
import rhinoscriptsyntax as rs

def setdegradation(level):
    settings = Rhino.PlugIns.PlugIn.GetPluginSettings(Rhino.RhinoApp.CurrentRhinoId, False)
    s = settings.GetChild("Options").GetChild("OpenGL")
    s.SetInteger("AntialiasMode", level)
    Rhino.PlugIns.PlugIn.SavePluginSettings( Rhino.RhinoApp.CurrentRhinoId)
    Rhino.PlugIns.PlugIn.RaiseOnPlugInSettingsSavedEvent()

print ">> -6"
setdegradation(-6)
print "<< -6"

for i in range(0, 5000000):
    n = i

rs.Sleep(1000); print "Now work"
# or
# rs.Sleep(0);
# Rhino.RhinoApp.Wait();

print ">> -6"
setdegradation(-6)
print "<< -6"

for i in range(0, 5000000):
    n = i

print ">> 3"
setdegradation(3)
print "<< 3"

for i in range(0, 5000000):
    n = i

print "end"

As long as Python does not leave its thread at least once, no call to RaiseOnPlugInSettingsSavedEvent will work

…?

-jmv

(finally, Rhino.RhinoDoc.ActiveDoc.Views.Redraw () is useless)

Did you test to see if a rs.Sleep(1) works too then? Possibly even just rs.Sleep(0)

No, as Jarek remarks

it depends on the machine. On mine, i can set the sleep to 100.
I think it’s a very special bug. I said above that

but in fact, I do not know, I have not tested with C# or C++ …

-jmv

but

rs.Sleep(0);
Rhino.RhinoApp.Wait();

work.

So RaiseOnPlugInSettingsSavedEvent, (despite misleading documentation). it need to raise a Idle to work.
but why just one time ? why the other calls of RaiseOnPlugInSettingsSavedEvent work after ?

Hi @kitjmv

On my end, unless I have rs.Sleep(600) at least, it does not work, I mean the first attempt does not, then later in the script the sleep can be very short. I don’t see any difference with using the Rhino.RhinoApp.Wait() in that behavior.
Ideally I would have the change happen instaneniously and not force wait ~1s.

How would I need to modify the code I posted last to make it work quick from the get-go? I am wondering if at least on your end you can avoid the initial wait for the change to be picked up.

Thanks!

–jarek

@Jarek

On your side, confirm me, only one call to rs.sleep is needed to make all calls toRaiseOnPlugInSettingsSavedEvent work ?

Your script must run on different machines ?