a2dTopLeft, a2dTopRight, a2dBottomLeft, a2dBottomRight equivalent for base.pixel2d?

Yes, you are 99% right, but you have written more text on the forum than the code required for this task. :wink:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath

class MyApp(ShowBase):

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

        self.old_size = (0, 0)

        self.center = NodePath("center")
        self.center.reparent_to(pixel2d)

        self.p2dTopRight = NodePath("p2dTopRight")
        self.p2dTopRight.reparent_to(pixel2d)
        
        self.p2dTopLeft = NodePath("p2dTopLeft")
        self.p2dTopLeft.reparent_to(pixel2d)


        smiley = loader.load_model("smiley.egg")
        smiley.set_scale(20)
        smiley.reparent_to(self.p2dTopLeft)

        smiley = loader.load_model("smiley.egg")
        smiley.set_scale(20)
        smiley.reparent_to(self.p2dTopRight)

        smiley = loader.load_model("smiley.egg")
        smiley.set_scale(20)
        smiley.reparent_to(self.center)

        taskMgr.add(self.update, 'update')

    def update(self, task):
        size = (base.win.get_x_size(), base.win.get_y_size())
        if size != self.old_size:
            self.center.set_pos(int(base.win.get_x_size()/2), 0, -int(base.win.get_y_size()/2))
            self.p2dTopRight.set_pos(base.win.get_x_size(), 0, 0)
        self.old_size = size
        return task.cont

app = MyApp()
app.run()

But do not forget the panda is used on mini computers. And too much ShowBase functionality is unnecessary there. For example, I now use this method of creating an application.

I got a bonus that the window opens instantly, no need to wait until the ShowBase window is initialized. In some cases, the user was able to increase the rendering speed to the buffer by simply abandoning ShowBase. Although before that he tried to enable multithreaded rendering, but stumbled over bugs. So the question is moot, adding a bunch of functionality and tasks to the already large ShowBase.