Roadmap

Table of Contents

1. Introduction

Don’t see the feature you need? Tell us on the forum or Discord.

If you would like to see some feature implemented sooner, please support the engine development on Patreon!

2. Planned before 7.0 release

2.1. (IN PROGRESS) New navigation components that support physics out-of-the-box

In progress: We have completely new navigation components in https://github.com/castle-engine/castle-engine/pull/533 . They achieve a few things:

  • more universal (suitable for 1st person 3D, 3rd person 3D, 2D cases),

  • more configurable inputs, also from editor (expose new "axis" paradigm),

  • more flexible (functionality split into a few components, easier to pick a subset of functionality you want, easier to write extensions), and honor the physics engine.

Once above is merged, eventually TCastleWalkNavigation will be deprecated. Don’t worry, the deprecated TCastleWalkNavigation will still be available for quite a while — we’re aware that many projects use it, since (as of today, before we merge PR 533) we actually advise using TCastleWalkNavigation, as it’s very easy to use and flexible enough for many situations.

2.2. (IN PROGRESS) Remove the need to care about PreciseCollisions, cleanup old collision detection using our octrees

We want 100% of collision detection (which also means ray-casting) at runtime to be done using physics, and thus determined by the presence of components like TCastleMeshCollider.

We’re almost there…​ except there are exceptions, see Old system for collisions and gravity. This means TCastleSceneCore.PreciseCollisions matters. We want to get rid of it, at least for run-time. The old collision detection using our octrees may remain:

  • Useful at design-time, in editor.

  • For frustum culling done by TCastleScene. This is invisible to the user.

To do this:

  • Deprecate TCastleXxxNavigation using older collisions. See above — we have components to replace them.

  • New Viewport.PointingDeviceHit instead of Viewport.MouseRayHit, Viewport.TransformUnderMouse, that exposes physics ray-casting by default.

This is started, things done:

2.3. (IN PROGRESS - ALMOST DONE) Steam integration, and engine available as Steam app

Integration with Steam done and rocks, https://castle-engine.io/steam .

TODO: Put engine on Steam as an app. We already have registered the application with Steam, and we have the app ID. We need to add achievements to CGE editor and submit it to Steam.

2.4. (IN PROGRESS - ALMOST DONE) Implement TCastleMoveAttack behavior, use for enemies in examples/fps_game and examples/creatures_behaviors

In progress.

  • Initial TCastleMoveAttack done, used in

  • Has simple logic of movement, getting close to player (or any other enemy), short-range attack.

  • We also have simple enemy logic implemented in "3D FPS Game" template and to show our behaviors.

TODO:

  • Use physics for all movement and gravity

  • Finish firing missiles, TCastleMissile finish

  • Eliminate all TODO in src/scene/castlelivingbehaviors_moveattack.inc and friends

  • Restore + modernize our "waypoints / sectors" (known as "navmesh" in other engines), make it possible to set up in editor

  • Change section title from "Living (Early Preview - Functionality Will Change!)""Living"

  • Phase 2: Use behavior trees

Note

Old approach to this was offered by the CreatureCreatures / CastleResources / CastleLevels / CastleItems / CastlePlayer units. They should be replaced with a better API. These 5 units expose a high-level API, that sits on top of the existing classes (like TCastleScene and TCastleTransform). But we are not 100% happy with their API. Reasons:

  • The API is too specialized at some points (3D games with creatures / items pickable),

  • It is confusing how it maps to API underneath (e.g. TPlayer somewhat controls the TCastleNavigation).

We want to express their features in different ways, in ways that are more closely and obviously connected with TCastleScene / TCastleViewport / TCastleNavigation. Basically, we’re very happy with current API of TCastleScene and TCastleTransform, and we want to make it more obvious how it is related to creatures/placeholders and other concepts in the engine. The existing CreatureCreatures / CastleResources / CastleLevels / CastleItems / CastlePlayer also use TCastleScene and TCastleTransform inside, but the relationship is non-obvious.

2.5. Component list class, to easily expose serialized list of components in editor (prerequisite of "New material components" item)

We want to have a component list class, that

  • Maps to a subtree in the "Hierarchy" in CGE editor,

  • Can be used to express current (this will make some code in editor and CastleInternalInspector simpler):

  • Can be used to express future things:

  • Is generic, so we can be safe at compile-time about what is allowed to be inserted. That’s why we don’t want to just use standard TComponentList.

  • Would allow CGE editor to easily hide some lists, while not hiding others. E.g. whether to expand TCastleBehavior in the hierarchy — can be just UI choice.

    Conceptually, when Unity has hierarchy (of GameObject) on left and list of components (components in Unity sense, i.e. pieces of GameObject) on right, we instead have a tree of components (components in Pascal and CGE sense, i.e. TComponent). It is just editor UI decision — which levels are shown in the tree (hierarchy), which are not (e.g. behaviors could be hidden, or shown in some different way, in editor — and it shall be unrelated to the Pascal classes organization).

Idea:

TCastleBaseComponentList = class(TComponent)

  • Internally uses TComponentList for storage because we want items to auto-disappear when they are freed wherever.

  • Do not inherit from TComponentList, to not expose everything, limit access to our methods/properties. So only use it as a private field.

  • Non-generic, editor can use it as a base class for all nested lists.

  • Editor operations like move up/down, remove, add, should use this class.

TCastleComponent.GetComponentLists method: Query all TCastleBaseComponentList. Maybe it should just use RTTI to query all TCastleComponentList<T> on given object, from them extract TCastleBaseComponentList and return them. This is crucial for editor to show hierarchy. One of the lists should be "default" to show it without intermediate item in hierarchy (e.g. TCastleTransform children are Children: TCastleComponentList<TCastleTransform> but we don’t display Children intermediate item in hierarchy).

TCastleComponentList<T> = class(TComponent)

  • Generic, safe to use from code.

  • internally uses InternalBaseList: TCastleBaseComponentList to store items, as private filed. (Do not inherit, to not expose everything non-generic.)

Another phrasing of this (equivalent, mostly):

