'aspect2d' is not defined

Hi! I was just wondering what library I need to import so I can run text nodes and/or where I can find the library for aspect2d. Thank you. Also I’m using Python. I’m just playing around with things, so this is all Panda code.

from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText
from direct.gui.OnscreenImage import OnscreenImage
from pandac.PandaModules import TextNode

class MyApp(ShowBase):
 
    def __init__(self):
        ShowBase.__init__(self)
 
        # Load the environment model.
        self.environ = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)
        imageObject = OnscreenImage(image = 'Book.png', pos = (0.3, 0, 0.04))
        #x= Left/right
        #y=
        #z=up/down
		

		
text = TextNode('node name')
text.setText("Every day in every way I'm getting better and better.")
textNodePath = aspect2d.attachNewNode(text)
textNodePath.setScale(0.07)
        
 

app = MyApp()
app.run()

aspect2d is an attribute of the ShowBase class. So you’ve already imported it, but you’re referencing it outside of your class definition, which is why you’re getting a NameError.

Here’s a working version of your example:

from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText
from direct.gui.OnscreenImage import OnscreenImage
from pandac.PandaModules import TextNode

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self) 
        # The above line initializes the ShowBase class, which gives you access to 
        # its attributes. 
        # You can also do this in a global scope with a statement like this: 
        # base = ShowBase()

        # Load the environment model.
        self.environ = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)
        imageObject = OnscreenImage(image='Book.png', pos=(0.3, 0, 0.04))
        #x= Left/right
        #y=
        #z=up/down

        text = TextNode('node name')
        text.setText("Every day in every way I'm getting better and better.")
        textNodePath = aspect2d.attachNewNode(text)
        textNodePath.setScale(0.07)

app = MyApp()
app.run()

Oh I get it! It needs to be within the indentations of the previous code. Thank you so much :slight_smile:

I may be mistaken, but I think that it’s more a matter of order of operations:

In the original version, the TextNode was being created outside of the class, and–importantly–above the point at which the class is first instantiated. This means that the code for TextNode was being run before the code in the class (since the class constructor should only be run when the class is instantiated), and thus before ShowBase was initialised.

In the second version, the code that creates the TextNode was moved into the class; as a result, it also only ran when the class was initialised, and because it was placed below the initialisation of ShowBase in the same method, happened after that. Thus ShowBase has been initialised by the time that the TextNode was created.

A quick note about indentation, in case you’re unfamiliar with this point: Python uses indentation to determine scope, as C++ uses curly brackets. If a piece of code is less-indented than the piece just above it, then it falls into the scope outside of that piece. For example, the following is all in one scope (barring the “if” statement):

    if isACat:
        print "mew"
        print "It's a cat!"
        print "paws!"

In this version, the last line is not in the same scope as the line above it, but is rather in the scope of the “if” statement, and so will be run regardless of the value of “isACat”:

    if isACat:
        print "mew"
        print "It's a cat!"
    print "paws!"

Finally, this version will, I believe, produce an error, as the middle line ends the scope of the “if” statement, and no new scope is defined for the final, indented line:

    if isACat:
        print "mew"
    print "It's a cat!"
        print "paws!"

Well, yes, it’s certainly true that the issue is with when ShowBase is initialized – not necessarily how.

That said, I think it would be odd to create a class just to initialize ShowBase in a global scope, which is why I placed the TextNode inside the class. Creating some kind of method (i.e. display_text) would probably make the most sense.

True, I do believe–but given Spark’s response to your answer, which could indicate a misunderstanding of both the source of the problem and the purpose of indentation in Python, I wanted to clarify what had been going wrong, as I recall.