Hi all! Today we announce a number of improvements for mobile (Android, iOS) development. They’ve been done while testing:
- Recently announced Castle Model Viewer on Android, see news.
-
Updated Game Services Demo on Google Play.
-
Updated Darkest Before the Dawn. A really old game developed using Castle Game Engine. Updated – no ads, use latest engine, released again on Google Play! Historically, this is the first game made for Android using Castle Game Engine, in 2013.
( Missed anything? See all Castle Game Engine applications on Google Play. )
Onward to engine improvements around the mobile:
-
TCastleContainer.SafeBorder
— new property, working on both iOS and Android, exposing the safe area on screen edges where you should not draw anything important/clickable, because the system itself may draw important/clickable stuff on top of your application there.For example the system clock/battery/network state take space on top. The software home/back buttons may be on the bottom. Notch are present on some phones which obscure some part of some edge. See Android docs for display cutouts, and here how these displays look like. There are a few terms more-or-less interchangeable for this: safe area, insets, display cutouts on Android, status bar/bottom bar on iOS.
Usually these are non-zero at top and bottom, but
TCastleContainer.SafeBorder
allows us to expose safe areas on potentially any screen side. Underlying API on Android actually gets all 4 sides. (Current code on iOS only queries for top safe area now, but we can improve it.)We also exposed
TCastleContainer.OnSafeBorderChanged
to notify about safe area changes. This is important, as applications dynamically switch orientation and/or enter/exit immersive fullscreen modes. So to supportTCastleContainer.SafeBorder
perfectly, make sure to react toTCastleContainer.OnSafeBorderChanged
events.Our inspector (F8 on desktop, hold 3 fingers for 1 second on mobile) also shows them, as red bars.
They behave OK with switchable orientations (portrait, landscape), phones and tablets and all supported Android versions, and it doesn’t break our behavior on fullscreen_immersive. This was some work to test 🙂
How to actually support them — you need to move / enlarge your UI, to leave an extra space at the respective screen edges. You can move your UI (
TCastleUserInterface.Translation
), you can enlarge it (TCastleUserInterface.Height
), you can use UI borders (TCastleUserInterface.Border
), you can use padding available on some controls, you can also just add a solid-colored rectangle just for the sake of these insets. There’s no “automatic” answer, as you see — what to do depends on what UI you display. You can take a look what Castle Model Viewer for mobile does. -
We have a new UI scaling method
usEncloseReferenceSizeAutoOrientation
. It is very similar tousEncloseReferenceSize
, but automatically “flips” the reference width/height based on whether the current window sizes indicate portrait or landscape orientation. This means that UI controls have the same physical (real) size as your application orientation changes at runtime (e.g. because you support both portrait and landscape, and user just rotated the device).Designing for it is a bit more work. You have to account for both modes, portrait and landscape, as they result in different reference sizes. Your UI must fit sensibly in both cases.
It is used by Castle Model Viewer for mobile so you can test it out and see how it works.
-
Gestures done with 2 fingers (on mobile) to zoom (pinch) and move (pan) with
TCastleExamineNavigation
have been quite improved. The code was simplified, the gestures now “kick in” instantly and they switch between pinch / pan dynamically, so you can effectively do both pinch and pan without releasing your fingers. This results in UX that feels much better to user.Again Castle Model Viewer for mobile is an example how it works. Run it and use 2 fingers e.g. on sample cat model to zoom/move it.
-
photo_service on Android was reimplemented to use modern approach on new Android devices and place the images reliably such that they appear in default “Photos” application.
Using it is really trivial, just call
TPhotoService.StoreImage
. The full code (from castle-model-viewer-mobile) is:procedure TViewDisplayScene.ClickScreenshot(Sender: TObject); var Image: TRGBImage; ImageUrl: String; begin .. Image := Container.SaveScreen; try ImageUrl := FileNameAutoInc(ApplicationConfig('screenshots/'), 'screenshot_%d.png'); SaveImage(Image, ImageUrl); TPhotoService.StoreImage(ImageUrl); finally FreeAndNil(Image) end; ... end;
-
We fixed saving files, when the subdirectory of the target file doesn’t exist. Our handler for saving to
file:/
protocol now creates directory automatically.This makes sense for our engine, because we don’t want you to care about need for
ForceDirectories
and similar calls, because we don’t want you to usually care whether the protocol you use isfile:/
or something else. We also don’t want you to depend on whetherApplicationConfig
returns URL withfile:/
protocol or something else (like future plannedcastle-config:/...
). We also want constructions likeSaveImage(..., ApplicationConfig('some_subdirectory/') + 'yet_another_subdirectory/foo.png');
to work automatically.A sample application is test_config_subdir.
-
We improved our Android documentation page (again — this seems to be most often updated documentation page of our website in 2024, maybe aside from roadmap 🙂 ). Simplified, and clearly recommends Android Studio. We work hard to make the Android process very simple and documented. At this point, installing Android Studio (not only Android command-line tools) is the best approach, IMHO — it has Java version that always works, has GUI-friendly access to emulators, mirroring, accepting licenses…
-
We improved our Android FAQ about emulator usage.
-
We improved our Android services list, to list all services and clearly specify which services are usually added automatically to the project.
That’s all, for this news announcement! We have a ton of new stuff, brace yourselves for more news 🙂 If you like this, we appreciate your support on Patreon, or other financial support , or other contributions. Reposting / resharing the news about our engine to interested people / places is in particular always appreciated!