Unify the processing of both visual children of TCastleTransform, and visual children of TCastleUserInterface, and NonVisualComponents — by new TCastleComponentList<T>. This will be backward compatible, and will guarantee that all these iterations really use the same mechanism (right now these iterations are ~consistent just because they have been manually made to look similar each time).

So we’ll have

TCastleComponent = class(TComponent)
  NonVisualComponents: TCastleComponentList<TCastleComponent>;
end;

TCastleUserInterface = class(TCastleComponent)
  Children: TCastleComponentList<TCastleUserInterface>;
end;

TCastleTransform =  = class(TCastleComponent)
  Children: TCastleComponentList<TCastleTransform>;
  Behaviors: TCastleComponentList<TCastleBehavior>;
end;

and iterating with for …​ in …​ will be always equivalent to iterating over Children.

So

for C in MyTransform do

will be equivalent to

for C in MyTransform.Children do

Same

for C in MyUserInterface do

will be equivalent to

for C in MyUserInterface.Children do

And you can also do

for C in MyTransform.Behaviors do…​

for C in MyTransform.NonVisualComponents do…​

Right now…​ it’s already mostly like that, but due to the fact that I declared a few things manually in the same way. The new TCastleComponentList<T> should force it to be consistent, and also make some code easier for editor.

2.6. New material components (allowing also material editing in the editor)

We want to allow you to edit materials in the CGE editor,

  • e.g. to modify (or completely override) materials from TCastleScene (like glTF),

  • to have full control over primitives (like TCastleSphere or TCastleImageTransform look),

  • to enable you to use cool CGE features like mirrors, shader effects easier.

This also means exposing new set of Pascal components to manage materials easier.

2.7. (IN PROGRESS) Make shadow maps available by a trivial property on light sources

Activating shadow maps has some disadvantages now:

  • You need to setup special X3D nodes and fields. At least put shadows TRUE on some light source in X3D, most likely you also want to specify defaultShadowMap on this light source.

  • The X3D field name is inconsistent. In X3D light nodes, shadows activates shadow maps, while shadowVolumesMain activates shadow volumes. This is inconsistent with TCastlePunctualLight.Shadows, which activates shadow volumes. As part of this work, we should make TCastlePunctualLight API and X3D nodes more consistent (we can, as shadow map stuff is our extension over X3D).

    We should also account for X3D 4.0 shadows additions and report to the X3D working group our experience, ev. suggestions for X3D improvements.

  • The lights cast shadow maps only within the same scene. (Work is under way to remove this limitation, this refactor is the important step and it is already pushed to the master branch.)

This is in contrast to shadow volumes that are trivial to activate (you literally toggle one checkbox, Shadows, on our light components TCastleXxxLight) and work across scenes, thus are very natural to set up using CGE editor.

