Engine on a form (VCL, FMX, LCL) using TCastleControl

1. Introduction

TCastleControl is a component you can drop on a form. It allows to do all CGE rendering and processing as part of a form, and TCastleControl can be surrounded on your form by any other components.

The same component is available for Lazarus (LCL) and Delphi (VCL, FMX) forms.

TCastleControl on Delphi VCL form 3D model viewer using TCastleControl on LCL

2. Delphi installation

  1. Install the Delphi packages following the Delphi packages installation instructions.

    Make sure to use the menu item "Tools → Castle Game Engine → Configure Delphi to Use Engine" as described on that page, to have CGE units available for all your projects.

  2. Test: Open the examples in examples/delphi, there’s one example for VCL one for FMX.

    These are regular Delphi projects, open them in Delphi, compile and run (for Windows 32-bit or 64-bit).

    You can also open each example in CGE editor (point the CGE editor to the CastleEngineManifest.xml file inside the example directory), to edit the 3D / 2D / UI designs there.

2.1. Screenshots

TCastleControl on Delphi VCL form TCastleControl on Delphi VCL form TCastleControl on Delphi VCL form TCastleControl on Delphi FMX form TCastleControl on Delphi FMX form TCastleControl on Delphi FMX form

3. Lazarus installation

  1. Install in Lazarus the package castle_components.lpk. In the package dialog, use the option to "Install" (under the "Use" button).

    Note: Installing the castle_components package will also automatically install the package castle_base, as a dependency. That’s good.

    castle_components: Choose the file castle_components: Install castle_components: Confirm Lazarus rebuild

    Once castle_components.lpk is successfully installed, Lazarus restarts, and you should see the "Castle" tab with our components.

  2. To test, open in Lazarus examples in examples/lazarus/. Like examples/lazarus/model_3d_viewer.

  3. To use in your own application:

    1. Create a normal new LCL project (using Lazarus "New Project" menu item). Choose "Application".

    2. Pick TCastleControl from the component palette (tab "Castle") and drop it on a regular Lazarus form.

    3. Done. Press "Run" :)

3.1. Screenshots

TCastleControl designed in Lazarus 3D model viewer using TCastleControl

4. Opening the project in CGE editor

While you will use Delphi / Lazarus to design your forms, it is also useful to design CGE components using CGE editor. To do this, create a CastleEngineManifest.xml file within your project.

This is an example for Delphi application:

<?xml version="1.0" encoding="utf-8"?>
<project name="my_project"
  standalone_source="my_project.dpr"
  compiler="delphi"
>
</project>
Note
Delphi uses can just open the project in Delphi IDE, and use from Delphi the menu item "Tools → Castle Game Engine → Open in CGE editor". This will automatically create a manifest file, just like shown above, if it is missing.

This is an example for Lazarus application:

<?xml version="1.0" encoding="utf-8"?>
<project name="my_project"
  lazarus_project="my_project.lpi"
  build_using_lazbuild="true"
>
</project>

This way you can open this project in the CGE editor and:

  • open and modify CGE designs, like xxx.castle-user-interface files,

  • run the project from CGE editor (CGE editor, and build tool, will just invoke Delphi compiler or lazbuild under the hood).

5. Initializing the resources

Essentially, you can initialize your game resources at any time. Even before any TCastleControl exists. For example in the OnCreate event of a main form. All Castle Game Engine components can be created and configured regardless of the OpenGL context existence.

6. Loading user interface and view

In the simple case, you can load a design (file xxx.castle-user-interface) using TCastleControlContainer.DesignUrl, and access loaded components using TCastleControlContainer.DesignedComponent.

Using TCastleControl.DesignUrl to load design in TCastleControl, visible at Lazarus design-time

In more involved cases, you should use multiple views within your control. In this case, use TCastleView within the TCastleControl, and load a design (file xxx.castle-user-interface) inside the view using TCastleView.DesignUrl. This is analogous to our recommended workflow with TCastleWindow. You can add new view using CGE editor ("Code → New Unit → View…​"), or just define a new unit like this:

unit GameViewMain;

interface

uses CastleUIControls;

type
  TViewMain = class(TCastleView)
  published
    { Components designed using CGE editor.
      These fields will be automatically initialized at Start. }
    // ButtonXxx: TCastleButton;
  public
    constructor Create(AOwner: TComponent); override;
    procedure Start; override;
  end;

var
  ViewMain: TViewMain;

implementation

constructor TViewMain.Create(AOwner: TComponent);
begin
  inherited;
  DesignUrl := 'castle-data:/gameviewmain.castle-user-interface';
end;

procedure TViewMain.Start;
begin
  inherited;
end;

end.

That’s enough to load gameviewmain.castle-user-interface design from your data subdirectory.

To initialize this view in your application, you can use this code e.g. in OnCreate form event:

ViewMain := TViewMain.Create(Application);
MyCastleControl.Container.View := ViewMain;

A simple example of using views with TCastleControl is in examples/lazarus/multiple_views. The CGE API used there is the same for Lazarus (LCL) and Delphi (VCL, FMX) versions of TCastleControl.

7. Focus (receiving key input)

Note
This section is important if your TCastleControl is placed on a form together with other LCL controls that may receive focus (that is, key input), like buttons (TButton) or edit boxes (TEdit).
Note
TODO: Keyboard focus on Delphi (VCL, FMX) is in-progress. This section (for now) applies only to Lazarus (LCL).

Like every LCL control, our TCastleControl receives the keys only when it has focus. The control does not capture all the keys pressed over the form (this would be bad, as other controls, maybe even other TCastleControl on the same form, may want to handle them). To make sure that controlling the camera by keys (like AWSD or arrows) works, make sure that your control has a focus.

  • You can call MyCastleControl.SetFocus; at any time to explicitly make the MyCastleControl focused. You can assign this to some menu item, or key shortcut handled by form, to allow user to easily switch focus to the TCastleControl instance.

  • You can also use TCastleControl.AutoFocus to make the control automatically focused when user presses mouse over it.

8. Comparison between TCastleWindow and TCastleControl

Most of this manual describes the process of using the engine with the TCastleWindow instead of TCastleControl. All new projects created from editor templates use TCastleWindow. We generally advise TCastleWindow, as:

  • TCastleWindow works on all CGE platforms (desktop, mobile - Android, iOS, consoles - Nintendo Switch, upcoming web target). It allows us to have true cross-platform projects, that can be recompiled to any supported platform out-of-the-box.

  • TCastleWindow allows us to handle events and message loop on the CGE side, and make it efficient. For example, it makes mouse look work perfectly smooth.

On the other hand, using the TCastleControl has one big benefit: as you place the control inside a form, you can surround it with all the standard VCL / FMX / LCL GUI controls. So you can use numerous GUI controls, with native look on all desktop systems, together with Castle Game Engine.

We are committed to supporting both approaches (TCastleControl and TCastleWindow) in the foreseeable future.

8.1. It is not allowed to use both TCastleWindow and TCastleControl in a single application

You have to make a choice:

You cannot mix these approaches, as neither VCL / FMX / LCL (in which our TCastleControl works) nor TCastleWindow are prepared to handle the situation that they only handle some application forms, and other library handles the other forms.

That is also why for Lazarus we have separate packages

You should not use both of these packages at the same time.

In case of Delphi, we have only one package, because there’s no reason to put TCastleWindow in a package.

Note that, if you use TCastleControl, it is OK to have multiple TCastleControl instances visible at the same time. Similarly, if you use TCastleWindow, you can have several TCastleWindow instances visible at the same time (but only on desktop platforms), see examples/window/multi_window.


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