Code cleanups: units map, more obvious subdirectories in engine, automatically checked dependencies, moved various units to internal

Dungeon map in Tiled rendered using Castle Game Engine

Lately I’ve done a number of rearrangements in CGE units, to make the engine code cleaner (easier to understand, both for new people and seasoned devs):

  1. Units map documentation is now up-to-date and more straightforward.

  2. Unit dependencies outlined in units map are (again) automatically checked by check_units_dependencies internal tool (using ppudump from FPC underneath).

  3. A lot of obscure/internal units have been renamed to CastleInternalXxx or marked as deprecated. We’re not finished with this cleanup yet, see more potential units that can become internal. But our list of units is already much shorter, making CGE API smaller so simpler to learn.

  4. Subdirectory src/3d is now src/transform. It contains TCastleTransform and friends, and is suitable for both 2D and 3D.

  5. Subdirectory src/x3d is now src/scene. It contains TCastleScene and friends (like TCastleViewport). I moved the 2 big units that define X3D fields and nodes to a subdirectory src/scene/x3d. The code loading particular model formats is now in src/scene/load, and some formats even get their own subdirectory, like src/scene/load/spine.

  6. I added subdirectory src/base_rendering, that contains some base OpenGL units (and will contain in the future alternative subdirectories for OpenGL, Vulkan etc.).

  7. We no longer use opengl subdirectories inside various other CGE directories. Things from base/opengl/, images/opengl/ mostly move to base_rendering. Things from scene/opengl/, ui/opengl/ mostly move to parent dir, i.e. just scene, ui.

    Why?

    The original idea for separating units that depend on OpenGL from things that don’t was that it would make it easier to recognize what needs to change when we add another renderer (like Vulkan).

    However, a lot of CGE units now depend on OpenGL only “very indirectly” and they have a clear API independent from OpenGL. For example, CastleControls unit depends on OpenGL, but actually both its interface and implementation are completely independent from OpenGL, and they will likely look the same when we have Vulkan available. They just use TDrawableImage and DrawPrimitive2D that make sense for any renderer.

    Similar notes go for e.g. CastleScene or CastleViewport. They depend on OpenGL now, but if (when?) we’ll jump to Vulkan, they will continue to exist with the same API, and even they’ll retain most of their implementation. We will just introduce then an abstraction layer, to make renderer “pluggable”, so that underneath TCastleScene, TCastleViewport, TCastleUserInterface will refer to the “current renderer” to do their drawing.

    All this meant that keeping these units in opengl/ subdirectory was not really very helpful. In fact, most of important CGE units were in opengl/ subdirectories, which was likely more confusing than helpful. E.g. ui/ looked like a mostly empty directory (mostly just joystick units) until you looked in ui/opengl/ that contained a lot of important classes.

  8. A few usages of is nested were cleaned — as it is not supported by Delphi. We previously tried to use “is nested” on FPC and anonymous methods on Delphi, but this resulted in a code complicated with ifdefs. It’s better to stick to a common subset of FPC and Delphi for now, which means — no “is nested”, no anonymous methods. (Of course you’re free to use them in your own projects, if you only care about using one of these compilers.)

P.S. I don’t really have any relevant screenshot to go with this post. So enjoy a screenshot with a sample Tiled dungeon map from here, rendered of course using our examples/tiled/map_viewer 🙂

1 Like