We want to upgrade our shadow maps support to address above issues:

  • TCastlePunctualLight should just have a property ShadowsMethod (enum smVolumes, smMaps) that will allow to easily switch between shadow volumes and shadow maps.

    Note
    Alternative, rejected, API idea was to turn Shadows into an enum with a possible "none" value, like Shadows: (None, Volumes, Maps). Separate Boolean to choose whether shadows are enabled at all, separate from choosing shadows algorithm, seems more natural. It is, conceptually, a different decision "do I want shadows" vs "what shadows algorithm do I want". It also means we (at the engine) have to choose one default shadow algorithm, instead of leaving the decision on users --- which is actually better for users.
  • More API:

    • Shadows distance?

      Instead of current projectionFar, which has auto-calculation but it can reach too far.

      What is Unity default, just hard code instead ot detecting?

    • Shadows distance falloff? Smooth transition to no shadows at all.

      This matches the existing logic in shadow( in GLSL that says "where the shadow map doesn’t reach, assume no shadow". So we just introduce a smooth falloff to this.

    • Take a look at what Godot, Unity, Ogre3d (last one has both shadow maps and volumes) expose in API, and what are their defaults.

3. Most important planned immediately after 7.0 release

3.1. (IN PROGRESS) Web platform (rendering using WebGL) support

Using FPC support for the WebAssembly:

Some "glue" may also be done using pas2js. This is a nice solution to expose to our WebAssembly code the JS API we need, like WebGL. Alternatively, we could just do it in plain JS.

This is already in-progress by Trung Le (Kagamma), Andrzej Kilijański and Michalis.

I wrote a longer post about plans and status of this here: https://castle-engine.io/wp/2023/04/08/web-target-progress-and-plans/ .

4. Important, big, impactful features (but we first focus on stuff above)

4.1. VR and AR

VR: Michalis has access to Oculus Quest since the beginning of 2022. Port most likely using OpenXR (to include the widest possible range of devices using a single cross-platform API).

Oculus Quest 2: Developer Mode for Castle Game Engine enabled!

AR: most likely using Android / iOS built-in frameworks, as these make AR widely available on modern phones.

4.2. More Delphi platforms

See about existing Delphi compatibility - we support Windows and Linux now. We plan to support more platforms with Delphi: Android, iOS…​

4.3. Load and animate glTF more efficiently

  1. We should read meshes in a way that keeps binary layout of data in glTF, so that it is ultra-fast to load, and it is loaded almost straight from glTF to GPU.

    Some modifications to CGE may be required here (CastleGeometryArrays will have to be made more flexible for this). New X3D nodes should be introduced, like BufferGeometry (same as X3DOM?).

  2. We should also perform skinning fully on GPU, avoiding CoordinateInterpolator done on CPU. We may introduce new X3D node for this like SkinnedAnimation (using H-Anim is also possible, but not that straightforward).

4.4. Support new glTF material extensions

See:

Thanks to Holger Seelig and X_ITE project, the path how to express this functionality in X3D is already known and tested:

4.5. More physics

  • Older physics based on octrees should be phased out.

    In progress: We’re slowly already doing it. If you want to get ahead, you can already use physical colliders (see physics manual) and use queries like PhysicsRayCast instead of WorldRay.

  • TCastleSceneCore.ExposeTransforms should work both ways, to allow to attach bodies and colliders to parts of the scene. This will enable e.g. ragdolls.

  • More physics backends, not only Kraft.

    We’re looking to add another physics engine that relies on some big, well-known and open-source engine. Our current considerations are either PhysX or Bullet.

    As as result of this, more physics engines can also be added more easily in the future.

  • See more in manual about physics, subsection "TODO".

4.6. (IN PROGRESS) Particle systems

With a designer. Example usage: blood, snow, rain, fire, smoke…​ 2D, 3D.

This is already in-progress by Trung Le (Kagamma). Use cge-3d-particle-emitter or Effekseer Integration. See CGE components.

4.7. Terrain features (in particular, editing terrain in CGE editor)

What we have now: The engine includes TCastleTerrain component and examples/terrain that shows how to generate terrains in various ways (from smoothed random noise, from a ready image) and render it. We also have the "Wyrd Forest" game that also uses CastleTerrain, and also includes a simple editor of terrain settings. See also news about terrains.

What we need: Visual, interactive editor for terrains, matching e.g. Unity feature set.

Enable editing heightmaps easily:

  • Edit the terrain heights within CGE editor, using something like a brush to lower/raise clicked points. To make hills, valleys in a comfortable way.

    The edited heights just land in TCastleTerrainImage with internal contents.

  • Use splatmap and enable editing it, to edit the terrain textures mixture within CGE editor. To effectively paint the terrain with different textures like grass, dirt, rock, snow.

    The splatmap is an internal (not directly visible) RGBA texture that determines the weights of the visible textures. E.g. imagine you have 4 visible texture types: grass, dirt, rock, snow. Then

    • splatmap red channel determines "how much to add grass at this point",

    • splatmap green channel determines "how much to add dirt at this point",

    • splatmap blue channel determines "how much to add rock at this point",

    • splatmap alpha channel determines "how much to add snow at this point".

    The editing code can watch over to make sure the weights are normalized, i.e. always sum to 1.0.

  • The existing terrain implementation, in TCastleTerrain and examples/terrain is a starting point — shows how we can randomize / generate a reasonable terrain with texture weights. But above additions are critical to make it really useful: in practice, for real games, people want to have control over the terrains. So the existing generation will remain part of the workflow, but only as an optional starting point.

    Note
    The fact that you can connect a few terrains together, and our generation can generate "neighbors" effectively, is super-useful and will be preserved.
  • Tools to plant big things (3D TCastleScene) in the terrain, like trees, rocks. You can do it now, though it’s manual: Use behavior TCastleStickToSurface and put multiple instances of the thing you want. Use TCastleTransformReference to make it optimal for memory when you can, so that multiple instances share the same resources.

    Optional LODs could be nice (but maybe this is outside of scope of terrains; LODs should be just on TCastleScene. Currently we have LODs on TCastleScene using TLODNode - works nice, though complicated to set up, we want to move away from exposing X3D nodes for this.)

  • Tools to plant many small things, like grass. This is a big different than "big things", and here automatic LODs that e.g. decrease density of grass with distance make sense.

  • More specialized and efficient rendering algorithm. Right now terrain in the end is just a simple big mesh of triangles. It’s actually quite fast to render (because modern GPUs can handle big shapes) but it’s not a sustainable way to render huge terrains.

  • Improve shaders for terrain to show it, like this BareGame example.

  • More than 4 layers. Each new set of 4 layers mean a new splatmap.

4.8. Vulkan renderer

Add a Vulkan renderer.

  • API:

    Almost all public CGE API will remain unchanged. For a long time now, we design our API to be independent from OpenGL, and all rendering (e.g. done by TCastleScene, TCastleViewport, TCastleUserInterface, TDrawableImage) is driven by a renderer-neutral API.

    Shaders will continue to be available using GLSL. There will be possibility to precompile them to SPIR-V before usage (for both Vulkan and new OpenGL, as new OpenGL also supports SPIR-V).

    Underneath, we will create a "pluggable" architecture for renderers. In theory we could implement a lot of renderers (e.g. also Metal or Direct3D) but given the limited resources, realistically we will focus on 2 renderers: Vulkan and OpenGL ("OpenGL" here meaning really a family OpenGL + OpenGLES + WebGL).

  • Approach:

    We have a simple example code that shows how you can start a new renderer: see new_renderer_skeleton example. This is great for testing initial implementation, before we have a "pluggable" architecture.

  • Header:

    I was playing with PasVulkan from which we could use a Vulkan API header. See news about PasVulkan.

    We could also get Vulkan header from GLAD 2 if only we port it to Pascal (we plan this already).

  • Platforms:

    Not all platforms support Vulkan, in particular it’s uncertain whether Apple with ever support it (they want to push Apple-specific Metal API). CGE will most likely use MoltenVK to render using Vulkan on Apple, see plans regarding macOS / iOS and OpenGL, Vulkan.

4.9. BGFX renderer

Look great:

  • open-source,

  • packed with features,

  • actively developed,

  • open for bindings from any language, any game engine (it is explicitly made as renderer useful for various game engines),

  • properly documented,

  • very good platform and renderer support.

This may be even better than direct Vulkan port. We shall see. On one hand, this provides more possibilities than just Vulkan (e.g. direct Metal renderer). And it may be easier to use than Vulkan. OTOH, it will not allow to squeeze "every last bit of performance from Vulkan" (though we really don’t need that in CGE in the first place; there are lots of optimizations on the table in CGE before it’s worth even thinking about low-level Vulkan optimizations).

4.10. Mobile: Wireframe on OpenGLES

Since glPolygonMode is not available at all on OpenGLES, we need to be able to generate wireframe geometry arrays on CPU, adding a "wireframe" option to CastleArraysGenerator that will generate a different (line) primitive for TGeometryArrays. Then the renderer can use such TGeometryArrays for OpenGLES.

This is started now, by having Shape.shading = "WIREFRAME" option, see Shape.shading field. We need to

  • make it available for all geometry shapes

  • make this feature more flexible, so that the renderer can switch between wireframe/non-wireframe rendering without any cost.

  • And then we can implement Attribute.WireframeEffect on OpenGLES correctly,

  • and allow to set Wireframe on specific viewports (so that some viewports may view wireframe, independent of others) on OpenGLES.

4.11. Mobile: On-screen keyboard on iOS (already done on Android)

4.12. Mobile: TGLImage.GetContents on OpenGLES

TGLImage.GetContents is not available on OpenGLES, as it doesn’t support glGetTexImage. Fixing it is a matter of implementing alternative way that draws texture to FBO and grabs using SaveScreenGL (using glReadPixels internally).

One has to use TGLRenderToTexture to render quad with a texture (making sure the framebuffer size, quad size, and texture size match, and without filtering) and then use glReadPixels to get the pixels from FBO. This will work on mobile (and also on desktops, although it will be less optimal alternative to glGetTexImage).

4.13. macOS: Package engine as one big application bundle

This will:

  • be simpler to users, as the engine will be "one single application" for macOS users.

  • avoid troubles resulting from Apple translocation. It right now prevents the CGE editor from detecting CGE path.

  • avoid current duplication of castle-editor/data in distributed package, thus making it smaller by ~60 MB.

See macOS.

4.14. macOS: Have signed app bundle for the editor

This will allow to run CGE editor on macOS by just double-clicking it, out-of-the-box.

See macOS.

We should also enable developers to easily sign their own applications packaged with CGE build tool.

4.15. Bridge TDrawableImage with TCastleScene, enable drawing UI into TCastleScene, to have UI rotated in 3D with perspective.

4.16. MDL and/or MaterialX integration

We can make 3D modeling of realistically-looking stuff much easier by reusing libraries of realistic materials.

4.17. USD – Universal Scene Description support

Explore possibility to support USD – Universal Scene Description format as a first-class citizen, alongside glTF and X3D, in CGE.

4.18. Integration with Nakama (scalable server for social and real-time games and apps)

Integration with Nakama:

Nakama is an open-source server and client library/API that provide networking capabilities typically needed in games.

  • The server is written in Go (see source code) and can be extended using Lua, JS, or Go modules. See server framework.

  • It supports out-of-the-box stuff like user accounts, matchmaking (connect people into rooms where the game happens), leaderboards, chat, etc. There’s infrastructure to synchronize data between players in a multi-player game.

  • Client library can be used from various game engines and languages so we’re confident it can be used from CGE too.

  • You can host the server yourself or pay to get ready hosting.

  • As you can see in above links, it seems really well documented, and actively maintained. These are naturally critical qualities for our dependencies.

I think Nakama may give CGE networking capabilities comparable with some popular solutions known from other game engines :)

