The only safe way to Update Sliders in GhPython

Over the years, there have been lots of threads here and on the old Grasshopper forum that deal with setting slider values in Grasshopper. They all have some advantages and disadvantages, but they have something in common: they too often end up breaking the Grasshopper SDK rule “never edit values while the definition is running”.

This thread shows a way of fixing that. This is a Rhino-6-only possibility, because this feature is new in Rhino 6. By overriding the Component Context menu, we can set the values outside of the solution, in a very Grasshopper-classic way.

Like this definition by Anders Holden Deleuran on the old Grasshopper forum, this uses the logic of searching sliders by name. You can however adapt it to using slider InstanceGuids, so that they can be renamed.

image

Here is the code:

"""
Reset named sliders.
Right-click on the component and choose "Update Sliders!" to update their values.
    Inputs:
        Sliders: (strings) A list with names of sliders
        Values: (numbers) A list with values of sliders
    Remarks: This component does not retuns any values.
 """

from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import rhinoscriptsyntax as rs

class UpdateSliders(component):
    
    def RunScript(self, Sliders, Values):
        if not Sliders or not Values:
            Sliders = None
            Values = None
            return
        self.Sliders = Sliders
        self.Values = Values
        if len(Sliders) != len(Values):
            raise Exception("Different lenghts of sliders and values")
        self.Component = ghenv.Component
        self.GhDef = None
        if self.Component: self.GhDef = self.Component.OnPingDocument()
        
        
    def AppendAdditionalComponentMenuItems(self, menu):
        item = Grasshopper.Kernel.GH_Component.Menu_AppendGenericMenuItem(
            menu, "Update Sliders!", self.OnClicked, self.Icon_24x24, None, True, False);
        item.ToolTipText = "Update the sliders now";
        
        
    def OnClicked(self, obj, args):
        try:
            self.UpdateValues(obj, args)
        except Exception, ex:
            System.Windows.Forms.MessageBox.Show(str(ex))
            
    def UpdateValues(self, obj, args):
        if not self.GhDef: return
        if not self.Sliders or not self.Values: return
        
        ghObjects = self.GhDef.Objects # Get to the GH objects
        
        # Iterate the GH objects
        for obj in ghObjects:
            # Set the named slider values
            if type(obj) is Grasshopper.Kernel.Special.GH_NumberSlider and \
                obj.NickName in self.Sliders:
                
                # Set min/max
                #obj.Slider.Minimum = 0
                #obj.Slider.Maximum = 10
                
                # Set value
                obj.Slider.Value = self.Values[self.Sliders.index(obj.NickName)]
                
                # Update slider
                obj.ExpireSolution(True)

Have a look and see if it helps!
Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

18 Likes

Maybe this is pointless, because it slows the solution, but if the only safest way is to update the sliders manually by a button then how is galapagos doing it?

How can I get access to sliders inside galapagos’ gene pool?

Hi, it seems to me that Galapagos, is only able to update the tick of the sliders without been able to read again the values, is basically for esthetic reasons. There are other discusions on this forum about how to create that dinamic effect but it is basically not useful for anything else. So Galapagos is not really using the data of the sliders, they are generated internally.

Yeah, I know it’s not reading the values from the sliders, they are used only for visualization, the random values are created inside galapagos code, but it is updating them while computing, and according to Giulio that’s unsafe.

I made a script doing pretty much the same but I get errors. If I have to do it with a button I’m losing the effect. And how I’m doing it is unsafe. I don’t understand then how is Galapagos doing it.

Yeah, Galapagos is updating the values on slider but it’s not using the values of the input, doing that cause all sorts of problems with the behavior of the slider and the Solution Expires. So there is not real feedback. You can modify Giulio’s Script for doing the same thing that Galapagos does.

Galapagos is not updating the sliders from the solution. It is doing it from a button that is invoked outside the solution mechanics.

Problems start if your script that computes the solution also calls for sliders to be recomputed.

So:

  1. Updating sliders from outside the class in gh_python?
    or
  2. updating from a separate gh_python, not the one defining their values?

It’s not a problem of class. It’s a problem of invocation chain (thread call stack).

The easiest way to fix it always is by doing what I mention above.

Yeah but I don’t want user interaction to update them I want it to happen automatically.

Nothing forbids you, from the button above, to request the computation of 7 different solutions, or even an infinite loop (might not be smart, though).

Hmm, how? Using boolean sticky variable to toggle it?

:smiley: about that I get slapped everytime I try to use While loops. Every single time if I forget to use try: except: I crash Rhino.

For example, by having:

try:
    for i in range(10):
        self.UpdateValues(obj, args)

in place of:

try:
    self.UpdateValues(obj, args)

Or in any other common way loops work.

1 Like

2 posts were split to a new topic: Deleting Rhino objects during solution time

How do I get the menu object to run AppendAdditionalComponentMenuItems?

@charles2, what are you meaning here? The method is called by Grasshopper.

Btw the docs say this method is obsolete.
(And also it doesn’t seem to work anymore – at least I didn’t got it to work. No button there…)

Guys… just a reminder: if you need help with something new in particular, please start a new topic!

As far as I know, Galapagos does use the values on the sliders in the sense that they are required to recalculate the definition and to return the objective. It doesn’t read the values, rather it sets them based on the algorithm. There’s quite a bit of care required to do this safely, i.e., without triggering unwanted recalculations of the definition.

In other words, there’s a difference between setting slider values and recalculating the definition based on the new values (“updating”). In Grasshopper, the two are linked so as to seem identical, but that’s not the case for Galapagos.

My version of this is here. Have a Look at Recalculate()

1 Like

Hi Giulio
Is it possible to autoUpdate values without right click?

Imagine a car has a flat tire and you ask: “Is it possible to drive?”. The answer may be:

  • it’s possible but your car will not work as well and might get damaged
  • it’s not possible without fixing the tire

Here it’s pretty much the same: if you want to make it work properly, then the answer is that any update to values that get recomputed should be from outside the “solving” timeframe. If you do while solving, there might be some combinations that work, but not really well… I hope this explains.

2 Likes