Neos-Metaverse / NeosPublic

A public issue/wiki only repository for the NeosVR project
194 stars 9 forks source link

Reversed for loop LogiX node #1917

Closed Gawdl3y closed 3 years ago

Gawdl3y commented 3 years ago

Is your feature request related to a problem? Please describe.

Using a for loop that has destructive actions on each iteration will cause incomplete loops when the destructive actions are being run against what is being iterated on. For example, using a For node to iterate over children slots and destroy them if they meet a condition. If element 0 meets the prerequisite condition, it gets deleted. This shifts all of the children down an index, so the next iteration running on element 1 means the new element 0 is skipped entirely.

Relevant issues

None found.

Describe the solution you'd like

A node that behaves identically to the For node, except runs the loop in reverse (starting at the last index and descending). This avoids the problem of indices changing entirely. Could possibly be named "Reverse For" or "For (Reverse)".

Describe alternatives you've considered

The most obvious alternative is manually looping with your own counter variable and a While node, but this is much less convenient than the self-contained For node.

Additional context

Equivalent C# for a standard For node:

for(int i = 0; i <= maxIndex; i++) {
    // do stuff
}

Equivalent C# for a Reverse For node:

for(int i = maxIndex; i >= 0; i--) {
    // do stuff
}
shadowpanther commented 3 years ago

The obvious shortcut would be

for(int i = 0; i <= maxIndex; i++) {
    j = maxIndex - i;
    // do stuff with j
}

That is, using For node to count up, but reversing that counter by subtracting it from a fixed value (number of children).

Gawdl3y commented 3 years ago

That's absolutely a valid option, and is actually what I ended up doing for my most recent use-case (specifically, I was iterating through slots and re-parenting them to a different slot when a specific one of their children met a condition). In my opinion, however, it muddies the waters a little bit in comparison to the loop just running in reverse since you are operating on the counter value rather than using it directly. Although it's not a huge difference, seeing as the purpose of the For node is to eliminate the need for your own counter logic, and how common running a loop in reverse is (in my experience, at least), I think it's worth implementing another node for.

bentallea commented 3 years ago

Having dealt with this issue, this is fairly simple to implement with the current logix. Here is some pseudocode to help.

index = 0; while (index < child count) {   if (condition == true) {     delete child at index;   } else {     index++;   } }

This is one of those times a for loop will not work as currently implemented due to not being able to skip the increment. This is why I use a while loop for this. This is the system I use for the fully functional Rubik's cube available in my Public Folder. If you want to see it, unpack the "FiniteStateMachine" object under "LogixRoot" in the cube. I had to deal with a lot of reparenting of objects while building the Rubiks Cube.

Frooxius commented 3 years ago

Added "Reverse" input to the For node in 2021.6.8.685, thanks!