Data directory and castle-data:/ URL protocol

1. Introduction

The data subdirectory of a Castle Game Engine project is special. This is where you should put all the files that your application will load during runtime. This includes designs (usually created using editor), 3D models, images, sounds, and any other data files that you need.

Load these files using a special URL protocol castle-data:/…​.

Here&#8217;s an unrelated Cthulhu 3D model screenshot. Flying Cthulhu from Sketchfab <a href="https://sketchfab.com/3d-models/flying-cthulhu-4737a3b84e00415b9d8bb42ae44285b2" class="bare">https://sketchfab.com/3d-models/flying-cthulhu-4737a3b84e00415b9d8bb42ae44285b2</a> by TooManyDemons

2. Features

  • This directory is automatically correctly packaged by the build tool and editor. E.g. it will be correctly added to the Android apk file, iOS or Nintendo Switch application.

  • It is detected in a smart way. E.g. it allows to place your data files in a system-wide location on Unix. The details are below.

  • The detection can be customized using the ApplicationDataOverride global variable. Though we recommend to not touch it — the default algorithm was designed to account for a lot of normal use-cases and has been adjusted to account for specifics of every platform.

Note
The files inside this directory should only be read (not modified) at run-time to make you sure that your application works in all contexts (e.g. with Android read-only assets or system-wide installations on desktops). If you want to write files, use the ApplicationConfig to get URL for writing configuration files.
Note
You are not limited at runtime to reading only files from this data directory, of course. You can read any file on disk (using regular filenames or file:/…​ URLs) at runtime. See network docs.

3. Example things to put in the data subdirectory

  • Designs made by editor. A typical view has this in constructor:

    constructor TViewMain.Create(AOwner: TComponent);
    begin
      inherited;
      DesignUrl := 'castle-data:/gameviewmain.castle-user-interface';
    end;
  • Game 3D and 2D models, loaded e.g. by

    MyScene.Load('castle-data:/my_model.x3d');
  • 2D images, loaded e.g. by

    MyImageControl.Url := 'castle-data:/my_image.png';
  • Sounds, loaded e.g. by

    MySound.Url := 'castle-data:/my_sound.wav';
  • …​ and really anything else you plan to load during the game. Your custom files can be loaded using

    MyStream := Download('castle-data:/my_binary_file');

    or

    MyTextReader := TTextReader.Create('castle-data:/my_text_file.txt');

4. Advanced: How do we determine the data directory?

The algorithm to find base data directory is OS-specific. It searches a couple of common locations, using the first location that exists. We look inside standard user-specific directories, then inside standard system-wide directories, then we look for the data subdirectory in the current exe directory (under Windows) or in the current working directory (under other OSes).

Warning
The algorithm below is complicated. Don’t read this! Instead follow the short explanation: just place the files inside the data subdirectory of your project, and everything will work out-of-the-box.

The details how we currently choose the data directory:

Windows
  • data subdirectory inside our exe directory, if exists.

  • ../../data relative to our exe location, if it exists and exe seems to be inside a subdirectory <platform>/<config>/.

    Where <platform> matches current Delphi <platform> name (like Win32 or Win64 — this is combined OS and CPU) and <config> matches Debug or Release. This is deliberately adjusted to Delphi / C++ Builder default project settings, so that we detect data automatically when exe location follows Delphi conventions. This deliberately checks whether subdirectory names match <platform>/<config>/, to avoid picking up a random data subdirectory for unrelated project.

  • Otherwise: just our exe directory.

    Warning
    Don’t depend on this "last resort" fallback in your applications. Instead, place the data inside the data subdirectory.
macOS
  • Contents/Resources/data subdirectory inside our bundle directory, if we are inside a bundle and such subdirectory exists.

  • Otherwise, fallback on generic Unix detection, see below.

iOS
  • data subdirectory inside our bundle directory, if we are inside a bundle and such subdirectory exists.

  • Otherwise, fallback on generic Unix detection, see below.

Android
  • Always use Android assets packaged in APK. This is a special location on Android where application should store it’s assets.

Nintendo Switch
  • Always use special location on Nintendo Switch where application should store it’s data.

Unix (Linux, FreeBSD, macOS…​)
  • ~/.local/share/<ApplicationName>.

    This is user-specific data directory, following the default dictated by basedir spec. If such directory exists, it is returned.

    This is checked first, to allow user to always override system-wide installation of a program with his/her own installation. E.g. consider the situation when an old version of a program is installed system-wide in /usr/local/share/my_program/ , but some user (with no access to root account) wants to install a newer version of it for himself. This is possible, because ~/.local/share/my_program/ is checked before /usr/local/share/my_program/.

  • /usr/local/share/<ApplicationName>. If such directory exists, it is returned.

    This is for system-wide installations without package manager.

  • /usr/share/<ApplicationName>. If such directory exists, it is returned.

    This is for system-wide installations with package manager.

  • data subdirectory of the current directory, if exists.

    This is easiest and comfortable for development, just keep the data subdirectory alongside the executable binary.

    This is searched after system-wide specific dirs above, to avoid accidentally picking unrelated data in current directory instead of system-wide data.

  • Otherwise: As a last resort, we just return the current directory.

    Warning
    Don’t depend on this "last resort" fallback in your applications. Instead, place the data inside the data subdirectory.

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