Allowing to trivially get multi-player functionality in your games.

4.20. Project settings editable using GUI

We will expose both current CastleEngineManifest.xml and data/CastleSettings.xml as something you can edit yourself with GUI.

But we don’t want to create and maintain a custom GUI for them, instead the plan is to:

  • Create Pascal components with published properties representing their data.

  • Make the project settings files just "JSON design files" for the editor.

So you’ll have a file like project.castle-project and using editor menu item like "Project Build Settings" will really just open a design project.castle-project (JSON) in the editor, and it will be just a serialized TCastleProject component. Same for "Project Runtime Settings" which edits data/settings.castle-project-settings.

Bonus: we’ll associate *.castle-project with the system, to open when you double-click it e.g. from Windows installer.

Bonus: you can add non-visual components to data/settings.castle-project-settings and load them using Container.DesignedComponent('xxx'). This is great e.g. to add sounds or fonts or other data that you want to later load in CGE, from any view.

There are a few details that have to be ironed out here:

  • how should the new equivalent of CastleEngineManifest.xml and data/CastleSettings.xml interact. We will likely keep 2 files, project.castle-project and data/settings.castle-project-settings, as

    • Some information doesn’t need to be packed into data, part of it could even be considered "somewhat secret" (e.g. SDK IDs for Android analytics should not be present anywhere in the non-Android builds).

    • Some information should be packed into data automatically, by default, everything. To enable that Bonus: you can add non-visual components feature.

  • most intuitive names for all the things above (menu item names, component names, extensions etc.) :)

Moreover:

  • Expose CastleDataIgnoreCase in data/settings.castle-project-settings. This makes sense to be read also by editor when editing the project, to ignore case also at design-time.

4.21. Creating animations in CGE editor, for UI and transforms

Allow designing and testing animations in CGE editor.

The features cover animating typical UI/transform things that you see in CGE editor directly: e.g. UI stuff (like TCastleUserInterface.Translation, TCastleImageControl.Color), 3D stuff (TCastleTransform.Translation, TCastleTransform.Rotation etc.).

Note
Animating everything in CGE is already possible right now using code. You can update any values you want in Update method of your view and change any value you need (like MyControl.Translation) using routines like Lerp or SmoothStep.

The point of this feature is to allow to design and see simple animations from editor. Code will then be able to just play them (e.g. using simple method MyAnimation.Play) whenever needed.

Features:

  • Make it possible to animate (at least!) any property of TCastleUserInterface and TCastleTransform. Access the property using RTTI, and at design-time in editor allow to choose TargetObject and TargetProperty with suitable type.

    Bonus: allow to animate any property of any TComponent.

  • It should allow to animate at least any Single/Double, TVector2/3/4 properties (this includes also colors, as TCastleColor[RGB] is just alias for TVector3/4; this includes also rotations, that is just TVector4 but can use slerp for interpolation).

    Bonus: allow to animate other property types. E.g. animating discrete (like boolean) actually makes sense — to hide stuff by animation, by changing Exists at specific point in time.

  • It should use TCastleBehaviorBase that will allow to attach it to any TCastleUserInterface and TCastleTransform. See talk about it in https://github.com/castle-engine/castle-engine/issues/473 .

  • Each such animation should define:

  • Bonus: Group animations, so that from code you can fire like MyUserInterfaceAppear.Play and it runs a number of animations at once — e.g. something "slides in" (translation changes), something appears (Exists changes), something fades in (Color.alpha changes)

See also:

4.22. Screen effects - expose as nicer components

Address a few shortcomings of our (see examples/screen_effects_demo/, screen effects):

  • Change terminology. "Screen effect" is non-standard, "post-processing effects" are better.

  • Expose as components some standard effects, like blur, changing colors in HSV, grayscale. They should have easy Pascal properties, serializable to JSON, and wrap the related X3D nodes underneath.

  • Expose as component a customizable shader effect allowing you to provide GLSL code in a text box (TStringList editor) in CGE editor.

  • This depends on making a more generic TCastleComponentList to expose TCastleScreenEffects.ScreenEffects list nicely.

4.23. Export (save) nodes graph to glTF

Currently we can export (save) nodes graph (from one TCastleScene or, using TCastleTransform.InternalBuildNode, from whole TCastleViewport contents) to X3D or STL.

We want to enable also saving to glTF. This means that everywhere where we allow saving, glTF will also be an output option:

4.24. Allow animating selected node graph properties, without changing the graph, to be able to reuse graphs

Right now our X3D graph usage is similar to HTML DOM usage from typical web applications: we modify the graph at runtime, everything that changes stuff (like animations) just changes the graph. This is simple to use, it nicely allows to animate everything in X3D and gives developers an easy way to modify everything at runtime.

The downside is that we waste significant memory, and loading time, in some cases. If you want to play different animations on each TCastleScene, then they need to have a different graph even though they are loaded from the same URL. Hence using e.g. TCastleScene.Clone or TCastleSceneCore.Cache really internally makes multiple copies of the graph. This could be more optimal in the future. E.g. assuming your model only uses glTF skinned animation or animates simple transformation position/rotation/scale, we could make the graph read-only, and only maintain small "diff" information at each instance.

4.25. FMOD Studio support

Right now our FMOD backend uses only "FMOD Core API".

We want to enable using higher-level FMOD events that drive the sound banks exported from "FMOD Studio".

4.26. Wwise backend

Allow using AudioKinetic’s Wwise as sound backend, and as a middleware to design sounds.

4.27. Asynchronous loading of assets

As described in threads, we want to allow loading assets asynchronously. This means that you use CGE API from one thread, but some operations are not "blocking" and CGE can internally use threads to finish their work, while your code continues to calculate, CGE events like Update continue to be processed etc.

For example:

TCastleScene.LoadAsync(const Url: String; const OnFinish: TNotifyEvent);

TCastleScene.PrepareResourcesAsynchronously;

TCastleTerrain.UpdateDataAsync(const NewData: TCastleTerrainData; const OnFinish: TNotifyEvent);

We already use such approach e.g. with TCastleDownload. Internally it can download in a thread, but you don’t need to worry about inherent "hard" issues with threads (synchronizing communication between threads, being careful who/when touches the shared variables). This approach results in:

  • Really comfortable API. You handle everything from one thread, you get simple callbacks when things are done, you can simply watch (e.g. in some Update) status of something, display progress bars, interrupt the operation etc.

  • Flexible implementation underneath. It can use Pascal threads underneath, or it can delegate work to another asynchronous API (e.g. to download using Java classes on Android), it can even fallback to synchronous if threads are not possible on some platform.

And it is possible to load OpenGL things in a thread: by having separate OpenGL context for the background thread, that shares resources (like VBO).

The ultimate demo is to implement exploring a huge city and loading neighboring pieces of the city asynchronously.

I mentioned this in the bottom part of Slides, movies and thoughts from my GIC 2022 presentation .

4.28. Merge TCastleImagePersistent and TDrawableImage

