So I preferred the prior way. It’s conceivable that you might introduce a second function so you can have it both ways, but that seems like overkill unless you anticipate having a lot of both cases in the code, which isn’t the case with The Witness
I now had a Lister Panel that could list things hierarchically, but it couldn’t actually perform its filtering when things were listed hierarchically, since I had not yet put in any code to call the filter. It may seem like an easy addition of just calling the old “passes_filter” call at each step of the hierarchy, but doing filtering that way has a drawback: if you want to, you can’t actually display the parent groups of things that are included in the filter unless the parent groups are also included in the filter.
In other words, say you want to see all grass entities in the world, but you want to see them in a view that shows the complete hierarchy leading up to each grass entity. Ie., if a grass entity was inside a group, you want to see that group expanded and the grass entity inside it, but you don’t want to see any other groups or any of the non-grass entities inside the group. This is a pretty common operation to want to do, since often times you want to manipulate the groups that things are in, but the only way to find those groups is by talking about the things that are in them. So filters are usually best written on non-groups even if you want to manipulate the groups themselves.
Filtering like this is not something that can readily be performed during a depth-first walk of the hierarchy, and even if it was, it’s not clear that the code should work that way, since part of the idea behind the Lister Panel was that the rendering code wouldn’t iterate over all the entities all the time, it would only iterate over the filtered entities as found by the update() function, to ensure that it could still be used if the total entity count got too large. So what I needed to do was write a prepass that went through the filtered entities and figured out what groups should be “pulled in” by the filtered entities if the Lister Panel was set to a mode where the hierarchy was always supposed to be shown.
There is a very easy way to write code like this in a structure where it is easy to ask what the “parent” of something in a hierarchy is. It is related to (but simpler than) the “disjoint set forest” data structure, which I highly recommend reading about if it’s not already in your wheelhouse of programming tools. The idea is simple: iterate over all the entities that you want to display. For each one, check to see if you’ve processed it already. If you haven’t, walk its pointer up to the root of the hierarchy, processing each entity along the way. This ensures that you visit each entity only once, that you never visit any entity other than the filtered entities and their ancestors, and that you always visit all ancestors of the filtered entities: