work on shutdown process and tidying

This commit is contained in:
Eric 2023-08-23 09:16:41 -07:00
parent 26d5295b59
commit 0bdf00769e
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
16 changed files with 200 additions and 120 deletions

88
.efrocachemap generated
View File

@ -4068,50 +4068,50 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "242acbe77fb4b4dba000a4f2bfc05628",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "b3b950f7aef84bdcb905bc4862bc46c0",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5bf6ff933f1202a16e59caab2614e7f5",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "5985564e7dcc9b37819c01f5617e07f5",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "3d490eb1e54ac4813f287c7aae7611cc",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "2cb1bebe253965580beacbc18aab4d19",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "39df8c4bf25de958ba7e0669b24fa851",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1dd9de26acbf937ded40fdd1e31ba213",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "9b6675625e5d11bfbdb79156533b5e7a",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "c204a8de7b8b28ba0f8669d0b2de0828",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3f62aa7d31a097a92404c022510f975b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "724b0e3118a0fae86ab3686efc82a1f0",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "129aa7848d1bb8c5d9e1151185f752d6",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "20b89b0333e5de59becfe21c2092300c",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5003b2740aed1c69b8296e5179d22d5b",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "d1e14b32cc026901a4e11c9e8c1715f1",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "2adbd526ecb26eba04c5165361c0a397",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "e7a3152446ef0fc03fc80609c25c824d",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "80fac001fbe4c6c3dcd9e64e38712394",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "61db43d2ee6123f4bdbb2a56eec29166",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "9cb423dc66c25d32365cf579bdb0ad48",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "dc03331ceb9a0bb57d74e6ab3ce69f16",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "9cb423dc66c25d32365cf579bdb0ad48",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "dc03331ceb9a0bb57d74e6ab3ce69f16",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "0a9803fd6e8750a0bec5036d848216a1",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "e353417db3536ee90e579b22f4eddb3e",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "0a9803fd6e8750a0bec5036d848216a1",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "e353417db3536ee90e579b22f4eddb3e",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "4cce38fc08e6a9aa47e0c57b23c930b5",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "5dd00571bd5aa72a4276d1b53cab4b2b",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "4cce38fc08e6a9aa47e0c57b23c930b5",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "5dd00571bd5aa72a4276d1b53cab4b2b",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "faf824b0fd529e4bb24bf633eba3ac0d",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "f3f34fa0cd21bd378fa5711c627a9698",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1272aaa24cce371db94f38661c8ab4f8",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "f3f34fa0cd21bd378fa5711c627a9698",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "b9ab40b7b1727328dd008b79397cafc4",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "80f77141b09264716c711d4c30190fc1",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "804a5e69223bb06d670ce6796526dee3",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "463170bfd59637e3b85bdbb7efd722ac",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "1acf5026c56619b9b73b32940be377f0",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f3244a1acf2f49587c28a18852e09121",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "e2faf9da55a00991bfe97d052556b4fa",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "8ee526c52e834f8d29244a0f37e33183",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "372da2c7dbe0b51ab8f738ac49f34d9a",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "29f810028429f10574471ad85cdc9044",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "70ee4f5892e693e209d8a75420292ad0",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "fc0465f8ffcaf843859ee9def7e90b22",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "916f4d2fcf14d7e973694848602736c5",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "e20ef3249191a24b428fd30b585a6ab9",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "c1b483c4c1639af5ad247e9252f51956",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "742d5e4793a557f7d322267cdf25fde3",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "4880ca58a6b9ce36769657c0f8a5a4c5",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "c8084478951a16ba144f12d65386b9b3",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "06c0d46f6b991aed566a17d32c0cd85d",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "77607a1c853c968a04340e538c196f4d",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "358193a334d56860d284716432c95f1e",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "ee39adeed9e2f6405c83f5f81ccf54fc",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9bc9ffe2da1a79524eb26a551ee50ba3",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ed1c7c6769b381526f5ac8d9e16a8bad",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ddce8a5ebc89ad56f23b24e2b04a5edc",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "8dc47367a8feb2908244f4b45ef332e8",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d8fd33af6124baf1bfd8ab39372abf17",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "78801f3a9a811c0e62528b60b78e36e1",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "ee6e1bdccf0f3db9c198ba5632739103",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "2f84ca77788e244cdc3edaeb00a0dc4c",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "ee6e1bdccf0f3db9c198ba5632739103",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "2f84ca77788e244cdc3edaeb00a0dc4c",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "61c0c1aac4376682c8bd77ad7d279b3a",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "f6a37946765a6a866c9f894c4e7bb15c",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "61c0c1aac4376682c8bd77ad7d279b3a",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "f6a37946765a6a866c9f894c4e7bb15c",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "d18be4e09ecb9dbe9e299dcfc7183cdf",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "fdcaa83411b0ac9e165ab5b41552e03a",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "d18be4e09ecb9dbe9e299dcfc7183cdf",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "fdcaa83411b0ac9e165ab5b41552e03a",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "bb7515a54eaab2d148575800c1250c47",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "e0c3972bcc77fa5fc5aed5802308b4b1",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "89cd2bd873934be3e46f409663e9c2cb",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "e0c3972bcc77fa5fc5aed5802308b4b1",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "89423e0c466b20a5bfbd660d85607264",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "0b1921de7f4505e9ad177b0be5fc5cb5",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6fae4927a00f7e78822e1efdac4c421d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "11178659f946fde59ad43af0c8a8aaac",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "59fa8ce09122d57e9ca64d28401f6f4a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "9f2ada0e934bba54e04924f389243d09",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1b5ca2f7ef5b934946d55486fe08bee3",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9d03b912cadc179744712665bdeaf866",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "eeddad968b176000e31c65be6206a2bc",