One less image class (we have too many image classes, see https://castle-engine.io/using_images ).

And it will avoid current counter-intuitive fact:

ImageControl.DrawableImage.CustomShader := Xxx;

The above is ignored, because ImageControl.CustomShader (equal to ImageControl.Content.CustomShader) overrides TDrawableImage.CustomShader. Similarly a few other drawable image properties, as TCastleImagePersistent.Draw does now:

{ All the DrawableImage properties must be set here,
  in case multiple TCastleImagePersistent refer to the same
  DrawableImage instance through the cache.
  Fortunately, almost all TDrawableImage properties have zero cost
  of change. }
DrawableImage.SmoothScaling := FSmoothScaling;
DrawableImage.Clip := FClip;
DrawableImage.ClipLine := FClipLine;
DrawableImage.Rotation := FRotation;
DrawableImage.RotationCenter := FRotationCenter;
DrawableImage.Alpha := FAlphaChannel;
DrawableImage.Color := FColor;
DrawableImage.CustomShader := FCustomShader;

4.29. (IN PROGRESS) Better gamepads (joysticks) API

Goal: Support modern gamepads (joysticks) with a nice API.

Note: We have support for gamepads (joysticks) already, see CastleJoysticks and examples/joysticks/ . But it is not easy to use — I’d like to improve the API, and improve it to handle various gamepad types in a more "seamless" fashion.

Features:

  • It should support at least the most popular controller, which X-box compatible controller, out-of-the-box.

    It seems we can easily support much more, using joysticks database: https://trello.com/c/483EsTNX/12-use-database-of-joysticks-to-better-understand-their-buttons-axis . But I make it explicit: the critical feature is support for the most common X-box compatible controller. Support for, potentially, every gamepad that exists in the world is secondary :)

  • Should support at least Windows, Linux, and Nintendo Switch. Switch support in this case is justified — because we already support Switch gamepads, but we’ll want to upgrade it to new API.

    Of course support for more platforms is desired. macOS, and maybe even mobile (it does seem one can connect gamepad to Android through at least Bluetooth, it actually works). But these are secondary. The platforms mentioned above are primary for this feature.

  • Should support multiple gamepads.

  • API should be nice. Current CastleJoysticks is complicated. This means:

    • TInputPressRelease structure, as send to TCastleUserInterface.Press (so in particular, TCastleView.Press) should have a type like GamePadButton (alternative to key on keyboard, or mouse button) that occurs when user presses / releases the button. It should say which gamepad was used to press it (to support multiple joysticks connected to system). And it should report a button.

      Buttons should have agnostic names, like North, East etc. Avoid using names like A B X Y that are in different places on different gamepad models (Xbox, PS, Nintendo…​). Maybe we can also have names like Accept, Cancel to follow conventions (e.g. on Xbox controller, A corresponds to "Accept" by convention, B corresponds to "Cancel").

    • TCastleInputAxis (that is also already in progress) should allow to observe chosen gamepad axis (based on gamepad index, and choice horizontal/vertical, also choice of gamepad axis — typical gamepads now have 2 axis). This is already a nice API to observe input that we want to have.

  • examples/joystick/ should look better. Show a sketch of a gamepad — and highlight the current axis used, button pressed.

4.30. Smart Tasks

Allow to define tasks that should occur regularly, but do not have to be done every frame. The engine should then automatically execute the tasks based on their need and current workload.

E.g. animation task may say "I want to update the model every frame, but actually I don’t have to — if under heavy workload it’s enough to only update 30 times per second or such". This would be a better (more general, smarter — activated automatically) way of optimizing it than current TCastleScene.AnimationSkipTicks.

Note

The API (terminology) and implementation have to play nicely with Delphi existing concept of "tasks" from Delphi Parallel Programming Library. Delphi already has a "task" meaning "a unit of work that can be executed in auto-created thread (using pool of threads underneath)", see

So:

  1. Our tasks, that are mainly to execute tasks in the main thread but with some delay ("execute this when convenient, I don’t need it done right now") should be clearly something different. To avoid confusing API for people that know Delphi tasks.

  2. When using threads, then we should use Delphi tasks (on Delphi), where possible. Only for FPC we’ll need to duplicate subset of it (unless FPC will get the compatible implementation).

4.31. KTX 2.0 support

A great format, by Khronos. Enables managing compressed textures much better. (than our existing solution: https://castle-engine.io/creating_data_auto_generated_textures.php )

4.32. Expose component name for Pascal code

Right now to access a component set up in the design, you have to manually add it to the published section of the design, adding a declaration like MyViewport: TCastleViewport.

The goal is to make it more automated. A bit like Lazarus or Delphi IDE when exposing components to code — but with some twist.

It would be easy to just expose all named components from the design in the published section of the view (this would be experience quite like when Delphi/Lazarus do) but, since typical game designs (we’ve seen it in Unity games in CAG) can contain thousands of components easily, and most of them are not supposed to be accessed from code, we want to go one step further:

  • Add a button "Expose To Code" (available on single component, or selection of components).

  • Once used, the component will be added to the published section of the view (name: type), and will be updated there (on rename/delete of this component, or change of it’s class).

  • This is also means we’ll edit the uses clause of unit to make sure all used component classes are registered, and declared, so that declarations in published section work. This is also something Delphi/Lazarus do. We know the unit of each component, so it should be easy.

It is possible we’ll add markers {$region 'Castle …​'} to help organize this. See the current markers in gameinitialize.pas.

4.33. Allow to override design properties when instantiated using TCastleDesign, TCastleTransformDesign

Allow to customize the hierarchy instantiated through TCastleDesign or TCastleTransformDesign.

In Unity, this is called "prefab overrides". In Delphi/Lazarus, frames also offer this functionality.

The idea is that, in the "outer" design, we can save only the differences from your original design to the customized version.

See Custom components documentation, and the section "Using designs to visually set up default state of your component".

4.34. New API for Tiled layers

  • New class TCastleTiledMap.TLayer = class(TCastleComponent)

    TODO: Make sure it can be serialized OK. Fallback on TCastleTiledMapLayer if necessary. But we prefer TCastleTiledMap.TLayer.

  • New published property Layers:TCastleComponentList<TLayer> inside TCastleTiledMap.

    Depends on TCastleComponentList plans. We want to serialize the properties of layers this way.

  • Remove existing Layers set from TCastleTiledMap.

    Write code in TCastleTiledMap.CustomSerialization(const SerializationProcess: TSerializationProcess); to upgrade existing designs to new API.

    Pascal code using old Layers will just be broken and have to be upgraded, acceptable.

  • Exists should be in TCastleTiledMap.TLayer, and not in TCastleTiledMapData.TLayer.

    Should toggling it toggle also TCastleTiledMapData.TLayer.Visible? Or let TCastleTiledMapData.TLayer.Visible stay as "initial value"? Undecided, not really very important.

  • The long-term goal is to have nice components for layers and maybe more (tiles), inside TCastleTiledMap, with published properties, that can be designed in CGE editor, and that are serialized using existing system to JSON.

    It should be possible to design layers (and maybe more, like tiles) in CGE editor.

    This way we can go, step by step, to having own Tiled-like editor in CGE, like Godot or Unity.

    At the same time, we want to support Tiled (as external application for map editing) and support it fully, because Tiled is great! and it may take us long time to actually have fully useful tile editor in CGE editor. The road should be that Data stuff, and everything in TCastleTiledMapData, becomes less and less useful. It’s an internal detail whether our public TCastleTiledMap.TLayer has a reference like Data:TCastleTiledMapData.TLayer or not.

4.35. Built-in tile editor in CGE, with support for 3D models on a grid

Built-in Tiled-like editing features in CGE would be great.

This is admittedly a long-term goal. A whole system for this, esp. with 3D, would be cool but also a significant new work.

What will likely be done sooner: "snapping" for 3D operations, that fils some subset of this functionality, e.g. allows to put 3D buildings on a grid.

4.36. ExposeTransforms is a powerful idea that can cover more use-cases

See docs and TCastleSceneCore.ExposeTransforms. It already contains TODOs showing how it should work like.

Moreover fix problem with names:

  • cannot duplicate model with ExposeTransforms now

  • cannot add another model with same bone names, before customizing bone name prefixes

  • solution: remove ExposeTransformsPrefix, rather add new property BoneName that doesn’t have to be unique and can be used for synchronization

  • document this on docs

Moreover, maybe:

  • ? Should expose the parent bones too (otherwise editing from code is hard, and applying edits back is hard — as you see a combined transformation only)

  • ? Rename to just Expose? ExposeTransforms sounds convoluted.

4.37. Improve editing (TCastleEdit, planned TCastleMemo)

  • Moving cursor freely in text (clicking, arrow keys, ctrl+arrow keys to move by words)

  • Free selection of any text subset (clicking, shift+arrows)

  • Multiline display (thus TCastleMemo, which should internally share code and be essentially TCastleEdit with > 1 line)

  • Right click with contextual menu - copy, paste, cut, select all, use platform-specific input method

  • Manual focus. Clicking on edit should keep it focused, no matter where the mouse moves. Tab or clicking elsewhere switches focus. Right now you can workaround it / do it manually by setting Container.ForceCaptureInput to the edit control.

All above will have to be synchronized with on-screen keyboard behavior on Android.

Moreover we want to support on-screen keyboard behavior on iOS as well, see https://github.com/castle-engine/castle-engine/issues/554 .

4.38. Editor Dark mode

Dark Mode design by Adrianna Matejek

I can’t count how many times I’ve been asked "when is the Dark Mode coming to CGE editor" :)

  1. One answer: It is already possible and easy on non-Windows.

    We use LCL and our editor just follows your OS (Windows, GTK, …​) theme. If you switch your system theme to something dark, then all your applications (including CGE) will become dark. This already works great e.g. on Linux or FreeBSD with GNOME, just switch your theme using GNOME settings and enjoy dark mode for everything.

    Unfortunately, on Windows, there’s no setting to change the WinAPI controls to use the dark theme.

  2. On Windows you can use MetaDarkStyle Lazarus package.

    We have a PR with this, not merged yet. You can easily do this yourself:

  3. Big Plan: The ultimate solution, that will allow to switch dark mode on/off on all platforms with exactly the same results, will come from reimplementing CGE editor using CGE user interface components. We made a decision some time ago, and it will definitely happen — but it’s still a big task, and it will take some time. The major benefits of it will be:

    • We will be able to use the editor on all platforms there are CGE targets. In particular, on the upcoming web target, which means you will be able to create and edit your games in your browser! Or even on mobile (but don’t hold your breath for making games on mobile — the form factors of mobile devices will likely make UX of CGE editor on mobile not very good).

    • It will necessitate CGE UI improvements, from which all CGE applications will benefit. For example, ready tree view, object inspector and list components.

    • It will allow to turn our "inspector at run-time" into full-featured "editor at run-time".

    • It will allow to avoid some LCL limitations, sometimes widgetset-specific. E.g. LCL GTK 2 widgetset uses deprecated GTK 2 and has known crashing issues, Qt5 widgetset needs libqt5pas library that most people don’t have (or don’t have in relevant version for latest LCL), macOS widgetset does not have a functional frames list and thus sprite sheet editor sucks…​ We will be able to ignore all of this, as they will be replaced by a cross-platform implementation.

    • And, last but not least: the dark mode, on all platforms, will be trivial to implement :)

