Hello @Michalis,
It would be great if, in addition to the usual Tag, components could also have a TagString or even TagFloat, etc.
Whatâs wrong with extending the component yourself to add such fields? And if for some reasons you donât want to, you can always create a new behavior with those fields and attach it to component.
Note that you can register your own extended components / behaviors to the editor if you want to use them in the editor.
Regarding behaviors, I donât have information â thank you for the link you provided.
As for extending components, I donât know how it works in FPC and CGE, but I have written many components for Delphi.
I do not want to add properties like TagString, TagFloat, as it doesnât seem to me a class design approach that âscalesâ (works with bigger and bigger applications).
That is:
-
If we add
TagFloatetc., and you will use them heavily, soon you will need e.g. 2 floats, and thenTagFloat2and so on will need to appear. -
The names of such properties are inherently unclear â every use-case uses
TagXxxfor something else. Itâs the opposite of self-documenting identifiers
You will use a number of TagXxxproperties, and it will not be clear from the code which instance uses what and for what purpose. -
Itâs inherently ânever going to be enoughâ. You will not have tags typed with all possible classes, records, including your own.
Instead, one can follow existing OOP best practices to extend classes. Namely, inheritance and composition. They allow to have clear names for your things (properties, fields, methodsâŚ), proper types, and as much (or as little) additional information as necessary for a particular task. I believe they are better answer:
-
The behaviors mentioned above are a simplest way to do âcompositionâ. You can add information and functionality to existing
TCastleTransforminstances, and itâs flexible, you can name and type them properly.Aside from linked manual page, please also read our tutorial âbad chessâ which shows a simplest usage of behaviors.
-
Other ways to use composition are possible - put
TCastleTransformand itâs descendants into parentTCastleTransform, putTCastleUserInterfaceand itâs descendants into parents, arrange any instances in lists and containers. -
And you can inherit from almost any CGE class in a useful way and extend itâs functionality.
I have used Behaviors.
The decision to add it is up to you; however, whether using Behaviors or inheritance, in many cases there is a need to configure certain things at design time, which is not easily possible with these two approaches.
Eh I kinda disagree. Both behaviors and custom components are easy to use at design time. To sum it up:
-
Register your new behaviors / components at initialization block:
RegisterSerializableComponent(TMyCustomComponent, âMy Custom Componentâ); -
Add your units with said new components to your projectâs
CastleEngineManifest.xml -
Rebuild a custom
castle-editorfor your project via build tool:castle-engine editor.
Now you can use your new behaviors / custom components at design time in castle-editor just like the default components.
(Of course if you use Delphi then you need to install both FPC / Lazarus for this to work, but I believe you already did that in your android thread
)
Yes, I have installed FPC / Lazarus.
However, I really prefer to focus on my own work rather than building a custom castle-editor.
In any case, I did the initializations in procedure TViewPlayWorld.Start, which ended up being somewhat complex and extensive.
I agree with @kagamma , the setup of behaviors is quite simple, I create them for useful component-extensions, to be easily setup via editor. For example, here is the ColorBehavior, no Update method, just to store different colors alongside the component which meant to be dynamically recolored based on some conditions/statuses:
TColorBehavior = class(TCastleBehavior)
strict private
FColor: TCastleColor;
FColorPersistent: TCastleColorPersistent;
function GetColorPersistent(): TCastleColor;
procedure SetColorPersistent(const AValue: TCastleColor);
public
constructor Create(AOwner: TComponent); override;
function PropertySections(const APropertyName: String): TPropertySections; override;
property Color: TCastleColor read FColor write FColor;
published
property ColorPersistent: TCastleColorPersistent read FColorPersistent;
end;
on Start I store the values (presetup in editor) for usage:
LBehaviors := MyComponent.FindAllBehaviors(TColorBehavior);
for LColorBehavior in LBehaviors do
MyComponent.CustomColors[LColorBehavior.Name] := TColorBehavior(LColorBehavior).Color;
btw, I use behaviors also in standard way, with Update method, to change translation of Component, for example, I have like around 10 different kind of behaviors in my game, which are good to adjust from editor, I have even special property for them
property ActiveInEditor: Boolean read FActiveInEditor write FActiveInEditor default False;
...
procedure TMyBehavior.Update(...);
begin
inherited;
{$IFDEF CASTLE_DESIGN_MODE}
if not ActiveInEditor then Exit;
{$ENDIF}
which allows to enable and disable them in editor (in the game they are always on), so they donât actually affect translations or whatever they supposed to, when you already set them up in editor, bc otherwise they distract you.
Moreover there is also a way to store âdictionariesâ/configs of complex types with the same mechanism of registration , but of different inheritance: TCastleComponent, fully editable from editor as well (check examples\2d_games\platformer\data\sounds.castle-component for example)
You donât need to do anything specific to build a custom editor, bc when you launch a project which contains custom components (it is defined in CastleEngineManifest.xml , there is an article in manual on how-to), it asks you to build/rebuild it automatically, you just click and wait a bit and get it with all brand-new features ![]()
I did this:
TSceneBehavior = class(TCastleBehavior)
public
deg : Int16;
I : Int32;
J : Int32;
fileName : string;
// procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;
end;
For now my problem is solved, and I thank everyone who took the time to guide and explain things.
Thanks everyone! Just adding a link to the manual page about âcustom componentsâ that expands the advises from this thread, how to make your own component (like a behavior) available in the editor at design-time: Custom Components | Manual | Castle Game Engine .