Skip to content

Upgrading to Castle Game Engine 7.0

Michalis Kamburelis edited this page Jan 20, 2020 · 5 revisions

This page documents some compatibility-breaking changes in Castle Game Engine API version 6.5 (unstable) and 7.0 (upcoming stable release), compared to the last 6.4 release.

Note that we try to do most of our changes without breaking compatibility, merely marking old API as "deprecated". This way you can keep using old API, and compiler nicely warns about it (although we advise to eventually upgrade "deprecated" stuff too, as "deprecated" stuff may be removed after a couple of more releases). The page below only lists changes that had to be done by removing/changing something previously available, and you just have to upgrade your code along with upgrading to CGE 6.5 / 7.0.

If you are unsure how to upgrade something, or why something changed, please talk with us!

A number of big changes happened to our user-interface classes, rooted in TCastleUserInterface class (previously called TUIControl). The things you need to be aware of:

  • TUIControl.RenderStyle is removed. It was a convoluted way to specify rendering order. Now, only the position of the control among the children (when you InsertFront, InsertBack etc.) determines the rendering order.

  • The default TCastleLabel color is now Black, not White. This compatibility break seemed unavoidable, unfortunately our UI controls were inconsistent -- most assumed a modern "black colors over white background scheme" (TCastleEdit, TCastleRectangleControl, TCastleCheckbox...), but TCastleLabel was by default white. So it e.g. was invisible over default TCastleRectangleControl.

    If you depended that the label is by default white, then now simply adjust your code to always set MyLabel.Color := White after creating MyLabel := TCastleLabel.Create(...). Alternatively, temporarily, you can set Theme.DefaultLabelWhite := true at the initialization of your game. (But beware that Theme.DefaultLabelWhite is only a temporary compatibility crutch. It doesn't play nicely with designs created in CGE editor, since the (de)serialization will still assume that by default label has white color.)

  • The default TCastleSceneManager.BackgroundColor is now very dark gray Vector4(0.1, 0.1, 0.1, 1), instead of pure black Vector4(0, 0, 0, 1). This makes a better default, as pure black things (3D / 2D models, or user interface, like labels) are still visible over this background (as well as pure white things).

    If you'd like to restore the old default, just set MySceneManager.BackgroundColor := Black after creating any TCastleSceneManager instance. If you use TCastleWindow or TCastleControl or TCastle2DControl, they contain a default scene manager. You can trivially modify it's properties by e.g. Window.SceneManager.BackgroundColor := Black.

    Note that this doesn't matter if you use Background node to specify a background color (or skybox textures) in X3D. It also doesn't matter if your scene manager is transparent (TCastleSceneManager.Transparent is true). In these cases, scene manager BackgroundColor doesn't matter.

  • The user interface coordinates (all positions, sizes, as well as font sizes) are float-based now. See this post for details. In some cases, you may need to adjust your code. For example if you do SomeIntValue := MyOtherControl.Width div 2;, now you will have to change it to SomeFloatValue := MyOtherControl.Width / 2;.

  • The interpretation of FullSize=true is now consistent across all TCastleUserInterface ancestors. It always overrides the control to fill the parent.

    So FullSize=true works the same. Even for TCastleButton. Even for TCastleImageControl with TCastleImageControl.Stretch=false value.

    Also, changing Left/Bottom properties doesn't matter when you use FullSize. Previously, it was possible to use FullSize to have a rectangle with the same size as parent, but still move it using Left/Bottom properties. It is no longer possible: FullSize always means fill the parent, so the rendered area of the control covers the parent. You can use WidthFraction := 1; HeightFraction := 1; to set size equal to the parent, but control the position as you like.

  • TCastleImageControl.ProportionalScaling values psFit and psEnclose work a bit differently.

    Previously, they placed the scaled image in the middle of the rectangle determined by Left,Bottom,Width,Height. Now, auto-sizing changes size, but the content keeps at the same left-bottom corner. So the scaled image's left-bottom corner is always at the position indicated by Left,Bottom properties.

    To center image, just use MyImageControl.Anchor(hpMiddle); MyImageControl.Anchor(vpMiddle);.

    This is consistent with other UI controls.

  • Anchors are always on now. The ability to turn them on / off in previous CGE versions was more confusing than helpful, and it was also useless.

    Previously you could deactivate anchor by setting HasHorizontalAnchor to false (in fact, it was false by default). Now, you should achieve the same effect by calling Anchor(hpLeft); (which is also the default state). This aligns left control border to left parent border with 0 delta, which has the same effect as "no anchor".

  • Some components are no longer registered on the component palette. To bring them back (e.g. to open LFM files that refer to these components), you can define {$define CASTLE_REGISTER_ALL_COMPONENTS_IN_LAZARUS} to the src/castleconf.inc file. See this commit log for reasons.

  • TCastleFont.Scale was removed (as it was a trap, due to how it was implemented and specified, it was only working on some TCastleFont descendants). Use only TCastleFont.Size. For TTextureFont (which is the most commonly used font descendant) the Scale property is still present, so usually writing Font.Scale := 0.5 continues to work, if Font is of class TTextureFont.

  • By default, fonts show a fallback glyph (like "?") if you try to render a missing character in the font. This is usually a good idea -- it allows the user to see that something is there (so e.g. "backspace" makes sense, otherwise you would "backspace" invisible characters sometimes), the developer knows that something is missing (the log will also contain warnings about missing characters). However, if you want to restore previous behaviour (that silently ignores missing glyphs) set TTextureFont.FontData.UseFallbackGlyph := false.

  • TGLImage.ClipLine and TCastleImageControl.ClipLine are expressed in local (texture) image coordinates, in which image (X, Y) span from (0, 0) (bottom-left) to (1, 1) (top-right). Previously, they worked in the final screen coordinates. The new definition is much more useful, it allows to express common use-cases with a constant equation, e.g. reject left half of the image by ClipLine = (1, 0, 0.5), regardless of the image size and position on the screen. It also plays nicely with UI scaling -- the previous definition was working in final device screen coordinates, and we avoid exposing them in UI API.

  • TCastleButton.Image and 4x TCastleButton.CustomBackgroundXxx properties change from TCastleImage to TCastleImagePersistent. Instead of assigning them like

    MyButton.CustomBackgroundNormal := LoadImage('castle-data:/my_image.png');
    MyButton.OwnsCustomBackgroundNormal := true;
    

    you should now use

    MyButton.CustomBackgroundNormal.URL := 'castle-data:/my_image.png';
    

    Eventually, you can also do more elaborate version:

    MyButton.CustomBackgroundNormal.Image := LoadImage('castle-data:/my_image.png');
    MyButton.CustomBackgroundNormal.OwnsImage := true; // actually this is no longer needed
    

    The contained image is now owned by default, which makes the usual use-case simpler. So the behaviour is like previous TCastleButton.OwnsImage, TCastleButton.OwnsCustomBackgroundXxx would be true by default. This change is the reason why we break compatibility --- although we could make an API that seems backward-compatible (that is, compiles OK), but it would have bad consequences at runtime, with applications crashing, since the default of OwnsXxx is now true (and you would free the same pointer two times, in some circumstances). We decided that it's better to break compatibility at compile-time.

    This change makes it possible to easily configure these images using CGE editor. But it also makes configuring these images through code easier.

    Moreover, there is an underlying cache (of both TEncodedImage and TDrawableImage) used. So you can set multiple images to the same URL, and don't worry about the resources duplication on GPU -- we will actually share all the resources underneath, across all TCastleImagePersistent with the same URL. (You can turn it off by TCastleImagePersistent.Cache is special circumstances, e.g. when loading image from URL but then editing it at runtime in some controls.)

    Also TCastleButton.CustomBackgroundCorners and TCastleButton.ImageAlphaTest are removed. They are replaced by new settings inside TCastleImagePersistent subcomponents, In particular you have MyButton.CustomBackgroundXxx.ProtectedSides and MyButton.Image.Alpha.

  • The callback TAdClosedEvent (used by TAds.OnFullScreenAdClosed) parameters changed.

    • Previously they were (const Sender: TObject; const Watched: boolean).
    • Now they are (const Sender: TObject; const WatchedStatus: TAdWatchStatus). The WatchedStatus enum provides more detailed information why the ad was not watched.
    • To upgrade your code easily, change the Watched: boolean -> WatchedStatus: TAdWatchStatus declaration and instead of Watched use WatchedStatus = wsWatched.
  • If you use sounds XML file with importance note that the default value of default_importance is now 10 (not maximum 2147483647). So sounds that had default_importance not explicitly specified are now treated as less important than e.g. default_importance="player". To easily restore previous behavior, just add default_importance="maximum" for sounds without explicit default_importance attribute.

    Note that this doesn't matter if you use sounds XML file, but never specify default_importance. In this case, all sounds have the same importance, and it's numerical value doesn't matter.

    It also doesn't matter in practice if you never play more than 16 sounds simultaneously at once. The "importance" doesn't matter if you don't play too many sounds at once.

  • We disabled the default behavior of limiting gravity to only work within the level bounding box. It was non-obvious, and often a trap for newcomers ("why does gravity not work if I jump high?"). To restore it, you can assign SceneManager.OnMoveAllowed event to do something like this:

    { Don't let objects/camera fall outside of the box because of gravity,
      as then they would fall into infinity. }
    if BecauseOfGravity then
      Allowed := Items.BoundingBox.Contains(NewPosition);
  • When creating resources from CastleCreatures and CastleItems units, pass SceneManager.LevelProperties as 1st argument, instead of SceneManager.Items.

  • Since this commit: TShapeNode.Material is now TAbstractMaterialNode, not a more specific TMaterialInfo.

    This may affect you if you used construction like this:

    Shape.Material := TMaterialNode.Create; // this still works OK
    Shape.Material.DiffuseColor := GreenRgb; // this will not compile anymore

    Since Shape.Material is now TAbstractMaterialNode, and TAbstractMaterialNode doesn't have DiffuseColor property, this will not compile anymore.

    Instead use local variable Mat: TMaterialNode and do it like this:

    Mat := TMaterialNode.Create;
    Mat.DiffuseColor := GreenRgb;
    Shape.Material := Mat;

    Reason for breakage: Other material descendants are possible. Already you can place there TTwoSidedMaterialNode. Soon you will also be able to place there TPhysicalMaterial to get Physical-Based Rendering.

  • TCastleSceneManager.OnMoveAllowed callback is removed. You can use TCastleWalkNavigation.OnMoveAllowed instead. Or set invisible colliders to limit the movement.

  • TCastleViewport by default has FullSize, AutoCamera, AutoNavigation set to false. Set them to true to have exact behavior from previous engine versions.

  • The management of levels and player in CastleLevels, CastlePlayer was upgraded in a few ways. In particular, you should now never add Player instance manually to Viewport.Items (so do not call Viewport.Items.Add(Player) yourself). Also, always assign TLevel.Player before calling TLevel.Load.

Clone this wiki locally
You can’t perform that action at this time.