4.39. Environment Lighting

It will work for all models, it is a great and modern way to do lighting.

4.40. Optimized animations (OptimizeExtensiveTransformations, InternalFastTransformUpdate) just out-of-the-box

As this post discusses, we have a few options to speed up animation processing.

Not all, but some of them should be "on" by default and have no possible adverse effects:

4.41. Improvements to auto-reloading changed data

In Castle Game Engine, we can auto-reload data files (images (in TCastleImageControl, TCastleImageTransform), scenes, Tiled maps) when they changed on disk. This is great when quickly prototyping the game, you can just save the file in external program (like Blender, GIMP, Tiled), Alt+Tab to the editor (or even your running game), and see how the new data "fits in".

Auto-reloading in editor (we call it "at design-time") is done automatically. Auto-reloading during the running game ("at run-time") must be explicitly enabled, by running the game in debug mode, then entering the inspector (using F8 key) and checking the "Monitor and Auto-Reload Data" checkbox.

The above describes what already works :)

Below are some missing things related to this:

  1. Changing textures used in a scene doesn’t cause reload of the scene.

    For example, when TCastleScene has xxx.gltf loaded, and xxx.gltf refers to texture my_texture.png, then changing xxx.gltf correctly reloads the scene, but changing my_texture.png does not.

    In general, TCastleScene doesn’t keep a centralized knowledge "all the files that are my dependencies".

    Implementing this knowledge is a TODO, it would be good to have it. For auto-reloading, also for possible auto-detection of unused files in data. To expand on the latter idea: While we will probably always pack whole data to package (so it’s like Unity Assets/Resources), it would be nice to have a button to allow to clean it manually ("list files in data that seem unused") or have a subdirectory in data (like data/managed/) where only used data is packaged.

  2. Caching right now sometimes "defeats" reloading. If something is in the cache and is referenced at least 2 times (e.g. there are 2 TCastleImageTransform components referring to the same image or you use TCastleSceneCore.Cache and the same scene URL is loaded 2 times), then reloading doesn’t work.

    The underlying reason is that cache never "lets go" of the loaded resource, because always someone refers to it, even as TCastleImageTransform is in the middle of TCastleImageTransform.ReloadUrl.

    Fixing this means reimplementing our ReloadUrl routines to reload the resource in the cache. Likely a way to notify all users of this resource "this is changing" will be necessary.

  3. We depend on LCL TApplicationProperties.OnActivate mechanism to detect the file changes when you switch back to CGE editor application. Unfortunately, it is not reliable with LCL GTK2 backend.

    Details: Sometimes the TApplicationProperties.OnActivate event fires when it should, sometimes it doesn’t…​ You can Alt+Tab between CGE editor and some other application, and see that sometimes TApplicationProperties.OnActivate just doesn’t happen. This was reproduced also with a trivial application (unrelated to CGE editor). It also happens with Lazarus IDE itself — Lazarus IDE seems to use similar mechanism to detect when Pascal file, opened in Lazarus, changed on disk (e.g. because you also edit it in VS Code). And sometimes, when you Alt+Tab between Lazarus and VS Code, Lazarus doesn’t notice the file change.

    The GTK2 can correctly send the relevant event (focus_in_event), which is used both by CGE TCastleWindow implementation on GTK, and Lazarus LCL GTK backend. So it doesn’t seem to be GTK2 fault. A similar mechanism just works reliably for TCastleWindow.

    We haven’t found any useful workaround, no other LCL event seems to receive any event that could be useful to workaround it. We have to submit a bugreport for LCL GTK2 (if you want to handle this, please let us know, we can use a help!). And possibly switch to something else (but Qt5 backend also has problems, using libraries that most people don’t have; and it will take some time before we can implement editor without LCL).

    The end result: CGE editor on Linux sometimes does not reload the data that changed. However, CGE applications, with "Monitor and Auto-Reload Data" selected, do reload the data reliably at run-time.

