Deattach Meshes with Tag

Hello
i’m trying to set a tag to my meshes so when my player goes to the “boss room”
i can just deattach and remove all the nodes than are not needed
(the player either dies or goes to the next level)
so far i have two functions

def allclear():
list = render.findAllMatches(’**/+GeomNode’)
print(“clearing full:”)
print(list)

for node in list:
    node.detachNode()
    node.removeNode() 

for just nuke it all
and for the ones untaged (not boss room)

def clear():
list = render.findAllMatches(’**/+GeomNode’)

if not list:
    pass
else:
    print("cleaning:")
    for node in list:
        key = str(node.getKey())
        tag = node.getTag(key)
        print(f"clearing {node}")
        print("with tags = " + tag)
        if tag == "1":
            pass
        else:
            node.detachNode()
            node.removeNode()

for the loading i use a cicle from a file
################################## file.txt
[Objectes]
0 = data/objects/cube0.egg 8,73,0 1
1 = data/objects/01.egg 57,100,0 0
##################################file

inside the cycle

lod = LODNode(str(sum_ob) + ‘LOD node’)
tree = NodePath(lod)
tree.reparentTo(render)
object = loader.loadModel(data[0])
object.setPos(float(data[1].split(’,’)[0]), float(data[1].split(’,’)[1]), float(data[1].split(’,’)[2]))

key = str(object.getKey())
object.setTag(key, data[2])
print(f"loading {data[0]}")
print(f"with tag " + object.getTag(“1”) + "and key "+ str(object.getKey()))
object.reparentTo(tree)
#and other LOD stuff

but it seems than the tag is loss somehow

i get in the console

loading data/objects/cube0.egg
with tag 1 and key 1
loading data/objects/01.egg
with tag and key 2
clearing:
clearing render/0LOD node/01.egg/Suzanne
with tags =
clearing render/1LOD node/cube0.egg/Cube
with tags =

and removes everything
is there any other way to make something close?

I think that the problem is that you’re searching for GeomNodes–but that the node that you’re attaching the tag to isn’t in fact a GeomNode.

To explain, when you load a model, the result contains, I believe, usually not just a GeomNode. Instead, it’s usually a non-GeomNode (a ModelNode specifically, I think) that has one or more GeomNodes amongst its children.

And since it’s this non-GeomNode to which you’re attaching your tag, when you search for GeomNodes via “findAllMatches” you’re not finding the tag amongst the results.

What I might suggest instead is to have “findAllMatches” search for the tags themselves. This can be done by simply replacing “+GeomNode” in your search with “=”, where “” is the tag that you want to find–noting that said tag can be partial, or a pattern, potentially allowing you to sweep up multiple tags in a single search.

For example:

results = render.findAllMatches("**/=someTag")
# Find all nodes that have the tag "someTag"

Or:

results = render.findAllMatches("**/=some*")
# Find all nodes that have a tag that starts with "some"

See this manual page for more (if you haven’t done so already).

Another approach might be to keep your NodePaths in a custom class that you create and store instances of, as called for. Since you thus have direct access to these instances, you can then clean them up relatively easily.

However, this may be overkill if you’re simply removing some models.

1 Like

thank you very much
i’m trying to use your tag method
like so:

def clear():
list = render.findAllMatches(’**/=1’)
if not list:
pass
else:
print(“clearing:”)
for node in list:
print(f"node {node}")
node.detachNode()
node.removeNode()

it successfully removes the principal mesh
but the other LOD meshes stay
(i guess this is good enough for my purpose and later i will do a nuke clean)
is there a way to tag the hole LODnode?

Well, what you have there only searches for nodes with a tag named “1”, and clears those–other nodes will be missed.

Hmm… I see three options here, offhand:

First, you could establish an additional tag that all such objects have, and then search for that instead.

Second, you could keep a record of all tags that have been used, and then search for all of them, rather than just for the tag “1”.

And third, you could rework you tagging system such that all objects have the same tag-key, with the current tag-key becoming part of the data stored in the tag. (Although in this case “Python-tags”–which can store non-string data–might be more useful.)

(Also, it seems that I was mistaken about using wildcard characters in searching for tag-keys: it seems that they work for node-names and for tag-values, but not for tag-keys (or node-types). My apologies for that error on my part!)

You should be able to tag it just as you can tag any other node, yes.

Note, by the way, that you likely don’t need to call both “detachNode” and “removeNode”, I believe. Specifically, my understanding is that “removeNode” will do pretty much the same as “detachNode”, but then also cause the NodePath to no longer reference the internal node.

See this post for more.

1 Like

yes!! thank you

now i have the tag referencing two things
models to deattach completelly
(for small things like cups and trees)
nodesloop
lod = LODNode(str(i) + ‘_LOD_node’)
tree = NodePath(lod)
keytree = str(tree.getKey())
tree.setTag(keytree,“1”)
tree.reparentTo(render)

and models to deattach the first lod (buildings when the player is far away and can’t reach them)

        object = loader.loadModel('data/objects/cube0.egg')
        object.setPos(8,73,0)
        object.setScale(1.5)
        object.setHpr(260,0,0)
        # set the object to render test with LOD,  and set tag for the renderer
        lod.addSwitch(50, 0.0)
        key = str(object.getKey())
        object.setTag(key, "2")
        object.reparentTo(tree)

(for some reason they workr only once, but i will solve that later by myself)

1 Like

this is my final code if someone is interested

def shortlodclear():
#clears first LOD mesh
    for node in render.findAllMatches('**/=1=2'):
        node.detachNode()
        node.removeNode()

def allclear():
    # clears all but camera
    listCh = render.getChildren()
    print("children")
    print(listCh)
    if not list:
        print("full no_list")
    else:
        for node in listCh:
           if str(node) != "render/camera" :
                print("removing " + str(node))
                node.removeNode()


def clear():
#clears nodes with tag 1
    list = render.findAllMatches('**/=1=1')
    if not list:
        print("no list")
    else:
        print("clearing:")
        for node in list:
            print(f"node {node}")
            node.removeNode()


# load
#loadloop
            lod = LODNode(str(i) + 'LOD_node')
            tree = NodePath(lod)
            tree.setTag("1", "1")
            tree.reparentTo(render)
            object = loader.loadModel('data/objects/cube0.egg')
            object.setTag("1", "2")
            lod.addSwitch(50, 0.0)
#rest of LOD stuff
1 Like

Thank you for posting that–it may help others in the future. :slight_smile:

It might be clearer if placed within code-tags, however–without them the indentation is lost, which I fear makes it harder to read (and prevents it from being executed as-is).

[edit] Ah, I see that you’ve done so–thank you for that! :slight_smile:

1 Like

yeah i’m still new here so idk the special tags

That’s fair! For what it’s worth, a selection of those tags is available via the menu-bar that is shown above the text-entry that the forum presents for the purpose of writing or editing posts.

1 Like

Note that findAllMatches returns a NodePathCollection, which defines useful operations you can apply to the entire set:

render.findAllMatches("**/=1=2").detach()

To exclude certain nodes from this, you can use removePath(...) on the returned NodePathCollection before calling detach().

1 Like