Some newb questions

Hello, everyone.

---- some description where am i coming for ----

I have some Delphi / desktop apps program experience (actually, was the last JediVCL Delphi 5 maintainer for a while).

Now i have to quickly, and in a spare time, sketch a simple simulation app. Main problem to me was Delphi audio is Win16-era API. And i would have eventually to make multi-channel almost realtime simulation (samples with some processing, probably, but that is to be researched yet). Also some very simplistic, but fast 2D graphics would be needed (previously did with VCL TCanvas and some custom zooming, but result was slow and ugly). So, i natually started to look for 2D game making libraries, and Castle is one of the most known and one of the most alive.

Maybe in long term i’d better with something like ZenGL, but have no time. So, let it be Castle (even if i would probably end up only using like 0.1% of all its riches).

Delphi XE2 was dumped for few reasons.

  1. It is not native for Castle, so bugs are possible, and debugging a complex library is not what i can do now.
  2. Linux compatibility can be a good bonus, if this sketch app would make into something better. Only using FLOSS tools, another bonus.
  3. Me and my current boss are growing tired of each other, so chances are in few months i won’t have legal Delphi XE2 anyway.

CodeTyphon was dumped as most FPC users say meeeh…
So in the end i seem to manage makins Win/Laz64 environment.

---- some thoughts about my future otions ----

ATM i compiled Castle from Git, run the editor, opened a wiki and… like a donkey between haystacks :slight_smile:

So, some questiones, very vague, sorry, ATM i am not sure myself where i am steering too.

  1. am i right, that the editor starts with TCastleWindowBase just has no options to start with LCL form and TCastleControlBase? Maybe engine could create some abstract “scene” that could easily get replanted into TForm after being designed?

  2. Were there any experiments to channel 2D output somewhere? Like, into remote computer (VNC? custom protocol?), into mjpeg/mpeg4 movie?

  3. is Castle’s user inputs processing bound to the TCastleWindowBase window? Event loop remarks at “Engine control to put on Lazarus form” article suggests so… In the end i might end up with a somewhat weird setup for the application: General scene setup window (LCL or VCL) active before/after the simulation test run, simplistic user controls window for those test runs (LCL or Castle 2D, not sure yet), and an optional 2D scene window (with or without zooming, not sure yet).

Such a disjoint “floating/docking windows” design is common for business applications (Lazarus itself), but hardly for games apps. So, here be dragons…

