Grasshopper

algorithmic modeling for Rhino

Changing sliders upstream causes "an object expired during a solution" warning

In a C#-component I'm trying to randomize slider values.

The values are updated, but the component triggers the warning  "an object expired during a solution", and I have to click close several times.

I've tried to expire the complete solution to have it recalculate, but it makes no difference.

What is the correct method to handle the expiring/recalulation of the components/solution?

the key code:

foreach(IGH_Param input in Component.Params.Input[0].Sources)
      {
        var slider = (Grasshopper.Kernel.Special.GH_NumberSlider) input; //try to cast that thing as a slider
        if(slider != null) //if the component was successfully cast as a slider
        {
          double range = Convert.ToDouble(slider.Slider.Maximum - slider.Slider.Minimum);

          slider.SetSliderValue((decimal) (rand.NextDouble() * range));
          slider.ExpireSolution(true);
        }
      }
      // do not recalculate this component ... will cause loop
      //this.Component.ExpireSolution(false);

Cheers, Eirik

Views: 1472

Attachments:

Replies to This Discussion

Yup, you're not allowed to start changing objects during solutions, because that would trigger another solution within the first one, which might trigger a third solution within the second one and so on until Rhino crashes with a stackoverflow exception.

If you want to modify sliders and run new solutions, you have to do so from 'the outside'. One way is to use UI events (menu clicks, button presses, slider drags, etc.), if you're doing this from code which is triggered by a solution (as I believe is the case here) you have to:

  1. Schedule a new solution and register a callback, then do nothing.
  2. When the scheduled solution is about to begin, your callback will be invoked and this is where you modify the sliders (but be careful, do not recompute them, only expire them).
  3. If you want to run more solutions, now would be a good time to schedule the next solution, but you can also do this from within RunScript, depends on the specifics of the case.

Maybe the attached will help.

Attachments:

Thanks David,

that was a great start.

I changed it a bit, added a lock for the butten (not really solid - but it works) to avoid it to have a function when pressed, otherwise the conversion continues endlessly and the numbers end up at 0.

I added the randomize function and the conversion the other way. The mm -> m is practical when we develop a solution and then want to use Karamba (which requires meters).

The component should work now and I uploaded it if anyone needs to randomize or convert lots of sliders in an existing solution.

Cheers,

Eirik

Attachments:

Thanks David,

the idea is to modify sliders in an existing soultion, to generate several variants which are documented as a screenshot downstream. Until now I've ran Octopus with no actual optimisation taking place and triggered the screenshot with a button.

I'm actually quite free how I trigger the slider modification, it could very well be from the 'outside'. One way would be a C# component connected to a Button component. Optimally I would like to set a number and tell the component to modify the sliders, update the solution and take a screenshot and then loop the modification.

Can I use this.Component.ExpireSolution() to achieve this?

BTW I got rid of the warnings using slider.Slider.Value=  instead of  slider.SetSliderValue()

Is that ok, or is that the wrong way?

the idea is to modify sliders in an existing solution [...]

That's not allowed. Once a solution is running you cannot go expiring stuff again. The only way forward in this case would be to run the slider values through a component and modify them when it's your turn.

One way would be a C# component connected to a Button component.

That doesn't actually solve the problem. Even though the button component itself will respond to the click outside of the solution, it then starts a solution right away. It really needs to be a UI event you yourself handle, or, alternatively, you handle the SolutionStarted event of the GH_Document and do your modifications there. However do note that this event is raised every time a solution kicks off, so you'd need to figure out a lightweight way to not do anything redundant when you handle this.

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

© 2022   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service