View File

@ -1,21 +1,34 @@
### 1.7.26 (build 21241, api 8, 2023-08-22)
### 1.7.26 (build 21244, api 8, 2023-08-23)
- Android should now be better at detecting hardware keyboards (you will see
'Configure Keyboard' and 'Configure Keyboard P2' buttons under
Settings->Controllers if a hardware keyboard is detected). It can be a bit
tricky distinguishing between gamepad type devices and keyboards on Android,
so please holler if you have a gamepad that now suddenly thinks it is a
keyboard or anything like that.
- Various general improvements to the pcommand (project command) system.
- Modules containing pcommand functions are now named with an 's' - so
`pcommands.py` instead of `pcommand.py`. `pcommand.py` in efrotools is now
solely related to the functioning of the pcommand system.
- Implemented the `pcommandbatch` system, which is a way to run pcommands using
a simple local server/client architecture, and set up key build targets to use
it instead of regular pcommand. In some cases, such as when assembling build
assets, this can speed things up by 5x or so. If you run into any problems
that seem to be related to this, you can disable it by setting env var
`BA_PCOMMANDBATCH_DISABLE=1`. See docs in `tools/efrotools/pcommandbatch.py`
for more info.
that by default instead of regular pcommand. In some cases, such as when
assembling build assets, this can speed things up by 5x or so. Run `make
pcommandbatch_speed_test` to see what the theoretical biggest speedup is on
your system. If you run into any problems that seem to be related to this, you
can disable it by setting env var `BA_PCOMMANDBATCH_DISABLE=1` which will
cause everything to go use regular old pcommand. See docs in
`tools/efrotools/pcommandbatch.py` for more info.
- Renamed the various `App` C++ classes to `AppAdapter` which better represents
their current intended role. They are not a general interface to app
functionality, but rather adapt the app to a particular paradigm or api (VR,
Headless, SDL GUI, etc.). Am trying to move any functionality out of those
classes that does not fit that definition.
Headless, SDL GUI, etc.). Also am trying to move any functionality out of
those classes that does not fit that definition.
- Started cleaning up the app exit process. This will allow the app to
gracefully run tasks such as syncing account data to the cloud or disk or
properly closing the audio system when shutting down. It also means there
should be more consistent use of the 'Quit?' confirm window. Please holler if
you see any odd behavior when trying to quit the app.
### 1.7.25 (build 21211, api 8, 2023-08-03)