OTOH for the first sketch i was thinking about a single LCL form app, having three sections (alRight “setup” panel, “alBottom” user control panel, and “alClient” 2D scene.

  1. the visual objects would probably be some simplistic mark (diamond, rect, circle, triangle, or maybe a bit more complicated, but not much) overlapped with some “radiation” hint, something like a translucent “function radius(angle)” background. Those to be smoothly rotated and/or moved. One user-controlled, others probably scripted. Of the two 2D Games approaches outlines, i dunno which to try first. Maybe to start with “imperative” one if it is simpler, then later to re-do it in “declarative” fashion.

  2. What about multithreading? Delphi VCL is a single-threaded library, but how you spawn background worker threads is well-known. Probably the same is with LCL, as that is a reasonable design for “buiseness apps” and as LCL was made to mimic VCL. Not sure about TCastleWindowBase.

That said, i am not sure i would actually need multithreading. It might end-up cross-threads communication would introduce some latency/synchronization issues comparing to a single hi-res (in time dimension) thread design. Or maybe, given modern CPUs, there would be just no human-noticeable difference between those.

Surely this is totally not what Castle Engine was designed for, and also is very very vague, but if someone has any advices or cheat-sheets it would be appreciated.

Hi and welcome!

First, note that for such reasons (2D graphics) Castle Game Engine should work equally well both with Delphi and FPC. Though I’ve given up using Delphi many years ago, I believe the current CGE state should give a stable results without bugs.

Castle Editor may generate a project for you, but you don’t have to stick with TCastleWindowBase. Castle Editor itself is based on LCL.You can easily design UI in LCL and use CGE for rendering; or you can design part of the UI in Castle Editor and load it in LCL-based app the same way you did with a “normal” generated project.

This is more complicated. While you can setup environment to do something like that, I don’t even know where to start it - most likely you’ll need to grab the render buffer and send this stream to FFMPEG which in turn - to some receiver. However, you can always just login through VNC or TeamViewer or Remote Desktop or any other convenient option and natively see the program output on the remote machine. Or use third-party streaming software like Open Broadcast Studio to stream.

No. TCastleControlBase has OnPress, OnMotion and OnRelease and also Container.Pressed and all other features of TCastleWindowBase input system. You can even assign those easily from Lazarus Object Inspector.

Yes, I was using Castle Game Engine this way and it works without issues.

Unfortunately I must admit I don’t understand what exactly you are trying to achieve here. However, yes, you can have any type of interactive or non-interactive markers in the viewport.

E.g. this is the application I was writing some time ago in Lazarus + Castle Game Engine - with map rendered in TCastleControlBase and other forms - LCL.

As a rule of a thumb you should not use multithreading with Castle Game Engine’s classes. However, nothing prevents you from doing multithreading when processing data or running simulation (obviously it’s up to you to provide thread-safety) - only when it’s actually being rendered it should be done in the main thread. You may copy data into some container accessible from the main thread periodically or use TCriticalSection class to prevent accessing the same data from different threads.

Depending on what you are doing. A 8-core CPU will perform the task almost 8 times faster than 1-core CPU with the same frequency. If your calculation/simulation takes 1-2 seconds, it’s negligible, if 1-2 days…

I’ve been using CGE for 2D and 3D scientific data visualization for many years and it’s most certainly suitable for that.

Hello! To add some notes on top of @eugeneloza answers:

The 4 editor templates are indeed based on TCastleWindowBase, not TCastleControlBase, to not confuse new users with too many choices. We recommend using TCastleWindowBase for most games – this makes a cross-platform application with 100% work done by CGE.

That said, you can use any example from examples/lazarus as a starting point for your TCastleControlBase applications. In particular simple examples/lazarus/model_3d_with_2d_controls shows how TCastleControlBase can load a design, “main.castle-user-interface”, created in CGE editor. Both TCastleWindowBase and TCastleControlBase can use the same editor designs, there is only a difference in where to initialize them.

See Engine control to put on Lazarus form | Manual | Castle Game Engine about TCastleControlBase notes.

You can record movies using the approach on Recording movies | Manual | Castle Game Engine , that results in perfect quality (as many FPS as you want) though recording is not real-time.

For real-time recording: I never attempted to control it programmatically, but recording CGE applications using OBS, VNC, TeamViewer and many other screen recording/sharing apps was tested. I routinely record some CGE things :slight_smile:

See Multithreading · castle-engine/castle-engine Wiki · GitHub about CGE + multi-threading.

Hello, and sorry for long delay.

Expected so, but in the long run, if this project would make it, multi-OS support of FPC would mean more than my familiarity with Delphi XE2. So, i’d settle on using “native” for library developer tools.

Nope, if it would go beyond proof of concept, the point would exactly be for the local operator and the remote superviusor seeing different pictures. Perhaps local operator would not even see Castle-generated picture, only LCL control tools

For an example, look here - Flightradar24: Live Flight Tracker - Real-Time Flight Tracker Map
You can see many aircrafts, but they do not have photo-realistic rendering and they do not have realistic sizes. They are just special marks, simplified and easily recognizable.

I would have to do a similar thing.

Looks nice. What did you use to render those circles? was it just pascal code in some .OnPaint event? Or are them some Castle’s objects, models, that you position and then delegate to the Castle core to render?

Also, if you remember, which of the two approaches you used for the map?
https://castle-engine.io/how_to_render_2d

I see, so it is the same as with VCL/LCL, ok

I expect each specific calculation to be short, but there to be dozens of them and they would to be done about 100 times per second in a quasi-realtime, too keep “input lag” minimal.

So in the end i am not sure if OS threads switching would not introduce more lag, than utilizing multiple cores would shred off. But i guess it jsut can not be answered theoretically, it is try and see thing.

For example i once used Delphi OmniThreadLibrary, which facilitate building complex computations as a pipeline of single-thread oneliners. It was really easy, and the pipeline was neatly distributed across cores… Just the very act of inserting simple numbers into thread-safe any-type collections and fetching from those took like 100 times more time than computations themselves :slight_smile: But the “atomized” code itself indeed was simplistic to the point of being error-proof, just could not be used in practice :smiley:

This is expectable from the common sense, and looking from the bird fly. Learning curve hits (or threatens) from the small details side :slight_smile: Thank you for specific point of reference.

But it would be nice if you have a kickstarter article, like compilation instruction, etc, showing this process of desiging in the GCE and then using/compiling in separate Lazarus session step by step. Not even “do once in GCE completely, then export to Laz”, but also that you can do it in 2-3 loops, updating the GCE project, then updating LCL parts in LAz and compiling in Laz, then moving back to GCE. Co-development in two IDEs basically.

Perhaps it would be less about educating and more about clearing fears (F.U.D.). That using GCE for TCastleControlBase-app is not a one-time switch but a feasible continuous work environment too.

OTOH maybe TCastleControlBase-based template just could be added to the editor, not as default option but after checking some “advanced mode” switch or maybe after importing it into editor’s library form a separate folder.

and many other screen recording/sharing apps was tested

This was expected, but i wonted graphic output remote-only, so it would not be screen captre.
Well, i did not actually expected anyone would really do such a crazy for a game-dev project thing, just asked for a slim wild chance :slight_smile:

Again, thank you both for answers.

After git pull i started recompiling it all :slight_smile:

Had a weird Lazarus crash after castle_components.lpk package recompilation, guess Lazarus IDE does not always know how to correctly relaunch itself. But it seems to launch okay the next time.

Got interested by view3dscene.lpr(3976,41) Warning: Symbol “LoadFromConfig” is deprecated: “load sound properties explicitly from UserConfig”

Tryied to control-click the symbol - and it failed.
See the screenshot

CodeTools weirdly chokes on … path (premature end of file error in bottom line). I wonder if that is an intentional choice of Laz devs or some temporary limitation.

Then there seems to be a typical Linux-2-Windows error about Russian language charsets. I think in English IDE it would give reasonable text there. Maybe i would switch Laz to English instead of trying to fix it…

Okay, i kept digging and went to

function UserConfig: TCastleConfig;
begin
  Result := FUserConfig;
end;

Would this really be needed in FPC where you have global properties?
https://www.freepascal.org/docs-html/ref/refse27.html

UserConfig is probably not what gets called 1000 times a second, but still, the pattern itself…
Would this function be a lazy-creating the object instance, it would make more sense IMHO, but the instance is created in initialization already.

P.S. in Delphi i’d make a singleton into a class-property of TCastleConfig and for compatibility turned UserConfig into an inline function reading that property. But FPC itself blurs the boundary between units and classes and provides for global properties, nice and neat.

P.P.S. on a re-reading i know wonder if this {$I using Linux-kind slashes in file path would actually be Delphi-compatible…

Our singletons are exposed through a global function, like UserConfig, not through a class function like TCastleConfig.Instance – just because that is what is most commonly used in other Pascal libraries I think. E.g. you have Application singleton in VCL/LCL, not TApplication.Instance.

Of course a class function, that you propose, would work as well here. It’s just a matter what approach seemed more consistent. We chose to go with “expose singletons using global functions”.

They are. The CGE code you’re reading now compiles and works with Delphi :), since a month Big merge: Delphi compatibility, integration with Vampyre Imaging Library, many new/upgraded examples, inspector improvements, more – Castle Game Engine . Windows allows slashes as well as backslashes in paths, and so does Delphi.

The instructions like

{$I auto_generated_persistent_vectors/tcastleviewport_persistent_vectors.inc}

already work in Delphi.

not through a class function like

not a function, a property!!! so a direct access to the variable itself, skipping any function/code, JMP/CALL etc

E.g. you have Application singleton in VCL/LCL, not TApplication.Instance .

Gotcha!!!

d:\fpcupdeluxe\lazarus\lcl\forms.pp

var
  Application: TApplication = nil;
  Screen: TScreen = nil;

Exactly because using a function to access a variable would be slower.
Even with a risk someone erroneously would re-assign those vars.

Delphi has little better tools to keep singletons source-compatible (inline functions are not exactly zero-op, and class properties take a lot of boilerplate even without global/top-level inline functions to access them)

But FPC itself has global (unit-level) properties that can give you both: zero-op access and write protection.

already work in Delphi.

Okay then, what is left to wonder is why Laz fails code browsing there, is it by design or just a misfeature?.. are they trying to prevent some chroot jail break or why this choking on relative paths?.. :frowning:

FPC global properties are not that helpful. They cannot use a global variable, from what I tested. This does not compile:

unit A;

interface

var
  FFoo: Integer;

property Foo: Integer read FFoo;

implementation

end.

So you need a function as a property getter anyway.

And there’s an additional complication if you want to hide this function – you need to place it in another, internal unit (because the global function has to be global too, it has to be visible in some unit’s inteface). See the docs you linked, Properties :slight_smile:

Also, Delphi doesn’t allow global properties, and we’re compatible with Delphi now too.

Also, some singletons end up to be “created on demand” in the end, not just returning a simple variable. So doing an optimization for a specific case (“this function just returns a variable”) is not very useful, if it there’s a significant chance that this implementation detail will change.

Declaring this function as inline is our best bet. That’s exactly what inline was invented for :slight_smile:

But on a more practical note, this falls under “optimizations that don’t matter”. See Coding Conventions | Castle Game Engine , section " Optimize smartly: profile, optimize where it matters (and not where it doesn’t), think about smarter algorithms and moving CPU work to GPU to get big benefits". I don’t think the speed of UserConfig function has a measureable effect on any real-life code :slight_smile: Which means we should just do what is simplest and makes secure API (that doesn’t expose writing to the singleton variable – I admittedly didn’t know LCL opens the Application singleton like that).

I forgot to address other questions, sorry:

  • As for TCastleControl : I want to document using it much better. Current Engine control to put on Lazarus form | Manual | Castle Game Engine is too succinct. I have in TODO to clearly explain there what is the equivalent CGE Application.OnInitialize, how to use TIUState with TCastleControl etc.

    While using TCastleWindow, with all UI designed in CGE, remains the focus of CGE (as this gets you cross-platform UI, rendered using CGE, everywhere), but I definitely want to document using alternative TCastleControl better. Esp. as we’ll also implement it for VCL and/or FMX (in addition to LCL) for Delphi.

  • As for path problems: From what I can see, these are problems in Lazarus with handling paths with localized characters on Windows. You should submit them to Lazarus devs.

    First, you may want to check whether they are not already fixed. Just 2 days ago Lazarus released 2.2.0, so check if the issue is still there, https://www.lazarus-ide.org/ . If not, you can still check “trunk” (latest “main” branch), e.g. by compiling Lazarus using fpcupdeluxe | Castle Game Engine . If the problem is still there, you can submit it on Issues · FPC / Lazarus / Lazarus · GitLab.

This won’t do too, at least in Delphi. Inline funciton is the same as non-instantiated generic (okay, it is the other direction, but still), it is materialized in compilation time at call site.

If the variable to be encapsulated is in the implementation section - then it is not available to the call site and the function would NOT be inlined (there is a special warning for it). And if you move the variable into interface- inline funciton would be inlined, but there is no safe insulation then.

there were spaces but there were no non-Latin letters.

Thank for the tip, would do!

If not, you can still check “trunk” (latest “main” branch)

I use “stable”. Trunk is bleeding edge (or it was in usual SVN practice), and i am not so much of kamikaze to have non-released compiler :slight_smile:

No, really…

fpcupdeluxe is NOT a tool to easily install/update FPC…
See LongDirtyAnimAlf commented on 2 Dec 2021 Feature Request: Build last known good config · Issue #372 · LongDirtyAnimAlf/fpcupdeluxe · GitHub

Well, maybe only so for a clean minimal Laz, without any libraries, in particular without VTV and OPM, without sparta_mdi and then without Castle itself… Which defeats the purpose.

And it also is NOT compatible with Russian Windows, which does not help to diagnose errors on IDE recompilation.

Oh. Thanks, I didn’t know about this limitation of inline in Delphi.

I don’t think it applies to FPC (at least I never saw a warning/hint about it) though I didn’t test now. If you can test it, I would be interested whether this is Delphi-specific limit of inline or applies to both FPC and Delphi.

That’s a long thread, in which an initial simple request (“store GIT hash of the last FPC/Lazarus, before updating them”) seems to go into a long and offtopic discussion. I’m sorry, I am not able to analyze that now :slight_smile:

I see Don’s statement on Feature Request: Build last known good config · Issue #372 · LongDirtyAnimAlf/fpcupdeluxe · GitHub that “Fpcupdeluxe is not meant for nb.”. This is Ok. I agree, it’s not for newbies, newbies should use official installers. It doesn’t really change my good opinion about fpcupdeluxe or my advises on fpcupdeluxe | Castle Game Engine .

  • We don’t recommend fpcupdeluxe as your first way of getting FPC/Lazarus – it is easier to just download FPC/Lazarus from https://www.lazarus-ide.org/ , that’s what we recommend in CGE editor GUI and manual.

  • That said, if you want to get FPC/Lazarus from trunk, or with cross-compilers, it is definitely easier to use fpcupdeluxe than recompiling FPC by hand. Esp. because fpcupdeluxe auto-downloads the cross bin/libs.

So in my eyes, FpcUpDeluxe is

  • harder to use than an FPC/Lazarus installer from https://www.lazarus-ide.org/ , which is a typical installer most Windows users expect,

  • if you want to get FPC trunk, or with cross-compilers, and your choice is between FpcUpDeluxe and doing it by hand (downloading cross bin/libs, sometimes editing FPC config, running proper make command in FPC tree) → then FpcUpDeluxe is easier than “doing it by hand”.

Would it also work for updating FPC/Laz while keeping all the settings and 3rd party libraries?

I didn’t know about this limitation of inline in Delphi. I don’t think it applies to FPC (at least I never saw a warning/hint about it)

You should had written it a half-hour earlier cause i am sure i just saw it in one of my failed attempts to compile Laz 2.2 :slight_smile:

OTOH this is not specific to Delphi or FPC, it is inevitable fundamental lmitation for compilation strategy FPC and Delphi share. If you would want to reflect upon different compilation implementations it it becomes obvious. But… while it would not be a long as the aforementioned GitHub thread, yet would still need you to think deep. And i think you would prefer to sleep for now :slight_smile:

D:\fpcupdeluxe\lazarus\components\chmhelp\lhelp\lhelpcore.pas(936,9) Note: (6058) Call to subroutine "function GetDebugLogger:TLazLogger;" marked as inline is not inlined
D:\fpcupdeluxe\lazarus\components\chmhelp\lhelp\lhelpcore.pas(948,11) Note: (6058) Call to subroutine "function GetDebugLogger:TLazLogger;" marked as inline is not inlined
D:\fpcupdeluxe\lazarus\components\chmhelp\lhelp\lhelpcore.pas(956,7) Note: (6058) Call to subroutine "function GetDebugLogger:TLazLogger;" marked as inline is not inlined
D:\fpcupdeluxe\lazarus\components\chmhelp\lhelp\lhelpcore.pas(991,7) Note: (6058) Call to subroutine "function GetDebugLogger:TLazLogger;" marked as inline is not inlined

Sadly, FPC does not bother to explain WHY it refused to inline it, unlike Delphi…

okay, Laz 2.2.0 running…

castle-engine.exe , castle-view-image.exe , view3dscene.exe are compiled without icons, and at least one of them has .ico file in repo

the CodeTools now show different error - included file was not found

view3dscene.lpr(1225,48) Error: включаемый файл не найден “…\embedded_data\scenes\clear_scene.inc”

But it is the same crazy unreadable error box when i try to control-Enter on it.

However, while the error texts seems crazy, it is not without reasons,

d:\DelphiProjects\Libs\Games\castle-view3dscene\view3dscene.lpr
{$I ../embedded_data/scenes/clear_scene.inc}

What should it give us?

d:\DelphiProjects\Libs\Games\embedded_data\scenes\clear_scene.inc

And there is no such folder (you do not make Src or Sources subfolder in the project root folder) ! Correct path is different!

d:\DelphiProjects\Libs\Games\castle-view3dscene\embedded_data\scenes\clear_scene.inc

So you have to remove that ‘…’ from the include.

You copy-pasted it from files like
D:\DelphiProjects\Libs\Games\castle-view3dscene\code\v3dscenescreeneffects.pas
but forgot to amend the path.

I am really buffled it compiles - it should immediately give a fatal error! It seems a big in FPC that it does not fail compilation! And i don’t know how you can surely guard against such a compiler bug…

0001-fixing-wrong-INCLUDE-paths.patch (2.3 KB)

Not installed by default, but can be compiled in using fpcupdeluxe

https://wiki.freepascal.org/Project_Groups

Perhaps can be used to simplify manual installation

Those inputs for Project Caption and Main State Name, after i created the project is there GCE-native way to adjust them, some property editor or similar, or is editing Pascal source files the only way ?

Sorry, you didn’t really provide enough of an explanation :slight_smile:

And all my thinking tells me that inlining this is possible. An intelligent compiler should be able to do inline, even when implementation uses things only in the scope of implementation section. The generated code is effectively part of the interface, as far as PPU is concerned. And I heard that FPC indeed does this.

So I made a test, and indeed FPC does inline a function like

function ReturnVar: TObject;
begin
  Result := SomeVar;
end;

or even

function ReturnVar: TObject;
begin
  if SomeVar = nil then
    SomeVar := TObject.Create;
  Result := SomeVar;
end;

They are inlined, despite the fact that SomeVar is in the implementation section. And it doesn’t even need any FPC optimization option, or activating FPC “whole-program optimization”.

This can be seen by comparing assembler outputs (.s files) with and without the inline present.

Simple test shows that this reasoning applies to making UserConfig inline in CGE too. So

function UserConfig: TCastleConfig;
begin
  Result := FUserConfig;
end;

can be inlined in FPC.

My trivial test is on GitHub - michaliskambi/test-pascal-inline .

Good catch. Indeed, I don’t understand how it compiled :slight_smile: I found one more instance of it, and fixed in Fix inlines path (should not be "../embedded_data/..." when referred · castle-engine/[email protected] · GitHub . Thanks!

For project caption: Just edit the caption in CastleEngineManifest.xml (see CastleEngineManifest.xml - Syntax and Examples | Manual | Castle Game Engine docs) and then click on “Regenerate Project (overwrites LPI, DPR, DPROJ, CastleAutoGenerated)” menu item in th editor. This will regenerate castleautogenerated.pas unit that contains this caption in Pascal.

We plan to enable editing pretty much everything in CastleEngineManifest.xml via a GUI in CGE editor of course some day. And the need for clicking “Regenerate Project (overwrites LPI, DPR, DPROJ, CastleAutoGenerated)” should one day disappear too, it may be just done automatically.

As for state name: There is no simple project-wide option to “rename the main state” once it has been created (yet). Maybe we’ll add an editor utility to rename any state one day. Right now, just rename the Pascal file, design file, and the class name inside:

  • code/gamestatemain.pascode/gamestatexxx.pas
  • data/gamestatemain.castle-user-interfacedata/gamestatexxx.castle-user-interface
  • class TStateMain → TStateXxx

Note that you don’t really have to make all these 3 renames. It is a convention, nothing more, that we keep these things (Pascal unit name, design file name, class name) consistent. You could go with a different approach (you can e.g. keep one or more states in a unit like MyStates or whatever) and it will still work.