We have made a significant change to how our vectors are declared. They now have X
, Y
, Z
, W
as fields (not properties), and the compiler will prevent you from falling into a trap of writing
Scene.Translation.X := Scene.Translation.X + 10;
Like in the below testcase:
uses SysUtils, CastleScene, CastleVectors; var S: TCastleScene; begin S := TCastleScene.Create(nil); S.Translation.X := S.Translation.X + 10; FreeAndNil(S); end.
This has always been invalid code, as it potentially modifies a temporary value, not the actual Scene.Translation
value. And even if it modifies the actual Scene.Translation
value (under some optimization/compiler version), it bypasses the Scene.Translation
property setter. This is documented in-depth in coding traps documentation page.
I recognized this was a significant trap when using CGE vectors, and changed the way vector is declared to make it impossible. From now on, this code will no longer compile. FPC prevents us from making this mistake.
This affects all our vectors and colors:
The change is mostly backward compatible (if your code was safe).
-
Some properties and methods remain as deprecated (so they will compile, for now, albeit with clear warning from a compiler):
Data
,Items
properties,methodsInit
andNormalizeMe
. We will completely remove them at some point in the future (we don’t like traps in API 🙂 ) so please follow the compiler warnings and adjust your code to not use them. -
Setting fields
X
,Y
,Z
,W
is now the only way to change the vector “in place” that works reliably and is not deprecated. -
V[0]
works but is read-only now. It is equivalent toV.X
orV.AsArray[0]
. -
Constructions that treat
Data
as an array will no longer work, as it is now an indexed property. SoV1.Data := V2.Data
should change to justV1 := V2
. -
Data
is no longer a direct field, soV.Data[0] += 2
will no longer work. Change it toV.X += 2
. If you really need by-index access, you can temporarily change it toV.Data[0] := V.Data[0] + 2
orV.InternalData[0] := V.InternalData[0] + 2
— these provide a quick upgrade path, although we recommend avoiding such constructions altogether in new code. -
Constant declarations will need to change.
Foo: TVector3 = (Data: (1, 2, 3))
should now beFoo: TVector3 = (X: 1; Y: 2; Z: 3)
.
The other records in CGE will soon follow with a similar redesign. The only way to change the record “in place” is by direct field access, not by some method or property setter. This means that compiler will prevent invalid operations. This applies to:
P.S. As usual with such posts, I had trouble selecting a screenshot. How do you visualize “vector API cleanup”? 🙂 So here’s a screenshot of view3dscene rendering glTF model of Cthulhu (model by TooManyDemons, distributed on SketchFab). The model is quite high-poly, done in ZBrush (4.5 million triangles, but it’s just s single mesh and it renders with 60 FPS).