4.42. Saving float-based images preserving their precision

We can read float-based images, into these 4 image formats:

We can read from KTX, PNG, TIFF.

However, we cannot save them now.

  • It doesn’t seem Vampyre supports saving TIFF, it always crashes.

  • We didn’t test can Vampyre save 16-bit PNG images.

  • We miss code to save 16-bit PNG images using LibPng.

  • We miss code to save float images to KTX.

4.43. Remove the need for "record wrappers" like TCastleVector3Persistent, instead serialize/deserialize directly from TVector3, and expose in editor TVector3, as RTTI for them is available

Note
This will require bumping required FPC version, but it’s worth it, as it will simplify a lot of code in CGE (and for users that define custom components). And before we get to this in CGE, possibly new FPC release(s) will happen, and most users will have the required FPC version anyway :)

While records (like TVector3) cannot be published in FPC, the information about public records is available using RTTI. We should add

{$RTTI EXPLICIT
  PROPERTIES([vcPublic])
  FIELDS([vcPublic])
  METHODS([vcPublic])}

(or only PROPERTIES([vcPublic])), seems enough?) to castleconf.inc and recommend it in Custom components documentation.

Then for public records, like this:

TCastleTransform = class
public
  property Translation: TVector3 read ... write ...;
  property Scale: TVector3 read ... write ...;
end;

we should be able to read/write them using RTTT, hopefully with code mostly compatible with both FPC and Delphi.

On high level, this means:

  1. We can enhance CastleComponentSerialize to serialize/deserialize records. Do it, at least for our important records (TVector2, TVector3, TVector4…​) or (if no big obstacles) for all records in general.

  2. We can enhance the object inspector, used in CGE editor, to show records. See lazarus/components/jitclasses/.

We shall be able to remove then:

  • All wrapper classes TCastleVector3Persistent etc.

  • All fields using them, like TranslationPersistent: TCastleVector3Persistent etc.

  • Generator in tools/internal/generate-persistent-vectors/

  • Complicated explanation about it in Custom components documentation.

4.44. IN PROGRESS: Options to deal with resources (like textures) when saving

There are a few useful options we could offer for saving, from all cases (from "Data → Export to X3D, STL…​" in editor, from https://castle-engine.io/castle-model-viewer , from https://castle-engine.io/castle-model-converter ):

  • embed all resources using data URI (then the resulting big X3D is "self-contained", you can e.g. use it with https://castle-engine.io/castle-model-viewer-mobile ).

  • or copy all resources to the target directory (this could be similar to an option offered by Blender → glTF exporter, it can also copy textures on save).

The term "resources" means here everything — other files referred to be Inline nodes, textures, audio files, shader files etc.

4.45. Python integration

We want to allow using Python to develop Castle Game Engine games.

Two use-cases are important:

  1. Use Python just for adding some behaviors.

    This means implementing a class like TCastlePythonBehavior with PythonCode: TStringList that descends from TCastleBehavior and allows to write Python code that can be executed at both design-time and run-time. This code should have access to all CGE API.

    The main advantage here is that, in contrast to implementing TCastleBehavior in Pascal, Python code can run at design-time. The practical advantages of it:

    • You don’t need to rebuild the editor to change the published properties of the Python behavior in the editor’s object inspector, so the workflow is a bit faster than using custom Pascal components in editor. (Python doesn’t have published but we’ll invent equivalent mechanism).

    • You can test the execution in editor’s "Play Simulation" mode (now only used to test physics). You can quickly iterate on some code, by just using "Play Simulation" from editor, and editing the Python code in the editor.

    Overall, this approach should be useful for everyone, including Pascal developers. You don’t resign from coding in Pascal, you just move some logic to Python. For some behaviors you lose some advantages of Pascal (type-safety checked at compile-time) but you gain some advantages of Python as a scripting language (you can iterate on some ideas faster, test them in editor).

  2. Write the whole game in Python.

    This means you write the whole game code in Python. In particular, view’s code is in Python, so e.g. you have a design gameviewmain.castle-user-interface and a corresponding Python code in gameviewmain.py. The Python code defines ViewMain class.

    This makes our engine available for Python developers. We get an additional crowd of people interested in our engine. To be clear, you can still mix Python with Pascal code, but the main use-case is here for people who want to write the whole game in Python.

Why?

  • Choosing Python is enticing. It’s very popular. It does not have a game engine like CGE, from what we can tell (comfortable editor, powerful 3D and 2D, open-source). What we offer may be very attractive to Python developers.

  • We have https://github.com/pyscripter/python4delphi . Very active, tested by both Delphi and FPC users.

  • This idea was somewhat validated at 2023 conference in Salamanca. Namely, Embarcadero tries to do similar with FMX - offer it as library for Python devs.

To be clear, this doesn’t preclude integration with other scripting languages. Other reasonable choices exist and we welcome work on integrating them:

  • Lua is a popular choice in gamedev. One can implement something like TCastleLuaBehavior that allows to paste LUA scripts that interact with CGE.

  • Pascal Script is a natural choice for us. And it would bring us the benefits of "it can run at design-time" while staying within the same (well, similar) programming language.


To improve this documentation just edit this page and create a pull request to cge-www repository.