View File

@ -290,6 +290,7 @@ class App:
self._pending_intent: AppIntent | None = None
self._intent: AppIntent | None = None
self._mode: AppMode | None = None
self._shutdown_task: asyncio.Task[None] | None = None
# Controls which app-modes we use for handling given
# app-intents. Plugins can override this to change high level
@ -705,11 +706,11 @@ class App:
# pylint: disable=too-many-branches
assert _babase.in_logic_thread()
if self._shutdown_called:
# Can't shut down until we've got our asyncio machinery spun up.
if self._shutdown_called and self._aioloop is not None:
# Entering shutdown state:
if self.state is not self.State.SHUTTING_DOWN:
self.state = self.State.SHUTTING_DOWN
_babase.lifecyclelog('app state shutting down')
self._on_app_shutdown()
elif self._app_paused:
@ -748,6 +749,17 @@ class App:
self._called_on_app_launching = True
self._on_app_launching()
async def _shutdown(self) -> None:
import asyncio
try:
# print('SHUTDOWN BEGIN')
await asyncio.sleep(0.0)
# print('SHUTDOWN END')
except Exception:
logging.exception('Error during shutdown.')
_babase.complete_shutdown()
def pause(self) -> None:
"""Should be called by the native layer when the app pauses."""
assert not self._app_paused # Should avoid redundant calls.
@ -761,7 +773,13 @@ class App:
self._update_state()
def shutdown(self) -> None:
"""Should be called by the native layer when the app wants to quit."""
"""Called by the native layer when the app wants to quit.
The app should use this notice to start cleaning up and shutting
down. Once shutdown is complete, it should call
_babase.complete_shutdown() which will trigger an actual exit
from the app.
"""
self._shutdown_called = True
self._update_state()
@ -806,6 +824,10 @@ class App:
'Error in on_app_shutdown for subsystem %s.', subsystem
)
# Now kick off any async shutdown task(s).
assert self._aioloop is not None
self._shutdown_task = self._aioloop.create_task(self._shutdown())
def read_config(self) -> None:
"""(internal)"""
from babase._appconfig import read_app_config

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21241
TARGET_BALLISTICA_BUILD = 21244
TARGET_BALLISTICA_VERSION = '1.7.26'

View File

