algorithmic modeling for Rhino
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.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));
// do not recalculate this component ... will cause loop
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:
Maybe the attached will help.
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.
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.