mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-06 15:47:06 +08:00
lots of logging improvements
This commit is contained in:
parent
643104f538
commit
b3e23f7bff
92
.efrocachemap
generated
92
.efrocachemap
generated
@ -4096,56 +4096,56 @@
|
|||||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c8904594aa4867a7525e6644249d5fd5",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b20c6e3a2287f1c6a9a898e78fcab105",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "7d3ba05e21b198bdccbdaf9d334f96f2",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "0f1eff142f1e5796be2e0340dcbb4c8f",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "8601ef36314294c18b686995ce9a02f6",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f40171c1c943c10e2d2120a586a711f7",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "36742622076742a5642de8c287cd92e4",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ea494bdeb942cbab86c0371bb0558f3b",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b05ee46d11b618cf917cae591fe6b97a",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "fba8474fd758e8d76bc6d7e90dfb7795",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a9a03ded1e4fccfdc1879bd8f70e0e7a",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4b1a35c2e6d7c2d9a01c6e2750716c24",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "05f37deacb796ef45828233ded9325e3",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "9ac4ee8aab0243a233ba8650cd0d0b73",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "f4b4df8f17219f81148efe3dc057856f",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "c804d14d91dab05f644079ae47e61728",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b6201f83d4f80fcc567398807c7d77b5",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1f7011d1c77548e48b7f6d3ac09a29da",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "331335944425c5a48abbcf137da46f0f",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "c50790a9a2e3001dd079a6bbd753c36f",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ac2d7714d87b781659c1e3333f760888",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "52528037523bf268e2c59a19626e7f2d",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1e7cc9348498df9bfb7b25cd83009d7c",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "a920948fcc94c397495ef8dd674d325b",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a3c7e011ad99046d2ef8b102e7d15733",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d0f7ad9287edd649d97844ada500a11d",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "43fd8535ad1e2c2c64fe57dacfb3305b",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1073804b2d2549f9eb992666fc3640c3",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "fc17d6883ddd4486a62b75494dbb9d15",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "73e6ca5aee9af5a87960b7ae174f0a71",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0a557a638ee4cb3150d90bcb5913de3e",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c09c4fac16134d5071a88ec8d3e1e950",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "85afe70f81c1f7d2de9520d498c74eb8",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e78b8bd1cb5aa452f536c57e855bcc27",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "a617c0412a804bce272113585c000318",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "0f08643a492ac7bf8fd3f13460003bce",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "5642e5614711b8e106de659db2b33ac7",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "48e684f7db6d88a62009d773ab51b065",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ea7018647c89777469979aa08e88573e",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "69a301acc9adfacdb8b3d200390bbfdd",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "ba7dc0b4e927f32fcf15c2f738fe004c",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "653df60722ed096b8cc3ac3a4196e5a5",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fb4c90da8d46ddab5847406fa397dbd5",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "f82c1e575e8f23c1e278db61a740a4d5",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "ba7dc0b4e927f32fcf15c2f738fe004c",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "653df60722ed096b8cc3ac3a4196e5a5",
|
||||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "fb4c90da8d46ddab5847406fa397dbd5",
|
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "f82c1e575e8f23c1e278db61a740a4d5",
|
||||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "225f13c4755aa018e63168c8aca0a8fd",
|
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "90125afd27068280c96cf37c950b641f",
|
||||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "d4c6e0f0ac69af106f1227daeae2db55",
|
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a210d341f1842b21ebbaadd80ae4a282",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "225f13c4755aa018e63168c8aca0a8fd",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "90125afd27068280c96cf37c950b641f",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "d4c6e0f0ac69af106f1227daeae2db55",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a210d341f1842b21ebbaadd80ae4a282",
|
||||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "e16971f1da7ad7f44bb185b4446965c6",
|
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "cdf4fca1c1aaae2c2294263f0717b333",
|
||||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d5638285fa481d769a5cd488a78d8269",
|
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "937b954eed2571cb4d5f9d2a0e3f77ed",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "e16971f1da7ad7f44bb185b4446965c6",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "cdf4fca1c1aaae2c2294263f0717b333",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d5638285fa481d769a5cd488a78d8269",
|
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "937b954eed2571cb4d5f9d2a0e3f77ed",
|
||||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "184b7e4731b09ccf3a6a3b001d8af097",
|
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "cdd7c61d6c0efd5fb0442e625123b63f",
|
||||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "507b5555ef5d067caf18fe9844ca04c7",
|
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "ea327f45634a8e42259c5ecadf219e36",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "838ee9bfd43169efe8daff8bb0efb1db",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "547362a74979fa82b854a475dffeae90",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "507b5555ef5d067caf18fe9844ca04c7",
|
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "ea327f45634a8e42259c5ecadf219e36",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "d1edb04136c433b57f3842830e9b272d",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "828f4682e3bbdc0da5b45a0050aeb5d8",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "4e64e07e3527e0536d1dc7f2dacd681a",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "cf4b13af9f0846a466204afbe74b9e86",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "301bad929a4f3c6e9f67e57ab730bded",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b43fa205beae83e030ec777d4974736b",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "6224ca7790cfa8274c3f9c8e4461b93f",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "aef585a4d739765b59f9a85dc27ff67f",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "bedcc6b5cc2a403a65d83c6244922feb",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "559b65282ab2bfff034aa64963a7af52",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "545edb5e8f7cce4e7bc3cdb0e4f98b82",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "5916245826eb4d3b68944006f82de6d9",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "79102625aebc9df3a0834f8d571fdbac",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "6844834b7fc1030c234bee21a376a017",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9e5a350dc8f5fcd1ab96c7a4c24a7ebe",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "c9b29530b90bb59e8570d991072efd77",
|
||||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
|
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc",
|
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "f0f9dc33ecd4ef7a384f131d62c96c97",
|
||||||
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
||||||
"src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69",
|
"src/ballistica/core/mgen/pyembed/binding_core.inc": "73bbc63c2a85aed75c26cfedf047fd9d",
|
||||||
"src/ballistica/core/mgen/pyembed/env.inc": "f015d726b44d2922112fc14d9f146d8b",
|
"src/ballistica/core/mgen/pyembed/env.inc": "f015d726b44d2922112fc14d9f146d8b",
|
||||||
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
|
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
|
||||||
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "c25b263f2a31fb5ebe057db07d144879",
|
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "c25b263f2a31fb5ebe057db07d144879",
|
||||||
|
|||||||
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,9 +1,24 @@
|
|||||||
### 1.7.37 (build 22025, api 9, 2024-10-07)
|
### 1.7.37 (build 22040, api 9, 2024-10-19)
|
||||||
- Bumping api version to 9. As you'll see below, there's some UI changes that
|
- Bumping api version to 9. As you'll see below, there's some UI changes that
|
||||||
will require a bit of work for any UI mods to adapt to. If your mods don't
|
will require a bit of work for any UI mods to adapt to. If your mods don't
|
||||||
touch UI stuff at all you can simply bump your api version and call it a day.
|
touch UI stuff at all you can simply bump your api version and call it a day.
|
||||||
I'm hopeful that api version won't need to be bumped again for along time (if
|
I'm hopeful that api version won't need to be bumped again for along time (if
|
||||||
ever).
|
ever).
|
||||||
|
- Heavily reworked and cleaned up the logging system. There is now a 'ba' Python
|
||||||
|
logger and various logger categories under it such as 'ba.lifecycle',
|
||||||
|
'ba.connectivity' or 'ba.v2transport'. By setting these individual loggers to
|
||||||
|
different levels such as 'debug', one can easily observe and debug specific
|
||||||
|
parts of app behavior. Over time I will better organize the logger hierarchy
|
||||||
|
and wire up more functionality to be logged this way.
|
||||||
|
- Added a 'Logging' tab to the dev-console. This allows easily setting log
|
||||||
|
levels for all existing Python loggers, as well as resetting them all to
|
||||||
|
defaults. Levels set here are restored on startup, so it is possible to debug
|
||||||
|
app startup behavior this way. Previously this sort of thing would generally
|
||||||
|
require setting cryptic environment variables which was not feasable on all
|
||||||
|
platforms, but this new system should work everywhere.
|
||||||
|
- Logs printed to both the command line and the in-app console now include
|
||||||
|
timestamps and logger names, and are color coded for severity (DEBUG=blue,
|
||||||
|
INFO=default, WARNING=orange/yellow, ERROR=red, CRITICAL=purple).
|
||||||
- Went ahead and fully removed `efro.call.tpartial` (since we're breaking
|
- Went ahead and fully removed `efro.call.tpartial` (since we're breaking
|
||||||
compatibility anyway by bumping api version). If you are using
|
compatibility anyway by bumping api version). If you are using
|
||||||
`efro.call.tpartial` anywhere, simply replace it with `functools.partial`.
|
`efro.call.tpartial` anywhere, simply replace it with `functools.partial`.
|
||||||
@ -113,6 +128,8 @@
|
|||||||
it will take you back to the co-op screen.
|
it will take you back to the co-op screen.
|
||||||
- (build 22018) Hardened SDL joystick handling code so the app won't crash if
|
- (build 22018) Hardened SDL joystick handling code so the app won't crash if
|
||||||
SDL_JoystickOpen() returns nullptr for whatever reason.
|
SDL_JoystickOpen() returns nullptr for whatever reason.
|
||||||
|
- (build 22028) Fixed a longstanding issue that could cause logic thread
|
||||||
|
bg-dynamics message overflows.
|
||||||
|
|
||||||
### 1.7.36 (build 21944, api 8, 2024-07-26)
|
### 1.7.36 (build 21944, api 8, 2024-07-26)
|
||||||
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these
|
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these
|
||||||
@ -159,6 +176,8 @@
|
|||||||
version and then upgrading to later builds of the same version containing
|
version and then upgrading to later builds of the same version containing
|
||||||
incompatibilities with the older sys scripts. This should help with that
|
incompatibilities with the older sys scripts. This should help with that
|
||||||
problem.
|
problem.
|
||||||
|
- `efro.log` is now `efro.logging` which better lines up with other logging
|
||||||
|
module names. It was originally named `log` to work around a mypy bug.
|
||||||
|
|
||||||
### 1.7.35 (build 21889, api 8, 2024-06-20)
|
### 1.7.35 (build 21889, api 8, 2024-06-20)
|
||||||
- Fixed an issue where the engine would block at exit on some version of Linux
|
- Fixed an issue where the engine would block at exit on some version of Linux
|
||||||
|
|||||||
@ -2,9 +2,9 @@ cpplint==2.0.0
|
|||||||
dmgbuild==1.6.2
|
dmgbuild==1.6.2
|
||||||
filelock==3.16.1
|
filelock==3.16.1
|
||||||
furo==2024.8.6
|
furo==2024.8.6
|
||||||
mypy==1.11.2
|
mypy==1.12.0
|
||||||
pbxproj==4.2.1
|
pbxproj==4.2.1
|
||||||
pdoc==14.7.0
|
pdoc==15.0.0
|
||||||
pur==7.3.2
|
pur==7.3.2
|
||||||
pylint==3.3.1
|
pylint==3.3.1
|
||||||
pylsp-mypy==0.6.9
|
pylsp-mypy==0.6.9
|
||||||
@ -13,10 +13,10 @@ python-daemon==3.0.1
|
|||||||
python-lsp-black==2.0.0
|
python-lsp-black==2.0.0
|
||||||
python-lsp-server==1.12.0
|
python-lsp-server==1.12.0
|
||||||
requests==2.32.3
|
requests==2.32.3
|
||||||
Sphinx==8.0.2
|
Sphinx==8.1.3
|
||||||
tomlkit==0.13.2
|
tomlkit==0.13.2
|
||||||
types-certifi==2021.10.8.3
|
types-certifi==2021.10.8.3
|
||||||
types-filelock==3.2.7
|
types-filelock==3.2.7
|
||||||
types-requests==2.32.0.20240914
|
types-requests==2.32.0.20241016
|
||||||
typing_extensions==4.12.2
|
typing_extensions==4.12.2
|
||||||
urllib3==2.2.3
|
urllib3==2.2.3
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
"ba_data/python/babase/__pycache__/_assetmanager.cpython-312.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_assetmanager.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_asyncio.cpython-312.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_asyncio.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_devconsole.cpython-312.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_devconsole.cpython-312.opt-1.pyc",
|
||||||
|
"ba_data/python/babase/__pycache__/_devconsoletabs.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_emptyappmode.cpython-312.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_emptyappmode.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_env.cpython-312.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_env.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_error.cpython-312.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_error.cpython-312.opt-1.pyc",
|
||||||
@ -42,6 +43,7 @@
|
|||||||
"ba_data/python/babase/_assetmanager.py",
|
"ba_data/python/babase/_assetmanager.py",
|
||||||
"ba_data/python/babase/_asyncio.py",
|
"ba_data/python/babase/_asyncio.py",
|
||||||
"ba_data/python/babase/_devconsole.py",
|
"ba_data/python/babase/_devconsole.py",
|
||||||
|
"ba_data/python/babase/_devconsoletabs.py",
|
||||||
"ba_data/python/babase/_emptyappmode.py",
|
"ba_data/python/babase/_emptyappmode.py",
|
||||||
"ba_data/python/babase/_env.py",
|
"ba_data/python/babase/_env.py",
|
||||||
"ba_data/python/babase/_error.py",
|
"ba_data/python/babase/_error.py",
|
||||||
@ -103,6 +105,8 @@
|
|||||||
"ba_data/python/bacommon/__pycache__/bacloud.cpython-312.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/bacloud.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/build.cpython-312.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/build.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/cloud.cpython-312.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/cloud.cpython-312.opt-1.pyc",
|
||||||
|
"ba_data/python/bacommon/__pycache__/loggercontrol.cpython-312.opt-1.pyc",
|
||||||
|
"ba_data/python/bacommon/__pycache__/logging.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/login.cpython-312.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/login.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/net.cpython-312.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/net.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/servermanager.cpython-312.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/servermanager.cpython-312.opt-1.pyc",
|
||||||
@ -112,6 +116,8 @@
|
|||||||
"ba_data/python/bacommon/bacloud.py",
|
"ba_data/python/bacommon/bacloud.py",
|
||||||
"ba_data/python/bacommon/build.py",
|
"ba_data/python/bacommon/build.py",
|
||||||
"ba_data/python/bacommon/cloud.py",
|
"ba_data/python/bacommon/cloud.py",
|
||||||
|
"ba_data/python/bacommon/loggercontrol.py",
|
||||||
|
"ba_data/python/bacommon/logging.py",
|
||||||
"ba_data/python/bacommon/login.py",
|
"ba_data/python/bacommon/login.py",
|
||||||
"ba_data/python/bacommon/net.py",
|
"ba_data/python/bacommon/net.py",
|
||||||
"ba_data/python/bacommon/servermanager.py",
|
"ba_data/python/bacommon/servermanager.py",
|
||||||
@ -577,7 +583,7 @@
|
|||||||
"ba_data/python/efro/__pycache__/cloudshell.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/cloudshell.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/__pycache__/debug.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/debug.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/__pycache__/error.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/error.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/__pycache__/log.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/logging.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/__pycache__/rpc.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/rpc.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/__pycache__/terminal.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/terminal.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/__pycache__/util.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/__pycache__/util.cpython-312.opt-1.pyc",
|
||||||
@ -601,7 +607,7 @@
|
|||||||
"ba_data/python/efro/dataclassio/extras.py",
|
"ba_data/python/efro/dataclassio/extras.py",
|
||||||
"ba_data/python/efro/debug.py",
|
"ba_data/python/efro/debug.py",
|
||||||
"ba_data/python/efro/error.py",
|
"ba_data/python/efro/error.py",
|
||||||
"ba_data/python/efro/log.py",
|
"ba_data/python/efro/logging.py",
|
||||||
"ba_data/python/efro/message/__init__.py",
|
"ba_data/python/efro/message/__init__.py",
|
||||||
"ba_data/python/efro/message/__pycache__/__init__.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/message/__pycache__/__init__.cpython-312.opt-1.pyc",
|
||||||
"ba_data/python/efro/message/__pycache__/_message.cpython-312.opt-1.pyc",
|
"ba_data/python/efro/message/__pycache__/_message.cpython-312.opt-1.pyc",
|
||||||
|
|||||||
@ -175,6 +175,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/babase/_assetmanager.py \
|
$(BUILD_DIR)/ba_data/python/babase/_assetmanager.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_asyncio.py \
|
$(BUILD_DIR)/ba_data/python/babase/_asyncio.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_devconsole.py \
|
$(BUILD_DIR)/ba_data/python/babase/_devconsole.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/babase/_devconsoletabs.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_emptyappmode.py \
|
$(BUILD_DIR)/ba_data/python/babase/_emptyappmode.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_env.py \
|
$(BUILD_DIR)/ba_data/python/babase/_env.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_error.py \
|
$(BUILD_DIR)/ba_data/python/babase/_error.py \
|
||||||
@ -452,6 +453,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_assetmanager.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_assetmanager.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_asyncio.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_asyncio.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_devconsole.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_devconsole.cpython-312.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_devconsoletabs.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_emptyappmode.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_emptyappmode.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_env.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_env.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_error.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_error.cpython-312.opt-1.pyc \
|
||||||
@ -732,6 +734,8 @@ SCRIPT_TARGETS_PY_PUBLIC_TOOLS = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bacommon/bacloud.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/bacloud.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/build.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/build.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/cloud.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/cloud.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bacommon/loggercontrol.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bacommon/logging.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/login.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/login.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/net.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/net.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/servermanager.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/servermanager.py \
|
||||||
@ -751,7 +755,7 @@ SCRIPT_TARGETS_PY_PUBLIC_TOOLS = \
|
|||||||
$(BUILD_DIR)/ba_data/python/efro/dataclassio/extras.py \
|
$(BUILD_DIR)/ba_data/python/efro/dataclassio/extras.py \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/debug.py \
|
$(BUILD_DIR)/ba_data/python/efro/debug.py \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/error.py \
|
$(BUILD_DIR)/ba_data/python/efro/error.py \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/log.py \
|
$(BUILD_DIR)/ba_data/python/efro/logging.py \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/message/__init__.py \
|
$(BUILD_DIR)/ba_data/python/efro/message/__init__.py \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/message/_message.py \
|
$(BUILD_DIR)/ba_data/python/efro/message/_message.py \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/message/_module.py \
|
$(BUILD_DIR)/ba_data/python/efro/message/_module.py \
|
||||||
@ -769,6 +773,8 @@ SCRIPT_TARGETS_PYC_PUBLIC_TOOLS = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/bacloud.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/bacloud.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/build.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/build.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/cloud.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/cloud.cpython-312.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/loggercontrol.cpython-312.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/logging.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/login.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/login.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/net.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/net.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/servermanager.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/servermanager.cpython-312.opt-1.pyc \
|
||||||
@ -788,7 +794,7 @@ SCRIPT_TARGETS_PYC_PUBLIC_TOOLS = \
|
|||||||
$(BUILD_DIR)/ba_data/python/efro/dataclassio/__pycache__/extras.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/dataclassio/__pycache__/extras.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/__pycache__/debug.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/__pycache__/debug.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/__pycache__/error.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/__pycache__/error.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/__pycache__/log.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/__pycache__/logging.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/message/__pycache__/__init__.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/message/__pycache__/__init__.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/message/__pycache__/_message.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/message/__pycache__/_message.cpython-312.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/efro/message/__pycache__/_module.cpython-312.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/efro/message/__pycache__/_module.cpython-312.opt-1.pyc \
|
||||||
|
|||||||
@ -15,6 +15,7 @@ a more focused way.
|
|||||||
# dependency loops. The exception is TYPE_CHECKING blocks and
|
# dependency loops. The exception is TYPE_CHECKING blocks and
|
||||||
# annotations since those aren't evaluated at runtime.
|
# annotations since those aren't evaluated at runtime.
|
||||||
|
|
||||||
|
import logging
|
||||||
from efro.util import set_canonical_module_names
|
from efro.util import set_canonical_module_names
|
||||||
|
|
||||||
|
|
||||||
@ -109,6 +110,7 @@ from _babase import (
|
|||||||
supports_max_fps,
|
supports_max_fps,
|
||||||
supports_vsync,
|
supports_vsync,
|
||||||
unlock_all_input,
|
unlock_all_input,
|
||||||
|
update_internal_logger_levels,
|
||||||
user_agent_string,
|
user_agent_string,
|
||||||
Vec3,
|
Vec3,
|
||||||
workspaces_in_use,
|
workspaces_in_use,
|
||||||
@ -185,6 +187,9 @@ from babase._plugin import PluginSpec, Plugin, PluginSubsystem
|
|||||||
from babase._stringedit import StringEditAdapter, StringEditSubsystem
|
from babase._stringedit import StringEditAdapter, StringEditSubsystem
|
||||||
from babase._text import timestring
|
from babase._text import timestring
|
||||||
|
|
||||||
|
# Our standard set of loggers.
|
||||||
|
balog = logging.getLogger('ba')
|
||||||
|
|
||||||
_babase.app = app = App()
|
_babase.app = app = App()
|
||||||
app.postinit()
|
app.postinit()
|
||||||
|
|
||||||
@ -215,6 +220,7 @@ __all__ = [
|
|||||||
'apptimer',
|
'apptimer',
|
||||||
'AppTimer',
|
'AppTimer',
|
||||||
'asset_loads_allowed',
|
'asset_loads_allowed',
|
||||||
|
'balog',
|
||||||
'Call',
|
'Call',
|
||||||
'fullscreen_control_available',
|
'fullscreen_control_available',
|
||||||
'fullscreen_control_get',
|
'fullscreen_control_get',
|
||||||
@ -344,6 +350,7 @@ __all__ = [
|
|||||||
'timestring',
|
'timestring',
|
||||||
'UIScale',
|
'UIScale',
|
||||||
'unlock_all_input',
|
'unlock_all_input',
|
||||||
|
'update_internal_logger_levels',
|
||||||
'user_agent_string',
|
'user_agent_string',
|
||||||
'utf8_all',
|
'utf8_all',
|
||||||
'Vec3',
|
'Vec3',
|
||||||
|
|||||||
@ -10,11 +10,12 @@ from functools import partial
|
|||||||
from typing import TYPE_CHECKING, assert_never
|
from typing import TYPE_CHECKING, assert_never
|
||||||
|
|
||||||
from efro.error import CommunicationError
|
from efro.error import CommunicationError
|
||||||
|
from efro.call import CallbackSet
|
||||||
from bacommon.login import LoginType
|
from bacommon.login import LoginType
|
||||||
import _babase
|
import _babase
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any, Callable
|
||||||
|
|
||||||
from babase._login import LoginAdapter, LoginInfo
|
from babase._login import LoginAdapter, LoginInfo
|
||||||
|
|
||||||
@ -31,10 +32,12 @@ class AccountV2Subsystem:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
assert _babase.in_logic_thread()
|
||||||
|
|
||||||
from babase._login import LoginAdapterGPGS, LoginAdapterGameCenter
|
from babase._login import LoginAdapterGPGS, LoginAdapterGameCenter
|
||||||
|
|
||||||
# Whether or not everything related to an initial login
|
# Whether or not everything related to an initial sign in (or
|
||||||
# (or lack thereof) has completed. This includes things like
|
# lack thereof) has completed. This includes things like
|
||||||
# workspace syncing. Completion of this is what flips the app
|
# workspace syncing. Completion of this is what flips the app
|
||||||
# into 'running' state.
|
# into 'running' state.
|
||||||
self._initial_sign_in_completed = False
|
self._initial_sign_in_completed = False
|
||||||
@ -46,6 +49,9 @@ class AccountV2Subsystem:
|
|||||||
self._implicit_signed_in_adapter: LoginAdapter | None = None
|
self._implicit_signed_in_adapter: LoginAdapter | None = None
|
||||||
self._implicit_state_changed = False
|
self._implicit_state_changed = False
|
||||||
self._can_do_auto_sign_in = True
|
self._can_do_auto_sign_in = True
|
||||||
|
self.on_primary_account_changed_callbacks: CallbackSet[
|
||||||
|
Callable[[AccountV2Handle | None], None]
|
||||||
|
] = CallbackSet()
|
||||||
|
|
||||||
adapter: LoginAdapter
|
adapter: LoginAdapter
|
||||||
if _babase.using_google_play_game_services():
|
if _babase.using_google_play_game_services():
|
||||||
@ -85,6 +91,13 @@ class AccountV2Subsystem:
|
|||||||
"""
|
"""
|
||||||
assert _babase.in_logic_thread()
|
assert _babase.in_logic_thread()
|
||||||
|
|
||||||
|
# Fire any registered callbacks.
|
||||||
|
for call in self.on_primary_account_changed_callbacks.getcalls():
|
||||||
|
try:
|
||||||
|
call(account)
|
||||||
|
except Exception:
|
||||||
|
logging.exception('Error in primary-account-changed callback.')
|
||||||
|
|
||||||
# Currently don't do anything special on sign-outs.
|
# Currently don't do anything special on sign-outs.
|
||||||
if account is None:
|
if account is None:
|
||||||
return
|
return
|
||||||
|
|||||||
@ -23,6 +23,7 @@ from babase._appmodeselector import AppModeSelector
|
|||||||
from babase._appintent import AppIntentDefault, AppIntentExec
|
from babase._appintent import AppIntentDefault, AppIntentExec
|
||||||
from babase._stringedit import StringEditSubsystem
|
from babase._stringedit import StringEditSubsystem
|
||||||
from babase._devconsole import DevConsoleSubsystem
|
from babase._devconsole import DevConsoleSubsystem
|
||||||
|
from babase._appconfig import AppConfig
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import asyncio
|
import asyncio
|
||||||
@ -182,6 +183,11 @@ class App:
|
|||||||
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Wrap our raw app config in our special wrapper and pass it to
|
||||||
|
# the native layer.
|
||||||
|
self.config = AppConfig(_babase.get_initial_app_config())
|
||||||
|
_babase.set_app_config(self.config)
|
||||||
|
|
||||||
self.env: babase.Env = _babase.Env()
|
self.env: babase.Env = _babase.Env()
|
||||||
self.state = self.State.NOT_STARTED
|
self.state = self.State.NOT_STARTED
|
||||||
|
|
||||||
@ -223,7 +229,7 @@ class App:
|
|||||||
self._asyncio_loop: asyncio.AbstractEventLoop | None = None
|
self._asyncio_loop: asyncio.AbstractEventLoop | None = None
|
||||||
self._asyncio_tasks: set[asyncio.Task] = set()
|
self._asyncio_tasks: set[asyncio.Task] = set()
|
||||||
self._asyncio_timer: babase.AppTimer | None = None
|
self._asyncio_timer: babase.AppTimer | None = None
|
||||||
self._config: babase.AppConfig | None = None
|
# self._config: babase.AppConfig | None = None
|
||||||
self._pending_intent: AppIntent | None = None
|
self._pending_intent: AppIntent | None = None
|
||||||
self._intent: AppIntent | None = None
|
self._intent: AppIntent | None = None
|
||||||
self._mode_selector: babase.AppModeSelector | None = None
|
self._mode_selector: babase.AppModeSelector | None = None
|
||||||
@ -330,11 +336,12 @@ class App:
|
|||||||
|
|
||||||
self._asyncio_tasks.remove(task)
|
self._asyncio_tasks.remove(task)
|
||||||
|
|
||||||
@property
|
# @property
|
||||||
def config(self) -> babase.AppConfig:
|
# def config(self) -> babase.AppConfig:
|
||||||
"""The babase.AppConfig instance representing the app's config state."""
|
# """The babase.AppConfig instance
|
||||||
assert self._config is not None
|
# representing the app's config state."""
|
||||||
return self._config
|
# assert self._config is not None
|
||||||
|
# return self._config
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mode_selector(self) -> babase.AppModeSelector:
|
def mode_selector(self) -> babase.AppModeSelector:
|
||||||
@ -585,12 +592,6 @@ class App:
|
|||||||
if self._mode is not None:
|
if self._mode is not None:
|
||||||
self._mode.on_app_active_changed()
|
self._mode.on_app_active_changed()
|
||||||
|
|
||||||
def read_config(self) -> None:
|
|
||||||
"""(internal)"""
|
|
||||||
from babase._appconfig import read_app_config
|
|
||||||
|
|
||||||
self._config = read_app_config()
|
|
||||||
|
|
||||||
def handle_deep_link(self, url: str) -> None:
|
def handle_deep_link(self, url: str) -> None:
|
||||||
"""Handle a deep link URL."""
|
"""Handle a deep link URL."""
|
||||||
from babase._language import Lstr
|
from babase._language import Lstr
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
"""Provides the AppConfig class."""
|
"""Provides the AppConfig class."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _babase
|
import _babase
|
||||||
@ -101,43 +100,6 @@ class AppConfig(dict):
|
|||||||
self.commit()
|
self.commit()
|
||||||
|
|
||||||
|
|
||||||
def read_app_config() -> AppConfig:
|
|
||||||
"""Read the app config."""
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
|
|
||||||
# NOTE: it is assumed that this only gets called once and the config
|
|
||||||
# object will not change from here on out
|
|
||||||
config_file_path = _babase.app.env.config_file_path
|
|
||||||
config_contents = ''
|
|
||||||
try:
|
|
||||||
if os.path.exists(config_file_path):
|
|
||||||
with open(config_file_path, encoding='utf-8') as infile:
|
|
||||||
config_contents = infile.read()
|
|
||||||
config = AppConfig(json.loads(config_contents))
|
|
||||||
else:
|
|
||||||
config = AppConfig()
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
logging.exception(
|
|
||||||
"Error reading config file '%s' at time %.3f.\n"
|
|
||||||
"Backing up broken config to'%s.broken'.",
|
|
||||||
config_file_path,
|
|
||||||
_babase.apptime(),
|
|
||||||
config_file_path,
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
shutil.copyfile(config_file_path, config_file_path + '.broken')
|
|
||||||
except Exception:
|
|
||||||
logging.exception('Error copying broken config.')
|
|
||||||
config = AppConfig()
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
def commit_app_config() -> None:
|
def commit_app_config() -> None:
|
||||||
"""Commit the config to persistent storage.
|
"""Commit the config to persistent storage.
|
||||||
|
|
||||||
@ -145,6 +107,7 @@ def commit_app_config() -> None:
|
|||||||
|
|
||||||
(internal)
|
(internal)
|
||||||
"""
|
"""
|
||||||
|
# FIXME - this should not require plus.
|
||||||
plus = _babase.app.plus
|
plus = _babase.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from functools import partial
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING, override
|
from typing import TYPE_CHECKING, override
|
||||||
|
|
||||||
from efro.log import LogLevel
|
from efro.logging import LogLevel
|
||||||
from efro.dataclassio import ioprepped, dataclass_to_json, dataclass_from_json
|
from efro.dataclassio import ioprepped, dataclass_to_json, dataclass_from_json
|
||||||
|
|
||||||
import _babase
|
import _babase
|
||||||
|
|||||||
@ -5,17 +5,14 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
from functools import partial
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING, override
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _babase
|
import _babase
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Callable, Any, Literal
|
from typing import Callable, Any, Literal
|
||||||
|
|
||||||
from babase import AppMode, UIScale
|
|
||||||
|
|
||||||
|
|
||||||
class DevConsoleTab:
|
class DevConsoleTab:
|
||||||
"""Defines behavior for a tab in the dev-console."""
|
"""Defines behavior for a tab in the dev-console."""
|
||||||
@ -38,6 +35,7 @@ class DevConsoleTab:
|
|||||||
label_scale: float = 1.0,
|
label_scale: float = 1.0,
|
||||||
corner_radius: float = 8.0,
|
corner_radius: float = 8.0,
|
||||||
style: Literal['normal', 'light'] = 'normal',
|
style: Literal['normal', 'light'] = 'normal',
|
||||||
|
disabled: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Add a button to the tab being refreshed."""
|
"""Add a button to the tab being refreshed."""
|
||||||
assert _babase.app.devconsole.is_refreshing
|
assert _babase.app.devconsole.is_refreshing
|
||||||
@ -52,6 +50,7 @@ class DevConsoleTab:
|
|||||||
label_scale,
|
label_scale,
|
||||||
corner_radius,
|
corner_radius,
|
||||||
style,
|
style,
|
||||||
|
disabled,
|
||||||
)
|
)
|
||||||
|
|
||||||
def text(
|
def text(
|
||||||
@ -98,151 +97,6 @@ class DevConsoleTab:
|
|||||||
return _babase.dev_console_base_scale()
|
return _babase.dev_console_base_scale()
|
||||||
|
|
||||||
|
|
||||||
class DevConsoleTabPython(DevConsoleTab):
|
|
||||||
"""The Python dev-console tab."""
|
|
||||||
|
|
||||||
@override
|
|
||||||
def refresh(self) -> None:
|
|
||||||
self.python_terminal()
|
|
||||||
|
|
||||||
|
|
||||||
class DevConsoleTabAppModes(DevConsoleTab):
|
|
||||||
"""Tab to switch app modes."""
|
|
||||||
|
|
||||||
@override
|
|
||||||
def refresh(self) -> None:
|
|
||||||
|
|
||||||
modes = _babase.app.mode_selector.testable_app_modes()
|
|
||||||
self.text(
|
|
||||||
'Available AppModes:',
|
|
||||||
scale=0.8,
|
|
||||||
pos=(15, 55),
|
|
||||||
h_anchor='left',
|
|
||||||
h_align='left',
|
|
||||||
v_align='none',
|
|
||||||
)
|
|
||||||
for i, mode in enumerate(modes):
|
|
||||||
self.button(
|
|
||||||
f'{mode.__module__}.{mode.__qualname__}',
|
|
||||||
pos=(10 + i * 260, 10),
|
|
||||||
size=(250, 40),
|
|
||||||
h_anchor='left',
|
|
||||||
label_scale=0.6,
|
|
||||||
call=partial(self._set_app_mode, mode),
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _set_app_mode(mode: type[AppMode]) -> None:
|
|
||||||
from babase._appintent import AppIntentDefault
|
|
||||||
|
|
||||||
intent = AppIntentDefault()
|
|
||||||
|
|
||||||
# Use private functionality to force a specific app-mode to
|
|
||||||
# handle this intent. Note that this should never be done
|
|
||||||
# outside of this explicit testing case. It is the app's job to
|
|
||||||
# determine which app-mode should be used to handle a given
|
|
||||||
# intent.
|
|
||||||
setattr(intent, '_force_app_mode_handler', mode)
|
|
||||||
|
|
||||||
_babase.app.set_intent(intent)
|
|
||||||
|
|
||||||
|
|
||||||
class DevConsoleTabUI(DevConsoleTab):
|
|
||||||
"""Tab to debug/test UI stuff."""
|
|
||||||
|
|
||||||
@override
|
|
||||||
def refresh(self) -> None:
|
|
||||||
from babase._mgen.enums import UIScale
|
|
||||||
|
|
||||||
self.text(
|
|
||||||
'Make sure all interactive UI fits in the'
|
|
||||||
' virtual bounds at all UI-scales (not counting things'
|
|
||||||
' that follow screen edges).\n'
|
|
||||||
'Note that some elements may not reflect UI-scale changes'
|
|
||||||
' until recreated.',
|
|
||||||
scale=0.6,
|
|
||||||
pos=(15, 70),
|
|
||||||
h_anchor='left',
|
|
||||||
h_align='left',
|
|
||||||
v_align='center',
|
|
||||||
)
|
|
||||||
|
|
||||||
ui_overlay = _babase.get_draw_ui_bounds()
|
|
||||||
self.button(
|
|
||||||
'Virtual Bounds ON' if ui_overlay else 'Virtual Bounds OFF',
|
|
||||||
pos=(10, 10),
|
|
||||||
size=(200, 30),
|
|
||||||
h_anchor='left',
|
|
||||||
label_scale=0.6,
|
|
||||||
call=self.toggle_ui_overlay,
|
|
||||||
style='light' if ui_overlay else 'normal',
|
|
||||||
)
|
|
||||||
x = 300
|
|
||||||
self.text(
|
|
||||||
'UI-Scale',
|
|
||||||
pos=(x - 5, 15),
|
|
||||||
h_anchor='left',
|
|
||||||
h_align='right',
|
|
||||||
v_align='none',
|
|
||||||
scale=0.6,
|
|
||||||
)
|
|
||||||
|
|
||||||
bwidth = 100
|
|
||||||
for scale in UIScale:
|
|
||||||
self.button(
|
|
||||||
scale.name.capitalize(),
|
|
||||||
pos=(x, 10),
|
|
||||||
size=(bwidth, 30),
|
|
||||||
h_anchor='left',
|
|
||||||
label_scale=0.6,
|
|
||||||
call=partial(_babase.app.set_ui_scale, scale),
|
|
||||||
style=(
|
|
||||||
'light'
|
|
||||||
if scale.name.lower() == _babase.get_ui_scale()
|
|
||||||
else 'normal'
|
|
||||||
),
|
|
||||||
)
|
|
||||||
x += bwidth + 2
|
|
||||||
|
|
||||||
def toggle_ui_overlay(self) -> None:
|
|
||||||
"""Toggle UI overlay drawing."""
|
|
||||||
_babase.set_draw_ui_bounds(not _babase.get_draw_ui_bounds())
|
|
||||||
self.request_refresh()
|
|
||||||
|
|
||||||
|
|
||||||
class DevConsoleTabTest(DevConsoleTab):
|
|
||||||
"""Test dev-console tab."""
|
|
||||||
|
|
||||||
@override
|
|
||||||
def refresh(self) -> None:
|
|
||||||
import random
|
|
||||||
|
|
||||||
self.button(
|
|
||||||
f'FLOOP-{random.randrange(200)}',
|
|
||||||
pos=(10, 10),
|
|
||||||
size=(100, 30),
|
|
||||||
h_anchor='left',
|
|
||||||
label_scale=0.6,
|
|
||||||
call=self.request_refresh,
|
|
||||||
)
|
|
||||||
self.button(
|
|
||||||
f'FLOOP2-{random.randrange(200)}',
|
|
||||||
pos=(120, 10),
|
|
||||||
size=(100, 30),
|
|
||||||
h_anchor='left',
|
|
||||||
label_scale=0.6,
|
|
||||||
style='light',
|
|
||||||
)
|
|
||||||
self.text(
|
|
||||||
'TestText',
|
|
||||||
scale=0.8,
|
|
||||||
pos=(15, 50),
|
|
||||||
h_anchor='left',
|
|
||||||
h_align='left',
|
|
||||||
v_align='none',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevConsoleTabEntry:
|
class DevConsoleTabEntry:
|
||||||
"""Represents a distinct tab in the dev-console."""
|
"""Represents a distinct tab in the dev-console."""
|
||||||
@ -263,28 +117,50 @@ class DevConsoleSubsystem:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from babase._devconsoletabs import (
|
||||||
|
DevConsoleTabPython,
|
||||||
|
DevConsoleTabAppModes,
|
||||||
|
DevConsoleTabUI,
|
||||||
|
DevConsoleTabLogging,
|
||||||
|
DevConsoleTabTest,
|
||||||
|
)
|
||||||
|
|
||||||
# All tabs in the dev-console. Add your own stuff here via
|
# All tabs in the dev-console. Add your own stuff here via
|
||||||
# plugins or whatnot.
|
# plugins or whatnot.
|
||||||
self.tabs: list[DevConsoleTabEntry] = [
|
self.tabs: list[DevConsoleTabEntry] = [
|
||||||
DevConsoleTabEntry('Python', DevConsoleTabPython),
|
DevConsoleTabEntry('Python', DevConsoleTabPython),
|
||||||
DevConsoleTabEntry('AppModes', DevConsoleTabAppModes),
|
DevConsoleTabEntry('AppModes', DevConsoleTabAppModes),
|
||||||
DevConsoleTabEntry('UI', DevConsoleTabUI),
|
DevConsoleTabEntry('UI', DevConsoleTabUI),
|
||||||
|
DevConsoleTabEntry('Logging', DevConsoleTabLogging),
|
||||||
]
|
]
|
||||||
if os.environ.get('BA_DEV_CONSOLE_TEST_TAB', '0') == '1':
|
if os.environ.get('BA_DEV_CONSOLE_TEST_TAB', '0') == '1':
|
||||||
self.tabs.append(DevConsoleTabEntry('Test', DevConsoleTabTest))
|
self.tabs.append(DevConsoleTabEntry('Test', DevConsoleTabTest))
|
||||||
self.is_refreshing = False
|
self.is_refreshing = False
|
||||||
|
self._tab_instances: dict[str, DevConsoleTab] = {}
|
||||||
|
|
||||||
def do_refresh_tab(self, tabname: str) -> None:
|
def do_refresh_tab(self, tabname: str) -> None:
|
||||||
"""Called by the C++ layer when a tab should be filled out."""
|
"""Called by the C++ layer when a tab should be filled out."""
|
||||||
assert _babase.in_logic_thread()
|
assert _babase.in_logic_thread()
|
||||||
|
|
||||||
# FIXME: We currently won't handle multiple tabs with the same
|
# Make noise if we have repeating tab names, as that breaks our
|
||||||
# name. We should give a clean error or something in that case.
|
# logic.
|
||||||
tab: DevConsoleTab | None = None
|
if __debug__:
|
||||||
for tabentry in self.tabs:
|
alltabnames = set[str](tabentry.name for tabentry in self.tabs)
|
||||||
if tabentry.name == tabname:
|
if len(alltabnames) != len(self.tabs):
|
||||||
tab = tabentry.factory()
|
logging.error(
|
||||||
break
|
'Duplicate dev-console tab names found;'
|
||||||
|
' tabs may behave unpredictably.'
|
||||||
|
)
|
||||||
|
|
||||||
|
tab: DevConsoleTab | None = self._tab_instances.get(tabname)
|
||||||
|
|
||||||
|
# If we haven't instantiated this tab yet, do so.
|
||||||
|
if tab is None:
|
||||||
|
for tabentry in self.tabs:
|
||||||
|
if tabentry.name == tabname:
|
||||||
|
tab = self._tab_instances[tabname] = tabentry.factory()
|
||||||
|
break
|
||||||
|
|
||||||
if tab is None:
|
if tab is None:
|
||||||
logging.error(
|
logging.error(
|
||||||
|
|||||||
610
src/assets/ba_data/python/babase/_devconsoletabs.py
Normal file
610
src/assets/ba_data/python/babase/_devconsoletabs.py
Normal file
@ -0,0 +1,610 @@
|
|||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Predefined tabs for the dev console."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
import logging
|
||||||
|
from functools import partial
|
||||||
|
from typing import TYPE_CHECKING, override, TypeVar, Generic
|
||||||
|
|
||||||
|
import _babase
|
||||||
|
|
||||||
|
from babase._devconsole import DevConsoleTab
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Callable, Literal
|
||||||
|
|
||||||
|
from bacommon.loggercontrol import LoggerControlConfig
|
||||||
|
from babase import AppMode
|
||||||
|
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
|
class DevConsoleTabPython(DevConsoleTab):
|
||||||
|
"""The Python dev-console tab."""
|
||||||
|
|
||||||
|
@override
|
||||||
|
def refresh(self) -> None:
|
||||||
|
self.python_terminal()
|
||||||
|
|
||||||
|
|
||||||
|
class DevConsoleTabAppModes(DevConsoleTab):
|
||||||
|
"""Tab to switch app modes."""
|
||||||
|
|
||||||
|
@override
|
||||||
|
def refresh(self) -> None:
|
||||||
|
|
||||||
|
bwidth = 260
|
||||||
|
bpadding = 5
|
||||||
|
modes = _babase.app.mode_selector.testable_app_modes()
|
||||||
|
xoffs = -0.5 * bwidth * len(modes)
|
||||||
|
|
||||||
|
self.text(
|
||||||
|
'Available AppModes:',
|
||||||
|
scale=0.8,
|
||||||
|
pos=(0, 75),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
for i, mode in enumerate(modes):
|
||||||
|
self.button(
|
||||||
|
f'{mode.__module__}.{mode.__qualname__}',
|
||||||
|
pos=(xoffs + i * bwidth + bpadding, 10),
|
||||||
|
size=(bwidth - 2.0 * bpadding, 40),
|
||||||
|
label_scale=0.6,
|
||||||
|
call=partial(self._set_app_mode, mode),
|
||||||
|
style=(
|
||||||
|
'light' if isinstance(_babase.app._mode, mode) else 'normal'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _set_app_mode(self, mode: type[AppMode]) -> None:
|
||||||
|
from babase._appintent import AppIntentDefault
|
||||||
|
|
||||||
|
intent = AppIntentDefault()
|
||||||
|
|
||||||
|
# Use private functionality to force a specific app-mode to
|
||||||
|
# handle this intent. Note that this should never be done
|
||||||
|
# outside of this explicit testing case. It is the app's job to
|
||||||
|
# determine which app-mode should be used to handle a given
|
||||||
|
# intent.
|
||||||
|
setattr(intent, '_force_app_mode_handler', mode)
|
||||||
|
|
||||||
|
_babase.app.set_intent(intent)
|
||||||
|
|
||||||
|
# Slight hackish: need to wait a moment before refreshing to
|
||||||
|
# pick up the new mode, as mode switches are asynchronous.
|
||||||
|
_babase.apptimer(0.1, self.request_refresh)
|
||||||
|
|
||||||
|
|
||||||
|
class DevConsoleTabUI(DevConsoleTab):
|
||||||
|
"""Tab to debug/test UI stuff."""
|
||||||
|
|
||||||
|
@override
|
||||||
|
def refresh(self) -> None:
|
||||||
|
from babase._mgen.enums import UIScale
|
||||||
|
|
||||||
|
xoffs = -375
|
||||||
|
|
||||||
|
self.text(
|
||||||
|
'Make sure all interactive UI fits in the'
|
||||||
|
' virtual bounds at all UI-scales (not counting things'
|
||||||
|
' that follow screen edges).\n'
|
||||||
|
'Note that some elements may not reflect UI-scale changes'
|
||||||
|
' until recreated.',
|
||||||
|
scale=0.6,
|
||||||
|
pos=(xoffs + 15, 70),
|
||||||
|
# h_anchor='left',
|
||||||
|
h_align='left',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
|
||||||
|
ui_overlay = _babase.get_draw_ui_bounds()
|
||||||
|
self.button(
|
||||||
|
'Virtual Bounds ON' if ui_overlay else 'Virtual Bounds OFF',
|
||||||
|
pos=(xoffs + 10, 10),
|
||||||
|
size=(200, 30),
|
||||||
|
# h_anchor='left',
|
||||||
|
label_scale=0.6,
|
||||||
|
call=self.toggle_ui_overlay,
|
||||||
|
style='light' if ui_overlay else 'normal',
|
||||||
|
)
|
||||||
|
x = 300
|
||||||
|
self.text(
|
||||||
|
'UI-Scale',
|
||||||
|
pos=(xoffs + x - 5, 15),
|
||||||
|
# h_anchor='left',
|
||||||
|
h_align='right',
|
||||||
|
v_align='none',
|
||||||
|
scale=0.6,
|
||||||
|
)
|
||||||
|
|
||||||
|
bwidth = 100
|
||||||
|
for scale in UIScale:
|
||||||
|
self.button(
|
||||||
|
scale.name.capitalize(),
|
||||||
|
pos=(xoffs + x, 10),
|
||||||
|
size=(bwidth, 30),
|
||||||
|
# h_anchor='left',
|
||||||
|
label_scale=0.6,
|
||||||
|
call=partial(_babase.app.set_ui_scale, scale),
|
||||||
|
style=(
|
||||||
|
'light'
|
||||||
|
if scale.name.lower() == _babase.get_ui_scale()
|
||||||
|
else 'normal'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
x += bwidth + 2
|
||||||
|
|
||||||
|
def toggle_ui_overlay(self) -> None:
|
||||||
|
"""Toggle UI overlay drawing."""
|
||||||
|
_babase.set_draw_ui_bounds(not _babase.get_draw_ui_bounds())
|
||||||
|
self.request_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
class Table(Generic[T]):
|
||||||
|
"""Used to show controls for arbitrarily large data in a grid form."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
entries: list[T],
|
||||||
|
draw_entry_call: Callable[
|
||||||
|
[int, T, DevConsoleTab, float, float, float, float], None
|
||||||
|
],
|
||||||
|
*,
|
||||||
|
entry_width: float = 300.0,
|
||||||
|
entry_height: float = 40.0,
|
||||||
|
margin_left_right: float = 60.0,
|
||||||
|
debug_bounds: bool = False,
|
||||||
|
max_columns: int | None = None,
|
||||||
|
) -> None:
|
||||||
|
self._title = title
|
||||||
|
self._entry_width = entry_width
|
||||||
|
self._entry_height = entry_height
|
||||||
|
self._margin_left_right = margin_left_right
|
||||||
|
self._focus_entry_index = 0
|
||||||
|
self._entries_per_page = 1
|
||||||
|
self._debug_bounds = debug_bounds
|
||||||
|
self._entries = entries
|
||||||
|
self._draw_entry_call = draw_entry_call
|
||||||
|
self._max_columns = max_columns
|
||||||
|
|
||||||
|
# Values updated on refresh (for aligning other custom
|
||||||
|
# widgets/etc.)
|
||||||
|
self.top_left: tuple[float, float] = (0.0, 0.0)
|
||||||
|
self.top_right: tuple[float, float] = (0.0, 0.0)
|
||||||
|
|
||||||
|
def set_entries(self, entries: list[T]) -> None:
|
||||||
|
"""Update table entries."""
|
||||||
|
self._entries = entries
|
||||||
|
|
||||||
|
# Clamp focus to new entries.
|
||||||
|
self._focus_entry_index = max(
|
||||||
|
0, min(len(self._entries) - 1, self._focus_entry_index)
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_focus_entry_index(self, index: int) -> None:
|
||||||
|
"""Explicitly set the focused entry.
|
||||||
|
|
||||||
|
This affects which page is shown at the next refresh.
|
||||||
|
"""
|
||||||
|
self._focus_entry_index = max(0, min(len(self._entries) - 1, index))
|
||||||
|
|
||||||
|
def refresh(self, tab: DevConsoleTab) -> None:
|
||||||
|
"""Call to refresh the data."""
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
|
||||||
|
margin_top = 50.0
|
||||||
|
margin_bottom = 10.0
|
||||||
|
|
||||||
|
# Update how much we can fit on a page based on our current size.
|
||||||
|
max_entry_area_width = tab.width - (self._margin_left_right * 2.0)
|
||||||
|
max_entry_area_height = tab.height - (margin_top + margin_bottom)
|
||||||
|
columns = max(1, int(max_entry_area_width / self._entry_width))
|
||||||
|
if self._max_columns is not None:
|
||||||
|
columns = min(columns, self._max_columns)
|
||||||
|
rows = max(1, int(max_entry_area_height / self._entry_height))
|
||||||
|
self._entries_per_page = rows * columns
|
||||||
|
|
||||||
|
# See which page our focus index falls in.
|
||||||
|
pagemax = math.ceil(len(self._entries) / self._entries_per_page)
|
||||||
|
|
||||||
|
page = self._focus_entry_index // self._entries_per_page
|
||||||
|
entry_offset = page * self._entries_per_page
|
||||||
|
|
||||||
|
entries_on_this_page = min(
|
||||||
|
self._entries_per_page, len(self._entries) - entry_offset
|
||||||
|
)
|
||||||
|
columns_on_this_page = math.ceil(entries_on_this_page / rows)
|
||||||
|
rows_on_this_page = min(entries_on_this_page, rows)
|
||||||
|
|
||||||
|
# We attach things to the center so resizes are smooth but we do
|
||||||
|
# some math in a left-centric way.
|
||||||
|
center_to_left = tab.width * -0.5
|
||||||
|
|
||||||
|
# Center our columns.
|
||||||
|
xoffs = 0.5 * (
|
||||||
|
max_entry_area_width - columns_on_this_page * self._entry_width
|
||||||
|
)
|
||||||
|
|
||||||
|
# Align everything to the bottom of the dev-console.
|
||||||
|
yoffs = -1.0 * (
|
||||||
|
tab.height
|
||||||
|
- (
|
||||||
|
rows_on_this_page * self._entry_height
|
||||||
|
+ margin_top
|
||||||
|
+ margin_bottom
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Keep our corners up to date for user use.
|
||||||
|
self.top_left = (center_to_left + xoffs, tab.height + yoffs)
|
||||||
|
self.top_right = (
|
||||||
|
self.top_left[0]
|
||||||
|
+ self._margin_left_right * 2.0
|
||||||
|
+ columns_on_this_page * self._entry_width,
|
||||||
|
self.top_left[1],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Page left/right buttons.
|
||||||
|
tab.button(
|
||||||
|
'<',
|
||||||
|
pos=(center_to_left + xoffs, margin_bottom),
|
||||||
|
size=(
|
||||||
|
self._margin_left_right,
|
||||||
|
rows_on_this_page * self._entry_height,
|
||||||
|
),
|
||||||
|
# h_anchor='left',
|
||||||
|
call=partial(self._page_left, tab),
|
||||||
|
disabled=entry_offset == 0,
|
||||||
|
)
|
||||||
|
tab.button(
|
||||||
|
'>',
|
||||||
|
pos=(
|
||||||
|
center_to_left
|
||||||
|
+ xoffs
|
||||||
|
+ self._margin_left_right
|
||||||
|
+ columns_on_this_page * self._entry_width,
|
||||||
|
margin_bottom,
|
||||||
|
),
|
||||||
|
size=(
|
||||||
|
self._margin_left_right,
|
||||||
|
rows_on_this_page * self._entry_height,
|
||||||
|
),
|
||||||
|
# h_anchor='left',
|
||||||
|
call=partial(self._page_right, tab),
|
||||||
|
disabled=(
|
||||||
|
entry_offset + entries_on_this_page >= len(self._entries)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for column in range(columns):
|
||||||
|
for row in range(rows):
|
||||||
|
entry_index = entry_offset + column * rows + row
|
||||||
|
if entry_index >= len(self._entries):
|
||||||
|
break
|
||||||
|
|
||||||
|
xpos = (
|
||||||
|
xoffs + self._margin_left_right + self._entry_width * column
|
||||||
|
)
|
||||||
|
ypos = (
|
||||||
|
yoffs
|
||||||
|
+ tab.height
|
||||||
|
- margin_top
|
||||||
|
- self._entry_height * (row + 1.0)
|
||||||
|
)
|
||||||
|
# Draw debug bounds.
|
||||||
|
if self._debug_bounds:
|
||||||
|
tab.button(
|
||||||
|
str(entry_index),
|
||||||
|
pos=(
|
||||||
|
center_to_left + xpos,
|
||||||
|
ypos,
|
||||||
|
),
|
||||||
|
size=(self._entry_width, self._entry_height),
|
||||||
|
# h_anchor='left',
|
||||||
|
)
|
||||||
|
# Run user drawing.
|
||||||
|
self._draw_entry_call(
|
||||||
|
entry_index,
|
||||||
|
self._entries[entry_index],
|
||||||
|
tab,
|
||||||
|
center_to_left + xpos,
|
||||||
|
ypos,
|
||||||
|
self._entry_width,
|
||||||
|
self._entry_height,
|
||||||
|
)
|
||||||
|
|
||||||
|
if entry_index >= len(self._entries):
|
||||||
|
break
|
||||||
|
|
||||||
|
tab.text(
|
||||||
|
f'{self._title} ({page + 1}/{pagemax})',
|
||||||
|
scale=0.8,
|
||||||
|
pos=(0, yoffs + tab.height - margin_top * 0.5),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
|
||||||
|
def _page_right(self, tab: DevConsoleTab) -> None:
|
||||||
|
# Set focus on the first entry in the page before the current.
|
||||||
|
page = self._focus_entry_index // self._entries_per_page
|
||||||
|
page += 1
|
||||||
|
self.set_focus_entry_index(page * self._entries_per_page)
|
||||||
|
tab.request_refresh()
|
||||||
|
|
||||||
|
def _page_left(self, tab: DevConsoleTab) -> None:
|
||||||
|
# Set focus on the first entry in the page after the current.
|
||||||
|
page = self._focus_entry_index // self._entries_per_page
|
||||||
|
page -= 1
|
||||||
|
self.set_focus_entry_index(page * self._entries_per_page)
|
||||||
|
tab.request_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
class DevConsoleTabLogging(DevConsoleTab):
|
||||||
|
"""Tab to wrangle logging levels."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
|
||||||
|
self._table = Table(
|
||||||
|
title='Logging Levels',
|
||||||
|
entry_width=800,
|
||||||
|
debug_bounds=False,
|
||||||
|
entries=list[str](),
|
||||||
|
draw_entry_call=self._draw_entry,
|
||||||
|
max_columns=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
@override
|
||||||
|
def refresh(self) -> None:
|
||||||
|
assert self._table is not None
|
||||||
|
|
||||||
|
# Update table entries with the latest set of loggers (this can
|
||||||
|
# change over time).
|
||||||
|
self._table.set_entries(
|
||||||
|
['root'] + sorted(logging.root.manager.loggerDict)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Draw the table.
|
||||||
|
self._table.refresh(self)
|
||||||
|
|
||||||
|
# Draw our control buttons in the corners.
|
||||||
|
tl = self._table.top_left
|
||||||
|
tr = self._table.top_right
|
||||||
|
bwidth = 140.0
|
||||||
|
bheight = 30.0
|
||||||
|
bvpad = 10.0
|
||||||
|
self.button(
|
||||||
|
'Reset',
|
||||||
|
pos=(tl[0], tl[1] - bheight - bvpad),
|
||||||
|
size=(bwidth, bheight),
|
||||||
|
label_scale=0.6,
|
||||||
|
call=self._reset,
|
||||||
|
disabled=(
|
||||||
|
not self._get_reset_logger_control_config().would_make_changes()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.button(
|
||||||
|
'Cloud Control OFF',
|
||||||
|
pos=(tr[0] - bwidth, tl[1] - bheight - bvpad),
|
||||||
|
size=(bwidth, bheight),
|
||||||
|
label_scale=0.6,
|
||||||
|
disabled=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_reset_logger_control_config(self) -> LoggerControlConfig:
|
||||||
|
from bacommon.logging import get_base_logger_control_config_client
|
||||||
|
|
||||||
|
return get_base_logger_control_config_client()
|
||||||
|
|
||||||
|
def _reset(self) -> None:
|
||||||
|
|
||||||
|
self._get_reset_logger_control_config().apply()
|
||||||
|
|
||||||
|
# Let the native layer know that levels changed.
|
||||||
|
_babase.update_internal_logger_levels()
|
||||||
|
|
||||||
|
# Blow away any existing values in app-config.
|
||||||
|
appconfig = _babase.app.config
|
||||||
|
if 'Log Levels' in appconfig:
|
||||||
|
del appconfig['Log Levels']
|
||||||
|
appconfig.commit()
|
||||||
|
|
||||||
|
self.request_refresh()
|
||||||
|
|
||||||
|
def _set_entry_val(self, entry_index: int, entry: str, val: int) -> None:
|
||||||
|
|
||||||
|
from bacommon.logging import get_base_logger_control_config_client
|
||||||
|
from bacommon.loggercontrol import LoggerControlConfig
|
||||||
|
|
||||||
|
# Focus on this entry with any interaction, so if we get resized
|
||||||
|
# it'll still be visible.
|
||||||
|
self._table.set_focus_entry_index(entry_index)
|
||||||
|
|
||||||
|
logging.getLogger(entry).setLevel(val)
|
||||||
|
|
||||||
|
# Let the native layer know that levels changed.
|
||||||
|
_babase.update_internal_logger_levels()
|
||||||
|
|
||||||
|
# Store only changes compared to the base config.
|
||||||
|
baseconfig = get_base_logger_control_config_client()
|
||||||
|
config = LoggerControlConfig.from_current_loggers().diff(baseconfig)
|
||||||
|
|
||||||
|
appconfig = _babase.app.config
|
||||||
|
appconfig['Log Levels'] = config.levels
|
||||||
|
appconfig.commit()
|
||||||
|
|
||||||
|
self.request_refresh()
|
||||||
|
|
||||||
|
def _draw_entry(
|
||||||
|
self,
|
||||||
|
entry_index: int,
|
||||||
|
entry: str,
|
||||||
|
tab: DevConsoleTab,
|
||||||
|
x: float,
|
||||||
|
y: float,
|
||||||
|
width: float,
|
||||||
|
height: float,
|
||||||
|
) -> None:
|
||||||
|
# pylint: disable=too-many-positional-arguments
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
|
||||||
|
xoffs = -15.0
|
||||||
|
bwidth = 80.0
|
||||||
|
btextscale = 0.5
|
||||||
|
tab.text(
|
||||||
|
entry,
|
||||||
|
(
|
||||||
|
x + width - bwidth * 6.5 - 10.0 + xoffs,
|
||||||
|
y + height * 0.5,
|
||||||
|
),
|
||||||
|
h_align='right',
|
||||||
|
scale=0.7,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(entry)
|
||||||
|
level = logger.level
|
||||||
|
index = 0
|
||||||
|
if entry != 'root' and level == logging.NOTSET:
|
||||||
|
# Show the level being inherited in NOTSET cases.
|
||||||
|
notsetlevelname = logging.getLevelName(logger.getEffectiveLevel())
|
||||||
|
if notsetlevelname == 'NOTSET':
|
||||||
|
notsetname = 'Not Set'
|
||||||
|
else:
|
||||||
|
notsetname = f'Not Set ({notsetlevelname.capitalize()})'
|
||||||
|
else:
|
||||||
|
notsetname = 'Not Set'
|
||||||
|
tab.button(
|
||||||
|
notsetname,
|
||||||
|
pos=(x + width - bwidth * 6.5 + xoffs + 1.0, y + 5.0),
|
||||||
|
size=(bwidth * 1.5 - 2.0, height - 10),
|
||||||
|
label_scale=btextscale,
|
||||||
|
style='light' if level == logging.NOTSET else 'normal',
|
||||||
|
call=partial(
|
||||||
|
self._set_entry_val, entry_index, entry, logging.NOTSET
|
||||||
|
),
|
||||||
|
)
|
||||||
|
index += 1
|
||||||
|
tab.button(
|
||||||
|
'Debug',
|
||||||
|
pos=(x + width - bwidth * 5 + xoffs + 1.0, y + 5.0),
|
||||||
|
size=(bwidth - 2.0, height - 10),
|
||||||
|
label_scale=btextscale,
|
||||||
|
style='light' if level == logging.DEBUG else 'normal',
|
||||||
|
call=partial(
|
||||||
|
self._set_entry_val, entry_index, entry, logging.DEBUG
|
||||||
|
),
|
||||||
|
)
|
||||||
|
index += 1
|
||||||
|
tab.button(
|
||||||
|
'Info',
|
||||||
|
pos=(x + width - bwidth * 4 + xoffs + 1.0, y + 5.0),
|
||||||
|
size=(bwidth - 2.0, height - 10),
|
||||||
|
label_scale=btextscale,
|
||||||
|
style='light' if level == logging.INFO else 'normal',
|
||||||
|
call=partial(self._set_entry_val, entry_index, entry, logging.INFO),
|
||||||
|
)
|
||||||
|
index += 1
|
||||||
|
tab.button(
|
||||||
|
'Warning',
|
||||||
|
pos=(x + width - bwidth * 3 + xoffs + 1.0, y + 5.0),
|
||||||
|
size=(bwidth - 2.0, height - 10),
|
||||||
|
label_scale=btextscale,
|
||||||
|
style='light' if level == logging.WARNING else 'normal',
|
||||||
|
call=partial(
|
||||||
|
self._set_entry_val, entry_index, entry, logging.WARNING
|
||||||
|
),
|
||||||
|
)
|
||||||
|
index += 1
|
||||||
|
tab.button(
|
||||||
|
'Error',
|
||||||
|
pos=(x + width - bwidth * 2 + xoffs + 1.0, y + 5.0),
|
||||||
|
size=(bwidth - 2.0, height - 10),
|
||||||
|
label_scale=btextscale,
|
||||||
|
style='light' if level == logging.ERROR else 'normal',
|
||||||
|
call=partial(
|
||||||
|
self._set_entry_val, entry_index, entry, logging.ERROR
|
||||||
|
),
|
||||||
|
)
|
||||||
|
index += 1
|
||||||
|
tab.button(
|
||||||
|
'Critical',
|
||||||
|
pos=(x + width - bwidth * 1 + xoffs + 1.0, y + 5.0),
|
||||||
|
size=(bwidth - 2.0, height - 10),
|
||||||
|
label_scale=btextscale,
|
||||||
|
style='light' if level == logging.CRITICAL else 'normal',
|
||||||
|
call=partial(
|
||||||
|
self._set_entry_val, entry_index, entry, logging.CRITICAL
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DevConsoleTabTest(DevConsoleTab):
|
||||||
|
"""Test dev-console tab."""
|
||||||
|
|
||||||
|
@override
|
||||||
|
def refresh(self) -> None:
|
||||||
|
|
||||||
|
self.button(
|
||||||
|
f'FLOOP-{random.randrange(200)}',
|
||||||
|
pos=(10, 10),
|
||||||
|
size=(100, 30),
|
||||||
|
h_anchor='left',
|
||||||
|
label_scale=0.6,
|
||||||
|
call=self.request_refresh,
|
||||||
|
)
|
||||||
|
self.button(
|
||||||
|
f'FLOOP2-{random.randrange(200)}',
|
||||||
|
pos=(120, 10),
|
||||||
|
size=(100, 30),
|
||||||
|
h_anchor='left',
|
||||||
|
label_scale=0.6,
|
||||||
|
style='light',
|
||||||
|
)
|
||||||
|
self.text(
|
||||||
|
'TestText',
|
||||||
|
scale=0.8,
|
||||||
|
pos=(15, 50),
|
||||||
|
h_anchor='left',
|
||||||
|
h_align='left',
|
||||||
|
v_align='none',
|
||||||
|
)
|
||||||
|
|
||||||
|
# Throw little bits of text in the corners to make sure
|
||||||
|
# widths/heights are correct.
|
||||||
|
self.text(
|
||||||
|
'BL',
|
||||||
|
scale=0.25,
|
||||||
|
pos=(0, 0),
|
||||||
|
h_anchor='left',
|
||||||
|
h_align='left',
|
||||||
|
v_align='bottom',
|
||||||
|
)
|
||||||
|
self.text(
|
||||||
|
'BR',
|
||||||
|
scale=0.25,
|
||||||
|
pos=(self.width, 0),
|
||||||
|
h_anchor='left',
|
||||||
|
h_align='right',
|
||||||
|
v_align='bottom',
|
||||||
|
)
|
||||||
|
self.text(
|
||||||
|
'TL',
|
||||||
|
scale=0.25,
|
||||||
|
pos=(0, self.height),
|
||||||
|
h_anchor='left',
|
||||||
|
h_align='left',
|
||||||
|
v_align='top',
|
||||||
|
)
|
||||||
|
self.text(
|
||||||
|
'TR',
|
||||||
|
scale=0.25,
|
||||||
|
pos=(self.width, self.height),
|
||||||
|
h_anchor='left',
|
||||||
|
h_align='right',
|
||||||
|
v_align='top',
|
||||||
|
)
|
||||||
@ -9,11 +9,11 @@ import logging
|
|||||||
import warnings
|
import warnings
|
||||||
from typing import TYPE_CHECKING, override
|
from typing import TYPE_CHECKING, override
|
||||||
|
|
||||||
from efro.log import LogLevel
|
from efro.logging import LogLevel
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from efro.log import LogEntry, LogHandler
|
from efro.logging import LogEntry, LogHandler
|
||||||
|
|
||||||
_g_babase_imported = False # pylint: disable=invalid-name
|
_g_babase_imported = False # pylint: disable=invalid-name
|
||||||
_g_babase_app_started = False # pylint: disable=invalid-name
|
_g_babase_app_started = False # pylint: disable=invalid-name
|
||||||
@ -186,7 +186,10 @@ def _feed_logs_to_babase(log_handler: LogHandler) -> None:
|
|||||||
# Forward this along to the engine to display in the in-app
|
# Forward this along to the engine to display in the in-app
|
||||||
# console, in the Android log, etc.
|
# console, in the Android log, etc.
|
||||||
_babase.emit_log(
|
_babase.emit_log(
|
||||||
name=entry.name, level=entry.level.name, message=entry.message
|
name=entry.name,
|
||||||
|
level=entry.level.name,
|
||||||
|
timestamp=entry.time.timestamp(),
|
||||||
|
message=entry.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
# We also want to feed some logs to the old v1-cloud-log system.
|
# We also want to feed some logs to the old v1-cloud-log system.
|
||||||
|
|||||||
@ -14,6 +14,7 @@ from babase import (
|
|||||||
AppIntentExec,
|
AppIntentExec,
|
||||||
AppIntentDefault,
|
AppIntentDefault,
|
||||||
invoke_main_menu,
|
invoke_main_menu,
|
||||||
|
in_logic_thread,
|
||||||
screenmessage,
|
screenmessage,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,13 +23,19 @@ import _baclassic
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
from babase import AppIntent
|
from efro.call import CallbackRegistration
|
||||||
|
from babase import AppIntent, AccountV2Handle
|
||||||
from bauiv1 import UIV1AppSubsystem, MainWindow, MainWindowState
|
from bauiv1 import UIV1AppSubsystem, MainWindow, MainWindowState
|
||||||
|
|
||||||
|
|
||||||
class ClassicAppMode(AppMode):
|
class ClassicAppMode(AppMode):
|
||||||
"""AppMode for the classic BombSquad experience."""
|
"""AppMode for the classic BombSquad experience."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._on_primary_account_changed_callback: (
|
||||||
|
CallbackRegistration | None
|
||||||
|
) = None
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_app_experience(cls) -> AppExperience:
|
def get_app_experience(cls) -> AppExperience:
|
||||||
@ -54,6 +61,8 @@ class ClassicAppMode(AppMode):
|
|||||||
# Let the native layer do its thing.
|
# Let the native layer do its thing.
|
||||||
_baclassic.classic_app_mode_activate()
|
_baclassic.classic_app_mode_activate()
|
||||||
|
|
||||||
|
assert app.plus is not None
|
||||||
|
|
||||||
# Wire up the root ui to do what we want.
|
# Wire up the root ui to do what we want.
|
||||||
ui = app.ui_v1
|
ui = app.ui_v1
|
||||||
ui.root_ui_calls[ui.RootUIElement.ACCOUNT_BUTTON] = (
|
ui.root_ui_calls[ui.RootUIElement.ACCOUNT_BUTTON] = (
|
||||||
@ -108,9 +117,24 @@ class ClassicAppMode(AppMode):
|
|||||||
self._root_ui_chest_slot_pressed, 4
|
self._root_ui_chest_slot_pressed, 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# We want to be informed when primary account changes.
|
||||||
|
self._on_primary_account_changed_callback = (
|
||||||
|
app.plus.accounts.on_primary_account_changed_callbacks.add(
|
||||||
|
self.update_for_primary_account
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Establish subscriptions/etc. for any current primary account.
|
||||||
|
self.update_for_primary_account(app.plus.accounts.primary)
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
|
|
||||||
|
# Stop being informed of account changes.
|
||||||
|
self._on_primary_account_changed_callback = None
|
||||||
|
|
||||||
|
# Remove any listeners for any current primary account.
|
||||||
|
self.update_for_primary_account(None)
|
||||||
|
|
||||||
# Save where we were in the UI so we return there next time.
|
# Save where we were in the UI so we return there next time.
|
||||||
if app.classic is not None:
|
if app.classic is not None:
|
||||||
app.classic.save_ui_state()
|
app.classic.save_ui_state()
|
||||||
@ -125,6 +149,14 @@ class ClassicAppMode(AppMode):
|
|||||||
if not app.active:
|
if not app.active:
|
||||||
invoke_main_menu()
|
invoke_main_menu()
|
||||||
|
|
||||||
|
def update_for_primary_account(
|
||||||
|
self, account: AccountV2Handle | None
|
||||||
|
) -> None:
|
||||||
|
"""Update subscriptions/etc. for a new primary account state."""
|
||||||
|
assert in_logic_thread()
|
||||||
|
del account # Unused.
|
||||||
|
# print('WOULD WIRE UP LISTENERS FOR ACCOUNT', account)
|
||||||
|
|
||||||
def _root_ui_menu_press(self) -> None:
|
def _root_ui_menu_press(self) -> None:
|
||||||
from babase import push_back_press
|
from babase import push_back_press
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
@ -27,7 +28,7 @@ import __main__
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from efro.log import LogHandler
|
from efro.logging import LogHandler
|
||||||
|
|
||||||
# IMPORTANT - It is likely (and in some cases expected) that this
|
# IMPORTANT - It is likely (and in some cases expected) that this
|
||||||
# module's code will be exec'ed multiple times. This is because it is
|
# module's code will be exec'ed multiple times. This is because it is
|
||||||
@ -52,7 +53,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
# Build number and version of the ballistica binary we expect to be
|
# Build number and version of the ballistica binary we expect to be
|
||||||
# using.
|
# using.
|
||||||
TARGET_BALLISTICA_BUILD = 22025
|
TARGET_BALLISTICA_BUILD = 22040
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.37'
|
TARGET_BALLISTICA_VERSION = '1.7.37'
|
||||||
|
|
||||||
|
|
||||||
@ -87,14 +88,13 @@ class EnvConfig:
|
|||||||
# stderr into the engine so they show up on in-app consoles, etc.
|
# stderr into the engine so they show up on in-app consoles, etc.
|
||||||
log_handler: LogHandler | None
|
log_handler: LogHandler | None
|
||||||
|
|
||||||
# Initial data from the ballisticakit-config.json file. This is
|
# Initial data from the config.json file in the config dir. The
|
||||||
# passed mostly as an optimization to avoid reading the same config
|
# config file is parsed by
|
||||||
# file twice, since config data is first needed in baenv and next in
|
|
||||||
# the engine. It will be cleared after passing it to the app's
|
|
||||||
# config management subsystem and should not be accessed by any
|
|
||||||
# other code.
|
|
||||||
initial_app_config: Any
|
initial_app_config: Any
|
||||||
|
|
||||||
|
# Timestamp when we first started doing stuff.
|
||||||
|
launch_time: float
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class _EnvGlobals:
|
class _EnvGlobals:
|
||||||
@ -172,6 +172,11 @@ def configure(
|
|||||||
are imported; the environment is locked in as soon as that happens.
|
are imported; the environment is locked in as soon as that happens.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Measure when we start doing this stuff. We plug this in to show
|
||||||
|
# relative times in our log timestamp displays and also pass this to
|
||||||
|
# the engine to do the same there.
|
||||||
|
launch_time = time.time()
|
||||||
|
|
||||||
envglobals = _EnvGlobals.get()
|
envglobals = _EnvGlobals.get()
|
||||||
|
|
||||||
# Keep track of whether we've been *called*, not whether a config
|
# Keep track of whether we've been *called*, not whether a config
|
||||||
@ -206,11 +211,19 @@ def configure(
|
|||||||
config_dir,
|
config_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
# The second thing we do is set up our logging system and pipe
|
# Set up our log-handler and pipe Python's stdout/stderr into it.
|
||||||
# Python's stdout/stderr into it. At this point we can at least
|
# Later, once the engine comes up, the handler will feed its logs
|
||||||
# debug problems on systems where native stdout/stderr is not easily
|
# (including cached history) to the os-specific output location.
|
||||||
# accessible such as Android.
|
# This means anything printed or logged at this point forward should
|
||||||
log_handler = _setup_logging() if setup_logging else None
|
# be visible on all platforms.
|
||||||
|
log_handler = _setup_logging(launch_time) if setup_logging else None
|
||||||
|
|
||||||
|
# Load the raw app-config dict.
|
||||||
|
app_config = _read_app_config(os.path.join(config_dir, 'config.json'))
|
||||||
|
|
||||||
|
# Set logging levels to stored values or defaults.
|
||||||
|
if setup_logging:
|
||||||
|
_set_log_levels(app_config)
|
||||||
|
|
||||||
# We want to always be run in UTF-8 mode; complain if we're not.
|
# We want to always be run in UTF-8 mode; complain if we're not.
|
||||||
if sys.flags.utf8_mode != 1:
|
if sys.flags.utf8_mode != 1:
|
||||||
@ -235,10 +248,46 @@ def configure(
|
|||||||
site_python_dir=site_python_dir,
|
site_python_dir=site_python_dir,
|
||||||
log_handler=log_handler,
|
log_handler=log_handler,
|
||||||
is_user_app_python_dir=is_user_app_python_dir,
|
is_user_app_python_dir=is_user_app_python_dir,
|
||||||
initial_app_config=None,
|
initial_app_config=app_config,
|
||||||
|
launch_time=launch_time,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _read_app_config(config_file_path: str) -> dict:
|
||||||
|
"""Read the app config."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
config: dict | Any
|
||||||
|
config_contents = ''
|
||||||
|
try:
|
||||||
|
if os.path.exists(config_file_path):
|
||||||
|
with open(config_file_path, encoding='utf-8') as infile:
|
||||||
|
config_contents = infile.read()
|
||||||
|
config = json.loads(config_contents)
|
||||||
|
if not isinstance(config, dict):
|
||||||
|
raise RuntimeError('Got non-dict for config root.')
|
||||||
|
else:
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logging.exception(
|
||||||
|
"Error reading config file '%s'.\n"
|
||||||
|
"Backing up broken config to'%s.broken'.",
|
||||||
|
config_file_path,
|
||||||
|
config_file_path,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
shutil.copyfile(config_file_path, config_file_path + '.broken')
|
||||||
|
except Exception:
|
||||||
|
logging.exception('Error copying broken config.')
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def _calc_data_dir(data_dir: str | None) -> str:
|
def _calc_data_dir(data_dir: str | None) -> str:
|
||||||
if data_dir is None:
|
if data_dir is None:
|
||||||
# To calc default data_dir, we assume this module was imported
|
# To calc default data_dir, we assume this module was imported
|
||||||
@ -262,23 +311,57 @@ def _calc_data_dir(data_dir: str | None) -> str:
|
|||||||
return data_dir
|
return data_dir
|
||||||
|
|
||||||
|
|
||||||
def _setup_logging() -> LogHandler:
|
def _setup_logging(launch_time: float) -> LogHandler:
|
||||||
from efro.log import setup_logging, LogLevel
|
from efro.logging import setup_logging, LogLevel
|
||||||
|
|
||||||
# TODO: should set this up with individual loggers under a top level
|
|
||||||
# 'ba' logger, and at that point we can kill off the
|
|
||||||
# suppress_non_root_debug option since we'll only ever need to set
|
|
||||||
# 'ba' to DEBUG at most.
|
|
||||||
log_handler = setup_logging(
|
log_handler = setup_logging(
|
||||||
log_path=None,
|
log_path=None,
|
||||||
level=LogLevel.DEBUG,
|
level=LogLevel.DEBUG,
|
||||||
suppress_non_root_debug=True,
|
|
||||||
log_stdout_stderr=True,
|
log_stdout_stderr=True,
|
||||||
cache_size_limit=1024 * 1024,
|
cache_size_limit=1024 * 1024,
|
||||||
|
launch_time=launch_time,
|
||||||
)
|
)
|
||||||
return log_handler
|
return log_handler
|
||||||
|
|
||||||
|
|
||||||
|
def _set_log_levels(app_config: dict) -> None:
|
||||||
|
|
||||||
|
from bacommon.logging import get_base_logger_control_config_client
|
||||||
|
from bacommon.loggercontrol import LoggerControlConfig
|
||||||
|
|
||||||
|
try:
|
||||||
|
config = app_config.get('Log Levels', None)
|
||||||
|
|
||||||
|
if config is None:
|
||||||
|
get_base_logger_control_config_client().apply()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Make sure data is expected types/values.
|
||||||
|
valid_levels = {
|
||||||
|
logging.NOTSET,
|
||||||
|
logging.DEBUG,
|
||||||
|
logging.INFO,
|
||||||
|
logging.WARNING,
|
||||||
|
logging.ERROR,
|
||||||
|
logging.CRITICAL,
|
||||||
|
}
|
||||||
|
for logname, loglevel in config.items():
|
||||||
|
if (
|
||||||
|
not isinstance(logname, str)
|
||||||
|
or not logname
|
||||||
|
or not isinstance(loglevel, int)
|
||||||
|
or not loglevel in valid_levels
|
||||||
|
):
|
||||||
|
raise ValueError("Invalid 'Log Levels' data read from config.")
|
||||||
|
|
||||||
|
get_base_logger_control_config_client().apply_diff(
|
||||||
|
LoggerControlConfig(levels=config)
|
||||||
|
).apply()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logging.exception('Error setting log levels.')
|
||||||
|
|
||||||
|
|
||||||
def _setup_certs(contains_python_dist: bool) -> None:
|
def _setup_certs(contains_python_dist: bool) -> None:
|
||||||
# In situations where we're bringing our own Python, let's also
|
# In situations where we're bringing our own Python, let's also
|
||||||
# provide our own root certs so ssl works. We can consider
|
# provide our own root certs so ssl works. We can consider
|
||||||
|
|||||||
@ -128,14 +128,8 @@ class CloudSubsystem(babase.AppSubsystem):
|
|||||||
The provided on_response call will be run in the logic thread
|
The provided on_response call will be run in the logic thread
|
||||||
and passed either the response or the error that occurred.
|
and passed either the response or the error that occurred.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError(
|
||||||
del msg # Unused.
|
'Cloud functionality is not present in this build.'
|
||||||
|
|
||||||
babase.pushcall(
|
|
||||||
babase.Call(
|
|
||||||
on_response,
|
|
||||||
RuntimeError('Cloud functionality is not available.'),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@ -158,7 +152,9 @@ class CloudSubsystem(babase.AppSubsystem):
|
|||||||
|
|
||||||
Must be called from a background thread.
|
Must be called from a background thread.
|
||||||
"""
|
"""
|
||||||
raise RuntimeError('Cloud functionality is not available.')
|
raise NotImplementedError(
|
||||||
|
'Cloud functionality is not present in this build.'
|
||||||
|
)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
async def send_message_async(
|
async def send_message_async(
|
||||||
@ -175,7 +171,14 @@ class CloudSubsystem(babase.AppSubsystem):
|
|||||||
|
|
||||||
Must be called from the logic thread.
|
Must be called from the logic thread.
|
||||||
"""
|
"""
|
||||||
raise RuntimeError('Cloud functionality is not available.')
|
raise NotImplementedError(
|
||||||
|
'Cloud functionality is not present in this build.'
|
||||||
|
)
|
||||||
|
|
||||||
|
# def subscribe(
|
||||||
|
# self,
|
||||||
|
# on_response: Callable[[Any], None],
|
||||||
|
# ) -> CallbackRegistration:
|
||||||
|
|
||||||
|
|
||||||
def cloud_console_exec(code: str) -> None:
|
def cloud_console_exec(code: str) -> None:
|
||||||
|
|||||||
@ -1575,6 +1575,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
|||||||
transition_delay=1.0,
|
transition_delay=1.0,
|
||||||
).autoretain()
|
).autoretain()
|
||||||
else:
|
else:
|
||||||
|
assert rating is not None
|
||||||
ZoomText(
|
ZoomText(
|
||||||
(
|
(
|
||||||
f'{rating:.1f}'
|
f'{rating:.1f}'
|
||||||
|
|||||||
@ -387,8 +387,6 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
|||||||
v_offs = 0.0
|
v_offs = 0.0
|
||||||
tdelay += len(player_entries) * 8 * t_incr
|
tdelay += len(player_entries) * 8 * t_incr
|
||||||
for _score, name, prec in player_entries:
|
for _score, name, prec in player_entries:
|
||||||
if not prec.player.in_game:
|
|
||||||
continue
|
|
||||||
tdelay -= 4 * t_incr
|
tdelay -= 4 * t_incr
|
||||||
v_offs -= 40
|
v_offs -= 40
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@ -627,6 +627,7 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
sale_title_text: str | bui.Lstr = ''
|
sale_title_text: str | bui.Lstr = ''
|
||||||
sale_time_text: str | bui.Lstr = ''
|
sale_time_text: str | bui.Lstr = ''
|
||||||
|
|
||||||
|
call: Callable | None
|
||||||
if purchased:
|
if purchased:
|
||||||
title_color = (0.8, 0.7, 0.9, 1.0)
|
title_color = (0.8, 0.7, 0.9, 1.0)
|
||||||
color = (0.63, 0.55, 0.78)
|
color = (0.63, 0.55, 0.78)
|
||||||
|
|||||||
@ -136,7 +136,7 @@ auto AppAdapter::DoClipboardGetText() -> std::string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto AppAdapter::GetKeyName(int keycode) -> std::string {
|
auto AppAdapter::GetKeyName(int keycode) -> std::string {
|
||||||
BA_LOG_ONCE(LogLevel::kWarning,
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kWarning,
|
||||||
"CorePlatform::GetKeyName not implemented here.");
|
"CorePlatform::GetKeyName not implemented here.");
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -169,7 +169,7 @@ auto AppAdapterApple::InGraphicsContext() -> bool {
|
|||||||
void AppAdapterApple::DoPushGraphicsContextRunnable(Runnable* runnable) {
|
void AppAdapterApple::DoPushGraphicsContextRunnable(Runnable* runnable) {
|
||||||
auto lock = std::scoped_lock(graphics_calls_mutex_);
|
auto lock = std::scoped_lock(graphics_calls_mutex_);
|
||||||
if (graphics_calls_.size() > 1000) {
|
if (graphics_calls_.size() > 1000) {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "graphics_calls_ got too big.");
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kError, "graphics_calls_ got too big.");
|
||||||
}
|
}
|
||||||
graphics_calls_.push_back(runnable);
|
graphics_calls_.push_back(runnable);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ void AppAdapterSDL::OnMainThreadStartApp() {
|
|||||||
uint32_t sdl_flags{SDL_INIT_VIDEO | SDL_INIT_JOYSTICK};
|
uint32_t sdl_flags{SDL_INIT_VIDEO | SDL_INIT_JOYSTICK};
|
||||||
|
|
||||||
if (strict_graphics_context_) {
|
if (strict_graphics_context_) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaNetworking, LogLevel::kWarning,
|
||||||
"AppAdapterSDL strict_graphics_context_ is enabled."
|
"AppAdapterSDL strict_graphics_context_ is enabled."
|
||||||
" Remember to turn this off.");
|
" Remember to turn this off.");
|
||||||
}
|
}
|
||||||
@ -309,7 +309,8 @@ void AppAdapterSDL::SleepUntilNextEventCycle_(microsecs_t cycle_start_time) {
|
|||||||
const microsecs_t min_sleep{2000};
|
const microsecs_t min_sleep{2000};
|
||||||
if (now + min_sleep >= target_time) {
|
if (now + min_sleep >= target_time) {
|
||||||
if (debug_log_sdl_frame_timing_) {
|
if (debug_log_sdl_frame_timing_) {
|
||||||
Log(LogLevel::kDebug, "no sleep."); // 'till brooklyn!
|
Log(LogName::kBaNetworking, LogLevel::kDebug,
|
||||||
|
"no sleep."); // 'till brooklyn!
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (debug_log_sdl_frame_timing_) {
|
if (debug_log_sdl_frame_timing_) {
|
||||||
@ -317,7 +318,7 @@ void AppAdapterSDL::SleepUntilNextEventCycle_(microsecs_t cycle_start_time) {
|
|||||||
snprintf(buf, sizeof(buf), "render %.1f sleep %.1f",
|
snprintf(buf, sizeof(buf), "render %.1f sleep %.1f",
|
||||||
(now - cycle_start_time) / 1000.0f,
|
(now - cycle_start_time) / 1000.0f,
|
||||||
(target_time - now) / 1000.0f);
|
(target_time - now) / 1000.0f);
|
||||||
Log(LogLevel::kDebug, buf);
|
Log(LogName::kBaNetworking, LogLevel::kDebug, buf);
|
||||||
}
|
}
|
||||||
g_core->platform->SleepMicrosecs(target_time - now);
|
g_core->platform->SleepMicrosecs(target_time - now);
|
||||||
}
|
}
|
||||||
@ -375,8 +376,9 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) {
|
|||||||
g_base->input->PushJoystickEvent(event, js);
|
g_base->input->PushJoystickEvent(event, js);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "Unable to get SDL Joystick for event type "
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
+ std::to_string(event.type));
|
"Unable to get SDL Joystick for event type "
|
||||||
|
+ std::to_string(event.type));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -563,7 +565,7 @@ void AppAdapterSDL::OnSDLJoystickAdded_(int device_index) {
|
|||||||
try {
|
try {
|
||||||
j = Object::NewDeferred<JoystickInput>(device_index);
|
j = Object::NewDeferred<JoystickInput>(device_index);
|
||||||
} catch (const std::exception& exc) {
|
} catch (const std::exception& exc) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
std::string("Error creating JoystickInput for SDL device-index "
|
std::string("Error creating JoystickInput for SDL device-index "
|
||||||
+ std::to_string(device_index) + ": ")
|
+ std::to_string(device_index) + ": ")
|
||||||
+ exc.what());
|
+ exc.what());
|
||||||
@ -602,7 +604,7 @@ void AppAdapterSDL::RemoveSDLInputDevice_(int index) {
|
|||||||
|
|
||||||
// Note: am running into this with a PS5 controller on macOS Sequoia beta.
|
// Note: am running into this with a PS5 controller on macOS Sequoia beta.
|
||||||
if (!j) {
|
if (!j) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
"GetSDLJoystickInput_() returned nullptr on RemoveSDLInputDevice_();"
|
"GetSDLJoystickInput_() returned nullptr on RemoveSDLInputDevice_();"
|
||||||
" joysticks size is "
|
" joysticks size is "
|
||||||
+ std::to_string(sdl_joysticks_.size()) + "; index is "
|
+ std::to_string(sdl_joysticks_.size()) + "; index is "
|
||||||
@ -614,9 +616,10 @@ void AppAdapterSDL::RemoveSDLInputDevice_(int index) {
|
|||||||
if (static_cast_check_fit<int>(sdl_joysticks_.size()) > index) {
|
if (static_cast_check_fit<int>(sdl_joysticks_.size()) > index) {
|
||||||
sdl_joysticks_[index] = nullptr;
|
sdl_joysticks_[index] = nullptr;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "Invalid index on RemoveSDLInputDevice: size is "
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
+ std::to_string(sdl_joysticks_.size())
|
"Invalid index on RemoveSDLInputDevice: size is "
|
||||||
+ "; index is " + std::to_string(index) + ".");
|
+ std::to_string(sdl_joysticks_.size()) + "; index is "
|
||||||
|
+ std::to_string(index) + ".");
|
||||||
}
|
}
|
||||||
g_base->input->PushRemoveInputDeviceCall(j, true);
|
g_base->input->PushRemoveInputDeviceCall(j, true);
|
||||||
}
|
}
|
||||||
@ -785,7 +788,8 @@ void AppAdapterSDL::DoPushGraphicsContextRunnable(Runnable* runnable) {
|
|||||||
if (strict_graphics_context_) {
|
if (strict_graphics_context_) {
|
||||||
auto lock = std::scoped_lock(strict_graphics_calls_mutex_);
|
auto lock = std::scoped_lock(strict_graphics_calls_mutex_);
|
||||||
if (strict_graphics_calls_.size() > 1000) {
|
if (strict_graphics_calls_.size() > 1000) {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "strict_graphics_calls_ got too big.");
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"strict_graphics_calls_ got too big.");
|
||||||
}
|
}
|
||||||
strict_graphics_calls_.push_back(runnable);
|
strict_graphics_calls_.push_back(runnable);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -52,7 +52,8 @@ void AppAdapterVR::VRPreDraw() {
|
|||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
// FIXME - this is internal graphics-server details that the render-server
|
// FIXME - this is internal graphics-server details that the render-server
|
||||||
// should handle.
|
// should handle.
|
||||||
Log(LogLevel::kWarning, "FIXME: Have GraphicsServer handle VR drawing.");
|
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
|
"FIXME: Have GraphicsServer handle VR drawing.");
|
||||||
// if (FrameDef* frame_def = g_base->graphics_server->GetRenderFrameDef()) {
|
// if (FrameDef* frame_def = g_base->graphics_server->GetRenderFrameDef()) {
|
||||||
// // Note: this could be part of PreprocessRenderFrameDef but the non-vr
|
// // Note: this could be part of PreprocessRenderFrameDef but the non-vr
|
||||||
// // path needs it to be separate since preprocess doesn't happen
|
// // path needs it to be separate since preprocess doesn't happen
|
||||||
@ -75,7 +76,8 @@ void AppAdapterVR::VRPostDraw() {
|
|||||||
g_base->graphics_server->FinishRenderFrameDef(vr_render_frame_def_);
|
g_base->graphics_server->FinishRenderFrameDef(vr_render_frame_def_);
|
||||||
vr_render_frame_def_ = nullptr;
|
vr_render_frame_def_ = nullptr;
|
||||||
}
|
}
|
||||||
Log(LogLevel::kWarning, "WOULD RUN RENDER UPKEEP CYCLE");
|
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
|
"WOULD RUN RENDER UPKEEP CYCLE");
|
||||||
// RunRenderUpkeepCycle();
|
// RunRenderUpkeepCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -302,7 +302,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
snprintf(buffer, sizeof(buffer), " %-50s %10s %10s", "FILE",
|
snprintf(buffer, sizeof(buffer), " %-50s %10s %10s", "FILE",
|
||||||
"PRELOAD_TIME", "LOAD_TIME");
|
"PRELOAD_TIME", "LOAD_TIME");
|
||||||
s += buffer;
|
s += buffer;
|
||||||
Log(LogLevel::kInfo, s);
|
Log(LogName::kBaAssets, LogLevel::kInfo, s);
|
||||||
millisecs_t total_preload_time = 0;
|
millisecs_t total_preload_time = 0;
|
||||||
millisecs_t total_load_time = 0;
|
millisecs_t total_load_time = 0;
|
||||||
assert(asset_lists_locked_);
|
assert(asset_lists_locked_);
|
||||||
@ -315,7 +315,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
i.second->GetName().c_str(),
|
i.second->GetName().c_str(),
|
||||||
static_cast_check_fit<int>(preload_time),
|
static_cast_check_fit<int>(preload_time),
|
||||||
static_cast_check_fit<int>(load_time));
|
static_cast_check_fit<int>(load_time));
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
assert(asset_lists_locked_);
|
assert(asset_lists_locked_);
|
||||||
@ -328,7 +328,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
i.second->GetName().c_str(),
|
i.second->GetName().c_str(),
|
||||||
static_cast_check_fit<int>(preload_time),
|
static_cast_check_fit<int>(preload_time),
|
||||||
static_cast_check_fit<int>(load_time));
|
static_cast_check_fit<int>(load_time));
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
assert(asset_lists_locked_);
|
assert(asset_lists_locked_);
|
||||||
@ -341,7 +341,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
i.second->GetName().c_str(),
|
i.second->GetName().c_str(),
|
||||||
static_cast_check_fit<int>(preload_time),
|
static_cast_check_fit<int>(preload_time),
|
||||||
static_cast_check_fit<int>(load_time));
|
static_cast_check_fit<int>(load_time));
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
assert(asset_lists_locked_);
|
assert(asset_lists_locked_);
|
||||||
@ -354,7 +354,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
i.second->GetName().c_str(),
|
i.second->GetName().c_str(),
|
||||||
static_cast_check_fit<int>(preload_time),
|
static_cast_check_fit<int>(preload_time),
|
||||||
static_cast_check_fit<int>(load_time));
|
static_cast_check_fit<int>(load_time));
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
assert(asset_lists_locked_);
|
assert(asset_lists_locked_);
|
||||||
@ -367,7 +367,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
i.second->file_name_full().c_str(),
|
i.second->file_name_full().c_str(),
|
||||||
static_cast_check_fit<int>(preload_time),
|
static_cast_check_fit<int>(preload_time),
|
||||||
static_cast_check_fit<int>(load_time));
|
static_cast_check_fit<int>(load_time));
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
@ -375,7 +375,7 @@ void Assets::PrintLoadInfo() {
|
|||||||
"(feeding data to OpenGL, etc): %i",
|
"(feeding data to OpenGL, etc): %i",
|
||||||
static_cast<int>(total_preload_time),
|
static_cast<int>(total_preload_time),
|
||||||
static_cast<int>(total_load_time));
|
static_cast<int>(total_load_time));
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::MarkAllAssetsForLoad() {
|
void Assets::MarkAllAssetsForLoad() {
|
||||||
@ -1029,35 +1029,35 @@ void Assets::Prune(int level) {
|
|||||||
if (kShowPruningInfo) {
|
if (kShowPruningInfo) {
|
||||||
assert(asset_lists_locked_);
|
assert(asset_lists_locked_);
|
||||||
if (textures_.size() != old_texture_count) {
|
if (textures_.size() != old_texture_count) {
|
||||||
Log(LogLevel::kInfo, "Textures pruned from "
|
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||||
+ std::to_string(old_texture_count) + " to "
|
"Textures pruned from " + std::to_string(old_texture_count) + " to "
|
||||||
+ std::to_string(textures_.size()));
|
+ std::to_string(textures_.size()));
|
||||||
}
|
}
|
||||||
if (text_textures_.size() != old_text_texture_count) {
|
if (text_textures_.size() != old_text_texture_count) {
|
||||||
Log(LogLevel::kInfo, "TextTextures pruned from "
|
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||||
+ std::to_string(old_text_texture_count) + " to "
|
"TextTextures pruned from " + std::to_string(old_text_texture_count)
|
||||||
+ std::to_string(text_textures_.size()));
|
+ " to " + std::to_string(text_textures_.size()));
|
||||||
}
|
}
|
||||||
if (qr_textures_.size() != old_qr_texture_count) {
|
if (qr_textures_.size() != old_qr_texture_count) {
|
||||||
Log(LogLevel::kInfo, "QrTextures pruned from "
|
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||||
+ std::to_string(old_qr_texture_count) + " to "
|
"QrTextures pruned from " + std::to_string(old_qr_texture_count)
|
||||||
+ std::to_string(qr_textures_.size()));
|
+ " to " + std::to_string(qr_textures_.size()));
|
||||||
}
|
}
|
||||||
if (meshes_.size() != old_mesh_count) {
|
if (meshes_.size() != old_mesh_count) {
|
||||||
Log(LogLevel::kInfo, "Meshes pruned from "
|
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||||
+ std::to_string(old_mesh_count) + " to "
|
"Meshes pruned from " + std::to_string(old_mesh_count) + " to "
|
||||||
+ std::to_string(meshes_.size()));
|
+ std::to_string(meshes_.size()));
|
||||||
}
|
}
|
||||||
if (collision_meshes_.size() != old_collision_mesh_count) {
|
if (collision_meshes_.size() != old_collision_mesh_count) {
|
||||||
Log(LogLevel::kInfo, "CollisionMeshes pruned from "
|
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||||
+ std::to_string(old_collision_mesh_count)
|
"CollisionMeshes pruned from "
|
||||||
+ " to "
|
+ std::to_string(old_collision_mesh_count) + " to "
|
||||||
+ std::to_string(collision_meshes_.size()));
|
+ std::to_string(collision_meshes_.size()));
|
||||||
}
|
}
|
||||||
if (sounds_.size() != old_sound_count) {
|
if (sounds_.size() != old_sound_count) {
|
||||||
Log(LogLevel::kInfo, "Sounds pruned from "
|
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||||
+ std::to_string(old_sound_count) + " to "
|
"Sounds pruned from " + std::to_string(old_sound_count) + " to "
|
||||||
+ std::to_string(sounds_.size()));
|
+ std::to_string(sounds_.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1164,11 +1164,11 @@ auto Assets::FindAssetFile(FileType type, const std::string& name)
|
|||||||
|
|
||||||
// We wanna fail gracefully for some types.
|
// We wanna fail gracefully for some types.
|
||||||
if (type == FileType::kSound && name != "blank") {
|
if (type == FileType::kSound && name != "blank") {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAssets, LogLevel::kError,
|
||||||
"Unable to load audio: '" + name + "'; trying fallback...");
|
"Unable to load audio: '" + name + "'; trying fallback...");
|
||||||
return FindAssetFile(type, "blank");
|
return FindAssetFile(type, "blank");
|
||||||
} else if (type == FileType::kTexture && name != "white") {
|
} else if (type == FileType::kTexture && name != "white") {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAssets, LogLevel::kError,
|
||||||
"Unable to load texture: '" + name + "'; trying fallback...");
|
"Unable to load texture: '" + name + "'; trying fallback...");
|
||||||
return FindAssetFile(type, "white");
|
return FindAssetFile(type, "white");
|
||||||
}
|
}
|
||||||
@ -1228,7 +1228,8 @@ void Assets::AddPackage(const std::string& name, const std::string& path) {
|
|||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (g_buildconfig.debug_build()) {
|
if (g_buildconfig.debug_build()) {
|
||||||
if (packages_.find(name) != packages_.end()) {
|
if (packages_.find(name) != packages_.end()) {
|
||||||
Log(LogLevel::kWarning, "adding duplicate package: '" + name + "'");
|
Log(LogName::kBaAssets, LogLevel::kWarning,
|
||||||
|
"adding duplicate package: '" + name + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packages_[name] = path;
|
packages_[name] = path;
|
||||||
@ -1386,7 +1387,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
|||||||
printed = true;
|
printed = true;
|
||||||
char* c = cJSON_Print(obj);
|
char* c = cJSON_Print(obj);
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaAssets, LogLevel::kError,
|
||||||
"found long key 'resource' in raw lstr json: " + std::string(c));
|
"found long key 'resource' in raw lstr json: " + std::string(c));
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
@ -1406,7 +1407,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
|||||||
printed = true;
|
printed = true;
|
||||||
char* c = cJSON_Print(obj);
|
char* c = cJSON_Print(obj);
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaAssets, LogLevel::kError,
|
||||||
"found long key 'fallback' in raw lstr json: " + std::string(c));
|
"found long key 'fallback' in raw lstr json: " + std::string(c));
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
@ -1431,7 +1432,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
|||||||
printed = true;
|
printed = true;
|
||||||
char* c = cJSON_Print(obj);
|
char* c = cJSON_Print(obj);
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaAssets, LogLevel::kError,
|
||||||
"found long key 'translate' in raw lstr json: " + std::string(c));
|
"found long key 'translate' in raw lstr json: " + std::string(c));
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
@ -1470,7 +1471,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
|||||||
printed = true;
|
printed = true;
|
||||||
char* c = cJSON_Print(obj);
|
char* c = cJSON_Print(obj);
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaAssets, LogLevel::kError,
|
||||||
"found long key 'value' in raw lstr json: " + std::string(c));
|
"found long key 'value' in raw lstr json: " + std::string(c));
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
@ -1501,8 +1502,9 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
|||||||
if (!printed) {
|
if (!printed) {
|
||||||
printed = true;
|
printed = true;
|
||||||
char* c = cJSON_Print(obj);
|
char* c = cJSON_Print(obj);
|
||||||
BA_LOG_ONCE(LogLevel::kError, "found long key 'subs' in raw lstr json: "
|
BA_LOG_ONCE(
|
||||||
+ std::string(c));
|
LogName::kBaAssets, LogLevel::kError,
|
||||||
|
"found long key 'subs' in raw lstr json: " + std::string(c));
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1571,8 +1573,9 @@ auto Assets::CompileResourceString(const std::string& s, const std::string& loc,
|
|||||||
|
|
||||||
cJSON* root = cJSON_Parse(s.c_str());
|
cJSON* root = cJSON_Parse(s.c_str());
|
||||||
if (root == nullptr) {
|
if (root == nullptr) {
|
||||||
Log(LogLevel::kError, "CompileResourceString failed (loc " + loc
|
Log(LogName::kBaAssets, LogLevel::kError,
|
||||||
+ "); invalid json: '" + s + "'");
|
"CompileResourceString failed (loc " + loc + "); invalid json: '" + s
|
||||||
|
+ "'");
|
||||||
*valid = false;
|
*valid = false;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -1581,8 +1584,9 @@ auto Assets::CompileResourceString(const std::string& s, const std::string& loc,
|
|||||||
result = DoCompileResourceString(root);
|
result = DoCompileResourceString(root);
|
||||||
*valid = true;
|
*valid = true;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Log(LogLevel::kError, "CompileResourceString failed (loc " + loc + "): "
|
Log(LogName::kBaAssets, LogLevel::kError,
|
||||||
+ std::string(e.what()) + "; str='" + s + "'");
|
"CompileResourceString failed (loc " + loc
|
||||||
|
+ "): " + std::string(e.what()) + "; str='" + s + "'");
|
||||||
result = "<error>";
|
result = "<error>";
|
||||||
*valid = false;
|
*valid = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ void AssetsServer::PushBeginWriteReplayCall(uint16_t protocol_version) {
|
|||||||
// We only allow writing one replay at once; make sure that's actually
|
// We only allow writing one replay at once; make sure that's actually
|
||||||
// the case.
|
// the case.
|
||||||
if (writing_replay_) {
|
if (writing_replay_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAssets, LogLevel::kError,
|
||||||
"AssetsServer got BeginWriteReplayCall while already writing");
|
"AssetsServer got BeginWriteReplayCall while already writing");
|
||||||
WriteReplayMessages();
|
WriteReplayMessages();
|
||||||
if (replay_out_file_) {
|
if (replay_out_file_) {
|
||||||
@ -76,7 +76,7 @@ void AssetsServer::PushBeginWriteReplayCall(uint16_t protocol_version) {
|
|||||||
replay_bytes_written_ = 0;
|
replay_bytes_written_ = 0;
|
||||||
|
|
||||||
if (!replay_out_file_) {
|
if (!replay_out_file_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"unable to open output-stream file: '" + file_path + "'");
|
"unable to open output-stream file: '" + file_path + "'");
|
||||||
} else {
|
} else {
|
||||||
// Write file id and protocol-version.
|
// Write file id and protocol-version.
|
||||||
@ -88,8 +88,9 @@ void AssetsServer::PushBeginWriteReplayCall(uint16_t protocol_version) {
|
|||||||
|| (fwrite(&version, sizeof(version), 1, replay_out_file_) != 1)) {
|
|| (fwrite(&version, sizeof(version), 1, replay_out_file_) != 1)) {
|
||||||
fclose(replay_out_file_);
|
fclose(replay_out_file_);
|
||||||
replay_out_file_ = nullptr;
|
replay_out_file_ = nullptr;
|
||||||
Log(LogLevel::kError, "error writing replay file header: "
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ g_core->platform->GetErrnoString());
|
"error writing replay file header: "
|
||||||
|
+ g_core->platform->GetErrnoString());
|
||||||
}
|
}
|
||||||
replay_bytes_written_ = 5;
|
replay_bytes_written_ = 5;
|
||||||
}
|
}
|
||||||
@ -109,7 +110,7 @@ void AssetsServer::PushAddMessageToReplayCall(
|
|||||||
|
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if (!writing_replay_) {
|
if (!writing_replay_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"AssetsServer got AddMessageToReplayCall while not writing replay");
|
"AssetsServer got AddMessageToReplayCall while not writing replay");
|
||||||
replays_broken_ = true;
|
replays_broken_ = true;
|
||||||
return;
|
return;
|
||||||
@ -120,7 +121,7 @@ void AssetsServer::PushAddMessageToReplayCall(
|
|||||||
// If we've got too much data built up (lets go with 10 megs for now),
|
// If we've got too much data built up (lets go with 10 megs for now),
|
||||||
// abort.
|
// abort.
|
||||||
if (replay_message_bytes_ > 10000000) {
|
if (replay_message_bytes_ > 10000000) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"replay output buffer exceeded 10 megs; aborting replay");
|
"replay output buffer exceeded 10 megs; aborting replay");
|
||||||
fclose(replay_out_file_);
|
fclose(replay_out_file_);
|
||||||
replay_out_file_ = nullptr;
|
replay_out_file_ = nullptr;
|
||||||
@ -142,7 +143,8 @@ void AssetsServer::PushEndWriteReplayCall() {
|
|||||||
|
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if (!writing_replay_) {
|
if (!writing_replay_) {
|
||||||
Log(LogLevel::kError, "_finishWritingReplay called while not writing");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"_finishWritingReplay called while not writing");
|
||||||
replays_broken_ = true;
|
replays_broken_ = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -179,8 +181,9 @@ void AssetsServer::WriteReplayMessages() {
|
|||||||
if (fwrite(&len8, 1, 1, replay_out_file_) != 1) {
|
if (fwrite(&len8, 1, 1, replay_out_file_) != 1) {
|
||||||
fclose(replay_out_file_);
|
fclose(replay_out_file_);
|
||||||
replay_out_file_ = nullptr;
|
replay_out_file_ = nullptr;
|
||||||
Log(LogLevel::kError, "error writing replay file: "
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ g_core->platform->GetErrnoString());
|
"error writing replay file: "
|
||||||
|
+ g_core->platform->GetErrnoString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,16 +194,18 @@ void AssetsServer::WriteReplayMessages() {
|
|||||||
if (fwrite(&len16, 2, 1, replay_out_file_) != 1) {
|
if (fwrite(&len16, 2, 1, replay_out_file_) != 1) {
|
||||||
fclose(replay_out_file_);
|
fclose(replay_out_file_);
|
||||||
replay_out_file_ = nullptr;
|
replay_out_file_ = nullptr;
|
||||||
Log(LogLevel::kError, "error writing replay file: "
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ g_core->platform->GetErrnoString());
|
"error writing replay file: "
|
||||||
|
+ g_core->platform->GetErrnoString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fwrite(&len32, 4, 1, replay_out_file_) != 1) {
|
if (fwrite(&len32, 4, 1, replay_out_file_) != 1) {
|
||||||
fclose(replay_out_file_);
|
fclose(replay_out_file_);
|
||||||
replay_out_file_ = nullptr;
|
replay_out_file_ = nullptr;
|
||||||
Log(LogLevel::kError, "error writing replay file: "
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ g_core->platform->GetErrnoString());
|
"error writing replay file: "
|
||||||
|
+ g_core->platform->GetErrnoString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,7 +216,7 @@ void AssetsServer::WriteReplayMessages() {
|
|||||||
if (result != 1) {
|
if (result != 1) {
|
||||||
fclose(replay_out_file_);
|
fclose(replay_out_file_);
|
||||||
replay_out_file_ = nullptr;
|
replay_out_file_ = nullptr;
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"error writing replay file: " + g_core->platform->GetErrnoString());
|
"error writing replay file: " + g_core->platform->GetErrnoString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,8 +62,9 @@ static auto LoadOgg(const char* file_name, std::vector<char>* buffer,
|
|||||||
f = g_core->platform->FOpen(file_name, "rb");
|
f = g_core->platform->FOpen(file_name, "rb");
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
fallback = true;
|
fallback = true;
|
||||||
Log(LogLevel::kError, std::string("Can't open sound file '") + file_name
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ "' for reading...");
|
std::string("Can't open sound file '") + file_name
|
||||||
|
+ "' for reading...");
|
||||||
|
|
||||||
// Attempt a fallback standin; if that doesn't work, throw in the towel.
|
// Attempt a fallback standin; if that doesn't work, throw in the towel.
|
||||||
file_name = "data/global/audio/blank.ogg";
|
file_name = "data/global/audio/blank.ogg";
|
||||||
@ -83,7 +84,7 @@ static auto LoadOgg(const char* file_name, std::vector<char>* buffer,
|
|||||||
|
|
||||||
// Try opening the given file
|
// Try opening the given file
|
||||||
if (ov_open_callbacks(f, &ogg_file, nullptr, 0, callbacks) != 0) {
|
if (ov_open_callbacks(f, &ogg_file, nullptr, 0, callbacks) != 0) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
std::string("Error decoding sound file '") + file_name + "'");
|
std::string("Error decoding sound file '") + file_name + "'");
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -207,9 +208,9 @@ static void LoadCachedOgg(const char* file_name, std::vector<char>* buffer,
|
|||||||
// with invalid formats of 0 once. Report and ignore if we see
|
// with invalid formats of 0 once. Report and ignore if we see
|
||||||
// something like that.
|
// something like that.
|
||||||
if (*format != AL_FORMAT_MONO16 && *format != AL_FORMAT_STEREO16) {
|
if (*format != AL_FORMAT_MONO16 && *format != AL_FORMAT_STEREO16) {
|
||||||
Log(LogLevel::kError, std::string("Ignoring invalid audio cache of ")
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ file_name + " with format "
|
std::string("Ignoring invalid audio cache of ") + file_name
|
||||||
+ std::to_string(*format));
|
+ " with format " + std::to_string(*format));
|
||||||
} else {
|
} else {
|
||||||
return; // SUCCESS!!!!
|
return; // SUCCESS!!!!
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,7 @@ TextureAsset::TextureAsset(const std::string& qr_url) : is_qr_code_(true) {
|
|||||||
"QR code url byte length %zu exceeds soft-limit of %zu;"
|
"QR code url byte length %zu exceeds soft-limit of %zu;"
|
||||||
" please use shorter urls. (url=%s)",
|
" please use shorter urls. (url=%s)",
|
||||||
qr_url.size(), soft_limit, qr_url.c_str());
|
qr_url.size(), soft_limit, qr_url.c_str());
|
||||||
Log(LogLevel::kWarning, buffer);
|
Log(LogName::kBaAssets, LogLevel::kWarning, buffer);
|
||||||
}
|
}
|
||||||
file_name_ = qr_url;
|
file_name_ = qr_url;
|
||||||
valid_ = true;
|
valid_ = true;
|
||||||
|
|||||||
@ -18,14 +18,15 @@ namespace ballistica::base {
|
|||||||
|
|
||||||
void _check_al_error(const char* file, int line) {
|
void _check_al_error(const char* file, int line) {
|
||||||
if (g_base->audio_server->paused()) {
|
if (g_base->audio_server->paused()) {
|
||||||
Log(LogLevel::kError, Utils::BaseName(file) + ":" + std::to_string(line)
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ ": Checking OpenAL error while paused.");
|
Utils::BaseName(file) + ":" + std::to_string(line)
|
||||||
|
+ ": Checking OpenAL error while paused.");
|
||||||
}
|
}
|
||||||
ALenum al_err = alGetError();
|
ALenum al_err = alGetError();
|
||||||
if (al_err != AL_NO_ERROR) {
|
if (al_err != AL_NO_ERROR) {
|
||||||
Log(LogLevel::kError, Utils::BaseName(file) + ":" + std::to_string(line)
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ ": OpenAL Error: " + GetALErrorString(al_err)
|
Utils::BaseName(file) + ":" + std::to_string(line)
|
||||||
+ ";");
|
+ ": OpenAL Error: " + GetALErrorString(al_err) + ";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -166,19 +166,19 @@ auto Audio::SafePlaySysSound(SysSoundID sound_id) -> std::optional<uint32_t> {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!g_base->InLogicThread()) {
|
if (!g_base->InLogicThread()) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Audio::SafePlaySysSound called from non-logic thread. id="
|
"Audio::SafePlaySysSound called from non-logic thread. id="
|
||||||
+ std::to_string(static_cast<int>(sound_id)));
|
+ std::to_string(static_cast<int>(sound_id)));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!g_base->assets->sys_assets_loaded()) {
|
if (!g_base->assets->sys_assets_loaded()) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
"Audio::SafePlaySysSound called before sys assets loaded. id="
|
"Audio::SafePlaySysSound called before sys assets loaded. id="
|
||||||
+ std::to_string(static_cast<int>(sound_id)));
|
+ std::to_string(static_cast<int>(sound_id)));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!g_base->assets->IsValidSysSound(sound_id)) {
|
if (!g_base->assets->IsValidSysSound(sound_id)) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
"Audio::SafePlaySysSound called with invalid sound_id. id="
|
"Audio::SafePlaySysSound called with invalid sound_id. id="
|
||||||
+ std::to_string(static_cast<int>(sound_id)));
|
+ std::to_string(static_cast<int>(sound_id)));
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@ -179,8 +179,9 @@ static void ALEventCallback_(ALenum eventType, ALuint object, ALuint param,
|
|||||||
[] { g_base->audio_server->OnDeviceDisconnected(); });
|
[] { g_base->audio_server->OnDeviceDisconnected(); });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kWarning, "Got unexpected OpenAL callback event "
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
+ std::to_string(static_cast<int>(eventType)));
|
"Got unexpected OpenAL callback event "
|
||||||
|
+ std::to_string(static_cast<int>(eventType)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +245,7 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
if (g_core->platform->GetOSVersionString().compare(0, prefix2.size(),
|
if (g_core->platform->GetOSVersionString().compare(0, prefix2.size(),
|
||||||
prefix2)
|
prefix2)
|
||||||
== 0) {
|
== 0) {
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaAudio, LogLevel::kInfo,
|
||||||
"Xiaomi Android 11 detected; using OpenSL instead of AAudio.");
|
"Xiaomi Android 11 detected; using OpenSL instead of AAudio.");
|
||||||
g_core->platform->SetEnv("BA_OBOE_USE_OPENSLES", "1");
|
g_core->platform->SetEnv("BA_OBOE_USE_OPENSLES", "1");
|
||||||
}
|
}
|
||||||
@ -260,7 +261,8 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
ALboolean enumeration =
|
ALboolean enumeration =
|
||||||
alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT");
|
alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT");
|
||||||
if (enumeration == AL_FALSE) {
|
if (enumeration == AL_FALSE) {
|
||||||
Log(LogLevel::kError, "OpenAL enumeration extensions missing.");
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
|
"OpenAL enumeration extensions missing.");
|
||||||
} else {
|
} else {
|
||||||
const ALCchar* devices =
|
const ALCchar* devices =
|
||||||
alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
|
alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
|
||||||
@ -298,7 +300,7 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
if (!device) {
|
if (!device) {
|
||||||
if (g_buildconfig.ostype_android()) {
|
if (g_buildconfig.ostype_android()) {
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||||
+ openalsoft_android_log_
|
+ openalsoft_android_log_
|
||||||
@ -315,11 +317,11 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
|
|
||||||
// Android special case: if we fail, try again after a few seconds.
|
// Android special case: if we fail, try again after a few seconds.
|
||||||
if (!impl_->alc_context && g_buildconfig.ostype_android()) {
|
if (!impl_->alc_context && g_buildconfig.ostype_android()) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Failed creating AL context; waiting and trying again.");
|
"Failed creating AL context; waiting and trying again.");
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-ERROR-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-ERROR-LOG-BEGIN ----------------------\n"
|
||||||
+ openalsoft_android_log_
|
+ openalsoft_android_log_
|
||||||
@ -334,7 +336,7 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
|
|
||||||
if (!device) {
|
if (!device) {
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||||
+ openalsoft_android_log_
|
+ openalsoft_android_log_
|
||||||
@ -346,17 +348,18 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
impl_->alc_context = alcCreateContext(device, nullptr);
|
impl_->alc_context = alcCreateContext(device, nullptr);
|
||||||
if (impl_->alc_context) {
|
if (impl_->alc_context) {
|
||||||
// For now want to explicitly know if this works.
|
// For now want to explicitly know if this works.
|
||||||
Log(LogLevel::kWarning, "Backup AL context creation successful!");
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
|
"Backup AL context creation successful!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Android special case: if we fail, try OpenSL back-end.
|
// Android special case: if we fail, try OpenSL back-end.
|
||||||
if (!impl_->alc_context && g_buildconfig.ostype_android()) {
|
if (!impl_->alc_context && g_buildconfig.ostype_android()) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Failed second time creating AL context; trying OpenSL backend.");
|
"Failed second time creating AL context; trying OpenSL backend.");
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-ERROR-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-ERROR-LOG-BEGIN ----------------------\n"
|
||||||
+ openalsoft_android_log_
|
+ openalsoft_android_log_
|
||||||
@ -370,7 +373,7 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
alGetError(); // Clear any errors.
|
alGetError(); // Clear any errors.
|
||||||
if (!device) {
|
if (!device) {
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||||
+ openalsoft_android_log_
|
+ openalsoft_android_log_
|
||||||
@ -382,7 +385,8 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
impl_->alc_context = alcCreateContext(device, nullptr);
|
impl_->alc_context = alcCreateContext(device, nullptr);
|
||||||
if (impl_->alc_context) {
|
if (impl_->alc_context) {
|
||||||
// For now want to explicitly know if this works.
|
// For now want to explicitly know if this works.
|
||||||
Log(LogLevel::kWarning, "Backup AL context creation 2 successful!");
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
|
"Backup AL context creation 2 successful!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +394,7 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
if (!impl_->alc_context) {
|
if (!impl_->alc_context) {
|
||||||
if (g_buildconfig.ostype_android()) {
|
if (g_buildconfig.ostype_android()) {
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||||
+ openalsoft_android_log_
|
+ openalsoft_android_log_
|
||||||
@ -459,8 +463,9 @@ void AudioServer::OnAppStartInThread_() {
|
|||||||
sound_source_refs_.push_back(s);
|
sound_source_refs_.push_back(s);
|
||||||
sources_.push_back(&(*s));
|
sources_.push_back(&(*s));
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "Made " + std::to_string(i) + " sources; (wanted "
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ std::to_string(target_source_count) + ").");
|
"Made " + std::to_string(i) + " sources; (wanted "
|
||||||
|
+ std::to_string(target_source_count) + ").");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,20 +503,23 @@ void AudioServer::CompleteShutdown_() {
|
|||||||
#if BA_ENABLE_AUDIO
|
#if BA_ENABLE_AUDIO
|
||||||
ALCboolean check = alcMakeContextCurrent(nullptr);
|
ALCboolean check = alcMakeContextCurrent(nullptr);
|
||||||
if (!check) {
|
if (!check) {
|
||||||
Log(LogLevel::kWarning, "Error on alcMakeContextCurrent at shutdown.");
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
|
"Error on alcMakeContextCurrent at shutdown.");
|
||||||
}
|
}
|
||||||
auto* device = alcGetContextsDevice(impl_->alc_context);
|
auto* device = alcGetContextsDevice(impl_->alc_context);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
Log(LogLevel::kWarning, "Unable to get ALCdevice at shutdown.");
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
|
"Unable to get ALCdevice at shutdown.");
|
||||||
} else {
|
} else {
|
||||||
alcDestroyContext(impl_->alc_context);
|
alcDestroyContext(impl_->alc_context);
|
||||||
ALenum err = alcGetError(device);
|
ALenum err = alcGetError(device);
|
||||||
if (err != ALC_NO_ERROR) {
|
if (err != ALC_NO_ERROR) {
|
||||||
Log(LogLevel::kWarning, "Error on AL shutdown.");
|
Log(LogName::kBaAudio, LogLevel::kWarning, "Error on AL shutdown.");
|
||||||
}
|
}
|
||||||
check = alcCloseDevice(device);
|
check = alcCloseDevice(device);
|
||||||
if (!check) {
|
if (!check) {
|
||||||
Log(LogLevel::kWarning, "Error on alcCloseDevice at shutdown.");
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
|
"Error on alcCloseDevice at shutdown.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -534,7 +542,7 @@ struct AudioServer::SoundFadeNode_ {
|
|||||||
void AudioServer::SetSuspended_(bool suspend) {
|
void AudioServer::SetSuspended_(bool suspend) {
|
||||||
if (!suspended_) {
|
if (!suspended_) {
|
||||||
if (!suspend) {
|
if (!suspend) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Got audio unsuspend request when already unsuspended.");
|
"Got audio unsuspend request when already unsuspended.");
|
||||||
} else {
|
} else {
|
||||||
#if BA_OSTYPE_IOS_TVOS
|
#if BA_OSTYPE_IOS_TVOS
|
||||||
@ -557,7 +565,7 @@ void AudioServer::SetSuspended_(bool suspend) {
|
|||||||
+ std::to_string(g_core->GetAppTimeSeconds()));
|
+ std::to_string(g_core->GetAppTimeSeconds()));
|
||||||
alcDevicePauseSOFT(device);
|
alcDevicePauseSOFT(device);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Error in alcDevicePauseSOFT at time "
|
"Error in alcDevicePauseSOFT at time "
|
||||||
+ std::to_string(g_core->GetAppTimeSeconds())
|
+ std::to_string(g_core->GetAppTimeSeconds())
|
||||||
+ "( playing since "
|
+ "( playing since "
|
||||||
@ -565,7 +573,8 @@ void AudioServer::SetSuspended_(bool suspend) {
|
|||||||
+ "): " + g_core->platform->DemangleCXXSymbol(typeid(e).name())
|
+ "): " + g_core->platform->DemangleCXXSymbol(typeid(e).name())
|
||||||
+ " " + e.what());
|
+ " " + e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Log(LogLevel::kError, "Unknown error in alcDevicePauseSOFT");
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
|
"Unknown error in alcDevicePauseSOFT");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -574,7 +583,7 @@ void AudioServer::SetSuspended_(bool suspend) {
|
|||||||
} else {
|
} else {
|
||||||
// Unsuspend if requested.
|
// Unsuspend if requested.
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Got audio suspend request when already suspended.");
|
"Got audio suspend request when already suspended.");
|
||||||
} else {
|
} else {
|
||||||
#if BA_OSTYPE_IOS_TVOS
|
#if BA_OSTYPE_IOS_TVOS
|
||||||
@ -599,13 +608,14 @@ void AudioServer::SetSuspended_(bool suspend) {
|
|||||||
+ std::to_string(g_core->GetAppTimeSeconds()));
|
+ std::to_string(g_core->GetAppTimeSeconds()));
|
||||||
alcDeviceResumeSOFT(device);
|
alcDeviceResumeSOFT(device);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Error in alcDeviceResumeSOFT at time "
|
"Error in alcDeviceResumeSOFT at time "
|
||||||
+ std::to_string(g_core->GetAppTimeSeconds()) + ": "
|
+ std::to_string(g_core->GetAppTimeSeconds()) + ": "
|
||||||
+ g_core->platform->DemangleCXXSymbol(typeid(e).name()) + " "
|
+ g_core->platform->DemangleCXXSymbol(typeid(e).name()) + " "
|
||||||
+ e.what());
|
+ e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Log(LogLevel::kError, "Unknown error in alcDeviceResumeSOFT");
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
|
"Unknown error in alcDeviceResumeSOFT");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
last_started_playing_time_ = g_core->GetAppTimeSeconds();
|
last_started_playing_time_ = g_core->GetAppTimeSeconds();
|
||||||
@ -777,7 +787,7 @@ void AudioServer::UpdateAvailableSources_() {
|
|||||||
// that probably means somebody's grabbing a source but never
|
// that probably means somebody's grabbing a source but never
|
||||||
// resubmitting it.
|
// resubmitting it.
|
||||||
if (t - i->client_source()->last_lock_time() > 10000) {
|
if (t - i->client_source()->last_lock_time() > 10000) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Client audio source has been locked for too long; "
|
"Client audio source has been locked for too long; "
|
||||||
"probably leaked. (debug id "
|
"probably leaked. (debug id "
|
||||||
+ std::to_string(i->client_source()->lock_debug_id()) + ")");
|
+ std::to_string(i->client_source()->lock_debug_id()) + ")");
|
||||||
@ -926,7 +936,8 @@ void AudioServer::ProcessDeviceDisconnects_(seconds_t real_time_seconds) {
|
|||||||
|
|
||||||
if (connected == 0
|
if (connected == 0
|
||||||
&& real_time_seconds - last_reset_attempt_time_ >= retry_interval) {
|
&& real_time_seconds - last_reset_attempt_time_ >= retry_interval) {
|
||||||
Log(LogLevel::kInfo, "OpenAL device disconnected; resetting...");
|
Log(LogName::kBaAudio, LogLevel::kInfo,
|
||||||
|
"OpenAL device disconnected; resetting...");
|
||||||
if (g_buildconfig.ostype_android()) {
|
if (g_buildconfig.ostype_android()) {
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
openalsoft_android_log_ +=
|
openalsoft_android_log_ +=
|
||||||
@ -995,7 +1006,7 @@ void AudioServer::ProcessDeviceDisconnects_(seconds_t real_time_seconds) {
|
|||||||
shipped_reconnect_logs_ = true;
|
shipped_reconnect_logs_ = true;
|
||||||
if (g_buildconfig.ostype_android()) {
|
if (g_buildconfig.ostype_android()) {
|
||||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||||
"Have been disconnected for a while; dumping OpenAL log.\n"
|
"Have been disconnected for a while; dumping OpenAL log.\n"
|
||||||
"------------------------"
|
"------------------------"
|
||||||
" OPENALSOFT-RECONNECT-LOG-BEGIN ----------------------\n"
|
" OPENALSOFT-RECONNECT-LOG-BEGIN ----------------------\n"
|
||||||
@ -1153,8 +1164,9 @@ AudioServer::ThreadSource_::ThreadSource_(AudioServer* audio_server_in,
|
|||||||
ALenum err = alGetError();
|
ALenum err = alGetError();
|
||||||
valid_ = (err == AL_NO_ERROR);
|
valid_ = (err == AL_NO_ERROR);
|
||||||
if (!valid_) {
|
if (!valid_) {
|
||||||
Log(LogLevel::kError, std::string("AL Error ") + GetALErrorString(err)
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ " on source creation.");
|
std::string("AL Error ") + GetALErrorString(err)
|
||||||
|
+ " on source creation.");
|
||||||
} else {
|
} else {
|
||||||
// In vr mode we keep the microphone a bit closer to the camera
|
// In vr mode we keep the microphone a bit closer to the camera
|
||||||
// for realism purposes, so we need stuff louder in general.
|
// for realism purposes, so we need stuff louder in general.
|
||||||
@ -1347,7 +1359,7 @@ void AudioServer::ThreadSource_::SetPosition(float x, float y, float z) {
|
|||||||
z = 500;
|
z = 500;
|
||||||
}
|
}
|
||||||
if (oob) {
|
if (oob) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaAudio, LogLevel::kError,
|
||||||
"AudioServer::ThreadSource::SetPosition"
|
"AudioServer::ThreadSource::SetPosition"
|
||||||
" got out-of-bounds value.");
|
" got out-of-bounds value.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,8 @@ void AudioSource::SetPosition(float x, float y, float z) {
|
|||||||
assert(client_queue_size_ > 0);
|
assert(client_queue_size_ > 0);
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
|
if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
|
||||||
Log(LogLevel::kError, "Got nan value in AudioSource::SetPosition.");
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
|
"Got nan value in AudioSource::SetPosition.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
g_base->audio_server->PushSourceSetPositionCall(play_id_, Vector3f(x, y, z));
|
g_base->audio_server->PushSourceSetPositionCall(play_id_, Vector3f(x, y, z));
|
||||||
|
|||||||
@ -89,9 +89,9 @@ void AudioStreamer::Update() {
|
|||||||
// A fun anomaly in the linux version; we sometimes get more
|
// A fun anomaly in the linux version; we sometimes get more
|
||||||
// "processed" buffers than we have queued.
|
// "processed" buffers than we have queued.
|
||||||
if (queued < processed) {
|
if (queued < processed) {
|
||||||
Log(LogLevel::kError, "Streamer oddness: queued(" + std::to_string(queued)
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
+ "); processed(" + std::to_string(processed)
|
"Streamer oddness: queued(" + std::to_string(queued) + "); processed("
|
||||||
+ ")");
|
+ std::to_string(processed) + ")");
|
||||||
processed = queued;
|
processed = queued;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -93,7 +93,7 @@ void OggStream::DoStream(char* pcm, int* size, unsigned int* rate) {
|
|||||||
static bool reported_error = false;
|
static bool reported_error = false;
|
||||||
if (!reported_error) {
|
if (!reported_error) {
|
||||||
reported_error = true;
|
reported_error = true;
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaAudio, LogLevel::kError,
|
||||||
"Error streaming ogg file: '" + file_name() + "'.");
|
"Error streaming ogg file: '" + file_name() + "'.");
|
||||||
}
|
}
|
||||||
if (loops()) {
|
if (loops()) {
|
||||||
|
|||||||
@ -31,10 +31,10 @@
|
|||||||
#include "ballistica/base/support/plus_soft.h"
|
#include "ballistica/base/support/plus_soft.h"
|
||||||
#include "ballistica/base/support/stdio_console.h"
|
#include "ballistica/base/support/stdio_console.h"
|
||||||
#include "ballistica/base/ui/ui_delegate.h"
|
#include "ballistica/base/ui/ui_delegate.h"
|
||||||
#include "ballistica/core/python/core_python.h"
|
|
||||||
#include "ballistica/shared/foundation/event_loop.h"
|
#include "ballistica/shared/foundation/event_loop.h"
|
||||||
#include "ballistica/shared/foundation/logging.h"
|
#include "ballistica/shared/foundation/logging.h"
|
||||||
#include "ballistica/shared/generic/utils.h"
|
#include "ballistica/shared/generic/utils.h"
|
||||||
|
#include "ballistica/shared/math/vector4f.h"
|
||||||
#include "ballistica/shared/python/python_command.h"
|
#include "ballistica/shared/python/python_command.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
@ -125,11 +125,6 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
|
|||||||
FatalError("babase._env.on_native_module_import() call failed.");
|
FatalError("babase._env.on_native_module_import() call failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ..and because Python is now feeding us logs, we can push any logs
|
|
||||||
// through that we've been holding on to and start forwarding log calls as
|
|
||||||
// they happen.
|
|
||||||
g_core->python->EnablePythonLoggingCalls();
|
|
||||||
|
|
||||||
// A marker we pop down at the very end so other modules can run sanity
|
// A marker we pop down at the very end so other modules can run sanity
|
||||||
// checks to make sure we aren't importing them reciprocally when they
|
// checks to make sure we aren't importing them reciprocally when they
|
||||||
// import us.
|
// import us.
|
||||||
@ -160,7 +155,7 @@ void BaseFeatureSet::SuccessScreenMessage() {
|
|||||||
python->objs().Get(BasePython::ObjID::kSuccessMessageCall).Call();
|
python->objs().Get(BasePython::ObjID::kSuccessMessageCall).Call();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"SuccessScreenMessage called without logic event_loop in place.");
|
"SuccessScreenMessage called without logic event_loop in place.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,7 +166,7 @@ void BaseFeatureSet::ErrorScreenMessage() {
|
|||||||
python->objs().Get(BasePython::ObjID::kErrorMessageCall).Call();
|
python->objs().Get(BasePython::ObjID::kErrorMessageCall).Call();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"ErrorScreenMessage called without logic event_loop in place.");
|
"ErrorScreenMessage called without logic event_loop in place.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +181,8 @@ auto BaseFeatureSet::GetV2AccountID() -> std::optional<std::string> {
|
|||||||
}
|
}
|
||||||
return result.ValueAsString();
|
return result.ValueAsString();
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "GetV2AccountID() py call errored.");
|
Log(LogName::kBaAccount, LogLevel::kError,
|
||||||
|
"GetV2AccountID() py call errored.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,7 +215,7 @@ void BaseFeatureSet::StartApp() {
|
|||||||
|
|
||||||
// Read in ba.app.config for anyone who wants to start looking at it
|
// Read in ba.app.config for anyone who wants to start looking at it
|
||||||
// (though we don't explicitly ask anyone to apply it until later).
|
// (though we don't explicitly ask anyone to apply it until later).
|
||||||
python->ReadConfig();
|
// python->ReadConfig();
|
||||||
|
|
||||||
// Allow our subsystems to start doing work in their own threads and
|
// Allow our subsystems to start doing work in their own threads and
|
||||||
// communicating with other subsystems. Note that we may still want to run
|
// communicating with other subsystems. Note that we may still want to run
|
||||||
@ -262,7 +258,7 @@ void BaseFeatureSet::StartApp() {
|
|||||||
char buffer[128];
|
char buffer[128];
|
||||||
snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
"StartApp() took too long (%.2lf seconds).", duration);
|
"StartApp() took too long (%.2lf seconds).", duration);
|
||||||
Log(LogLevel::kWarning, buffer);
|
Log(LogName::kBa, LogLevel::kWarning, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +267,7 @@ void BaseFeatureSet::SuspendApp() {
|
|||||||
assert(g_core->InMainThread());
|
assert(g_core->InMainThread());
|
||||||
|
|
||||||
if (app_suspended_) {
|
if (app_suspended_) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
"AppAdapter::SuspendApp() called with app already suspended.");
|
"AppAdapter::SuspendApp() called with app already suspended.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -313,7 +309,7 @@ void BaseFeatureSet::SuspendApp() {
|
|||||||
// running_loop_count = loops.size();
|
// running_loop_count = loops.size();
|
||||||
if (running_loops.empty()) {
|
if (running_loops.empty()) {
|
||||||
if (g_buildconfig.debug_build()) {
|
if (g_buildconfig.debug_build()) {
|
||||||
Log(LogLevel::kDebug,
|
Log(LogName::kBa, LogLevel::kDebug,
|
||||||
"SuspendApp() completed in "
|
"SuspendApp() completed in "
|
||||||
+ std::to_string(core::CorePlatform::GetCurrentMillisecs()
|
+ std::to_string(core::CorePlatform::GetCurrentMillisecs()
|
||||||
- start_time)
|
- start_time)
|
||||||
@ -374,7 +370,7 @@ void BaseFeatureSet::SuspendApp() {
|
|||||||
}
|
}
|
||||||
msg += ").";
|
msg += ").";
|
||||||
|
|
||||||
Log(LogLevel::kError, msg);
|
Log(LogName::kBa, LogLevel::kError, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseFeatureSet::UnsuspendApp() {
|
void BaseFeatureSet::UnsuspendApp() {
|
||||||
@ -382,7 +378,7 @@ void BaseFeatureSet::UnsuspendApp() {
|
|||||||
assert(g_core->InMainThread());
|
assert(g_core->InMainThread());
|
||||||
|
|
||||||
if (!app_suspended_) {
|
if (!app_suspended_) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
"AppAdapter::UnsuspendApp() called with app not in suspendedstate.");
|
"AppAdapter::UnsuspendApp() called with app not in suspendedstate.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -400,7 +396,7 @@ void BaseFeatureSet::UnsuspendApp() {
|
|||||||
g_base->networking->OnAppUnsuspend();
|
g_base->networking->OnAppUnsuspend();
|
||||||
|
|
||||||
if (g_buildconfig.debug_build()) {
|
if (g_buildconfig.debug_build()) {
|
||||||
Log(LogLevel::kDebug,
|
Log(LogName::kBa, LogLevel::kDebug,
|
||||||
"UnsuspendApp() completed in "
|
"UnsuspendApp() completed in "
|
||||||
+ std::to_string(core::CorePlatform::GetCurrentMillisecs()
|
+ std::to_string(core::CorePlatform::GetCurrentMillisecs()
|
||||||
- start_time)
|
- start_time)
|
||||||
@ -431,7 +427,7 @@ void BaseFeatureSet::LogVersionInfo_() {
|
|||||||
snprintf(buffer, sizeof(buffer), "BallisticaKit %s build %d.",
|
snprintf(buffer, sizeof(buffer), "BallisticaKit %s build %d.",
|
||||||
kEngineVersion, kEngineBuildNumber);
|
kEngineVersion, kEngineBuildNumber);
|
||||||
}
|
}
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBa, LogLevel::kInfo, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseFeatureSet::set_app_mode(AppMode* mode) {
|
void BaseFeatureSet::set_app_mode(AppMode* mode) {
|
||||||
@ -440,7 +436,7 @@ void BaseFeatureSet::set_app_mode(AppMode* mode) {
|
|||||||
// Redundant sets should not happen (make an exception here for empty mode
|
// Redundant sets should not happen (make an exception here for empty mode
|
||||||
// since that's in place before any app mode is officially set).
|
// since that's in place before any app mode is officially set).
|
||||||
if (mode == app_mode_ && mode != EmptyAppMode::GetSingleton()) {
|
if (mode == app_mode_ && mode != EmptyAppMode::GetSingleton()) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
"set_app_mode called with already-current app-mode; unexpected.");
|
"set_app_mode called with already-current app-mode; unexpected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +564,8 @@ auto BaseFeatureSet::GetAppInstanceUUID() -> const std::string& {
|
|||||||
if (!have_app_instance_uuid) {
|
if (!have_app_instance_uuid) {
|
||||||
// As an emergency fallback simply use a single random number. We
|
// As an emergency fallback simply use a single random number. We
|
||||||
// should probably simply disallow this before Python is up.
|
// should probably simply disallow this before Python is up.
|
||||||
Log(LogLevel::kWarning, "GetSessionUUID() using rand fallback.");
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
|
"GetSessionUUID() using rand fallback.");
|
||||||
srand(static_cast<unsigned int>(
|
srand(static_cast<unsigned int>(
|
||||||
core::CorePlatform::GetCurrentMillisecs())); // NOLINT
|
core::CorePlatform::GetCurrentMillisecs())); // NOLINT
|
||||||
app_instance_uuid =
|
app_instance_uuid =
|
||||||
@ -576,7 +573,8 @@ auto BaseFeatureSet::GetAppInstanceUUID() -> const std::string& {
|
|||||||
have_app_instance_uuid = true;
|
have_app_instance_uuid = true;
|
||||||
}
|
}
|
||||||
if (app_instance_uuid.size() >= 100) {
|
if (app_instance_uuid.size() >= 100) {
|
||||||
Log(LogLevel::kWarning, "session id longer than it should be.");
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
|
"session id longer than it should be.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return app_instance_uuid;
|
return app_instance_uuid;
|
||||||
@ -668,6 +666,7 @@ void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {
|
|||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
if (!warned) {
|
if (!warned) {
|
||||||
warned = true;
|
warned = true;
|
||||||
|
printf("MSG %s\n", msg.c_str());
|
||||||
printf(
|
printf(
|
||||||
"WARNING: V1CloudLog called before babase fully imported; "
|
"WARNING: V1CloudLog called before babase fully imported; "
|
||||||
"ignoring.\n");
|
"ignoring.\n");
|
||||||
@ -725,8 +724,9 @@ void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {
|
|||||||
plus()->DirectSendV1CloudLogs(logprefix, logsuffix, false, nullptr);
|
plus()->DirectSendV1CloudLogs(logprefix, logsuffix, false, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseFeatureSet::PushDevConsolePrintCall(const std::string& msg) {
|
void BaseFeatureSet::PushDevConsolePrintCall(const std::string& msg,
|
||||||
ui->PushDevConsolePrintCall(msg);
|
float scale, Vector4f color) {
|
||||||
|
ui->PushDevConsolePrintCall(msg, scale, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* BaseFeatureSet::GetPyExceptionType(PyExcType exctype) {
|
PyObject* BaseFeatureSet::GetPyExceptionType(PyExcType exctype) {
|
||||||
@ -833,7 +833,7 @@ void BaseFeatureSet::DoPushObjCall(const PythonObjectSetBase* objset, int id) {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBa, LogLevel::kError,
|
||||||
"BaseFeatureSet::DoPushObjCall called before event loop created.");
|
"BaseFeatureSet::DoPushObjCall called before event loop created.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -968,8 +968,9 @@ void BaseFeatureSet::SetAppActive(bool active) {
|
|||||||
// Issue a gentle warning if they are feeding us the same state twice in a
|
// Issue a gentle warning if they are feeding us the same state twice in a
|
||||||
// row; might imply faulty logic on an app-adapter or whatnot.
|
// row; might imply faulty logic on an app-adapter or whatnot.
|
||||||
if (app_active_set_ && app_active_ == active) {
|
if (app_active_set_ && app_active_ == active) {
|
||||||
Log(LogLevel::kWarning, "SetAppActive called with state "
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
+ std::to_string(active) + " twice in a row.");
|
"SetAppActive called with state " + std::to_string(active)
|
||||||
|
+ " twice in a row.");
|
||||||
}
|
}
|
||||||
app_active_set_ = true;
|
app_active_set_ = true;
|
||||||
app_active_ = active;
|
app_active_ = active;
|
||||||
|
|||||||
@ -731,7 +731,8 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
|
|||||||
-> PyObject* override;
|
-> PyObject* override;
|
||||||
auto FeatureSetFromData(PyObject* obj) -> FeatureSetNativeComponent* override;
|
auto FeatureSetFromData(PyObject* obj) -> FeatureSetNativeComponent* override;
|
||||||
void DoV1CloudLog(const std::string& msg) override;
|
void DoV1CloudLog(const std::string& msg) override;
|
||||||
void PushDevConsolePrintCall(const std::string& msg) override;
|
void PushDevConsolePrintCall(const std::string& msg, float scale,
|
||||||
|
Vector4f color) override;
|
||||||
auto GetPyExceptionType(PyExcType exctype) -> PyObject* override;
|
auto GetPyExceptionType(PyExcType exctype) -> PyObject* override;
|
||||||
auto PrintPythonStackTrace() -> bool override;
|
auto PrintPythonStackTrace() -> bool override;
|
||||||
auto GetPyLString(PyObject* obj) -> std::string override;
|
auto GetPyLString(PyObject* obj) -> std::string override;
|
||||||
|
|||||||
@ -72,8 +72,8 @@ void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass a newly allocated raw pointer to the bg-dynamics thread; it takes care
|
// Pass a newly allocated raw pointer to the bg-dynamics thread; it takes
|
||||||
// of disposing it when done.
|
// care of disposing it when done.
|
||||||
auto d = Object::NewDeferred<BGDynamicsServer::StepData>();
|
auto d = Object::NewDeferred<BGDynamicsServer::StepData>();
|
||||||
d->graphics_quality = Graphics::GraphicsQualityFromRequest(
|
d->graphics_quality = Graphics::GraphicsQualityFromRequest(
|
||||||
g_base->graphics->settings()->graphics_quality,
|
g_base->graphics->settings()->graphics_quality,
|
||||||
|
|||||||
@ -1372,7 +1372,7 @@ void BGDynamicsServer::Emit(const BGDynamicsEmission& def) {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
int t = static_cast<int>(def.emit_type);
|
int t = static_cast<int>(def.emit_type);
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kError,
|
||||||
"Invalid bg-dynamics emit type: " + std::to_string(t));
|
"Invalid bg-dynamics emit type: " + std::to_string(t));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2361,9 +2361,9 @@ void BGDynamicsServer::Step(StepData* step_data) {
|
|||||||
|
|
||||||
// Math sanity check.
|
// Math sanity check.
|
||||||
if (step_count_ < 0) {
|
if (step_count_ < 0) {
|
||||||
BA_LOG_ONCE(LogLevel::kWarning, "BGDynamics step_count too low ("
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
+ std::to_string(step_count_)
|
"BGDynamics step_count too low (" + std::to_string(step_count_)
|
||||||
+ "); should not happen.");
|
+ "); should not happen.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2376,9 +2376,9 @@ void BGDynamicsServer::PushStep(StepData* data) {
|
|||||||
|
|
||||||
// Client thread should stop feeding us if we get clogged up.
|
// Client thread should stop feeding us if we get clogged up.
|
||||||
if (step_count_ > 5) {
|
if (step_count_ > 5) {
|
||||||
BA_LOG_ONCE(LogLevel::kWarning, "BGDynamics step_count too high ("
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kWarning,
|
||||||
+ std::to_string(step_count_)
|
"BGDynamics step_count too high (" + std::to_string(step_count_)
|
||||||
+ "); should not happen.");
|
+ "); should not happen.");
|
||||||
}
|
}
|
||||||
|
|
||||||
event_loop()->PushCall([this, data] { Step(data); });
|
event_loop()->PushCall([this, data] { Step(data); });
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class RendererGL::MeshAssetDataGL : public MeshAssetRendererData {
|
|||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kWarning,
|
LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"GL WARNING - USING 32 BIT INDICES WHICH WONT WORK IN ES2!!");
|
"GL WARNING - USING 32 BIT INDICES WHICH WONT WORK IN ES2!!");
|
||||||
elem_count_ = static_cast<uint32_t>(model.indices32().size());
|
elem_count_ = static_cast<uint32_t>(model.indices32().size());
|
||||||
index_type_ = GL_UNSIGNED_INT;
|
index_type_ = GL_UNSIGNED_INT;
|
||||||
|
|||||||
@ -126,7 +126,7 @@ class RendererGL::MeshDataGL : public MeshRendererData {
|
|||||||
dynamic_draw_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
dynamic_draw_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
||||||
index_state_ = data->state;
|
index_state_ = data->state;
|
||||||
have_index_data_ = true;
|
have_index_data_ = true;
|
||||||
BA_LOG_ONCE(LogLevel::kWarning,
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"GL WARNING - USING 32 BIT INDICES WHICH WONT WORK IN ES2!!");
|
"GL WARNING - USING 32 BIT INDICES WHICH WONT WORK IN ES2!!");
|
||||||
index_type_ = GL_UNSIGNED_INT;
|
index_type_ = GL_UNSIGNED_INT;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,7 +86,7 @@ class RendererGL::ProgramBlurGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ class RendererGL::ProgramBlurGL : public RendererGL::ProgramGL {
|
|||||||
"(colorTex,vUV8));\n"
|
"(colorTex,vUV8));\n"
|
||||||
"}";
|
"}";
|
||||||
if (flags & SHD_DEBUG_PRINT) {
|
if (flags & SHD_DEBUG_PRINT) {
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class RendererGL::ShaderGL : public Object {
|
|||||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||||
// Let's not crash here. We have a better chance of calling home this
|
// Let's not crash here. We have a better chance of calling home this
|
||||||
// way and theres a chance the game will still be playable.
|
// way and theres a chance the game will still be playable.
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
std::string("Compile failed for ") + GetTypeName()
|
std::string("Compile failed for ") + GetTypeName()
|
||||||
+ " shader:\n------------SOURCE BEGIN-------------\n" + src_fin
|
+ " shader:\n------------SOURCE BEGIN-------------\n" + src_fin
|
||||||
+ "\n-----------SOURCE END-------------\n" + GetInfo()
|
+ "\n-----------SOURCE END-------------\n" + GetInfo()
|
||||||
@ -65,7 +65,7 @@ class RendererGL::ShaderGL : public Object {
|
|||||||
const char* version = (const char*)glGetString(GL_VERSION);
|
const char* version = (const char*)glGetString(GL_VERSION);
|
||||||
const char* vendor = (const char*)glGetString(GL_VENDOR);
|
const char* vendor = (const char*)glGetString(GL_VENDOR);
|
||||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
std::string("WARNING: info returned for ") + GetTypeName()
|
std::string("WARNING: info returned for ") + GetTypeName()
|
||||||
+ " shader:\n------------SOURCE BEGIN-------------\n" + src_fin
|
+ " shader:\n------------SOURCE BEGIN-------------\n" + src_fin
|
||||||
+ "\n-----------SOURCE END-------------\n" + info
|
+ "\n-----------SOURCE END-------------\n" + info
|
||||||
@ -166,7 +166,7 @@ class RendererGL::ProgramGL {
|
|||||||
GLint linkStatus;
|
GLint linkStatus;
|
||||||
glGetProgramiv(program_, GL_LINK_STATUS, &linkStatus);
|
glGetProgramiv(program_, GL_LINK_STATUS, &linkStatus);
|
||||||
if (linkStatus == GL_FALSE) {
|
if (linkStatus == GL_FALSE) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"Link failed for program '" + name_ + "':\n" + GetInfo());
|
"Link failed for program '" + name_ + "':\n" + GetInfo());
|
||||||
} else {
|
} else {
|
||||||
assert(linkStatus == GL_TRUE);
|
assert(linkStatus == GL_TRUE);
|
||||||
@ -176,8 +176,9 @@ class RendererGL::ProgramGL {
|
|||||||
&& (strstr(info.c_str(), "error:") || strstr(info.c_str(), "warning:")
|
&& (strstr(info.c_str(), "error:") || strstr(info.c_str(), "warning:")
|
||||||
|| strstr(info.c_str(), "Error:")
|
|| strstr(info.c_str(), "Error:")
|
||||||
|| strstr(info.c_str(), "Warning:"))) {
|
|| strstr(info.c_str(), "Warning:"))) {
|
||||||
Log(LogLevel::kError, "WARNING: program using frag shader '" + name_
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
+ "' returned info:\n" + info);
|
"WARNING: program using frag shader '" + name_
|
||||||
|
+ "' returned info:\n" + info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,9 +315,9 @@ class RendererGL::ProgramGL {
|
|||||||
assert(IsBound());
|
assert(IsBound());
|
||||||
int c = glGetUniformLocation(program_, tex_name);
|
int c = glGetUniformLocation(program_, tex_name);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
Log(LogLevel::kError, "ShaderGL: " + name_
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
+ ": Can't set texture unit for texture '"
|
"ShaderGL: " + name_ + ": Can't set texture unit for texture '"
|
||||||
+ tex_name + "'");
|
+ tex_name + "'");
|
||||||
BA_DEBUG_CHECK_GL_ERROR;
|
BA_DEBUG_CHECK_GL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
glUniform1i(c, unit);
|
glUniform1i(c, unit);
|
||||||
|
|||||||
@ -235,7 +235,7 @@ class RendererGL::ProgramObjectGL : public RendererGL::ProgramGL {
|
|||||||
}
|
}
|
||||||
s += "}";
|
s += "}";
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -321,7 +321,7 @@ class RendererGL::ProgramObjectGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -158,7 +158,7 @@ class RendererGL::ProgramPostProcessGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ class RendererGL::ProgramPostProcessGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class RendererGL::ProgramShieldGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ class RendererGL::ProgramShieldGL : public RendererGL::ProgramGL {
|
|||||||
//" " BA_GLSL_FRAGCOLOR " = vec4(vec3(depth),1);\n"
|
//" " BA_GLSL_FRAGCOLOR " = vec4(vec3(depth),1);\n"
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -234,7 +234,7 @@ class RendererGL::ProgramSimpleGL : public RendererGL::ProgramGL {
|
|||||||
"}";
|
"}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT) {
|
if (flags & SHD_DEBUG_PRINT) {
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ class RendererGL::ProgramSimpleGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT) {
|
if (flags & SHD_DEBUG_PRINT) {
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -114,7 +114,7 @@ class RendererGL::ProgramSmokeGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ class RendererGL::ProgramSmokeGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT)
|
if (flags & SHD_DEBUG_PRINT)
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "ballistica/base/graphics/gl/program/program_gl.h"
|
#include "ballistica/base/graphics/gl/program/program_gl.h"
|
||||||
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
||||||
|
#include "ballistica/base/graphics/graphics.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ class RendererGL::ProgramSpriteGL : public RendererGL::ProgramGL {
|
|||||||
s += "}";
|
s += "}";
|
||||||
|
|
||||||
if (flags & SHD_DEBUG_PRINT) {
|
if (flags & SHD_DEBUG_PRINT) {
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@ -163,7 +164,7 @@ class RendererGL::ProgramSpriteGL : public RendererGL::ProgramGL {
|
|||||||
}
|
}
|
||||||
s += "}";
|
s += "}";
|
||||||
if (flags & SHD_DEBUG_PRINT) {
|
if (flags & SHD_DEBUG_PRINT) {
|
||||||
Log(LogLevel::kInfo,
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class RendererGL::RenderTargetGL : public RenderTarget {
|
|||||||
// this needs to be on for glClear to work on depth.
|
// this needs to be on for glClear to work on depth.
|
||||||
if (!renderer_->depth_writing_enabled_) {
|
if (!renderer_->depth_writing_enabled_) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kWarning,
|
LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"RendererGL: depth-writing not enabled when clearing depth");
|
"RendererGL: depth-writing not enabled when clearing depth");
|
||||||
}
|
}
|
||||||
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
||||||
|
|||||||
@ -90,7 +90,7 @@ void RendererGL::CheckGLError(const char* file, int line) {
|
|||||||
BA_PRECONDITION_FATAL(vendor);
|
BA_PRECONDITION_FATAL(vendor);
|
||||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||||
BA_PRECONDITION_FATAL(renderer);
|
BA_PRECONDITION_FATAL(renderer);
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"OpenGL Error at " + std::string(file) + " line " + std::to_string(line)
|
"OpenGL Error at " + std::string(file) + " line " + std::to_string(line)
|
||||||
+ ": " + GLErrorToString(err) + "\nrenderer: " + renderer
|
+ ": " + GLErrorToString(err) + "\nrenderer: " + renderer
|
||||||
+ "\nvendor: " + vendor + "\nversion: " + version
|
+ "\nvendor: " + vendor + "\nversion: " + version
|
||||||
@ -174,7 +174,7 @@ void RendererGL::CheckGLVersion() {
|
|||||||
if (gl_is_es()) {
|
if (gl_is_es()) {
|
||||||
// GL ES version strings start with 'OpenGL ES X' with X being version.
|
// GL ES version strings start with 'OpenGL ES X' with X being version.
|
||||||
const char* prefix = "OpenGL ES ";
|
const char* prefix = "OpenGL ES ";
|
||||||
int prefixlen = strlen(prefix);
|
auto prefixlen = strlen(prefix);
|
||||||
BA_PRECONDITION_FATAL(!strncmp(version_str, prefix, prefixlen));
|
BA_PRECONDITION_FATAL(!strncmp(version_str, prefix, prefixlen));
|
||||||
if (version_str[prefixlen] != '3') {
|
if (version_str[prefixlen] != '3') {
|
||||||
FatalError(
|
FatalError(
|
||||||
@ -223,11 +223,9 @@ void RendererGL::CheckGLCapabilities_() {
|
|||||||
basestr = "OpenGL";
|
basestr = "OpenGL";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_buildconfig.debug_build()) {
|
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||||
Log(LogLevel::kInfo, std::string("Using ") + basestr + " (vendor: " + vendor
|
std::string("Using ") + basestr + " (vendor: " + vendor
|
||||||
+ ", renderer: " + renderer
|
+ ", renderer: " + renderer + ", version: " + version_str + ").");
|
||||||
+ ", version: " + version_str + ").");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build a vector of extensions. Newer GLs give us extensions as lists
|
// Build a vector of extensions. Newer GLs give us extensions as lists
|
||||||
// already, but on older ones we may need to break a single string apart
|
// already, but on older ones we may need to break a single string apart
|
||||||
@ -246,7 +244,8 @@ void RendererGL::CheckGLCapabilities_() {
|
|||||||
extensions.push_back(extension);
|
extensions.push_back(extension);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kWarning, "Falling back on legacy GL_EXTENSIONS parsing.");
|
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
|
"Falling back on legacy GL_EXTENSIONS parsing.");
|
||||||
// Fall back on parsing the single giant string if need be.
|
// Fall back on parsing the single giant string if need be.
|
||||||
// (Can probably kill this).
|
// (Can probably kill this).
|
||||||
auto* ex = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
auto* ex = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||||
@ -292,7 +291,8 @@ void RendererGL::CheckGLCapabilities_() {
|
|||||||
c_types.push_back(TextureCompressionType::kETC1);
|
c_types.push_back(TextureCompressionType::kETC1);
|
||||||
} else {
|
} else {
|
||||||
if (g_buildconfig.ostype_android()) {
|
if (g_buildconfig.ostype_android()) {
|
||||||
Log(LogLevel::kError, "Android device missing ETC1 support.");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"Android device missing ETC1 support.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +360,8 @@ void RendererGL::CheckGLCapabilities_() {
|
|||||||
&samples[0]);
|
&samples[0]);
|
||||||
msaa_max_samples_rgb565_ = samples[0];
|
msaa_max_samples_rgb565_ = samples[0];
|
||||||
} else {
|
} else {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "Got 0 samplecounts for RGB565");
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"Got 0 samplecounts for RGB565");
|
||||||
msaa_max_samples_rgb565_ = 0;
|
msaa_max_samples_rgb565_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,7 +375,8 @@ void RendererGL::CheckGLCapabilities_() {
|
|||||||
&samples[0]);
|
&samples[0]);
|
||||||
msaa_max_samples_rgb8_ = samples[0];
|
msaa_max_samples_rgb8_ = samples[0];
|
||||||
} else {
|
} else {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "Got 0 samplecounts for RGB8");
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"Got 0 samplecounts for RGB8");
|
||||||
msaa_max_samples_rgb8_ = 0;
|
msaa_max_samples_rgb8_ = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2385,7 +2387,7 @@ void RendererGL::UpdateVignetteTex_(bool force) {
|
|||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
static bool reported = false;
|
static bool reported = false;
|
||||||
if (!reported) {
|
if (!reported) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"32-bit vignette creation failed; falling back to 16.");
|
"32-bit vignette creation failed; falling back to 16.");
|
||||||
reported = true;
|
reported = true;
|
||||||
}
|
}
|
||||||
@ -2443,7 +2445,8 @@ void RendererGL::UpdateVignetteTex_(bool force) {
|
|||||||
|
|
||||||
auto RendererGL::GetFunkyDepthIssue_() -> bool {
|
auto RendererGL::GetFunkyDepthIssue_() -> bool {
|
||||||
if (!funky_depth_issue_set_) {
|
if (!funky_depth_issue_set_) {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "fetching funky depth issue but not set");
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"fetching funky depth issue but not set");
|
||||||
}
|
}
|
||||||
return funky_depth_issue_;
|
return funky_depth_issue_;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,8 @@ class RendererGL::TextureDataGL : public TextureAssetRendererData {
|
|||||||
|
|
||||||
~TextureDataGL() override {
|
~TextureDataGL() override {
|
||||||
if (!g_base->app_adapter->InGraphicsContext()) {
|
if (!g_base->app_adapter->InGraphicsContext()) {
|
||||||
Log(LogLevel::kError, "TextureDataGL dying outside of graphics thread.");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"TextureDataGL dying outside of graphics thread.");
|
||||||
} else {
|
} else {
|
||||||
// If we're currently bound as anything, clear that out (otherwise a
|
// If we're currently bound as anything, clear that out (otherwise a
|
||||||
// new texture with that same ID won't be bindable).
|
// new texture with that same ID won't be bindable).
|
||||||
|
|||||||
@ -204,7 +204,7 @@ auto Graphics::TextureQualityFromAppConfig() -> TextureQualityRequest {
|
|||||||
} else if (texqualstr == "Low") {
|
} else if (texqualstr == "Low") {
|
||||||
texture_quality_requested = TextureQualityRequest::kLow;
|
texture_quality_requested = TextureQualityRequest::kLow;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"Invalid texture quality: '" + texqualstr + "'; defaulting to low.");
|
"Invalid texture quality: '" + texqualstr + "'; defaulting to low.");
|
||||||
texture_quality_requested = TextureQualityRequest::kLow;
|
texture_quality_requested = TextureQualityRequest::kLow;
|
||||||
}
|
}
|
||||||
@ -221,7 +221,8 @@ auto Graphics::VSyncFromAppConfig() -> VSyncRequest {
|
|||||||
} else if (v_sync == "Never") {
|
} else if (v_sync == "Never") {
|
||||||
return VSyncRequest::kNever;
|
return VSyncRequest::kNever;
|
||||||
}
|
}
|
||||||
Log(LogLevel::kError, "Invalid 'Vertical Sync' value: '" + v_sync + "'");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"Invalid 'Vertical Sync' value: '" + v_sync + "'");
|
||||||
return VSyncRequest::kNever;
|
return VSyncRequest::kNever;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +241,7 @@ auto Graphics::GraphicsQualityFromAppConfig() -> GraphicsQualityRequest {
|
|||||||
} else if (gqualstr == "Low") {
|
} else if (gqualstr == "Low") {
|
||||||
graphics_quality_requested = GraphicsQualityRequest::kLow;
|
graphics_quality_requested = GraphicsQualityRequest::kLow;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"Invalid graphics quality: '" + gqualstr + "'; defaulting to auto.");
|
"Invalid graphics quality: '" + gqualstr + "'; defaulting to auto.");
|
||||||
graphics_quality_requested = GraphicsQualityRequest::kAuto;
|
graphics_quality_requested = GraphicsQualityRequest::kAuto;
|
||||||
}
|
}
|
||||||
@ -627,7 +628,7 @@ void Graphics::FadeScreen(bool to, millisecs_t time, PyObject* endcall) {
|
|||||||
// (otherwise, overlapping fades can cause things to get lost)
|
// (otherwise, overlapping fades can cause things to get lost)
|
||||||
if (fade_end_call_.Exists()) {
|
if (fade_end_call_.Exists()) {
|
||||||
if (g_buildconfig.debug_build()) {
|
if (g_buildconfig.debug_build()) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"2 fades overlapping; running first fade-end-call early.");
|
"2 fades overlapping; running first fade-end-call early.");
|
||||||
}
|
}
|
||||||
fade_end_call_->Schedule();
|
fade_end_call_->Schedule();
|
||||||
@ -861,7 +862,7 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
if (g_core->vr_mode()) {
|
if (g_core->vr_mode()) {
|
||||||
if (frame_def->GetOverlayFlatPass()->HasDrawCommands()) {
|
if (frame_def->GetOverlayFlatPass()->HasDrawCommands()) {
|
||||||
if (!g_base->ui->MainMenuVisible()) {
|
if (!g_base->ui->MainMenuVisible()) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"Drawing in overlay pass in VR mode with no UI present; "
|
"Drawing in overlay pass in VR mode with no UI present; "
|
||||||
"shouldn't happen!");
|
"shouldn't happen!");
|
||||||
}
|
}
|
||||||
@ -1015,7 +1016,7 @@ void Graphics::DrawFades(FrameDef* frame_def) {
|
|||||||
// TEMP HACK - don't trigger this while inactive.
|
// TEMP HACK - don't trigger this while inactive.
|
||||||
// Need to make overall fade logic smarter.
|
// Need to make overall fade logic smarter.
|
||||||
if (faded_time > 15000 && g_base->app_active()) {
|
if (faded_time > 15000 && g_base->app_active()) {
|
||||||
Log(LogLevel::kError, "FORCE-ENDING STUCK FADE");
|
Log(LogName::kBaGraphics, LogLevel::kError, "FORCE-ENDING STUCK FADE");
|
||||||
fade_out_ = false;
|
fade_out_ = false;
|
||||||
fade_ = 1.0f;
|
fade_ = 1.0f;
|
||||||
fade_time_ = 1000;
|
fade_time_ = 1000;
|
||||||
@ -1513,8 +1514,9 @@ void Graphics::DrawRadialMeter(MeshIndexedSimpleFull* m, float amt) {
|
|||||||
|
|
||||||
void Graphics::OnScreenSizeChange() {}
|
void Graphics::OnScreenSizeChange() {}
|
||||||
|
|
||||||
void Graphics::CalcVirtualRes_(float* x, float* y) {
|
void Graphics::GetBaseVirtualRes(float* x, float* y) {
|
||||||
assert(g_base);
|
assert(x);
|
||||||
|
assert(y);
|
||||||
float base_virtual_res_x;
|
float base_virtual_res_x;
|
||||||
float base_virtual_res_y;
|
float base_virtual_res_y;
|
||||||
if (g_base->ui->scale() == UIScale::kSmall) {
|
if (g_base->ui->scale() == UIScale::kSmall) {
|
||||||
@ -1524,6 +1526,15 @@ void Graphics::CalcVirtualRes_(float* x, float* y) {
|
|||||||
base_virtual_res_x = kBaseVirtualResX;
|
base_virtual_res_x = kBaseVirtualResX;
|
||||||
base_virtual_res_y = kBaseVirtualResY;
|
base_virtual_res_y = kBaseVirtualResY;
|
||||||
}
|
}
|
||||||
|
*x = base_virtual_res_x;
|
||||||
|
*y = base_virtual_res_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::CalcVirtualRes_(float* x, float* y) {
|
||||||
|
assert(g_base);
|
||||||
|
float base_virtual_res_x;
|
||||||
|
float base_virtual_res_y;
|
||||||
|
GetBaseVirtualRes(&base_virtual_res_x, &base_virtual_res_y);
|
||||||
|
|
||||||
float x_in = *x;
|
float x_in = *x;
|
||||||
float y_in = *y;
|
float y_in = *y;
|
||||||
@ -1662,7 +1673,7 @@ auto Graphics::ReflectionTypeFromString(const std::string& s)
|
|||||||
void Graphics::LanguageChanged() {
|
void Graphics::LanguageChanged() {
|
||||||
assert(g_base && g_base->InLogicThread());
|
assert(g_base && g_base->InLogicThread());
|
||||||
if (building_frame_def_) {
|
if (building_frame_def_) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
"Graphics::LanguageChanged() called during draw; should not happen.");
|
"Graphics::LanguageChanged() called during draw; should not happen.");
|
||||||
}
|
}
|
||||||
screenmessages->ClearScreenMessageTranslations();
|
screenmessages->ClearScreenMessageTranslations();
|
||||||
@ -1683,8 +1694,9 @@ auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request,
|
|||||||
case GraphicsQualityRequest::kAuto:
|
case GraphicsQualityRequest::kAuto:
|
||||||
return auto_val;
|
return auto_val;
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::kError, "Unhandled GraphicsQualityRequest value: "
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ std::to_string(static_cast<int>(request)));
|
"Unhandled GraphicsQualityRequest value: "
|
||||||
|
+ std::to_string(static_cast<int>(request)));
|
||||||
return GraphicsQuality::kLow;
|
return GraphicsQuality::kLow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1702,8 +1714,9 @@ auto Graphics::TextureQualityFromRequest(TextureQualityRequest request,
|
|||||||
case TextureQualityRequest::kAuto:
|
case TextureQualityRequest::kAuto:
|
||||||
return auto_val;
|
return auto_val;
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::kError, "Unhandled TextureQualityRequest value: "
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
+ std::to_string(static_cast<int>(request)));
|
"Unhandled TextureQualityRequest value: "
|
||||||
|
+ std::to_string(static_cast<int>(request)));
|
||||||
return TextureQuality::kLow;
|
return TextureQuality::kLow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1747,13 +1760,8 @@ void Graphics::DrawUIBounds(RenderPass* pass) {
|
|||||||
auto xf = c.ScopedTransform();
|
auto xf = c.ScopedTransform();
|
||||||
|
|
||||||
float width, height;
|
float width, height;
|
||||||
if (g_base->ui->scale() == UIScale::kSmall) {
|
|
||||||
width = kBaseVirtualResSmallX;
|
GetBaseVirtualRes(&width, &height);
|
||||||
height = kBaseVirtualResSmallY;
|
|
||||||
} else {
|
|
||||||
width = kBaseVirtualResX;
|
|
||||||
height = kBaseVirtualResY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slight offset in z to reduce z fighting.
|
// Slight offset in z to reduce z fighting.
|
||||||
c.Translate(0.5f * pass->virtual_width(), 0.5f * pass->virtual_height(),
|
c.Translate(0.5f * pass->virtual_width(), 0.5f * pass->virtual_height(),
|
||||||
|
|||||||
@ -153,6 +153,7 @@ class Graphics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawUIBounds(RenderPass* pass);
|
void DrawUIBounds(RenderPass* pass);
|
||||||
|
static void GetBaseVirtualRes(float* x, float* y);
|
||||||
|
|
||||||
// Enable progress bar drawing locally.
|
// Enable progress bar drawing locally.
|
||||||
void EnableProgressBar(bool fade_in);
|
void EnableProgressBar(bool fade_in);
|
||||||
|
|||||||
@ -178,7 +178,7 @@ auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* {
|
|||||||
millisecs_t t = g_core->GetAppTimeMillisecs() - start_time;
|
millisecs_t t = g_core->GetAppTimeMillisecs() - start_time;
|
||||||
if (t >= 1000) {
|
if (t >= 1000) {
|
||||||
if (g_buildconfig.debug_build()) {
|
if (g_buildconfig.debug_build()) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"GraphicsServer: timed out at " + std::to_string(t)
|
"GraphicsServer: timed out at " + std::to_string(t)
|
||||||
+ "ms waiting for logic thread to send us a FrameDef.");
|
+ "ms waiting for logic thread to send us a FrameDef.");
|
||||||
}
|
}
|
||||||
@ -266,7 +266,8 @@ void GraphicsServer::ReloadLostRenderer() {
|
|||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
|
|
||||||
if (!renderer_) {
|
if (!renderer_) {
|
||||||
Log(LogLevel::kError, "No renderer on GraphicsServer::ReloadLostRenderer.");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"No renderer on GraphicsServer::ReloadLostRenderer.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,11 +324,12 @@ void GraphicsServer::set_renderer(Renderer* renderer) {
|
|||||||
void GraphicsServer::LoadRenderer() {
|
void GraphicsServer::LoadRenderer() {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
if (!renderer_) {
|
if (!renderer_) {
|
||||||
Log(LogLevel::kError, "LoadRenderer() called with no renderer present.");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"LoadRenderer() called with no renderer present.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (renderer_loaded_) {
|
if (renderer_loaded_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"LoadRenderer() called with an already-loaded renderer present.");
|
"LoadRenderer() called with an already-loaded renderer present.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -369,11 +371,12 @@ void GraphicsServer::LoadRenderer() {
|
|||||||
void GraphicsServer::UnloadRenderer() {
|
void GraphicsServer::UnloadRenderer() {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
if (!renderer_) {
|
if (!renderer_) {
|
||||||
Log(LogLevel::kError, "UnloadRenderer() called with no renderer present.");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"UnloadRenderer() called with no renderer present.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!renderer_loaded_) {
|
if (!renderer_loaded_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"UnloadRenderer() called with an already unloaded renderer present.");
|
"UnloadRenderer() called with an already unloaded renderer present.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -532,7 +535,7 @@ void GraphicsServer::PushRemoveRenderHoldCall() {
|
|||||||
assert(render_hold_);
|
assert(render_hold_);
|
||||||
render_hold_--;
|
render_hold_--;
|
||||||
if (render_hold_ < 0) {
|
if (render_hold_ < 0) {
|
||||||
Log(LogLevel::kError, "RenderHold < 0");
|
Log(LogName::kBaGraphics, LogLevel::kError, "RenderHold < 0");
|
||||||
render_hold_ = 0;
|
render_hold_ = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -17,7 +17,8 @@ class MeshData {
|
|||||||
: type_(type), draw_type_(draw_type) {}
|
: type_(type), draw_type_(draw_type) {}
|
||||||
virtual ~MeshData() {
|
virtual ~MeshData() {
|
||||||
if (renderer_data_) {
|
if (renderer_data_) {
|
||||||
Log(LogLevel::kError, "MeshData going down with rendererData intact!");
|
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||||
|
"MeshData going down with rendererData intact!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::list<MeshData*>::iterator iterator_;
|
std::list<MeshData*>::iterator iterator_;
|
||||||
|
|||||||
@ -76,7 +76,7 @@ class MeshIndexedBase : public Mesh {
|
|||||||
// For use by subclasses in their IsValid() overrides
|
// For use by subclasses in their IsValid() overrides
|
||||||
auto IndexSizeIsValid(size_t data_size) const -> bool {
|
auto IndexSizeIsValid(size_t data_size) const -> bool {
|
||||||
if (index_data_size() == 2 && data_size > 65535) {
|
if (index_data_size() == 2 && data_size > 65535) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"Got mesh data with > 65535 elems and 16 bit indices: "
|
"Got mesh data with > 65535 elems and 16 bit indices: "
|
||||||
+ GetObjectDescription()
|
+ GetObjectDescription()
|
||||||
+ ". This case requires 32 bit indices.");
|
+ ". This case requires 32 bit indices.");
|
||||||
|
|||||||
@ -32,7 +32,7 @@ class MeshIndexedStaticDynamic : public MeshIndexedBase {
|
|||||||
|
|
||||||
// Static and dynamic data sizes should always match, right?
|
// Static and dynamic data sizes should always match, right?
|
||||||
if (static_data_->elements.size() != dynamic_data_->elements.size()) {
|
if (static_data_->elements.size() != dynamic_data_->elements.size()) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kError,
|
||||||
"Mesh static and dynamic data sizes do not match");
|
"Mesh static and dynamic data sizes do not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,8 @@ NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
|||||||
|| (border_bottom + border_top) > 1.0f)
|
|| (border_bottom + border_top) > 1.0f)
|
||||||
|| (border_left < 0.0f || border_right < 0.0f
|
|| (border_left < 0.0f || border_right < 0.0f
|
||||||
|| (border_left + border_right) > 1.0f)) {
|
|| (border_left + border_right) > 1.0f)) {
|
||||||
BA_LOG_ONCE(LogLevel::kWarning, "Invalid nine-patch values provided.");
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
|
"Invalid nine-patch values provided.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Statically allocate enough for a full 9 patches even though we may
|
// Statically allocate enough for a full 9 patches even though we may
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class RenderTarget : public Object {
|
|||||||
void DrawBegin(bool clear,
|
void DrawBegin(bool clear,
|
||||||
const Vector4f& clear_color = {0.0f, 0.0f, 0.0f, 1.0f}) {
|
const Vector4f& clear_color = {0.0f, 0.0f, 0.0f, 1.0f}) {
|
||||||
DrawBegin(clear, clear_color.x, clear_color.y, clear_color.z,
|
DrawBegin(clear, clear_color.x, clear_color.y, clear_color.z,
|
||||||
clear_color.w);
|
clear_color.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnScreenSizeChange();
|
void OnScreenSizeChange();
|
||||||
|
|||||||
@ -152,7 +152,7 @@ void ScreenMessages::DrawMiscOverlays(FrameDef* frame_def) {
|
|||||||
|
|
||||||
if (i->translation_dirty) {
|
if (i->translation_dirty) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kWarning,
|
LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"Found dirty translation on screenmessage draw pass 1; raw="
|
"Found dirty translation on screenmessage draw pass 1; raw="
|
||||||
+ i->s_raw);
|
+ i->s_raw);
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ void ScreenMessages::DrawMiscOverlays(FrameDef* frame_def) {
|
|||||||
}
|
}
|
||||||
if (i->translation_dirty) {
|
if (i->translation_dirty) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kWarning,
|
LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"Found dirty translation on screenmessage draw pass 2; raw="
|
"Found dirty translation on screenmessage draw pass 2; raw="
|
||||||
+ i->s_raw);
|
+ i->s_raw);
|
||||||
}
|
}
|
||||||
@ -495,7 +495,7 @@ void ScreenMessages::ClearScreenMessageTranslations() {
|
|||||||
auto ScreenMessages::ScreenMessageEntry::GetText() -> TextGroup& {
|
auto ScreenMessages::ScreenMessageEntry::GetText() -> TextGroup& {
|
||||||
if (translation_dirty) {
|
if (translation_dirty) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kWarning,
|
LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
"Found dirty translation on screenmessage GetText; raw=" + s_raw);
|
"Found dirty translation on screenmessage GetText; raw=" + s_raw);
|
||||||
}
|
}
|
||||||
if (!s_mesh_.Exists()) {
|
if (!s_mesh_.Exists()) {
|
||||||
|
|||||||
@ -349,7 +349,8 @@ TextGraphics::TextGraphics() {
|
|||||||
if (g.tex_max_x > 1.0f || g.tex_max_x < 0.0f || g.tex_min_x > 1.0
|
if (g.tex_max_x > 1.0f || g.tex_max_x < 0.0f || g.tex_min_x > 1.0
|
||||||
|| g.tex_min_x < 0.0f || g.tex_max_y > 1.0f || g.tex_max_y < 0.0
|
|| g.tex_min_x < 0.0f || g.tex_max_y > 1.0f || g.tex_max_y < 0.0
|
||||||
|| g.tex_min_y > 1.0f || g.tex_min_y < 0.0f) {
|
|| g.tex_min_y > 1.0f || g.tex_min_y < 0.0f) {
|
||||||
BA_LOG_ONCE(LogLevel::kWarning, "glyph bounds error");
|
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kWarning,
|
||||||
|
"glyph bounds error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1042,7 +1043,7 @@ void TextGraphics::GetOSTextSpanBoundsAndWidth(const std::string& s, Rect* r,
|
|||||||
g_core->platform->GetTextBoundsAndWidth(s, &entry->r, &entry->width);
|
g_core->platform->GetTextBoundsAndWidth(s, &entry->r, &entry->width);
|
||||||
} else {
|
} else {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaGraphics, LogLevel::kError,
|
||||||
"FIXME: GetOSTextSpanBoundsAndWidth unimplemented on this platform");
|
"FIXME: GetOSTextSpanBoundsAndWidth unimplemented on this platform");
|
||||||
r->l = 0.0f;
|
r->l = 0.0f;
|
||||||
r->r = 1.0f;
|
r->r = 1.0f;
|
||||||
|
|||||||
@ -289,7 +289,7 @@ auto JoystickInput::GetButtonName(int index) -> std::string {
|
|||||||
|
|
||||||
JoystickInput::~JoystickInput() {
|
JoystickInput::~JoystickInput() {
|
||||||
if (!g_base->InLogicThread()) {
|
if (!g_base->InLogicThread()) {
|
||||||
Log(LogLevel::kError, "Joystick dying in wrong thread.");
|
Log(LogName::kBaInput, LogLevel::kError, "Joystick dying in wrong thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill our child if need be.
|
// Kill our child if need be.
|
||||||
@ -311,7 +311,7 @@ JoystickInput::~JoystickInput() {
|
|||||||
[joystick] { SDL_JoystickClose(joystick); });
|
[joystick] { SDL_JoystickClose(joystick); });
|
||||||
sdl_joystick_ = nullptr;
|
sdl_joystick_ = nullptr;
|
||||||
#else
|
#else
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
"sdl_joystick_ set in non-sdl-joystick build destructor.");
|
"sdl_joystick_ set in non-sdl-joystick build destructor.");
|
||||||
#endif // BA_ENABLE_SDL_JOYSTICKS
|
#endif // BA_ENABLE_SDL_JOYSTICKS
|
||||||
}
|
}
|
||||||
@ -654,7 +654,7 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) {
|
|||||||
hat_held_ = true;
|
hat_held_ = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||||
"Invalid hat value: "
|
"Invalid hat value: "
|
||||||
+ std::to_string(static_cast<int>(e->jhat.value)));
|
+ std::to_string(static_cast<int>(e->jhat.value)));
|
||||||
break;
|
break;
|
||||||
@ -1231,7 +1231,7 @@ void JoystickInput::UpdateMapping() {
|
|||||||
auto* cl{g_base->HaveClassic() ? g_base->classic() : nullptr};
|
auto* cl{g_base->HaveClassic() ? g_base->classic() : nullptr};
|
||||||
|
|
||||||
if (!cl) {
|
if (!cl) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaInput, LogLevel::kWarning,
|
||||||
"Classic not present; can't config joystick mapping.");
|
"Classic not present; can't config joystick mapping.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -852,7 +852,7 @@ void TouchInput::UpdateMapping() {
|
|||||||
} else if (touch_movement_type == "joystick") {
|
} else if (touch_movement_type == "joystick") {
|
||||||
movement_control_type_ = TouchInput::MovementControlType::kJoystick;
|
movement_control_type_ = TouchInput::MovementControlType::kJoystick;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
"Invalid touch-movement-type: " + touch_movement_type);
|
"Invalid touch-movement-type: " + touch_movement_type);
|
||||||
movement_control_type_ = TouchInput::MovementControlType::kSwipe;
|
movement_control_type_ = TouchInput::MovementControlType::kSwipe;
|
||||||
}
|
}
|
||||||
@ -863,7 +863,8 @@ void TouchInput::UpdateMapping() {
|
|||||||
} else if (touch_action_type == "buttons") {
|
} else if (touch_action_type == "buttons") {
|
||||||
action_control_type_ = TouchInput::ActionControlType::kButtons;
|
action_control_type_ = TouchInput::ActionControlType::kButtons;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "Invalid touch-action-type: " + touch_action_type);
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
|
"Invalid touch-action-type: " + touch_action_type);
|
||||||
action_control_type_ = TouchInput::ActionControlType::kSwipe;
|
action_control_type_ = TouchInput::ActionControlType::kSwipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ void Input::PushCreateKeyboardInputDevices() {
|
|||||||
void Input::CreateKeyboardInputDevices_() {
|
void Input::CreateKeyboardInputDevices_() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (keyboard_input_ != nullptr || keyboard_input_2_ != nullptr) {
|
if (keyboard_input_ != nullptr || keyboard_input_2_ != nullptr) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
"CreateKeyboardInputDevices called with existing kbs.");
|
"CreateKeyboardInputDevices called with existing kbs.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ void Input::PushDestroyKeyboardInputDevices() {
|
|||||||
void Input::DestroyKeyboardInputDevices_() {
|
void Input::DestroyKeyboardInputDevices_() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (keyboard_input_ == nullptr || keyboard_input_2_ == nullptr) {
|
if (keyboard_input_ == nullptr || keyboard_input_2_ == nullptr) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
"DestroyKeyboardInputDevices called with null kb(s).");
|
"DestroyKeyboardInputDevices called with null kb(s).");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -558,7 +558,7 @@ void Input::StepDisplayTime() {
|
|||||||
// If input has been locked an excessively long amount of time, unlock it.
|
// If input has been locked an excessively long amount of time, unlock it.
|
||||||
if (input_lock_count_temp_) {
|
if (input_lock_count_temp_) {
|
||||||
if (real_time - last_input_temp_lock_time_ > 10000) {
|
if (real_time - last_input_temp_lock_time_ > 10000) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
"Input has been temp-locked for 10 seconds; unlocking.");
|
"Input has been temp-locked for 10 seconds; unlocking.");
|
||||||
input_lock_count_temp_ = 0;
|
input_lock_count_temp_ = 0;
|
||||||
PrintLockLabels_();
|
PrintLockLabels_();
|
||||||
@ -664,7 +664,7 @@ void Input::UnlockAllInput(bool permanent, const std::string& label) {
|
|||||||
input_lock_count_temp_--;
|
input_lock_count_temp_--;
|
||||||
input_unlock_temp_labels_.push_back(label);
|
input_unlock_temp_labels_.push_back(label);
|
||||||
if (input_lock_count_temp_ < 0) {
|
if (input_lock_count_temp_ < 0) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBaInput, LogLevel::kWarning,
|
||||||
"temp input unlock at time "
|
"temp input unlock at time "
|
||||||
+ std::to_string(g_core->GetAppTimeMillisecs())
|
+ std::to_string(g_core->GetAppTimeMillisecs())
|
||||||
+ " with no active lock: '" + label + "'");
|
+ " with no active lock: '" + label + "'");
|
||||||
@ -719,7 +719,7 @@ void Input::PrintLockLabels_() {
|
|||||||
s += "\n " + std::to_string(num++) + ": " + recent_input_locks_unlock;
|
s += "\n " + std::to_string(num++) + ": " + recent_input_locks_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(LogLevel::kError, s);
|
Log(LogName::kBaInput, LogLevel::kError, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::PushTextInputEvent(const std::string& text) {
|
void Input::PushTextInputEvent(const std::string& text) {
|
||||||
@ -757,7 +757,8 @@ void Input::PushTextInputEvent(const std::string& text) {
|
|||||||
// platforms) but make a stink if they sent us something that we can't
|
// platforms) but make a stink if they sent us something that we can't
|
||||||
// at least translate to unicode.
|
// at least translate to unicode.
|
||||||
if (!Utils::IsValidUTF8(text)) {
|
if (!Utils::IsValidUTF8(text)) {
|
||||||
Log(LogLevel::kWarning, "PushTextInputEvent passed invalid utf-8 text.");
|
Log(LogName::kBaInput, LogLevel::kWarning,
|
||||||
|
"PushTextInputEvent passed invalid utf-8 text.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,7 +845,8 @@ void Input::CaptureKeyboardInput(HandleKeyPressCall* press_call,
|
|||||||
HandleKeyReleaseCall* release_call) {
|
HandleKeyReleaseCall* release_call) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (keyboard_input_capture_press_ || keyboard_input_capture_release_) {
|
if (keyboard_input_capture_press_ || keyboard_input_capture_release_) {
|
||||||
Log(LogLevel::kError, "Setting key capture redundantly.");
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
|
"Setting key capture redundantly.");
|
||||||
}
|
}
|
||||||
keyboard_input_capture_press_ = press_call;
|
keyboard_input_capture_press_ = press_call;
|
||||||
keyboard_input_capture_release_ = release_call;
|
keyboard_input_capture_release_ = release_call;
|
||||||
@ -859,7 +861,8 @@ void Input::ReleaseKeyboardInput() {
|
|||||||
void Input::CaptureJoystickInput(HandleJoystickEventCall* call) {
|
void Input::CaptureJoystickInput(HandleJoystickEventCall* call) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (joystick_input_capture_) {
|
if (joystick_input_capture_) {
|
||||||
Log(LogLevel::kError, "Setting joystick capture redundantly.");
|
Log(LogName::kBaInput, LogLevel::kError,
|
||||||
|
"Setting joystick capture redundantly.");
|
||||||
}
|
}
|
||||||
joystick_input_capture_ = call;
|
joystick_input_capture_ = call;
|
||||||
}
|
}
|
||||||
@ -930,7 +933,7 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
|
|||||||
count++;
|
count++;
|
||||||
if (count > 10) {
|
if (count > 10) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kWarning,
|
LogName::kBaInput, LogLevel::kWarning,
|
||||||
"Input::HandleKeyPress_ seems to be getting passed repeat key"
|
"Input::HandleKeyPress_ seems to be getting passed repeat key"
|
||||||
" press events. Only initial press events should be passed.");
|
" press events. Only initial press events should be passed.");
|
||||||
}
|
}
|
||||||
@ -1442,7 +1445,7 @@ void Input::HandleTouchEvent_(const TouchEvent& e) {
|
|||||||
// overall multitouch gesture, it should always be winding up as our
|
// overall multitouch gesture, it should always be winding up as our
|
||||||
// single_touch_.
|
// single_touch_.
|
||||||
if (e.type == TouchEvent::Type::kDown && single_touch_ != nullptr) {
|
if (e.type == TouchEvent::Type::kDown && single_touch_ != nullptr) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||||
"Got touch labeled first but will not be our single.");
|
"Got touch labeled first but will not be our single.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1452,7 +1455,7 @@ void Input::HandleTouchEvent_(const TouchEvent& e) {
|
|||||||
if ((e.type == TouchEvent::Type::kUp
|
if ((e.type == TouchEvent::Type::kUp
|
||||||
|| e.type == TouchEvent::Type::kCanceled)
|
|| e.type == TouchEvent::Type::kCanceled)
|
||||||
&& single_touch_ != nullptr && single_touch_ != e.touch) {
|
&& single_touch_ != nullptr && single_touch_ != e.touch) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||||
"Last touch coming up is not single touch!");
|
"Last touch coming up is not single touch!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1567,7 +1570,7 @@ void Input::LsInputDevices() {
|
|||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(LogLevel::kInfo, out);
|
Log(LogName::kBaInput, LogLevel::kInfo, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Input::ShouldAllowInputInAttractMode_(InputDevice* device) const -> bool {
|
auto Input::ShouldAllowInputInAttractMode_(InputDevice* device) const -> bool {
|
||||||
|
|||||||
@ -73,7 +73,7 @@ void RemoteAppServer::HandleData(int socket, uint8_t* buffer, size_t amt,
|
|||||||
}
|
}
|
||||||
case BA_PACKET_REMOTE_ID_REQUEST: {
|
case BA_PACKET_REMOTE_ID_REQUEST: {
|
||||||
if (amt < 5 || amt > 127) {
|
if (amt < 5 || amt > 127) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||||
"Received invalid BA_PACKET_REMOTE_ID_REQUEST of length "
|
"Received invalid BA_PACKET_REMOTE_ID_REQUEST of length "
|
||||||
+ std::to_string(amt));
|
+ std::to_string(amt));
|
||||||
break;
|
break;
|
||||||
@ -214,7 +214,8 @@ void RemoteAppServer::HandleData(int socket, uint8_t* buffer, size_t amt,
|
|||||||
|
|
||||||
// Each state is 2 bytes. So make sure our length adds up.
|
// Each state is 2 bytes. So make sure our length adds up.
|
||||||
if (amt != 4 + state_count * 3) {
|
if (amt != 4 + state_count * 3) {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "Invalid state packet");
|
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||||
|
"Invalid state packet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RemoteAppClient* client = clients_ + joystick_id;
|
RemoteAppClient* client = clients_ + joystick_id;
|
||||||
|
|||||||
@ -384,7 +384,7 @@ void Logic::OnAppModeChanged() {
|
|||||||
// long sleep we're currently in the middle of.
|
// long sleep we're currently in the middle of.
|
||||||
if (g_core->HeadlessMode()) {
|
if (g_core->HeadlessMode()) {
|
||||||
if (debug_log_display_time_) {
|
if (debug_log_display_time_) {
|
||||||
Log(LogLevel::kDebug,
|
Log(LogName::kBa, LogLevel::kDebug,
|
||||||
"Resetting headless display step timer due to app-mode change.");
|
"Resetting headless display step timer due to app-mode change.");
|
||||||
}
|
}
|
||||||
assert(headless_display_time_step_timer_);
|
assert(headless_display_time_step_timer_);
|
||||||
@ -419,7 +419,7 @@ void Logic::UpdateDisplayTimeForHeadlessMode_() {
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
snprintf(buffer, sizeof(buffer), "stepping display-time at app-time %.4f",
|
snprintf(buffer, sizeof(buffer), "stepping display-time at app-time %.4f",
|
||||||
static_cast<double>(app_time_microsecs) / 1000000.0);
|
static_cast<double>(app_time_microsecs) / 1000000.0);
|
||||||
Log(LogLevel::kDebug, buffer);
|
Log(LogName::kBa, LogLevel::kDebug, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,7 +441,7 @@ void Logic::PostUpdateDisplayTimeForHeadlessMode_() {
|
|||||||
snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
"will try to sleep for %.4f at app-time %.4f (until %.4f)",
|
"will try to sleep for %.4f at app-time %.4f (until %.4f)",
|
||||||
sleepsecs, apptimesecs, apptimesecs + sleepsecs);
|
sleepsecs, apptimesecs, apptimesecs + sleepsecs);
|
||||||
Log(LogLevel::kDebug, buffer);
|
Log(LogName::kBa, LogLevel::kDebug, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sleep_microsecs = headless_display_step_microsecs;
|
auto sleep_microsecs = headless_display_step_microsecs;
|
||||||
@ -548,7 +548,7 @@ void Logic::UpdateDisplayTimeForFrameDraw_() {
|
|||||||
snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
"trailing_dist %.6f > trail_buffer %.6f; will offset %.6f).",
|
"trailing_dist %.6f > trail_buffer %.6f; will offset %.6f).",
|
||||||
trailing_dist, trail_buffer, offs);
|
trailing_dist, trail_buffer, offs);
|
||||||
Log(LogLevel::kDebug, buffer);
|
Log(LogName::kBa, LogLevel::kDebug, buffer);
|
||||||
}
|
}
|
||||||
display_time_increment_ = display_time_increment_ + offs;
|
display_time_increment_ = display_time_increment_ + offs;
|
||||||
}
|
}
|
||||||
@ -559,7 +559,7 @@ void Logic::UpdateDisplayTimeForFrameDraw_() {
|
|||||||
"final %.5f current(%s) %.5f sample %.5f chaos %.5f",
|
"final %.5f current(%s) %.5f sample %.5f chaos %.5f",
|
||||||
display_time_increment_, use_avg ? "avg" : "sample", used,
|
display_time_increment_, use_avg ? "avg" : "sample", used,
|
||||||
this_increment, chaos);
|
this_increment, chaos);
|
||||||
Log(LogLevel::kDebug, buffer);
|
Log(LogName::kBa, LogLevel::kDebug, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,7 +660,7 @@ void Logic::SetAppTimerLength(int timer_id, microsecs_t length) {
|
|||||||
if (t) {
|
if (t) {
|
||||||
t->SetLength(length);
|
t->SetLength(length);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Logic::SetAppTimerLength() called on nonexistent timer.");
|
"Logic::SetAppTimerLength() called on nonexistent timer.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -687,7 +687,7 @@ void Logic::SetDisplayTimerLength(int timer_id, microsecs_t length) {
|
|||||||
if (t) {
|
if (t) {
|
||||||
t->SetLength(length);
|
t->SetLength(length);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Logic::SetDisplayTimerLength() called on nonexistent timer.");
|
"Logic::SetDisplayTimerLength() called on nonexistent timer.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,8 +61,9 @@ void NetworkReader::OnAppUnsuspend() {
|
|||||||
void NetworkReader::PokeSelf_() {
|
void NetworkReader::PokeSelf_() {
|
||||||
int sd = socket(AF_INET, SOCK_DGRAM, 0);
|
int sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
Log(LogLevel::kError, "Unable to create sleep ping socket; errno "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Unable to create sleep ping socket; errno "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
} else {
|
} else {
|
||||||
struct sockaddr_in serv_addr{};
|
struct sockaddr_in serv_addr{};
|
||||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||||
@ -71,8 +72,9 @@ void NetworkReader::PokeSelf_() {
|
|||||||
serv_addr.sin_port = 0; // any
|
serv_addr.sin_port = 0; // any
|
||||||
int bresult = ::bind(sd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
int bresult = ::bind(sd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||||
if (bresult == 1) {
|
if (bresult == 1) {
|
||||||
Log(LogLevel::kError, "Unable to bind sleep socket: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Unable to bind sleep socket: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
} else {
|
} else {
|
||||||
struct sockaddr_in t_addr{};
|
struct sockaddr_in t_addr{};
|
||||||
memset(&t_addr, 0, sizeof(t_addr));
|
memset(&t_addr, 0, sizeof(t_addr));
|
||||||
@ -83,8 +85,9 @@ void NetworkReader::PokeSelf_() {
|
|||||||
ssize_t sresult =
|
ssize_t sresult =
|
||||||
sendto(sd, b, 1, 0, (struct sockaddr*)(&t_addr), sizeof(t_addr));
|
sendto(sd, b, 1, 0, (struct sockaddr*)(&t_addr), sizeof(t_addr));
|
||||||
if (sresult == -1) {
|
if (sresult == -1) {
|
||||||
Log(LogLevel::kError, "Error on sleep self-sendto: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Error on sleep self-sendto: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_core->platform->CloseSocket(sd);
|
g_core->platform->CloseSocket(sd);
|
||||||
@ -115,7 +118,7 @@ void NetworkReader::DoPoll_(bool* can_read_4, bool* can_read_6) {
|
|||||||
// Aint no thang.
|
// Aint no thang.
|
||||||
} else {
|
} else {
|
||||||
// Let's complain for anything else though.
|
// Let's complain for anything else though.
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Error on select: " + g_core->platform->GetSocketErrorString());
|
"Error on select: " + g_core->platform->GetSocketErrorString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -123,7 +126,8 @@ void NetworkReader::DoPoll_(bool* can_read_4, bool* can_read_6) {
|
|||||||
*can_read_6 = index_6 != -1 && fds[index_6].revents & POLLIN;
|
*can_read_6 = index_6 != -1 && fds[index_6].revents & POLLIN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BA_LOG_ONCE(LogLevel::kError, "DoPoll called with neither sd4 or sd6 set.");
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"DoPoll called with neither sd4 or sd6 set.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +171,7 @@ void NetworkReader::DoSelect_(bool* can_read_4, bool* can_read_6) {
|
|||||||
// Aint no thang.
|
// Aint no thang.
|
||||||
} else {
|
} else {
|
||||||
// Let's complain for anything else though.
|
// Let's complain for anything else though.
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Error on select: " + g_core->platform->GetSocketErrorString());
|
"Error on select: " + g_core->platform->GetSocketErrorString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -235,7 +239,7 @@ auto NetworkReader::RunThread_() -> int {
|
|||||||
recvfrom(sd, buffer, sizeof(buffer), 0,
|
recvfrom(sd, buffer, sizeof(buffer), 0,
|
||||||
reinterpret_cast<sockaddr*>(&from), &from_size);
|
reinterpret_cast<sockaddr*>(&from), &from_size);
|
||||||
if (rresult == 0) {
|
if (rresult == 0) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"NetworkReader Recv got length 0; this shouldn't "
|
"NetworkReader Recv got length 0; this shouldn't "
|
||||||
"happen");
|
"happen");
|
||||||
} else if (rresult == -1) {
|
} else if (rresult == -1) {
|
||||||
@ -384,7 +388,7 @@ void NetworkReader::PushIncomingUDPPacketCall_(const std::vector<uint8_t>& data,
|
|||||||
// these are unreliable messages so its ok to just drop them.
|
// these are unreliable messages so its ok to just drop them.
|
||||||
if (!g_base->logic->event_loop()->CheckPushSafety()) {
|
if (!g_base->logic->event_loop()->CheckPushSafety()) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Ignoring excessive udp-connection input packets; (could this be a "
|
"Ignoring excessive udp-connection input packets; (could this be a "
|
||||||
"flood attack?).");
|
"flood attack?).");
|
||||||
return;
|
return;
|
||||||
@ -413,8 +417,9 @@ void NetworkReader::OpenSockets_() {
|
|||||||
|
|
||||||
sd4_ = socket(AF_INET, SOCK_DGRAM, 0);
|
sd4_ = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (sd4_ < 0) {
|
if (sd4_ < 0) {
|
||||||
Log(LogLevel::kError, "Unable to open host socket; errno "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Unable to open host socket; errno "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
} else {
|
} else {
|
||||||
g_core->platform->SetSocketNonBlocking(sd4_);
|
g_core->platform->SetSocketNonBlocking(sd4_);
|
||||||
|
|
||||||
@ -465,8 +470,9 @@ void NetworkReader::OpenSockets_() {
|
|||||||
// available everywhere (win XP, etc) so let's do this for now.
|
// available everywhere (win XP, etc) so let's do this for now.
|
||||||
sd6_ = socket(AF_INET6, SOCK_DGRAM, 0);
|
sd6_ = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
if (sd6_ < 0) {
|
if (sd6_ < 0) {
|
||||||
Log(LogLevel::kError, "Unable to open ipv6 socket: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Unable to open ipv6 socket: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
} else {
|
} else {
|
||||||
// Since we're explicitly creating both a v4 and v6 socket, tell the v6
|
// Since we're explicitly creating both a v4 and v6 socket, tell the v6
|
||||||
// to *not* do both itself (not sure if this is necessary; on mac it
|
// to *not* do both itself (not sure if this is necessary; on mac it
|
||||||
@ -475,7 +481,8 @@ void NetworkReader::OpenSockets_() {
|
|||||||
if (setsockopt(sd6_, IPPROTO_IPV6, IPV6_V6ONLY,
|
if (setsockopt(sd6_, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||||
reinterpret_cast<char*>(&on), sizeof(on))
|
reinterpret_cast<char*>(&on), sizeof(on))
|
||||||
== -1) {
|
== -1) {
|
||||||
Log(LogLevel::kError, "Error setting socket as ipv6-only");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Error setting socket as ipv6-only");
|
||||||
}
|
}
|
||||||
|
|
||||||
g_core->platform->SetSocketNonBlocking(sd6_);
|
g_core->platform->SetSocketNonBlocking(sd6_);
|
||||||
@ -522,9 +529,9 @@ void NetworkReader::OpenSockets_() {
|
|||||||
+ std::to_string(initial_requested_port)
|
+ std::to_string(initial_requested_port)
|
||||||
+ "; some network functionality may fail.",
|
+ "; some network functionality may fail.",
|
||||||
{1, 0.5f, 0});
|
{1, 0.5f, 0});
|
||||||
Log(LogLevel::kWarning, "Unable to bind udp port "
|
Log(LogName::kBaNetworking, LogLevel::kWarning,
|
||||||
+ std::to_string(initial_requested_port)
|
"Unable to bind udp port " + std::to_string(initial_requested_port)
|
||||||
+ "; some network functionality may fail.");
|
+ "; some network functionality may fail.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ void NetworkWriter::PushSendToCall(const std::vector<uint8_t>& msg,
|
|||||||
// Avoid buffer-full errors if something is causing us to write too often;
|
// Avoid buffer-full errors if something is causing us to write too often;
|
||||||
// these are unreliable messages so its ok to just drop them.
|
// these are unreliable messages so its ok to just drop them.
|
||||||
if (!event_loop()->CheckPushSafety()) {
|
if (!event_loop()->CheckPushSafety()) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Excessive send-to calls in net-write-module.");
|
"Excessive send-to calls in net-write-module.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -116,7 +116,7 @@ void BasePlatformApple::LoginAdapterGetSignInToken(
|
|||||||
if (login_type == "game_center") {
|
if (login_type == "game_center") {
|
||||||
BallisticaKit::GameCenterContext::getSignInToken(attempt_id);
|
BallisticaKit::GameCenterContext::getSignInToken(attempt_id);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Got unexpected get-sign-in-token login-type: " + login_type);
|
"Got unexpected get-sign-in-token login-type: " + login_type);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -130,7 +130,7 @@ void BasePlatformApple::LoginAdapterBackEndActiveChange(
|
|||||||
if (login_type == "game_center") {
|
if (login_type == "game_center") {
|
||||||
BallisticaKit::GameCenterContext::backEndActiveChange(active);
|
BallisticaKit::GameCenterContext::backEndActiveChange(active);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Got unexpected back-end-active-change login-type: " + login_type);
|
"Got unexpected back-end-active-change login-type: " + login_type);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -104,12 +104,12 @@ void BasePlatform::DoPurchase(const std::string& item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BasePlatform::RestorePurchases() {
|
void BasePlatform::RestorePurchases() {
|
||||||
Log(LogLevel::kError, "RestorePurchases() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "RestorePurchases() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasePlatform::PurchaseAck(const std::string& purchase,
|
void BasePlatform::PurchaseAck(const std::string& purchase,
|
||||||
const std::string& order_id) {
|
const std::string& order_id) {
|
||||||
Log(LogLevel::kError, "PurchaseAck() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "PurchaseAck() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasePlatform::OpenURL(const std::string& url) {
|
void BasePlatform::OpenURL(const std::string& url) {
|
||||||
@ -134,7 +134,7 @@ void BasePlatform::OverlayWebBrowserOpenURL(const std::string& url) {
|
|||||||
|
|
||||||
std::scoped_lock lock(web_overlay_mutex_);
|
std::scoped_lock lock(web_overlay_mutex_);
|
||||||
if (web_overlay_open_) {
|
if (web_overlay_open_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"OverlayWebBrowserOnClose called with already existing overlay.");
|
"OverlayWebBrowserOnClose called with already existing overlay.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ auto BasePlatform::OverlayWebBrowserIsOpen() -> bool {
|
|||||||
void BasePlatform::OverlayWebBrowserOnClose() {
|
void BasePlatform::OverlayWebBrowserOnClose() {
|
||||||
std::scoped_lock lock(web_overlay_mutex_);
|
std::scoped_lock lock(web_overlay_mutex_);
|
||||||
if (!web_overlay_open_) {
|
if (!web_overlay_open_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"OverlayWebBrowserOnClose called with no known overlay.");
|
"OverlayWebBrowserOnClose called with no known overlay.");
|
||||||
}
|
}
|
||||||
web_overlay_open_ = false;
|
web_overlay_open_ = false;
|
||||||
@ -174,12 +174,13 @@ void BasePlatform::OverlayWebBrowserClose() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BasePlatform::DoOverlayWebBrowserOpenURL(const std::string& url) {
|
void BasePlatform::DoOverlayWebBrowserOpenURL(const std::string& url) {
|
||||||
Log(LogLevel::kError, "DoOpenURLInOverlayBrowser unimplemented");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"DoOpenURLInOverlayBrowser unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasePlatform::DoOverlayWebBrowserClose() {
|
void BasePlatform::DoOverlayWebBrowserClose() {
|
||||||
// As a default, use Python's webbrowser module functionality.
|
// As a default, use Python's webbrowser module functionality.
|
||||||
Log(LogLevel::kError, "DoOverlayWebBrowserClose unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "DoOverlayWebBrowserClose unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !BA_OSTYPE_WINDOWS
|
#if !BA_OSTYPE_WINDOWS
|
||||||
@ -188,7 +189,7 @@ static void HandleSIGINT(int s) {
|
|||||||
g_base->logic->event_loop()->PushCall(
|
g_base->logic->event_loop()->PushCall(
|
||||||
[] { g_base->logic->HandleInterruptSignal(); });
|
[] { g_base->logic->HandleInterruptSignal(); });
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"SigInt handler called before g_base->logic->event_loop exists.");
|
"SigInt handler called before g_base->logic->event_loop exists.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +198,7 @@ static void HandleSIGTERM(int s) {
|
|||||||
g_base->logic->event_loop()->PushCall(
|
g_base->logic->event_loop()->PushCall(
|
||||||
[] { g_base->logic->HandleTerminateSignal(); });
|
[] { g_base->logic->HandleTerminateSignal(); });
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"SigInt handler called before g_base->logic->event_loop exists.");
|
"SigInt handler called before g_base->logic->event_loop exists.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,17 +277,18 @@ void BasePlatform::StringEditorCancel() {
|
|||||||
void BasePlatform::DoInvokeStringEditor(const std::string& title,
|
void BasePlatform::DoInvokeStringEditor(const std::string& title,
|
||||||
const std::string& value,
|
const std::string& value,
|
||||||
std::optional<int> max_chars) {
|
std::optional<int> max_chars) {
|
||||||
Log(LogLevel::kError, "FIXME: DoInvokeStringEditor() unimplemented");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"FIXME: DoInvokeStringEditor() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BasePlatform::SupportsOpenDirExternally() -> bool { return false; }
|
auto BasePlatform::SupportsOpenDirExternally() -> bool { return false; }
|
||||||
|
|
||||||
void BasePlatform::OpenDirExternally(const std::string& path) {
|
void BasePlatform::OpenDirExternally(const std::string& path) {
|
||||||
Log(LogLevel::kError, "OpenDirExternally() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "OpenDirExternally() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasePlatform::OpenFileExternally(const std::string& path) {
|
void BasePlatform::OpenFileExternally(const std::string& path) {
|
||||||
Log(LogLevel::kError, "OpenFileExternally() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "OpenFileExternally() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BasePlatform::SafeStdinFGetS(char* s, int n, FILE* iop) -> char* {
|
auto BasePlatform::SafeStdinFGetS(char* s, int n, FILE* iop) -> char* {
|
||||||
|
|||||||
@ -23,8 +23,9 @@ void BasePlatformLinux::OpenDirExternally(const std::string& path) {
|
|||||||
std::string cmd = std::string("xdg-open \"") + path + "\"";
|
std::string cmd = std::string("xdg-open \"") + path + "\"";
|
||||||
int result = system(cmd.c_str());
|
int result = system(cmd.c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
Log(LogLevel::kError, "Got return value " + std::to_string(result)
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ " on xdg-open cmd '" + cmd + "'");
|
"Got return value " + std::to_string(result) + " on xdg-open cmd '"
|
||||||
|
+ cmd + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +33,9 @@ void BasePlatformLinux::OpenFileExternally(const std::string& path) {
|
|||||||
std::string cmd = std::string("xdg-open \"") + path + "\"";
|
std::string cmd = std::string("xdg-open \"") + path + "\"";
|
||||||
int result = system(cmd.c_str());
|
int result = system(cmd.c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
Log(LogLevel::kError, "Got return value " + std::to_string(result)
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ " on xdg-open cmd '" + cmd + "'");
|
"Got return value " + std::to_string(result) + " on xdg-open cmd '"
|
||||||
|
+ cmd + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -348,7 +348,7 @@ static const char* GetScancodeName(SDL_Scancode scancode) {
|
|||||||
const char* name;
|
const char* name;
|
||||||
if (static_cast<int>(scancode) < SDL_SCANCODE_UNKNOWN
|
if (static_cast<int>(scancode) < SDL_SCANCODE_UNKNOWN
|
||||||
|| scancode >= SDL_NUM_SCANCODES) {
|
|| scancode >= SDL_NUM_SCANCODES) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||||
"GetScancodeName passed invalid scancode "
|
"GetScancodeName passed invalid scancode "
|
||||||
+ std::to_string(static_cast<int>(scancode)));
|
+ std::to_string(static_cast<int>(scancode)));
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@ -36,7 +36,7 @@ void BasePlatformWindows::DoOpenURL(const std::string& url) {
|
|||||||
|
|
||||||
// This should return > 32 on success.
|
// This should return > 32 on success.
|
||||||
if (r <= 32) {
|
if (r <= 32) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Error " + std::to_string(r) + " opening URL '" + url + "'");
|
"Error " + std::to_string(r) + " opening URL '" + url + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +49,8 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
|
|||||||
g_base->logic->event_loop()->PushCall(
|
g_base->logic->event_loop()->PushCall(
|
||||||
[] { g_base->logic->HandleInterruptSignal(); });
|
[] { g_base->logic->HandleInterruptSignal(); });
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "SigInt handler called before g_logic exists.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"SigInt handler called before g_logic exists.");
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
|
|||||||
void BasePlatformWindows::SetupInterruptHandling() {
|
void BasePlatformWindows::SetupInterruptHandling() {
|
||||||
// Set up Ctrl-C handling.
|
// Set up Ctrl-C handling.
|
||||||
if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
|
if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
|
||||||
Log(LogLevel::kError, "Error on SetConsoleCtrlHandler()");
|
Log(LogName::kBa, LogLevel::kError, "Error on SetConsoleCtrlHandler()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,8 +74,9 @@ void BasePlatformWindows::OpenDirExternally(const std::string& path) {
|
|||||||
core::CorePlatformWindows::UTF8Decode(path).c_str(), nullptr,
|
core::CorePlatformWindows::UTF8Decode(path).c_str(), nullptr,
|
||||||
SW_SHOWNORMAL));
|
SW_SHOWNORMAL));
|
||||||
if (r <= 32) {
|
if (r <= 32) {
|
||||||
Log(LogLevel::kError, "Error " + std::to_string(r)
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ " on open_dir_externally for '" + path + "'");
|
"Error " + std::to_string(r) + " on open_dir_externally for '" + path
|
||||||
|
+ "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,8 +86,9 @@ void BasePlatformWindows::OpenFileExternally(const std::string& path) {
|
|||||||
core::CorePlatformWindows::UTF8Decode(path).c_str(), nullptr,
|
core::CorePlatformWindows::UTF8Decode(path).c_str(), nullptr,
|
||||||
SW_SHOWNORMAL));
|
SW_SHOWNORMAL));
|
||||||
if (r <= 32) {
|
if (r <= 32) {
|
||||||
Log(LogLevel::kError, "Error " + std::to_string(r)
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ " on open_file_externally for '" + path + "'");
|
"Error " + std::to_string(r) + " on open_file_externally for '" + path
|
||||||
|
+ "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -106,27 +106,8 @@ void BasePython::SoftImportClassic() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// void BasePython::SoftImportUIV1() {
|
void BasePython::SetConfig(PyObject* config) {
|
||||||
// // To keep our init order clean, we want to root out any attempted uses
|
objs_.Store(ObjID::kConfig, config);
|
||||||
// // of this before _babase/babase has been fully imported.
|
|
||||||
// assert(g_base);
|
|
||||||
// assert(g_base->IsBaseCompletelyImported());
|
|
||||||
|
|
||||||
// auto gil{Python::ScopedInterpreterLock()};
|
|
||||||
// auto result = PythonRef::StolenSoft(PyImport_ImportModule("_bauiv1"));
|
|
||||||
// if (!result.Exists()) {
|
|
||||||
// // Ignore any errors here for now. All that will matter is whether plus
|
|
||||||
// // gave us its interface.
|
|
||||||
// PyErr_Clear();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void BasePython::ReadConfig() {
|
|
||||||
auto gil{Python::ScopedInterpreterLock()};
|
|
||||||
// Read the config file and store the config dict for easy access.
|
|
||||||
objs().Get(ObjID::kAppReadConfigCall).Call();
|
|
||||||
objs_.Store(ObjID::kConfig, *objs().Get(ObjID::kApp).GetAttr("config"));
|
|
||||||
assert(PyDict_Check(*objs().Get(ObjID::kConfig)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasePython::Reset() {
|
void BasePython::Reset() {
|
||||||
@ -360,7 +341,7 @@ auto BasePython::GetRawConfigValue(const char* name, float default_value)
|
|||||||
try {
|
try {
|
||||||
return Python::GetPyFloat(value);
|
return Python::GetPyFloat(value);
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"expected a float for config value '" + std::string(name) + "'");
|
"expected a float for config value '" + std::string(name) + "'");
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
@ -382,7 +363,7 @@ auto BasePython::GetRawConfigValue(const char* name,
|
|||||||
}
|
}
|
||||||
return Python::GetPyFloat(value);
|
return Python::GetPyFloat(value);
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"expected a float for config value '" + std::string(name) + "'");
|
"expected a float for config value '" + std::string(name) + "'");
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
@ -399,7 +380,7 @@ auto BasePython::GetRawConfigValue(const char* name, int default_value) -> int {
|
|||||||
try {
|
try {
|
||||||
return static_cast_check_fit<int>(Python::GetPyInt64(value));
|
return static_cast_check_fit<int>(Python::GetPyInt64(value));
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Expected an int value for config value '" + std::string(name) + "'.");
|
"Expected an int value for config value '" + std::string(name) + "'.");
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
@ -417,7 +398,7 @@ auto BasePython::GetRawConfigValue(const char* name, bool default_value)
|
|||||||
try {
|
try {
|
||||||
return Python::GetPyBool(value);
|
return Python::GetPyBool(value);
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Expected a bool value for config value '" + std::string(name) + "'.");
|
"Expected a bool value for config value '" + std::string(name) + "'.");
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
@ -525,7 +506,7 @@ auto BasePython::GetResource(const char* key, const char* fallback_resource,
|
|||||||
try {
|
try {
|
||||||
return g_base->python->GetPyLString(results.Get());
|
return g_base->python->GetPyLString(results.Get());
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"GetResource failed for '" + std::string(key) + "'");
|
"GetResource failed for '" + std::string(key) + "'");
|
||||||
|
|
||||||
// Hmm; I guess let's just return the key to help identify/fix the
|
// Hmm; I guess let's just return the key to help identify/fix the
|
||||||
@ -533,7 +514,8 @@ auto BasePython::GetResource(const char* key, const char* fallback_resource,
|
|||||||
return std::string("<res-err: ") + key + ">";
|
return std::string("<res-err: ") + key + ">";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "GetResource failed for '" + std::string(key) + "'");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"GetResource failed for '" + std::string(key) + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hmm; I guess let's just return the key to help identify/fix the issue?..
|
// Hmm; I guess let's just return the key to help identify/fix the issue?..
|
||||||
@ -553,12 +535,12 @@ auto BasePython::GetTranslation(const char* category, const char* s)
|
|||||||
try {
|
try {
|
||||||
return g_base->python->GetPyLString(results.Get());
|
return g_base->python->GetPyLString(results.Get());
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"GetTranslation failed for '" + std::string(category) + "'");
|
"GetTranslation failed for '" + std::string(category) + "'");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"GetTranslation failed for category '" + std::string(category) + "'");
|
"GetTranslation failed for category '" + std::string(category) + "'");
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@ -574,7 +556,7 @@ void BasePython::RunDeepLink(const std::string& url) {
|
|||||||
.Get(base::BasePython::ObjID::kAppHandleDeepLinkCall)
|
.Get(base::BasePython::ObjID::kAppHandleDeepLinkCall)
|
||||||
.Call(args);
|
.Call(args);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "Error on deep-link call");
|
Log(LogName::kBa, LogLevel::kError, "Error on deep-link call");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +577,8 @@ auto BasePython::CanPyStringEditAdapterBeReplaced(PyObject* o) -> bool {
|
|||||||
.Get(BasePython::ObjID::kStringEditAdapterCanBeReplacedCall)
|
.Get(BasePython::ObjID::kStringEditAdapterCanBeReplacedCall)
|
||||||
.Call(args);
|
.Call(args);
|
||||||
if (!result.Exists()) {
|
if (!result.Exists()) {
|
||||||
Log(LogLevel::kError, "Error getting StringEdit valid state.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"Error getting StringEdit valid state.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result.Get() == Py_True) {
|
if (result.Get() == Py_True) {
|
||||||
@ -604,7 +587,8 @@ auto BasePython::CanPyStringEditAdapterBeReplaced(PyObject* o) -> bool {
|
|||||||
if (result.Get() == Py_False) {
|
if (result.Get() == Py_False) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log(LogLevel::kError, "Got unexpected value for StringEdit valid.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"Got unexpected value for StringEdit valid.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,6 @@ class BasePython {
|
|||||||
kEmptyCall,
|
kEmptyCall,
|
||||||
kPrintTraceCall,
|
kPrintTraceCall,
|
||||||
kToggleFullscreenCall,
|
kToggleFullscreenCall,
|
||||||
kAppReadConfigCall,
|
|
||||||
kUIRemotePressCall,
|
kUIRemotePressCall,
|
||||||
kRemoveInGameAdsMessageCall,
|
kRemoveInGameAdsMessageCall,
|
||||||
kAppOnNativeStartCall,
|
kAppOnNativeStartCall,
|
||||||
@ -124,7 +123,8 @@ class BasePython {
|
|||||||
void AddPythonClasses(PyObject* module);
|
void AddPythonClasses(PyObject* module);
|
||||||
void ImportPythonObjs();
|
void ImportPythonObjs();
|
||||||
void ImportPythonAppObjs();
|
void ImportPythonAppObjs();
|
||||||
void ReadConfig();
|
void SetConfig(PyObject* config);
|
||||||
|
// void ReadConfig();
|
||||||
|
|
||||||
const auto& objs() { return objs_; }
|
const auto& objs() { return objs_; }
|
||||||
|
|
||||||
|
|||||||
@ -275,7 +275,7 @@ static auto PyPushCall(PyObject* self, PyObject* args, PyObject* keywds)
|
|||||||
// Warn the user not to use this from the logic thread since it doesnt
|
// Warn the user not to use this from the logic thread since it doesnt
|
||||||
// save/restore context.
|
// save/restore context.
|
||||||
if (!suppress_warning && g_base->InLogicThread()) {
|
if (!suppress_warning && g_base->InLogicThread()) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
"babase.pushcall() called from the logic thread with "
|
"babase.pushcall() called from the logic thread with "
|
||||||
"from_other_thread set to true (call "
|
"from_other_thread set to true (call "
|
||||||
+ Python::ObjToString(call_obj) + " at "
|
+ Python::ObjToString(call_obj) + " at "
|
||||||
@ -802,13 +802,15 @@ static PyMethodDef PyEnvDef = {
|
|||||||
static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds)
|
static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds)
|
||||||
-> PyObject* {
|
-> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
static const char* kwlist[] = {"name", "level", "message", nullptr};
|
static const char* kwlist[] = {"name", "level", "timestamp", "message",
|
||||||
|
nullptr};
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* levelstr;
|
const char* levelstr;
|
||||||
const char* message;
|
const char* message;
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss",
|
double timestamp;
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ssds",
|
||||||
const_cast<char**>(kwlist), &name, &levelstr,
|
const_cast<char**>(kwlist), &name, &levelstr,
|
||||||
&message)) {
|
×tamp, &message)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,7 +831,7 @@ static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds)
|
|||||||
fprintf(stderr, "Invalid log level to emit_log(): %s\n", levelstr);
|
fprintf(stderr, "Invalid log level to emit_log(): %s\n", levelstr);
|
||||||
level = LogLevel::kInfo;
|
level = LogLevel::kInfo;
|
||||||
}
|
}
|
||||||
Logging::EmitLog(name, level, message);
|
Logging::EmitLog(name, level, timestamp, message);
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
@ -840,7 +842,8 @@ static PyMethodDef PyEmitLogDef = {
|
|||||||
(PyCFunction)PyEmitLog, // method
|
(PyCFunction)PyEmitLog, // method
|
||||||
METH_VARARGS | METH_KEYWORDS, // flags
|
METH_VARARGS | METH_KEYWORDS, // flags
|
||||||
|
|
||||||
"emit_log(name: str, level: str, message: str) -> None\n"
|
"emit_log(name: str, level: str, timestamp: float, message: str)"
|
||||||
|
" -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)\n"
|
"(internal)\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|||||||
@ -190,7 +190,7 @@ static auto PyScreenMessage(PyObject* self, PyObject* args, PyObject* keywds)
|
|||||||
color = BasePython::GetPyVector3f(color_obj);
|
color = BasePython::GetPyVector3f(color_obj);
|
||||||
}
|
}
|
||||||
if (log) {
|
if (log) {
|
||||||
Log(LogLevel::kInfo, message_str);
|
Log(LogName::kBa, LogLevel::kInfo, message_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This version simply displays it locally.
|
// This version simply displays it locally.
|
||||||
|
|||||||
@ -110,7 +110,7 @@ static auto PySetUIScale(PyObject* self, PyObject* args, PyObject* keywds)
|
|||||||
const char* scalestr;
|
const char* scalestr;
|
||||||
|
|
||||||
static const char* kwlist[] = {"scale", nullptr};
|
static const char* kwlist[] = {"scale", nullptr};
|
||||||
PyObject* input_device_id_obj = Py_None;
|
// PyObject* input_device_id_obj = Py_None;
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
|
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
|
||||||
const_cast<char**>(kwlist), &scalestr)) {
|
const_cast<char**>(kwlist), &scalestr)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -328,7 +328,8 @@ static auto PySetUpSigInt(PyObject* self) -> PyObject* {
|
|||||||
if (g_base) {
|
if (g_base) {
|
||||||
g_base->platform->SetupInterruptHandling();
|
g_base->platform->SetupInterruptHandling();
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "setup_sigint called before g_base exists.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"setup_sigint called before g_base exists.");
|
||||||
}
|
}
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
@ -1578,13 +1579,14 @@ static auto PyDevConsoleAddButton(PyObject* self, PyObject* args) -> PyObject* {
|
|||||||
float label_scale;
|
float label_scale;
|
||||||
float corner_radius;
|
float corner_radius;
|
||||||
const char* style;
|
const char* style;
|
||||||
if (!PyArg_ParseTuple(args, "sffffOsffs", &label, &x, &y, &width, &height,
|
int disabled;
|
||||||
&call, &h_anchor, &label_scale, &corner_radius,
|
if (!PyArg_ParseTuple(args, "sffffOsffsp", &label, &x, &y, &width, &height,
|
||||||
&style)) {
|
&call, &h_anchor, &label_scale, &corner_radius, &style,
|
||||||
|
&disabled)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
dev_console->AddButton(label, x, y, width, height, call, h_anchor,
|
dev_console->AddButton(label, x, y, width, height, call, h_anchor,
|
||||||
label_scale, corner_radius, style);
|
label_scale, corner_radius, style, disabled);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
@ -1605,6 +1607,7 @@ static PyMethodDef PyDevConsoleAddButtonDef = {
|
|||||||
" label_scale: float,\n"
|
" label_scale: float,\n"
|
||||||
" corner_radius: float,\n"
|
" corner_radius: float,\n"
|
||||||
" style: str,\n"
|
" style: str,\n"
|
||||||
|
" disabled: bool,\n"
|
||||||
") -> None\n"
|
") -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)",
|
"(internal)",
|
||||||
@ -1970,6 +1973,26 @@ static PyMethodDef PyGetDrawUIBoundsDef = {
|
|||||||
"(internal)",
|
"(internal)",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -------------------------- get_initial_app_config ---------------------------
|
||||||
|
|
||||||
|
static auto PyGetInitialAppConfig(PyObject* self) -> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
|
||||||
|
return g_core->HandOverInitialAppConfig();
|
||||||
|
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef PyGetInitialAppConfigDef = {
|
||||||
|
"get_initial_app_config", // name
|
||||||
|
(PyCFunction)PyGetInitialAppConfig, // method
|
||||||
|
METH_NOARGS, // flags
|
||||||
|
|
||||||
|
"get_initial_app_config() -> dict\n"
|
||||||
|
"\n"
|
||||||
|
"(internal)",
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------- set_draw_ui_bounds -----------------------------
|
// --------------------------- set_draw_ui_bounds -----------------------------
|
||||||
|
|
||||||
static auto PySetDrawUIBounds(PyObject* self, PyObject* args, PyObject* keywds)
|
static auto PySetDrawUIBounds(PyObject* self, PyObject* args, PyObject* keywds)
|
||||||
@ -2020,6 +2043,53 @@ static PyMethodDef PyPushBackPressDef = {
|
|||||||
"(internal)",
|
"(internal)",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ---------------------------- set_app_config ---------------------------------
|
||||||
|
|
||||||
|
static auto PySetAppConfig(PyObject* self, PyObject* args) -> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
PyObject* config_obj;
|
||||||
|
if (!PyArg_ParseTuple(args, "O", &config_obj)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
BA_PRECONDITION(PyDict_Check(config_obj));
|
||||||
|
g_base->python->SetConfig(config_obj);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef PySetAppConfigDef = {
|
||||||
|
"set_app_config", // name
|
||||||
|
PySetAppConfig, // method
|
||||||
|
METH_VARARGS, // flags
|
||||||
|
|
||||||
|
"set_app_config(config: dict) -> None\n"
|
||||||
|
"\n"
|
||||||
|
"(internal)",
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------- update_internal_logger_levels -------------------------
|
||||||
|
|
||||||
|
static auto PyUpdateInternalLoggerLevels(PyObject* self) -> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
g_core->UpdateInternalLoggerLevels();
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef PyUpdateInternalLoggerLevelsDef = {
|
||||||
|
"update_internal_logger_levels", // name
|
||||||
|
(PyCFunction)PyUpdateInternalLoggerLevels, // method
|
||||||
|
METH_NOARGS, // flags
|
||||||
|
|
||||||
|
"update_internal_logger_levels() -> None\n"
|
||||||
|
"\n"
|
||||||
|
"Update the native layer to re-cache Python logger levels.\n"
|
||||||
|
"\n"
|
||||||
|
"The native layer caches logger levels so it can efficiently\n"
|
||||||
|
"avoid making Python log calls for disabled logger levels. If any\n"
|
||||||
|
"logger levels are changed at runtime, call this method after to\n"
|
||||||
|
"instruct the native layer to regenerate its cache so the change\n"
|
||||||
|
"is properly reflected in logs originating from the native layer."};
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
|
auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
|
||||||
@ -2095,6 +2165,9 @@ auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
|
|||||||
PyPushBackPressDef,
|
PyPushBackPressDef,
|
||||||
PyGetDrawUIBoundsDef,
|
PyGetDrawUIBoundsDef,
|
||||||
PySetDrawUIBoundsDef,
|
PySetDrawUIBoundsDef,
|
||||||
|
PyGetInitialAppConfigDef,
|
||||||
|
PySetAppConfigDef,
|
||||||
|
PyUpdateInternalLoggerLevelsDef,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,12 +24,14 @@
|
|||||||
#include "ballistica/base/ui/ui.h"
|
#include "ballistica/base/ui/ui.h"
|
||||||
#include "ballistica/shared/foundation/event_loop.h"
|
#include "ballistica/shared/foundation/event_loop.h"
|
||||||
#include "ballistica/shared/generic/utils.h"
|
#include "ballistica/shared/generic/utils.h"
|
||||||
|
#include "ballistica/shared/math/vector4f.h"
|
||||||
#include "ballistica/shared/python/python_command.h"
|
#include "ballistica/shared/python/python_command.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
|
|
||||||
// How much of the screen the console covers when it is at full size.
|
// How much of the screen the console covers when it is at full size.
|
||||||
const float kDevConsoleSize{0.9f};
|
const float kDevConsoleFullSizeCoverage{0.9f};
|
||||||
|
const float kDevConsoleMiniSize{100.0f};
|
||||||
const int kDevConsoleLineLimit{80};
|
const int kDevConsoleLineLimit{80};
|
||||||
const int kDevConsoleStringBreakUpSize{1950};
|
const int kDevConsoleStringBreakUpSize{1950};
|
||||||
const float kDevConsoleTabButtonCornerRadius{16.0f};
|
const float kDevConsoleTabButtonCornerRadius{16.0f};
|
||||||
@ -99,32 +101,32 @@ static auto IsValidHungryChar_(uint32_t this_char) -> bool {
|
|||||||
|| (this_char >= 48 && this_char <= 57) || this_char == '_');
|
|| (this_char >= 48 && this_char <= 57) || this_char == '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawRect(RenderPass* pass, Mesh* mesh, float bottom, float x,
|
static void DrawRect(RenderPass* pass, Mesh* mesh, float x, float y,
|
||||||
float y, float width, float height,
|
float width, float height, const Vector3f& bgcolor,
|
||||||
const Vector3f& bgcolor) {
|
float alpha = 1.0f) {
|
||||||
SimpleComponent c(pass);
|
SimpleComponent c(pass);
|
||||||
c.SetTransparent(true);
|
c.SetTransparent(true);
|
||||||
c.SetColor(bgcolor.x, bgcolor.y, bgcolor.z, 1.0f);
|
c.SetColor(bgcolor.x, bgcolor.y, bgcolor.z, alpha);
|
||||||
c.SetTexture(g_base->assets->SysTexture(SysTextureID::kCircle));
|
c.SetTexture(g_base->assets->SysTexture(SysTextureID::kCircle));
|
||||||
// Draw mesh bg.
|
// Draw mesh bg.
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
auto xf = c.ScopedTransform();
|
auto xf = c.ScopedTransform();
|
||||||
c.Translate(x, y + bottom, kDevConsoleZDepth);
|
c.Translate(x, y, kDevConsoleZDepth);
|
||||||
c.DrawMesh(mesh);
|
c.DrawMesh(mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawText(RenderPass* pass, TextGroup* tgrp, float tscale,
|
static void DrawText(RenderPass* pass, TextGroup* tgrp, float tscale, float x,
|
||||||
float bottom, float x, float y, const Vector3f& fgcolor) {
|
float y, const Vector3f& fgcolor, float alpha = 1.0f) {
|
||||||
SimpleComponent c(pass);
|
SimpleComponent c(pass);
|
||||||
c.SetTransparent(true);
|
c.SetTransparent(true);
|
||||||
// Draw text.
|
// Draw text.
|
||||||
{
|
{
|
||||||
auto xf = c.ScopedTransform();
|
auto xf = c.ScopedTransform();
|
||||||
c.Translate(x, y + bottom, kDevConsoleZDepth);
|
c.Translate(x, y, kDevConsoleZDepth);
|
||||||
c.Scale(tscale, tscale, 1.0f);
|
c.Scale(tscale, tscale, 1.0f);
|
||||||
int elem_count = tgrp->GetElementCount();
|
int elem_count = tgrp->GetElementCount();
|
||||||
c.SetColor(fgcolor.x, fgcolor.y, fgcolor.z, 1.0f);
|
c.SetColor(fgcolor.x, fgcolor.y, fgcolor.z, alpha);
|
||||||
c.SetFlatness(1.0f);
|
c.SetFlatness(1.0f);
|
||||||
for (int e = 0; e < elem_count; e++) {
|
for (int e = 0; e < elem_count; e++) {
|
||||||
c.SetTexture(tgrp->GetElementTexture(e));
|
c.SetTexture(tgrp->GetElementTexture(e));
|
||||||
@ -186,7 +188,8 @@ class DevConsole::Text_ : public DevConsole::Widget_ {
|
|||||||
|
|
||||||
void Draw(RenderPass* pass, float bottom) override {
|
void Draw(RenderPass* pass, float bottom) override {
|
||||||
auto fgcolor = Vector3f{0.8f, 0.7f, 0.8f};
|
auto fgcolor = Vector3f{0.8f, 0.7f, 0.8f};
|
||||||
DrawText(pass, &text_group, scale, bottom, x + XOffs(h_attach), y, fgcolor);
|
DrawText(pass, &text_group, scale, x + XOffs(h_attach), bottom + y,
|
||||||
|
fgcolor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -203,11 +206,12 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
|||||||
TextGroup text_group;
|
TextGroup text_group;
|
||||||
float text_scale;
|
float text_scale;
|
||||||
DevButtonStyle_ style;
|
DevButtonStyle_ style;
|
||||||
|
bool disabled;
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
Button_(const std::string& label, float text_scale, DevConsoleHAnchor_ attach,
|
Button_(const std::string& label, float text_scale, DevConsoleHAnchor_ attach,
|
||||||
float x, float y, float width, float height, float corner_radius,
|
float x, float y, float width, float height, float corner_radius,
|
||||||
DevButtonStyle_ style, const F& lambda)
|
DevButtonStyle_ style, bool disabled, const F& lambda)
|
||||||
: attach{attach},
|
: attach{attach},
|
||||||
x{x},
|
x{x},
|
||||||
y{y},
|
y{y},
|
||||||
@ -216,6 +220,7 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
|||||||
call{NewLambdaRunnable(lambda)},
|
call{NewLambdaRunnable(lambda)},
|
||||||
text_scale{text_scale},
|
text_scale{text_scale},
|
||||||
style{style},
|
style{style},
|
||||||
|
disabled{disabled},
|
||||||
mesh(0.0f, 0.0f, 0.0f, width, height,
|
mesh(0.0f, 0.0f, 0.0f, width, height,
|
||||||
NinePatchMesh::BorderForRadius(corner_radius, width, height),
|
NinePatchMesh::BorderForRadius(corner_radius, width, height),
|
||||||
NinePatchMesh::BorderForRadius(corner_radius, height, width),
|
NinePatchMesh::BorderForRadius(corner_radius, height, width),
|
||||||
@ -232,7 +237,9 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
|||||||
|
|
||||||
auto HandleMouseDown(float mx, float my) -> bool override {
|
auto HandleMouseDown(float mx, float my) -> bool override {
|
||||||
if (InUs(mx, my)) {
|
if (InUs(mx, my)) {
|
||||||
pressed = true;
|
if (!disabled) {
|
||||||
|
pressed = true;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -266,9 +273,11 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
|||||||
bgcolor =
|
bgcolor =
|
||||||
pressed ? Vector3f{0.8f, 0.7f, 0.8f} : Vector3f{0.25, 0.2f, 0.3f};
|
pressed ? Vector3f{0.8f, 0.7f, 0.8f} : Vector3f{0.25, 0.2f, 0.3f};
|
||||||
}
|
}
|
||||||
DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height, bgcolor);
|
float alpha = disabled ? 0.3f : 1.0f;
|
||||||
DrawText(pass, &text_group, text_scale, bottom,
|
DrawRect(pass, &mesh, x + XOffs(attach), bottom + y, width, height, bgcolor,
|
||||||
x + XOffs(attach) + width * 0.5f, y + height * 0.5f, fgcolor);
|
alpha);
|
||||||
|
DrawText(pass, &text_group, text_scale, x + XOffs(attach) + width * 0.5f,
|
||||||
|
bottom + y + height * 0.5f, fgcolor, alpha);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -336,12 +345,12 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Draw(RenderPass* pass, float bottom) override {
|
void Draw(RenderPass* pass, float bottom) override {
|
||||||
DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height,
|
DrawRect(pass, &mesh, x + XOffs(attach), bottom + y, width, height,
|
||||||
pressed ? Vector3f{0.5f, 0.2f, 1.0f}
|
pressed ? Vector3f{0.5f, 0.2f, 1.0f}
|
||||||
: on ? Vector3f{0.5f, 0.4f, 0.6f}
|
: on ? Vector3f{0.5f, 0.4f, 0.6f}
|
||||||
: Vector3f{0.25, 0.2f, 0.3f});
|
: Vector3f{0.25, 0.2f, 0.3f});
|
||||||
DrawText(pass, &text_group, text_scale, bottom,
|
DrawText(pass, &text_group, text_scale, x + XOffs(attach) + width * 0.5f,
|
||||||
x + XOffs(attach) + width * 0.5f, y + height * 0.5f,
|
bottom + y + height * 0.5f,
|
||||||
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
|
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||||
: on ? Vector3f{1.0f, 1.0f, 1.0f}
|
: on ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||||
: Vector3f{0.8f, 0.7f, 0.8f});
|
: Vector3f{0.8f, 0.7f, 0.8f});
|
||||||
@ -417,12 +426,12 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Draw(RenderPass* pass, float bottom) override {
|
void Draw(RenderPass* pass, float bottom) override {
|
||||||
DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height,
|
DrawRect(pass, &mesh, x + XOffs(attach), bottom + y, width, height,
|
||||||
pressed ? Vector3f{0.4f, 0.2f, 0.8f}
|
pressed ? Vector3f{0.4f, 0.2f, 0.8f}
|
||||||
: selected ? Vector3f{0.4f, 0.3f, 0.4f}
|
: selected ? Vector3f{0.4f, 0.3f, 0.4f}
|
||||||
: Vector3f{0.25, 0.2f, 0.3f});
|
: Vector3f{0.25, 0.2f, 0.3f});
|
||||||
DrawText(pass, &text_group, text_scale, bottom,
|
DrawText(pass, &text_group, text_scale, x + XOffs(attach) + width * 0.5f,
|
||||||
x + XOffs(attach) + width * 0.5f, y + height * 0.5f,
|
bottom + y + height * 0.5f,
|
||||||
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
|
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||||
: selected ? Vector3f{1.0f, 1.0f, 1.0f}
|
: selected ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||||
: Vector3f{0.6f, 0.5f, 0.6f});
|
: Vector3f{0.6f, 0.5f, 0.6f});
|
||||||
@ -431,10 +440,16 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
|
|||||||
|
|
||||||
class DevConsole::OutputLine_ {
|
class DevConsole::OutputLine_ {
|
||||||
public:
|
public:
|
||||||
OutputLine_(std::string s_in, double c)
|
OutputLine_(std::string s_in, double creation_time, float scale,
|
||||||
: creation_time(c), s(std::move(s_in)) {}
|
Vector4f color)
|
||||||
double creation_time;
|
: creation_time(creation_time),
|
||||||
|
s(std::move(s_in)),
|
||||||
|
scale(scale),
|
||||||
|
color(color) {}
|
||||||
std::string s;
|
std::string s;
|
||||||
|
double creation_time;
|
||||||
|
float scale;
|
||||||
|
Vector4f color;
|
||||||
auto GetText() -> TextGroup& {
|
auto GetText() -> TextGroup& {
|
||||||
if (!s_mesh_.Exists()) {
|
if (!s_mesh_.Exists()) {
|
||||||
s_mesh_ = Object::New<TextGroup>();
|
s_mesh_ = Object::New<TextGroup>();
|
||||||
@ -555,7 +570,8 @@ void DevConsole::AddText(const char* text, float x, float y,
|
|||||||
void DevConsole::AddButton(const char* label, float x, float y, float width,
|
void DevConsole::AddButton(const char* label, float x, float y, float width,
|
||||||
float height, PyObject* call,
|
float height, PyObject* call,
|
||||||
const char* h_anchor_str, float label_scale,
|
const char* h_anchor_str, float label_scale,
|
||||||
float corner_radius, const char* style_str) {
|
float corner_radius, const char* style_str,
|
||||||
|
bool disabled) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
auto style = DevButtonStyleFromStr_(style_str);
|
auto style = DevButtonStyleFromStr_(style_str);
|
||||||
@ -563,7 +579,7 @@ void DevConsole::AddButton(const char* label, float x, float y, float width,
|
|||||||
|
|
||||||
widgets_.emplace_back(std::make_unique<Button_>(
|
widgets_.emplace_back(std::make_unique<Button_>(
|
||||||
label, label_scale, h_anchor, x, y, width, height, corner_radius, style,
|
label, label_scale, h_anchor, x, y, width, height, corner_radius, style,
|
||||||
[this, callref = PythonRef::Acquired(call)] {
|
disabled, [this, callref = PythonRef::Acquired(call)] {
|
||||||
if (callref.Get() != Py_None) {
|
if (callref.Get() != Py_None) {
|
||||||
callref.Call();
|
callref.Call();
|
||||||
}
|
}
|
||||||
@ -574,7 +590,7 @@ void DevConsole::AddPythonTerminal() {
|
|||||||
float bs = BaseScale();
|
float bs = BaseScale();
|
||||||
widgets_.emplace_back(std::make_unique<Button_>(
|
widgets_.emplace_back(std::make_unique<Button_>(
|
||||||
"Exec", 0.5f * bs, DevConsoleHAnchor_::kRight, -33.0f * bs, 15.95f * bs,
|
"Exec", 0.5f * bs, DevConsoleHAnchor_::kRight, -33.0f * bs, 15.95f * bs,
|
||||||
32.0f * bs, 13.0f * bs, 2.0 * bs, DevButtonStyle_::kNormal,
|
32.0f * bs, 13.0f * bs, 2.0 * bs, DevButtonStyle_::kNormal, false,
|
||||||
[this] { Exec(); }));
|
[this] { Exec(); }));
|
||||||
python_terminal_visible_ = true;
|
python_terminal_visible_ = true;
|
||||||
}
|
}
|
||||||
@ -632,7 +648,11 @@ auto DevConsole::Width() -> float {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto DevConsole::Height() -> float {
|
auto DevConsole::Height() -> float {
|
||||||
return g_base->graphics->screen_virtual_height() - Bottom_();
|
if (state_ == State_::kMini) {
|
||||||
|
return kDevConsoleMiniSize;
|
||||||
|
}
|
||||||
|
return g_base->graphics->screen_virtual_height()
|
||||||
|
* kDevConsoleFullSizeCoverage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevConsole::HandleMouseUp(int button, float x, float y) {
|
void DevConsole::HandleMouseUp(int button, float x, float y) {
|
||||||
@ -678,7 +698,7 @@ void DevConsole::InvokeStringEditor_() {
|
|||||||
.Get(BasePython::ObjID::kDevConsoleStringEditAdapterClass)
|
.Get(BasePython::ObjID::kDevConsoleStringEditAdapterClass)
|
||||||
.Call();
|
.Call();
|
||||||
if (!result.Exists()) {
|
if (!result.Exists()) {
|
||||||
Log(LogLevel::kError, "Error invoking string edit dialog.");
|
Log(LogName::kBa, LogLevel::kError, "Error invoking string edit dialog.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1037,12 +1057,11 @@ auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool {
|
|||||||
void DevConsole::Exec() {
|
void DevConsole::Exec() {
|
||||||
BA_PRECONDITION(g_base->InLogicThread());
|
BA_PRECONDITION(g_base->InLogicThread());
|
||||||
if (!input_enabled_) {
|
if (!input_enabled_) {
|
||||||
Log(LogLevel::kWarning, "Console input is not allowed yet.");
|
Log(LogName::kBa, LogLevel::kWarning, "Console input is not allowed yet.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input_history_position_ = 0;
|
input_history_position_ = 0;
|
||||||
if (input_string_ == "clear") {
|
if (input_string_ == "clear") {
|
||||||
last_line_.clear();
|
|
||||||
output_lines_.clear();
|
output_lines_.clear();
|
||||||
} else {
|
} else {
|
||||||
SubmitPythonCommand_(input_string_);
|
SubmitPythonCommand_(input_string_);
|
||||||
@ -1077,7 +1096,7 @@ void DevConsole::SubmitPythonCommand_(const std::string& command) {
|
|||||||
if (cmd.CanEval()) {
|
if (cmd.CanEval()) {
|
||||||
auto obj = cmd.Eval(true, nullptr, nullptr);
|
auto obj = cmd.Eval(true, nullptr, nullptr);
|
||||||
if (obj.Exists() && obj.Get() != Py_None) {
|
if (obj.Exists() && obj.Get() != Py_None) {
|
||||||
Print(obj.Repr() + "\n");
|
Print(obj.Repr(), 1.0f, kVector4f1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not eval-able; just exec it.
|
// Not eval-able; just exec it.
|
||||||
@ -1129,23 +1148,21 @@ void DevConsole::ToggleState() {
|
|||||||
transition_start_ = g_base->logic->display_time();
|
transition_start_ = g_base->logic->display_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevConsole::Print(const std::string& s_in) {
|
void DevConsole::Print(const std::string& s_in, float scale, Vector4f color) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
std::string s = Utils::GetValidUTF8(s_in.c_str(), "cspr");
|
std::string s = Utils::GetValidUTF8(s_in.c_str(), "cspr");
|
||||||
last_line_ += s;
|
|
||||||
std::vector<std::string> broken_up;
|
std::vector<std::string> broken_up;
|
||||||
g_base->text_graphics->BreakUpString(
|
g_base->text_graphics->BreakUpString(
|
||||||
last_line_.c_str(), kDevConsoleStringBreakUpSize, &broken_up);
|
s.c_str(), kDevConsoleStringBreakUpSize / scale, &broken_up);
|
||||||
|
|
||||||
// Spit out all completed lines and keep the last one as lastline.
|
// Spit out all lines.
|
||||||
for (size_t i = 0; i < broken_up.size() - 1; i++) {
|
for (size_t i = 0; i < broken_up.size(); i++) {
|
||||||
output_lines_.emplace_back(broken_up[i], g_base->logic->display_time());
|
output_lines_.emplace_back(broken_up[i], g_base->logic->display_time(),
|
||||||
|
scale, color);
|
||||||
if (output_lines_.size() > kDevConsoleLineLimit) {
|
if (output_lines_.size() > kDevConsoleLineLimit) {
|
||||||
output_lines_.pop_front();
|
output_lines_.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_line_ = broken_up[broken_up.size() - 1];
|
|
||||||
last_line_mesh_dirty_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DevConsole::Bottom_() const -> float {
|
auto DevConsole::Bottom_() const -> float {
|
||||||
@ -1160,30 +1177,29 @@ auto DevConsole::Bottom_() const -> float {
|
|||||||
// dev-consoles are not meant to be especially pretty and I think it is
|
// dev-consoles are not meant to be especially pretty and I think it is
|
||||||
// more important for them to be able to be written to a known hard-coded
|
// more important for them to be able to be written to a known hard-coded
|
||||||
// mini-size.
|
// mini-size.
|
||||||
float mini_size = 100.0f;
|
//
|
||||||
|
|
||||||
// Now that we have tabs and drop-shadows hanging down, we have to
|
// Now that we have tabs and drop-shadows hanging down, we have to
|
||||||
// overshoot the top of the screen when transitioning out.
|
// overshoot the top of the screen when transitioning out.
|
||||||
float top_buffer = 100.0f;
|
float top_buffer = 100.0f;
|
||||||
if (state_ == State_::kMini) {
|
if (state_ == State_::kMini) {
|
||||||
bottom = vh - mini_size;
|
bottom = vh - kDevConsoleMiniSize;
|
||||||
} else {
|
} else {
|
||||||
bottom = vh - vh * kDevConsoleSize;
|
bottom = vh * (1.0f - kDevConsoleFullSizeCoverage);
|
||||||
}
|
}
|
||||||
if (g_base->logic->display_time() - transition_start_ < kTransitionSeconds) {
|
if (g_base->logic->display_time() - transition_start_ < kTransitionSeconds) {
|
||||||
float from_height;
|
float from_height;
|
||||||
if (state_prev_ == State_::kMini) {
|
if (state_prev_ == State_::kMini) {
|
||||||
from_height = vh - mini_size;
|
from_height = vh - kDevConsoleMiniSize;
|
||||||
} else if (state_prev_ == State_::kFull) {
|
} else if (state_prev_ == State_::kFull) {
|
||||||
from_height = vh - vh * kDevConsoleSize;
|
from_height = vh - vh * kDevConsoleFullSizeCoverage;
|
||||||
} else {
|
} else {
|
||||||
from_height = vh + top_buffer;
|
from_height = vh + top_buffer;
|
||||||
}
|
}
|
||||||
float to_height;
|
float to_height;
|
||||||
if (state_ == State_::kMini) {
|
if (state_ == State_::kMini) {
|
||||||
to_height = vh - mini_size;
|
to_height = vh - kDevConsoleMiniSize;
|
||||||
} else if (state_ == State_::kFull) {
|
} else if (state_ == State_::kFull) {
|
||||||
to_height = vh - vh * kDevConsoleSize;
|
to_height = vh - vh * kDevConsoleFullSizeCoverage;
|
||||||
} else {
|
} else {
|
||||||
to_height = vh + top_buffer;
|
to_height = vh + top_buffer;
|
||||||
}
|
}
|
||||||
@ -1205,6 +1221,31 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the virtual screen size has changed, refresh.
|
||||||
|
auto screen_virtual_width{g_base->graphics->screen_virtual_width()};
|
||||||
|
auto screen_virtual_height{g_base->graphics->screen_virtual_height()};
|
||||||
|
|
||||||
|
if (last_virtual_res_x_ < 0.0f) {
|
||||||
|
// First time through, just grab current value; don't refresh.
|
||||||
|
last_virtual_res_x_ = screen_virtual_width;
|
||||||
|
last_virtual_res_y_ = screen_virtual_height;
|
||||||
|
} else {
|
||||||
|
// Otherwise if virtual res changed and its been long enough, refresh.
|
||||||
|
auto display_time{g_base->logic->display_time()};
|
||||||
|
double update_interval{0.2};
|
||||||
|
if (display_time > last_virtual_res_change_time_ + update_interval
|
||||||
|
&& (last_virtual_res_x_ != screen_virtual_width
|
||||||
|
|| last_virtual_res_y_ != screen_virtual_height)) {
|
||||||
|
last_virtual_res_x_ = screen_virtual_width;
|
||||||
|
last_virtual_res_y_ = screen_virtual_height;
|
||||||
|
last_virtual_res_change_time_ = display_time;
|
||||||
|
g_base->logic->event_loop()->PushCall([this] {
|
||||||
|
RefreshTabButtons_();
|
||||||
|
RefreshTabContents_();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float bottom = Bottom_();
|
float bottom = Bottom_();
|
||||||
|
|
||||||
float border_height{3.0f};
|
float border_height{3.0f};
|
||||||
@ -1355,7 +1396,6 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
|||||||
{
|
{
|
||||||
SimpleComponent c(pass);
|
SimpleComponent c(pass);
|
||||||
c.SetTransparent(true);
|
c.SetTransparent(true);
|
||||||
c.SetColor(1, 1, 1, 1);
|
|
||||||
c.SetFlatness(1.0f);
|
c.SetFlatness(1.0f);
|
||||||
float draw_scale = 0.64f;
|
float draw_scale = 0.64f;
|
||||||
float v_inc = 18.0f;
|
float v_inc = 18.0f;
|
||||||
@ -1363,38 +1403,19 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
|||||||
* (g_base->graphics->screen_virtual_width()
|
* (g_base->graphics->screen_virtual_width()
|
||||||
- (kDevConsoleStringBreakUpSize * draw_scale));
|
- (kDevConsoleStringBreakUpSize * draw_scale));
|
||||||
float v = bottom + 32.0f * bs;
|
float v = bottom + 32.0f * bs;
|
||||||
if (!last_line_.empty()) {
|
|
||||||
if (last_line_mesh_dirty_) {
|
|
||||||
if (!last_line_mesh_group_.Exists()) {
|
|
||||||
last_line_mesh_group_ = Object::New<TextGroup>();
|
|
||||||
}
|
|
||||||
last_line_mesh_group_->SetText(last_line_);
|
|
||||||
last_line_mesh_dirty_ = false;
|
|
||||||
}
|
|
||||||
int elem_count = last_line_mesh_group_->GetElementCount();
|
|
||||||
for (int e = 0; e < elem_count; e++) {
|
|
||||||
c.SetTexture(last_line_mesh_group_->GetElementTexture(e));
|
|
||||||
{
|
|
||||||
auto xf = c.ScopedTransform();
|
|
||||||
c.Translate(h, v + 2, kDevConsoleZDepth);
|
|
||||||
c.Scale(draw_scale, draw_scale);
|
|
||||||
c.DrawMesh(last_line_mesh_group_->GetElementMesh(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v += v_inc;
|
|
||||||
}
|
|
||||||
for (auto i = output_lines_.rbegin(); i != output_lines_.rend(); i++) {
|
for (auto i = output_lines_.rbegin(); i != output_lines_.rend(); i++) {
|
||||||
int elem_count = i->GetText().GetElementCount();
|
int elem_count = i->GetText().GetElementCount();
|
||||||
for (int e = 0; e < elem_count; e++) {
|
for (int e = 0; e < elem_count; e++) {
|
||||||
|
c.SetColor(i->color.x, i->color.y, i->color.z, i->color.a);
|
||||||
c.SetTexture(i->GetText().GetElementTexture(e));
|
c.SetTexture(i->GetText().GetElementTexture(e));
|
||||||
{
|
{
|
||||||
auto xf = c.ScopedTransform();
|
auto xf = c.ScopedTransform();
|
||||||
c.Translate(h, v + 2, kDevConsoleZDepth);
|
c.Translate(h, v + 2, kDevConsoleZDepth);
|
||||||
c.Scale(draw_scale, draw_scale);
|
c.Scale(draw_scale * i->scale, draw_scale * i->scale);
|
||||||
c.DrawMesh(i->GetText().GetElementMesh(e));
|
c.DrawMesh(i->GetText().GetElementMesh(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v += v_inc;
|
v += v_inc * i->scale;
|
||||||
if (v > pass->virtual_height() + v_inc) {
|
if (v > pass->virtual_height() + v_inc) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "ballistica/base/graphics/mesh/image_mesh.h"
|
#include "ballistica/base/graphics/mesh/image_mesh.h"
|
||||||
#include "ballistica/base/graphics/text/text_group.h"
|
#include "ballistica/base/graphics/text/text_group.h"
|
||||||
#include "ballistica/shared/foundation/object.h"
|
#include "ballistica/shared/foundation/object.h"
|
||||||
|
#include "ballistica/shared/math/vector4f.h"
|
||||||
#include "ballistica/shared/python/python_ref.h"
|
#include "ballistica/shared/python/python_ref.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
@ -36,7 +37,7 @@ class DevConsole {
|
|||||||
auto PasteFromClipboard() -> bool;
|
auto PasteFromClipboard() -> bool;
|
||||||
|
|
||||||
/// Print text to the console.
|
/// Print text to the console.
|
||||||
void Print(const std::string& s_in);
|
void Print(const std::string& s_in, float scale, Vector4f color);
|
||||||
void Draw(FrameDef* frame_def);
|
void Draw(FrameDef* frame_def);
|
||||||
|
|
||||||
void StepDisplayTime();
|
void StepDisplayTime();
|
||||||
@ -58,7 +59,7 @@ class DevConsole {
|
|||||||
|
|
||||||
void AddButton(const char* label, float x, float y, float width, float height,
|
void AddButton(const char* label, float x, float y, float width, float height,
|
||||||
PyObject* call, const char* h_anchor_str, float label_scale,
|
PyObject* call, const char* h_anchor_str, float label_scale,
|
||||||
float corner_radius, const char* style_str);
|
float corner_radius, const char* style_str, bool disabled);
|
||||||
void AddText(const char* text, float x, float y, const char* h_anchor_str,
|
void AddText(const char* text, float x, float y, const char* h_anchor_str,
|
||||||
const char* h_align_str, const char* v_align_str, float scale);
|
const char* h_align_str, const char* v_align_str, float scale);
|
||||||
void AddPythonTerminal();
|
void AddPythonTerminal();
|
||||||
@ -96,12 +97,14 @@ class DevConsole {
|
|||||||
State_ state_prev_{State_::kInactive};
|
State_ state_prev_{State_::kInactive};
|
||||||
bool input_text_dirty_{true};
|
bool input_text_dirty_{true};
|
||||||
bool input_enabled_{};
|
bool input_enabled_{};
|
||||||
bool last_line_mesh_dirty_{true};
|
|
||||||
bool python_terminal_visible_{};
|
bool python_terminal_visible_{};
|
||||||
bool python_terminal_pressed_{};
|
bool python_terminal_pressed_{};
|
||||||
bool refresh_pending_{};
|
bool refresh_pending_{};
|
||||||
bool carat_dirty_{true};
|
bool carat_dirty_{true};
|
||||||
float carat_x_{};
|
float carat_x_{};
|
||||||
|
float last_virtual_res_x_{-1.0f};
|
||||||
|
float last_virtual_res_y_{-1.0f};
|
||||||
|
seconds_t last_virtual_res_change_time_{};
|
||||||
seconds_t transition_start_{};
|
seconds_t transition_start_{};
|
||||||
millisecs_t last_carat_x_change_time_{};
|
millisecs_t last_carat_x_change_time_{};
|
||||||
ImageMesh bg_mesh_;
|
ImageMesh bg_mesh_;
|
||||||
@ -111,7 +114,6 @@ class DevConsole {
|
|||||||
TextGroup title_text_group_;
|
TextGroup title_text_group_;
|
||||||
TextGroup prompt_text_group_;
|
TextGroup prompt_text_group_;
|
||||||
TextGroup input_text_group_;
|
TextGroup input_text_group_;
|
||||||
std::string last_line_;
|
|
||||||
std::string input_string_;
|
std::string input_string_;
|
||||||
std::list<std::string> tabs_;
|
std::list<std::string> tabs_;
|
||||||
std::string active_tab_;
|
std::string active_tab_;
|
||||||
@ -120,7 +122,6 @@ class DevConsole {
|
|||||||
std::list<OutputLine_> output_lines_;
|
std::list<OutputLine_> output_lines_;
|
||||||
std::vector<std::unique_ptr<Widget_> > widgets_;
|
std::vector<std::unique_ptr<Widget_> > widgets_;
|
||||||
std::vector<std::unique_ptr<Widget_> > tab_buttons_;
|
std::vector<std::unique_ptr<Widget_> > tab_buttons_;
|
||||||
Object::Ref<TextGroup> last_line_mesh_group_;
|
|
||||||
Object::Ref<Repeater> key_repeater_;
|
Object::Ref<Repeater> key_repeater_;
|
||||||
Object::Ref<NinePatchMesh> carat_mesh_;
|
Object::Ref<NinePatchMesh> carat_mesh_;
|
||||||
Object::Ref<NinePatchMesh> carat_glow_mesh_;
|
Object::Ref<NinePatchMesh> carat_glow_mesh_;
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "ballistica/shared/foundation/event_loop.h"
|
#include "ballistica/shared/foundation/event_loop.h"
|
||||||
#include "ballistica/shared/foundation/macros.h"
|
#include "ballistica/shared/foundation/macros.h"
|
||||||
#include "ballistica/shared/generic/utils.h"
|
#include "ballistica/shared/generic/utils.h"
|
||||||
|
#include "ballistica/shared/math/vector4f.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
|
|
||||||
@ -165,13 +166,13 @@ void UI::OnAppStart() {
|
|||||||
if (force_scale_) {
|
if (force_scale_) {
|
||||||
if (scale_ == UIScale::kSmall) {
|
if (scale_ == UIScale::kSmall) {
|
||||||
ScreenMessage("FORCING SMALL UI FOR TESTING", Vector3f(1, 0, 0));
|
ScreenMessage("FORCING SMALL UI FOR TESTING", Vector3f(1, 0, 0));
|
||||||
Log(LogLevel::kInfo, "FORCING SMALL UI FOR TESTING");
|
Log(LogName::kBa, LogLevel::kInfo, "FORCING SMALL UI FOR TESTING");
|
||||||
} else if (scale_ == UIScale::kMedium) {
|
} else if (scale_ == UIScale::kMedium) {
|
||||||
ScreenMessage("FORCING MEDIUM UI FOR TESTING", Vector3f(1, 0, 0));
|
ScreenMessage("FORCING MEDIUM UI FOR TESTING", Vector3f(1, 0, 0));
|
||||||
Log(LogLevel::kInfo, "FORCING MEDIUM UI FOR TESTING");
|
Log(LogName::kBa, LogLevel::kInfo, "FORCING MEDIUM UI FOR TESTING");
|
||||||
} else if (scale_ == UIScale::kLarge) {
|
} else if (scale_ == UIScale::kLarge) {
|
||||||
ScreenMessage("FORCING LARGE UI FOR TESTING", Vector3f(1, 0, 0));
|
ScreenMessage("FORCING LARGE UI FOR TESTING", Vector3f(1, 0, 0));
|
||||||
Log(LogLevel::kInfo, "FORCING LARGE UI FOR TESTING");
|
Log(LogName::kBa, LogLevel::kInfo, "FORCING LARGE UI FOR TESTING");
|
||||||
} else {
|
} else {
|
||||||
FatalError("Unhandled scale.");
|
FatalError("Unhandled scale.");
|
||||||
}
|
}
|
||||||
@ -576,7 +577,8 @@ void UI::ShowURL(const std::string& url) {
|
|||||||
g_base->logic->event_loop()->PushCall(
|
g_base->logic->event_loop()->PushCall(
|
||||||
[ui_delegate, url] { ui_delegate->DoShowURL(url); });
|
[ui_delegate, url] { ui_delegate->DoShowURL(url); });
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kWarning, "UI::ShowURL called without ui_delegate present.");
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
|
"UI::ShowURL called without ui_delegate present.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,7 +623,8 @@ void UI::SetUIDelegate(base::UIDelegateInterface* delegate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI::PushDevConsolePrintCall(const std::string& msg) {
|
void UI::PushDevConsolePrintCall(const std::string& msg, float scale,
|
||||||
|
Vector4f color) {
|
||||||
// Completely ignore this stuff in headless mode.
|
// Completely ignore this stuff in headless mode.
|
||||||
if (g_core->HeadlessMode()) {
|
if (g_core->HeadlessMode()) {
|
||||||
return;
|
return;
|
||||||
@ -630,12 +633,14 @@ void UI::PushDevConsolePrintCall(const std::string& msg) {
|
|||||||
// printed. Otherwise store it for the console to grab when it's ready.
|
// printed. Otherwise store it for the console to grab when it's ready.
|
||||||
if (auto* event_loop = g_base->logic->event_loop()) {
|
if (auto* event_loop = g_base->logic->event_loop()) {
|
||||||
if (dev_console_ != nullptr) {
|
if (dev_console_ != nullptr) {
|
||||||
event_loop->PushCall([this, msg] { dev_console_->Print(msg); });
|
event_loop->PushCall([this, msg, scale, color] {
|
||||||
|
dev_console_->Print(msg, scale, color);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Didn't send a print; store for later.
|
// Didn't send a print; store for later.
|
||||||
dev_console_startup_messages_ += msg;
|
dev_console_startup_messages_.emplace_back(msg, scale, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI::OnAssetsAvailable() {
|
void UI::OnAssetsAvailable() {
|
||||||
@ -648,7 +653,10 @@ void UI::OnAssetsAvailable() {
|
|||||||
|
|
||||||
// Print any messages that have built up.
|
// Print any messages that have built up.
|
||||||
if (!dev_console_startup_messages_.empty()) {
|
if (!dev_console_startup_messages_.empty()) {
|
||||||
dev_console_->Print(dev_console_startup_messages_);
|
for (auto&& entry : dev_console_startup_messages_) {
|
||||||
|
dev_console_->Print(std::get<0>(entry), std::get<1>(entry),
|
||||||
|
std::get<2>(entry));
|
||||||
|
}
|
||||||
dev_console_startup_messages_.clear();
|
dev_console_startup_messages_.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,13 @@
|
|||||||
#ifndef BALLISTICA_BASE_UI_UI_H_
|
#ifndef BALLISTICA_BASE_UI_UI_H_
|
||||||
#define BALLISTICA_BASE_UI_UI_H_
|
#define BALLISTICA_BASE_UI_UI_H_
|
||||||
|
|
||||||
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ballistica/base/graphics/support/frame_def.h"
|
#include "ballistica/base/graphics/support/frame_def.h"
|
||||||
#include "ballistica/base/ui/widget_message.h"
|
#include "ballistica/base/ui/widget_message.h"
|
||||||
|
#include "ballistica/shared/math/vector4f.h"
|
||||||
|
|
||||||
// Predeclare a few things from ui_v1.
|
// Predeclare a few things from ui_v1.
|
||||||
namespace ballistica::ui_v1 {
|
namespace ballistica::ui_v1 {
|
||||||
@ -123,7 +125,8 @@ class UI {
|
|||||||
|
|
||||||
auto* dev_console() const { return dev_console_; }
|
auto* dev_console() const { return dev_console_; }
|
||||||
|
|
||||||
void PushDevConsolePrintCall(const std::string& msg);
|
void PushDevConsolePrintCall(const std::string& msg, float scale,
|
||||||
|
Vector4f color);
|
||||||
|
|
||||||
auto* delegate() const { return delegate_; }
|
auto* delegate() const { return delegate_; }
|
||||||
|
|
||||||
@ -154,7 +157,8 @@ class UI {
|
|||||||
OperationContext* operation_context_{};
|
OperationContext* operation_context_{};
|
||||||
base::UIDelegateInterface* delegate_{};
|
base::UIDelegateInterface* delegate_{};
|
||||||
DevConsole* dev_console_{};
|
DevConsole* dev_console_{};
|
||||||
std::string dev_console_startup_messages_;
|
std::list<std::tuple<std::string, float, Vector4f>>
|
||||||
|
dev_console_startup_messages_;
|
||||||
millisecs_t last_input_device_use_time_{};
|
millisecs_t last_input_device_use_time_{};
|
||||||
millisecs_t last_widget_input_reject_err_sound_time_{};
|
millisecs_t last_widget_input_reject_err_sound_time_{};
|
||||||
UIScale scale_{UIScale::kLarge};
|
UIScale scale_{UIScale::kLarge};
|
||||||
|
|||||||
@ -151,9 +151,9 @@ auto ClassicFeatureSet::GetV1AccountLoginStateString() -> std::string {
|
|||||||
out = "signing_in";
|
out = "signing_in";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::kError, "Unknown V1LoginState '"
|
Log(LogName::kBaAccount, LogLevel::kError,
|
||||||
+ std::to_string(static_cast<int>(state))
|
"Unknown V1LoginState '" + std::to_string(static_cast<int>(state))
|
||||||
+ "'");
|
+ "'");
|
||||||
out = "signed_out";
|
out = "signed_out";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,9 +128,10 @@ void ClassicAppMode::Reset_() {
|
|||||||
|
|
||||||
// If all is well our sessions should all be dead at this point.
|
// If all is well our sessions should all be dead at this point.
|
||||||
if (g_scene_v1->session_count != 0) {
|
if (g_scene_v1->session_count != 0) {
|
||||||
Log(LogLevel::kError, "SceneV1 session count is non-zero ("
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ std::to_string(g_scene_v1->session_count)
|
"SceneV1 session count is non-zero ("
|
||||||
+ ") on ClassicAppMode::Reset_().");
|
+ std::to_string(g_scene_v1->session_count)
|
||||||
|
+ ") on ClassicAppMode::Reset_().");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the engine itself to a default state.
|
// Reset the engine itself to a default state.
|
||||||
@ -159,15 +160,16 @@ void ClassicAppMode::HostScanCycle() {
|
|||||||
scan_socket_ = socket(AF_INET, SOCK_DGRAM, 0);
|
scan_socket_ = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
if (scan_socket_ == -1) {
|
if (scan_socket_ == -1) {
|
||||||
Log(LogLevel::kError, "Error opening scan socket: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString()
|
"Error opening scan socket: "
|
||||||
+ ".");
|
+ g_core->platform->GetSocketErrorString() + ".");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since this guy lives in the logic-thread we need it to not block.
|
// Since this guy lives in the logic-thread we need it to not block.
|
||||||
if (!g_core->platform->SetSocketNonBlocking(scan_socket_)) {
|
if (!g_core->platform->SetSocketNonBlocking(scan_socket_)) {
|
||||||
Log(LogLevel::kError, "Error setting socket non-blocking.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Error setting socket non-blocking.");
|
||||||
g_core->platform->CloseSocket(scan_socket_);
|
g_core->platform->CloseSocket(scan_socket_);
|
||||||
scan_socket_ = -1;
|
scan_socket_ = -1;
|
||||||
return;
|
return;
|
||||||
@ -182,7 +184,7 @@ void ClassicAppMode::HostScanCycle() {
|
|||||||
int result =
|
int result =
|
||||||
::bind(scan_socket_, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
::bind(scan_socket_, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||||
if (result == 1) {
|
if (result == 1) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Error binding socket: " + g_core->platform->GetSocketErrorString()
|
"Error binding socket: " + g_core->platform->GetSocketErrorString()
|
||||||
+ ".");
|
+ ".");
|
||||||
g_core->platform->CloseSocket(scan_socket_);
|
g_core->platform->CloseSocket(scan_socket_);
|
||||||
@ -196,9 +198,9 @@ void ClassicAppMode::HostScanCycle() {
|
|||||||
sizeof(op_val));
|
sizeof(op_val));
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
Log(LogLevel::kError, "Error enabling broadcast for scan-socket: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString()
|
"Error enabling broadcast for scan-socket: "
|
||||||
+ ".");
|
+ g_core->platform->GetSocketErrorString() + ".");
|
||||||
g_core->platform->CloseSocket(scan_socket_);
|
g_core->platform->CloseSocket(scan_socket_);
|
||||||
scan_socket_ = -1;
|
scan_socket_ = -1;
|
||||||
return;
|
return;
|
||||||
@ -230,8 +232,9 @@ void ClassicAppMode::HostScanCycle() {
|
|||||||
case ENETUNREACH:
|
case ENETUNREACH:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::kError, "Error on scanSocket sendto: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Error on scan-socket sendto: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,8 +256,9 @@ void ClassicAppMode::HostScanCycle() {
|
|||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::kError, "Error: recvfrom error: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Error: recvfrom error: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -311,11 +315,11 @@ void ClassicAppMode::HostScanCycle() {
|
|||||||
PruneScanResults_();
|
PruneScanResults_();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Got invalid BA_PACKET_HOST_QUERY_RESPONSE packet");
|
"Got invalid BA_PACKET_HOST_QUERY_RESPONSE packet");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Got invalid BA_PACKET_HOST_QUERY_RESPONSE packet");
|
"Got invalid BA_PACKET_HOST_QUERY_RESPONSE packet");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,7 +392,7 @@ bool ClassicAppMode::HasConnectionToClients() const {
|
|||||||
auto ClassicAppMode::GetActiveOrWarn() -> ClassicAppMode* {
|
auto ClassicAppMode::GetActiveOrWarn() -> ClassicAppMode* {
|
||||||
auto* val{GetActive()};
|
auto* val{GetActive()};
|
||||||
if (val == nullptr) {
|
if (val == nullptr) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
"Attempting to access ClassicAppMode while it is inactive.");
|
"Attempting to access ClassicAppMode while it is inactive.");
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -515,6 +519,16 @@ void ClassicAppMode::StepDisplayTime() {
|
|||||||
}
|
}
|
||||||
legacy_display_time_millisecs_prev_ = legacy_display_time_millisecs_;
|
legacy_display_time_millisecs_prev_ = legacy_display_time_millisecs_;
|
||||||
|
|
||||||
|
// Special case: due to things like app-mode-switches our
|
||||||
|
// prev-display-time-millisecs may be way in the past which
|
||||||
|
// can give us huge step values. So if this value is much bigger
|
||||||
|
// than the direct conversion of display_time_increment, clamp it.
|
||||||
|
auto milliseconds_inc_max =
|
||||||
|
static_cast<int>(g_base->logic->display_time_increment() * 1000.0 * 1.5);
|
||||||
|
if (legacy_display_time_millisecs_inc > milliseconds_inc_max) {
|
||||||
|
legacy_display_time_millisecs_inc = milliseconds_inc_max;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateKickVote_();
|
UpdateKickVote_();
|
||||||
|
|
||||||
HandleQuitOnIdle_();
|
HandleQuitOnIdle_();
|
||||||
@ -559,8 +573,9 @@ void ClassicAppMode::StepDisplayTime() {
|
|||||||
|
|
||||||
// Complain when our full update takes longer than 1/60th second.
|
// Complain when our full update takes longer than 1/60th second.
|
||||||
if (duration > (1000 / 60)) {
|
if (duration > (1000 / 60)) {
|
||||||
Log(LogLevel::kInfo, "Logic::StepDisplayTime update took too long ("
|
Log(LogName::kBa, LogLevel::kInfo,
|
||||||
+ std::to_string(duration) + " ms).");
|
"Logic::StepDisplayTime update took too long ("
|
||||||
|
+ std::to_string(duration) + " ms).");
|
||||||
|
|
||||||
// Limit these if we want (not doing so for now).
|
// Limit these if we want (not doing so for now).
|
||||||
next_long_update_report_time_ = app_time;
|
next_long_update_report_time_ = app_time;
|
||||||
@ -624,7 +639,7 @@ void ClassicAppMode::UpdateGameRoster() {
|
|||||||
for (auto&& p : hs->players()) {
|
for (auto&& p : hs->players()) {
|
||||||
auto* delegate = p->input_device_delegate();
|
auto* delegate = p->input_device_delegate();
|
||||||
if (delegate == nullptr || !delegate->InputDeviceExists()) {
|
if (delegate == nullptr || !delegate->InputDeviceExists()) {
|
||||||
BA_LOG_ONCE(LogLevel::kWarning,
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kWarning,
|
||||||
"Found player with no/invalid input-device-delegate in "
|
"Found player with no/invalid input-device-delegate in "
|
||||||
"UpdateGameRoster.");
|
"UpdateGameRoster.");
|
||||||
continue;
|
continue;
|
||||||
@ -1215,7 +1230,7 @@ void ClassicAppMode::PruneSessions_() {
|
|||||||
try {
|
try {
|
||||||
i.Clear();
|
i.Clear();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Exception killing Session: " + std::string(e.what()));
|
"Exception killing Session: " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
have_dead_session = true;
|
have_dead_session = true;
|
||||||
@ -1403,7 +1418,8 @@ void ClassicAppMode::HandleQuitOnIdle_() {
|
|||||||
if (!idle_exiting_ && idle_seconds > (idle_exit_minutes_.value() * 60.0f)) {
|
if (!idle_exiting_ && idle_seconds > (idle_exit_minutes_.value() * 60.0f)) {
|
||||||
idle_exiting_ = true;
|
idle_exiting_ = true;
|
||||||
|
|
||||||
Log(LogLevel::kInfo, "Quitting due to reaching idle-exit-minutes.");
|
Log(LogName::kBa, LogLevel::kInfo,
|
||||||
|
"Quitting due to reaching idle-exit-minutes.");
|
||||||
g_base->logic->event_loop()->PushCall([] { g_base->logic->Shutdown(); });
|
g_base->logic->event_loop()->PushCall([] { g_base->logic->Shutdown(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1462,7 +1478,8 @@ void ClassicAppMode::HandleGameQuery(const char* buffer, size_t size,
|
|||||||
|
|
||||||
BA_PRECONDITION_FATAL(!usid.empty());
|
BA_PRECONDITION_FATAL(!usid.empty());
|
||||||
if (usid.size() > 100) {
|
if (usid.size() > 100) {
|
||||||
Log(LogLevel::kError, "had to truncate session-id; shouldn't happen");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"had to truncate session-id; shouldn't happen");
|
||||||
usid.resize(100);
|
usid.resize(100);
|
||||||
}
|
}
|
||||||
if (usid.empty()) {
|
if (usid.empty()) {
|
||||||
@ -1488,8 +1505,9 @@ void ClassicAppMode::HandleGameQuery(const char* buffer, size_t size,
|
|||||||
g_base->network_writer->PushSendToCall(msg_buffer, SockAddr(*from));
|
g_base->network_writer->PushSendToCall(msg_buffer, SockAddr(*from));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "Got invalid game-query packet of len "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ std::to_string(size) + "; expected 5.");
|
"Got invalid game-query packet of len " + std::to_string(size)
|
||||||
|
+ "; expected 5.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "ballistica/core/platform/core_platform.h"
|
#include "ballistica/core/platform/core_platform.h"
|
||||||
#include "ballistica/core/python/core_python.h"
|
#include "ballistica/core/python/core_python.h"
|
||||||
|
#include "ballistica/shared/foundation/macros.h"
|
||||||
#include "ballistica/shared/foundation/types.h"
|
#include "ballistica/shared/foundation/types.h"
|
||||||
#include "ballistica/shared/generic/runnable.h"
|
#include "ballistica/shared/generic/runnable.h"
|
||||||
|
|
||||||
@ -29,14 +30,14 @@ auto CoreFeatureSet::Import(const CoreConfig* config) -> CoreFeatureSet* {
|
|||||||
"call.");
|
"call.");
|
||||||
}
|
}
|
||||||
if (g_core == nullptr) {
|
if (g_core == nullptr) {
|
||||||
DoImport(*config);
|
DoImport_(*config);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If no config is passed, use a default. If the user wants env vars
|
// If no config is passed, use a default. If the user wants env vars
|
||||||
// or anything else factored in, they should do so themselves in the
|
// or anything else factored in, they should do so themselves in the
|
||||||
// config they pass (CoreConfig::ForEnvVars(), etc.).
|
// config they pass (CoreConfig::ForEnvVars(), etc.).
|
||||||
if (g_core == nullptr) {
|
if (g_core == nullptr) {
|
||||||
DoImport({});
|
DoImport_({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -57,23 +58,23 @@ auto CoreFeatureSet::Import(const CoreConfig* config) -> CoreFeatureSet* {
|
|||||||
// between monolithic and modular.
|
// between monolithic and modular.
|
||||||
std::vector<std::string> argbuffer;
|
std::vector<std::string> argbuffer;
|
||||||
std::vector<char*> argv = CorePython::FetchPythonArgs(&argbuffer);
|
std::vector<char*> argv = CorePython::FetchPythonArgs(&argbuffer);
|
||||||
DoImport(CoreConfig::ForArgsAndEnvVars(static_cast<int>(argv.size()),
|
DoImport_(CoreConfig::ForArgsAndEnvVars(static_cast<int>(argv.size()),
|
||||||
argv.data()));
|
argv.data()));
|
||||||
} else {
|
} else {
|
||||||
// Not using Python sys args but we still want to process env vars.
|
// Not using Python sys args but we still want to process env vars.
|
||||||
DoImport(CoreConfig::ForEnvVars());
|
DoImport_(CoreConfig::ForEnvVars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return g_core;
|
return g_core;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFeatureSet::DoImport(const CoreConfig& config) {
|
void CoreFeatureSet::DoImport_(const CoreConfig& config) {
|
||||||
millisecs_t start_millisecs = CorePlatform::GetCurrentMillisecs();
|
millisecs_t start_millisecs = CorePlatform::GetCurrentMillisecs();
|
||||||
|
|
||||||
assert(g_core == nullptr);
|
assert(g_core == nullptr);
|
||||||
g_core = new CoreFeatureSet(config);
|
g_core = new CoreFeatureSet(config);
|
||||||
g_core->PostInit();
|
g_core->PostInit_();
|
||||||
|
|
||||||
// Slightly hacky: have to report our begin time after the fact since core
|
// Slightly hacky: have to report our begin time after the fact since core
|
||||||
// didn't exist before. Can at least add an offset to give an accurate
|
// didn't exist before. Can at least add an offset to give an accurate
|
||||||
@ -97,16 +98,16 @@ CoreFeatureSet::CoreFeatureSet(CoreConfig config)
|
|||||||
assert(g_core == nullptr);
|
assert(g_core == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFeatureSet::PostInit() {
|
void CoreFeatureSet::PostInit_() {
|
||||||
// Some of this stuff might access g_core so we run most of our init
|
// Some of this stuff might access g_core so we run most of our init
|
||||||
// *after* assigning our singleton to be safe.
|
// *after* assigning our singleton to be safe.
|
||||||
|
|
||||||
// Should migrate this to classic.
|
// Should migrate this to classic.
|
||||||
set_legacy_user_agent_string(platform->GetLegacyUserAgentString());
|
set_legacy_user_agent_string(platform->GetLegacyUserAgentString());
|
||||||
|
|
||||||
RunSanityChecks();
|
RunSanityChecks_();
|
||||||
|
|
||||||
build_src_dir_ = CalcBuildSrcDir();
|
build_src_dir_ = CalcBuildSrcDir_();
|
||||||
|
|
||||||
// On monolithic builds we need to bring up Python itself.
|
// On monolithic builds we need to bring up Python itself.
|
||||||
if (g_buildconfig.monolithic_build()) {
|
if (g_buildconfig.monolithic_build()) {
|
||||||
@ -119,13 +120,9 @@ void CoreFeatureSet::PostInit() {
|
|||||||
// Grab whatever Python stuff we use.
|
// Grab whatever Python stuff we use.
|
||||||
python->ImportPythonObjs();
|
python->ImportPythonObjs();
|
||||||
|
|
||||||
// Normally we wait until later to start pushing logs through to Python
|
// We grabbed all our log handles/etc. above, so we can start piping logs
|
||||||
// (so that our log handling system is fully bootstrapped), but
|
// through to Python now.
|
||||||
// technically we can push our log calls out to Python any time now since
|
python->EnablePythonLoggingCalls();
|
||||||
// we grabbed the logging calls above. Do so immediately here if asked.
|
|
||||||
if (!core_config_.hold_early_logs) {
|
|
||||||
python->EnablePythonLoggingCalls();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::core_config() const -> const CoreConfig& {
|
auto CoreFeatureSet::core_config() const -> const CoreConfig& {
|
||||||
@ -167,6 +164,16 @@ void CoreFeatureSet::ApplyBaEnvConfig() {
|
|||||||
ba_env_site_python_dir_ =
|
ba_env_site_python_dir_ =
|
||||||
envcfg.GetAttr("site_python_dir").ValueAsOptionalString();
|
envcfg.GetAttr("site_python_dir").ValueAsOptionalString();
|
||||||
|
|
||||||
|
ba_env_launch_timestamp_ = envcfg.GetAttr("launch_time").ValueAsDouble();
|
||||||
|
|
||||||
|
auto appcfg = envcfg.GetAttr("initial_app_config");
|
||||||
|
initial_app_config_ = appcfg.NewRef();
|
||||||
|
|
||||||
|
// This is also a reasonable time to grab initial logger levels that baenv
|
||||||
|
// likely mucked with. For any changes after this to make it to the native
|
||||||
|
// layer, babase.update_internal_logger_levels() must be called.
|
||||||
|
UpdateInternalLoggerLevels();
|
||||||
|
|
||||||
// Consider app-python-dir to be 'custom' if baenv provided a value for it
|
// Consider app-python-dir to be 'custom' if baenv provided a value for it
|
||||||
// AND that value differs from baenv's default.
|
// AND that value differs from baenv's default.
|
||||||
auto standard_app_python_dir =
|
auto standard_app_python_dir =
|
||||||
@ -183,6 +190,10 @@ void CoreFeatureSet::ApplyBaEnvConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CoreFeatureSet::UpdateInternalLoggerLevels() {
|
||||||
|
python->UpdateInternalLoggerLevels(log_levels_);
|
||||||
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::GetAppPythonDirectory() -> std::optional<std::string> {
|
auto CoreFeatureSet::GetAppPythonDirectory() -> std::optional<std::string> {
|
||||||
BA_PRECONDITION(have_ba_env_vals_);
|
BA_PRECONDITION(have_ba_env_vals_);
|
||||||
return ba_env_app_python_dir_;
|
return ba_env_app_python_dir_;
|
||||||
@ -209,7 +220,7 @@ auto CoreFeatureSet::GetSitePythonDirectory() -> std::optional<std::string> {
|
|||||||
return ba_env_site_python_dir_;
|
return ba_env_site_python_dir_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::CalcBuildSrcDir() -> std::string {
|
auto CoreFeatureSet::CalcBuildSrcDir_() -> std::string {
|
||||||
// Let's grab a string of the portion of __FILE__ before our project root.
|
// Let's grab a string of the portion of __FILE__ before our project root.
|
||||||
// We can use it to make error messages/etc. more pretty by stripping out
|
// We can use it to make error messages/etc. more pretty by stripping out
|
||||||
// all but sub-project paths.
|
// all but sub-project paths.
|
||||||
@ -217,14 +228,15 @@ auto CoreFeatureSet::CalcBuildSrcDir() -> std::string {
|
|||||||
auto* f_end = strstr(f, "src" BA_DIRSLASH "ballistica" BA_DIRSLASH
|
auto* f_end = strstr(f, "src" BA_DIRSLASH "ballistica" BA_DIRSLASH
|
||||||
"core" BA_DIRSLASH "core.cc");
|
"core" BA_DIRSLASH "core.cc");
|
||||||
if (!f_end) {
|
if (!f_end) {
|
||||||
Log(LogLevel::kWarning, "Unable to calc build source dir from __FILE__.");
|
Log(LogName::kBa, LogLevel::kWarning,
|
||||||
|
"Unable to calc build source dir from __FILE__.");
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
return std::string(f).substr(0, f_end - f);
|
return std::string(f).substr(0, f_end - f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFeatureSet::RunSanityChecks() {
|
void CoreFeatureSet::RunSanityChecks_() {
|
||||||
// Sanity check: make sure asserts are stripped out of release builds
|
// Sanity check: make sure asserts are stripped out of release builds
|
||||||
// (NDEBUG should do this).
|
// (NDEBUG should do this).
|
||||||
#if !BA_DEBUG_BUILD
|
#if !BA_DEBUG_BUILD
|
||||||
@ -267,11 +279,11 @@ void CoreFeatureSet::RunSanityChecks() {
|
|||||||
// from. Use this to adjust the filtering as necessary so the resulting
|
// from. Use this to adjust the filtering as necessary so the resulting
|
||||||
// type name matches what is expected.
|
// type name matches what is expected.
|
||||||
if (explicit_bool(false)) {
|
if (explicit_bool(false)) {
|
||||||
Log(LogLevel::kError, "static_type_name check; name is '"
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ static_type_name<decltype(g_core)>()
|
"static_type_name check; name is '"
|
||||||
+ "' debug_full is '"
|
+ static_type_name<decltype(g_core)>() + "' debug_full is '"
|
||||||
+ static_type_name<decltype(g_core)>(true) + "'");
|
+ static_type_name<decltype(g_core)>(true) + "'");
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"static_type_name check; name is '"
|
"static_type_name check; name is '"
|
||||||
+ static_type_name<decltype(testrunnable)>() + "' debug_full is '"
|
+ static_type_name<decltype(testrunnable)>() + "' debug_full is '"
|
||||||
+ static_type_name<decltype(testrunnable)>(true) + "'");
|
+ static_type_name<decltype(testrunnable)>(true) + "'");
|
||||||
@ -293,13 +305,16 @@ auto CoreFeatureSet::SoftImportBase() -> BaseSoftInterface* {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CoreFeatureSet::LifecycleLog(const char* msg, double offset_seconds) {
|
void CoreFeatureSet::LifecycleLog(const char* msg, double offset_seconds) {
|
||||||
if (!core_config_.lifecycle_log) {
|
// Early out to avoid work if we won't show anyway.
|
||||||
|
if (!LogLevelEnabled(LogName::kBaLifecycle, LogLevel::kDebug)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We include time-since-start as part of the message here.
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
snprintf(buffer, sizeof(buffer), "LIFE: %s @ %.3fs.", msg,
|
snprintf(buffer, sizeof(buffer), "%s @ %.3fs.", msg,
|
||||||
g_core->GetAppTimeSeconds() + offset_seconds);
|
g_core->GetAppTimeSeconds() + offset_seconds);
|
||||||
Log(LogLevel::kInfo, buffer);
|
Log(LogName::kBaLifecycle, LogLevel::kDebug, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::HeadlessMode() -> bool {
|
auto CoreFeatureSet::HeadlessMode() -> bool {
|
||||||
@ -308,29 +323,27 @@ auto CoreFeatureSet::HeadlessMode() -> bool {
|
|||||||
return g_buildconfig.headless_build();
|
return g_buildconfig.headless_build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto CoreFeatureSet::vr_mode() -> bool { return core_config_.vr_mode; }
|
|
||||||
|
|
||||||
static void WaitThenDie(millisecs_t wait, const std::string& action) {
|
static void WaitThenDie(millisecs_t wait, const std::string& action) {
|
||||||
CorePlatform::SleepMillisecs(wait);
|
CorePlatform::SleepMillisecs(wait);
|
||||||
FatalError("Timed out waiting for " + action + ".");
|
FatalError("Timed out waiting for " + action + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::GetAppTimeMillisecs() -> millisecs_t {
|
auto CoreFeatureSet::GetAppTimeMillisecs() -> millisecs_t {
|
||||||
UpdateAppTime();
|
UpdateAppTime_();
|
||||||
return app_time_microsecs_ / 1000;
|
return app_time_microsecs_ / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::GetAppTimeMicrosecs() -> microsecs_t {
|
auto CoreFeatureSet::GetAppTimeMicrosecs() -> microsecs_t {
|
||||||
UpdateAppTime();
|
UpdateAppTime_();
|
||||||
return app_time_microsecs_;
|
return app_time_microsecs_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::GetAppTimeSeconds() -> seconds_t {
|
auto CoreFeatureSet::GetAppTimeSeconds() -> seconds_t {
|
||||||
UpdateAppTime();
|
UpdateAppTime_();
|
||||||
return static_cast<seconds_t>(app_time_microsecs_) / 1000000;
|
return static_cast<seconds_t>(app_time_microsecs_) / 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFeatureSet::UpdateAppTime() {
|
void CoreFeatureSet::UpdateAppTime_() {
|
||||||
microsecs_t t = CorePlatform::GetCurrentMicrosecs();
|
microsecs_t t = CorePlatform::GetCurrentMicrosecs();
|
||||||
|
|
||||||
// If we're at a different time than our last query, do our funky math.
|
// If we're at a different time than our last query, do our funky math.
|
||||||
@ -356,15 +369,6 @@ void CoreFeatureSet::UpdateAppTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// void CoreFeatureSet::UpdateMainThreadID() {
|
|
||||||
// auto current_id = std::this_thread::get_id();
|
|
||||||
|
|
||||||
// // This gets called a lot and it may happen before we are spun up, so just
|
|
||||||
// // ignore it in that case.
|
|
||||||
// main_thread_id = current_id;
|
|
||||||
// main_event_loop_->set_thread_id(current_id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
void CoreFeatureSet::StartSuicideTimer(const std::string& action,
|
void CoreFeatureSet::StartSuicideTimer(const std::string& action,
|
||||||
millisecs_t delay) {
|
millisecs_t delay) {
|
||||||
if (!started_suicide_) {
|
if (!started_suicide_) {
|
||||||
@ -433,4 +437,14 @@ auto CoreFeatureSet::CurrentThreadName() -> std::string {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto CoreFeatureSet::HandOverInitialAppConfig() -> PyObject* {
|
||||||
|
BA_PRECONDITION(initial_app_config_);
|
||||||
|
|
||||||
|
// Don't decrement the refcount on the pointer we're holding; just clear
|
||||||
|
// and return it, effectively handing over the ref.
|
||||||
|
auto* out{initial_app_config_};
|
||||||
|
initial_app_config_ = nullptr;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ballistica::core
|
} // namespace ballistica::core
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
#ifndef BALLISTICA_CORE_CORE_H_
|
#ifndef BALLISTICA_CORE_CORE_H_
|
||||||
#define BALLISTICA_CORE_CORE_H_
|
#define BALLISTICA_CORE_CORE_H_
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -186,13 +185,36 @@ class CoreFeatureSet {
|
|||||||
void set_event_loops_suspended(bool val) { event_loops_suspended_ = val; }
|
void set_event_loops_suspended(bool val) { event_loops_suspended_ = val; }
|
||||||
static auto CurrentThreadName() -> std::string;
|
static auto CurrentThreadName() -> std::string;
|
||||||
|
|
||||||
|
auto HandOverInitialAppConfig() -> PyObject*;
|
||||||
|
|
||||||
|
/// Grab current Python logging levels for all logs we use internally. If
|
||||||
|
/// any changes are made at runtime to Python logging levels that we use,
|
||||||
|
/// this should be called after.
|
||||||
|
void UpdateInternalLoggerLevels();
|
||||||
|
|
||||||
|
/// Check whether a certain log name/level combo will be shown. It is much
|
||||||
|
/// more efficient to gate log calls using this (especially frequent or
|
||||||
|
/// debug ones) rather than letting the Python layer do the gating. Be
|
||||||
|
/// aware, however, that UpdateInternalLoggerLevels() must be called after
|
||||||
|
/// making any changes to Python logger levels to keep this internal
|
||||||
|
/// system up to date.
|
||||||
|
auto LogLevelEnabled(LogName name, LogLevel level) -> bool {
|
||||||
|
return log_levels_[static_cast<int>(name)] <= level;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ba_env_launch_timestamp() {
|
||||||
|
// Make sure we set this before accessing it.
|
||||||
|
assert(ba_env_launch_timestamp_ > 0.0);
|
||||||
|
return ba_env_launch_timestamp_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit CoreFeatureSet(CoreConfig config);
|
explicit CoreFeatureSet(CoreConfig config);
|
||||||
static void DoImport(const CoreConfig& config);
|
static void DoImport_(const CoreConfig& config);
|
||||||
static auto CalcBuildSrcDir() -> std::string;
|
static auto CalcBuildSrcDir_() -> std::string;
|
||||||
void RunSanityChecks();
|
void RunSanityChecks_();
|
||||||
void UpdateAppTime();
|
void UpdateAppTime_();
|
||||||
void PostInit();
|
void PostInit_();
|
||||||
|
|
||||||
// Note to self: don't use single bits for these as they may be owned by
|
// Note to self: don't use single bits for these as they may be owned by
|
||||||
// different threads.
|
// different threads.
|
||||||
@ -203,7 +225,9 @@ class CoreFeatureSet {
|
|||||||
bool vr_mode_{};
|
bool vr_mode_{};
|
||||||
bool using_custom_app_python_dir_{};
|
bool using_custom_app_python_dir_{};
|
||||||
bool engine_done_{};
|
bool engine_done_{};
|
||||||
|
LogLevel log_levels_[static_cast<int>(LogName::kLast)]{};
|
||||||
|
|
||||||
|
PyObject* initial_app_config_{};
|
||||||
std::thread::id main_thread_id_{};
|
std::thread::id main_thread_id_{};
|
||||||
CoreConfig core_config_;
|
CoreConfig core_config_;
|
||||||
std::string build_src_dir_;
|
std::string build_src_dir_;
|
||||||
@ -217,6 +241,7 @@ class CoreFeatureSet {
|
|||||||
std::optional<std::string> ba_env_user_python_dir_;
|
std::optional<std::string> ba_env_user_python_dir_;
|
||||||
std::optional<std::string> ba_env_site_python_dir_;
|
std::optional<std::string> ba_env_site_python_dir_;
|
||||||
std::string ba_env_data_dir_;
|
std::string ba_env_data_dir_;
|
||||||
|
double ba_env_launch_timestamp_{-1.0};
|
||||||
std::mutex thread_info_map_mutex_;
|
std::mutex thread_info_map_mutex_;
|
||||||
std::unordered_map<std::thread::id, std::string> thread_info_map_;
|
std::unordered_map<std::thread::id, std::string> thread_info_map_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -178,10 +178,10 @@ auto CorePlatform::GetLegacyDeviceUUID() -> const std::string& {
|
|||||||
if (FILE* f2 = FOpen(path.c_str(), "wb")) {
|
if (FILE* f2 = FOpen(path.c_str(), "wb")) {
|
||||||
size_t result = fwrite(val.c_str(), val.size(), 1, f2);
|
size_t result = fwrite(val.c_str(), val.size(), 1, f2);
|
||||||
if (result != 1)
|
if (result != 1)
|
||||||
Log(LogLevel::kError, "unable to write bsuuid file.");
|
Log(LogName::kBa, LogLevel::kError, "unable to write bsuuid file.");
|
||||||
fclose(f2);
|
fclose(f2);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"unable to open bsuuid file for writing: '" + path + "'");
|
"unable to open bsuuid file for writing: '" + path + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +192,8 @@ auto CorePlatform::GetLegacyDeviceUUID() -> const std::string& {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto CorePlatform::GetDeviceV1AccountUUIDPrefix() -> std::string {
|
auto CorePlatform::GetDeviceV1AccountUUIDPrefix() -> std::string {
|
||||||
Log(LogLevel::kError, "GetDeviceV1AccountUUIDPrefix() unimplemented");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"GetDeviceV1AccountUUIDPrefix() unimplemented");
|
||||||
return "u";
|
return "u";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,10 +249,12 @@ void CorePlatform::SetLowLevelConfigValue(const char* key, int value) {
|
|||||||
if (f) {
|
if (f) {
|
||||||
size_t result = fwrite(out.c_str(), out.size(), 1, f);
|
size_t result = fwrite(out.c_str(), out.size(), 1, f);
|
||||||
if (result != 1)
|
if (result != 1)
|
||||||
Log(LogLevel::kError, "unable to write low level config file.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"unable to write low level config file.");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "unable to open low level config file for writing.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"unable to open low level config file for writing.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +428,7 @@ auto CorePlatform::GetLocale() -> std::string {
|
|||||||
return lang;
|
return lang;
|
||||||
} else {
|
} else {
|
||||||
if (!g_buildconfig.headless_build()) {
|
if (!g_buildconfig.headless_build()) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kError,
|
||||||
"No LANG value available; defaulting to en_US");
|
"No LANG value available; defaulting to en_US");
|
||||||
}
|
}
|
||||||
return "en_US";
|
return "en_US";
|
||||||
@ -688,7 +691,7 @@ auto CorePlatform::ConvertIncomingLeaderboardScore(
|
|||||||
|
|
||||||
void CorePlatform::SubmitScore(const std::string& game,
|
void CorePlatform::SubmitScore(const std::string& game,
|
||||||
const std::string& version, int64_t score) {
|
const std::string& version, int64_t score) {
|
||||||
Log(LogLevel::kError, "FIXME: SubmitScore() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "FIXME: SubmitScore() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::ReportAchievement(const std::string& achievement) {}
|
void CorePlatform::ReportAchievement(const std::string& achievement) {}
|
||||||
@ -701,7 +704,8 @@ auto CorePlatform::HaveLeaderboard(const std::string& game,
|
|||||||
void CorePlatform::ShowGameServiceUI(const std::string& show,
|
void CorePlatform::ShowGameServiceUI(const std::string& show,
|
||||||
const std::string& game,
|
const std::string& game,
|
||||||
const std::string& game_version) {
|
const std::string& game_version) {
|
||||||
Log(LogLevel::kError, "FIXME: ShowGameServiceUI() unimplemented");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"FIXME: ShowGameServiceUI() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::AndroidSetResString(const std::string& res) {
|
void CorePlatform::AndroidSetResString(const std::string& res) {
|
||||||
@ -729,7 +733,7 @@ auto CorePlatform::DemangleCXXSymbol(const std::string& s) -> std::string {
|
|||||||
abi::__cxa_demangle(s.c_str(), nullptr, nullptr, &demangle_status);
|
abi::__cxa_demangle(s.c_str(), nullptr, nullptr, &demangle_status);
|
||||||
if (demangled_name != nullptr) {
|
if (demangled_name != nullptr) {
|
||||||
if (demangle_status != 0) {
|
if (demangle_status != 0) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBa, LogLevel::kError,
|
||||||
"__cxa_demangle got buffer but non-zero status; unexpected");
|
"__cxa_demangle got buffer but non-zero status; unexpected");
|
||||||
}
|
}
|
||||||
std::string retval = demangled_name;
|
std::string retval = demangled_name;
|
||||||
@ -744,25 +748,28 @@ auto CorePlatform::DemangleCXXSymbol(const std::string& s) -> std::string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::ResetAchievements() {
|
void CorePlatform::ResetAchievements() {
|
||||||
Log(LogLevel::kError, "ResetAchievements() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "ResetAchievements() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::RunEvents() {}
|
void CorePlatform::RunEvents() {}
|
||||||
|
|
||||||
void CorePlatform::MusicPlayerPlay(PyObject* target) {
|
void CorePlatform::MusicPlayerPlay(PyObject* target) {
|
||||||
Log(LogLevel::kError, "MusicPlayerPlay() unimplemented on this platform");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"MusicPlayerPlay() unimplemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::MusicPlayerStop() {
|
void CorePlatform::MusicPlayerStop() {
|
||||||
Log(LogLevel::kError, "MusicPlayerStop() unimplemented on this platform");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"MusicPlayerStop() unimplemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::MusicPlayerShutdown() {
|
void CorePlatform::MusicPlayerShutdown() {
|
||||||
Log(LogLevel::kError, "MusicPlayerShutdown() unimplemented on this platform");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"MusicPlayerShutdown() unimplemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::MusicPlayerSetVolume(float volume) {
|
void CorePlatform::MusicPlayerSetVolume(float volume) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"MusicPlayerSetVolume() unimplemented on this platform");
|
"MusicPlayerSetVolume() unimplemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,7 +792,7 @@ void CorePlatform::SubmitAnalyticsCounts() {}
|
|||||||
void CorePlatform::SetPlatformMiscReadVals(const std::string& vals) {}
|
void CorePlatform::SetPlatformMiscReadVals(const std::string& vals) {}
|
||||||
|
|
||||||
void CorePlatform::ShowAd(const std::string& purpose) {
|
void CorePlatform::ShowAd(const std::string& purpose) {
|
||||||
Log(LogLevel::kError, "ShowAd() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "ShowAd() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CorePlatform::GetHasAds() -> bool { return false; }
|
auto CorePlatform::GetHasAds() -> bool { return false; }
|
||||||
@ -796,7 +803,7 @@ auto CorePlatform::GetHasVideoAds() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::SignInV1(const std::string& account_type) {
|
void CorePlatform::SignInV1(const std::string& account_type) {
|
||||||
Log(LogLevel::kError, "SignInV1() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "SignInV1() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::V1LoginDidChange() {
|
void CorePlatform::V1LoginDidChange() {
|
||||||
@ -804,33 +811,35 @@ void CorePlatform::V1LoginDidChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::SignOutV1() {
|
void CorePlatform::SignOutV1() {
|
||||||
Log(LogLevel::kError, "SignOutV1() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "SignOutV1() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::MacMusicAppInit() {
|
void CorePlatform::MacMusicAppInit() {
|
||||||
Log(LogLevel::kError, "MacMusicAppInit() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "MacMusicAppInit() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CorePlatform::MacMusicAppGetVolume() -> int {
|
auto CorePlatform::MacMusicAppGetVolume() -> int {
|
||||||
Log(LogLevel::kError, "MacMusicAppGetVolume() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "MacMusicAppGetVolume() unimplemented");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::MacMusicAppSetVolume(int volume) {
|
void CorePlatform::MacMusicAppSetVolume(int volume) {
|
||||||
Log(LogLevel::kError, "MacMusicAppSetVolume() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "MacMusicAppSetVolume() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::MacMusicAppStop() {
|
void CorePlatform::MacMusicAppStop() {
|
||||||
Log(LogLevel::kError, "MacMusicAppStop() unimplemented");
|
Log(LogName::kBa, LogLevel::kError, "MacMusicAppStop() unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CorePlatform::MacMusicAppPlayPlaylist(const std::string& playlist)
|
auto CorePlatform::MacMusicAppPlayPlaylist(const std::string& playlist)
|
||||||
-> bool {
|
-> bool {
|
||||||
Log(LogLevel::kError, "MacMusicAppPlayPlaylist() unimplemented");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"MacMusicAppPlayPlaylist() unimplemented");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto CorePlatform::MacMusicAppGetPlaylists() -> std::list<std::string> {
|
auto CorePlatform::MacMusicAppGetPlaylists() -> std::list<std::string> {
|
||||||
Log(LogLevel::kError, "MacMusicAppGetPlaylists() unimplemented");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"MacMusicAppGetPlaylists() unimplemented");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,8 +944,9 @@ auto CorePlatform::SetSocketNonBlocking(int sd) -> bool {
|
|||||||
#else
|
#else
|
||||||
int result = fcntl(sd, F_SETFL, O_NONBLOCK);
|
int result = fcntl(sd, F_SETFL, O_NONBLOCK);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
Log(LogLevel::kError, "Error setting non-blocking socket: "
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Error setting non-blocking socket: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1069,6 +1079,12 @@ auto CorePlatform::GetCurrentMicrosecs() -> millisecs_t {
|
|||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto CorePlatform::GetSecondsSinceEpoch() -> double {
|
||||||
|
return std::chrono::duration<double>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
auto CorePlatform::GetCurrentWholeSeconds() -> int64_t {
|
auto CorePlatform::GetCurrentWholeSeconds() -> int64_t {
|
||||||
return std::chrono::time_point_cast<std::chrono::seconds>(
|
return std::chrono::time_point_cast<std::chrono::seconds>(
|
||||||
std::chrono::steady_clock::now())
|
std::chrono::steady_clock::now())
|
||||||
|
|||||||
@ -369,6 +369,9 @@ class CorePlatform {
|
|||||||
/// to not go backwards.
|
/// to not go backwards.
|
||||||
static auto GetCurrentWholeSeconds() -> int64_t;
|
static auto GetCurrentWholeSeconds() -> int64_t;
|
||||||
|
|
||||||
|
/// Return seconds since the epoch; same as Python's time.time().
|
||||||
|
static auto GetSecondsSinceEpoch() -> double;
|
||||||
|
|
||||||
static void SleepSeconds(seconds_t duration);
|
static void SleepSeconds(seconds_t duration);
|
||||||
static void SleepMillisecs(millisecs_t duration);
|
static void SleepMillisecs(millisecs_t duration);
|
||||||
static void SleepMicrosecs(microsecs_t duration);
|
static void SleepMicrosecs(microsecs_t duration);
|
||||||
|
|||||||
@ -919,7 +919,8 @@ auto CorePlatformWindows::GetEnv(const std::string& name)
|
|||||||
|
|
||||||
// This should always succeed at this point; make noise if not.
|
// This should always succeed at this point; make noise if not.
|
||||||
if (result == 0 || result > big_buffer.size()) {
|
if (result == 0 || result > big_buffer.size()) {
|
||||||
Log(LogLevel::kError, "GetEnv to allocated buffer failed; unexpected.");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"GetEnv to allocated buffer failed; unexpected.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return UTF8Encode(big_buffer.data());
|
return UTF8Encode(big_buffer.data());
|
||||||
@ -997,14 +998,15 @@ std::vector<uint32_t> CorePlatformWindows::GetBroadcastAddrs() {
|
|||||||
pIPAddrTable = static_cast<MIB_IPADDRTABLE*>(MALLOC(dwSize));
|
pIPAddrTable = static_cast<MIB_IPADDRTABLE*>(MALLOC(dwSize));
|
||||||
}
|
}
|
||||||
if (pIPAddrTable == nullptr) {
|
if (pIPAddrTable == nullptr) {
|
||||||
Log(LogLevel::kError, "Memory allocation failed for GetIpAddrTable\n");
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
|
"Memory allocation failed for GetIpAddrTable\n");
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
// Make a second call to GetIpAddrTable to get the actual data we want
|
// Make a second call to GetIpAddrTable to get the actual data we want
|
||||||
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
|
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"GetIpAddrTable failed with error " + std::to_string(dwRetVal));
|
"GetIpAddrTable failed with error " + std::to_string(dwRetVal));
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
@ -1040,8 +1042,9 @@ bool CorePlatformWindows::SetSocketNonBlocking(int sd) {
|
|||||||
unsigned long dataval = 1; // NOLINT (func signature wants long)
|
unsigned long dataval = 1; // NOLINT (func signature wants long)
|
||||||
int result = ioctlsocket(sd, FIONBIO, &dataval);
|
int result = ioctlsocket(sd, FIONBIO, &dataval);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
Log(LogLevel::kError, "Error setting non-blocking socket: "
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
+ g_core->platform->GetSocketErrorString());
|
"Error setting non-blocking socket: "
|
||||||
|
+ g_core->platform->GetSocketErrorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ballistica/core/mgen/python_modules_monolithic.h"
|
#include "ballistica/core/mgen/python_modules_monolithic.h"
|
||||||
#include "ballistica/core/platform/core_platform.h"
|
#include "ballistica/core/platform/core_platform.h"
|
||||||
|
#include "ballistica/shared/foundation/macros.h"
|
||||||
#include "ballistica/shared/python/python.h"
|
#include "ballistica/shared/python/python.h"
|
||||||
#include "ballistica/shared/python/python_command.h"
|
#include "ballistica/shared/python/python_command.h"
|
||||||
|
|
||||||
@ -174,18 +176,38 @@ void CorePython::EnablePythonLoggingCalls() {
|
|||||||
}
|
}
|
||||||
auto gil{Python::ScopedInterpreterLock()};
|
auto gil{Python::ScopedInterpreterLock()};
|
||||||
|
|
||||||
assert(objs().Exists(ObjID::kLoggingDebugCall));
|
// Make sure we've got all our logging Python bits we need.
|
||||||
assert(objs().Exists(ObjID::kLoggingInfoCall));
|
assert(objs().Exists(ObjID::kLoggingLevelDebug));
|
||||||
assert(objs().Exists(ObjID::kLoggingWarningCall));
|
assert(objs().Exists(ObjID::kLoggingLevelInfo));
|
||||||
assert(objs().Exists(ObjID::kLoggingErrorCall));
|
assert(objs().Exists(ObjID::kLoggingLevelWarning));
|
||||||
assert(objs().Exists(ObjID::kLoggingCriticalCall));
|
assert(objs().Exists(ObjID::kLoggingLevelError));
|
||||||
|
assert(objs().Exists(ObjID::kLoggingLevelCritical));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerRoot));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerRootLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBa));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaAccount));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaAccountLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaAudio));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaAudioLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaGraphics));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaGraphicsLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaLifecycle));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaLifecycleLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaAssets));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaAssetsLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaInput));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaInputLogCall));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaNetworking));
|
||||||
|
assert(objs().Exists(ObjID::kLoggerBaNetworkingLogCall));
|
||||||
|
|
||||||
// Push any early log calls we've been holding on to along to Python.
|
// Push any early log calls we've been holding on to along to Python.
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(early_log_lock_);
|
std::scoped_lock lock(early_log_lock_);
|
||||||
python_logging_calls_enabled_ = true;
|
python_logging_calls_enabled_ = true;
|
||||||
for (auto&& entry : early_logs_) {
|
for (auto&& entry : early_logs_) {
|
||||||
LoggingCall(entry.first, "[HELD] " + entry.second);
|
LoggingCall(std::get<0>(entry), std::get<1>(entry),
|
||||||
|
"[HELD] " + std::get<2>(entry));
|
||||||
}
|
}
|
||||||
early_logs_.clear();
|
early_logs_.clear();
|
||||||
}
|
}
|
||||||
@ -214,6 +236,72 @@ void CorePython::ImportPythonObjs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CorePython::UpdateInternalLoggerLevels(LogLevel* log_levels) {
|
||||||
|
assert(python_logging_calls_enabled_);
|
||||||
|
assert(Python::HaveGIL());
|
||||||
|
|
||||||
|
const int log_level_debug{10};
|
||||||
|
const int log_level_info{20};
|
||||||
|
const int log_level_warning{30};
|
||||||
|
const int log_level_error{40};
|
||||||
|
const int log_level_critical{50};
|
||||||
|
assert(log_level_debug == objs().Get(ObjID::kLoggingLevelDebug).ValueAsInt());
|
||||||
|
assert(log_level_info == objs().Get(ObjID::kLoggingLevelInfo).ValueAsInt());
|
||||||
|
assert(log_level_warning
|
||||||
|
== objs().Get(ObjID::kLoggingLevelWarning).ValueAsInt());
|
||||||
|
assert(log_level_error == objs().Get(ObjID::kLoggingLevelError).ValueAsInt());
|
||||||
|
assert(log_level_critical
|
||||||
|
== objs().Get(ObjID::kLoggingLevelCritical).ValueAsInt());
|
||||||
|
|
||||||
|
std::pair<LogName, ObjID> pairs[] = {
|
||||||
|
{LogName::kRoot, ObjID::kLoggerRoot},
|
||||||
|
{LogName::kBa, ObjID::kLoggerBa},
|
||||||
|
{LogName::kBaAccount, ObjID::kLoggerBaAccount},
|
||||||
|
{LogName::kBaAudio, ObjID::kLoggerBaAudio},
|
||||||
|
{LogName::kBaGraphics, ObjID::kLoggerBaGraphics},
|
||||||
|
{LogName::kBaLifecycle, ObjID::kLoggerBaLifecycle},
|
||||||
|
{LogName::kBaAssets, ObjID::kLoggerBaAssets},
|
||||||
|
{LogName::kBaInput, ObjID::kLoggerBaInput},
|
||||||
|
{LogName::kBaNetworking, ObjID::kLoggerBaNetworking},
|
||||||
|
};
|
||||||
|
|
||||||
|
int count{};
|
||||||
|
for (const auto& pair : pairs) {
|
||||||
|
count++;
|
||||||
|
auto logname{pair.first};
|
||||||
|
auto objid{pair.second};
|
||||||
|
auto out{objs().Get(objid).GetAttr("getEffectiveLevel").Call()};
|
||||||
|
assert(out.Exists());
|
||||||
|
auto outval{static_cast<int>(out.ValueAsInt())};
|
||||||
|
|
||||||
|
switch (outval) {
|
||||||
|
case log_level_debug:
|
||||||
|
log_levels[static_cast<int>(logname)] = LogLevel::kDebug;
|
||||||
|
break;
|
||||||
|
case log_level_info:
|
||||||
|
log_levels[static_cast<int>(logname)] = LogLevel::kInfo;
|
||||||
|
break;
|
||||||
|
case log_level_warning:
|
||||||
|
log_levels[static_cast<int>(logname)] = LogLevel::kWarning;
|
||||||
|
break;
|
||||||
|
case log_level_error:
|
||||||
|
log_levels[static_cast<int>(logname)] = LogLevel::kError;
|
||||||
|
break;
|
||||||
|
case log_level_critical:
|
||||||
|
log_levels[static_cast<int>(logname)] = LogLevel::kCritical;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Found unexpected resolved logging level %d\n", outval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sanity check: Make sure we covered our full set of LogNames.
|
||||||
|
if (count != static_cast<int>(LogName::kLast)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"WARNING: UpdateInternalLoggerLevels does not seem to be covering "
|
||||||
|
"all log names.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CorePython::SoftImportBase() {
|
void CorePython::SoftImportBase() {
|
||||||
auto gil{Python::ScopedInterpreterLock()};
|
auto gil{Python::ScopedInterpreterLock()};
|
||||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_babase"));
|
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_babase"));
|
||||||
@ -296,23 +384,25 @@ void CorePython::MonolithicModeBaEnvConfigure() {
|
|||||||
g_core->LifecycleLog("baenv.configure() end");
|
g_core->LifecycleLog("baenv.configure() end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) {
|
void CorePython::LoggingCall(LogName logname, LogLevel loglevel,
|
||||||
// If we're not yet sending logs to Python, store this one away until we are.
|
const std::string& msg) {
|
||||||
|
// If we're not yet sending logs to Python, store this one away until we
|
||||||
|
// are.
|
||||||
if (!python_logging_calls_enabled_) {
|
if (!python_logging_calls_enabled_) {
|
||||||
std::scoped_lock lock(early_log_lock_);
|
std::scoped_lock lock(early_log_lock_);
|
||||||
early_logs_.emplace_back(loglevel, msg);
|
early_logs_.emplace_back(logname, loglevel, msg);
|
||||||
|
|
||||||
// UPDATE - trying to disable this for now to make the concept of delayed
|
// UPDATE - trying to disable this for now to make the concept of
|
||||||
// logs a bit less scary. Perhaps we can update fatal-error to dump these or
|
// delayed logs a bit less scary. Perhaps we can update fatal-error to
|
||||||
// have a mode to immediate-print them as needed.
|
// dump these or have a mode to immediate-print them as needed.
|
||||||
if (explicit_bool(false)) {
|
if (explicit_bool(false)) {
|
||||||
// There's a chance that we're going down in flames and this log
|
// There's a chance that we're going down in flames and this log might
|
||||||
// might be useful to see even if we never get a chance to chip it to
|
// be useful to see even if we never get a chance to chip it to
|
||||||
// Python. So let's make an attempt to get it at least seen now in
|
// Python. So let's make an attempt to get it at least seen now in
|
||||||
// whatever way we can. (platform display-log call and stderr).
|
// whatever way we can. (platform display-log call and stderr).
|
||||||
const char* errmsg{
|
const char* errmsg{
|
||||||
"CorePython::LoggingCall() called before Python"
|
"CorePython::LoggingCall() called before Python logging "
|
||||||
" logging available."};
|
"available."};
|
||||||
if (g_core->platform) {
|
if (g_core->platform) {
|
||||||
g_core->platform->EmitPlatformLog("root", LogLevel::kError, errmsg);
|
g_core->platform->EmitPlatformLog("root", LogLevel::kError, errmsg);
|
||||||
g_core->platform->EmitPlatformLog("root", loglevel, msg);
|
g_core->platform->EmitPlatformLog("root", loglevel, msg);
|
||||||
@ -322,42 +412,93 @@ void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok; seems we've got Python calls. Run the right one for our log level.
|
|
||||||
ObjID logcallobj;
|
|
||||||
switch (loglevel) {
|
|
||||||
case LogLevel::kDebug:
|
|
||||||
logcallobj = ObjID::kLoggingDebugCall;
|
|
||||||
break;
|
|
||||||
case LogLevel::kInfo:
|
|
||||||
logcallobj = ObjID::kLoggingInfoCall;
|
|
||||||
break;
|
|
||||||
case LogLevel::kWarning:
|
|
||||||
logcallobj = ObjID::kLoggingWarningCall;
|
|
||||||
break;
|
|
||||||
case LogLevel::kError:
|
|
||||||
logcallobj = ObjID::kLoggingErrorCall;
|
|
||||||
break;
|
|
||||||
case LogLevel::kCritical:
|
|
||||||
logcallobj = ObjID::kLoggingCriticalCall;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logcallobj = ObjID::kLoggingInfoCall;
|
|
||||||
fprintf(stderr, "Unexpected LogLevel %d\n", static_cast<int>(loglevel));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we're good to go from any thread.
|
// Make sure we're good to go from any thread.
|
||||||
Python::ScopedInterpreterLock lock;
|
Python::ScopedInterpreterLock lock;
|
||||||
|
|
||||||
PythonRef args(Py_BuildValue("(s)", msg.c_str()), PythonRef::kSteal);
|
ObjID logcallobj;
|
||||||
|
bool handled{};
|
||||||
|
switch (logname) {
|
||||||
|
case LogName::kRoot:
|
||||||
|
logcallobj = ObjID::kLoggerRootLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBa:
|
||||||
|
logcallobj = ObjID::kLoggerBaLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaAccount:
|
||||||
|
logcallobj = ObjID::kLoggerBaAccountLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaAudio:
|
||||||
|
logcallobj = ObjID::kLoggerBaAudioLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaGraphics:
|
||||||
|
logcallobj = ObjID::kLoggerBaGraphicsLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaAssets:
|
||||||
|
logcallobj = ObjID::kLoggerBaAssetsLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaInput:
|
||||||
|
logcallobj = ObjID::kLoggerBaInputLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaNetworking:
|
||||||
|
logcallobj = ObjID::kLoggerBaNetworkingLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kBaLifecycle:
|
||||||
|
logcallobj = ObjID::kLoggerBaLifecycleLogCall;
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case LogName::kLast:
|
||||||
|
logcallobj = ObjID::kLoggerRootLogCall;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Handle this here instead of via default clause so we get warnings about
|
||||||
|
// new unhandled enum values.
|
||||||
|
if (!handled) {
|
||||||
|
logcallobj = ObjID::kLoggerRootLogCall;
|
||||||
|
fprintf(stderr, "Unexpected LogName %d\n", static_cast<int>(logname));
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjID loglevelobjid;
|
||||||
|
switch (loglevel) {
|
||||||
|
case LogLevel::kDebug:
|
||||||
|
loglevelobjid = ObjID::kLoggingLevelDebug;
|
||||||
|
break;
|
||||||
|
case LogLevel::kInfo:
|
||||||
|
loglevelobjid = ObjID::kLoggingLevelInfo;
|
||||||
|
break;
|
||||||
|
case LogLevel::kWarning:
|
||||||
|
loglevelobjid = ObjID::kLoggingLevelWarning;
|
||||||
|
break;
|
||||||
|
case LogLevel::kError:
|
||||||
|
loglevelobjid = ObjID::kLoggingLevelError;
|
||||||
|
break;
|
||||||
|
case LogLevel::kCritical:
|
||||||
|
loglevelobjid = ObjID::kLoggingLevelCritical;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
loglevelobjid = ObjID::kLoggingLevelInfo;
|
||||||
|
fprintf(stderr, "Unexpected LogLevel %d\n", static_cast<int>(loglevel));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PythonRef args(
|
||||||
|
Py_BuildValue("(Os)", objs().Get(loglevelobjid).Get(), msg.c_str()),
|
||||||
|
PythonRef::kSteal);
|
||||||
objs().Get(logcallobj).Call(args);
|
objs().Get(logcallobj).Call(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CorePython::WasModularMainCalled() -> bool {
|
auto CorePython::WasModularMainCalled() -> bool {
|
||||||
assert(!g_buildconfig.monolithic_build());
|
assert(!g_buildconfig.monolithic_build());
|
||||||
|
|
||||||
// This gets called in modular builds before anything is inited, so we need to
|
// This gets called in modular builds before anything is inited, so we need
|
||||||
// avoid using anything from g_core or whatnot here; only raw Python stuff.
|
// to avoid using anything from g_core or whatnot here; only raw Python
|
||||||
|
// stuff.
|
||||||
|
|
||||||
PyObject* baenv = PyImport_ImportModule("baenv");
|
PyObject* baenv = PyImport_ImportModule("baenv");
|
||||||
if (!baenv) {
|
if (!baenv) {
|
||||||
@ -394,8 +535,9 @@ auto CorePython::WasModularMainCalled() -> bool {
|
|||||||
|
|
||||||
auto CorePython::FetchPythonArgs(std::vector<std::string>* buffer)
|
auto CorePython::FetchPythonArgs(std::vector<std::string>* buffer)
|
||||||
-> std::vector<char*> {
|
-> std::vector<char*> {
|
||||||
// This gets called in modular builds before anything is inited, so we need to
|
// This gets called in modular builds before anything is inited, so we need
|
||||||
// avoid using anything from g_core or whatnot here; only raw Python stuff.
|
// to avoid using anything from g_core or whatnot here; only raw Python
|
||||||
|
// stuff.
|
||||||
|
|
||||||
assert(buffer && buffer->empty());
|
assert(buffer && buffer->empty());
|
||||||
PyObject* sys = PyImport_ImportModule("sys");
|
PyObject* sys = PyImport_ImportModule("sys");
|
||||||
|
|||||||
@ -24,11 +24,29 @@ class CorePython {
|
|||||||
kJsonDumpsCall,
|
kJsonDumpsCall,
|
||||||
kJsonLoadsCall,
|
kJsonLoadsCall,
|
||||||
kEmptyTuple,
|
kEmptyTuple,
|
||||||
kLoggingDebugCall,
|
kLoggingLevelDebug,
|
||||||
kLoggingInfoCall,
|
kLoggingLevelInfo,
|
||||||
kLoggingWarningCall,
|
kLoggingLevelWarning,
|
||||||
kLoggingErrorCall,
|
kLoggingLevelError,
|
||||||
kLoggingCriticalCall,
|
kLoggingLevelCritical,
|
||||||
|
kLoggerRoot,
|
||||||
|
kLoggerRootLogCall,
|
||||||
|
kLoggerBa,
|
||||||
|
kLoggerBaLogCall,
|
||||||
|
kLoggerBaAccount,
|
||||||
|
kLoggerBaAccountLogCall,
|
||||||
|
kLoggerBaAudio,
|
||||||
|
kLoggerBaAudioLogCall,
|
||||||
|
kLoggerBaGraphics,
|
||||||
|
kLoggerBaGraphicsLogCall,
|
||||||
|
kLoggerBaLifecycle,
|
||||||
|
kLoggerBaLifecycleLogCall,
|
||||||
|
kLoggerBaAssets,
|
||||||
|
kLoggerBaAssetsLogCall,
|
||||||
|
kLoggerBaInput,
|
||||||
|
kLoggerBaInputLogCall,
|
||||||
|
kLoggerBaNetworking,
|
||||||
|
kLoggerBaNetworkingLogCall,
|
||||||
kPrependSysPathCall,
|
kPrependSysPathCall,
|
||||||
kBaEnvConfigureCall,
|
kBaEnvConfigureCall,
|
||||||
kBaEnvGetConfigCall,
|
kBaEnvGetConfigCall,
|
||||||
@ -49,10 +67,11 @@ class CorePython {
|
|||||||
/// Can be called from any thread at any time. If called before Python
|
/// Can be called from any thread at any time. If called before Python
|
||||||
/// logging is available, logs locally using Logging::EmitPlatformLog()
|
/// logging is available, logs locally using Logging::EmitPlatformLog()
|
||||||
/// (with an added warning).
|
/// (with an added warning).
|
||||||
void LoggingCall(LogLevel loglevel, const std::string& msg);
|
void LoggingCall(LogName logname, LogLevel loglevel, const std::string& msg);
|
||||||
void ImportPythonObjs();
|
void ImportPythonObjs();
|
||||||
void VerifyPythonEnvironment();
|
void VerifyPythonEnvironment();
|
||||||
void SoftImportBase();
|
void SoftImportBase();
|
||||||
|
void UpdateInternalLoggerLevels(LogLevel* log_levels);
|
||||||
|
|
||||||
static auto WasModularMainCalled() -> bool;
|
static auto WasModularMainCalled() -> bool;
|
||||||
|
|
||||||
@ -70,7 +89,7 @@ class CorePython {
|
|||||||
// go here. They all get shipped at once as soon as it is possible.
|
// go here. They all get shipped at once as soon as it is possible.
|
||||||
bool python_logging_calls_enabled_{};
|
bool python_logging_calls_enabled_{};
|
||||||
std::mutex early_log_lock_;
|
std::mutex early_log_lock_;
|
||||||
std::list<std::pair<LogLevel, std::string>> early_logs_;
|
std::list<std::tuple<LogName, LogLevel, std::string>> early_logs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica::core
|
} // namespace ballistica::core
|
||||||
|
|||||||
@ -33,7 +33,8 @@ class BaseSoftInterface {
|
|||||||
virtual auto FeatureSetFromData(PyObject* obj)
|
virtual auto FeatureSetFromData(PyObject* obj)
|
||||||
-> FeatureSetNativeComponent* = 0;
|
-> FeatureSetNativeComponent* = 0;
|
||||||
virtual void DoV1CloudLog(const std::string& msg) = 0;
|
virtual void DoV1CloudLog(const std::string& msg) = 0;
|
||||||
virtual void PushDevConsolePrintCall(const std::string& msg) = 0;
|
virtual void PushDevConsolePrintCall(const std::string& msg, float scale,
|
||||||
|
Vector4f color) = 0;
|
||||||
virtual auto GetPyExceptionType(PyExcType exctype) -> PyObject* = 0;
|
virtual auto GetPyExceptionType(PyExcType exctype) -> PyObject* = 0;
|
||||||
virtual auto PrintPythonStackTrace() -> bool = 0;
|
virtual auto PrintPythonStackTrace() -> bool = 0;
|
||||||
virtual auto GetPyLString(PyObject* obj) -> std::string = 0;
|
virtual auto GetPyLString(PyObject* obj) -> std::string = 0;
|
||||||
|
|||||||
@ -78,11 +78,15 @@ static auto ParseArgValue(int argc, char** argv, int* i, const char* arg_long,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::ApplyEnvVars() {
|
void CoreConfig::ApplyEnvVars() {
|
||||||
if (auto* envval = getenv("BA_LIFECYCLE_LOG")) {
|
// TODO(ericf): This is now simply a log level. If we want to allow
|
||||||
if (!strcmp(envval, "1")) {
|
// controlling log-levels via env-vars we should come up with a unified
|
||||||
lifecycle_log = true;
|
// system for that.
|
||||||
}
|
|
||||||
}
|
// if (auto* envval = getenv("BA_LIFECYCLE_LOG")) {
|
||||||
|
// if (!strcmp(envval, "1")) {
|
||||||
|
// lifecycle_log = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
if (auto* envval = getenv("BA_DEBUGGER_ATTACHED")) {
|
if (auto* envval = getenv("BA_DEBUGGER_ATTACHED")) {
|
||||||
if (!strcmp(envval, "1")) {
|
if (!strcmp(envval, "1")) {
|
||||||
debugger_attached = true;
|
debugger_attached = true;
|
||||||
|
|||||||
@ -30,14 +30,7 @@ class CoreConfig {
|
|||||||
bool vr_mode{};
|
bool vr_mode{};
|
||||||
|
|
||||||
/// Log various stages/times in the bootstrapping process.
|
/// Log various stages/times in the bootstrapping process.
|
||||||
bool lifecycle_log{};
|
// bool lifecycle_log{};
|
||||||
|
|
||||||
/// Normally early C++ Log() calls are held until babase has been imported
|
|
||||||
/// so that when they are pushed out to the Python logging calls they are
|
|
||||||
/// properly routed through the full engine. If you are not using babase
|
|
||||||
/// or are trying to debug early issues you can flip this off to push
|
|
||||||
/// things to Python as soon as technically possible.
|
|
||||||
bool hold_early_logs{true};
|
|
||||||
|
|
||||||
/// Let the engine know there's a debugger attached so it should do things
|
/// Let the engine know there's a debugger attached so it should do things
|
||||||
/// like abort() instead of exiting with error codes.
|
/// like abort() instead of exiting with error codes.
|
||||||
|
|||||||
@ -156,7 +156,7 @@ void Connection::HandleGamePacketCompressed(const std::vector<uint8_t>& data) {
|
|||||||
try {
|
try {
|
||||||
data_decompressed = g_base->huffman->decompress(data);
|
data_decompressed = g_base->huffman->decompress(data);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
std::string("Error in huffman decompression for packet: ") + e.what());
|
std::string("Error in huffman decompression for packet: ") + e.what());
|
||||||
|
|
||||||
// Hmmm i guess lets just ignore this packet and keep on trucking?.. or
|
// Hmmm i guess lets just ignore this packet and keep on trucking?.. or
|
||||||
@ -176,7 +176,7 @@ void Connection::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
switch (data[0]) {
|
switch (data[0]) {
|
||||||
case BA_SCENEPACKET_KEEPALIVE: {
|
case BA_SCENEPACKET_KEEPALIVE: {
|
||||||
if (data.size() != 4) {
|
if (data.size() != 4) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Error: got invalid BA_SCENEPACKET_KEEPALIVE packet.");
|
"Error: got invalid BA_SCENEPACKET_KEEPALIVE packet.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -190,7 +190,8 @@ void Connection::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
|
|
||||||
// Expect 1 byte type, 2 byte num, 3 byte acks, at least 1 byte payload.
|
// Expect 1 byte type, 2 byte num, 3 byte acks, at least 1 byte payload.
|
||||||
if (data.size() < 7) {
|
if (data.size() < 7) {
|
||||||
Log(LogLevel::kError, "Got invalid BA_PACKET_STATE packet.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Got invalid BA_PACKET_STATE packet.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint16_t num;
|
uint16_t num;
|
||||||
@ -221,7 +222,8 @@ void Connection::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
// Expect 1 byte type, 2 byte num, 2 byte unreliable-num, 3 byte acks,
|
// Expect 1 byte type, 2 byte num, 2 byte unreliable-num, 3 byte acks,
|
||||||
// at least 1 byte payload.
|
// at least 1 byte payload.
|
||||||
if (data.size() < 9) {
|
if (data.size() < 9) {
|
||||||
Log(LogLevel::kError, "Got invalid BA_PACKET_STATE_UNRELIABLE packet.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Got invalid BA_PACKET_STATE_UNRELIABLE packet.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint16_t num, num_unreliable;
|
uint16_t num, num_unreliable;
|
||||||
@ -242,8 +244,9 @@ void Connection::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::kError, "Connection got unknown packet type: "
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ std::to_string(static_cast<int>(data[0])));
|
"Connection got unknown packet type: "
|
||||||
|
+ std::to_string(static_cast<int>(data[0])));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +328,7 @@ void Connection::SendReliableMessage(const std::vector<uint8_t>& data) {
|
|||||||
void Connection::SendUnreliableMessage(const std::vector<uint8_t>& data) {
|
void Connection::SendUnreliableMessage(const std::vector<uint8_t>& data) {
|
||||||
// For now we just silently drop anything bigger than our max packet size.
|
// For now we just silently drop anything bigger than our max packet size.
|
||||||
if (data.size() + 8 > kMaxPacketSize) {
|
if (data.size() + 8 > kMaxPacketSize) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Error: Dropping outgoing unreliable packet of size "
|
"Error: Dropping outgoing unreliable packet of size "
|
||||||
+ std::to_string(data.size()) + ".");
|
+ std::to_string(data.size()) + ".");
|
||||||
return;
|
return;
|
||||||
@ -438,11 +441,12 @@ void Connection::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
multipart_buffer_.resize(old_size + (buffer.size() - 1));
|
multipart_buffer_.resize(old_size + (buffer.size() - 1));
|
||||||
memcpy(&(multipart_buffer_[old_size]), &(buffer[1]), buffer.size() - 1);
|
memcpy(&(multipart_buffer_[old_size]), &(buffer[1]), buffer.size() - 1);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "got invalid BA_MESSAGE_MULTIPART");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"got invalid BA_MESSAGE_MULTIPART");
|
||||||
}
|
}
|
||||||
if (buffer[0] == BA_MESSAGE_MULTIPART_END) {
|
if (buffer[0] == BA_MESSAGE_MULTIPART_END) {
|
||||||
if (multipart_buffer_[0] == BA_MESSAGE_MULTIPART) {
|
if (multipart_buffer_[0] == BA_MESSAGE_MULTIPART) {
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"nested multipart message detected; kicking");
|
"nested multipart message detected; kicking");
|
||||||
Error("");
|
Error("");
|
||||||
}
|
}
|
||||||
@ -487,7 +491,7 @@ void Connection::SendGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
&& data[0] != BA_SCENEPACKET_HANDSHAKE_RESPONSE) {
|
&& data[0] != BA_SCENEPACKET_HANDSHAKE_RESPONSE) {
|
||||||
if (explicit_bool(false)) {
|
if (explicit_bool(false)) {
|
||||||
BA_LOG_ONCE(
|
BA_LOG_ONCE(
|
||||||
LogLevel::kError,
|
LogName::kBaNetworking, LogLevel::kError,
|
||||||
"SendGamePacket() called before can_communicate set ("
|
"SendGamePacket() called before can_communicate set ("
|
||||||
+ g_core->platform->DemangleCXXSymbol(typeid(*this).name())
|
+ g_core->platform->DemangleCXXSymbol(typeid(*this).name())
|
||||||
+ " ptype " + std::to_string(static_cast<int>(data[0])) + ")");
|
+ " ptype " + std::to_string(static_cast<int>(data[0])) + ")");
|
||||||
|
|||||||
@ -31,7 +31,7 @@ void ConnectionSet::RegisterClientController(ClientControllerInterface* c) {
|
|||||||
// This shouldn't happen, but if there's already a controller registered,
|
// This shouldn't happen, but if there's already a controller registered,
|
||||||
// detach all clients from it.
|
// detach all clients from it.
|
||||||
if (client_controller_) {
|
if (client_controller_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"RegisterClientController() called "
|
"RegisterClientController() called "
|
||||||
"but already have a controller; bad.");
|
"but already have a controller; bad.");
|
||||||
for (auto&& i : connections_to_clients_) {
|
for (auto&& i : connections_to_clients_) {
|
||||||
@ -214,7 +214,7 @@ auto ConnectionSet::GetConnectionsToClients()
|
|||||||
if (connections_to_client.second.Exists()) {
|
if (connections_to_client.second.Exists()) {
|
||||||
connections.push_back(connections_to_client.second.Get());
|
connections.push_back(connections_to_client.second.Get());
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"HAVE NONEXISTENT CONNECTION_TO_CLIENT IN LIST; UNEXPECTED");
|
"HAVE NONEXISTENT CONNECTION_TO_CLIENT IN LIST; UNEXPECTED");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ void ConnectionSet::SendScreenMessageToAll(const std::string& s, float r,
|
|||||||
void ConnectionSet::PrepareForLaunchHostSession() {
|
void ConnectionSet::PrepareForLaunchHostSession() {
|
||||||
// If for some reason we're still attached to a host, kill the connection.
|
// If for some reason we're still attached to a host, kill the connection.
|
||||||
if (connection_to_host_.Exists()) {
|
if (connection_to_host_.Exists()) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Had host-connection during LaunchHostSession(); shouldn't happen.");
|
"Had host-connection during LaunchHostSession(); shouldn't happen.");
|
||||||
connection_to_host_->RequestDisconnect();
|
connection_to_host_->RequestDisconnect();
|
||||||
connection_to_host_.Clear();
|
connection_to_host_.Clear();
|
||||||
@ -320,8 +320,9 @@ auto ConnectionSet::DisconnectClient(int client_id, int ban_seconds) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (client_id > 255) {
|
if (client_id > 255) {
|
||||||
Log(LogLevel::kError, "DisconnectClient got client_id > 255 ("
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ std::to_string(client_id) + ")");
|
"DisconnectClient got client_id > 255 (" + std::to_string(client_id)
|
||||||
|
+ ")");
|
||||||
} else {
|
} else {
|
||||||
std::vector<uint8_t> msg_out(2);
|
std::vector<uint8_t> msg_out(2);
|
||||||
msg_out[0] = BA_MESSAGE_KICK_VOTE;
|
msg_out[0] = BA_MESSAGE_KICK_VOTE;
|
||||||
@ -409,7 +410,7 @@ void ConnectionSet::UnregisterClientController(ClientControllerInterface* c) {
|
|||||||
|
|
||||||
// This shouldn't happen.
|
// This shouldn't happen.
|
||||||
if (client_controller_ != c) {
|
if (client_controller_ != c) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"UnregisterClientController() called with a non-registered "
|
"UnregisterClientController() called with a non-registered "
|
||||||
"controller");
|
"controller");
|
||||||
return;
|
return;
|
||||||
@ -675,7 +676,8 @@ void ConnectionSet::HandleIncomingUDPPacket(const std::vector<uint8_t>& data_in,
|
|||||||
msg_out[0] = BA_PACKET_CLIENT_DENY;
|
msg_out[0] = BA_PACKET_CLIENT_DENY;
|
||||||
msg_out[1] = request_id;
|
msg_out[1] = request_id;
|
||||||
g_base->network_writer->PushSendToCall(msg_out, addr);
|
g_base->network_writer->PushSendToCall(msg_out, addr);
|
||||||
Log(LogLevel::kError, "All client slots full; really?..");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"All client slots full; really?..");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connection_to_client = Object::New<ConnectionToClientUDP>(
|
connection_to_client = Object::New<ConnectionToClientUDP>(
|
||||||
@ -717,7 +719,7 @@ auto ConnectionSet::VerifyClientAddr(uint8_t client_id, const SockAddr& addr)
|
|||||||
if (addr == connection_to_client_udp->addr()) {
|
if (addr == connection_to_client_udp->addr()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"VerifyClientAddr() found mismatch for client "
|
"VerifyClientAddr() found mismatch for client "
|
||||||
+ std::to_string(client_id) + ".");
|
+ std::to_string(client_id) + ".");
|
||||||
return false;
|
return false;
|
||||||
@ -730,7 +732,7 @@ void ConnectionSet::SetClientInfoFromMasterServer(
|
|||||||
const std::string& client_token, PyObject* info_obj) {
|
const std::string& client_token, PyObject* info_obj) {
|
||||||
// NOLINTNEXTLINE (python doing bitwise math on signed int)
|
// NOLINTNEXTLINE (python doing bitwise math on signed int)
|
||||||
if (!PyDict_Check(info_obj)) {
|
if (!PyDict_Check(info_obj)) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"got non-dict for master-server client info for token " + client_token
|
"got non-dict for master-server client info for token " + client_token
|
||||||
+ ": " + Python::ObjToString(info_obj));
|
+ ": " + Python::ObjToString(info_obj));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -144,7 +144,8 @@ void ConnectionToClient::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.empty()) {
|
if (data.empty()) {
|
||||||
Log(LogLevel::kError, "ConnectionToClient got data size 0.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"ConnectionToClient got data size 0.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +158,8 @@ void ConnectionToClient::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
case BA_SCENEPACKET_HANDSHAKE_RESPONSE: {
|
case BA_SCENEPACKET_HANDSHAKE_RESPONSE: {
|
||||||
// We sent the client a handshake and they're responding.
|
// We sent the client a handshake and they're responding.
|
||||||
if (data.size() < 3) {
|
if (data.size() < 3) {
|
||||||
Log(LogLevel::kError, "got invalid BA_SCENEPACKET_HANDSHAKE_RESPONSE");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"got invalid BA_SCENEPACKET_HANDSHAKE_RESPONSE");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +352,8 @@ void ConnectionToClient::SendScreenMessage(const std::string& s, float r,
|
|||||||
void ConnectionToClient::HandleMessagePacket(
|
void ConnectionToClient::HandleMessagePacket(
|
||||||
const std::vector<uint8_t>& buffer) {
|
const std::vector<uint8_t>& buffer) {
|
||||||
if (buffer.empty()) {
|
if (buffer.empty()) {
|
||||||
Log(LogLevel::kError, "Got invalid HandleMessagePacket.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Got invalid HandleMessagePacket.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +407,8 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
if (b) {
|
if (b) {
|
||||||
build_number_ = b->valueint;
|
build_number_ = b->valueint;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "No buildnumber in clientinfo msg.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"No buildnumber in clientinfo msg.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab their token (we use this to ask the
|
// Grab their token (we use this to ask the
|
||||||
@ -413,7 +417,8 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
if (t) {
|
if (t) {
|
||||||
token_ = t->valuestring;
|
token_ = t->valuestring;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "No token in clientinfo msg.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"No token in clientinfo msg.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Newer clients also pass a peer-hash, which
|
// Newer clients also pass a peer-hash, which
|
||||||
@ -432,7 +437,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
}
|
}
|
||||||
cJSON_Delete(info);
|
cJSON_Delete(info);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Got invalid json in clientinfo message: '"
|
"Got invalid json in clientinfo message: '"
|
||||||
+ std::string(reinterpret_cast<const char*>(&(buffer[1])))
|
+ std::string(reinterpret_cast<const char*>(&(buffer[1])))
|
||||||
+ "'.");
|
+ "'.");
|
||||||
@ -473,7 +478,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
// we support for game streams vs client-connections. We could disallow
|
// we support for game streams vs client-connections. We could disallow
|
||||||
// connections to/from these older peers while still allowing old replays
|
// connections to/from these older peers while still allowing old replays
|
||||||
// to play back.
|
// to play back.
|
||||||
BA_LOG_ONCE(LogLevel::kError,
|
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Received old pre-json player profiles msg; ignoring.");
|
"Received old pre-json player profiles msg; ignoring.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -501,7 +506,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
// spamming before we can verify their identities)
|
// spamming before we can verify their identities)
|
||||||
if (appmode->require_client_authentication()
|
if (appmode->require_client_authentication()
|
||||||
&& !got_info_from_master_server_) {
|
&& !got_info_from_master_server_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Ignoring chat message from peer with no client info.");
|
"Ignoring chat message from peer with no client info.");
|
||||||
SendScreenMessage(R"({"r":"loadingTryAgainText"})", 1, 0, 0);
|
SendScreenMessage(R"({"r":"loadingTryAgainText"})", 1, 0, 0);
|
||||||
} else if (last_chat_times_.size() >= 5) {
|
} else if (last_chat_times_.size() >= 5) {
|
||||||
@ -599,7 +604,8 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
GetClientInputDevice(buffer[1])) {
|
GetClientInputDevice(buffer[1])) {
|
||||||
int count = static_cast<int>((buffer.size() - 2) / 5);
|
int count = static_cast<int>((buffer.size() - 2) / 5);
|
||||||
if ((buffer.size() - 2) % 5 != 0) {
|
if ((buffer.size() - 2) % 5 != 0) {
|
||||||
Log(LogLevel::kError, "Error: invalid player-input-commands packet");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Error: invalid player-input-commands packet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int index = 2;
|
int index = 2;
|
||||||
@ -617,7 +623,8 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
case BA_MESSAGE_REMOVE_REMOTE_PLAYER: {
|
case BA_MESSAGE_REMOVE_REMOTE_PLAYER: {
|
||||||
last_remove_player_time_ = g_core->GetAppTimeMillisecs();
|
last_remove_player_time_ = g_core->GetAppTimeMillisecs();
|
||||||
if (buffer.size() != 2) {
|
if (buffer.size() != 2) {
|
||||||
Log(LogLevel::kError, "Error: invalid remove-remote-player packet");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Error: invalid remove-remote-player packet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ClientInputDevice* cid = GetClientInputDevice(buffer[1])) {
|
if (ClientInputDevice* cid = GetClientInputDevice(buffer[1])) {
|
||||||
@ -632,7 +639,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
host_session->RemovePlayer(player);
|
host_session->RemovePlayer(player);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Unable to get ClientInputDevice for remove-remote-player msg.");
|
"Unable to get ClientInputDevice for remove-remote-player msg.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,7 +648,8 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
|
|
||||||
case BA_MESSAGE_REQUEST_REMOTE_PLAYER: {
|
case BA_MESSAGE_REQUEST_REMOTE_PLAYER: {
|
||||||
if (buffer.size() != 2) {
|
if (buffer.size() != 2) {
|
||||||
Log(LogLevel::kError, "Error: invalid remote-player-request packet");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Error: invalid remote-player-request packet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,7 +660,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
// It should have one of our special client delegates attached.
|
// It should have one of our special client delegates attached.
|
||||||
auto* cid_d = dynamic_cast<ClientInputDeviceDelegate*>(&cid->delegate());
|
auto* cid_d = dynamic_cast<ClientInputDeviceDelegate*>(&cid->delegate());
|
||||||
if (!cid_d) {
|
if (!cid_d) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Can't get client-input-device-delegate in request-remote-player "
|
"Can't get client-input-device-delegate in request-remote-player "
|
||||||
"msg.");
|
"msg.");
|
||||||
break;
|
break;
|
||||||
@ -676,7 +684,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
} else {
|
} else {
|
||||||
// Either timed out or have info; let the request go through.
|
// Either timed out or have info; let the request go through.
|
||||||
if (still_waiting_for_auth) {
|
if (still_waiting_for_auth) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Allowing player-request without client\'s master-server "
|
"Allowing player-request without client\'s master-server "
|
||||||
"info (build "
|
"info (build "
|
||||||
+ std::to_string(build_number_) + ")");
|
+ std::to_string(build_number_) + ")");
|
||||||
@ -685,7 +693,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"ConnectionToClient got remote player"
|
"ConnectionToClient got remote player"
|
||||||
" request but have no host session");
|
" request but have no host session");
|
||||||
}
|
}
|
||||||
@ -699,9 +707,9 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
if (multipart_buffer_size() > 50000) {
|
if (multipart_buffer_size() > 50000) {
|
||||||
// Its not actually unknown but shhh don't tell the hackers...
|
// Its not actually unknown but shhh don't tell the hackers...
|
||||||
SendScreenMessage(R"({"r":"errorUnknownText"})", 1, 0, 0);
|
SendScreenMessage(R"({"r":"errorUnknownText"})", 1, 0, 0);
|
||||||
Log(LogLevel::kError, "Client data limit exceeded by '"
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ peer_spec().GetShortName()
|
"Client data limit exceeded by '" + peer_spec().GetShortName()
|
||||||
+ "'; kicking.");
|
+ "'; kicking.");
|
||||||
appmode->BanPlayer(peer_spec(), 1000 * 60);
|
appmode->BanPlayer(peer_spec(), 1000 * 60);
|
||||||
Error("");
|
Error("");
|
||||||
return;
|
return;
|
||||||
@ -792,8 +800,9 @@ void ConnectionToClient::HandleMasterServerClientInfo(PyObject* info_obj) {
|
|||||||
"{\"t\":[\"serverResponses\","
|
"{\"t\":[\"serverResponses\","
|
||||||
"\"Your account was rejected. Are you signed in?\"]}",
|
"\"Your account was rejected. Are you signed in?\"]}",
|
||||||
1, 0, 0);
|
1, 0, 0);
|
||||||
Log(LogLevel::kError, "Master server found no valid account for '"
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
+ peer_spec().GetShortName() + "'; kicking.");
|
"Master server found no valid account for '"
|
||||||
|
+ peer_spec().GetShortName() + "'; kicking.");
|
||||||
|
|
||||||
// Not benning anymore. People were exploiting this by impersonating
|
// Not benning anymore. People were exploiting this by impersonating
|
||||||
// other players using their public ids to get them banned from
|
// other players using their public ids to get them banned from
|
||||||
|
|||||||
@ -72,7 +72,8 @@ void ConnectionToClientUDP::HandleGamePacket(
|
|||||||
|
|
||||||
void ConnectionToClientUDP::Die() {
|
void ConnectionToClientUDP::Die() {
|
||||||
if (did_die_) {
|
if (did_die_) {
|
||||||
Log(LogLevel::kError, "Posting multiple die messages; probably not good.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Posting multiple die messages; probably not good.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// this will actually clear the object..
|
// this will actually clear the object..
|
||||||
|
|||||||
@ -250,7 +250,7 @@ void ConnectionToHost::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
g_base->python->GetRawConfigValue("Player Profiles");
|
g_base->python->GetRawConfigValue("Player Profiles");
|
||||||
PythonRef empty_dict;
|
PythonRef empty_dict;
|
||||||
if (!profiles) {
|
if (!profiles) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"No profiles found; sending empty list to host");
|
"No profiles found; sending empty list to host");
|
||||||
empty_dict.Steal(PyDict_New());
|
empty_dict.Steal(PyDict_New());
|
||||||
profiles = empty_dict.Get();
|
profiles = empty_dict.Get();
|
||||||
@ -265,7 +265,7 @@ void ConnectionToHost::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
.Get(core::CorePython::ObjID::kJsonDumpsCall)
|
.Get(core::CorePython::ObjID::kJsonDumpsCall)
|
||||||
.Call(args, keywds);
|
.Call(args, keywds);
|
||||||
if (!results.Exists()) {
|
if (!results.Exists()) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Error getting json dump of local profiles");
|
"Error getting json dump of local profiles");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -276,14 +276,14 @@ void ConnectionToHost::HandleGamePacket(const std::vector<uint8_t>& data) {
|
|||||||
memcpy(&(msg[1]), &s[0], s.size());
|
memcpy(&(msg[1]), &s[0], s.size());
|
||||||
SendReliableMessage(msg);
|
SendReliableMessage(msg);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
std::string("exc sending player profiles to host: ")
|
std::string("Error sending player profiles to host: ")
|
||||||
+ e.what());
|
+ e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Connected to old protocol; can't send player profiles");
|
"Connected to old protocol; can't send player profiles");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -311,7 +311,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
if (buffer.empty()) {
|
if (buffer.empty()) {
|
||||||
Log(LogLevel::kError, "Got invalid HandleMessagePacket");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Got invalid HandleMessagePacket");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +336,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
if (b) {
|
if (b) {
|
||||||
build_number_ = b->valueint;
|
build_number_ = b->valueint;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "no buildnumber in hostinfo msg");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"no buildnumber in hostinfo msg");
|
||||||
}
|
}
|
||||||
// Party name.
|
// Party name.
|
||||||
cJSON* n = cJSON_GetObjectItem(info, "n");
|
cJSON* n = cJSON_GetObjectItem(info, "n");
|
||||||
@ -344,7 +346,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
}
|
}
|
||||||
cJSON_Delete(info);
|
cJSON_Delete(info);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "got invalid json in hostinfo message");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"got invalid json in hostinfo message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
got_host_info_ = true;
|
got_host_info_ = true;
|
||||||
@ -440,7 +443,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
case BA_MESSAGE_ATTACH_REMOTE_PLAYER_2: {
|
case BA_MESSAGE_ATTACH_REMOTE_PLAYER_2: {
|
||||||
// New-style packet which includes a 32-bit player_id.
|
// New-style packet which includes a 32-bit player_id.
|
||||||
if (buffer.size() != 6) {
|
if (buffer.size() != 6) {
|
||||||
Log(LogLevel::kError, "Invalid attach-remote-player-2 msg");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Invalid attach-remote-player-2 msg");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +461,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
delegate->AttachToRemotePlayer(this,
|
delegate->AttachToRemotePlayer(this,
|
||||||
static_cast_check_fit<int>(player_id));
|
static_cast_check_fit<int>(player_id));
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"InputDevice does not have a SceneV1 delegate as expected "
|
"InputDevice does not have a SceneV1 delegate as expected "
|
||||||
"(loc1).");
|
"(loc1).");
|
||||||
}
|
}
|
||||||
@ -476,7 +480,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
// public servers.
|
// public servers.
|
||||||
// TODO(ericf): can remove this once back-compat-protocol > 29.
|
// TODO(ericf): can remove this once back-compat-protocol > 29.
|
||||||
if (buffer.size() != 3) {
|
if (buffer.size() != 3) {
|
||||||
Log(LogLevel::kError, "Invalid attach-remote-player msg.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Invalid attach-remote-player msg.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +495,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
&input_device->delegate())) {
|
&input_device->delegate())) {
|
||||||
delegate->AttachToRemotePlayer(this, buffer[2]);
|
delegate->AttachToRemotePlayer(this, buffer[2]);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"InputDevice does not have a SceneV1 delegate as expected "
|
"InputDevice does not have a SceneV1 delegate as expected "
|
||||||
"(loc2).");
|
"(loc2).");
|
||||||
}
|
}
|
||||||
@ -508,7 +513,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
|
|
||||||
case BA_MESSAGE_DETACH_REMOTE_PLAYER: {
|
case BA_MESSAGE_DETACH_REMOTE_PLAYER: {
|
||||||
if (buffer.size() != 2) {
|
if (buffer.size() != 2) {
|
||||||
Log(LogLevel::kError, "Invalid detach-remote-player msg");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Invalid detach-remote-player msg");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Server is telling us that our local input device is no longer
|
// Server is telling us that our local input device is no longer
|
||||||
@ -532,7 +538,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
|||||||
// be cleared out at this point. Just complain if that's not
|
// be cleared out at this point. Just complain if that's not
|
||||||
// the case.
|
// the case.
|
||||||
if (connection_to_host != nullptr) {
|
if (connection_to_host != nullptr) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"InputDevice does not have a SceneV1 delegate as expected "
|
"InputDevice does not have a SceneV1 delegate as expected "
|
||||||
"(loc3).");
|
"(loc3).");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,7 +125,8 @@ void ConnectionToHostUDP::Update() {
|
|||||||
// departure before doing this when possible.
|
// departure before doing this when possible.
|
||||||
void ConnectionToHostUDP::Die() {
|
void ConnectionToHostUDP::Die() {
|
||||||
if (did_die_) {
|
if (did_die_) {
|
||||||
Log(LogLevel::kError, "Posting multiple die messages; probably not good.");
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
|
"Posting multiple die messages; probably not good.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (auto* appmode = classic::ClassicAppMode::GetActiveOrWarn()) {
|
if (auto* appmode = classic::ClassicAppMode::GetActiveOrWarn()) {
|
||||||
@ -133,7 +134,7 @@ void ConnectionToHostUDP::Die() {
|
|||||||
appmode->connections()->PushDisconnectedFromHostCall();
|
appmode->connections()->PushDisconnectedFromHostCall();
|
||||||
did_die_ = true;
|
did_die_ = true;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||||
"Running update for non-current host-connection; shouldn't "
|
"Running update for non-current host-connection; shouldn't "
|
||||||
"happen.");
|
"happen.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,14 +136,14 @@ class Dynamics::Impl_ {
|
|||||||
|
|
||||||
Dynamics::Dynamics(Scene* scene_in)
|
Dynamics::Dynamics(Scene* scene_in)
|
||||||
: scene_(scene_in),
|
: scene_(scene_in),
|
||||||
collision_cache_(new base::CollisionCache()),
|
collision_cache_(std::make_unique<base::CollisionCache>()),
|
||||||
impl_(std::make_unique<Impl_>(this)) {
|
impl_(std::make_unique<Impl_>(this)) {
|
||||||
ResetODE_();
|
ResetODE_();
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynamics::~Dynamics() {
|
Dynamics::~Dynamics() {
|
||||||
if (in_process_) {
|
if (in_process_) {
|
||||||
Log(LogLevel::kError,
|
Log(LogName::kBa, LogLevel::kError,
|
||||||
"Dynamics going down within Process() call;"
|
"Dynamics going down within Process() call;"
|
||||||
" should not happen.");
|
" should not happen.");
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user