Panda3D naming conventions and builtins don't seem very consistent

  1. It’s good that the API now tries to be more like other Python APIs and suggests and supports snake_case vs camelCase except for classes.
    But the method arguments still seem to require camelCase, and also some constants like AntialiasAttrib and TransparencyAttrib constants use CamelCase while other constants like DGG use uppercase. This causes 2% of the code to still be camelCase and not consistent, vs using camelCase for everything.

  2. it’s good that we are warned that run() is deprecated and we should use base.run() instead, however I don’t see the same treatment with render, render2d, aspect2d, pixel2d, loader, taskMgr, etc. Built-in Global Variables — Panda3D Manual

I don’t know, maybe you disagree and think using buitins like this is fine, but then why are “run()” and “camera” an exception, specifically? I see most code out there using base.cam and base.camera, not merely “camera”, so what makes run() and camera a special situation here?

Good questions. Some background:

The C++ codebase is all implemented in under_score (except type names), so already matching Python conventions. When Panda was first wrapped to a scripting language, it was a language that didn’t support underscores in identifiers. That is the origin of the camelCase convention. When this scripting language was changed to Python, the convention was kept, because PEP 8 didn’t really exist at the time.

The C++ codebase (ie. all modules under panda3d.* package) is wrapped using an automatic binding generator, so it is trivial to offer both snake_case and camelCase variants. The method arguments were already all in snake_case, so no problem there. The Python part of the Panda3D codebase (the direct.* tree) is more difficult to offer in both variants. This all requires manual work. We can duplicate method names easily, but we can’t do the same with method arguments so easily, not without wrapper methods that add additional overhead.

To be honest, the direct.* tree is a bit of a mess, for more reasons than just the coding conventions. Since it adds only a little bit of functionality over the C++ codebase, we have long thought about replacing it and instead implementing its important features in C++ instead, which would be available as snake_case. Then, the direct tree can be split off into a separate library on PyPI for people who need backward compatibility. This might be something that is done in a future Panda 2.0 or 3.0, at which time we can drop the camelCase variants as well.

The reason for all the builtins is that Walt Disney Imagineering uses the DIRECT library for live coding, and it’s convenient to have all the relevant variables handy in the interactive interpreter. But, we have started to move away from them since they are bothering people who are trying to maintain a clean coding style. Also, they make it difficult for automated code inspection tools to figure out what is what.

To respond to your specific points:

  1. TransparencyAttrib constants are also available in under_score case, ie. M_alpha, M_premultiplied_alpha, etc., because it is a C++ class. Note that this isn’t according to Python conventions, strictly, since Guido van Rossum recently decided that all constants ought to be UPPER_SNAKE_CASE. This might be addressed in a future version, but it’s not a pressing need.
  2. The simple reason why we don’t issue a deprecation warning for camera and render is because Python doesn’t technically allow us to do so, whereas we can for run(), which is a function. But we still prefer base.camera and base.render in example code.

In the meantime, if you identify parts of the Panda codebase that don’t presently support snake_case but could support it relatively easily, feel free to submit an issue report or pull request. It’s likely that we have simply overlooked it, or that there are some complications with that particular interface.

1 Like

I don’t see other Panda3D classes which currently don’t support snake_case.

But I think

  1. This info should be in the manual, and in the beginning, probably before the Hello World pages

  2. The manual codes should be updated to use snake_case, since right now all sample code starting from Hello World tutorial pages seem to use camelCase. Same with sample programs.

So right now, new users don’t seem to be clearly told camelCase is discouraged, and on the contrary, they see the official manual using camelCase, so they assume that is the convention this API uses. It’s not like there aren’t other APIs which use camelCase (like PyOpenCV). There doesn’t even seem to be clear that snake_case is also supported.

Also

  1. The API reference also uses camelCase, which also hints newcomers that camelCase is what is used. And again, they don’t seem to be told that snake_case is even supported as an alternative.
    I understand that the APi reference is automatically generated, but can’t the generator be configured to convert camel case to snake case? If not, then we go back to point 1, at least the manual should tell them that early on.

  2. The info on builtins shouldn’t be in the end of the API reference but also somewhere in the beginning of the manual.

The 1.11 manual (you can see the version selector on the left side) actually does use snake_case for the API reference and all references to function names. However, someone still needs to go through and convert all the sample code. This is the main reason why the manual hasn’t been updated already; because that work hasn’t been done yet, we didn’t want the manual to be inconsistent and confusing.

You’re right that there needs to be some note somewhere at the beginning of the manual.

I’m not sure that the builtins page needs to be in the beginning of the manual. It is a reference list and it’s not really useful to be taught a list of built-ins when first learning Panda3D, especially because most of them are discouraged or deprecated. Built-ins could however be mentioned where the relevant concept is introduced (eg. render where the scene graphs are introduced) and they should be clickable links to the builtins reference page, like how it works for all functions and classes.

Sure, the builtins page doesn’t need to be moved, in case simply be linked.

  1. But it needs to be mentioned early on. You have some sample programs which do not use “base.” to access the builtins, like fractal-plants, glow-filter, infinite-tunnel, looking-and-gripping, particles/steam_example.py , procedural-cube, render-to-texture, roaming-ralph and shadows . The person starting off with these samples, or supplementing the samples with the manual will get very confused where just “render” comes from. Some samples have base.render, some have self.render and some have just “render”. There are three ways to have access to it.

  2. Some sample programs have a single startup class in main.py either inheriting from ShowBase or creating an instance of ShowBase inside of their constructor and have everything in main.py inside that class, while some (like procedural-cube) just have an instance of ShowBase called base and have most of the functions and variables in main.py not be placed inside a “startup” class.

So first, which is preferred? Have your main class inherit from ShowBase, instantiate ShowBase in your class, or have no class at all in your main.py where you instantiate your main classes and start the game? If doesn’t matter, beginners should still known that all three options exist and they may encounter any of them in sample code or open source code.

  1. Another confusing bit is how some sample program main.py classes inherit from DirectObject and some inherit from the singleton class ShowBase or instantiate ShowBase inside their constructor. The distinction between the two (DirectObject and ShowBase) is not clear. Even more, some functionality can be achieved by both calling either a ShowBase instance method or the DirectObject inherited class method.
    Maybe I missed it but it doesn’t look like the manual goes into DirectObject and when to use it and how it relates to ShowBase.

However, someone still needs to go through and convert all the sample code. This is the main reason why the manual hasn’t been updated already; because that work hasn’t been done yet, we didn’t want the manual to be inconsistent and confusing.

I think you mean the manual hasn’t been converted to snake_case yet to stay consistent with sample programs. But at the same time, the latest manual version is inconsistent with the API reference for the same reason.

Thanks