mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-19 21:37:57 +08:00
v1.7.26
This commit is contained in:
parent
4cf54d4f85
commit
82aa76b29b
92
.efrocachemap
generated
92
.efrocachemap
generated
@ -4064,54 +4064,54 @@
|
||||
"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": "2ce43921f1917e4face2bd89de255c89",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "cfad36d58003989bd3fb758d72900914",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "11a8f7317dafd295f43e5b8573b21caa",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "dca6448b3d8f3acd46632f103d270b38",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "dcf48e1ee93b7a747b0c33efca58057a",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "b568da36b6a2ee329e31ff321df54810",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b9e6b511c5fea84b0a81335fd3000592",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ec94eec1e4c1084535c65e9923de87d6",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d53c169951686dd96a85668def6dbbfc",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "b46e409cb87de94f6cf6f7d3e10e032f",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "4692a22e7ddaf15e34157325252b5fb3",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d0ab73deaa89dd9fa1b75c65d463d293",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3db746bb01e002fee667c70c6f57f928",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "10c06bd2c02a9b2ac488993e2ffc6700",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "01a466465933b84f3772e9d274ee9c40",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "3d3233606e03eb3b8ffe04169a5f2fce",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c59aeaf8686b4008d0b11728a0523397",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "92dcffd261cfe8bf80806ebc765bb323",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "57639e6862d409cf39ad2fd609aafb20",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "fa7a86c50be523dcb7ff6aadb9d79d0e",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d16860bc4d3ff0abae745e2fd5638149",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "620ed03a89ad8053656a466da6053676",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d16860bc4d3ff0abae745e2fd5638149",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "620ed03a89ad8053656a466da6053676",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "642d380b38d5fd4a5f50a331579e6e9c",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a767b4b9d20e61e0a6fb7289660959e9",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "642d380b38d5fd4a5f50a331579e6e9c",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a767b4b9d20e61e0a6fb7289660959e9",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "fecd29b4aff2924b2403f36996cdca93",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "9aea5093bb559d64e28edc3c112b06b2",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "fecd29b4aff2924b2403f36996cdca93",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "9aea5093bb559d64e28edc3c112b06b2",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "8ce1ea0d1d64dac282100599159ad2a3",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "adf78a2ab5fb271d83e80fb72b68784f",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "864807f34140eed4dada8832878a1173",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "adf78a2ab5fb271d83e80fb72b68784f",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8d271eb87a692db53219288d762a5194",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "3a2e88e7788e47cc86ac87df0ea46ce3",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "d0db9d64f7ff618cb6a62f59a70a00f0",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "308f59dbc2f3193b1adb321db9a09ff1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "d66fe8cbfcd4d472ff3536c274f2a8d4",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "89d7812f28754a00ad797bb994c81846",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "ea8906f5c66ba5606bff77e8e57f3ade",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d117fce0b21244310ce6771a29c237be",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "bb5e0df17efe96476c3c2b8c41c7979b",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "056115be35ac1afc1f62b58dcc8f217a",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "cf2b052caaa06d512ef379687b3aff86",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "97b8d5f261f84b8047d43df1ca81777a",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "f304ee46675e7552c31e174d81199307",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "70b54361b557f5e8d4271a0c976b28b6",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "06c778dc4c2772acf6dbaf67eb7321c9",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "212a5c7206c1aa9a8427b61471e9e89b",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f3a1028602c7bbd3f8d62bd843af628d",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "9c4c6d1c50e225dc61cfbab4a82a37a6",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "4db4b600478f1767fdd0462a137912de",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "628bc102cf6ef17b38804c4c9baa5265",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "fb9d165ab24084e8beaa6d7c51c81a77",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "ae88283e96a9238aab7561d2afcd9a5f",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e5fe958377b8dcf5d5203dbd17aaab72",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "f22e8af184b19b4929162e901a056454",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "5fa2cb24b9e78bddb1bf9efb197d0c51",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d36f11acfa5e68f303d347c3895979d0",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "570a7e325c15ecebcc419d48a046dd24",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "3155f665993e5f850db5b87c9296abe7",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d1bfae5e75824ba89338892bc0f84c6b",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b1466048e319c0d60139c46751f3eb79",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d1bfae5e75824ba89338892bc0f84c6b",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "b1466048e319c0d60139c46751f3eb79",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "656176631037184b6e22b0b68c3cd1fa",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "12b633db4dad37bbb5a5c398db0c10dd",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "656176631037184b6e22b0b68c3cd1fa",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "12b633db4dad37bbb5a5c398db0c10dd",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "7e014214c6cb9ddaa0e95f5186ba9df6",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "45ddc559dd5ef563d2df5c5db9c9fbc0",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "7e014214c6cb9ddaa0e95f5186ba9df6",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "45ddc559dd5ef563d2df5c5db9c9fbc0",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "1a15bf7d809addab4992827da9d89895",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "a1e03b7d13482beab8852691b5698974",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "807e3629d9d4611cd93feb87face4e51",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "a1e03b7d13482beab8852691b5698974",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f7bc04993982b164f6e86ad6ce350ef",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d24102dd35c29b6a77cdf3d9921695da",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "8edef08a22594617d2b4273e0e4cba40",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "cb6c0c6efad034b53fe1a8f930f2ce81",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "3ec4aadf128132116fc5479a46bd1f71",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "14c2cf0812e3022391caffd9409d0650",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "67c207425afc5023cea9740e3bd459c3",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "7219b9034f14c5b769818b80135ea61b",
|
||||
"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": "ad5475b871dadc69bc2cf8ccac550878",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "ef931ec35861d4ad37850b7278588922",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "ad347097a38e0d7ede9eb6dec6a80ee9",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "077bf63282b23d1880287200c9f6035f",
|
||||
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
||||
"src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69",
|
||||
"src/ballistica/core/mgen/pyembed/env.inc": "8be46e5818f360d10b7b0224a9e91d07",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
### 1.7.26 (build 21250, api 8, 2023-08-23)
|
||||
### 1.7.26 (build 21256, api 8, 2023-08-25)
|
||||
|
||||
- Android should now be better at detecting hardware keyboards (you will see
|
||||
'Configure Keyboard' and 'Configure Keyboard P2' buttons under
|
||||
@ -24,14 +24,19 @@
|
||||
functionality, but rather adapt the app to a particular paradigm or api (VR,
|
||||
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
|
||||
- Started cleaning up the app shutdown 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.
|
||||
- Unix TERM signal now triggers graceful app shutdown.
|
||||
- Added `ba.app.add_shutdown_task()` to register coroutines to be run as part of
|
||||
shutdown.
|
||||
- Removed `babase.app.iircade_mode`. RIP iiRcade :(.
|
||||
- Changed `AppState.INITIAL` to `AppState.NOT_RUNNING`, added a
|
||||
`AppState.NATIVE_BOOTSTRAPPING`, and changed `AppState.LAUNCHING` to
|
||||
`AppState.INITING`. These better describe what the app is actually doing while
|
||||
in those states.
|
||||
|
||||
### 1.7.25 (build 21211, api 8, 2023-08-03)
|
||||
|
||||
|
||||
@ -128,7 +128,7 @@ class AccountV2Subsystem:
|
||||
# Ok; no workspace to worry about; carry on.
|
||||
if not self._initial_sign_in_completed:
|
||||
self._initial_sign_in_completed = True
|
||||
_babase.app.on_initial_sign_in_completed()
|
||||
_babase.app.on_initial_sign_in_complete()
|
||||
|
||||
def on_active_logins_changed(self, logins: dict[LoginType, str]) -> None:
|
||||
"""Should be called when logins for the active account change."""
|
||||
@ -163,7 +163,7 @@ class AccountV2Subsystem:
|
||||
"""
|
||||
if not self._initial_sign_in_completed:
|
||||
self._initial_sign_in_completed = True
|
||||
_babase.app.on_initial_sign_in_completed()
|
||||
_babase.app.on_initial_sign_in_complete()
|
||||
|
||||
@staticmethod
|
||||
def _hashstr(val: str) -> str:
|
||||
@ -409,7 +409,7 @@ class AccountV2Subsystem:
|
||||
def _on_set_active_workspace_completed(self) -> None:
|
||||
if not self._initial_sign_in_completed:
|
||||
self._initial_sign_in_completed = True
|
||||
_babase.app.on_initial_sign_in_completed()
|
||||
_babase.app.on_initial_sign_in_complete()
|
||||
|
||||
|
||||
class AccountV2Handle:
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from enum import Enum
|
||||
import logging
|
||||
from enum import Enum
|
||||
from typing import TYPE_CHECKING
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from functools import cached_property
|
||||
@ -58,31 +58,41 @@ class App:
|
||||
|
||||
health_monitor: AppHealthMonitor
|
||||
|
||||
# How long we allow shutdown tasks to run before killing them.
|
||||
# Currently the entire app hard-exits if shutdown takes 10 seconds,
|
||||
# so we need to keep it under that.
|
||||
SHUTDOWN_TASK_TIMEOUT_SECONDS = 5
|
||||
|
||||
class State(Enum):
|
||||
"""High level state the app can be in."""
|
||||
|
||||
# Waiting on the native layer to finish spinning up; our launch
|
||||
# process here has not yet started.
|
||||
BOOTSTRAPPING = 0
|
||||
# The app has not yet begun starting and should not be used in
|
||||
# any way.
|
||||
NOT_RUNNING = 'not_running'
|
||||
|
||||
# Our app subsystems are being inited but should not yet
|
||||
# interact.
|
||||
LAUNCHING = 1
|
||||
# The native layer is spinning up its machinery (screens,
|
||||
# renderers, etc.). Nothing should happen in the Python layer
|
||||
# until this completes.
|
||||
NATIVE_BOOTSTRAPPING = 'native_bootstrapping'
|
||||
|
||||
# App subsystems are inited and interacting, but the app has not
|
||||
# yet embarked on a high level course of action. It is doing
|
||||
# initial account logins, workspace & asset downloads, etc. in
|
||||
# order to prepare for this.
|
||||
LOADING = 2
|
||||
# Python app subsystems are being inited but should not yet
|
||||
# interact or do any work.
|
||||
INITING = 'initing'
|
||||
|
||||
# Python app subsystems are inited and interacting, but the app
|
||||
# has not yet embarked on a high level course of action. It is
|
||||
# doing initial account logins, workspace & asset downloads,
|
||||
# etc.
|
||||
LOADING = 'loading'
|
||||
|
||||
# All pieces are in place and the app is now doing its thing.
|
||||
RUNNING = 3
|
||||
RUNNING = 'running'
|
||||
|
||||
# The app is backgrounded or otherwise suspended.
|
||||
PAUSED = 4
|
||||
PAUSED = 'paused'
|
||||
|
||||
# The app is shutting down.
|
||||
SHUTTING_DOWN = 5
|
||||
SHUTTING_DOWN = 'shutting_down'
|
||||
|
||||
@property
|
||||
def aioloop(self) -> asyncio.AbstractEventLoop:
|
||||
@ -236,19 +246,20 @@ class App:
|
||||
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
||||
return
|
||||
|
||||
self.state = self.State.BOOTSTRAPPING
|
||||
self.state = self.State.NOT_RUNNING
|
||||
|
||||
self._subsystems: list[AppSubsystem] = []
|
||||
|
||||
self._native_bootstrapped = False
|
||||
self._native_bootstrapping_completed = False
|
||||
self._init_completed = False
|
||||
self._meta_scan_completed = False
|
||||
self._native_start_called = False
|
||||
self._native_paused = False
|
||||
self._native_shutdown_called = False
|
||||
self._launch_completed = False
|
||||
self._initial_sign_in_completed = False
|
||||
self._meta_scan_completed = False
|
||||
self._called_on_app_launching = False
|
||||
self._called_on_app_loading = False
|
||||
self._called_on_app_running = False
|
||||
self._called_on_initing = False
|
||||
self._called_on_loading = False
|
||||
self._called_on_running = False
|
||||
self._subsystem_registration_ended = False
|
||||
self._pending_apply_app_config = False
|
||||
|
||||
@ -484,13 +495,13 @@ class App:
|
||||
def run(self) -> None:
|
||||
"""Run the app to completion.
|
||||
|
||||
Note that this only works on platforms where ballistica
|
||||
Note that this only works on platforms where Ballistica
|
||||
manages its own event loop.
|
||||
"""
|
||||
_babase.run_app()
|
||||
|
||||
def _on_app_launching(self) -> None:
|
||||
"""Called when the app enters the launching state.
|
||||
def _on_initing(self) -> None:
|
||||
"""Called when the app enters the initing state.
|
||||
|
||||
Here we can put together subsystems and other pieces for the
|
||||
app, but most things should not be doing any work yet.
|
||||
@ -503,7 +514,7 @@ class App:
|
||||
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
_env.on_app_launching()
|
||||
_env.on_app_state_initing()
|
||||
|
||||
self._aioloop = _asyncio.setup_asyncio()
|
||||
self.health_monitor = AppHealthMonitor()
|
||||
@ -531,28 +542,25 @@ class App:
|
||||
|
||||
# __FEATURESET_APP_SUBSYSTEM_CREATE_END__
|
||||
|
||||
self._launch_completed = True
|
||||
# We're a pretty short-lived state. This should flip us to
|
||||
# 'loading'.
|
||||
self._init_completed = True
|
||||
self._update_state()
|
||||
|
||||
def _on_app_loading(self) -> None:
|
||||
"""Called when the app enters the loading state.
|
||||
def _on_loading(self) -> None:
|
||||
"""Called when we enter the loading state.
|
||||
|
||||
At this point, all built-in pieces of the app should be in place
|
||||
and can start doing 'work'. Though at a high level, the goal of
|
||||
the app at this point is only to sign in to initial accounts,
|
||||
download workspaces, and otherwise prepare itself to really
|
||||
'run'.
|
||||
and can start talking to each other and doing work. Though at a
|
||||
high level, the goal of the app at this point is only to sign in
|
||||
to initial accounts, download workspaces, and otherwise prepare
|
||||
itself to really 'run'.
|
||||
"""
|
||||
from babase._apputils import log_dumped_app_state
|
||||
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Get meta-system scanning built-in stuff in the bg.
|
||||
self.meta.start_scan(scan_complete_cb=self._on_meta_scan_complete)
|
||||
|
||||
# If any traceback dumps happened last run, log and clear them.
|
||||
log_dumped_app_state()
|
||||
|
||||
# Inform all app subsystems in the same order they were inited.
|
||||
# Operate on a copy here because subsystems can still be added
|
||||
# at this point.
|
||||
@ -568,7 +576,7 @@ class App:
|
||||
# is not present, however, we just do it ourself so we can
|
||||
# proceed on to the running state.
|
||||
if self.plus is None:
|
||||
_babase.pushcall(self.on_initial_sign_in_completed)
|
||||
_babase.pushcall(self.on_initial_sign_in_complete)
|
||||
|
||||
def _on_meta_scan_complete(self) -> None:
|
||||
"""Called when meta-scan is done doing its thing."""
|
||||
@ -581,8 +589,8 @@ class App:
|
||||
self._meta_scan_completed = True
|
||||
self._update_state()
|
||||
|
||||
def _on_app_running(self) -> None:
|
||||
"""Called when the app enters the running state.
|
||||
def _on_running(self) -> None:
|
||||
"""Called when we enter the running state.
|
||||
|
||||
At this point, all workspaces, initial accounts, etc. are in place
|
||||
and we can actually get started doing whatever we're gonna do.
|
||||
@ -704,51 +712,61 @@ class App:
|
||||
# pylint: disable=too-many-branches
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Can't shut down until we've got our asyncio machinery spun up.
|
||||
if self._native_shutdown_called and self._aioloop is not None:
|
||||
# Shutdown trumps all. Though we can't shut down until init is
|
||||
# completed since we need our asyncio stuff to exist for the
|
||||
# shutdown process.
|
||||
if self._native_shutdown_called and self._init_completed:
|
||||
# Entering shutdown state:
|
||||
if self.state is not self.State.SHUTTING_DOWN:
|
||||
self.state = self.State.SHUTTING_DOWN
|
||||
self._on_app_shutdown()
|
||||
self._on_shutting_down()
|
||||
|
||||
elif self._native_paused:
|
||||
# Entering paused state:
|
||||
if self.state is not self.State.PAUSED:
|
||||
self.state = self.State.PAUSED
|
||||
self._on_app_pause()
|
||||
self._on_pause()
|
||||
else:
|
||||
# Leaving paused state:
|
||||
if self.state is self.State.PAUSED:
|
||||
self._on_app_resume()
|
||||
self._on_resume()
|
||||
|
||||
# Handle initially entering or returning to other states.
|
||||
if self._initial_sign_in_completed and self._meta_scan_completed:
|
||||
if self.state != self.State.RUNNING:
|
||||
self.state = self.State.RUNNING
|
||||
_babase.lifecyclelog('app state running')
|
||||
if not self._called_on_app_running:
|
||||
self._called_on_app_running = True
|
||||
self._on_app_running()
|
||||
elif self._launch_completed:
|
||||
if not self._called_on_running:
|
||||
self._called_on_running = True
|
||||
self._on_running()
|
||||
elif self._init_completed:
|
||||
if self.state is not self.State.LOADING:
|
||||
self.state = self.State.LOADING
|
||||
_babase.lifecyclelog('app state loading')
|
||||
if not self._called_on_app_loading:
|
||||
self._called_on_app_loading = True
|
||||
self._on_app_loading()
|
||||
if not self._called_on_loading:
|
||||
self._called_on_loading = True
|
||||
self._on_loading()
|
||||
elif self._native_bootstrapping_completed:
|
||||
if self.state is not self.State.INITING:
|
||||
self.state = self.State.INITING
|
||||
_babase.lifecyclelog('app state initing')
|
||||
if not self._called_on_initing:
|
||||
self._called_on_initing = True
|
||||
self._on_initing()
|
||||
else:
|
||||
# Only thing left is launching. We shouldn't be getting
|
||||
# called before at least that is complete.
|
||||
assert self._native_bootstrapped
|
||||
if self.state is not self.State.LAUNCHING:
|
||||
self.state = self.State.LAUNCHING
|
||||
_babase.lifecyclelog('app state launching')
|
||||
if not self._called_on_app_launching:
|
||||
self._called_on_app_launching = True
|
||||
self._on_app_launching()
|
||||
# Only possibility left is app-start. We shouldn't be
|
||||
# getting called before at least that happens.
|
||||
assert self._native_start_called
|
||||
assert self.state is self.State.NOT_RUNNING
|
||||
if bool(True):
|
||||
self.state = self.State.NATIVE_BOOTSTRAPPING
|
||||
|
||||
def add_shutdown_task(self, coro: Coroutine[None, None, None]) -> None:
|
||||
"""Add a task to be run on app shutdown."""
|
||||
"""Add a task to be run on app shutdown.
|
||||
|
||||
Note that tasks will be killed after
|
||||
App.SHUTDOWN_TASK_TIMEOUT_SECONDS if they are still running.
|
||||
"""
|
||||
if self.state is self.State.SHUTTING_DOWN:
|
||||
raise RuntimeError(
|
||||
'Cannot add shutdown tasks with state SHUTTING_DOWN.'
|
||||
@ -780,15 +798,22 @@ class App:
|
||||
|
||||
task = asyncio.create_task(coro)
|
||||
try:
|
||||
await asyncio.wait_for(task, 5.0)
|
||||
await asyncio.wait_for(task, self.SHUTDOWN_TASK_TIMEOUT_SECONDS)
|
||||
except Exception:
|
||||
logging.exception('Error in shutdown task.')
|
||||
|
||||
def on_native_bootstrapped(self) -> None:
|
||||
def on_native_start(self) -> None:
|
||||
"""Called by the native layer when the app is being started."""
|
||||
assert _babase.in_logic_thread()
|
||||
assert not self._native_start_called
|
||||
self._native_start_called = True
|
||||
self._update_state()
|
||||
|
||||
def on_native_bootstrapping_complete(self) -> None:
|
||||
"""Called by the native layer once its ready to rock."""
|
||||
assert _babase.in_logic_thread()
|
||||
assert not self._native_bootstrapped
|
||||
self._native_bootstrapped = True
|
||||
assert not self._native_bootstrapping_completed
|
||||
self._native_bootstrapping_completed = True
|
||||
self._update_state()
|
||||
|
||||
def on_native_pause(self) -> None:
|
||||
@ -811,7 +836,7 @@ class App:
|
||||
self._native_shutdown_called = True
|
||||
self._update_state()
|
||||
|
||||
def _on_app_pause(self) -> None:
|
||||
def _on_pause(self) -> None:
|
||||
"""Called when the app goes to a paused state."""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
@ -824,7 +849,7 @@ class App:
|
||||
'Error in on_app_pause for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def _on_app_resume(self) -> None:
|
||||
def _on_resume(self) -> None:
|
||||
"""Called when resuming."""
|
||||
assert _babase.in_logic_thread()
|
||||
self.fg_state += 1
|
||||
@ -838,7 +863,7 @@ class App:
|
||||
'Error in on_app_resume for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def _on_app_shutdown(self) -> None:
|
||||
def _on_shutting_down(self) -> None:
|
||||
"""(internal)"""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
@ -882,7 +907,7 @@ class App:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
def on_initial_sign_in_completed(self) -> None:
|
||||
def on_initial_sign_in_complete(self) -> None:
|
||||
"""Called when initial sign-in (or lack thereof) completes.
|
||||
|
||||
This normally gets called by the plus subsystem. The
|
||||
|
||||
@ -378,6 +378,10 @@ class AppHealthMonitor(AppSubsystem):
|
||||
self._response = False
|
||||
self._first_check = True
|
||||
|
||||
def on_app_loading(self) -> None:
|
||||
# If any traceback dumps happened last run, log and clear them.
|
||||
log_dumped_app_state()
|
||||
|
||||
def _app_monitor_thread_main(self) -> None:
|
||||
try:
|
||||
self._monitor_app()
|
||||
|
||||
@ -149,14 +149,15 @@ def on_main_thread_start_app() -> None:
|
||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||
|
||||
|
||||
def on_app_launching() -> None:
|
||||
"""Called when the app reaches the launching state."""
|
||||
def on_app_state_initing() -> None:
|
||||
"""Called when the app reaches the initing state."""
|
||||
import _babase
|
||||
import baenv
|
||||
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Let the user know if the app Python dir is a 'user' one.
|
||||
# Let the user know if the app Python dir is a 'user' one. This is a
|
||||
# risky thing to be doing so don't let them forget they're doing it.
|
||||
envconfig = baenv.get_config()
|
||||
if envconfig.is_user_app_python_dir:
|
||||
_babase.screenmessage(
|
||||
@ -192,12 +193,13 @@ def _feed_logs_to_babase(log_handler: LogHandler) -> None:
|
||||
# cache. This will feed the engine any logs that happened between
|
||||
# baenv.configure() and now.
|
||||
|
||||
# FIXME: while this works for now, the downside is that these
|
||||
# FIXME: while this setup works for now, the downside is that these
|
||||
# callbacks fire in a bg thread so certain things like android
|
||||
# logging will be delayed compared to code that uses native logging
|
||||
# calls directly. Perhaps we should add some sort of 'immediate'
|
||||
# callback option to better handle such cases (similar to the
|
||||
# immediate echofile stderr print that already occurs).
|
||||
# logging will be delayed relative to code that uses native logging
|
||||
# calls directly. Ideally we should add some sort of 'immediate'
|
||||
# callback option to better handle such cases (analogous to the
|
||||
# immediate echofile stderr print that LogHandler already
|
||||
# supports).
|
||||
log_handler.add_callback(_on_log, feed_existing_logs=True)
|
||||
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ class PluginSubsystem(AppSubsystem):
|
||||
config_changed = True
|
||||
found_new = True
|
||||
|
||||
# If we're *not* auto-enabling, just let the user know if we
|
||||
# If we're *not* auto-enabling, simply let the user know if we
|
||||
# found new ones.
|
||||
if found_new and not auto_enable_new_plugins:
|
||||
_babase.screenmessage(
|
||||
@ -131,10 +131,10 @@ class PluginSubsystem(AppSubsystem):
|
||||
disappeared_plugs.add(class_path)
|
||||
continue
|
||||
|
||||
# If plugins disappeared, let the user know gently and remove them
|
||||
# from the config so we'll again let the user know if they later
|
||||
# reappear. This makes it much smoother to switch between users
|
||||
# or workspaces.
|
||||
# If plugins disappeared, let the user know gently and remove
|
||||
# them from the config so we'll again let the user know if they
|
||||
# later reappear. This makes it much smoother to switch between
|
||||
# users or workspaces.
|
||||
if disappeared_plugs:
|
||||
_babase.getsimplesound('shieldDown').play()
|
||||
_babase.screenmessage(
|
||||
@ -217,7 +217,7 @@ class PluginSpec:
|
||||
key. Remember to commit the app-config after making any changes.
|
||||
|
||||
The 'attempted_load' attr will be True if the engine has attempted
|
||||
to load the plugin. If 'attempted_load' is True for a plugin-spec
|
||||
to load the plugin. If 'attempted_load' is True for a PluginSpec
|
||||
but the 'plugin' attr is None, it means there was an error loading
|
||||
the plugin. If a plugin's api-version does not match the running
|
||||
app, if a new plugin is detected with auto-enable-plugins disabled,
|
||||
@ -249,7 +249,7 @@ class PluginSpec:
|
||||
plugstate['enabled'] = val
|
||||
|
||||
def attempt_load_if_enabled(self) -> Plugin | None:
|
||||
"""Possibly load the plugin and report errors."""
|
||||
"""Possibly load the plugin and log any errors."""
|
||||
from babase._general import getclass
|
||||
from babase._language import Lstr
|
||||
|
||||
@ -308,8 +308,8 @@ class Plugin:
|
||||
Category: **App Classes**
|
||||
|
||||
Plugins are discoverable by the meta-tag system
|
||||
and the user can select which ones they want to activate.
|
||||
Active plugins are then called at specific times as the
|
||||
and the user can select which ones they want to enable.
|
||||
Enabled plugins are then called at specific times as the
|
||||
app is running in order to modify its behavior in some way.
|
||||
"""
|
||||
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import threading
|
||||
import logging
|
||||
import weakref
|
||||
import threading
|
||||
from enum import Enum
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
@ -36,7 +37,9 @@ class MasterServerV1CallThread(threading.Thread):
|
||||
callback: MasterServerCallback | None,
|
||||
response_type: MasterServerResponseType,
|
||||
):
|
||||
super().__init__()
|
||||
# Set daemon=True so long-running requests don't keep us from
|
||||
# quitting the app.
|
||||
super().__init__(daemon=True)
|
||||
self._request = request
|
||||
self._request_type = request_type
|
||||
if not isinstance(response_type, MasterServerResponseType):
|
||||
@ -76,6 +79,16 @@ class MasterServerV1CallThread(threading.Thread):
|
||||
|
||||
from efro.error import is_urllib_communication_error
|
||||
|
||||
# If the app is going down, this is a no-op. Trying to avoid the
|
||||
# rare odd crash I see from (presumably) SSL stuff getting used
|
||||
# while the app is being torn down.
|
||||
if babase.app.state is babase.app.State.SHUTTING_DOWN:
|
||||
logging.warning(
|
||||
'MasterServerV1CallThread.run() during app'
|
||||
' shutdown is a no-op.'
|
||||
)
|
||||
return
|
||||
|
||||
plus = babase.app.plus
|
||||
assert plus is not None
|
||||
response_data: Any = None
|
||||
|
||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21250
|
||||
TARGET_BALLISTICA_BUILD = 21256
|
||||
TARGET_BALLISTICA_VERSION = '1.7.26'
|
||||
|
||||
|
||||
|
||||
@ -199,7 +199,11 @@ class QuitWindow:
|
||||
)
|
||||
bui.lock_all_input()
|
||||
|
||||
# Unlock and fade back in shortly.. just in case something goes wrong
|
||||
# (or on android where quit just backs out of our activity and
|
||||
# we may come back)
|
||||
bui.apptimer(0.3, bui.unlock_all_input)
|
||||
# Unlock and fade back in shortly. Just in case something goes
|
||||
# wrong (or on Android where quit just backs out of our activity
|
||||
# and we may come back after).
|
||||
def _come_back() -> None:
|
||||
bui.unlock_all_input()
|
||||
bui.fade_screen(True, time=0.1)
|
||||
|
||||
bui.apptimer(0.3, _come_back)
|
||||
|
||||
@ -1406,11 +1406,11 @@ def _check_merch_availability_in_bg_thread() -> None:
|
||||
time.sleep(1.1934) # A bit randomized to avoid aliasing.
|
||||
|
||||
|
||||
# Slight hack; start checking merch availability in the bg
|
||||
# (but only if it looks like we're part of a running app; don't want to
|
||||
# do this during docs generation/etc.)
|
||||
# Slight hack; start checking merch availability in the bg (but only if
|
||||
# it looks like we've been imported for use in a running app; don't want
|
||||
# to do this during docs generation/etc.)
|
||||
if (
|
||||
os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') != '1'
|
||||
and bui.app.state is not bui.app.State.BOOTSTRAPPING
|
||||
and bui.app.state is not bui.app.State.NOT_RUNNING
|
||||
):
|
||||
Thread(target=_check_merch_availability_in_bg_thread, daemon=True).start()
|
||||
|
||||
@ -140,7 +140,6 @@ void AppAdapter::OnAppPause_() {
|
||||
g_base->network_reader->OnAppPause();
|
||||
}
|
||||
g_base->networking->OnAppPause();
|
||||
g_core->platform->OnAppPause();
|
||||
}
|
||||
|
||||
void AppAdapter::OnAppResume_() {
|
||||
@ -151,7 +150,6 @@ void AppAdapter::OnAppResume_() {
|
||||
EventLoop::SetEventLoopsPaused(false);
|
||||
|
||||
// Run resumes that expect to happen in the main thread.
|
||||
g_core->platform->OnAppResume();
|
||||
g_base->network_reader->OnAppResume();
|
||||
g_base->networking->OnAppResume();
|
||||
|
||||
|
||||
@ -75,12 +75,12 @@ BaseFeatureSet::BaseFeatureSet()
|
||||
}
|
||||
|
||||
void BaseFeatureSet::OnModuleExec(PyObject* module) {
|
||||
// Ok, our feature-set's Python module is getting imported. Like any
|
||||
// normal Python module, we take this opportunity to import/create the
|
||||
// Ok, our feature-set's Python module is getting imported. Just like a
|
||||
// pure Python module would, we take this opportunity to import/create the
|
||||
// stuff we use.
|
||||
|
||||
// Importing core should always be the first thing we do. Various
|
||||
// ballistica functionality will fail if this has not been done.
|
||||
// Ballistica functionality will fail if this has not been done.
|
||||
assert(g_core == nullptr);
|
||||
g_core = core::CoreFeatureSet::Import();
|
||||
|
||||
@ -106,17 +106,18 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
|
||||
g_base->python->AddPythonClasses(module);
|
||||
|
||||
// Store our C++ front-end with our Python module. This is what allows
|
||||
// others to 'import' our C++ front end.
|
||||
// other C++ code to 'import' our C++ front end and talk to us directly.
|
||||
g_base->StoreOnPythonModule(module);
|
||||
|
||||
// Import all the Python stuff we use.
|
||||
g_base->python->ImportPythonObjs();
|
||||
|
||||
// Run some sanity checks, wire up our log handler, etc.
|
||||
auto result = g_base->python->objs()
|
||||
.Get(BasePython::ObjID::kOnNativeModuleImportCall)
|
||||
.Call();
|
||||
if (!result.Exists()) {
|
||||
bool success = g_base->python->objs()
|
||||
.Get(BasePython::ObjID::kEnvOnNativeModuleImportCall)
|
||||
.Call()
|
||||
.Exists();
|
||||
if (!success) {
|
||||
FatalError("babase._env.on_native_module_import() call failed.");
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +62,6 @@ void Logic::OnAppStart() {
|
||||
g_base->audio->OnAppStart();
|
||||
g_base->input->OnAppStart();
|
||||
g_base->ui->OnAppStart();
|
||||
g_core->platform->OnAppStart();
|
||||
g_base->app_mode()->OnAppStart();
|
||||
if (g_base->HavePlus()) {
|
||||
g_base->plus()->OnAppStart();
|
||||
@ -80,7 +79,7 @@ void Logic::OnInitialScreenCreated() {
|
||||
// business logic.
|
||||
|
||||
// Let the Python layer know the native layer is now fully functional.
|
||||
// This will probably result in the Python layer flipping to the LAUNCHING
|
||||
// This will probably result in the Python layer flipping to the INITING
|
||||
// state.
|
||||
CompleteAppBootstrapping();
|
||||
|
||||
@ -109,7 +108,7 @@ void Logic::CompleteAppBootstrapping() {
|
||||
assert(!app_bootstrapping_complete_);
|
||||
app_bootstrapping_complete_ = true;
|
||||
|
||||
g_core->LifecycleLog("app bootstrapping complete");
|
||||
g_core->LifecycleLog("app native bootstrapping complete");
|
||||
|
||||
// Let the assets system know it can start loading stuff now that
|
||||
// we have a screen and thus know texture formats/etc.
|
||||
@ -143,7 +142,7 @@ void Logic::CompleteAppBootstrapping() {
|
||||
// Let Python know we're done bootstrapping so it can flip the app
|
||||
// into the 'launching' state.
|
||||
g_base->python->objs()
|
||||
.Get(BasePython::ObjID::kAppOnNativeBootstrappedCall)
|
||||
.Get(BasePython::ObjID::kAppOnNativeBootstrappingCompleteCall)
|
||||
.Call();
|
||||
|
||||
UpdatePendingWorkTimer();
|
||||
@ -181,7 +180,6 @@ void Logic::OnAppPause() {
|
||||
g_base->plus()->OnAppPause();
|
||||
}
|
||||
g_base->app_mode()->OnAppPause();
|
||||
g_core->platform->OnAppPause();
|
||||
g_base->ui->OnAppPause();
|
||||
g_base->input->OnAppPause();
|
||||
g_base->audio->OnAppPause();
|
||||
@ -197,7 +195,6 @@ void Logic::OnAppResume() {
|
||||
g_base->audio->OnAppResume();
|
||||
g_base->input->OnAppResume();
|
||||
g_base->ui->OnAppResume();
|
||||
g_core->platform->OnAppResume();
|
||||
g_base->app_mode()->OnAppResume();
|
||||
if (g_base->HavePlus()) {
|
||||
g_base->plus()->OnAppResume();
|
||||
@ -234,7 +231,6 @@ void Logic::OnAppShutdown() {
|
||||
g_base->plus()->OnAppShutdown();
|
||||
}
|
||||
g_base->app_mode()->OnAppShutdown();
|
||||
g_core->platform->OnAppShutdown();
|
||||
g_base->ui->OnAppShutdown();
|
||||
g_base->input->OnAppShutdown();
|
||||
g_base->audio->OnAppShutdown();
|
||||
@ -269,7 +265,6 @@ void Logic::DoApplyAppConfig() {
|
||||
g_base->audio->DoApplyAppConfig();
|
||||
g_base->input->DoApplyAppConfig();
|
||||
g_base->ui->DoApplyAppConfig();
|
||||
g_core->platform->DoApplyAppConfig();
|
||||
g_base->app_mode()->DoApplyAppConfig();
|
||||
if (g_base->HavePlus()) {
|
||||
g_base->plus()->DoApplyAppConfig();
|
||||
@ -585,15 +580,20 @@ void Logic::UpdatePendingWorkTimer() {
|
||||
void Logic::HandleInterruptSignal() {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// Interrupt signals are 'gentle' requests to shut down.
|
||||
|
||||
// Special case; when running under the server-wrapper, we completely
|
||||
// ignore interrupt signals (the wrapper acts on them).
|
||||
if (g_base->server_wrapper_managed()) {
|
||||
return;
|
||||
}
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
// Go with a low level process shutdown here. In situations where we're
|
||||
// getting interrupt signals I don't think we'd ever want high level
|
||||
// 'soft' quits.
|
||||
void Logic::HandleTerminateSignal() {
|
||||
// Interrupt signals are slightly more stern requests to shut down.
|
||||
// We always respond to these.
|
||||
assert(g_base->InLogicThread());
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,9 @@ class Logic {
|
||||
return app_bootstrapping_complete_;
|
||||
}
|
||||
void NotifyOfPendingAssetLoads();
|
||||
|
||||
void HandleInterruptSignal();
|
||||
void HandleTerminateSignal();
|
||||
|
||||
auto NewAppTimer(millisecs_t length, bool repeat,
|
||||
const Object::Ref<Runnable>& runnable) -> int;
|
||||
|
||||
@ -257,11 +257,21 @@ void BasePlatform::DoOpenURL(const std::string& url) {
|
||||
|
||||
#if !BA_OSTYPE_WINDOWS
|
||||
static void HandleSIGINT(int s) {
|
||||
if (g_base->logic) {
|
||||
if (g_base && g_base->logic->event_loop()) {
|
||||
g_base->logic->event_loop()->PushCall(
|
||||
[] { g_base->logic->HandleInterruptSignal(); });
|
||||
} else {
|
||||
Log(LogLevel::kError, "SigInt handler called before g_logic exists.");
|
||||
Log(LogLevel::kError,
|
||||
"SigInt handler called before g_base->logic->event_loop exists.");
|
||||
}
|
||||
}
|
||||
static void HandleSIGTERM(int s) {
|
||||
if (g_base && g_base->logic->event_loop()) {
|
||||
g_base->logic->event_loop()->PushCall(
|
||||
[] { g_base->logic->HandleTerminateSignal(); });
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
"SigInt handler called before g_base->logic->event_loop exists.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -271,11 +281,20 @@ void BasePlatform::SetupInterruptHandling() {
|
||||
#if BA_OSTYPE_WINDOWS
|
||||
throw Exception();
|
||||
#else
|
||||
struct sigaction handler {};
|
||||
handler.sa_handler = HandleSIGINT;
|
||||
sigemptyset(&handler.sa_mask);
|
||||
handler.sa_flags = 0;
|
||||
sigaction(SIGINT, &handler, nullptr);
|
||||
{
|
||||
struct sigaction handler {};
|
||||
handler.sa_handler = HandleSIGINT;
|
||||
sigemptyset(&handler.sa_mask);
|
||||
handler.sa_flags = 0;
|
||||
sigaction(SIGINT, &handler, nullptr);
|
||||
}
|
||||
{
|
||||
struct sigaction handler {};
|
||||
handler.sa_handler = HandleSIGTERM;
|
||||
sigemptyset(&handler.sa_mask);
|
||||
handler.sa_flags = 0;
|
||||
sigaction(SIGTERM, &handler, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -142,7 +142,10 @@ void BasePython::OnMainThreadStartApp() {
|
||||
}
|
||||
}
|
||||
|
||||
void BasePython::OnAppStart() { assert(g_base->InLogicThread()); }
|
||||
void BasePython::OnAppStart() {
|
||||
assert(g_base->InLogicThread());
|
||||
objs().Get(BasePython::ObjID::kAppOnNativeStartCall).Call();
|
||||
}
|
||||
|
||||
void BasePython::OnAppPause() {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
@ -35,7 +35,7 @@ class BasePython {
|
||||
kCallClass,
|
||||
kGarbageCollectSessionEndCall,
|
||||
kConfig,
|
||||
kAppOnNativeBootstrappedCall,
|
||||
kAppOnNativeBootstrappingCompleteCall,
|
||||
kResetToMainMenuCall,
|
||||
kSetConfigFullscreenOnCall,
|
||||
kSetConfigFullscreenOffCall,
|
||||
@ -69,10 +69,11 @@ class BasePython {
|
||||
kAppReadConfigCall,
|
||||
kUIRemotePressCall,
|
||||
kRemoveInGameAdsMessageCall,
|
||||
kAppOnNativeStartCall,
|
||||
kAppOnNativePauseCall,
|
||||
kAppOnNativeResumeCall,
|
||||
kQuitCall,
|
||||
kAppOnNativeShutdownCall,
|
||||
kQuitCall,
|
||||
kShowPostPurchaseMessageCall,
|
||||
kContextError,
|
||||
kNotFoundError,
|
||||
@ -98,7 +99,7 @@ class BasePython {
|
||||
kLoginAdapterGetSignInTokenResponseCall,
|
||||
kPreEnv,
|
||||
kOpenURLWithWebBrowserModuleCall,
|
||||
kOnNativeModuleImportCall,
|
||||
kEnvOnNativeModuleImportCall,
|
||||
kOnMainThreadStartAppCall,
|
||||
kAppPushApplyAppConfigCall,
|
||||
kLast // Sentinel; must be at end.
|
||||
|
||||
@ -516,6 +516,9 @@ static auto PyQuit(PyObject* self, PyObject* args, PyObject* keywds)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Log(LogLevel::kDebug,
|
||||
// "QUIT soft=" + std::to_string(soft) + " back=" + std::to_string(back));
|
||||
|
||||
// FIXME this should all just go through platform and/or app-adapter.
|
||||
|
||||
if (g_buildconfig.ostype_ios_tvos()) {
|
||||
|
||||
@ -32,8 +32,8 @@ void ClassicFeatureSet::OnModuleExec(PyObject* module) {
|
||||
assert(g_classic == nullptr);
|
||||
g_classic = new ClassicFeatureSet();
|
||||
|
||||
// Store our C++ front-end with our Python module.
|
||||
// This is what allows others to 'import' our C++ front end.
|
||||
// Store our C++ front-end with our Python module. This is what allows
|
||||
// other C++ code to 'import' our C++ front end and talk to us directly.
|
||||
g_classic->StoreOnPythonModule(module);
|
||||
|
||||
// Import any Python stuff we use into objs_.
|
||||
|
||||
@ -644,22 +644,6 @@ auto CorePlatform::GetTextTextureData(void* tex) -> uint8_t* {
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
void CorePlatform::OnAppStart() {
|
||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||
}
|
||||
|
||||
void CorePlatform::OnAppPause() {
|
||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||
}
|
||||
|
||||
void CorePlatform::OnAppResume() {
|
||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||
}
|
||||
|
||||
void CorePlatform::OnAppShutdown() {
|
||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||
}
|
||||
|
||||
void CorePlatform::OnScreenSizeChange() {
|
||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||
}
|
||||
@ -700,8 +684,6 @@ void CorePlatform::AndroidSetResString(const std::string& res) {
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
void CorePlatform::DoApplyAppConfig() {}
|
||||
|
||||
void CorePlatform::AndroidSynthesizeBackPress() {
|
||||
Log(LogLevel::kError, "AndroidSynthesizeBackPress() unimplemented");
|
||||
}
|
||||
|
||||
@ -51,11 +51,6 @@ class CorePlatform {
|
||||
|
||||
virtual void WillExitMain(bool errored);
|
||||
|
||||
virtual void OnAppStart();
|
||||
virtual void OnAppPause();
|
||||
virtual void OnAppResume();
|
||||
virtual void OnAppShutdown();
|
||||
virtual void DoApplyAppConfig();
|
||||
virtual void OnScreenSizeChange();
|
||||
virtual void StepDisplayTime();
|
||||
|
||||
|
||||
@ -50,8 +50,8 @@ void SceneV1FeatureSet::OnModuleExec(PyObject* module) {
|
||||
assert(g_scene_v1 == nullptr);
|
||||
g_scene_v1 = new SceneV1FeatureSet();
|
||||
|
||||
// Store our C++ front-end with our Python module.
|
||||
// This is what allows others to 'import' our C++ front end.
|
||||
// Store our C++ front-end with our Python module. This is what allows
|
||||
// other C++ code to 'import' our C++ front end and talk to us directly.
|
||||
g_scene_v1->StoreOnPythonModule(module);
|
||||
|
||||
// Define our classes.
|
||||
|
||||
@ -1376,10 +1376,7 @@ void SceneV1AppMode::HandleQuitOnIdle() {
|
||||
idle_exiting_ = true;
|
||||
|
||||
Log(LogLevel::kInfo, "Quitting due to reaching idle-exit-minutes.");
|
||||
g_base->logic->event_loop()->PushCall([] {
|
||||
assert(g_base->InLogicThread());
|
||||
g_base->python->objs().Get(base::BasePython::ObjID::kQuitCall).Call();
|
||||
});
|
||||
g_base->logic->event_loop()->PushCall([] { g_base->logic->Shutdown(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 = 21250;
|
||||
const int kEngineBuildNumber = 21256;
|
||||
const char* kEngineVersion = "1.7.26";
|
||||
|
||||
#if BA_MONOLITHIC_BUILD
|
||||
|
||||
@ -86,16 +86,8 @@ EventLoop::EventLoop(EventLoopID identifier_in, ThreadSource source)
|
||||
// Block until the thread is bootstrapped.
|
||||
// (maybe not necessary, but let's be cautious in case we'd
|
||||
// try to use things like thread_id before they're known).
|
||||
if (identifier_ == EventLoopID::kLogic) {
|
||||
g_core->LifecycleLog("logic thread bootstrap wait begin");
|
||||
}
|
||||
|
||||
client_listener_cv_.wait(lock, [this] { return bootstrapped_; });
|
||||
|
||||
if (identifier_ == EventLoopID::kLogic) {
|
||||
g_core->LifecycleLog("logic thread bootstrap wait end");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ThreadSource::kWrapMain: {
|
||||
@ -758,20 +750,12 @@ void EventLoop::PushRunnableSynchronous(Runnable* runnable) {
|
||||
PushCrossThreadRunnable_(runnable, &complete);
|
||||
}
|
||||
|
||||
if (identifier_ == EventLoopID::kLogic) {
|
||||
g_core->LifecycleLog("logic thread sync run push begin");
|
||||
}
|
||||
|
||||
// Now listen until our completion flag gets set.
|
||||
client_listener_cv_.wait(lock, [complete_ptr] {
|
||||
// Go back to sleep on spurious wakeups
|
||||
// (if we're not actually complete yet).
|
||||
return *complete_ptr;
|
||||
});
|
||||
|
||||
if (identifier_ == EventLoopID::kLogic) {
|
||||
g_core->LifecycleLog("logic thread sync run push end");
|
||||
}
|
||||
}
|
||||
|
||||
auto EventLoop::CheckPushSafety() -> bool {
|
||||
|
||||
@ -23,8 +23,8 @@ void TemplateFsFeatureSet::OnModuleExec(PyObject* module) {
|
||||
// Create our feature-set's C++ front-end.
|
||||
g_template_fs = new TemplateFsFeatureSet();
|
||||
|
||||
// Store our C++ front-end on our Python module.
|
||||
// This is what allows others to 'import' our C++ front end.
|
||||
// Store our C++ front-end with our Python module. This is what allows
|
||||
// other C++ code to 'import' our C++ front end and talk to us directly.
|
||||
g_template_fs->StoreOnPythonModule(module);
|
||||
|
||||
// Import any Python stuff we use into objs_.
|
||||
|
||||
@ -78,6 +78,6 @@ values = [
|
||||
_hooks.implicit_sign_out, # kImplicitSignOutCall
|
||||
_hooks.login_adapter_get_sign_in_token_response, # kLoginAdapterGetSignInTokenResponseCall
|
||||
_hooks.open_url_with_webbrowser_module, # kOpenURLWithWebBrowserModuleCall
|
||||
_env.on_native_module_import, # kOnNativeModuleImportCall
|
||||
_env.on_native_module_import, # kEnvOnNativeModuleImportCall
|
||||
_env.on_main_thread_start_app, # kOnMainThreadStartAppCall
|
||||
]
|
||||
|
||||
@ -12,7 +12,8 @@ values = [
|
||||
app.lang.get_resource, # kGetResourceCall
|
||||
app.lang.translate, # kTranslateCall
|
||||
app.push_apply_app_config, # kAppPushApplyAppConfigCall
|
||||
app.on_native_bootstrapped, # kAppOnNativeBootstrappedCall
|
||||
app.on_native_start, # kAppOnNativeStartCall
|
||||
app.on_native_bootstrapping_complete, # kAppOnNativeBootstrappingCompleteCall
|
||||
app.on_native_pause, # kAppOnNativePauseCall
|
||||
app.on_native_resume, # kAppOnNativeResumeCall
|
||||
app.on_native_shutdown, # kAppOnNativeShutdownCall
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user