Is the NodePath overloaded with functions?

Thinking about how to implement my own GUI, I came to the conclusion that it is necessary to write classes that should have a hierarchical structure. However, the question arose how to add them to the graph for rendering… of course, you need to connect to NodePath for this.

However, this is not logical, since NodePath itself implements a hierarchical structure. It also has a massive set of functions that are atypical for a scene graph tree For example, setting up collisions and so on…

The question arose how to have a simple NodePath just to add an object, say GeomNode, to the rendering tree for visualization.

I wonder whether it might not be better to instead inherit from PandaNode (or GeomNode), and then just use baseline NodePaths when they’re called for?

Otherwise, what I usually do for my in-game (non-GUI) object-classes is to have them contain their relevant NodePaths, rather than inheriting. Adding to the scene-graph is then done pretty much as with any other node.

This is an option, but what to do with a huge number of methods that are not needed.

There are so many of them that you can change the properties of anything.
https://www.panda3d.org/reference/cxx/classNodePath.html

I mean, you can just… not use them if they’re not relevant to you, surely?

This… doesn’t actually seem like a bad thing, to me. ^^;

In general, I’d much rather have the ability to do lots of things and not require it than lack the ability to do something and want it, I feel.

result = self.ralph.get_top().find_all_matches("**/-Camera")

if result:
    for cam in result:
        class_cam = cam.node()
        if len(class_cam.display_regions) > 0:
            display_regions = class_cam.display_regions
            for display_region in display_regions:
                window = display_region.get_window()
                window.engine.remove_all_windows()

If you insert this code in the ralph example at the end of the initialization function, you will get an interesting relationship. Or rather, the absence of it. You can also insert this into any part of your application by simply changing the search node.

True, but why waste RAM on a table of unnecessary functions ever?

Testing it on my side it… just finds all cameras below the scene-root, and removes the windows associated with them. That doesn’t seem like unexpected behaviour…

Unless you mean that it’s unexpected that this can be done from the “Ralph” node? That’s just a consequence of Panda’s scene-graph design, and the fact that cameras are nodes in the scene, I would say.

True in turn–but is the wastage significant? I’m willing to give up a little bit of RAM–which is in abundance these days–for the sake of convenience, I feel.

If you noticed I got access to the entire structure of the engine, you can even configure the graphics library.

At the moment, the design of NodePath as a whole does not correspond to the scene graph functions in general. For example, the functions of the graph should be to reparent(attach), hide, set camera masks, and so on. I think the rest of the functions should be based on the type of object that was added to the NodePath as data.

I’m not sure that we should neglect the resources of iron, because Panda3D is positioned as a multiplatform engine. For example, someone wants to release a product on Raspberry Pi or on Android where the hardware is not so powerful. And in general, there is no need to clutter up the RAM.

It might be a good option to make a copy of Node Path and remove unnecessary functions.

NodePath is a handle to a node. It allows manipulating the properties of a node that can be set relative to other nodes. This includes all the properties contained within a RenderState and a TransformState.

It makes sense to have these setters even for node types that don’t contain renderable geometry, because you can set these properties on a node and have them affect child nodes.

Methods in a class don’t consume an appreciable amount of RAM. An object does not consume more RAM if its class has more members.

1 Like

Well, I’m not worried now, but it’s still too cumbersome and confusing to use in its own hierarchical structure. I would like to have unique methods for a certain type of graphic element. For example, a toggle switch can have a status in the form of digits [0, 1, 2, 3] and a button simply has the status True or False.

Another problem that DirectGIU also faces is different methods for the same goal.

from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        text_object = OnscreenText(text='my text string', pos=(-0.5, 0.02), scale=0.07)

        # 1
        text_object["fg"] = (0, 1, 0, 1)
        # 2
        text_object.setFg((0, 1, 0, 1))
        # 3
        text_object.node().set_text_color((0, 1, 0, 1))
        # 4 It is supposed to, but it does not work. But it works for mesh.
        text_object.set_color((0, 1, 0, 1))
        # Perhaps there are more options, but fortunately I don't know or I hurried to forget
        # ...

app = MyApp()
app.run()

I would like to get away from this. I think the set of methods should vary from the type of class. The first thing that comes to mind is to create a utilitarian NodePath for these purposes, which will contain only methods for interacting with the tree graph, and the rest should be implemented in the interior of the class for the use of the user.

Here’s a funny example

from direct.showbase.ShowBase import ShowBase
from panda3d.core import DynamicTextFont, TextNode, NodePath

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        font = DynamicTextFont('ds-crystal.ttf')
        # You can do this
        font.set_fg((0, 1, 0, 1))

        info = TextNode('Test')
        # Or is it
        info.set_text_color((0, 1, 0, 1))
        info.set_font(font)
        info.set_text('Test')

        node_path = NodePath(info)
        node_path.set_scale(0.1)
        # And you can do it like this, In this case it works.
        node_path.set_color((0, 1, 0, 1))
        node_path.reparent_to(aspect2d)

app = MyApp()
app.run()

In fact, it is almost never necessary it is necessary to change the rendering attributes of child elements. This is generally applicable to transformation.

This I rather disagree with: I’ve found it rather useful at times to have the ability to have a node affect or even override rendering aspects of nodes below it, as I recall.

I think that this is perhaps an “each to their own” sort of thing: I don’t think that your position is incorrect, but nor do I think that it’s true for all people.

Honestly, I quite like that I can control as much as I can from NodePath.