algorithmic modeling for Rhino
I had mentioned offhand in this discussion, but I thought I'd reiterate it here - it would be really great to have an option to cause Hoopsnake to automatically re-run its loop on an update to the data being fed to it. If I want to use a recursive process as a substep of a much larger definition, hoopsnake "breaks" the parametric flow of a definition, in that making a change upstream of hoopsnake does not cause those changes to be propagated all the way downstream.
As an example, imagine using hoopsnake with galapagos, where the genome drives a recursive process that generates the fitness factor; as it works currently, the hoopsnake component would not recalculate on a change in the genome, so galapagos would not function properly.
My original idea was to check for change in the B* input and start looping only if it is true. In this sense, we'd have four cases:
Hoopsnake loops and B* is true - continue looping.
Hoopsnake loops and B* is false - stop.
Hoopsnake is idle and B* becomes true - start looping.
Hoopsnake is idle and B* becomes (or is) false - do nothing.
So, your loop-ending logic would remain exactly the same, only now you could have additional loop-starting logic somehow attached to it, if you want to. That coupled with a separate option to enable value-checking at the inputs.
Just one thing to note though, even with this feature I am not sure if it would be possible to allow for multiple loops within a single Galapagos iteration. Galapagos depends on detecting the end of a single loop and would therefore continue as soon as the first loop finished executing, at the same time with Hoopsnake, which would probably cause all hell to break loose imo.
Still I believe that eventually nested loops using multiple Hoopsnake components could be feasible, but to do the same with other types of components would require changes to those components as well.
Would this strategy require writing some test to trigger a new loop? What sort of a function are you imagining gets fed into B* that can handle these situations? In the attached screenshot, I am not clear what I would have to add to B* in order to cause it to become true when the slider changes.
We can forget about galapagos then for now - I am just interested in this in the context of normal definitions.
EDIT: ah - I reread your reply. What you're suggesting is BOTH the ability to program a function that triggers a new loop on the fulfilment of some condition, AND the triggering of loops when the inputs to S or D* change - is that right?
I actually believe that triggering Hoopsnake "by hand" using another component (i.e. slider) is not really a good idea, at least at this stage. Imagine: You move the slider and then the component immediately starts looping. But while it's looping the slider is still active, since each loop is a regular grasshopper solution! So, you may quite easily accidentally change the slider value while a solution is being calculated using Hoopsnake. Which renders the slider useless as a trigger in the first place.
A solution to this problem would be to disable the Grasshopper interface for as long as the looping takes, but that would then render the whole process really clunky, especially if you have slow definitions. And you still have the problem where, for example, you just want to adjust a value, but then that value change triggers the loop.
I would therefore consider automatic retriggering solely for the purpose of "chaining" multiple Hoopsnake components, although that's too kind of a premature idea for the time being...
In any case, lets check the possibilities each input offers:
S: Not much, as it is not intended to be changed by the Hoopsnake loop anyway.
B: Has to be true in any case to loop. Otherwise, even if manually triggered to loop will stop. Therefore, the termination evaluation function has to be true when we want to trigger the loop.
D: This is where the real decision lies. Imo, either case (considering this input or not for triggering) would be fine. But still, keep in mind that the B* would, by definition, still need to be true in order for any looping to be performed.
So, to sum up I'd say that B&D both trigger change, but only if B is true. And an interface based option to disable this of course.
What about adding a boolean reset as a separate input rather than an automatic reset for a change in S B or D?
This would let the patch be triggered in a more customized way according to the particular logic of the patch.
Another related thought would be to have a way to automatically trigger one more iteration within grasshopper rather than having to press the button in the hoopsnake popup window. This could allow anyone who wanted to to attach a timer and animate the iterations according to set intervals.
Also, thank you Yiannis, hoopsnake is already a huge addition to grasshopper.
I agree with Daniel about the separated trigger input. Any change of the value would trigger the loop. Maybe you can plug in the I output of another hs component to nest? I guess it's not that simple...
In that case there is no need for disabling an option (that could be troublesome) and you can trigger loop from gh canvas.
Hoopsnake loops and T* doesn't change => continue loop.
Hoopsnake loops and T* does change => break loop
Hoopsnake is idle and T* doesn't change => do nothing.
Hoopsnake is idle and T* does change => start loop.
Maybe another case if IsNull ?
I don't understand your idea about the timer. Are you talking about Step triggering or Loop triggering?
I am a fan of the idea of the separate trigger input. It may not be as minimal a solution, but I think for the sake of clarity and ease of use it makes the most sense. And Fred's suggestion that it respond not to a specific value (such as TRUE) but to any update in value solves the problem I have. Having a separate input also sidesteps the necessity of a special option to choose between "auto-reloop" mode and the way it currently functions.
Despite Yiannis's concerns, I think having some way to cause the loop to automatically re-run on ANY update would be extremely valuable. His solution with freezing the GH interface while this runs does not seem like such a bad thing to me - I am more than used to waiting a minute or two for a complicated definition to respond to a change far upstream.
The way I get around this limitation currently is simply to avoid using hoopsnake and manually link together copy-pasted sets of components, one for each step of the loop. This is inelegant and messy, but it gets the job done, updating automatically each time the input changes. Because each individual operation is relatively simple, it's actually perfectly fast for my purposes. Assuming that HS's looping is almost the same as or faster than this dumb stringing-copies method, I think the "clunky" processing that Yiannis fears is really not a problem. For me the crucial thing is to be able to include a recursive process in the middle of a definition, and not have to worry about the separate step of double-clicking the HS component, resetting it, and telling it to loop, every time I make an upstream change.
First of all, I would like to thank you all for your involvement and great ideas that help the development of this component, as well as Grasshopper in general I should say.
I've been thinking about it and I am convinced that indeed as you propose a separate trigger that checks for data changes is the way to go. The scheme I was considering is more or less similar to the image Fred posted, although as you can see the outputs are somehow different: iS outputs the iteration count, while iL outputs the loop count, i.e. the number of complete loops (till the B* turned false) that have occurred so far. It's not so much informative in itself, but the change it produces is useful to drive serially linked Hoopsnakes, adding to the already discussed ability to nest Hoopsnakes using iS.
I believe that it is a simple and relatively easy to understand scheme, and it doesn't prevent the use of Hoopsnake as it is currently being used. However, in order to implement it a fundamental re-working of the internals of Hoopsnake needs to be carried out and since I haven't even began with it I can't really foresee what obstacles would come up during development... but i'll give it a try anyway.
Still, that is a couple weeks away since I am currently quite busy with my graduation project and there are also a couple bugfixes that need to be done first..
So, thanks again for the great feedback and please do say what you think of it!