mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-27 17:33:13 +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/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c8904594aa4867a7525e6644249d5fd5",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "7d3ba05e21b198bdccbdaf9d334f96f2",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "8601ef36314294c18b686995ce9a02f6",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "36742622076742a5642de8c287cd92e4",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b05ee46d11b618cf917cae591fe6b97a",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a9a03ded1e4fccfdc1879bd8f70e0e7a",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "05f37deacb796ef45828233ded9325e3",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "f4b4df8f17219f81148efe3dc057856f",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b6201f83d4f80fcc567398807c7d77b5",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "331335944425c5a48abbcf137da46f0f",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ac2d7714d87b781659c1e3333f760888",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1e7cc9348498df9bfb7b25cd83009d7c",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a3c7e011ad99046d2ef8b102e7d15733",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "43fd8535ad1e2c2c64fe57dacfb3305b",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "fc17d6883ddd4486a62b75494dbb9d15",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0a557a638ee4cb3150d90bcb5913de3e",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "85afe70f81c1f7d2de9520d498c74eb8",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "a617c0412a804bce272113585c000318",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "5642e5614711b8e106de659db2b33ac7",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ea7018647c89777469979aa08e88573e",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "ba7dc0b4e927f32fcf15c2f738fe004c",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fb4c90da8d46ddab5847406fa397dbd5",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "ba7dc0b4e927f32fcf15c2f738fe004c",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "fb4c90da8d46ddab5847406fa397dbd5",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "225f13c4755aa018e63168c8aca0a8fd",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "d4c6e0f0ac69af106f1227daeae2db55",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "225f13c4755aa018e63168c8aca0a8fd",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "d4c6e0f0ac69af106f1227daeae2db55",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "e16971f1da7ad7f44bb185b4446965c6",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d5638285fa481d769a5cd488a78d8269",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "e16971f1da7ad7f44bb185b4446965c6",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d5638285fa481d769a5cd488a78d8269",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "184b7e4731b09ccf3a6a3b001d8af097",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "507b5555ef5d067caf18fe9844ca04c7",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "838ee9bfd43169efe8daff8bb0efb1db",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "507b5555ef5d067caf18fe9844ca04c7",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "d1edb04136c433b57f3842830e9b272d",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "4e64e07e3527e0536d1dc7f2dacd681a",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "301bad929a4f3c6e9f67e57ab730bded",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "6224ca7790cfa8274c3f9c8e4461b93f",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "bedcc6b5cc2a403a65d83c6244922feb",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "545edb5e8f7cce4e7bc3cdb0e4f98b82",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "79102625aebc9df3a0834f8d571fdbac",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9e5a350dc8f5fcd1ab96c7a4c24a7ebe",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b20c6e3a2287f1c6a9a898e78fcab105",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "0f1eff142f1e5796be2e0340dcbb4c8f",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f40171c1c943c10e2d2120a586a711f7",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ea494bdeb942cbab86c0371bb0558f3b",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "fba8474fd758e8d76bc6d7e90dfb7795",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4b1a35c2e6d7c2d9a01c6e2750716c24",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "9ac4ee8aab0243a233ba8650cd0d0b73",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "c804d14d91dab05f644079ae47e61728",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1f7011d1c77548e48b7f6d3ac09a29da",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "c50790a9a2e3001dd079a6bbd753c36f",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "52528037523bf268e2c59a19626e7f2d",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "a920948fcc94c397495ef8dd674d325b",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d0f7ad9287edd649d97844ada500a11d",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1073804b2d2549f9eb992666fc3640c3",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "73e6ca5aee9af5a87960b7ae174f0a71",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c09c4fac16134d5071a88ec8d3e1e950",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e78b8bd1cb5aa452f536c57e855bcc27",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "0f08643a492ac7bf8fd3f13460003bce",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "48e684f7db6d88a62009d773ab51b065",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "69a301acc9adfacdb8b3d200390bbfdd",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "653df60722ed096b8cc3ac3a4196e5a5",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "f82c1e575e8f23c1e278db61a740a4d5",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "653df60722ed096b8cc3ac3a4196e5a5",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "f82c1e575e8f23c1e278db61a740a4d5",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "90125afd27068280c96cf37c950b641f",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a210d341f1842b21ebbaadd80ae4a282",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "90125afd27068280c96cf37c950b641f",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a210d341f1842b21ebbaadd80ae4a282",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "cdf4fca1c1aaae2c2294263f0717b333",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "937b954eed2571cb4d5f9d2a0e3f77ed",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "cdf4fca1c1aaae2c2294263f0717b333",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "937b954eed2571cb4d5f9d2a0e3f77ed",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "cdd7c61d6c0efd5fb0442e625123b63f",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "ea327f45634a8e42259c5ecadf219e36",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "547362a74979fa82b854a475dffeae90",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "ea327f45634a8e42259c5ecadf219e36",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "828f4682e3bbdc0da5b45a0050aeb5d8",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "cf4b13af9f0846a466204afbe74b9e86",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b43fa205beae83e030ec777d4974736b",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "aef585a4d739765b59f9a85dc27ff67f",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "559b65282ab2bfff034aa64963a7af52",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "5916245826eb4d3b68944006f82de6d9",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "6844834b7fc1030c234bee21a376a017",
|
||||
"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/enums.py": "794d258d59fd17a61752843a9a0551ad",
|
||||
"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/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/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
|
||||
"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
|
||||
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.
|
||||
I'm hopeful that api version won't need to be bumped again for along time (if
|
||||
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
|
||||
compatibility anyway by bumping api version). If you are using
|
||||
`efro.call.tpartial` anywhere, simply replace it with `functools.partial`.
|
||||
@ -113,6 +128,8 @@
|
||||
it will take you back to the co-op screen.
|
||||
- (build 22018) Hardened SDL joystick handling code so the app won't crash if
|
||||
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)
|
||||
- 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
|
||||
incompatibilities with the older sys scripts. This should help with that
|
||||
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)
|
||||
- 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
|
||||
filelock==3.16.1
|
||||
furo==2024.8.6
|
||||
mypy==1.11.2
|
||||
mypy==1.12.0
|
||||
pbxproj==4.2.1
|
||||
pdoc==14.7.0
|
||||
pdoc==15.0.0
|
||||
pur==7.3.2
|
||||
pylint==3.3.1
|
||||
pylsp-mypy==0.6.9
|
||||
@ -13,10 +13,10 @@ python-daemon==3.0.1
|
||||
python-lsp-black==2.0.0
|
||||
python-lsp-server==1.12.0
|
||||
requests==2.32.3
|
||||
Sphinx==8.0.2
|
||||
Sphinx==8.1.3
|
||||
tomlkit==0.13.2
|
||||
types-certifi==2021.10.8.3
|
||||
types-filelock==3.2.7
|
||||
types-requests==2.32.0.20240914
|
||||
types-requests==2.32.0.20241016
|
||||
typing_extensions==4.12.2
|
||||
urllib3==2.2.3
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
"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__/_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__/_env.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/_asyncio.py",
|
||||
"ba_data/python/babase/_devconsole.py",
|
||||
"ba_data/python/babase/_devconsoletabs.py",
|
||||
"ba_data/python/babase/_emptyappmode.py",
|
||||
"ba_data/python/babase/_env.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__/build.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__/net.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/build.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/net.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__/debug.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__/terminal.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/debug.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/__pycache__/__init__.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/_asyncio.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/_env.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__/_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__/_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__/_env.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/build.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/net.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/debug.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/_message.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__/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__/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__/net.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/__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__/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__/_message.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
|
||||
# annotations since those aren't evaluated at runtime.
|
||||
|
||||
import logging
|
||||
from efro.util import set_canonical_module_names
|
||||
|
||||
|
||||
@ -109,6 +110,7 @@ from _babase import (
|
||||
supports_max_fps,
|
||||
supports_vsync,
|
||||
unlock_all_input,
|
||||
update_internal_logger_levels,
|
||||
user_agent_string,
|
||||
Vec3,
|
||||
workspaces_in_use,
|
||||
@ -185,6 +187,9 @@ from babase._plugin import PluginSpec, Plugin, PluginSubsystem
|
||||
from babase._stringedit import StringEditAdapter, StringEditSubsystem
|
||||
from babase._text import timestring
|
||||
|
||||
# Our standard set of loggers.
|
||||
balog = logging.getLogger('ba')
|
||||
|
||||
_babase.app = app = App()
|
||||
app.postinit()
|
||||
|
||||
@ -215,6 +220,7 @@ __all__ = [
|
||||
'apptimer',
|
||||
'AppTimer',
|
||||
'asset_loads_allowed',
|
||||
'balog',
|
||||
'Call',
|
||||
'fullscreen_control_available',
|
||||
'fullscreen_control_get',
|
||||
@ -344,6 +350,7 @@ __all__ = [
|
||||
'timestring',
|
||||
'UIScale',
|
||||
'unlock_all_input',
|
||||
'update_internal_logger_levels',
|
||||
'user_agent_string',
|
||||
'utf8_all',
|
||||
'Vec3',
|
||||
|
||||
@ -10,11 +10,12 @@ from functools import partial
|
||||
from typing import TYPE_CHECKING, assert_never
|
||||
|
||||
from efro.error import CommunicationError
|
||||
from efro.call import CallbackSet
|
||||
from bacommon.login import LoginType
|
||||
import _babase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any
|
||||
from typing import Any, Callable
|
||||
|
||||
from babase._login import LoginAdapter, LoginInfo
|
||||
|
||||
@ -31,10 +32,12 @@ class AccountV2Subsystem:
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
from babase._login import LoginAdapterGPGS, LoginAdapterGameCenter
|
||||
|
||||
# Whether or not everything related to an initial login
|
||||
# (or lack thereof) has completed. This includes things like
|
||||
# Whether or not everything related to an initial sign in (or
|
||||
# lack thereof) has completed. This includes things like
|
||||
# workspace syncing. Completion of this is what flips the app
|
||||
# into 'running' state.
|
||||
self._initial_sign_in_completed = False
|
||||
@ -46,6 +49,9 @@ class AccountV2Subsystem:
|
||||
self._implicit_signed_in_adapter: LoginAdapter | None = None
|
||||
self._implicit_state_changed = False
|
||||
self._can_do_auto_sign_in = True
|
||||
self.on_primary_account_changed_callbacks: CallbackSet[
|
||||
Callable[[AccountV2Handle | None], None]
|
||||
] = CallbackSet()
|
||||
|
||||
adapter: LoginAdapter
|
||||
if _babase.using_google_play_game_services():
|
||||
@ -85,6 +91,13 @@ class AccountV2Subsystem:
|
||||
"""
|
||||
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.
|
||||
if account is None:
|
||||
return
|
||||
|
||||
@ -23,6 +23,7 @@ from babase._appmodeselector import AppModeSelector
|
||||
from babase._appintent import AppIntentDefault, AppIntentExec
|
||||
from babase._stringedit import StringEditSubsystem
|
||||
from babase._devconsole import DevConsoleSubsystem
|
||||
from babase._appconfig import AppConfig
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import asyncio
|
||||
@ -182,6 +183,11 @@ class App:
|
||||
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
||||
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.state = self.State.NOT_STARTED
|
||||
|
||||
@ -223,7 +229,7 @@ class App:
|
||||
self._asyncio_loop: asyncio.AbstractEventLoop | None = None
|
||||
self._asyncio_tasks: set[asyncio.Task] = set()
|
||||
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._intent: AppIntent | None = None
|
||||
self._mode_selector: babase.AppModeSelector | None = None
|
||||
@ -330,11 +336,12 @@ class App:
|
||||
|
||||
self._asyncio_tasks.remove(task)
|
||||
|
||||
@property
|
||||
def config(self) -> babase.AppConfig:
|
||||
"""The babase.AppConfig instance representing the app's config state."""
|
||||
assert self._config is not None
|
||||
return self._config
|
||||
# @property
|
||||
# def config(self) -> babase.AppConfig:
|
||||
# """The babase.AppConfig instance
|
||||
# representing the app's config state."""
|
||||
# assert self._config is not None
|
||||
# return self._config
|
||||
|
||||
@property
|
||||
def mode_selector(self) -> babase.AppModeSelector:
|
||||
@ -585,12 +592,6 @@ class App:
|
||||
if self._mode is not None:
|
||||
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:
|
||||
"""Handle a deep link URL."""
|
||||
from babase._language import Lstr
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
"""Provides the AppConfig class."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _babase
|
||||
@ -101,43 +100,6 @@ class AppConfig(dict):
|
||||
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:
|
||||
"""Commit the config to persistent storage.
|
||||
|
||||
@ -145,6 +107,7 @@ def commit_app_config() -> None:
|
||||
|
||||
(internal)
|
||||
"""
|
||||
# FIXME - this should not require plus.
|
||||
plus = _babase.app.plus
|
||||
assert plus is not None
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ from functools import partial
|
||||
from dataclasses import dataclass
|
||||
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
|
||||
|
||||
import _babase
|
||||
|
||||
@ -5,17 +5,14 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import logging
|
||||
from functools import partial
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, override
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _babase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any, Literal
|
||||
|
||||
from babase import AppMode, UIScale
|
||||
|
||||
|
||||
class DevConsoleTab:
|
||||
"""Defines behavior for a tab in the dev-console."""
|
||||
@ -38,6 +35,7 @@ class DevConsoleTab:
|
||||
label_scale: float = 1.0,
|
||||
corner_radius: float = 8.0,
|
||||
style: Literal['normal', 'light'] = 'normal',
|
||||
disabled: bool = False,
|
||||
) -> None:
|
||||
"""Add a button to the tab being refreshed."""
|
||||
assert _babase.app.devconsole.is_refreshing
|
||||
@ -52,6 +50,7 @@ class DevConsoleTab:
|
||||
label_scale,
|
||||
corner_radius,
|
||||
style,
|
||||
disabled,
|
||||
)
|
||||
|
||||
def text(
|
||||
@ -98,151 +97,6 @@ class DevConsoleTab:
|
||||
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
|
||||
class DevConsoleTabEntry:
|
||||
"""Represents a distinct tab in the dev-console."""
|
||||
@ -263,28 +117,50 @@ class DevConsoleSubsystem:
|
||||
"""
|
||||
|
||||
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
|
||||
# plugins or whatnot.
|
||||
self.tabs: list[DevConsoleTabEntry] = [
|
||||
DevConsoleTabEntry('Python', DevConsoleTabPython),
|
||||
DevConsoleTabEntry('AppModes', DevConsoleTabAppModes),
|
||||
DevConsoleTabEntry('UI', DevConsoleTabUI),
|
||||
DevConsoleTabEntry('Logging', DevConsoleTabLogging),
|
||||
]
|
||||
if os.environ.get('BA_DEV_CONSOLE_TEST_TAB', '0') == '1':
|
||||
self.tabs.append(DevConsoleTabEntry('Test', DevConsoleTabTest))
|
||||
self.is_refreshing = False
|
||||
self._tab_instances: dict[str, DevConsoleTab] = {}
|
||||
|
||||
def do_refresh_tab(self, tabname: str) -> None:
|
||||
"""Called by the C++ layer when a tab should be filled out."""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# FIXME: We currently won't handle multiple tabs with the same
|
||||
# name. We should give a clean error or something in that case.
|
||||
tab: DevConsoleTab | None = None
|
||||
for tabentry in self.tabs:
|
||||
if tabentry.name == tabname:
|
||||
tab = tabentry.factory()
|
||||
break
|
||||
# Make noise if we have repeating tab names, as that breaks our
|
||||
# logic.
|
||||
if __debug__:
|
||||
alltabnames = set[str](tabentry.name for tabentry in self.tabs)
|
||||
if len(alltabnames) != len(self.tabs):
|
||||
logging.error(
|
||||
'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:
|
||||
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
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from efro.log import LogLevel
|
||||
from efro.logging import LogLevel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
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_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
|
||||
# console, in the Android log, etc.
|
||||
_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.
|
||||
|
||||
@ -14,6 +14,7 @@ from babase import (
|
||||
AppIntentExec,
|
||||
AppIntentDefault,
|
||||
invoke_main_menu,
|
||||
in_logic_thread,
|
||||
screenmessage,
|
||||
)
|
||||
|
||||
@ -22,13 +23,19 @@ import _baclassic
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable
|
||||
|
||||
from babase import AppIntent
|
||||
from efro.call import CallbackRegistration
|
||||
from babase import AppIntent, AccountV2Handle
|
||||
from bauiv1 import UIV1AppSubsystem, MainWindow, MainWindowState
|
||||
|
||||
|
||||
class ClassicAppMode(AppMode):
|
||||
"""AppMode for the classic BombSquad experience."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._on_primary_account_changed_callback: (
|
||||
CallbackRegistration | None
|
||||
) = None
|
||||
|
||||
@override
|
||||
@classmethod
|
||||
def get_app_experience(cls) -> AppExperience:
|
||||
@ -54,6 +61,8 @@ class ClassicAppMode(AppMode):
|
||||
# Let the native layer do its thing.
|
||||
_baclassic.classic_app_mode_activate()
|
||||
|
||||
assert app.plus is not None
|
||||
|
||||
# Wire up the root ui to do what we want.
|
||||
ui = app.ui_v1
|
||||
ui.root_ui_calls[ui.RootUIElement.ACCOUNT_BUTTON] = (
|
||||
@ -108,9 +117,24 @@ class ClassicAppMode(AppMode):
|
||||
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
|
||||
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.
|
||||
if app.classic is not None:
|
||||
app.classic.save_ui_state()
|
||||
@ -125,6 +149,14 @@ class ClassicAppMode(AppMode):
|
||||
if not app.active:
|
||||
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:
|
||||
from babase import push_back_press
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from dataclasses import dataclass
|
||||
@ -27,7 +28,7 @@ import __main__
|
||||
if TYPE_CHECKING:
|
||||
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
|
||||
# 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
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 22025
|
||||
TARGET_BALLISTICA_BUILD = 22040
|
||||
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.
|
||||
log_handler: LogHandler | None
|
||||
|
||||
# Initial data from the ballisticakit-config.json file. This is
|
||||
# passed mostly as an optimization to avoid reading the same config
|
||||
# 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 data from the config.json file in the config dir. The
|
||||
# config file is parsed by
|
||||
initial_app_config: Any
|
||||
|
||||
# Timestamp when we first started doing stuff.
|
||||
launch_time: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class _EnvGlobals:
|
||||
@ -172,6 +172,11 @@ def configure(
|
||||
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()
|
||||
|
||||
# Keep track of whether we've been *called*, not whether a config
|
||||
@ -206,11 +211,19 @@ def configure(
|
||||
config_dir,
|
||||
)
|
||||
|
||||
# The second thing we do is set up our logging system and pipe
|
||||
# Python's stdout/stderr into it. At this point we can at least
|
||||
# debug problems on systems where native stdout/stderr is not easily
|
||||
# accessible such as Android.
|
||||
log_handler = _setup_logging() if setup_logging else None
|
||||
# Set up our log-handler and pipe Python's stdout/stderr into it.
|
||||
# Later, once the engine comes up, the handler will feed its logs
|
||||
# (including cached history) to the os-specific output location.
|
||||
# This means anything printed or logged at this point forward should
|
||||
# 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.
|
||||
if sys.flags.utf8_mode != 1:
|
||||
@ -235,10 +248,46 @@ def configure(
|
||||
site_python_dir=site_python_dir,
|
||||
log_handler=log_handler,
|
||||
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:
|
||||
if data_dir is None:
|
||||
# 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
|
||||
|
||||
|
||||
def _setup_logging() -> LogHandler:
|
||||
from efro.log import setup_logging, LogLevel
|
||||
def _setup_logging(launch_time: float) -> LogHandler:
|
||||
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_path=None,
|
||||
level=LogLevel.DEBUG,
|
||||
suppress_non_root_debug=True,
|
||||
log_stdout_stderr=True,
|
||||
cache_size_limit=1024 * 1024,
|
||||
launch_time=launch_time,
|
||||
)
|
||||
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:
|
||||
# In situations where we're bringing our own Python, let's also
|
||||
# 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
|
||||
and passed either the response or the error that occurred.
|
||||
"""
|
||||
|
||||
del msg # Unused.
|
||||
|
||||
babase.pushcall(
|
||||
babase.Call(
|
||||
on_response,
|
||||
RuntimeError('Cloud functionality is not available.'),
|
||||
)
|
||||
raise NotImplementedError(
|
||||
'Cloud functionality is not present in this build.'
|
||||
)
|
||||
|
||||
@overload
|
||||
@ -158,7 +152,9 @@ class CloudSubsystem(babase.AppSubsystem):
|
||||
|
||||
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
|
||||
async def send_message_async(
|
||||
@ -175,7 +171,14 @@ class CloudSubsystem(babase.AppSubsystem):
|
||||
|
||||
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:
|
||||
|
||||
@ -1575,6 +1575,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
||||
transition_delay=1.0,
|
||||
).autoretain()
|
||||
else:
|
||||
assert rating is not None
|
||||
ZoomText(
|
||||
(
|
||||
f'{rating:.1f}'
|
||||
|
||||
@ -387,8 +387,6 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
||||
v_offs = 0.0
|
||||
tdelay += len(player_entries) * 8 * t_incr
|
||||
for _score, name, prec in player_entries:
|
||||
if not prec.player.in_game:
|
||||
continue
|
||||
tdelay -= 4 * t_incr
|
||||
v_offs -= 40
|
||||
Text(
|
||||
|
||||
@ -627,6 +627,7 @@ class StoreBrowserWindow(bui.MainWindow):
|
||||
sale_title_text: str | bui.Lstr = ''
|
||||
sale_time_text: str | bui.Lstr = ''
|
||||
|
||||
call: Callable | None
|
||||
if purchased:
|
||||
title_color = (0.8, 0.7, 0.9, 1.0)
|
||||
color = (0.63, 0.55, 0.78)
|
||||
|
||||
@ -136,7 +136,7 @@ auto AppAdapter::DoClipboardGetText() -> 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.");
|
||||
return "?";
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ auto AppAdapterApple::InGraphicsContext() -> bool {
|
||||
void AppAdapterApple::DoPushGraphicsContextRunnable(Runnable* runnable) {
|
||||
auto lock = std::scoped_lock(graphics_calls_mutex_);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ void AppAdapterSDL::OnMainThreadStartApp() {
|
||||
uint32_t sdl_flags{SDL_INIT_VIDEO | SDL_INIT_JOYSTICK};
|
||||
|
||||
if (strict_graphics_context_) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaNetworking, LogLevel::kWarning,
|
||||
"AppAdapterSDL strict_graphics_context_ is enabled."
|
||||
" Remember to turn this off.");
|
||||
}
|
||||
@ -309,7 +309,8 @@ void AppAdapterSDL::SleepUntilNextEventCycle_(microsecs_t cycle_start_time) {
|
||||
const microsecs_t min_sleep{2000};
|
||||
if (now + min_sleep >= target_time) {
|
||||
if (debug_log_sdl_frame_timing_) {
|
||||
Log(LogLevel::kDebug, "no sleep."); // 'till brooklyn!
|
||||
Log(LogName::kBaNetworking, LogLevel::kDebug,
|
||||
"no sleep."); // 'till brooklyn!
|
||||
}
|
||||
} else {
|
||||
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",
|
||||
(now - cycle_start_time) / 1000.0f,
|
||||
(target_time - now) / 1000.0f);
|
||||
Log(LogLevel::kDebug, buf);
|
||||
Log(LogName::kBaNetworking, LogLevel::kDebug, buf);
|
||||
}
|
||||
g_core->platform->SleepMicrosecs(target_time - now);
|
||||
}
|
||||
@ -375,8 +376,9 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) {
|
||||
g_base->input->PushJoystickEvent(event, js);
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError, "Unable to get SDL Joystick for event type "
|
||||
+ std::to_string(event.type));
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"Unable to get SDL Joystick for event type "
|
||||
+ std::to_string(event.type));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -563,7 +565,7 @@ void AppAdapterSDL::OnSDLJoystickAdded_(int device_index) {
|
||||
try {
|
||||
j = Object::NewDeferred<JoystickInput>(device_index);
|
||||
} catch (const std::exception& exc) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
std::string("Error creating JoystickInput for SDL device-index "
|
||||
+ std::to_string(device_index) + ": ")
|
||||
+ exc.what());
|
||||
@ -602,7 +604,7 @@ void AppAdapterSDL::RemoveSDLInputDevice_(int index) {
|
||||
|
||||
// Note: am running into this with a PS5 controller on macOS Sequoia beta.
|
||||
if (!j) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"GetSDLJoystickInput_() returned nullptr on RemoveSDLInputDevice_();"
|
||||
" joysticks size 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) {
|
||||
sdl_joysticks_[index] = nullptr;
|
||||
} else {
|
||||
Log(LogLevel::kError, "Invalid index on RemoveSDLInputDevice: size is "
|
||||
+ std::to_string(sdl_joysticks_.size())
|
||||
+ "; index is " + std::to_string(index) + ".");
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"Invalid index on RemoveSDLInputDevice: size is "
|
||||
+ std::to_string(sdl_joysticks_.size()) + "; index is "
|
||||
+ std::to_string(index) + ".");
|
||||
}
|
||||
g_base->input->PushRemoveInputDeviceCall(j, true);
|
||||
}
|
||||
@ -785,7 +788,8 @@ void AppAdapterSDL::DoPushGraphicsContextRunnable(Runnable* runnable) {
|
||||
if (strict_graphics_context_) {
|
||||
auto lock = std::scoped_lock(strict_graphics_calls_mutex_);
|
||||
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);
|
||||
} else {
|
||||
|
||||
@ -52,7 +52,8 @@ void AppAdapterVR::VRPreDraw() {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
// FIXME - this is internal graphics-server details that the render-server
|
||||
// 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()) {
|
||||
// // Note: this could be part of PreprocessRenderFrameDef but the non-vr
|
||||
// // 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_);
|
||||
vr_render_frame_def_ = nullptr;
|
||||
}
|
||||
Log(LogLevel::kWarning, "WOULD RUN RENDER UPKEEP CYCLE");
|
||||
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"WOULD RUN RENDER UPKEEP CYCLE");
|
||||
// RunRenderUpkeepCycle();
|
||||
}
|
||||
|
||||
|
||||
@ -302,7 +302,7 @@ void Assets::PrintLoadInfo() {
|
||||
snprintf(buffer, sizeof(buffer), " %-50s %10s %10s", "FILE",
|
||||
"PRELOAD_TIME", "LOAD_TIME");
|
||||
s += buffer;
|
||||
Log(LogLevel::kInfo, s);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, s);
|
||||
millisecs_t total_preload_time = 0;
|
||||
millisecs_t total_load_time = 0;
|
||||
assert(asset_lists_locked_);
|
||||
@ -315,7 +315,7 @@ void Assets::PrintLoadInfo() {
|
||||
i.second->GetName().c_str(),
|
||||
static_cast_check_fit<int>(preload_time),
|
||||
static_cast_check_fit<int>(load_time));
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||
num++;
|
||||
}
|
||||
assert(asset_lists_locked_);
|
||||
@ -328,7 +328,7 @@ void Assets::PrintLoadInfo() {
|
||||
i.second->GetName().c_str(),
|
||||
static_cast_check_fit<int>(preload_time),
|
||||
static_cast_check_fit<int>(load_time));
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||
num++;
|
||||
}
|
||||
assert(asset_lists_locked_);
|
||||
@ -341,7 +341,7 @@ void Assets::PrintLoadInfo() {
|
||||
i.second->GetName().c_str(),
|
||||
static_cast_check_fit<int>(preload_time),
|
||||
static_cast_check_fit<int>(load_time));
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||
num++;
|
||||
}
|
||||
assert(asset_lists_locked_);
|
||||
@ -354,7 +354,7 @@ void Assets::PrintLoadInfo() {
|
||||
i.second->GetName().c_str(),
|
||||
static_cast_check_fit<int>(preload_time),
|
||||
static_cast_check_fit<int>(load_time));
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||
num++;
|
||||
}
|
||||
assert(asset_lists_locked_);
|
||||
@ -367,7 +367,7 @@ void Assets::PrintLoadInfo() {
|
||||
i.second->file_name_full().c_str(),
|
||||
static_cast_check_fit<int>(preload_time),
|
||||
static_cast_check_fit<int>(load_time));
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||
num++;
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
@ -375,7 +375,7 @@ void Assets::PrintLoadInfo() {
|
||||
"(feeding data to OpenGL, etc): %i",
|
||||
static_cast<int>(total_preload_time),
|
||||
static_cast<int>(total_load_time));
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo, buffer);
|
||||
}
|
||||
|
||||
void Assets::MarkAllAssetsForLoad() {
|
||||
@ -1029,35 +1029,35 @@ void Assets::Prune(int level) {
|
||||
if (kShowPruningInfo) {
|
||||
assert(asset_lists_locked_);
|
||||
if (textures_.size() != old_texture_count) {
|
||||
Log(LogLevel::kInfo, "Textures pruned from "
|
||||
+ std::to_string(old_texture_count) + " to "
|
||||
+ std::to_string(textures_.size()));
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||
"Textures pruned from " + std::to_string(old_texture_count) + " to "
|
||||
+ std::to_string(textures_.size()));
|
||||
}
|
||||
if (text_textures_.size() != old_text_texture_count) {
|
||||
Log(LogLevel::kInfo, "TextTextures pruned from "
|
||||
+ std::to_string(old_text_texture_count) + " to "
|
||||
+ std::to_string(text_textures_.size()));
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||
"TextTextures pruned from " + std::to_string(old_text_texture_count)
|
||||
+ " to " + std::to_string(text_textures_.size()));
|
||||
}
|
||||
if (qr_textures_.size() != old_qr_texture_count) {
|
||||
Log(LogLevel::kInfo, "QrTextures pruned from "
|
||||
+ std::to_string(old_qr_texture_count) + " to "
|
||||
+ std::to_string(qr_textures_.size()));
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||
"QrTextures pruned from " + std::to_string(old_qr_texture_count)
|
||||
+ " to " + std::to_string(qr_textures_.size()));
|
||||
}
|
||||
if (meshes_.size() != old_mesh_count) {
|
||||
Log(LogLevel::kInfo, "Meshes pruned from "
|
||||
+ std::to_string(old_mesh_count) + " to "
|
||||
+ std::to_string(meshes_.size()));
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||
"Meshes pruned from " + std::to_string(old_mesh_count) + " to "
|
||||
+ std::to_string(meshes_.size()));
|
||||
}
|
||||
if (collision_meshes_.size() != old_collision_mesh_count) {
|
||||
Log(LogLevel::kInfo, "CollisionMeshes pruned from "
|
||||
+ std::to_string(old_collision_mesh_count)
|
||||
+ " to "
|
||||
+ std::to_string(collision_meshes_.size()));
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||
"CollisionMeshes pruned from "
|
||||
+ std::to_string(old_collision_mesh_count) + " to "
|
||||
+ std::to_string(collision_meshes_.size()));
|
||||
}
|
||||
if (sounds_.size() != old_sound_count) {
|
||||
Log(LogLevel::kInfo, "Sounds pruned from "
|
||||
+ std::to_string(old_sound_count) + " to "
|
||||
+ std::to_string(sounds_.size()));
|
||||
Log(LogName::kBaAssets, LogLevel::kInfo,
|
||||
"Sounds pruned from " + std::to_string(old_sound_count) + " to "
|
||||
+ 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.
|
||||
if (type == FileType::kSound && name != "blank") {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAssets, LogLevel::kError,
|
||||
"Unable to load audio: '" + name + "'; trying fallback...");
|
||||
return FindAssetFile(type, "blank");
|
||||
} else if (type == FileType::kTexture && name != "white") {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAssets, LogLevel::kError,
|
||||
"Unable to load texture: '" + name + "'; trying fallback...");
|
||||
return FindAssetFile(type, "white");
|
||||
}
|
||||
@ -1228,7 +1228,8 @@ void Assets::AddPackage(const std::string& name, const std::string& path) {
|
||||
assert(g_base->InLogicThread());
|
||||
if (g_buildconfig.debug_build()) {
|
||||
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;
|
||||
@ -1386,7 +1387,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
printed = true;
|
||||
char* c = cJSON_Print(obj);
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaAssets, LogLevel::kError,
|
||||
"found long key 'resource' in raw lstr json: " + std::string(c));
|
||||
free(c);
|
||||
}
|
||||
@ -1406,7 +1407,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
printed = true;
|
||||
char* c = cJSON_Print(obj);
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaAssets, LogLevel::kError,
|
||||
"found long key 'fallback' in raw lstr json: " + std::string(c));
|
||||
free(c);
|
||||
}
|
||||
@ -1431,7 +1432,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
printed = true;
|
||||
char* c = cJSON_Print(obj);
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaAssets, LogLevel::kError,
|
||||
"found long key 'translate' in raw lstr json: " + std::string(c));
|
||||
free(c);
|
||||
}
|
||||
@ -1470,7 +1471,7 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
printed = true;
|
||||
char* c = cJSON_Print(obj);
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaAssets, LogLevel::kError,
|
||||
"found long key 'value' in raw lstr json: " + std::string(c));
|
||||
free(c);
|
||||
}
|
||||
@ -1501,8 +1502,9 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
if (!printed) {
|
||||
printed = true;
|
||||
char* c = cJSON_Print(obj);
|
||||
BA_LOG_ONCE(LogLevel::kError, "found long key 'subs' in raw lstr json: "
|
||||
+ std::string(c));
|
||||
BA_LOG_ONCE(
|
||||
LogName::kBaAssets, LogLevel::kError,
|
||||
"found long key 'subs' in raw lstr json: " + std::string(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());
|
||||
if (root == nullptr) {
|
||||
Log(LogLevel::kError, "CompileResourceString failed (loc " + loc
|
||||
+ "); invalid json: '" + s + "'");
|
||||
Log(LogName::kBaAssets, LogLevel::kError,
|
||||
"CompileResourceString failed (loc " + loc + "); invalid json: '" + s
|
||||
+ "'");
|
||||
*valid = false;
|
||||
return "";
|
||||
}
|
||||
@ -1581,8 +1584,9 @@ auto Assets::CompileResourceString(const std::string& s, const std::string& loc,
|
||||
result = DoCompileResourceString(root);
|
||||
*valid = true;
|
||||
} catch (const std::exception& e) {
|
||||
Log(LogLevel::kError, "CompileResourceString failed (loc " + loc + "): "
|
||||
+ std::string(e.what()) + "; str='" + s + "'");
|
||||
Log(LogName::kBaAssets, LogLevel::kError,
|
||||
"CompileResourceString failed (loc " + loc
|
||||
+ "): " + std::string(e.what()) + "; str='" + s + "'");
|
||||
result = "<error>";
|
||||
*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
|
||||
// the case.
|
||||
if (writing_replay_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAssets, LogLevel::kError,
|
||||
"AssetsServer got BeginWriteReplayCall while already writing");
|
||||
WriteReplayMessages();
|
||||
if (replay_out_file_) {
|
||||
@ -76,7 +76,7 @@ void AssetsServer::PushBeginWriteReplayCall(uint16_t protocol_version) {
|
||||
replay_bytes_written_ = 0;
|
||||
|
||||
if (!replay_out_file_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"unable to open output-stream file: '" + file_path + "'");
|
||||
} else {
|
||||
// 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)) {
|
||||
fclose(replay_out_file_);
|
||||
replay_out_file_ = nullptr;
|
||||
Log(LogLevel::kError, "error writing replay file header: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"error writing replay file header: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
}
|
||||
replay_bytes_written_ = 5;
|
||||
}
|
||||
@ -109,7 +110,7 @@ void AssetsServer::PushAddMessageToReplayCall(
|
||||
|
||||
// Sanity check.
|
||||
if (!writing_replay_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"AssetsServer got AddMessageToReplayCall while not writing replay");
|
||||
replays_broken_ = true;
|
||||
return;
|
||||
@ -120,7 +121,7 @@ void AssetsServer::PushAddMessageToReplayCall(
|
||||
// If we've got too much data built up (lets go with 10 megs for now),
|
||||
// abort.
|
||||
if (replay_message_bytes_ > 10000000) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"replay output buffer exceeded 10 megs; aborting replay");
|
||||
fclose(replay_out_file_);
|
||||
replay_out_file_ = nullptr;
|
||||
@ -142,7 +143,8 @@ void AssetsServer::PushEndWriteReplayCall() {
|
||||
|
||||
// Sanity check.
|
||||
if (!writing_replay_) {
|
||||
Log(LogLevel::kError, "_finishWritingReplay called while not writing");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"_finishWritingReplay called while not writing");
|
||||
replays_broken_ = true;
|
||||
return;
|
||||
}
|
||||
@ -179,8 +181,9 @@ void AssetsServer::WriteReplayMessages() {
|
||||
if (fwrite(&len8, 1, 1, replay_out_file_) != 1) {
|
||||
fclose(replay_out_file_);
|
||||
replay_out_file_ = nullptr;
|
||||
Log(LogLevel::kError, "error writing replay file: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"error writing replay file: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -191,16 +194,18 @@ void AssetsServer::WriteReplayMessages() {
|
||||
if (fwrite(&len16, 2, 1, replay_out_file_) != 1) {
|
||||
fclose(replay_out_file_);
|
||||
replay_out_file_ = nullptr;
|
||||
Log(LogLevel::kError, "error writing replay file: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"error writing replay file: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (fwrite(&len32, 4, 1, replay_out_file_) != 1) {
|
||||
fclose(replay_out_file_);
|
||||
replay_out_file_ = nullptr;
|
||||
Log(LogLevel::kError, "error writing replay file: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"error writing replay file: "
|
||||
+ g_core->platform->GetErrnoString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -211,7 +216,7 @@ void AssetsServer::WriteReplayMessages() {
|
||||
if (result != 1) {
|
||||
fclose(replay_out_file_);
|
||||
replay_out_file_ = nullptr;
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"error writing replay file: " + g_core->platform->GetErrnoString());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -62,8 +62,9 @@ static auto LoadOgg(const char* file_name, std::vector<char>* buffer,
|
||||
f = g_core->platform->FOpen(file_name, "rb");
|
||||
if (f == nullptr) {
|
||||
fallback = true;
|
||||
Log(LogLevel::kError, std::string("Can't open sound file '") + file_name
|
||||
+ "' for reading...");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
std::string("Can't open sound file '") + file_name
|
||||
+ "' for reading...");
|
||||
|
||||
// Attempt a fallback standin; if that doesn't work, throw in the towel.
|
||||
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
|
||||
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 + "'");
|
||||
|
||||
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
|
||||
// something like that.
|
||||
if (*format != AL_FORMAT_MONO16 && *format != AL_FORMAT_STEREO16) {
|
||||
Log(LogLevel::kError, std::string("Ignoring invalid audio cache of ")
|
||||
+ file_name + " with format "
|
||||
+ std::to_string(*format));
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
std::string("Ignoring invalid audio cache of ") + file_name
|
||||
+ " with format " + std::to_string(*format));
|
||||
} else {
|
||||
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;"
|
||||
" please use shorter urls. (url=%s)",
|
||||
qr_url.size(), soft_limit, qr_url.c_str());
|
||||
Log(LogLevel::kWarning, buffer);
|
||||
Log(LogName::kBaAssets, LogLevel::kWarning, buffer);
|
||||
}
|
||||
file_name_ = qr_url;
|
||||
valid_ = true;
|
||||
|
||||
@ -18,14 +18,15 @@ namespace ballistica::base {
|
||||
|
||||
void _check_al_error(const char* file, int line) {
|
||||
if (g_base->audio_server->paused()) {
|
||||
Log(LogLevel::kError, Utils::BaseName(file) + ":" + std::to_string(line)
|
||||
+ ": Checking OpenAL error while paused.");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
Utils::BaseName(file) + ":" + std::to_string(line)
|
||||
+ ": Checking OpenAL error while paused.");
|
||||
}
|
||||
ALenum al_err = alGetError();
|
||||
if (al_err != AL_NO_ERROR) {
|
||||
Log(LogLevel::kError, Utils::BaseName(file) + ":" + std::to_string(line)
|
||||
+ ": OpenAL Error: " + GetALErrorString(al_err)
|
||||
+ ";");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
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 {};
|
||||
}
|
||||
if (!g_base->InLogicThread()) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Audio::SafePlaySysSound called from non-logic thread. id="
|
||||
+ std::to_string(static_cast<int>(sound_id)));
|
||||
return {};
|
||||
}
|
||||
if (!g_base->assets->sys_assets_loaded()) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"Audio::SafePlaySysSound called before sys assets loaded. id="
|
||||
+ std::to_string(static_cast<int>(sound_id)));
|
||||
return {};
|
||||
}
|
||||
if (!g_base->assets->IsValidSysSound(sound_id)) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"Audio::SafePlaySysSound called with invalid sound_id. id="
|
||||
+ std::to_string(static_cast<int>(sound_id)));
|
||||
return {};
|
||||
|
||||
@ -179,8 +179,9 @@ static void ALEventCallback_(ALenum eventType, ALuint object, ALuint param,
|
||||
[] { g_base->audio_server->OnDeviceDisconnected(); });
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kWarning, "Got unexpected OpenAL callback event "
|
||||
+ std::to_string(static_cast<int>(eventType)));
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"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(),
|
||||
prefix2)
|
||||
== 0) {
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaAudio, LogLevel::kInfo,
|
||||
"Xiaomi Android 11 detected; using OpenSL instead of AAudio.");
|
||||
g_core->platform->SetEnv("BA_OBOE_USE_OPENSLES", "1");
|
||||
}
|
||||
@ -260,7 +261,8 @@ void AudioServer::OnAppStartInThread_() {
|
||||
ALboolean enumeration =
|
||||
alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT");
|
||||
if (enumeration == AL_FALSE) {
|
||||
Log(LogLevel::kError, "OpenAL enumeration extensions missing.");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"OpenAL enumeration extensions missing.");
|
||||
} else {
|
||||
const ALCchar* devices =
|
||||
alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
|
||||
@ -298,7 +300,7 @@ void AudioServer::OnAppStartInThread_() {
|
||||
if (!device) {
|
||||
if (g_buildconfig.ostype_android()) {
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"------------------------"
|
||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||
+ openalsoft_android_log_
|
||||
@ -315,11 +317,11 @@ void AudioServer::OnAppStartInThread_() {
|
||||
|
||||
// Android special case: if we fail, try again after a few seconds.
|
||||
if (!impl_->alc_context && g_buildconfig.ostype_android()) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Failed creating AL context; waiting and trying again.");
|
||||
{
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"------------------------"
|
||||
" OPENALSOFT-ERROR-LOG-BEGIN ----------------------\n"
|
||||
+ openalsoft_android_log_
|
||||
@ -334,7 +336,7 @@ void AudioServer::OnAppStartInThread_() {
|
||||
|
||||
if (!device) {
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"------------------------"
|
||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||
+ openalsoft_android_log_
|
||||
@ -346,17 +348,18 @@ void AudioServer::OnAppStartInThread_() {
|
||||
impl_->alc_context = alcCreateContext(device, nullptr);
|
||||
if (impl_->alc_context) {
|
||||
// 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.
|
||||
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.");
|
||||
{
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"------------------------"
|
||||
" OPENALSOFT-ERROR-LOG-BEGIN ----------------------\n"
|
||||
+ openalsoft_android_log_
|
||||
@ -370,7 +373,7 @@ void AudioServer::OnAppStartInThread_() {
|
||||
alGetError(); // Clear any errors.
|
||||
if (!device) {
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"------------------------"
|
||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||
+ openalsoft_android_log_
|
||||
@ -382,7 +385,8 @@ void AudioServer::OnAppStartInThread_() {
|
||||
impl_->alc_context = alcCreateContext(device, nullptr);
|
||||
if (impl_->alc_context) {
|
||||
// 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 (g_buildconfig.ostype_android()) {
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"------------------------"
|
||||
" OPENALSOFT-FATAL-ERROR-LOG-BEGIN ----------------------\n"
|
||||
+ openalsoft_android_log_
|
||||
@ -459,8 +463,9 @@ void AudioServer::OnAppStartInThread_() {
|
||||
sound_source_refs_.push_back(s);
|
||||
sources_.push_back(&(*s));
|
||||
} else {
|
||||
Log(LogLevel::kError, "Made " + std::to_string(i) + " sources; (wanted "
|
||||
+ std::to_string(target_source_count) + ").");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Made " + std::to_string(i) + " sources; (wanted "
|
||||
+ std::to_string(target_source_count) + ").");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -498,20 +503,23 @@ void AudioServer::CompleteShutdown_() {
|
||||
#if BA_ENABLE_AUDIO
|
||||
ALCboolean check = alcMakeContextCurrent(nullptr);
|
||||
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);
|
||||
if (!device) {
|
||||
Log(LogLevel::kWarning, "Unable to get ALCdevice at shutdown.");
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"Unable to get ALCdevice at shutdown.");
|
||||
} else {
|
||||
alcDestroyContext(impl_->alc_context);
|
||||
ALenum err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
Log(LogLevel::kWarning, "Error on AL shutdown.");
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning, "Error on AL shutdown.");
|
||||
}
|
||||
check = alcCloseDevice(device);
|
||||
if (!check) {
|
||||
Log(LogLevel::kWarning, "Error on alcCloseDevice at shutdown.");
|
||||
Log(LogName::kBaAudio, LogLevel::kWarning,
|
||||
"Error on alcCloseDevice at shutdown.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -534,7 +542,7 @@ struct AudioServer::SoundFadeNode_ {
|
||||
void AudioServer::SetSuspended_(bool suspend) {
|
||||
if (!suspended_) {
|
||||
if (!suspend) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Got audio unsuspend request when already unsuspended.");
|
||||
} else {
|
||||
#if BA_OSTYPE_IOS_TVOS
|
||||
@ -557,7 +565,7 @@ void AudioServer::SetSuspended_(bool suspend) {
|
||||
+ std::to_string(g_core->GetAppTimeSeconds()));
|
||||
alcDevicePauseSOFT(device);
|
||||
} catch (const std::exception& e) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Error in alcDevicePauseSOFT at time "
|
||||
+ std::to_string(g_core->GetAppTimeSeconds())
|
||||
+ "( playing since "
|
||||
@ -565,7 +573,8 @@ void AudioServer::SetSuspended_(bool suspend) {
|
||||
+ "): " + g_core->platform->DemangleCXXSymbol(typeid(e).name())
|
||||
+ " " + e.what());
|
||||
} catch (...) {
|
||||
Log(LogLevel::kError, "Unknown error in alcDevicePauseSOFT");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Unknown error in alcDevicePauseSOFT");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -574,7 +583,7 @@ void AudioServer::SetSuspended_(bool suspend) {
|
||||
} else {
|
||||
// Unsuspend if requested.
|
||||
if (suspend) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Got audio suspend request when already suspended.");
|
||||
} else {
|
||||
#if BA_OSTYPE_IOS_TVOS
|
||||
@ -599,13 +608,14 @@ void AudioServer::SetSuspended_(bool suspend) {
|
||||
+ std::to_string(g_core->GetAppTimeSeconds()));
|
||||
alcDeviceResumeSOFT(device);
|
||||
} catch (const std::exception& e) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Error in alcDeviceResumeSOFT at time "
|
||||
+ std::to_string(g_core->GetAppTimeSeconds()) + ": "
|
||||
+ g_core->platform->DemangleCXXSymbol(typeid(e).name()) + " "
|
||||
+ e.what());
|
||||
} catch (...) {
|
||||
Log(LogLevel::kError, "Unknown error in alcDeviceResumeSOFT");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Unknown error in alcDeviceResumeSOFT");
|
||||
}
|
||||
#endif
|
||||
last_started_playing_time_ = g_core->GetAppTimeSeconds();
|
||||
@ -777,7 +787,7 @@ void AudioServer::UpdateAvailableSources_() {
|
||||
// that probably means somebody's grabbing a source but never
|
||||
// resubmitting it.
|
||||
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; "
|
||||
"probably leaked. (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
|
||||
&& 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()) {
|
||||
std::scoped_lock lock(openalsoft_android_log_mutex_);
|
||||
openalsoft_android_log_ +=
|
||||
@ -995,7 +1006,7 @@ void AudioServer::ProcessDeviceDisconnects_(seconds_t real_time_seconds) {
|
||||
shipped_reconnect_logs_ = true;
|
||||
if (g_buildconfig.ostype_android()) {
|
||||
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"
|
||||
"------------------------"
|
||||
" OPENALSOFT-RECONNECT-LOG-BEGIN ----------------------\n"
|
||||
@ -1153,8 +1164,9 @@ AudioServer::ThreadSource_::ThreadSource_(AudioServer* audio_server_in,
|
||||
ALenum err = alGetError();
|
||||
valid_ = (err == AL_NO_ERROR);
|
||||
if (!valid_) {
|
||||
Log(LogLevel::kError, std::string("AL Error ") + GetALErrorString(err)
|
||||
+ " on source creation.");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
std::string("AL Error ") + GetALErrorString(err)
|
||||
+ " on source creation.");
|
||||
} else {
|
||||
// In vr mode we keep the microphone a bit closer to the camera
|
||||
// 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;
|
||||
}
|
||||
if (oob) {
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaAudio, LogLevel::kError,
|
||||
"AudioServer::ThreadSource::SetPosition"
|
||||
" got out-of-bounds value.");
|
||||
}
|
||||
|
||||
@ -42,7 +42,8 @@ void AudioSource::SetPosition(float x, float y, float z) {
|
||||
assert(client_queue_size_ > 0);
|
||||
#if BA_DEBUG_BUILD
|
||||
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
|
||||
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
|
||||
// "processed" buffers than we have queued.
|
||||
if (queued < processed) {
|
||||
Log(LogLevel::kError, "Streamer oddness: queued(" + std::to_string(queued)
|
||||
+ "); processed(" + std::to_string(processed)
|
||||
+ ")");
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Streamer oddness: queued(" + std::to_string(queued) + "); processed("
|
||||
+ std::to_string(processed) + ")");
|
||||
processed = queued;
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ void OggStream::DoStream(char* pcm, int* size, unsigned int* rate) {
|
||||
static bool reported_error = false;
|
||||
if (!reported_error) {
|
||||
reported_error = true;
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaAudio, LogLevel::kError,
|
||||
"Error streaming ogg file: '" + file_name() + "'.");
|
||||
}
|
||||
if (loops()) {
|
||||
|
||||
@ -31,10 +31,10 @@
|
||||
#include "ballistica/base/support/plus_soft.h"
|
||||
#include "ballistica/base/support/stdio_console.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/logging.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/shared/math/vector4f.h"
|
||||
#include "ballistica/shared/python/python_command.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
@ -125,11 +125,6 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
|
||||
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
|
||||
// checks to make sure we aren't importing them reciprocally when they
|
||||
// import us.
|
||||
@ -160,7 +155,7 @@ void BaseFeatureSet::SuccessScreenMessage() {
|
||||
python->objs().Get(BasePython::ObjID::kSuccessMessageCall).Call();
|
||||
});
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"SuccessScreenMessage called without logic event_loop in place.");
|
||||
}
|
||||
}
|
||||
@ -171,7 +166,7 @@ void BaseFeatureSet::ErrorScreenMessage() {
|
||||
python->objs().Get(BasePython::ObjID::kErrorMessageCall).Call();
|
||||
});
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"ErrorScreenMessage called without logic event_loop in place.");
|
||||
}
|
||||
}
|
||||
@ -186,7 +181,8 @@ auto BaseFeatureSet::GetV2AccountID() -> std::optional<std::string> {
|
||||
}
|
||||
return result.ValueAsString();
|
||||
} else {
|
||||
Log(LogLevel::kError, "GetV2AccountID() py call errored.");
|
||||
Log(LogName::kBaAccount, LogLevel::kError,
|
||||
"GetV2AccountID() py call errored.");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@ -219,7 +215,7 @@ void BaseFeatureSet::StartApp() {
|
||||
|
||||
// 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).
|
||||
python->ReadConfig();
|
||||
// python->ReadConfig();
|
||||
|
||||
// Allow our subsystems to start doing work in their own threads and
|
||||
// communicating with other subsystems. Note that we may still want to run
|
||||
@ -262,7 +258,7 @@ void BaseFeatureSet::StartApp() {
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"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());
|
||||
|
||||
if (app_suspended_) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBa, LogLevel::kWarning,
|
||||
"AppAdapter::SuspendApp() called with app already suspended.");
|
||||
return;
|
||||
}
|
||||
@ -313,7 +309,7 @@ void BaseFeatureSet::SuspendApp() {
|
||||
// running_loop_count = loops.size();
|
||||
if (running_loops.empty()) {
|
||||
if (g_buildconfig.debug_build()) {
|
||||
Log(LogLevel::kDebug,
|
||||
Log(LogName::kBa, LogLevel::kDebug,
|
||||
"SuspendApp() completed in "
|
||||
+ std::to_string(core::CorePlatform::GetCurrentMillisecs()
|
||||
- start_time)
|
||||
@ -374,7 +370,7 @@ void BaseFeatureSet::SuspendApp() {
|
||||
}
|
||||
msg += ").";
|
||||
|
||||
Log(LogLevel::kError, msg);
|
||||
Log(LogName::kBa, LogLevel::kError, msg);
|
||||
}
|
||||
|
||||
void BaseFeatureSet::UnsuspendApp() {
|
||||
@ -382,7 +378,7 @@ void BaseFeatureSet::UnsuspendApp() {
|
||||
assert(g_core->InMainThread());
|
||||
|
||||
if (!app_suspended_) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBa, LogLevel::kWarning,
|
||||
"AppAdapter::UnsuspendApp() called with app not in suspendedstate.");
|
||||
return;
|
||||
}
|
||||
@ -400,7 +396,7 @@ void BaseFeatureSet::UnsuspendApp() {
|
||||
g_base->networking->OnAppUnsuspend();
|
||||
|
||||
if (g_buildconfig.debug_build()) {
|
||||
Log(LogLevel::kDebug,
|
||||
Log(LogName::kBa, LogLevel::kDebug,
|
||||
"UnsuspendApp() completed in "
|
||||
+ std::to_string(core::CorePlatform::GetCurrentMillisecs()
|
||||
- start_time)
|
||||
@ -431,7 +427,7 @@ void BaseFeatureSet::LogVersionInfo_() {
|
||||
snprintf(buffer, sizeof(buffer), "BallisticaKit %s build %d.",
|
||||
kEngineVersion, kEngineBuildNumber);
|
||||
}
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBa, LogLevel::kInfo, buffer);
|
||||
}
|
||||
|
||||
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
|
||||
// since that's in place before any app mode is officially set).
|
||||
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.");
|
||||
}
|
||||
|
||||
@ -568,7 +564,8 @@ auto BaseFeatureSet::GetAppInstanceUUID() -> const std::string& {
|
||||
if (!have_app_instance_uuid) {
|
||||
// As an emergency fallback simply use a single random number. We
|
||||
// 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>(
|
||||
core::CorePlatform::GetCurrentMillisecs())); // NOLINT
|
||||
app_instance_uuid =
|
||||
@ -576,7 +573,8 @@ auto BaseFeatureSet::GetAppInstanceUUID() -> const std::string& {
|
||||
have_app_instance_uuid = true;
|
||||
}
|
||||
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;
|
||||
@ -668,6 +666,7 @@ void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
warned = true;
|
||||
printf("MSG %s\n", msg.c_str());
|
||||
printf(
|
||||
"WARNING: V1CloudLog called before babase fully imported; "
|
||||
"ignoring.\n");
|
||||
@ -725,8 +724,9 @@ void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {
|
||||
plus()->DirectSendV1CloudLogs(logprefix, logsuffix, false, nullptr);
|
||||
}
|
||||
|
||||
void BaseFeatureSet::PushDevConsolePrintCall(const std::string& msg) {
|
||||
ui->PushDevConsolePrintCall(msg);
|
||||
void BaseFeatureSet::PushDevConsolePrintCall(const std::string& msg,
|
||||
float scale, Vector4f color) {
|
||||
ui->PushDevConsolePrintCall(msg, scale, color);
|
||||
}
|
||||
|
||||
PyObject* BaseFeatureSet::GetPyExceptionType(PyExcType exctype) {
|
||||
@ -833,7 +833,7 @@ void BaseFeatureSet::DoPushObjCall(const PythonObjectSetBase* objset, int id) {
|
||||
});
|
||||
} else {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBa, LogLevel::kError,
|
||||
"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
|
||||
// row; might imply faulty logic on an app-adapter or whatnot.
|
||||
if (app_active_set_ && app_active_ == active) {
|
||||
Log(LogLevel::kWarning, "SetAppActive called with state "
|
||||
+ std::to_string(active) + " twice in a row.");
|
||||
Log(LogName::kBa, LogLevel::kWarning,
|
||||
"SetAppActive called with state " + std::to_string(active)
|
||||
+ " twice in a row.");
|
||||
}
|
||||
app_active_set_ = true;
|
||||
app_active_ = active;
|
||||
|
||||
@ -731,7 +731,8 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
|
||||
-> PyObject* override;
|
||||
auto FeatureSetFromData(PyObject* obj) -> FeatureSetNativeComponent* 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 PrintPythonStackTrace() -> bool override;
|
||||
auto GetPyLString(PyObject* obj) -> std::string override;
|
||||
|
||||
@ -72,8 +72,8 @@ void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass a newly allocated raw pointer to the bg-dynamics thread; it takes care
|
||||
// of disposing it when done.
|
||||
// Pass a newly allocated raw pointer to the bg-dynamics thread; it takes
|
||||
// care of disposing it when done.
|
||||
auto d = Object::NewDeferred<BGDynamicsServer::StepData>();
|
||||
d->graphics_quality = Graphics::GraphicsQualityFromRequest(
|
||||
g_base->graphics->settings()->graphics_quality,
|
||||
|
||||
@ -1372,7 +1372,7 @@ void BGDynamicsServer::Emit(const BGDynamicsEmission& def) {
|
||||
}
|
||||
default: {
|
||||
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));
|
||||
break;
|
||||
}
|
||||
@ -2361,9 +2361,9 @@ void BGDynamicsServer::Step(StepData* step_data) {
|
||||
|
||||
// Math sanity check.
|
||||
if (step_count_ < 0) {
|
||||
BA_LOG_ONCE(LogLevel::kWarning, "BGDynamics step_count too low ("
|
||||
+ std::to_string(step_count_)
|
||||
+ "); should not happen.");
|
||||
BA_LOG_ONCE(LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"BGDynamics step_count too low (" + std::to_string(step_count_)
|
||||
+ "); should not happen.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2376,9 +2376,9 @@ void BGDynamicsServer::PushStep(StepData* data) {
|
||||
|
||||
// Client thread should stop feeding us if we get clogged up.
|
||||
if (step_count_ > 5) {
|
||||
BA_LOG_ONCE(LogLevel::kWarning, "BGDynamics step_count too high ("
|
||||
+ std::to_string(step_count_)
|
||||
+ "); should not happen.");
|
||||
BA_LOG_ONCE(LogName::kBa, LogLevel::kWarning,
|
||||
"BGDynamics step_count too high (" + std::to_string(step_count_)
|
||||
+ "); should not happen.");
|
||||
}
|
||||
|
||||
event_loop()->PushCall([this, data] { Step(data); });
|
||||
|
||||
@ -80,7 +80,7 @@ class RendererGL::MeshAssetDataGL : public MeshAssetRendererData {
|
||||
}
|
||||
case 4: {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kWarning,
|
||||
LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"GL WARNING - USING 32 BIT INDICES WHICH WONT WORK IN ES2!!");
|
||||
elem_count_ = static_cast<uint32_t>(model.indices32().size());
|
||||
index_type_ = GL_UNSIGNED_INT;
|
||||
|
||||
@ -126,7 +126,7 @@ class RendererGL::MeshDataGL : public MeshRendererData {
|
||||
dynamic_draw_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
||||
index_state_ = data->state;
|
||||
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!!");
|
||||
index_type_ = GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ class RendererGL::ProgramBlurGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
@ -121,7 +121,7 @@ class RendererGL::ProgramBlurGL : public RendererGL::ProgramGL {
|
||||
"(colorTex,vUV8));\n"
|
||||
"}";
|
||||
if (flags & SHD_DEBUG_PRINT) {
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
}
|
||||
return s;
|
||||
|
||||
@ -49,7 +49,7 @@ class RendererGL::ShaderGL : public Object {
|
||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||
// 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.
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
std::string("Compile failed for ") + GetTypeName()
|
||||
+ " shader:\n------------SOURCE BEGIN-------------\n" + src_fin
|
||||
+ "\n-----------SOURCE END-------------\n" + GetInfo()
|
||||
@ -65,7 +65,7 @@ class RendererGL::ShaderGL : public Object {
|
||||
const char* version = (const char*)glGetString(GL_VERSION);
|
||||
const char* vendor = (const char*)glGetString(GL_VENDOR);
|
||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
std::string("WARNING: info returned for ") + GetTypeName()
|
||||
+ " shader:\n------------SOURCE BEGIN-------------\n" + src_fin
|
||||
+ "\n-----------SOURCE END-------------\n" + info
|
||||
@ -166,7 +166,7 @@ class RendererGL::ProgramGL {
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(program_, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus == GL_FALSE) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"Link failed for program '" + name_ + "':\n" + GetInfo());
|
||||
} else {
|
||||
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:"))) {
|
||||
Log(LogLevel::kError, "WARNING: program using frag shader '" + name_
|
||||
+ "' returned info:\n" + info);
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"WARNING: program using frag shader '" + name_
|
||||
+ "' returned info:\n" + info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,9 +315,9 @@ class RendererGL::ProgramGL {
|
||||
assert(IsBound());
|
||||
int c = glGetUniformLocation(program_, tex_name);
|
||||
if (c == -1) {
|
||||
Log(LogLevel::kError, "ShaderGL: " + name_
|
||||
+ ": Can't set texture unit for texture '"
|
||||
+ tex_name + "'");
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"ShaderGL: " + name_ + ": Can't set texture unit for texture '"
|
||||
+ tex_name + "'");
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
} else {
|
||||
glUniform1i(c, unit);
|
||||
|
||||
@ -235,7 +235,7 @@ class RendererGL::ProgramObjectGL : public RendererGL::ProgramGL {
|
||||
}
|
||||
s += "}";
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
@ -321,7 +321,7 @@ class RendererGL::ProgramObjectGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ class RendererGL::ProgramPostProcessGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
@ -306,7 +306,7 @@ class RendererGL::ProgramPostProcessGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ class RendererGL::ProgramShieldGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
@ -114,7 +114,7 @@ class RendererGL::ProgramShieldGL : public RendererGL::ProgramGL {
|
||||
//" " BA_GLSL_FRAGCOLOR " = vec4(vec3(depth),1);\n"
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ class RendererGL::ProgramSimpleGL : public RendererGL::ProgramGL {
|
||||
"}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT) {
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
}
|
||||
|
||||
@ -383,7 +383,7 @@ class RendererGL::ProgramSimpleGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT) {
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
}
|
||||
|
||||
|
||||
@ -114,7 +114,7 @@ class RendererGL::ProgramSmokeGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
@ -160,7 +160,7 @@ class RendererGL::ProgramSmokeGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT)
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#include "ballistica/base/graphics/gl/program/program_gl.h"
|
||||
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -121,7 +122,7 @@ class RendererGL::ProgramSpriteGL : public RendererGL::ProgramGL {
|
||||
s += "}";
|
||||
|
||||
if (flags & SHD_DEBUG_PRINT) {
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nVertex code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
}
|
||||
return s;
|
||||
@ -163,7 +164,7 @@ class RendererGL::ProgramSpriteGL : public RendererGL::ProgramGL {
|
||||
}
|
||||
s += "}";
|
||||
if (flags & SHD_DEBUG_PRINT) {
|
||||
Log(LogLevel::kInfo,
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
"\nFragment code for shader '" + GetName(flags) + "':\n\n" + s);
|
||||
}
|
||||
return s;
|
||||
|
||||
@ -60,7 +60,7 @@ class RendererGL::RenderTargetGL : public RenderTarget {
|
||||
// this needs to be on for glClear to work on depth.
|
||||
if (!renderer_->depth_writing_enabled_) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kWarning,
|
||||
LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"RendererGL: depth-writing not enabled when clearing depth");
|
||||
}
|
||||
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
@ -90,7 +90,7 @@ void RendererGL::CheckGLError(const char* file, int line) {
|
||||
BA_PRECONDITION_FATAL(vendor);
|
||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||
BA_PRECONDITION_FATAL(renderer);
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"OpenGL Error at " + std::string(file) + " line " + std::to_string(line)
|
||||
+ ": " + GLErrorToString(err) + "\nrenderer: " + renderer
|
||||
+ "\nvendor: " + vendor + "\nversion: " + version
|
||||
@ -174,7 +174,7 @@ void RendererGL::CheckGLVersion() {
|
||||
if (gl_is_es()) {
|
||||
// GL ES version strings start with 'OpenGL ES X' with X being version.
|
||||
const char* prefix = "OpenGL ES ";
|
||||
int prefixlen = strlen(prefix);
|
||||
auto prefixlen = strlen(prefix);
|
||||
BA_PRECONDITION_FATAL(!strncmp(version_str, prefix, prefixlen));
|
||||
if (version_str[prefixlen] != '3') {
|
||||
FatalError(
|
||||
@ -223,11 +223,9 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
basestr = "OpenGL";
|
||||
}
|
||||
|
||||
if (g_buildconfig.debug_build()) {
|
||||
Log(LogLevel::kInfo, std::string("Using ") + basestr + " (vendor: " + vendor
|
||||
+ ", renderer: " + renderer
|
||||
+ ", version: " + version_str + ").");
|
||||
}
|
||||
Log(LogName::kBaGraphics, LogLevel::kInfo,
|
||||
std::string("Using ") + basestr + " (vendor: " + vendor
|
||||
+ ", renderer: " + renderer + ", version: " + version_str + ").");
|
||||
|
||||
// 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
|
||||
@ -246,7 +244,8 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
extensions.push_back(extension);
|
||||
}
|
||||
} 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.
|
||||
// (Can probably kill this).
|
||||
auto* ex = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
@ -292,7 +291,8 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
c_types.push_back(TextureCompressionType::kETC1);
|
||||
} else {
|
||||
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]);
|
||||
msaa_max_samples_rgb565_ = samples[0];
|
||||
} 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;
|
||||
}
|
||||
|
||||
@ -374,7 +375,8 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
&samples[0]);
|
||||
msaa_max_samples_rgb8_ = samples[0];
|
||||
} 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;
|
||||
}
|
||||
} else {
|
||||
@ -2385,7 +2387,7 @@ void RendererGL::UpdateVignetteTex_(bool force) {
|
||||
if (err != GL_NO_ERROR) {
|
||||
static bool reported = false;
|
||||
if (!reported) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"32-bit vignette creation failed; falling back to 16.");
|
||||
reported = true;
|
||||
}
|
||||
@ -2443,7 +2445,8 @@ void RendererGL::UpdateVignetteTex_(bool force) {
|
||||
|
||||
auto RendererGL::GetFunkyDepthIssue_() -> bool {
|
||||
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_;
|
||||
}
|
||||
|
||||
@ -27,7 +27,8 @@ class RendererGL::TextureDataGL : public TextureAssetRendererData {
|
||||
|
||||
~TextureDataGL() override {
|
||||
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 {
|
||||
// If we're currently bound as anything, clear that out (otherwise a
|
||||
// new texture with that same ID won't be bindable).
|
||||
|
||||
@ -204,7 +204,7 @@ auto Graphics::TextureQualityFromAppConfig() -> TextureQualityRequest {
|
||||
} else if (texqualstr == "Low") {
|
||||
texture_quality_requested = TextureQualityRequest::kLow;
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"Invalid texture quality: '" + texqualstr + "'; defaulting to low.");
|
||||
texture_quality_requested = TextureQualityRequest::kLow;
|
||||
}
|
||||
@ -221,7 +221,8 @@ auto Graphics::VSyncFromAppConfig() -> VSyncRequest {
|
||||
} else if (v_sync == "Never") {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -240,7 +241,7 @@ auto Graphics::GraphicsQualityFromAppConfig() -> GraphicsQualityRequest {
|
||||
} else if (gqualstr == "Low") {
|
||||
graphics_quality_requested = GraphicsQualityRequest::kLow;
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"Invalid graphics quality: '" + gqualstr + "'; defaulting to auto.");
|
||||
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)
|
||||
if (fade_end_call_.Exists()) {
|
||||
if (g_buildconfig.debug_build()) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"2 fades overlapping; running first fade-end-call early.");
|
||||
}
|
||||
fade_end_call_->Schedule();
|
||||
@ -861,7 +862,7 @@ void Graphics::BuildAndPushFrameDef() {
|
||||
if (g_core->vr_mode()) {
|
||||
if (frame_def->GetOverlayFlatPass()->HasDrawCommands()) {
|
||||
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; "
|
||||
"shouldn't happen!");
|
||||
}
|
||||
@ -1015,7 +1016,7 @@ void Graphics::DrawFades(FrameDef* frame_def) {
|
||||
// TEMP HACK - don't trigger this while inactive.
|
||||
// Need to make overall fade logic smarter.
|
||||
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_ = 1.0f;
|
||||
fade_time_ = 1000;
|
||||
@ -1513,8 +1514,9 @@ void Graphics::DrawRadialMeter(MeshIndexedSimpleFull* m, float amt) {
|
||||
|
||||
void Graphics::OnScreenSizeChange() {}
|
||||
|
||||
void Graphics::CalcVirtualRes_(float* x, float* y) {
|
||||
assert(g_base);
|
||||
void Graphics::GetBaseVirtualRes(float* x, float* y) {
|
||||
assert(x);
|
||||
assert(y);
|
||||
float base_virtual_res_x;
|
||||
float base_virtual_res_y;
|
||||
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_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 y_in = *y;
|
||||
@ -1662,7 +1673,7 @@ auto Graphics::ReflectionTypeFromString(const std::string& s)
|
||||
void Graphics::LanguageChanged() {
|
||||
assert(g_base && g_base->InLogicThread());
|
||||
if (building_frame_def_) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBa, LogLevel::kWarning,
|
||||
"Graphics::LanguageChanged() called during draw; should not happen.");
|
||||
}
|
||||
screenmessages->ClearScreenMessageTranslations();
|
||||
@ -1683,8 +1694,9 @@ auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request,
|
||||
case GraphicsQualityRequest::kAuto:
|
||||
return auto_val;
|
||||
default:
|
||||
Log(LogLevel::kError, "Unhandled GraphicsQualityRequest value: "
|
||||
+ std::to_string(static_cast<int>(request)));
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Unhandled GraphicsQualityRequest value: "
|
||||
+ std::to_string(static_cast<int>(request)));
|
||||
return GraphicsQuality::kLow;
|
||||
}
|
||||
}
|
||||
@ -1702,8 +1714,9 @@ auto Graphics::TextureQualityFromRequest(TextureQualityRequest request,
|
||||
case TextureQualityRequest::kAuto:
|
||||
return auto_val;
|
||||
default:
|
||||
Log(LogLevel::kError, "Unhandled TextureQualityRequest value: "
|
||||
+ std::to_string(static_cast<int>(request)));
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"Unhandled TextureQualityRequest value: "
|
||||
+ std::to_string(static_cast<int>(request)));
|
||||
return TextureQuality::kLow;
|
||||
}
|
||||
}
|
||||
@ -1747,13 +1760,8 @@ void Graphics::DrawUIBounds(RenderPass* pass) {
|
||||
auto xf = c.ScopedTransform();
|
||||
|
||||
float width, height;
|
||||
if (g_base->ui->scale() == UIScale::kSmall) {
|
||||
width = kBaseVirtualResSmallX;
|
||||
height = kBaseVirtualResSmallY;
|
||||
} else {
|
||||
width = kBaseVirtualResX;
|
||||
height = kBaseVirtualResY;
|
||||
}
|
||||
|
||||
GetBaseVirtualRes(&width, &height);
|
||||
|
||||
// Slight offset in z to reduce z fighting.
|
||||
c.Translate(0.5f * pass->virtual_width(), 0.5f * pass->virtual_height(),
|
||||
|
||||
@ -153,6 +153,7 @@ class Graphics {
|
||||
}
|
||||
|
||||
void DrawUIBounds(RenderPass* pass);
|
||||
static void GetBaseVirtualRes(float* x, float* y);
|
||||
|
||||
// Enable progress bar drawing locally.
|
||||
void EnableProgressBar(bool fade_in);
|
||||
|
||||
@ -178,7 +178,7 @@ auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* {
|
||||
millisecs_t t = g_core->GetAppTimeMillisecs() - start_time;
|
||||
if (t >= 1000) {
|
||||
if (g_buildconfig.debug_build()) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"GraphicsServer: timed out at " + std::to_string(t)
|
||||
+ "ms waiting for logic thread to send us a FrameDef.");
|
||||
}
|
||||
@ -266,7 +266,8 @@ void GraphicsServer::ReloadLostRenderer() {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
if (!renderer_) {
|
||||
Log(LogLevel::kError, "No renderer on GraphicsServer::ReloadLostRenderer.");
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"No renderer on GraphicsServer::ReloadLostRenderer.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -323,11 +324,12 @@ void GraphicsServer::set_renderer(Renderer* renderer) {
|
||||
void GraphicsServer::LoadRenderer() {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!renderer_) {
|
||||
Log(LogLevel::kError, "LoadRenderer() called with no renderer present.");
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"LoadRenderer() called with no renderer present.");
|
||||
return;
|
||||
}
|
||||
if (renderer_loaded_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"LoadRenderer() called with an already-loaded renderer present.");
|
||||
return;
|
||||
}
|
||||
@ -369,11 +371,12 @@ void GraphicsServer::LoadRenderer() {
|
||||
void GraphicsServer::UnloadRenderer() {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!renderer_) {
|
||||
Log(LogLevel::kError, "UnloadRenderer() called with no renderer present.");
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"UnloadRenderer() called with no renderer present.");
|
||||
return;
|
||||
}
|
||||
if (!renderer_loaded_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaGraphics, LogLevel::kError,
|
||||
"UnloadRenderer() called with an already unloaded renderer present.");
|
||||
return;
|
||||
}
|
||||
@ -532,7 +535,7 @@ void GraphicsServer::PushRemoveRenderHoldCall() {
|
||||
assert(render_hold_);
|
||||
render_hold_--;
|
||||
if (render_hold_ < 0) {
|
||||
Log(LogLevel::kError, "RenderHold < 0");
|
||||
Log(LogName::kBaGraphics, LogLevel::kError, "RenderHold < 0");
|
||||
render_hold_ = 0;
|
||||
}
|
||||
});
|
||||
|
||||
@ -17,7 +17,8 @@ class MeshData {
|
||||
: type_(type), draw_type_(draw_type) {}
|
||||
virtual ~MeshData() {
|
||||
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_;
|
||||
|
||||
@ -76,7 +76,7 @@ class MeshIndexedBase : public Mesh {
|
||||
// For use by subclasses in their IsValid() overrides
|
||||
auto IndexSizeIsValid(size_t data_size) const -> bool {
|
||||
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: "
|
||||
+ GetObjectDescription()
|
||||
+ ". This case requires 32 bit indices.");
|
||||
|
||||
@ -32,7 +32,7 @@ class MeshIndexedStaticDynamic : public MeshIndexedBase {
|
||||
|
||||
// Static and dynamic data sizes should always match, right?
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -13,7 +13,8 @@ NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
||||
|| (border_bottom + border_top) > 1.0f)
|
||||
|| (border_left < 0.0f || border_right < 0.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
|
||||
|
||||
@ -24,7 +24,7 @@ class RenderTarget : public Object {
|
||||
void DrawBegin(bool clear,
|
||||
const Vector4f& clear_color = {0.0f, 0.0f, 0.0f, 1.0f}) {
|
||||
DrawBegin(clear, clear_color.x, clear_color.y, clear_color.z,
|
||||
clear_color.w);
|
||||
clear_color.a);
|
||||
}
|
||||
|
||||
void OnScreenSizeChange();
|
||||
|
||||
@ -152,7 +152,7 @@ void ScreenMessages::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
|
||||
if (i->translation_dirty) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kWarning,
|
||||
LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"Found dirty translation on screenmessage draw pass 1; raw="
|
||||
+ i->s_raw);
|
||||
}
|
||||
@ -261,7 +261,7 @@ void ScreenMessages::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
}
|
||||
if (i->translation_dirty) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kWarning,
|
||||
LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"Found dirty translation on screenmessage draw pass 2; raw="
|
||||
+ i->s_raw);
|
||||
}
|
||||
@ -495,7 +495,7 @@ void ScreenMessages::ClearScreenMessageTranslations() {
|
||||
auto ScreenMessages::ScreenMessageEntry::GetText() -> TextGroup& {
|
||||
if (translation_dirty) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kWarning,
|
||||
LogName::kBaGraphics, LogLevel::kWarning,
|
||||
"Found dirty translation on screenmessage GetText; raw=" + s_raw);
|
||||
}
|
||||
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
|
||||
|| 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) {
|
||||
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);
|
||||
} else {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaGraphics, LogLevel::kError,
|
||||
"FIXME: GetOSTextSpanBoundsAndWidth unimplemented on this platform");
|
||||
r->l = 0.0f;
|
||||
r->r = 1.0f;
|
||||
|
||||
@ -289,7 +289,7 @@ auto JoystickInput::GetButtonName(int index) -> std::string {
|
||||
|
||||
JoystickInput::~JoystickInput() {
|
||||
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.
|
||||
@ -311,7 +311,7 @@ JoystickInput::~JoystickInput() {
|
||||
[joystick] { SDL_JoystickClose(joystick); });
|
||||
sdl_joystick_ = nullptr;
|
||||
#else
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"sdl_joystick_ set in non-sdl-joystick build destructor.");
|
||||
#endif // BA_ENABLE_SDL_JOYSTICKS
|
||||
}
|
||||
@ -654,7 +654,7 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) {
|
||||
hat_held_ = true;
|
||||
break;
|
||||
default:
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||
"Invalid hat value: "
|
||||
+ std::to_string(static_cast<int>(e->jhat.value)));
|
||||
break;
|
||||
@ -1231,7 +1231,7 @@ void JoystickInput::UpdateMapping() {
|
||||
auto* cl{g_base->HaveClassic() ? g_base->classic() : nullptr};
|
||||
|
||||
if (!cl) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaInput, LogLevel::kWarning,
|
||||
"Classic not present; can't config joystick mapping.");
|
||||
}
|
||||
|
||||
|
||||
@ -852,7 +852,7 @@ void TouchInput::UpdateMapping() {
|
||||
} else if (touch_movement_type == "joystick") {
|
||||
movement_control_type_ = TouchInput::MovementControlType::kJoystick;
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"Invalid touch-movement-type: " + touch_movement_type);
|
||||
movement_control_type_ = TouchInput::MovementControlType::kSwipe;
|
||||
}
|
||||
@ -863,7 +863,8 @@ void TouchInput::UpdateMapping() {
|
||||
} else if (touch_action_type == "buttons") {
|
||||
action_control_type_ = TouchInput::ActionControlType::kButtons;
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ void Input::PushCreateKeyboardInputDevices() {
|
||||
void Input::CreateKeyboardInputDevices_() {
|
||||
assert(g_base->InLogicThread());
|
||||
if (keyboard_input_ != nullptr || keyboard_input_2_ != nullptr) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"CreateKeyboardInputDevices called with existing kbs.");
|
||||
return;
|
||||
}
|
||||
@ -53,7 +53,7 @@ void Input::PushDestroyKeyboardInputDevices() {
|
||||
void Input::DestroyKeyboardInputDevices_() {
|
||||
assert(g_base->InLogicThread());
|
||||
if (keyboard_input_ == nullptr || keyboard_input_2_ == nullptr) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"DestroyKeyboardInputDevices called with null kb(s).");
|
||||
return;
|
||||
}
|
||||
@ -558,7 +558,7 @@ void Input::StepDisplayTime() {
|
||||
// If input has been locked an excessively long amount of time, unlock it.
|
||||
if (input_lock_count_temp_) {
|
||||
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_lock_count_temp_ = 0;
|
||||
PrintLockLabels_();
|
||||
@ -664,7 +664,7 @@ void Input::UnlockAllInput(bool permanent, const std::string& label) {
|
||||
input_lock_count_temp_--;
|
||||
input_unlock_temp_labels_.push_back(label);
|
||||
if (input_lock_count_temp_ < 0) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBaInput, LogLevel::kWarning,
|
||||
"temp input unlock at time "
|
||||
+ std::to_string(g_core->GetAppTimeMillisecs())
|
||||
+ " with no active lock: '" + label + "'");
|
||||
@ -719,7 +719,7 @@ void Input::PrintLockLabels_() {
|
||||
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) {
|
||||
@ -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
|
||||
// at least translate to unicode.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -844,7 +845,8 @@ void Input::CaptureKeyboardInput(HandleKeyPressCall* press_call,
|
||||
HandleKeyReleaseCall* release_call) {
|
||||
assert(g_base->InLogicThread());
|
||||
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_release_ = release_call;
|
||||
@ -859,7 +861,8 @@ void Input::ReleaseKeyboardInput() {
|
||||
void Input::CaptureJoystickInput(HandleJoystickEventCall* call) {
|
||||
assert(g_base->InLogicThread());
|
||||
if (joystick_input_capture_) {
|
||||
Log(LogLevel::kError, "Setting joystick capture redundantly.");
|
||||
Log(LogName::kBaInput, LogLevel::kError,
|
||||
"Setting joystick capture redundantly.");
|
||||
}
|
||||
joystick_input_capture_ = call;
|
||||
}
|
||||
@ -930,7 +933,7 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
|
||||
count++;
|
||||
if (count > 10) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kWarning,
|
||||
LogName::kBaInput, LogLevel::kWarning,
|
||||
"Input::HandleKeyPress_ seems to be getting passed repeat key"
|
||||
" 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
|
||||
// single_touch_.
|
||||
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.");
|
||||
}
|
||||
|
||||
@ -1452,7 +1455,7 @@ void Input::HandleTouchEvent_(const TouchEvent& e) {
|
||||
if ((e.type == TouchEvent::Type::kUp
|
||||
|| e.type == TouchEvent::Type::kCanceled)
|
||||
&& 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!");
|
||||
}
|
||||
}
|
||||
@ -1567,7 +1570,7 @@ void Input::LsInputDevices() {
|
||||
++index;
|
||||
}
|
||||
|
||||
Log(LogLevel::kInfo, out);
|
||||
Log(LogName::kBaInput, LogLevel::kInfo, out);
|
||||
}
|
||||
|
||||
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: {
|
||||
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 "
|
||||
+ std::to_string(amt));
|
||||
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.
|
||||
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;
|
||||
}
|
||||
RemoteAppClient* client = clients_ + joystick_id;
|
||||
|
||||
@ -384,7 +384,7 @@ void Logic::OnAppModeChanged() {
|
||||
// long sleep we're currently in the middle of.
|
||||
if (g_core->HeadlessMode()) {
|
||||
if (debug_log_display_time_) {
|
||||
Log(LogLevel::kDebug,
|
||||
Log(LogName::kBa, LogLevel::kDebug,
|
||||
"Resetting headless display step timer due to app-mode change.");
|
||||
}
|
||||
assert(headless_display_time_step_timer_);
|
||||
@ -419,7 +419,7 @@ void Logic::UpdateDisplayTimeForHeadlessMode_() {
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "stepping display-time at app-time %.4f",
|
||||
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),
|
||||
"will try to sleep for %.4f at app-time %.4f (until %.4f)",
|
||||
sleepsecs, apptimesecs, apptimesecs + sleepsecs);
|
||||
Log(LogLevel::kDebug, buffer);
|
||||
Log(LogName::kBa, LogLevel::kDebug, buffer);
|
||||
}
|
||||
|
||||
auto sleep_microsecs = headless_display_step_microsecs;
|
||||
@ -548,7 +548,7 @@ void Logic::UpdateDisplayTimeForFrameDraw_() {
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"trailing_dist %.6f > trail_buffer %.6f; will offset %.6f).",
|
||||
trailing_dist, trail_buffer, offs);
|
||||
Log(LogLevel::kDebug, buffer);
|
||||
Log(LogName::kBa, LogLevel::kDebug, buffer);
|
||||
}
|
||||
display_time_increment_ = display_time_increment_ + offs;
|
||||
}
|
||||
@ -559,7 +559,7 @@ void Logic::UpdateDisplayTimeForFrameDraw_() {
|
||||
"final %.5f current(%s) %.5f sample %.5f chaos %.5f",
|
||||
display_time_increment_, use_avg ? "avg" : "sample", used,
|
||||
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) {
|
||||
t->SetLength(length);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Logic::SetAppTimerLength() called on nonexistent timer.");
|
||||
}
|
||||
}
|
||||
@ -687,7 +687,7 @@ void Logic::SetDisplayTimerLength(int timer_id, microsecs_t length) {
|
||||
if (t) {
|
||||
t->SetLength(length);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Logic::SetDisplayTimerLength() called on nonexistent timer.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,8 +61,9 @@ void NetworkReader::OnAppUnsuspend() {
|
||||
void NetworkReader::PokeSelf_() {
|
||||
int sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sd < 0) {
|
||||
Log(LogLevel::kError, "Unable to create sleep ping socket; errno "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Unable to create sleep ping socket; errno "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
} else {
|
||||
struct sockaddr_in serv_addr{};
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
@ -71,8 +72,9 @@ void NetworkReader::PokeSelf_() {
|
||||
serv_addr.sin_port = 0; // any
|
||||
int bresult = ::bind(sd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
if (bresult == 1) {
|
||||
Log(LogLevel::kError, "Unable to bind sleep socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Unable to bind sleep socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
} else {
|
||||
struct sockaddr_in t_addr{};
|
||||
memset(&t_addr, 0, sizeof(t_addr));
|
||||
@ -83,8 +85,9 @@ void NetworkReader::PokeSelf_() {
|
||||
ssize_t sresult =
|
||||
sendto(sd, b, 1, 0, (struct sockaddr*)(&t_addr), sizeof(t_addr));
|
||||
if (sresult == -1) {
|
||||
Log(LogLevel::kError, "Error on sleep self-sendto: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error on sleep self-sendto: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
}
|
||||
}
|
||||
g_core->platform->CloseSocket(sd);
|
||||
@ -115,7 +118,7 @@ void NetworkReader::DoPoll_(bool* can_read_4, bool* can_read_6) {
|
||||
// Aint no thang.
|
||||
} else {
|
||||
// Let's complain for anything else though.
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error on select: " + g_core->platform->GetSocketErrorString());
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
} 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.
|
||||
} else {
|
||||
// Let's complain for anything else though.
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error on select: " + g_core->platform->GetSocketErrorString());
|
||||
}
|
||||
} else {
|
||||
@ -235,7 +239,7 @@ auto NetworkReader::RunThread_() -> int {
|
||||
recvfrom(sd, buffer, sizeof(buffer), 0,
|
||||
reinterpret_cast<sockaddr*>(&from), &from_size);
|
||||
if (rresult == 0) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"NetworkReader Recv got length 0; this shouldn't "
|
||||
"happen");
|
||||
} 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.
|
||||
if (!g_base->logic->event_loop()->CheckPushSafety()) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaNetworking, LogLevel::kError,
|
||||
"Ignoring excessive udp-connection input packets; (could this be a "
|
||||
"flood attack?).");
|
||||
return;
|
||||
@ -413,8 +417,9 @@ void NetworkReader::OpenSockets_() {
|
||||
|
||||
sd4_ = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sd4_ < 0) {
|
||||
Log(LogLevel::kError, "Unable to open host socket; errno "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Unable to open host socket; errno "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
} else {
|
||||
g_core->platform->SetSocketNonBlocking(sd4_);
|
||||
|
||||
@ -465,8 +470,9 @@ void NetworkReader::OpenSockets_() {
|
||||
// available everywhere (win XP, etc) so let's do this for now.
|
||||
sd6_ = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sd6_ < 0) {
|
||||
Log(LogLevel::kError, "Unable to open ipv6 socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Unable to open ipv6 socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
} else {
|
||||
// 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
|
||||
@ -475,7 +481,8 @@ void NetworkReader::OpenSockets_() {
|
||||
if (setsockopt(sd6_, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
reinterpret_cast<char*>(&on), sizeof(on))
|
||||
== -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_);
|
||||
@ -522,9 +529,9 @@ void NetworkReader::OpenSockets_() {
|
||||
+ std::to_string(initial_requested_port)
|
||||
+ "; some network functionality may fail.",
|
||||
{1, 0.5f, 0});
|
||||
Log(LogLevel::kWarning, "Unable to bind udp port "
|
||||
+ std::to_string(initial_requested_port)
|
||||
+ "; some network functionality may fail.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kWarning,
|
||||
"Unable to bind udp port " + std::to_string(initial_requested_port)
|
||||
+ "; 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;
|
||||
// these are unreliable messages so its ok to just drop them.
|
||||
if (!event_loop()->CheckPushSafety()) {
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Excessive send-to calls in net-write-module.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ void BasePlatformApple::LoginAdapterGetSignInToken(
|
||||
if (login_type == "game_center") {
|
||||
BallisticaKit::GameCenterContext::getSignInToken(attempt_id);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Got unexpected get-sign-in-token login-type: " + login_type);
|
||||
}
|
||||
#else
|
||||
@ -130,7 +130,7 @@ void BasePlatformApple::LoginAdapterBackEndActiveChange(
|
||||
if (login_type == "game_center") {
|
||||
BallisticaKit::GameCenterContext::backEndActiveChange(active);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Got unexpected back-end-active-change login-type: " + login_type);
|
||||
}
|
||||
#else
|
||||
|
||||
@ -104,12 +104,12 @@ void BasePlatform::DoPurchase(const std::string& item) {
|
||||
}
|
||||
|
||||
void BasePlatform::RestorePurchases() {
|
||||
Log(LogLevel::kError, "RestorePurchases() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "RestorePurchases() unimplemented");
|
||||
}
|
||||
|
||||
void BasePlatform::PurchaseAck(const std::string& purchase,
|
||||
const std::string& order_id) {
|
||||
Log(LogLevel::kError, "PurchaseAck() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "PurchaseAck() unimplemented");
|
||||
}
|
||||
|
||||
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_);
|
||||
if (web_overlay_open_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"OverlayWebBrowserOnClose called with already existing overlay.");
|
||||
return;
|
||||
}
|
||||
@ -155,7 +155,7 @@ auto BasePlatform::OverlayWebBrowserIsOpen() -> bool {
|
||||
void BasePlatform::OverlayWebBrowserOnClose() {
|
||||
std::scoped_lock lock(web_overlay_mutex_);
|
||||
if (!web_overlay_open_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"OverlayWebBrowserOnClose called with no known overlay.");
|
||||
}
|
||||
web_overlay_open_ = false;
|
||||
@ -174,12 +174,13 @@ void BasePlatform::OverlayWebBrowserClose() {
|
||||
}
|
||||
|
||||
void BasePlatform::DoOverlayWebBrowserOpenURL(const std::string& url) {
|
||||
Log(LogLevel::kError, "DoOpenURLInOverlayBrowser unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"DoOpenURLInOverlayBrowser unimplemented");
|
||||
}
|
||||
|
||||
void BasePlatform::DoOverlayWebBrowserClose() {
|
||||
// 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
|
||||
@ -188,7 +189,7 @@ static void HandleSIGINT(int s) {
|
||||
g_base->logic->event_loop()->PushCall(
|
||||
[] { g_base->logic->HandleInterruptSignal(); });
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"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->HandleTerminateSignal(); });
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"SigInt handler called before g_base->logic->event_loop exists.");
|
||||
}
|
||||
}
|
||||
@ -276,17 +277,18 @@ void BasePlatform::StringEditorCancel() {
|
||||
void BasePlatform::DoInvokeStringEditor(const std::string& title,
|
||||
const std::string& value,
|
||||
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; }
|
||||
|
||||
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) {
|
||||
Log(LogLevel::kError, "OpenFileExternally() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "OpenFileExternally() unimplemented");
|
||||
}
|
||||
|
||||
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 + "\"";
|
||||
int result = system(cmd.c_str());
|
||||
if (result != 0) {
|
||||
Log(LogLevel::kError, "Got return value " + std::to_string(result)
|
||||
+ " on xdg-open cmd '" + cmd + "'");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"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 + "\"";
|
||||
int result = system(cmd.c_str());
|
||||
if (result != 0) {
|
||||
Log(LogLevel::kError, "Got return value " + std::to_string(result)
|
||||
+ " on xdg-open cmd '" + cmd + "'");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"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;
|
||||
if (static_cast<int>(scancode) < SDL_SCANCODE_UNKNOWN
|
||||
|| scancode >= SDL_NUM_SCANCODES) {
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaInput, LogLevel::kError,
|
||||
"GetScancodeName passed invalid scancode "
|
||||
+ std::to_string(static_cast<int>(scancode)));
|
||||
return "";
|
||||
|
||||
@ -36,7 +36,7 @@ void BasePlatformWindows::DoOpenURL(const std::string& url) {
|
||||
|
||||
// This should return > 32 on success.
|
||||
if (r <= 32) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"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->HandleInterruptSignal(); });
|
||||
} 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;
|
||||
|
||||
@ -61,7 +62,7 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
|
||||
void BasePlatformWindows::SetupInterruptHandling() {
|
||||
// Set up Ctrl-C handling.
|
||||
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,
|
||||
SW_SHOWNORMAL));
|
||||
if (r <= 32) {
|
||||
Log(LogLevel::kError, "Error " + std::to_string(r)
|
||||
+ " on open_dir_externally for '" + path + "'");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"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,
|
||||
SW_SHOWNORMAL));
|
||||
if (r <= 32) {
|
||||
Log(LogLevel::kError, "Error " + std::to_string(r)
|
||||
+ " on open_file_externally for '" + path + "'");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Error " + std::to_string(r) + " on open_file_externally for '" + path
|
||||
+ "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -106,27 +106,8 @@ void BasePython::SoftImportClassic() {
|
||||
}
|
||||
}
|
||||
|
||||
// void BasePython::SoftImportUIV1() {
|
||||
// // To keep our init order clean, we want to root out any attempted uses
|
||||
// // 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::SetConfig(PyObject* config) {
|
||||
objs_.Store(ObjID::kConfig, config);
|
||||
}
|
||||
|
||||
void BasePython::Reset() {
|
||||
@ -360,7 +341,7 @@ auto BasePython::GetRawConfigValue(const char* name, float default_value)
|
||||
try {
|
||||
return Python::GetPyFloat(value);
|
||||
} catch (const std::exception&) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"expected a float for config value '" + std::string(name) + "'");
|
||||
return default_value;
|
||||
}
|
||||
@ -382,7 +363,7 @@ auto BasePython::GetRawConfigValue(const char* name,
|
||||
}
|
||||
return Python::GetPyFloat(value);
|
||||
} catch (const std::exception&) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"expected a float for config value '" + std::string(name) + "'");
|
||||
return default_value;
|
||||
}
|
||||
@ -399,7 +380,7 @@ auto BasePython::GetRawConfigValue(const char* name, int default_value) -> int {
|
||||
try {
|
||||
return static_cast_check_fit<int>(Python::GetPyInt64(value));
|
||||
} catch (const std::exception&) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Expected an int value for config value '" + std::string(name) + "'.");
|
||||
return default_value;
|
||||
}
|
||||
@ -417,7 +398,7 @@ auto BasePython::GetRawConfigValue(const char* name, bool default_value)
|
||||
try {
|
||||
return Python::GetPyBool(value);
|
||||
} catch (const std::exception&) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Expected a bool value for config value '" + std::string(name) + "'.");
|
||||
return default_value;
|
||||
}
|
||||
@ -525,7 +506,7 @@ auto BasePython::GetResource(const char* key, const char* fallback_resource,
|
||||
try {
|
||||
return g_base->python->GetPyLString(results.Get());
|
||||
} catch (const std::exception&) {
|
||||
Log(LogLevel::kError,
|
||||
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
|
||||
@ -533,7 +514,8 @@ auto BasePython::GetResource(const char* key, const char* fallback_resource,
|
||||
return std::string("<res-err: ") + key + ">";
|
||||
}
|
||||
} 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?..
|
||||
@ -553,12 +535,12 @@ auto BasePython::GetTranslation(const char* category, const char* s)
|
||||
try {
|
||||
return g_base->python->GetPyLString(results.Get());
|
||||
} catch (const std::exception&) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"GetTranslation failed for '" + std::string(category) + "'");
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"GetTranslation failed for category '" + std::string(category) + "'");
|
||||
}
|
||||
return "";
|
||||
@ -574,7 +556,7 @@ void BasePython::RunDeepLink(const std::string& url) {
|
||||
.Get(base::BasePython::ObjID::kAppHandleDeepLinkCall)
|
||||
.Call(args);
|
||||
} 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)
|
||||
.Call(args);
|
||||
if (!result.Exists()) {
|
||||
Log(LogLevel::kError, "Error getting StringEdit valid state.");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Error getting StringEdit valid state.");
|
||||
return false;
|
||||
}
|
||||
if (result.Get() == Py_True) {
|
||||
@ -604,7 +587,8 @@ auto BasePython::CanPyStringEditAdapterBeReplaced(PyObject* o) -> bool {
|
||||
if (result.Get() == Py_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;
|
||||
}
|
||||
|
||||
|
||||
@ -75,7 +75,6 @@ class BasePython {
|
||||
kEmptyCall,
|
||||
kPrintTraceCall,
|
||||
kToggleFullscreenCall,
|
||||
kAppReadConfigCall,
|
||||
kUIRemotePressCall,
|
||||
kRemoveInGameAdsMessageCall,
|
||||
kAppOnNativeStartCall,
|
||||
@ -124,7 +123,8 @@ class BasePython {
|
||||
void AddPythonClasses(PyObject* module);
|
||||
void ImportPythonObjs();
|
||||
void ImportPythonAppObjs();
|
||||
void ReadConfig();
|
||||
void SetConfig(PyObject* config);
|
||||
// void ReadConfig();
|
||||
|
||||
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
|
||||
// save/restore context.
|
||||
if (!suppress_warning && g_base->InLogicThread()) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBa, LogLevel::kWarning,
|
||||
"babase.pushcall() called from the logic thread with "
|
||||
"from_other_thread set to true (call "
|
||||
+ Python::ObjToString(call_obj) + " at "
|
||||
@ -802,13 +802,15 @@ static PyMethodDef PyEnvDef = {
|
||||
static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds)
|
||||
-> PyObject* {
|
||||
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* levelstr;
|
||||
const char* message;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss",
|
||||
double timestamp;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ssds",
|
||||
const_cast<char**>(kwlist), &name, &levelstr,
|
||||
&message)) {
|
||||
×tamp, &message)) {
|
||||
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);
|
||||
level = LogLevel::kInfo;
|
||||
}
|
||||
Logging::EmitLog(name, level, message);
|
||||
Logging::EmitLog(name, level, timestamp, message);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
@ -840,7 +842,8 @@ static PyMethodDef PyEmitLogDef = {
|
||||
(PyCFunction)PyEmitLog, // method
|
||||
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"
|
||||
"(internal)\n"
|
||||
"\n"
|
||||
|
||||
@ -190,7 +190,7 @@ static auto PyScreenMessage(PyObject* self, PyObject* args, PyObject* keywds)
|
||||
color = BasePython::GetPyVector3f(color_obj);
|
||||
}
|
||||
if (log) {
|
||||
Log(LogLevel::kInfo, message_str);
|
||||
Log(LogName::kBa, LogLevel::kInfo, message_str);
|
||||
}
|
||||
|
||||
// This version simply displays it locally.
|
||||
|
||||
@ -110,7 +110,7 @@ static auto PySetUIScale(PyObject* self, PyObject* args, PyObject* keywds)
|
||||
const char* scalestr;
|
||||
|
||||
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",
|
||||
const_cast<char**>(kwlist), &scalestr)) {
|
||||
return nullptr;
|
||||
@ -328,7 +328,8 @@ static auto PySetUpSigInt(PyObject* self) -> PyObject* {
|
||||
if (g_base) {
|
||||
g_base->platform->SetupInterruptHandling();
|
||||
} 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;
|
||||
BA_PYTHON_CATCH;
|
||||
@ -1578,13 +1579,14 @@ static auto PyDevConsoleAddButton(PyObject* self, PyObject* args) -> PyObject* {
|
||||
float label_scale;
|
||||
float corner_radius;
|
||||
const char* style;
|
||||
if (!PyArg_ParseTuple(args, "sffffOsffs", &label, &x, &y, &width, &height,
|
||||
&call, &h_anchor, &label_scale, &corner_radius,
|
||||
&style)) {
|
||||
int disabled;
|
||||
if (!PyArg_ParseTuple(args, "sffffOsffsp", &label, &x, &y, &width, &height,
|
||||
&call, &h_anchor, &label_scale, &corner_radius, &style,
|
||||
&disabled)) {
|
||||
return nullptr;
|
||||
}
|
||||
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;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
@ -1605,6 +1607,7 @@ static PyMethodDef PyDevConsoleAddButtonDef = {
|
||||
" label_scale: float,\n"
|
||||
" corner_radius: float,\n"
|
||||
" style: str,\n"
|
||||
" disabled: bool,\n"
|
||||
") -> None\n"
|
||||
"\n"
|
||||
"(internal)",
|
||||
@ -1970,6 +1973,26 @@ static PyMethodDef PyGetDrawUIBoundsDef = {
|
||||
"(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 -----------------------------
|
||||
|
||||
static auto PySetDrawUIBounds(PyObject* self, PyObject* args, PyObject* keywds)
|
||||
@ -2020,6 +2043,53 @@ static PyMethodDef PyPushBackPressDef = {
|
||||
"(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> {
|
||||
@ -2095,6 +2165,9 @@ auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
|
||||
PyPushBackPressDef,
|
||||
PyGetDrawUIBoundsDef,
|
||||
PySetDrawUIBoundsDef,
|
||||
PyGetInitialAppConfigDef,
|
||||
PySetAppConfigDef,
|
||||
PyUpdateInternalLoggerLevelsDef,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -24,12 +24,14 @@
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/shared/math/vector4f.h"
|
||||
#include "ballistica/shared/python/python_command.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
// 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 kDevConsoleStringBreakUpSize{1950};
|
||||
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 == '_');
|
||||
}
|
||||
|
||||
static void DrawRect(RenderPass* pass, Mesh* mesh, float bottom, float x,
|
||||
float y, float width, float height,
|
||||
const Vector3f& bgcolor) {
|
||||
static void DrawRect(RenderPass* pass, Mesh* mesh, float x, float y,
|
||||
float width, float height, const Vector3f& bgcolor,
|
||||
float alpha = 1.0f) {
|
||||
SimpleComponent c(pass);
|
||||
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));
|
||||
// Draw mesh bg.
|
||||
if (mesh) {
|
||||
auto xf = c.ScopedTransform();
|
||||
c.Translate(x, y + bottom, kDevConsoleZDepth);
|
||||
c.Translate(x, y, kDevConsoleZDepth);
|
||||
c.DrawMesh(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawText(RenderPass* pass, TextGroup* tgrp, float tscale,
|
||||
float bottom, float x, float y, const Vector3f& fgcolor) {
|
||||
static void DrawText(RenderPass* pass, TextGroup* tgrp, float tscale, float x,
|
||||
float y, const Vector3f& fgcolor, float alpha = 1.0f) {
|
||||
SimpleComponent c(pass);
|
||||
c.SetTransparent(true);
|
||||
// Draw text.
|
||||
{
|
||||
auto xf = c.ScopedTransform();
|
||||
c.Translate(x, y + bottom, kDevConsoleZDepth);
|
||||
c.Translate(x, y, kDevConsoleZDepth);
|
||||
c.Scale(tscale, tscale, 1.0f);
|
||||
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);
|
||||
for (int e = 0; e < elem_count; e++) {
|
||||
c.SetTexture(tgrp->GetElementTexture(e));
|
||||
@ -186,7 +188,8 @@ class DevConsole::Text_ : public DevConsole::Widget_ {
|
||||
|
||||
void Draw(RenderPass* pass, float bottom) override {
|
||||
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;
|
||||
float text_scale;
|
||||
DevButtonStyle_ style;
|
||||
bool disabled;
|
||||
|
||||
template <typename F>
|
||||
Button_(const std::string& label, float text_scale, DevConsoleHAnchor_ attach,
|
||||
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},
|
||||
x{x},
|
||||
y{y},
|
||||
@ -216,6 +220,7 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
||||
call{NewLambdaRunnable(lambda)},
|
||||
text_scale{text_scale},
|
||||
style{style},
|
||||
disabled{disabled},
|
||||
mesh(0.0f, 0.0f, 0.0f, width, height,
|
||||
NinePatchMesh::BorderForRadius(corner_radius, width, height),
|
||||
NinePatchMesh::BorderForRadius(corner_radius, height, width),
|
||||
@ -232,7 +237,9 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
||||
|
||||
auto HandleMouseDown(float mx, float my) -> bool override {
|
||||
if (InUs(mx, my)) {
|
||||
pressed = true;
|
||||
if (!disabled) {
|
||||
pressed = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -266,9 +273,11 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
||||
bgcolor =
|
||||
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);
|
||||
DrawText(pass, &text_group, text_scale, bottom,
|
||||
x + XOffs(attach) + width * 0.5f, y + height * 0.5f, fgcolor);
|
||||
float alpha = disabled ? 0.3f : 1.0f;
|
||||
DrawRect(pass, &mesh, x + XOffs(attach), bottom + y, width, height, bgcolor,
|
||||
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 {
|
||||
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}
|
||||
: on ? Vector3f{0.5f, 0.4f, 0.6f}
|
||||
: Vector3f{0.25, 0.2f, 0.3f});
|
||||
DrawText(pass, &text_group, text_scale, bottom,
|
||||
x + XOffs(attach) + width * 0.5f, y + height * 0.5f,
|
||||
DrawText(pass, &text_group, text_scale, x + XOffs(attach) + width * 0.5f,
|
||||
bottom + y + height * 0.5f,
|
||||
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||
: on ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||
: Vector3f{0.8f, 0.7f, 0.8f});
|
||||
@ -417,12 +426,12 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
|
||||
}
|
||||
|
||||
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}
|
||||
: selected ? Vector3f{0.4f, 0.3f, 0.4f}
|
||||
: Vector3f{0.25, 0.2f, 0.3f});
|
||||
DrawText(pass, &text_group, text_scale, bottom,
|
||||
x + XOffs(attach) + width * 0.5f, y + height * 0.5f,
|
||||
DrawText(pass, &text_group, text_scale, x + XOffs(attach) + width * 0.5f,
|
||||
bottom + y + height * 0.5f,
|
||||
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||
: selected ? Vector3f{1.0f, 1.0f, 1.0f}
|
||||
: Vector3f{0.6f, 0.5f, 0.6f});
|
||||
@ -431,10 +440,16 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
|
||||
|
||||
class DevConsole::OutputLine_ {
|
||||
public:
|
||||
OutputLine_(std::string s_in, double c)
|
||||
: creation_time(c), s(std::move(s_in)) {}
|
||||
double creation_time;
|
||||
OutputLine_(std::string s_in, double creation_time, float scale,
|
||||
Vector4f color)
|
||||
: creation_time(creation_time),
|
||||
s(std::move(s_in)),
|
||||
scale(scale),
|
||||
color(color) {}
|
||||
std::string s;
|
||||
double creation_time;
|
||||
float scale;
|
||||
Vector4f color;
|
||||
auto GetText() -> TextGroup& {
|
||||
if (!s_mesh_.Exists()) {
|
||||
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,
|
||||
float height, 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) {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
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_>(
|
||||
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) {
|
||||
callref.Call();
|
||||
}
|
||||
@ -574,7 +590,7 @@ void DevConsole::AddPythonTerminal() {
|
||||
float bs = BaseScale();
|
||||
widgets_.emplace_back(std::make_unique<Button_>(
|
||||
"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(); }));
|
||||
python_terminal_visible_ = true;
|
||||
}
|
||||
@ -632,7 +648,11 @@ auto DevConsole::Width() -> 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) {
|
||||
@ -678,7 +698,7 @@ void DevConsole::InvokeStringEditor_() {
|
||||
.Get(BasePython::ObjID::kDevConsoleStringEditAdapterClass)
|
||||
.Call();
|
||||
if (!result.Exists()) {
|
||||
Log(LogLevel::kError, "Error invoking string edit dialog.");
|
||||
Log(LogName::kBa, LogLevel::kError, "Error invoking string edit dialog.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1037,12 +1057,11 @@ auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool {
|
||||
void DevConsole::Exec() {
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
if (!input_enabled_) {
|
||||
Log(LogLevel::kWarning, "Console input is not allowed yet.");
|
||||
Log(LogName::kBa, LogLevel::kWarning, "Console input is not allowed yet.");
|
||||
return;
|
||||
}
|
||||
input_history_position_ = 0;
|
||||
if (input_string_ == "clear") {
|
||||
last_line_.clear();
|
||||
output_lines_.clear();
|
||||
} else {
|
||||
SubmitPythonCommand_(input_string_);
|
||||
@ -1077,7 +1096,7 @@ void DevConsole::SubmitPythonCommand_(const std::string& command) {
|
||||
if (cmd.CanEval()) {
|
||||
auto obj = cmd.Eval(true, nullptr, nullptr);
|
||||
if (obj.Exists() && obj.Get() != Py_None) {
|
||||
Print(obj.Repr() + "\n");
|
||||
Print(obj.Repr(), 1.0f, kVector4f1);
|
||||
}
|
||||
} else {
|
||||
// Not eval-able; just exec it.
|
||||
@ -1129,23 +1148,21 @@ void DevConsole::ToggleState() {
|
||||
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());
|
||||
std::string s = Utils::GetValidUTF8(s_in.c_str(), "cspr");
|
||||
last_line_ += s;
|
||||
std::vector<std::string> broken_up;
|
||||
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.
|
||||
for (size_t i = 0; i < broken_up.size() - 1; i++) {
|
||||
output_lines_.emplace_back(broken_up[i], g_base->logic->display_time());
|
||||
// Spit out all lines.
|
||||
for (size_t i = 0; i < broken_up.size(); i++) {
|
||||
output_lines_.emplace_back(broken_up[i], g_base->logic->display_time(),
|
||||
scale, color);
|
||||
if (output_lines_.size() > kDevConsoleLineLimit) {
|
||||
output_lines_.pop_front();
|
||||
}
|
||||
}
|
||||
last_line_ = broken_up[broken_up.size() - 1];
|
||||
last_line_mesh_dirty_ = true;
|
||||
}
|
||||
|
||||
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
|
||||
// more important for them to be able to be written to a known hard-coded
|
||||
// mini-size.
|
||||
float mini_size = 100.0f;
|
||||
|
||||
//
|
||||
// Now that we have tabs and drop-shadows hanging down, we have to
|
||||
// overshoot the top of the screen when transitioning out.
|
||||
float top_buffer = 100.0f;
|
||||
if (state_ == State_::kMini) {
|
||||
bottom = vh - mini_size;
|
||||
bottom = vh - kDevConsoleMiniSize;
|
||||
} else {
|
||||
bottom = vh - vh * kDevConsoleSize;
|
||||
bottom = vh * (1.0f - kDevConsoleFullSizeCoverage);
|
||||
}
|
||||
if (g_base->logic->display_time() - transition_start_ < kTransitionSeconds) {
|
||||
float from_height;
|
||||
if (state_prev_ == State_::kMini) {
|
||||
from_height = vh - mini_size;
|
||||
from_height = vh - kDevConsoleMiniSize;
|
||||
} else if (state_prev_ == State_::kFull) {
|
||||
from_height = vh - vh * kDevConsoleSize;
|
||||
from_height = vh - vh * kDevConsoleFullSizeCoverage;
|
||||
} else {
|
||||
from_height = vh + top_buffer;
|
||||
}
|
||||
float to_height;
|
||||
if (state_ == State_::kMini) {
|
||||
to_height = vh - mini_size;
|
||||
to_height = vh - kDevConsoleMiniSize;
|
||||
} else if (state_ == State_::kFull) {
|
||||
to_height = vh - vh * kDevConsoleSize;
|
||||
to_height = vh - vh * kDevConsoleFullSizeCoverage;
|
||||
} else {
|
||||
to_height = vh + top_buffer;
|
||||
}
|
||||
@ -1205,6 +1221,31 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
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 border_height{3.0f};
|
||||
@ -1355,7 +1396,6 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
{
|
||||
SimpleComponent c(pass);
|
||||
c.SetTransparent(true);
|
||||
c.SetColor(1, 1, 1, 1);
|
||||
c.SetFlatness(1.0f);
|
||||
float draw_scale = 0.64f;
|
||||
float v_inc = 18.0f;
|
||||
@ -1363,38 +1403,19 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
* (g_base->graphics->screen_virtual_width()
|
||||
- (kDevConsoleStringBreakUpSize * draw_scale));
|
||||
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++) {
|
||||
int elem_count = i->GetText().GetElementCount();
|
||||
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));
|
||||
{
|
||||
auto xf = c.ScopedTransform();
|
||||
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));
|
||||
}
|
||||
}
|
||||
v += v_inc;
|
||||
v += v_inc * i->scale;
|
||||
if (v > pass->virtual_height() + v_inc) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "ballistica/base/graphics/mesh/image_mesh.h"
|
||||
#include "ballistica/base/graphics/text/text_group.h"
|
||||
#include "ballistica/shared/foundation/object.h"
|
||||
#include "ballistica/shared/math/vector4f.h"
|
||||
#include "ballistica/shared/python/python_ref.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
@ -36,7 +37,7 @@ class DevConsole {
|
||||
auto PasteFromClipboard() -> bool;
|
||||
|
||||
/// 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 StepDisplayTime();
|
||||
@ -58,7 +59,7 @@ class DevConsole {
|
||||
|
||||
void AddButton(const char* label, float x, float y, float width, float height,
|
||||
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,
|
||||
const char* h_align_str, const char* v_align_str, float scale);
|
||||
void AddPythonTerminal();
|
||||
@ -96,12 +97,14 @@ class DevConsole {
|
||||
State_ state_prev_{State_::kInactive};
|
||||
bool input_text_dirty_{true};
|
||||
bool input_enabled_{};
|
||||
bool last_line_mesh_dirty_{true};
|
||||
bool python_terminal_visible_{};
|
||||
bool python_terminal_pressed_{};
|
||||
bool refresh_pending_{};
|
||||
bool carat_dirty_{true};
|
||||
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_{};
|
||||
millisecs_t last_carat_x_change_time_{};
|
||||
ImageMesh bg_mesh_;
|
||||
@ -111,7 +114,6 @@ class DevConsole {
|
||||
TextGroup title_text_group_;
|
||||
TextGroup prompt_text_group_;
|
||||
TextGroup input_text_group_;
|
||||
std::string last_line_;
|
||||
std::string input_string_;
|
||||
std::list<std::string> tabs_;
|
||||
std::string active_tab_;
|
||||
@ -120,7 +122,6 @@ class DevConsole {
|
||||
std::list<OutputLine_> output_lines_;
|
||||
std::vector<std::unique_ptr<Widget_> > widgets_;
|
||||
std::vector<std::unique_ptr<Widget_> > tab_buttons_;
|
||||
Object::Ref<TextGroup> last_line_mesh_group_;
|
||||
Object::Ref<Repeater> key_repeater_;
|
||||
Object::Ref<NinePatchMesh> carat_mesh_;
|
||||
Object::Ref<NinePatchMesh> carat_glow_mesh_;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/foundation/macros.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/shared/math/vector4f.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -165,13 +166,13 @@ void UI::OnAppStart() {
|
||||
if (force_scale_) {
|
||||
if (scale_ == UIScale::kSmall) {
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
FatalError("Unhandled scale.");
|
||||
}
|
||||
@ -576,7 +577,8 @@ void UI::ShowURL(const std::string& url) {
|
||||
g_base->logic->event_loop()->PushCall(
|
||||
[ui_delegate, url] { ui_delegate->DoShowURL(url); });
|
||||
} 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.
|
||||
if (g_core->HeadlessMode()) {
|
||||
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.
|
||||
if (auto* event_loop = g_base->logic->event_loop()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
// 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() {
|
||||
@ -648,7 +653,10 @@ void UI::OnAssetsAvailable() {
|
||||
|
||||
// Print any messages that have built up.
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,13 @@
|
||||
#ifndef BALLISTICA_BASE_UI_UI_H_
|
||||
#define BALLISTICA_BASE_UI_UI_H_
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/base/graphics/support/frame_def.h"
|
||||
#include "ballistica/base/ui/widget_message.h"
|
||||
#include "ballistica/shared/math/vector4f.h"
|
||||
|
||||
// Predeclare a few things from ui_v1.
|
||||
namespace ballistica::ui_v1 {
|
||||
@ -123,7 +125,8 @@ class UI {
|
||||
|
||||
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_; }
|
||||
|
||||
@ -154,7 +157,8 @@ class UI {
|
||||
OperationContext* operation_context_{};
|
||||
base::UIDelegateInterface* delegate_{};
|
||||
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_widget_input_reject_err_sound_time_{};
|
||||
UIScale scale_{UIScale::kLarge};
|
||||
|
||||
@ -151,9 +151,9 @@ auto ClassicFeatureSet::GetV1AccountLoginStateString() -> std::string {
|
||||
out = "signing_in";
|
||||
break;
|
||||
default:
|
||||
Log(LogLevel::kError, "Unknown V1LoginState '"
|
||||
+ std::to_string(static_cast<int>(state))
|
||||
+ "'");
|
||||
Log(LogName::kBaAccount, LogLevel::kError,
|
||||
"Unknown V1LoginState '" + std::to_string(static_cast<int>(state))
|
||||
+ "'");
|
||||
out = "signed_out";
|
||||
break;
|
||||
}
|
||||
|
||||
@ -128,9 +128,10 @@ void ClassicAppMode::Reset_() {
|
||||
|
||||
// If all is well our sessions should all be dead at this point.
|
||||
if (g_scene_v1->session_count != 0) {
|
||||
Log(LogLevel::kError, "SceneV1 session count is non-zero ("
|
||||
+ std::to_string(g_scene_v1->session_count)
|
||||
+ ") on ClassicAppMode::Reset_().");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"SceneV1 session count is non-zero ("
|
||||
+ std::to_string(g_scene_v1->session_count)
|
||||
+ ") on ClassicAppMode::Reset_().");
|
||||
}
|
||||
|
||||
// Reset the engine itself to a default state.
|
||||
@ -159,15 +160,16 @@ void ClassicAppMode::HostScanCycle() {
|
||||
scan_socket_ = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (scan_socket_ == -1) {
|
||||
Log(LogLevel::kError, "Error opening scan socket: "
|
||||
+ g_core->platform->GetSocketErrorString()
|
||||
+ ".");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error opening scan socket: "
|
||||
+ g_core->platform->GetSocketErrorString() + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// Since this guy lives in the logic-thread we need it to not block.
|
||||
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_);
|
||||
scan_socket_ = -1;
|
||||
return;
|
||||
@ -182,7 +184,7 @@ void ClassicAppMode::HostScanCycle() {
|
||||
int result =
|
||||
::bind(scan_socket_, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
if (result == 1) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error binding socket: " + g_core->platform->GetSocketErrorString()
|
||||
+ ".");
|
||||
g_core->platform->CloseSocket(scan_socket_);
|
||||
@ -196,9 +198,9 @@ void ClassicAppMode::HostScanCycle() {
|
||||
sizeof(op_val));
|
||||
|
||||
if (result != 0) {
|
||||
Log(LogLevel::kError, "Error enabling broadcast for scan-socket: "
|
||||
+ g_core->platform->GetSocketErrorString()
|
||||
+ ".");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error enabling broadcast for scan-socket: "
|
||||
+ g_core->platform->GetSocketErrorString() + ".");
|
||||
g_core->platform->CloseSocket(scan_socket_);
|
||||
scan_socket_ = -1;
|
||||
return;
|
||||
@ -230,8 +232,9 @@ void ClassicAppMode::HostScanCycle() {
|
||||
case ENETUNREACH:
|
||||
break;
|
||||
default:
|
||||
Log(LogLevel::kError, "Error on scanSocket sendto: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error on scan-socket sendto: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -253,8 +256,9 @@ void ClassicAppMode::HostScanCycle() {
|
||||
case EWOULDBLOCK:
|
||||
break;
|
||||
default:
|
||||
Log(LogLevel::kError, "Error: recvfrom error: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error: recvfrom error: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -311,11 +315,11 @@ void ClassicAppMode::HostScanCycle() {
|
||||
PruneScanResults_();
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Got invalid BA_PACKET_HOST_QUERY_RESPONSE packet");
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Got invalid BA_PACKET_HOST_QUERY_RESPONSE packet");
|
||||
}
|
||||
}
|
||||
@ -388,7 +392,7 @@ bool ClassicAppMode::HasConnectionToClients() const {
|
||||
auto ClassicAppMode::GetActiveOrWarn() -> ClassicAppMode* {
|
||||
auto* val{GetActive()};
|
||||
if (val == nullptr) {
|
||||
Log(LogLevel::kWarning,
|
||||
Log(LogName::kBa, LogLevel::kWarning,
|
||||
"Attempting to access ClassicAppMode while it is inactive.");
|
||||
}
|
||||
return val;
|
||||
@ -515,6 +519,16 @@ void ClassicAppMode::StepDisplayTime() {
|
||||
}
|
||||
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_();
|
||||
|
||||
HandleQuitOnIdle_();
|
||||
@ -559,8 +573,9 @@ void ClassicAppMode::StepDisplayTime() {
|
||||
|
||||
// Complain when our full update takes longer than 1/60th second.
|
||||
if (duration > (1000 / 60)) {
|
||||
Log(LogLevel::kInfo, "Logic::StepDisplayTime update took too long ("
|
||||
+ std::to_string(duration) + " ms).");
|
||||
Log(LogName::kBa, LogLevel::kInfo,
|
||||
"Logic::StepDisplayTime update took too long ("
|
||||
+ std::to_string(duration) + " ms).");
|
||||
|
||||
// Limit these if we want (not doing so for now).
|
||||
next_long_update_report_time_ = app_time;
|
||||
@ -624,7 +639,7 @@ void ClassicAppMode::UpdateGameRoster() {
|
||||
for (auto&& p : hs->players()) {
|
||||
auto* delegate = p->input_device_delegate();
|
||||
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 "
|
||||
"UpdateGameRoster.");
|
||||
continue;
|
||||
@ -1215,7 +1230,7 @@ void ClassicAppMode::PruneSessions_() {
|
||||
try {
|
||||
i.Clear();
|
||||
} catch (const std::exception& e) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Exception killing Session: " + std::string(e.what()));
|
||||
}
|
||||
have_dead_session = true;
|
||||
@ -1403,7 +1418,8 @@ void ClassicAppMode::HandleQuitOnIdle_() {
|
||||
if (!idle_exiting_ && idle_seconds > (idle_exit_minutes_.value() * 60.0f)) {
|
||||
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(); });
|
||||
}
|
||||
}
|
||||
@ -1462,7 +1478,8 @@ void ClassicAppMode::HandleGameQuery(const char* buffer, size_t size,
|
||||
|
||||
BA_PRECONDITION_FATAL(!usid.empty());
|
||||
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);
|
||||
}
|
||||
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));
|
||||
|
||||
} else {
|
||||
Log(LogLevel::kError, "Got invalid game-query packet of len "
|
||||
+ std::to_string(size) + "; expected 5.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"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/python/core_python.h"
|
||||
#include "ballistica/shared/foundation/macros.h"
|
||||
#include "ballistica/shared/foundation/types.h"
|
||||
#include "ballistica/shared/generic/runnable.h"
|
||||
|
||||
@ -29,14 +30,14 @@ auto CoreFeatureSet::Import(const CoreConfig* config) -> CoreFeatureSet* {
|
||||
"call.");
|
||||
}
|
||||
if (g_core == nullptr) {
|
||||
DoImport(*config);
|
||||
DoImport_(*config);
|
||||
}
|
||||
} else {
|
||||
// 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
|
||||
// config they pass (CoreConfig::ForEnvVars(), etc.).
|
||||
if (g_core == nullptr) {
|
||||
DoImport({});
|
||||
DoImport_({});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -57,23 +58,23 @@ auto CoreFeatureSet::Import(const CoreConfig* config) -> CoreFeatureSet* {
|
||||
// between monolithic and modular.
|
||||
std::vector<std::string> argbuffer;
|
||||
std::vector<char*> argv = CorePython::FetchPythonArgs(&argbuffer);
|
||||
DoImport(CoreConfig::ForArgsAndEnvVars(static_cast<int>(argv.size()),
|
||||
argv.data()));
|
||||
DoImport_(CoreConfig::ForArgsAndEnvVars(static_cast<int>(argv.size()),
|
||||
argv.data()));
|
||||
} else {
|
||||
// Not using Python sys args but we still want to process env vars.
|
||||
DoImport(CoreConfig::ForEnvVars());
|
||||
DoImport_(CoreConfig::ForEnvVars());
|
||||
}
|
||||
}
|
||||
}
|
||||
return g_core;
|
||||
}
|
||||
|
||||
void CoreFeatureSet::DoImport(const CoreConfig& config) {
|
||||
void CoreFeatureSet::DoImport_(const CoreConfig& config) {
|
||||
millisecs_t start_millisecs = CorePlatform::GetCurrentMillisecs();
|
||||
|
||||
assert(g_core == nullptr);
|
||||
g_core = new CoreFeatureSet(config);
|
||||
g_core->PostInit();
|
||||
g_core->PostInit_();
|
||||
|
||||
// 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
|
||||
@ -97,16 +98,16 @@ CoreFeatureSet::CoreFeatureSet(CoreConfig config)
|
||||
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
|
||||
// *after* assigning our singleton to be safe.
|
||||
|
||||
// Should migrate this to classic.
|
||||
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.
|
||||
if (g_buildconfig.monolithic_build()) {
|
||||
@ -119,13 +120,9 @@ void CoreFeatureSet::PostInit() {
|
||||
// Grab whatever Python stuff we use.
|
||||
python->ImportPythonObjs();
|
||||
|
||||
// Normally we wait until later to start pushing logs through to Python
|
||||
// (so that our log handling system is fully bootstrapped), but
|
||||
// technically we can push our log calls out to Python any time now since
|
||||
// we grabbed the logging calls above. Do so immediately here if asked.
|
||||
if (!core_config_.hold_early_logs) {
|
||||
python->EnablePythonLoggingCalls();
|
||||
}
|
||||
// We grabbed all our log handles/etc. above, so we can start piping logs
|
||||
// through to Python now.
|
||||
python->EnablePythonLoggingCalls();
|
||||
}
|
||||
|
||||
auto CoreFeatureSet::core_config() const -> const CoreConfig& {
|
||||
@ -167,6 +164,16 @@ void CoreFeatureSet::ApplyBaEnvConfig() {
|
||||
ba_env_site_python_dir_ =
|
||||
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
|
||||
// AND that value differs from baenv's default.
|
||||
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> {
|
||||
BA_PRECONDITION(have_ba_env_vals_);
|
||||
return ba_env_app_python_dir_;
|
||||
@ -209,7 +220,7 @@ auto CoreFeatureSet::GetSitePythonDirectory() -> std::optional<std::string> {
|
||||
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.
|
||||
// We can use it to make error messages/etc. more pretty by stripping out
|
||||
// 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
|
||||
"core" BA_DIRSLASH "core.cc");
|
||||
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 "";
|
||||
} else {
|
||||
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
|
||||
// (NDEBUG should do this).
|
||||
#if !BA_DEBUG_BUILD
|
||||
@ -267,11 +279,11 @@ void CoreFeatureSet::RunSanityChecks() {
|
||||
// from. Use this to adjust the filtering as necessary so the resulting
|
||||
// type name matches what is expected.
|
||||
if (explicit_bool(false)) {
|
||||
Log(LogLevel::kError, "static_type_name check; name is '"
|
||||
+ static_type_name<decltype(g_core)>()
|
||||
+ "' debug_full is '"
|
||||
+ static_type_name<decltype(g_core)>(true) + "'");
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"static_type_name check; name is '"
|
||||
+ static_type_name<decltype(g_core)>() + "' debug_full is '"
|
||||
+ static_type_name<decltype(g_core)>(true) + "'");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"static_type_name check; name is '"
|
||||
+ static_type_name<decltype(testrunnable)>() + "' debug_full is '"
|
||||
+ static_type_name<decltype(testrunnable)>(true) + "'");
|
||||
@ -293,13 +305,16 @@ auto CoreFeatureSet::SoftImportBase() -> BaseSoftInterface* {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// We include time-since-start as part of the message here.
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "LIFE: %s @ %.3fs.", msg,
|
||||
snprintf(buffer, sizeof(buffer), "%s @ %.3fs.", msg,
|
||||
g_core->GetAppTimeSeconds() + offset_seconds);
|
||||
Log(LogLevel::kInfo, buffer);
|
||||
Log(LogName::kBaLifecycle, LogLevel::kDebug, buffer);
|
||||
}
|
||||
|
||||
auto CoreFeatureSet::HeadlessMode() -> bool {
|
||||
@ -308,29 +323,27 @@ auto CoreFeatureSet::HeadlessMode() -> bool {
|
||||
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) {
|
||||
CorePlatform::SleepMillisecs(wait);
|
||||
FatalError("Timed out waiting for " + action + ".");
|
||||
}
|
||||
|
||||
auto CoreFeatureSet::GetAppTimeMillisecs() -> millisecs_t {
|
||||
UpdateAppTime();
|
||||
UpdateAppTime_();
|
||||
return app_time_microsecs_ / 1000;
|
||||
}
|
||||
|
||||
auto CoreFeatureSet::GetAppTimeMicrosecs() -> microsecs_t {
|
||||
UpdateAppTime();
|
||||
UpdateAppTime_();
|
||||
return app_time_microsecs_;
|
||||
}
|
||||
|
||||
auto CoreFeatureSet::GetAppTimeSeconds() -> seconds_t {
|
||||
UpdateAppTime();
|
||||
UpdateAppTime_();
|
||||
return static_cast<seconds_t>(app_time_microsecs_) / 1000000;
|
||||
}
|
||||
|
||||
void CoreFeatureSet::UpdateAppTime() {
|
||||
void CoreFeatureSet::UpdateAppTime_() {
|
||||
microsecs_t t = CorePlatform::GetCurrentMicrosecs();
|
||||
|
||||
// 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,
|
||||
millisecs_t delay) {
|
||||
if (!started_suicide_) {
|
||||
@ -433,4 +437,14 @@ auto CoreFeatureSet::CurrentThreadName() -> std::string {
|
||||
#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
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#ifndef BALLISTICA_CORE_CORE_H_
|
||||
#define BALLISTICA_CORE_CORE_H_
|
||||
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
@ -186,13 +185,36 @@ class CoreFeatureSet {
|
||||
void set_event_loops_suspended(bool val) { event_loops_suspended_ = val; }
|
||||
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:
|
||||
explicit CoreFeatureSet(CoreConfig config);
|
||||
static void DoImport(const CoreConfig& config);
|
||||
static auto CalcBuildSrcDir() -> std::string;
|
||||
void RunSanityChecks();
|
||||
void UpdateAppTime();
|
||||
void PostInit();
|
||||
static void DoImport_(const CoreConfig& config);
|
||||
static auto CalcBuildSrcDir_() -> std::string;
|
||||
void RunSanityChecks_();
|
||||
void UpdateAppTime_();
|
||||
void PostInit_();
|
||||
|
||||
// Note to self: don't use single bits for these as they may be owned by
|
||||
// different threads.
|
||||
@ -203,7 +225,9 @@ class CoreFeatureSet {
|
||||
bool vr_mode_{};
|
||||
bool using_custom_app_python_dir_{};
|
||||
bool engine_done_{};
|
||||
LogLevel log_levels_[static_cast<int>(LogName::kLast)]{};
|
||||
|
||||
PyObject* initial_app_config_{};
|
||||
std::thread::id main_thread_id_{};
|
||||
CoreConfig core_config_;
|
||||
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_site_python_dir_;
|
||||
std::string ba_env_data_dir_;
|
||||
double ba_env_launch_timestamp_{-1.0};
|
||||
std::mutex thread_info_map_mutex_;
|
||||
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")) {
|
||||
size_t result = fwrite(val.c_str(), val.size(), 1, f2);
|
||||
if (result != 1)
|
||||
Log(LogLevel::kError, "unable to write bsuuid file.");
|
||||
Log(LogName::kBa, LogLevel::kError, "unable to write bsuuid file.");
|
||||
fclose(f2);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"unable to open bsuuid file for writing: '" + path + "'");
|
||||
}
|
||||
}
|
||||
@ -192,7 +192,8 @@ auto CorePlatform::GetLegacyDeviceUUID() -> const std::string& {
|
||||
}
|
||||
|
||||
auto CorePlatform::GetDeviceV1AccountUUIDPrefix() -> std::string {
|
||||
Log(LogLevel::kError, "GetDeviceV1AccountUUIDPrefix() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"GetDeviceV1AccountUUIDPrefix() unimplemented");
|
||||
return "u";
|
||||
}
|
||||
|
||||
@ -248,10 +249,12 @@ void CorePlatform::SetLowLevelConfigValue(const char* key, int value) {
|
||||
if (f) {
|
||||
size_t result = fwrite(out.c_str(), out.size(), 1, f);
|
||||
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);
|
||||
} 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;
|
||||
} else {
|
||||
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");
|
||||
}
|
||||
return "en_US";
|
||||
@ -688,7 +691,7 @@ auto CorePlatform::ConvertIncomingLeaderboardScore(
|
||||
|
||||
void CorePlatform::SubmitScore(const std::string& game,
|
||||
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) {}
|
||||
@ -701,7 +704,8 @@ auto CorePlatform::HaveLeaderboard(const std::string& game,
|
||||
void CorePlatform::ShowGameServiceUI(const std::string& show,
|
||||
const std::string& game,
|
||||
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) {
|
||||
@ -729,7 +733,7 @@ auto CorePlatform::DemangleCXXSymbol(const std::string& s) -> std::string {
|
||||
abi::__cxa_demangle(s.c_str(), nullptr, nullptr, &demangle_status);
|
||||
if (demangled_name != nullptr) {
|
||||
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");
|
||||
}
|
||||
std::string retval = demangled_name;
|
||||
@ -744,25 +748,28 @@ auto CorePlatform::DemangleCXXSymbol(const std::string& s) -> std::string {
|
||||
}
|
||||
|
||||
void CorePlatform::ResetAchievements() {
|
||||
Log(LogLevel::kError, "ResetAchievements() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "ResetAchievements() unimplemented");
|
||||
}
|
||||
|
||||
void CorePlatform::RunEvents() {}
|
||||
|
||||
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() {
|
||||
Log(LogLevel::kError, "MusicPlayerStop() unimplemented on this platform");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"MusicPlayerStop() unimplemented on this platform");
|
||||
}
|
||||
|
||||
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) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"MusicPlayerSetVolume() unimplemented on this platform");
|
||||
}
|
||||
|
||||
@ -785,7 +792,7 @@ void CorePlatform::SubmitAnalyticsCounts() {}
|
||||
void CorePlatform::SetPlatformMiscReadVals(const std::string& vals) {}
|
||||
|
||||
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; }
|
||||
@ -796,7 +803,7 @@ auto CorePlatform::GetHasVideoAds() -> bool {
|
||||
}
|
||||
|
||||
void CorePlatform::SignInV1(const std::string& account_type) {
|
||||
Log(LogLevel::kError, "SignInV1() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "SignInV1() unimplemented");
|
||||
}
|
||||
|
||||
void CorePlatform::V1LoginDidChange() {
|
||||
@ -804,33 +811,35 @@ void CorePlatform::V1LoginDidChange() {
|
||||
}
|
||||
|
||||
void CorePlatform::SignOutV1() {
|
||||
Log(LogLevel::kError, "SignOutV1() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "SignOutV1() unimplemented");
|
||||
}
|
||||
|
||||
void CorePlatform::MacMusicAppInit() {
|
||||
Log(LogLevel::kError, "MacMusicAppInit() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "MacMusicAppInit() unimplemented");
|
||||
}
|
||||
|
||||
auto CorePlatform::MacMusicAppGetVolume() -> int {
|
||||
Log(LogLevel::kError, "MacMusicAppGetVolume() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "MacMusicAppGetVolume() unimplemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CorePlatform::MacMusicAppSetVolume(int volume) {
|
||||
Log(LogLevel::kError, "MacMusicAppSetVolume() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "MacMusicAppSetVolume() unimplemented");
|
||||
}
|
||||
|
||||
void CorePlatform::MacMusicAppStop() {
|
||||
Log(LogLevel::kError, "MacMusicAppStop() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError, "MacMusicAppStop() unimplemented");
|
||||
}
|
||||
|
||||
auto CorePlatform::MacMusicAppPlayPlaylist(const std::string& playlist)
|
||||
-> bool {
|
||||
Log(LogLevel::kError, "MacMusicAppPlayPlaylist() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"MacMusicAppPlayPlaylist() unimplemented");
|
||||
return false;
|
||||
}
|
||||
auto CorePlatform::MacMusicAppGetPlaylists() -> std::list<std::string> {
|
||||
Log(LogLevel::kError, "MacMusicAppGetPlaylists() unimplemented");
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"MacMusicAppGetPlaylists() unimplemented");
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -935,8 +944,9 @@ auto CorePlatform::SetSocketNonBlocking(int sd) -> bool {
|
||||
#else
|
||||
int result = fcntl(sd, F_SETFL, O_NONBLOCK);
|
||||
if (result != 0) {
|
||||
Log(LogLevel::kError, "Error setting non-blocking socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Error setting non-blocking socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -1069,6 +1079,12 @@ auto CorePlatform::GetCurrentMicrosecs() -> millisecs_t {
|
||||
.count();
|
||||
}
|
||||
|
||||
auto CorePlatform::GetSecondsSinceEpoch() -> double {
|
||||
return std::chrono::duration<double>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
|
||||
auto CorePlatform::GetCurrentWholeSeconds() -> int64_t {
|
||||
return std::chrono::time_point_cast<std::chrono::seconds>(
|
||||
std::chrono::steady_clock::now())
|
||||
|
||||
@ -369,6 +369,9 @@ class CorePlatform {
|
||||
/// to not go backwards.
|
||||
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 SleepMillisecs(millisecs_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.
|
||||
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 UTF8Encode(big_buffer.data());
|
||||
@ -997,14 +998,15 @@ std::vector<uint32_t> CorePlatformWindows::GetBroadcastAddrs() {
|
||||
pIPAddrTable = static_cast<MIB_IPADDRTABLE*>(MALLOC(dwSize));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
// Make a second call to GetIpAddrTable to get the actual data we want
|
||||
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"GetIpAddrTable failed with error " + std::to_string(dwRetVal));
|
||||
err = true;
|
||||
}
|
||||
@ -1040,8 +1042,9 @@ bool CorePlatformWindows::SetSocketNonBlocking(int sd) {
|
||||
unsigned long dataval = 1; // NOLINT (func signature wants long)
|
||||
int result = ioctlsocket(sd, FIONBIO, &dataval);
|
||||
if (result != 0) {
|
||||
Log(LogLevel::kError, "Error setting non-blocking socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Error setting non-blocking socket: "
|
||||
+ g_core->platform->GetSocketErrorString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -4,10 +4,12 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/core/mgen/python_modules_monolithic.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_command.h"
|
||||
|
||||
@ -174,18 +176,38 @@ void CorePython::EnablePythonLoggingCalls() {
|
||||
}
|
||||
auto gil{Python::ScopedInterpreterLock()};
|
||||
|
||||
assert(objs().Exists(ObjID::kLoggingDebugCall));
|
||||
assert(objs().Exists(ObjID::kLoggingInfoCall));
|
||||
assert(objs().Exists(ObjID::kLoggingWarningCall));
|
||||
assert(objs().Exists(ObjID::kLoggingErrorCall));
|
||||
assert(objs().Exists(ObjID::kLoggingCriticalCall));
|
||||
// Make sure we've got all our logging Python bits we need.
|
||||
assert(objs().Exists(ObjID::kLoggingLevelDebug));
|
||||
assert(objs().Exists(ObjID::kLoggingLevelInfo));
|
||||
assert(objs().Exists(ObjID::kLoggingLevelWarning));
|
||||
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.
|
||||
{
|
||||
std::scoped_lock lock(early_log_lock_);
|
||||
python_logging_calls_enabled_ = true;
|
||||
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();
|
||||
}
|
||||
@ -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() {
|
||||
auto gil{Python::ScopedInterpreterLock()};
|
||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_babase"));
|
||||
@ -296,23 +384,25 @@ void CorePython::MonolithicModeBaEnvConfigure() {
|
||||
g_core->LifecycleLog("baenv.configure() end");
|
||||
}
|
||||
|
||||
void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) {
|
||||
// If we're not yet sending logs to Python, store this one away until we are.
|
||||
void CorePython::LoggingCall(LogName logname, LogLevel loglevel,
|
||||
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_) {
|
||||
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
|
||||
// logs a bit less scary. Perhaps we can update fatal-error to dump these or
|
||||
// have a mode to immediate-print them as needed.
|
||||
// UPDATE - trying to disable this for now to make the concept of
|
||||
// delayed logs a bit less scary. Perhaps we can update fatal-error to
|
||||
// dump these or have a mode to immediate-print them as needed.
|
||||
if (explicit_bool(false)) {
|
||||
// There's a chance that we're going down in flames and this log
|
||||
// might be useful to see even if we never get a chance to chip it to
|
||||
// There's a chance that we're going down in flames and this log might
|
||||
// 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
|
||||
// whatever way we can. (platform display-log call and stderr).
|
||||
const char* errmsg{
|
||||
"CorePython::LoggingCall() called before Python"
|
||||
" logging available."};
|
||||
"CorePython::LoggingCall() called before Python logging "
|
||||
"available."};
|
||||
if (g_core->platform) {
|
||||
g_core->platform->EmitPlatformLog("root", LogLevel::kError, errmsg);
|
||||
g_core->platform->EmitPlatformLog("root", loglevel, msg);
|
||||
@ -322,42 +412,93 @@ void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) {
|
||||
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.
|
||||
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);
|
||||
}
|
||||
|
||||
auto CorePython::WasModularMainCalled() -> bool {
|
||||
assert(!g_buildconfig.monolithic_build());
|
||||
|
||||
// This gets called in modular builds before anything is inited, so we need to
|
||||
// avoid using anything from g_core or whatnot here; only raw Python stuff.
|
||||
// This gets called in modular builds before anything is inited, so we need
|
||||
// to avoid using anything from g_core or whatnot here; only raw Python
|
||||
// stuff.
|
||||
|
||||
PyObject* baenv = PyImport_ImportModule("baenv");
|
||||
if (!baenv) {
|
||||
@ -394,8 +535,9 @@ auto CorePython::WasModularMainCalled() -> bool {
|
||||
|
||||
auto CorePython::FetchPythonArgs(std::vector<std::string>* buffer)
|
||||
-> std::vector<char*> {
|
||||
// This gets called in modular builds before anything is inited, so we need to
|
||||
// avoid using anything from g_core or whatnot here; only raw Python stuff.
|
||||
// This gets called in modular builds before anything is inited, so we need
|
||||
// to avoid using anything from g_core or whatnot here; only raw Python
|
||||
// stuff.
|
||||
|
||||
assert(buffer && buffer->empty());
|
||||
PyObject* sys = PyImport_ImportModule("sys");
|
||||
|
||||
@ -24,11 +24,29 @@ class CorePython {
|
||||
kJsonDumpsCall,
|
||||
kJsonLoadsCall,
|
||||
kEmptyTuple,
|
||||
kLoggingDebugCall,
|
||||
kLoggingInfoCall,
|
||||
kLoggingWarningCall,
|
||||
kLoggingErrorCall,
|
||||
kLoggingCriticalCall,
|
||||
kLoggingLevelDebug,
|
||||
kLoggingLevelInfo,
|
||||
kLoggingLevelWarning,
|
||||
kLoggingLevelError,
|
||||
kLoggingLevelCritical,
|
||||
kLoggerRoot,
|
||||
kLoggerRootLogCall,
|
||||
kLoggerBa,
|
||||
kLoggerBaLogCall,
|
||||
kLoggerBaAccount,
|
||||
kLoggerBaAccountLogCall,
|
||||
kLoggerBaAudio,
|
||||
kLoggerBaAudioLogCall,
|
||||
kLoggerBaGraphics,
|
||||
kLoggerBaGraphicsLogCall,
|
||||
kLoggerBaLifecycle,
|
||||
kLoggerBaLifecycleLogCall,
|
||||
kLoggerBaAssets,
|
||||
kLoggerBaAssetsLogCall,
|
||||
kLoggerBaInput,
|
||||
kLoggerBaInputLogCall,
|
||||
kLoggerBaNetworking,
|
||||
kLoggerBaNetworkingLogCall,
|
||||
kPrependSysPathCall,
|
||||
kBaEnvConfigureCall,
|
||||
kBaEnvGetConfigCall,
|
||||
@ -49,10 +67,11 @@ class CorePython {
|
||||
/// Can be called from any thread at any time. If called before Python
|
||||
/// logging is available, logs locally using Logging::EmitPlatformLog()
|
||||
/// (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 VerifyPythonEnvironment();
|
||||
void SoftImportBase();
|
||||
void UpdateInternalLoggerLevels(LogLevel* log_levels);
|
||||
|
||||
static auto WasModularMainCalled() -> bool;
|
||||
|
||||
@ -70,7 +89,7 @@ class CorePython {
|
||||
// go here. They all get shipped at once as soon as it is possible.
|
||||
bool python_logging_calls_enabled_{};
|
||||
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
|
||||
|
||||
@ -33,7 +33,8 @@ class BaseSoftInterface {
|
||||
virtual auto FeatureSetFromData(PyObject* obj)
|
||||
-> FeatureSetNativeComponent* = 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 PrintPythonStackTrace() -> bool = 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() {
|
||||
if (auto* envval = getenv("BA_LIFECYCLE_LOG")) {
|
||||
if (!strcmp(envval, "1")) {
|
||||
lifecycle_log = true;
|
||||
}
|
||||
}
|
||||
// TODO(ericf): This is now simply a log level. If we want to allow
|
||||
// controlling log-levels via env-vars we should come up with a unified
|
||||
// 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 (!strcmp(envval, "1")) {
|
||||
debugger_attached = true;
|
||||
|
||||
@ -30,14 +30,7 @@ class CoreConfig {
|
||||
bool vr_mode{};
|
||||
|
||||
/// Log various stages/times in the bootstrapping process.
|
||||
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};
|
||||
// bool lifecycle_log{};
|
||||
|
||||
/// Let the engine know there's a debugger attached so it should do things
|
||||
/// like abort() instead of exiting with error codes.
|
||||
|
||||
@ -156,7 +156,7 @@ void Connection::HandleGamePacketCompressed(const std::vector<uint8_t>& data) {
|
||||
try {
|
||||
data_decompressed = g_base->huffman->decompress(data);
|
||||
} catch (const std::exception& e) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
std::string("Error in huffman decompression for packet: ") + e.what());
|
||||
|
||||
// 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]) {
|
||||
case BA_SCENEPACKET_KEEPALIVE: {
|
||||
if (data.size() != 4) {
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error: got invalid BA_SCENEPACKET_KEEPALIVE packet.");
|
||||
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.
|
||||
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;
|
||||
}
|
||||
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,
|
||||
// at least 1 byte payload.
|
||||
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;
|
||||
}
|
||||
uint16_t num, num_unreliable;
|
||||
@ -242,8 +244,9 @@ void Connection::HandleGamePacket(const std::vector<uint8_t>& data) {
|
||||
}
|
||||
|
||||
default:
|
||||
Log(LogLevel::kError, "Connection got unknown packet type: "
|
||||
+ std::to_string(static_cast<int>(data[0])));
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Connection got unknown packet type: "
|
||||
+ std::to_string(static_cast<int>(data[0])));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -325,7 +328,7 @@ void Connection::SendReliableMessage(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.
|
||||
if (data.size() + 8 > kMaxPacketSize) {
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error: Dropping outgoing unreliable packet of size "
|
||||
+ std::to_string(data.size()) + ".");
|
||||
return;
|
||||
@ -438,11 +441,12 @@ void Connection::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
multipart_buffer_.resize(old_size + (buffer.size() - 1));
|
||||
memcpy(&(multipart_buffer_[old_size]), &(buffer[1]), buffer.size() - 1);
|
||||
} 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 (multipart_buffer_[0] == BA_MESSAGE_MULTIPART) {
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||
"nested multipart message detected; kicking");
|
||||
Error("");
|
||||
}
|
||||
@ -487,7 +491,7 @@ void Connection::SendGamePacket(const std::vector<uint8_t>& data) {
|
||||
&& data[0] != BA_SCENEPACKET_HANDSHAKE_RESPONSE) {
|
||||
if (explicit_bool(false)) {
|
||||
BA_LOG_ONCE(
|
||||
LogLevel::kError,
|
||||
LogName::kBaNetworking, LogLevel::kError,
|
||||
"SendGamePacket() called before can_communicate set ("
|
||||
+ g_core->platform->DemangleCXXSymbol(typeid(*this).name())
|
||||
+ " 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,
|
||||
// detach all clients from it.
|
||||
if (client_controller_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"RegisterClientController() called "
|
||||
"but already have a controller; bad.");
|
||||
for (auto&& i : connections_to_clients_) {
|
||||
@ -214,7 +214,7 @@ auto ConnectionSet::GetConnectionsToClients()
|
||||
if (connections_to_client.second.Exists()) {
|
||||
connections.push_back(connections_to_client.second.Get());
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"HAVE NONEXISTENT CONNECTION_TO_CLIENT IN LIST; UNEXPECTED");
|
||||
}
|
||||
}
|
||||
@ -274,7 +274,7 @@ void ConnectionSet::SendScreenMessageToAll(const std::string& s, float r,
|
||||
void ConnectionSet::PrepareForLaunchHostSession() {
|
||||
// If for some reason we're still attached to a host, kill the connection.
|
||||
if (connection_to_host_.Exists()) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Had host-connection during LaunchHostSession(); shouldn't happen.");
|
||||
connection_to_host_->RequestDisconnect();
|
||||
connection_to_host_.Clear();
|
||||
@ -320,8 +320,9 @@ auto ConnectionSet::DisconnectClient(int client_id, int ban_seconds) -> bool {
|
||||
return false;
|
||||
}
|
||||
if (client_id > 255) {
|
||||
Log(LogLevel::kError, "DisconnectClient got client_id > 255 ("
|
||||
+ std::to_string(client_id) + ")");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"DisconnectClient got client_id > 255 (" + std::to_string(client_id)
|
||||
+ ")");
|
||||
} else {
|
||||
std::vector<uint8_t> msg_out(2);
|
||||
msg_out[0] = BA_MESSAGE_KICK_VOTE;
|
||||
@ -409,7 +410,7 @@ void ConnectionSet::UnregisterClientController(ClientControllerInterface* c) {
|
||||
|
||||
// This shouldn't happen.
|
||||
if (client_controller_ != c) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"UnregisterClientController() called with a non-registered "
|
||||
"controller");
|
||||
return;
|
||||
@ -675,7 +676,8 @@ void ConnectionSet::HandleIncomingUDPPacket(const std::vector<uint8_t>& data_in,
|
||||
msg_out[0] = BA_PACKET_CLIENT_DENY;
|
||||
msg_out[1] = request_id;
|
||||
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;
|
||||
}
|
||||
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()) {
|
||||
return true;
|
||||
}
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||
"VerifyClientAddr() found mismatch for client "
|
||||
+ std::to_string(client_id) + ".");
|
||||
return false;
|
||||
@ -730,7 +732,7 @@ void ConnectionSet::SetClientInfoFromMasterServer(
|
||||
const std::string& client_token, PyObject* info_obj) {
|
||||
// NOLINTNEXTLINE (python doing bitwise math on signed int)
|
||||
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
|
||||
+ ": " + Python::ObjToString(info_obj));
|
||||
return;
|
||||
|
||||
@ -144,7 +144,8 @@ void ConnectionToClient::HandleGamePacket(const std::vector<uint8_t>& data) {
|
||||
}
|
||||
|
||||
if (data.empty()) {
|
||||
Log(LogLevel::kError, "ConnectionToClient got data size 0.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"ConnectionToClient got data size 0.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -157,7 +158,8 @@ void ConnectionToClient::HandleGamePacket(const std::vector<uint8_t>& data) {
|
||||
case BA_SCENEPACKET_HANDSHAKE_RESPONSE: {
|
||||
// We sent the client a handshake and they're responding.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -350,7 +352,8 @@ void ConnectionToClient::SendScreenMessage(const std::string& s, float r,
|
||||
void ConnectionToClient::HandleMessagePacket(
|
||||
const std::vector<uint8_t>& buffer) {
|
||||
if (buffer.empty()) {
|
||||
Log(LogLevel::kError, "Got invalid HandleMessagePacket.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Got invalid HandleMessagePacket.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -404,7 +407,8 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
if (b) {
|
||||
build_number_ = b->valueint;
|
||||
} 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
|
||||
@ -413,7 +417,8 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
if (t) {
|
||||
token_ = t->valuestring;
|
||||
} 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
|
||||
@ -432,7 +437,7 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
}
|
||||
cJSON_Delete(info);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Got invalid json in clientinfo message: '"
|
||||
+ 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
|
||||
// connections to/from these older peers while still allowing old replays
|
||||
// to play back.
|
||||
BA_LOG_ONCE(LogLevel::kError,
|
||||
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Received old pre-json player profiles msg; ignoring.");
|
||||
break;
|
||||
}
|
||||
@ -501,7 +506,7 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
// spamming before we can verify their identities)
|
||||
if (appmode->require_client_authentication()
|
||||
&& !got_info_from_master_server_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Ignoring chat message from peer with no client info.");
|
||||
SendScreenMessage(R"({"r":"loadingTryAgainText"})", 1, 0, 0);
|
||||
} else if (last_chat_times_.size() >= 5) {
|
||||
@ -599,7 +604,8 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
GetClientInputDevice(buffer[1])) {
|
||||
int count = static_cast<int>((buffer.size() - 2) / 5);
|
||||
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;
|
||||
}
|
||||
int index = 2;
|
||||
@ -617,7 +623,8 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
case BA_MESSAGE_REMOVE_REMOTE_PLAYER: {
|
||||
last_remove_player_time_ = g_core->GetAppTimeMillisecs();
|
||||
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;
|
||||
}
|
||||
if (ClientInputDevice* cid = GetClientInputDevice(buffer[1])) {
|
||||
@ -632,7 +639,7 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
host_session->RemovePlayer(player);
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Unable to get ClientInputDevice for remove-remote-player msg.");
|
||||
}
|
||||
}
|
||||
@ -641,7 +648,8 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
|
||||
case BA_MESSAGE_REQUEST_REMOTE_PLAYER: {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -652,7 +660,7 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
// It should have one of our special client delegates attached.
|
||||
auto* cid_d = dynamic_cast<ClientInputDeviceDelegate*>(&cid->delegate());
|
||||
if (!cid_d) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Can't get client-input-device-delegate in request-remote-player "
|
||||
"msg.");
|
||||
break;
|
||||
@ -676,7 +684,7 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
} else {
|
||||
// Either timed out or have info; let the request go through.
|
||||
if (still_waiting_for_auth) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Allowing player-request without client\'s master-server "
|
||||
"info (build "
|
||||
+ std::to_string(build_number_) + ")");
|
||||
@ -685,7 +693,7 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"ConnectionToClient got remote player"
|
||||
" request but have no host session");
|
||||
}
|
||||
@ -699,9 +707,9 @@ void ConnectionToClient::HandleMessagePacket(
|
||||
if (multipart_buffer_size() > 50000) {
|
||||
// Its not actually unknown but shhh don't tell the hackers...
|
||||
SendScreenMessage(R"({"r":"errorUnknownText"})", 1, 0, 0);
|
||||
Log(LogLevel::kError, "Client data limit exceeded by '"
|
||||
+ peer_spec().GetShortName()
|
||||
+ "'; kicking.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Client data limit exceeded by '" + peer_spec().GetShortName()
|
||||
+ "'; kicking.");
|
||||
appmode->BanPlayer(peer_spec(), 1000 * 60);
|
||||
Error("");
|
||||
return;
|
||||
@ -792,8 +800,9 @@ void ConnectionToClient::HandleMasterServerClientInfo(PyObject* info_obj) {
|
||||
"{\"t\":[\"serverResponses\","
|
||||
"\"Your account was rejected. Are you signed in?\"]}",
|
||||
1, 0, 0);
|
||||
Log(LogLevel::kError, "Master server found no valid account for '"
|
||||
+ peer_spec().GetShortName() + "'; kicking.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Master server found no valid account for '"
|
||||
+ peer_spec().GetShortName() + "'; kicking.");
|
||||
|
||||
// Not benning anymore. People were exploiting this by impersonating
|
||||
// other players using their public ids to get them banned from
|
||||
|
||||
@ -72,7 +72,8 @@ void ConnectionToClientUDP::HandleGamePacket(
|
||||
|
||||
void ConnectionToClientUDP::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;
|
||||
}
|
||||
// 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");
|
||||
PythonRef empty_dict;
|
||||
if (!profiles) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"No profiles found; sending empty list to host");
|
||||
empty_dict.Steal(PyDict_New());
|
||||
profiles = empty_dict.Get();
|
||||
@ -265,7 +265,7 @@ void ConnectionToHost::HandleGamePacket(const std::vector<uint8_t>& data) {
|
||||
.Get(core::CorePython::ObjID::kJsonDumpsCall)
|
||||
.Call(args, keywds);
|
||||
if (!results.Exists()) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Error getting json dump of local profiles");
|
||||
} else {
|
||||
try {
|
||||
@ -276,14 +276,14 @@ void ConnectionToHost::HandleGamePacket(const std::vector<uint8_t>& data) {
|
||||
memcpy(&(msg[1]), &s[0], s.size());
|
||||
SendReliableMessage(msg);
|
||||
} catch (const std::exception& e) {
|
||||
Log(LogLevel::kError,
|
||||
std::string("exc sending player profiles to host: ")
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
std::string("Error sending player profiles to host: ")
|
||||
+ e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"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());
|
||||
|
||||
if (buffer.empty()) {
|
||||
Log(LogLevel::kError, "Got invalid HandleMessagePacket");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Got invalid HandleMessagePacket");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -335,7 +336,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
if (b) {
|
||||
build_number_ = b->valueint;
|
||||
} else {
|
||||
Log(LogLevel::kError, "no buildnumber in hostinfo msg");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"no buildnumber in hostinfo msg");
|
||||
}
|
||||
// Party name.
|
||||
cJSON* n = cJSON_GetObjectItem(info, "n");
|
||||
@ -344,7 +346,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
}
|
||||
cJSON_Delete(info);
|
||||
} 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;
|
||||
@ -440,7 +443,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
case BA_MESSAGE_ATTACH_REMOTE_PLAYER_2: {
|
||||
// New-style packet which includes a 32-bit player_id.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -457,7 +461,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
delegate->AttachToRemotePlayer(this,
|
||||
static_cast_check_fit<int>(player_id));
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"InputDevice does not have a SceneV1 delegate as expected "
|
||||
"(loc1).");
|
||||
}
|
||||
@ -476,7 +480,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
// public servers.
|
||||
// TODO(ericf): can remove this once back-compat-protocol > 29.
|
||||
if (buffer.size() != 3) {
|
||||
Log(LogLevel::kError, "Invalid attach-remote-player msg.");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Invalid attach-remote-player msg.");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -490,7 +495,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
&input_device->delegate())) {
|
||||
delegate->AttachToRemotePlayer(this, buffer[2]);
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"InputDevice does not have a SceneV1 delegate as expected "
|
||||
"(loc2).");
|
||||
}
|
||||
@ -508,7 +513,8 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
|
||||
case BA_MESSAGE_DETACH_REMOTE_PLAYER: {
|
||||
if (buffer.size() != 2) {
|
||||
Log(LogLevel::kError, "Invalid detach-remote-player msg");
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Invalid detach-remote-player msg");
|
||||
break;
|
||||
}
|
||||
// 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
|
||||
// the case.
|
||||
if (connection_to_host != nullptr) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"InputDevice does not have a SceneV1 delegate as expected "
|
||||
"(loc3).");
|
||||
}
|
||||
|
||||
@ -125,7 +125,8 @@ void ConnectionToHostUDP::Update() {
|
||||
// departure before doing this when possible.
|
||||
void ConnectionToHostUDP::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;
|
||||
}
|
||||
if (auto* appmode = classic::ClassicAppMode::GetActiveOrWarn()) {
|
||||
@ -133,7 +134,7 @@ void ConnectionToHostUDP::Die() {
|
||||
appmode->connections()->PushDisconnectedFromHostCall();
|
||||
did_die_ = true;
|
||||
} else {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBaNetworking, LogLevel::kError,
|
||||
"Running update for non-current host-connection; shouldn't "
|
||||
"happen.");
|
||||
}
|
||||
|
||||
@ -136,14 +136,14 @@ class Dynamics::Impl_ {
|
||||
|
||||
Dynamics::Dynamics(Scene* scene_in)
|
||||
: scene_(scene_in),
|
||||
collision_cache_(new base::CollisionCache()),
|
||||
collision_cache_(std::make_unique<base::CollisionCache>()),
|
||||
impl_(std::make_unique<Impl_>(this)) {
|
||||
ResetODE_();
|
||||
}
|
||||
|
||||
Dynamics::~Dynamics() {
|
||||
if (in_process_) {
|
||||
Log(LogLevel::kError,
|
||||
Log(LogName::kBa, LogLevel::kError,
|
||||
"Dynamics going down within Process() call;"
|
||||
" 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