@ -12,6 +12,7 @@
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/base_python.h"
#include "ballistica/base/support/stress_test.h"
#include "ballistica/base/ui/ui.h"
#include "ballistica/core/platform/core_platform.h"
#include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/python/python.h"
@ -159,7 +160,9 @@ void AppAdapterSDL::HandleSDLEvent(const SDL_Event& event) {
#endif
case SDL_QUIT:
g_base->logic->event_loop()->PushCall([] { g_base->logic->Shutdown(); });
// g_base->logic->event_loop()->PushCall([] { g_base->logic->Shutdown();
// });
g_base->logic->event_loop()->PushCall([] { g_base->ui->ConfirmQuit(); });
break;
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD && !BA_HEADLESS_BUILD

View File

@ -14,6 +14,7 @@
#include "ballistica/base/support/app_config.h"
#include "ballistica/base/ui/console.h"
#include "ballistica/base/ui/ui.h"
#include "ballistica/shared/buildconfig/buildconfig_common.h"
#include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/generic/utils.h"
@ -963,16 +964,16 @@ void Input::HandleKeyPress(const SDL_Keysym* keysym) {
if (!g_buildconfig.ostype_ios_tvos() && !g_buildconfig.ostype_android()) {
// Command-F or Control-F toggles full-screen.
if (!repeat_press && keysym->sym == SDLK_f
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) { // NOLINT
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) {
g_base->python->objs()
.Get(BasePython::ObjID::kToggleFullscreenCall)
.Call();
return;
}
// Command-Q or Control-Q quits.
if (!repeat_press && keysym->sym == SDLK_q
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) { // NOLINT
// Control-Q quits. On mac, the usual cmd-q gets handled by SDL/etc.
// implicitly.
if (!repeat_press && keysym->sym == SDLK_q && (keysym->mod & KMOD_CTRL)) {
g_base->ui->ConfirmQuit();
return;
}
@ -987,7 +988,7 @@ void Input::HandleKeyPress(const SDL_Keysym* keysym) {
// Ctrl-V or Cmd-V sends paste commands to any interested text fields.
// Command-Q or Control-Q quits.
if (!repeat_press && keysym->sym == SDLK_v
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) { // NOLINT
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) {
g_base->ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste));
return;
}

View File

@ -128,28 +128,58 @@ void Logic::OnAppResume() {
g_base->python->OnAppResume();
}
void Logic::Shutdown() {
assert(g_base->InLogicThread());
assert(g_base->IsAppStarted());
if (!shutting_down_) {
shutting_down_ = true;
OnAppShutdown();
}
}
void Logic::OnAppShutdown() {
assert(g_core);
assert(g_base->CurrentContext().IsEmpty());
assert(shutting_down_);
g_core->LifecycleLog("app state shutting down");
// Nuke the app from orbit if we get stuck while shutting down.
g_core->StartSuicideTimer("shutdown", 10000);
// Note: keep these in opposite order of OnAppStart.
// Let our subsystems know we're shutting down.
// Note: Keep these in opposite order of OnAppStart.
// Note2: Any shutdown processes that take a non-zero amount of time
// should be registered as shutdown-tasks
g_base->python->OnAppShutdown();
if (g_base->HavePlus()) {
g_base->plus()->OnAppShutdown();
}
g_base->app_mode()->OnAppShutdown();
g_core->platform->OnAppResume();
g_core->platform->OnAppShutdown();
g_base->ui->OnAppShutdown();
g_base->input->OnAppShutdown();
g_base->audio->OnAppShutdown();
g_base->graphics->OnAppShutdown();
}
void Logic::CompleteShutdown() {
BA_PRECONDITION(g_base->InLogicThread());
BA_PRECONDITION(shutting_down_);
BA_PRECONDITION(!shutdown_completed_);
shutdown_completed_ = true;
OnAppShutdownComplete();
}
void Logic::OnAppShutdownComplete() {
assert(g_base->InLogicThread());
// Wrap up any last business here in the logic thread and then
// kick things over to the main thread to exit out of the main loop.
g_core->LifecycleLog("app shutdown complete");
// FIXME: Should add a mechanism where we give the above subsystems
// a short bit of time to complete shutdown if they need it.
// For now just completing instantly.
g_core->main_event_loop()->PushCall([] { g_base->OnAppShutdownComplete(); });
}
@ -592,15 +622,6 @@ void Logic::NotifyOfPendingAssetLoads() {
UpdatePendingWorkTimer();
}
void Logic::Shutdown() {
assert(g_base->InLogicThread());
if (!g_core->shutting_down) {
g_core->shutting_down = true;
OnAppShutdown();
}
}
auto Logic::NewAppTimer(millisecs_t length, bool repeat,
const Object::Ref<Runnable>& runnable) -> int {
// App-Timers simply get injected into our loop and run alongside our own

View File

@ -44,6 +44,7 @@ class Logic {
void OnAppResume();
void OnAppShutdown();
void OnAppShutdownComplete();
void OnAppModeChanged();
@ -55,14 +56,14 @@ class Logic {
/// graphical builds we also use this opportunity to step our logic.
void Draw();
/// Kick off a low level app shutdown which will result in the process
/// exiting. Platform-agnostic code should generally not call this
/// directly and should instead use high level calls like babase.quit().
/// This allows platforms such as mobile to take alternate actions which
/// may involve leaving the underlying process running. FIXME: I feel like
/// this should be in one of the App classes.
/// Kick off an app shutdown. Shutdown is an asynchronous process which
/// may take a bit of time to complete. Safe to call repeatedly.
void Shutdown();
/// Should be called by the Python layer when it has completed all
/// shutdown related tasks.
void CompleteShutdown();
/// Has CompleteAppBootstrapping been called?
auto app_bootstrapping_complete() const {
return app_bootstrapping_complete_;
@ -95,6 +96,8 @@ class Logic {
}
auto applied_app_config() const { return applied_app_config_; }
auto shutting_down() const { return shutting_down_; }
auto shutdown_completed() const { return shutdown_completed_; }
private:
void UpdateDisplayTimeForFrameDraw();
@ -127,6 +130,8 @@ class Logic {
bool have_pending_loads_{};
bool debug_log_display_time_{};
bool applied_app_config_{};
bool shutting_down_{};
bool shutdown_completed_{};
};
} // namespace ballistica::base

View File

@ -68,6 +68,28 @@ static PyMethodDef PyRunAppDef = {
"manages its own event loop.",
};
// --------------------------- complete_shutdown -------------------------------
static auto PyCompleteShutdown(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
assert(g_base);
g_base->logic->CompleteShutdown();
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyCompleteShutdownDef = {
"complete_shutdown", // name
(PyCFunction)PyCompleteShutdown, // method
METH_NOARGS, // flags
"complete_shutdown() -> None\n"
"\n"
"Complete the shutdown process, triggering the app to exit.\n",
};
// -------------------------------- appnameupper -------------------------------
static auto PyAppNameUpper(PyObject* self) -> PyObject* {
@ -484,6 +506,8 @@ static PyMethodDef PyDisplayTimerDef = {
static auto PyQuit(PyObject* self, PyObject* args, PyObject* keywds)
-> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->IsAppStarted());
static const char* kwlist[] = {"soft", "back", nullptr};
int soft = 0;
int back = 0;
@ -492,7 +516,7 @@ static auto PyQuit(PyObject* self, PyObject* args, PyObject* keywds)
return nullptr;
}
// FIXME this should all just go through platform.
// FIXME this should all just go through platform and/or app-adapter.
if (g_buildconfig.ostype_ios_tvos()) {
// This should never be called on iOS
@ -503,9 +527,6 @@ static auto PyQuit(PyObject* self, PyObject* args, PyObject* keywds)
// A few types get handled specially on Android.
if (g_buildconfig.ostype_android()) {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "ConstantConditionsOC"
if (!handled && back) {
// Back-quit simply synthesizes a back press.
// Note to self: I remember this behaved slightly differently than
@ -514,8 +535,6 @@ static auto PyQuit(PyObject* self, PyObject* args, PyObject* keywds)
handled = true;
}
#pragma clang diagnostic pop
if (!handled && soft) {
// Soft-quit just kills our activity but doesn't run app shutdown.
// Thus we'll be able to spin back up (reset to the main menu)
@ -1517,6 +1536,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
PyEmptyAppModeHandleIntentDefaultDef,
PyEmptyAppModeHandleIntentExecDef,
PyGetImmediateReturnCodeDef,
PyCompleteShutdownDef,
};
}

View File

@ -42,7 +42,7 @@ void StdioConsole::StartInMainThread() {
// results of the last script-command message we may have just sent.
if (stdin_is_terminal) {
g_base->logic->event_loop()->PushCall([] {
if (!g_core->shutting_down) {
if (!g_base->logic->shutting_down()) {
printf(">>> ");
fflush(stdout);
}
@ -97,7 +97,7 @@ void StdioConsole::StartInMainThread() {
if (g_buildconfig.windows_console_build()) {
core::CorePlatform::SleepMillisecs(250);
}
if (!g_core->shutting_down) {
if (!g_base->logic->shutting_down()) {
printf("Stdin EOF reached. Use Ctrl-C to quit.\n");
fflush(stdout);
}

View File

@ -342,29 +342,24 @@ void UI::ShowURL(const std::string& url) {
void UI::ConfirmQuit() {
g_base->logic->event_loop()->PushCall([] {
assert(g_base->InLogicThread());
if (g_core->HeadlessMode()) {
Log(LogLevel::kError, "UI::ConfirmQuit() unhandled on headless.");
// If we're headless or input is locked or the in-app-console is up or
// we don't have ui-v1, just quit immediately; a confirm screen
// wouldn't work anyway.
if (g_core->HeadlessMode() || g_base->input->IsInputLocked()
|| !g_base->HaveUIV1()
|| (g_base->console() != nullptr && g_base->console()->active())) {
g_base->logic->Shutdown();
// g_base->python->objs().Get(BasePython::ObjID::kQuitCall).Call();
return;
} else {
// If input is locked or the in-app-console is up or we don't have ui-v1,
// just quit immediately; a confirm screen wouldn't work anyway.
if (g_base->input->IsInputLocked() || !g_base->HaveUIV1()
|| (g_base->console() != nullptr && g_base->console()->active())) {
// Just go through _babase.quit().
// FIXME: Shouldn't need to go out to the Python layer here;
// once we've got a high level quit call in platform we can use
// that directly.
g_base->python->objs().Get(BasePython::ObjID::kQuitCall).Call();
return;
} else {
ScopedSetContext ssc(nullptr);
g_base->audio->PlaySound(g_base->assets->SysSound(SysSoundID::kSwish));
g_base->ui_v1()->DoQuitWindow();
ScopedSetContext ssc(nullptr);
g_base->audio->PlaySound(g_base->assets->SysSound(SysSoundID::kSwish));
g_base->ui_v1()->DoQuitWindow();
// If we have a keyboard, give it UI ownership.
InputDevice* keyboard = g_base->input->keyboard_input();
if (keyboard) {
g_base->ui->SetUIInputDevice(keyboard);
}
// If we have a keyboard, give it UI ownership.
InputDevice* keyboard = g_base->input->keyboard_input();
if (keyboard) {
g_base->ui->SetUIInputDevice(keyboard);
}
}
});

View File

@ -52,13 +52,14 @@ class UI {
/// called from any thread.
void ShowURL(const std::string& url);
/// High level call to request a quit ui (or in some cases quit
/// immediately). This can be called from any thread.
/// High level call to request a quit ui. When a UI can't be shown,
/// triggers an immediate shutdown. This can be called from any thread.
void ConfirmQuit();
/// Return whether there is UI present in either the main or overlay
/// stacks. Generally this implies the focus should be on the UI.
auto MainMenuVisible() const -> bool;
auto PartyIconVisible() -> bool;
void ActivatePartyIcon();
void HandleLegacyRootUIMouseMotion(float x, float y);

View File

@ -160,7 +160,6 @@ class CoreFeatureSet {
bool v1_cloud_log_full{};
int master_server_source{};
int session_count{};
bool shutting_down{};
bool have_incentivized_ad{false};
bool should_pause{};
bool reset_vr_orientation{};

View File

@ -645,19 +645,19 @@ auto CorePlatform::GetTextTextureData(void* tex) -> uint8_t* {
}
void CorePlatform::OnAppStart() {
// assert(g_base_soft && g_base_soft->InLogicThread());
assert(g_base_soft && g_base_soft->InLogicThread());
}
void CorePlatform::OnAppPause() {
// assert(g_base_soft && g_base_soft->InLogicThread());
assert(g_base_soft && g_base_soft->InLogicThread());
}
void CorePlatform::OnAppResume() {
// assert(g_base_soft && g_base_soft->InLogicThread());
assert(g_base_soft && g_base_soft->InLogicThread());
}
void CorePlatform::OnAppShutdown() {
// assert(g_base_soft && g_base_soft->InLogicThread());
assert(g_base_soft && g_base_soft->InLogicThread());
}
void CorePlatform::OnScreenSizeChange() {

View File

@ -1470,7 +1470,7 @@ void SceneV1AppMode::HandleGameQuery(const char* buffer, size_t size,
void SceneV1AppMode::RunMainMenu() {
assert(g_base->InLogicThread());
if (g_core->shutting_down) {
if (g_base->logic->shutting_down()) {
return;
}
assert(g_base->InLogicThread());

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21241;
const int kEngineBuildNumber = 21244;
const char* kEngineVersion = "1.7.26";
#if BA_MONOLITHIC_BUILD