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:
-
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. AndTCastleUIState
orTCastleUiState
are too convoluted. So for a long time I knew it will have to be renamed toTCastleState
orTCastleView
. I finally finished the work to go withTCastleView
.“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.
-
The way we changed states, using
TUIState
class methods/properties, could be improved to use simple methods onContainer
.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 orTCastleControl
(whether for LCL, VCL or FMX). You can just doMyControl.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):
-
Rename
TUIState
->TCastleView
. -
Remove
CastleUIState
unit from your uses clause. Make sure unitCastleUIControls
is there (it likely is there already). -
Change in ApplicationInitialize:
TUIState.Current := ...
to
Window.Container.View := ...
-
Change in various states (views):
TUIState.Current := ... TUIState.Push(...) TUIState.Pop(...)
to (respectively)
Container.View := ... Container.PushView(...) Container.PopView(...)
-
Optionally, as a final touch: rename your units and designs.
Previously we called them
gamestatexxx
. With class likeTStateXxx
, with variable likeStateXxx
.Now we advise to call them
gameviewxxx
. With class likeTViewXxx
, with variable likeViewXxx
. If you choose to go with rename, you will likely find that a general interactive renamestate
->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.
I have followed the upgrading changes but get this error?
Look at the type of your
StatePlay
variable (it is inGameStatePlay
unit, you can just ctrl + click on it in Lazarus to jump to declaration). It likely has a typeTStatePlay
, so here you should createStatePlay := TStatePlay.Create...
.Also,
TCastleView
is inCastleUIControls
. Which you can find by searching for it in API docs, Castle Game Engine: CastleUIControls: Class TCastleView . But, you don’t want to create justTCastleView
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.