TUIState is now TCastleView, methods to change the view are now part of Container, new slick UI when opening the project

Platformer game view
Editor UI to open existing views

We have an important change to one of our most important concepts: states (TUIState descendants) are now called views (and descend from TCastleView).

It’s a change in terminology, and a change in API. While previously you were changing states using class functions and properties, like TUIState.Current := Xxx, now you should use regular container methods, like Container.View := Xxx.

Oh, and to this we add a new slick UI when opening the project 🙂

Why?

It addresses two things:

  1. The name “state” was too generic and thus meaningless. Almost every variable and object instance in your application can be called some “state”.

    It made sense if you think “user interface state” or “state of a state machine… but the sole word “state” is too generic.

    Moreover, TUIState class name is not consistent with CGE naming. And TCastleUIState or TCastleUiState are too convoluted. So for a long time I knew it will have to be renamed to TCastleState or TCastleView. I finally finished the work to go with TCastleView.

    “View” doesn’t seem too bad name. It clearly communicates it’s something visual and is a way to “see” CGE stuff. And, view isn’t that often used as a noun, so when someone says “This view is amazing” you can fairly safely assume they talk about TCastleView (assuming you’re in the middle of CGE manual, not on a hiking trip 🙂 ).

    It is consistent e.g. with React view.

  2. The way we changed states, using TUIState class methods/properties, could be improved to use simple methods on Container.

    This way there’s often no need to know what is the “central” container (TCastleControl.MainControl is now deprecated) and every container has it’s own, separate, state stack (or rather: view stack now). This makes things simpler if you try to use multiple containers or TCastleControl (whether for LCL, VCL or FMX). You can just do

    MyControl.Container.View := PlayGame;
    

    instead of

    TCastleControl.MainControl := MyControl;
    TUIState.Current := PlayGame;
    

    This is already reflected in new TCastleControl docs.

Upgrading

This change is 100% backward-compatible. The old code will continue to work, though we advise you to upgrade to new names and container methods/properties.

In total, the upgrade path in typical applications is rather straightforward, although it will require to do a lot of replacements (I recommend to commit everything to your version control before doing the upgrade, and then have a nice diff to audit with state->view upgrade):

  1. Rename TUIState -> TCastleView.

  2. Remove CastleUIState unit from your uses clause. Make sure unit CastleUIControls is there (it likely is there already).

  3. Change in ApplicationInitialize:

    TUIState.Current := ...
    

    to

    Window.Container.View := ...
    
  4. Change in various states (views):

    TUIState.Current := ...
    TUIState.Push(...)
    TUIState.Pop(...)
    

    to (respectively)

    Container.View := ...
    Container.PushView(...)
    Container.PopView(...)
    
  5. Optionally, as a final touch: rename your units and designs.

    Previously we called them gamestatexxx . With class like TStateXxx, with variable like StateXxx.

    Now we advise to call them gameviewxxx . With class like TViewXxx, with variable like ViewXxx. If you choose to go with rename, you will likely find that a general interactive rename state->view, and accepting 99% of the replacements, it the way to go.

    You can just rename them everywhere. Remember that the unit also refers to the design, doing something like

    DesignUrl := 'castle-data:/gamestatemain.castle-user-interface';
    

    So if you rename both the unit and design (which we recommend, to keep F12 working nicely in CGE editor) then change also that line of code to

    DesignUrl := 'castle-data:/gameviewmain.castle-user-interface';
    

New editor UI when opening new project

This is accompanied by a cool upgrade to our CGE editor UI. It happened because of independent reasons (I did UX testing on a live human at Christmas :), and came back with lots of nice conclusions) but it is nicely connected with the whole views terminology.

Now, when opening any project, you will be greeted with a UI to

  • compile and run / stop the project
  • create a new view (Pascal unit and design)
  • open an existing view

This UI emphasizes your most recommended actions after opening the project.

Docs

Our documentation, including important chapters about view events and managing views, has been upgraded to new terminology.

Our examples are also fully upgraded now to use view terminology everywhere.

1 Like

I have followed the upgrading changes but get this error?

Look at the type of your StatePlay variable (it is in GameStatePlay unit, you can just ctrl + click on it in Lazarus to jump to declaration). It likely has a type TStatePlay, so here you should create StatePlay := TStatePlay.Create... .

Also, TCastleView is in CastleUIControls . Which you can find by searching for it in API docs, Castle Game Engine: CastleUIControls: Class TCastleView . But, you don’t want to create just TCastleView there.

I now have StatePlay := TCastleViewPlay.Create(Application) in TStateMenu but now I get an error message I did not have before when using TStatePlay?

Hm, this error message seems unrelated to TUIState → TCastleView rename, and indicates some problem you had before or that you did something weird at conversion. I’m afraid I cannot tell where’s the problem looking at the screenshot.

Please submit a testcase to reproduce the problem, preferably a small testcase.

If you have a version control (as I recommended in TUIState is now TCastleView, methods to change the view are now part of Container, new slick UI when opening the project – Castle Game Engine as I recommend in general – use version control) then please look at your changes, and see whether they make sense, if you didn’t touch anything unusual.