mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-07 16:13:23 +08:00
Initial work on AppExperiences
This commit is contained in:
parent
7b8a98bf98
commit
183c5abf60
56
.efrocachemap
generated
56
.efrocachemap
generated
@ -4064,26 +4064,26 @@
|
|||||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "95166586256dc94f679d3f15cf570ed8",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ca001c9f2b4edf8d4918c1bcaf0cb561",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "820f8a69f86434ff6dab9cc23e675708",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "fcb58aae4535a761be49420f4e4a7711",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "70903ec2f476fbc5908cc52522f69e0c",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "8f453b8193ba06a3cc59374cdd2a1c09",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "442f2bdde3c176d9a4431c9fdcca892e",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7c389cb83619516ce96118227668500e",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "5354821ede7348ba9bb90bee8fe5ccb7",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2ffcc486e9ba8f0fd5279083a2e54aff",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ab0cb59c874beb50e554d3d7c552565e",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "366bab5bff3ff9344e54bf7492f4d7c3",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "dec2c09bd136aa413b9b94729f7d6d2e",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "78277cc1bd40ba88fd1475f8755e0721",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a5c43eb8befc810d693ec9c9f83fcba4",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "5f063e4d45e40ade22f1bad63658752e",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "56bf9b14517f0a579964b39218498fcf",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f7114c78146f22e89143218c9930b43e",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "d6a10e3a6bc1a07609598f962439c6c8",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "90c0ea0ce7a35d8f15b2a29bef704819",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ab5cb01ed4a8a8db80ca65ab5cd0133b",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "e1b4932fd7f359404c979604a1e33444",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "231bd6e18145b06028e4f90fd7de106c",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "28ab454f71dfecd1986a245eb4a732e7",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3cc88ed5471e9b7f2b84af4ee58a8061",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "7b1a4db9c3f36fd428cdafbc1459bc1b",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "4586629e8f114c1b5a22444ae26b5917",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "bc5a48ff49975901f212d18b1dbbb6f5",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e1177b377c3e48d60057a9719bf9d0e3",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "7742db7c9555907fc7b2d5c89d48dfd0",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "518c529a7133d5ea41d730d12ae156c4",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "d81bc55d666f630a14de90f30be29fb4",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "41e7afae9395843c575c65593aab423c",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "5ab68bfee69a6fe07b5b8a68938220e6",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d95e4cc445b722f111e51b3d4b7bdde9",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "59a2b3cb2c1dde98c6aedf72aa9fdbfb",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d75e3afcc1db962cd483f8b80a65c930",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "2199e800eb102d56197e11782b7adf12",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "2b1b27fc2ca79803d79796a7414db3a2",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "3193300cf9927276893960698d8246f6",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b5a129d83796c9e7015ab5e319d2c22f",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b5a129d83796c9e7015ab5e319d2c22f",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5",
|
||||||
@ -4100,14 +4100,14 @@
|
|||||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df",
|
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d34c0a142e7d391a109a33ea3cc77c08",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d34c0a142e7d391a109a33ea3cc77c08",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df",
|
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "aa15bc38411a8a4194b3711c9c6ebf56",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "13a3bb41dda8cfdb3ffdbc57a0390275",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "3539534ba129d95e99f89ddf79d14f28",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "042ff1129bab0def6bf90250b5c08a32",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "75e16f083a18621fe4502bc170e6a696",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "699ab8e6fd3e8517acac76cd5b40dfbc",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "29b9a8543b1612c0451eaaf90647b905",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "5b53317f8900cab59288be44b353dffc",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "4fb61373afaa6ce350601b245fcb1b7a",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "978ea0ba60c026efd45729cd48c0feba",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "d8e606cdfef72b6170721d87ee1d9b11",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "1fb524f11277090440cda18bfc3ee3a0",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "240b54fa0d4334591c0876a2b72a4663",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "91452d47e879acd0d7fdd06a44fbcfed",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a7887447024ce5570da3f468bad5bbb4",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "7e9469f3cac9ab85c5e9d1256679604c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
|
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "ad347097a38e0d7ede9eb6dec6a80ee9",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "ad347097a38e0d7ede9eb6dec6a80ee9",
|
||||||
|
|||||||
23
CHANGELOG.md
23
CHANGELOG.md
@ -1,19 +1,19 @@
|
|||||||
### 1.7.28 (build 21299, api 8, 2023-09-01)
|
### 1.7.28 (build 21303, api 8, 2023-09-01)
|
||||||
|
|
||||||
- Added some high level functionality for copying and deleting feature-sets to
|
- Added some high level functionality for copying and deleting feature-sets to
|
||||||
the `tools/spinoff` tool. For example, to create your own `poo` feature-set,
|
the `spinoff` tool. For example, to create your own `poo` feature-set based on
|
||||||
do `tools/spinoff fset-copy template_fs poo`. Then do `make update` and `make
|
the existing `template_fs` one, do `tools/spinoff fset-copy template_fs poo`.
|
||||||
cmake` to build and run the app, and from within it you should be able to do
|
Then do `make update` and `make cmake` to build and run the app, and from
|
||||||
`import bapoo` to get at your nice shiny poo feature-set. When you are done
|
within it you should be able to do `import bapoo` to get at your nice shiny
|
||||||
playing, you can do `tools/spinoff fset-delete poo` to blow away any traces of
|
poo feature-set. When you are done playing around, you can do `tools/spinoff
|
||||||
it.
|
fset-delete poo` to blow away any traces of it.
|
||||||
- Public builds now properly reconstruct the CMakeLists.txt file for project
|
- Public builds now properly reconstruct the CMakeLists.txt file for project
|
||||||
changes.
|
changes.
|
||||||
- Efrocache now supports a starter-archive when building server builds. This
|
- Efrocache now supports a starter-archive when building server builds. This
|
||||||
means that if you do something like `make clean; make
|
means that if you do something like `make clean; make
|
||||||
prefab-server-release-build` you should only see a few file downloads
|
prefab-server-release-build` you should see just a few file downloads
|
||||||
happening instead of hundreds or thousands which would happen before, which
|
happening instead of the hundreds that would happen before, which should be
|
||||||
should be significantly faster & more efficient.
|
significantly faster & more efficient.
|
||||||
|
|
||||||
### 1.7.27 (build 21282, api 8, 2023-08-30)
|
### 1.7.27 (build 21282, api 8, 2023-08-30)
|
||||||
|
|
||||||
@ -40,7 +40,8 @@
|
|||||||
`build_number`, `device_name`, `config_file_path`, `version`, `debug_build`,
|
`build_number`, `device_name`, `config_file_path`, `version`, `debug_build`,
|
||||||
`test_build`, `data_directory`, `python_directory_user`,
|
`test_build`, `data_directory`, `python_directory_user`,
|
||||||
`python_directory_app`, `python_directory_app_site`, `api_version`, `on_tv`,
|
`python_directory_app`, `python_directory_app_site`, `api_version`, `on_tv`,
|
||||||
`vr_mode`.
|
`vr_mode`, `toolbar_test`, `arcade_mode`, `headless_mode`, `demo_mode`, and
|
||||||
|
`protocol_version`.
|
||||||
- Reverting the Android keyboard changes from 1.7.26, as I've received a few
|
- Reverting the Android keyboard changes from 1.7.26, as I've received a few
|
||||||
reports of bluetooth game controllers now thinking they are keyboards. I'm
|
reports of bluetooth game controllers now thinking they are keyboards. I'm
|
||||||
thinking I'll have to bite the bullet and implement something that asks the
|
thinking I'll have to bite the bullet and implement something that asks the
|
||||||
|
|||||||
@ -96,6 +96,7 @@
|
|||||||
"ba_data/python/baclassic/osmusic.py",
|
"ba_data/python/baclassic/osmusic.py",
|
||||||
"ba_data/python/bacommon/__init__.py",
|
"ba_data/python/bacommon/__init__.py",
|
||||||
"ba_data/python/bacommon/__pycache__/__init__.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/__init__.cpython-311.opt-1.pyc",
|
||||||
|
"ba_data/python/bacommon/__pycache__/app.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/assets.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/assets.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/bacloud.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/bacloud.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/build.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/build.cpython-311.opt-1.pyc",
|
||||||
@ -104,6 +105,7 @@
|
|||||||
"ba_data/python/bacommon/__pycache__/net.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/net.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/servermanager.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/servermanager.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bacommon/__pycache__/transfer.cpython-311.opt-1.pyc",
|
"ba_data/python/bacommon/__pycache__/transfer.cpython-311.opt-1.pyc",
|
||||||
|
"ba_data/python/bacommon/app.py",
|
||||||
"ba_data/python/bacommon/assets.py",
|
"ba_data/python/bacommon/assets.py",
|
||||||
"ba_data/python/bacommon/bacloud.py",
|
"ba_data/python/bacommon/bacloud.py",
|
||||||
"ba_data/python/bacommon/build.py",
|
"ba_data/python/bacommon/build.py",
|
||||||
|
|||||||
@ -712,6 +712,7 @@ $(eval $(call make-opt-pyc-target,$(element))))
|
|||||||
|
|
||||||
SCRIPT_TARGETS_PY_PUBLIC_TOOLS = \
|
SCRIPT_TARGETS_PY_PUBLIC_TOOLS = \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__init__.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/__init__.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bacommon/app.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/assets.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/assets.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/bacloud.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/bacloud.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/build.py \
|
$(BUILD_DIR)/ba_data/python/bacommon/build.py \
|
||||||
@ -746,6 +747,7 @@ SCRIPT_TARGETS_PY_PUBLIC_TOOLS = \
|
|||||||
|
|
||||||
SCRIPT_TARGETS_PYC_PUBLIC_TOOLS = \
|
SCRIPT_TARGETS_PYC_PUBLIC_TOOLS = \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/__init__.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/__init__.cpython-311.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/app.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/assets.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/assets.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/bacloud.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/bacloud.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/build.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bacommon/__pycache__/build.cpython-311.opt-1.pyc \
|
||||||
|
|||||||
@ -64,7 +64,7 @@ class AccountV2Subsystem:
|
|||||||
|
|
||||||
def set_primary_credentials(self, credentials: str | None) -> None:
|
def set_primary_credentials(self, credentials: str | None) -> None:
|
||||||
"""Set credentials for the primary app account."""
|
"""Set credentials for the primary app account."""
|
||||||
raise RuntimeError('This should be overridden.')
|
raise NotImplementedError('This should be overridden.')
|
||||||
|
|
||||||
def have_primary_credentials(self) -> bool:
|
def have_primary_credentials(self) -> bool:
|
||||||
"""Are credentials currently set for the primary app account?
|
"""Are credentials currently set for the primary app account?
|
||||||
@ -73,7 +73,7 @@ class AccountV2Subsystem:
|
|||||||
only that they exist. If/when credentials are validated, the 'primary'
|
only that they exist. If/when credentials are validated, the 'primary'
|
||||||
account handle will be set.
|
account handle will be set.
|
||||||
"""
|
"""
|
||||||
raise RuntimeError('This should be overridden.')
|
raise NotImplementedError('This should be overridden.')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def primary(self) -> AccountV2Handle | None:
|
def primary(self) -> AccountV2Handle | None:
|
||||||
|
|||||||
@ -112,7 +112,9 @@ class App:
|
|||||||
project.
|
project.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def app_mode_for_intent(self, intent: AppIntent) -> type[AppMode]:
|
def app_mode_for_intent(
|
||||||
|
self, intent: AppIntent
|
||||||
|
) -> type[AppMode] | None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
|
||||||
# __GOOD_PLACE_FOR_CUSTOM_SPINOFF_LOGIC__
|
# __GOOD_PLACE_FOR_CUSTOM_SPINOFF_LOGIC__
|
||||||
@ -127,10 +129,10 @@ class App:
|
|||||||
|
|
||||||
import babase
|
import babase
|
||||||
|
|
||||||
if bascenev1.SceneV1AppMode.supports_intent(intent):
|
if bascenev1.SceneV1AppMode.can_handle_intent(intent):
|
||||||
return bascenev1.SceneV1AppMode
|
return bascenev1.SceneV1AppMode
|
||||||
|
|
||||||
if babase.EmptyAppMode.supports_intent(intent):
|
if babase.EmptyAppMode.can_handle_intent(intent):
|
||||||
return babase.EmptyAppMode
|
return babase.EmptyAppMode
|
||||||
|
|
||||||
raise RuntimeError(f'No handler found for intent {type(intent)}.')
|
raise RuntimeError(f'No handler found for intent {type(intent)}.')
|
||||||
@ -144,19 +146,13 @@ class App:
|
|||||||
the single shared instance.
|
the single shared instance.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Hack for docs-generation.
|
||||||
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
||||||
return
|
return
|
||||||
|
|
||||||
self.env: babase.Env = _babase.Env()
|
self.env: babase.Env = _babase.Env()
|
||||||
|
|
||||||
self.state = self.State.NOT_RUNNING
|
self.state = self.State.NOT_RUNNING
|
||||||
|
|
||||||
# Controls which app-modes we use for handling given
|
|
||||||
# app-intents. Plugins can override this to change high level
|
|
||||||
# app behavior and spinoff projects can change the default
|
|
||||||
# implementation for the same effect.
|
|
||||||
self.mode_selector: babase.AppModeSelector | None = None
|
|
||||||
|
|
||||||
# Default executor which can be used for misc background
|
# Default executor which can be used for misc background
|
||||||
# processing. It should also be passed to any additional asyncio
|
# processing. It should also be passed to any additional asyncio
|
||||||
# loops we create so that everything shares the same single set
|
# loops we create so that everything shares the same single set
|
||||||
@ -193,6 +189,7 @@ class App:
|
|||||||
self._pending_intent: AppIntent | None = None
|
self._pending_intent: AppIntent | None = None
|
||||||
self._intent: AppIntent | None = None
|
self._intent: AppIntent | None = None
|
||||||
self._mode: AppMode | None = None
|
self._mode: AppMode | None = None
|
||||||
|
self._mode_selector: babase.AppModeSelector | None = None
|
||||||
self._shutdown_task: asyncio.Task[None] | None = None
|
self._shutdown_task: asyncio.Task[None] | None = None
|
||||||
self._shutdown_tasks: list[Coroutine[None, None, None]] = [
|
self._shutdown_tasks: list[Coroutine[None, None, None]] = [
|
||||||
self._wait_for_shutdown_suppressions()
|
self._wait_for_shutdown_suppressions()
|
||||||
@ -201,6 +198,7 @@ class App:
|
|||||||
def postinit(self) -> None:
|
def postinit(self) -> None:
|
||||||
"""Called after we've been inited and assigned to babase.app."""
|
"""Called after we've been inited and assigned to babase.app."""
|
||||||
|
|
||||||
|
# Hack for docs-generation.
|
||||||
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -231,6 +229,31 @@ class App:
|
|||||||
assert self._config is not None
|
assert self._config is not None
|
||||||
return self._config
|
return self._config
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode_selector(self) -> babase.AppModeSelector:
|
||||||
|
"""Controls which app-modes are used for handling given intents.
|
||||||
|
|
||||||
|
Plugins can override this to change high level app behavior and
|
||||||
|
spinoff projects can change the default implementation for the
|
||||||
|
same effect.
|
||||||
|
"""
|
||||||
|
if self._mode_selector is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
'mode_selector cannot be used until the app reaches'
|
||||||
|
' the running state.'
|
||||||
|
)
|
||||||
|
return self._mode_selector
|
||||||
|
|
||||||
|
@mode_selector.setter
|
||||||
|
def mode_selector(self, selector: babase.AppModeSelector) -> None:
|
||||||
|
# Don't allow overriding this until after we've initially set it.
|
||||||
|
if self._mode_selector is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
'mode_selector cannot be used until the app reaches'
|
||||||
|
' the running state.'
|
||||||
|
)
|
||||||
|
self._mode_selector = selector
|
||||||
|
|
||||||
# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__
|
# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__
|
||||||
# This section generated by batools.appmodule; do not edit.
|
# This section generated by batools.appmodule; do not edit.
|
||||||
|
|
||||||
@ -303,8 +326,8 @@ class App:
|
|||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
"""Run the app to completion.
|
"""Run the app to completion.
|
||||||
|
|
||||||
Note that this only works on platforms where Ballistica
|
Note that this only works on builds where Ballistica manages
|
||||||
manages its own event loop.
|
its own event loop.
|
||||||
"""
|
"""
|
||||||
_babase.run_app()
|
_babase.run_app()
|
||||||
|
|
||||||
@ -423,7 +446,7 @@ class App:
|
|||||||
self._update_state()
|
self._update_state()
|
||||||
|
|
||||||
def _set_intent(self, intent: AppIntent) -> None:
|
def _set_intent(self, intent: AppIntent) -> None:
|
||||||
# This should be running in a bg thread.
|
# This should be happening in a bg thread.
|
||||||
assert not _babase.in_logic_thread()
|
assert not _babase.in_logic_thread()
|
||||||
try:
|
try:
|
||||||
# Ask the selector what app-mode to use for this intent.
|
# Ask the selector what app-mode to use for this intent.
|
||||||
@ -431,15 +454,27 @@ class App:
|
|||||||
raise RuntimeError('No AppModeSelector set.')
|
raise RuntimeError('No AppModeSelector set.')
|
||||||
modetype = self.mode_selector.app_mode_for_intent(intent)
|
modetype = self.mode_selector.app_mode_for_intent(intent)
|
||||||
|
|
||||||
# Make sure the app-mode they return *actually* supports the
|
# NOTE: Since intents are somewhat high level things, should
|
||||||
# intent.
|
# we do some universal thing like a screenmessage saying
|
||||||
if not modetype.supports_intent(intent):
|
# 'The app cannot handle that request' on failure?
|
||||||
|
|
||||||
|
if modetype is None:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f'Intent {intent} is not supported by AppMode class'
|
f'No app-mode found to handle app-intent'
|
||||||
f' {modetype}'
|
f' type {type(intent)}.'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Kick back to the logic thread to apply.
|
# Make sure the app-mode the selector gave us *actually*
|
||||||
|
# supports the intent.
|
||||||
|
if not modetype.can_handle_intent(intent):
|
||||||
|
raise RuntimeError(
|
||||||
|
f'Intent {intent} cannot be handled by AppMode type'
|
||||||
|
f' {modetype} (selector {self.mode_selector}'
|
||||||
|
f' incorrectly thinks that it can be).'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ok; seems legit. Now instantiate the mode if necessary and
|
||||||
|
# kick back to the logic thread to apply.
|
||||||
mode = modetype()
|
mode = modetype()
|
||||||
_babase.pushcall(
|
_babase.pushcall(
|
||||||
tpartial(self._apply_intent, intent, mode),
|
tpartial(self._apply_intent, intent, mode),
|
||||||
@ -480,6 +515,9 @@ class App:
|
|||||||
# Hmm; what should we do in this case?...
|
# Hmm; what should we do in this case?...
|
||||||
logging.exception('Error activating app-mode %s.', mode)
|
logging.exception('Error activating app-mode %s.', mode)
|
||||||
|
|
||||||
|
# Let the world know when we first have an app-mode; certain
|
||||||
|
# app stuff such as input processing can proceed at that
|
||||||
|
# point.
|
||||||
if is_initial_mode:
|
if is_initial_mode:
|
||||||
_babase.on_initial_app_mode_set()
|
_babase.on_initial_app_mode_set()
|
||||||
|
|
||||||
@ -599,7 +637,7 @@ class App:
|
|||||||
|
|
||||||
# Set a default app-mode-selector. Plugins can then override
|
# Set a default app-mode-selector. Plugins can then override
|
||||||
# this if they want in the on_app_running callback below.
|
# this if they want in the on_app_running callback below.
|
||||||
self.mode_selector = self.DefaultAppModeSelector()
|
self._mode_selector = self.DefaultAppModeSelector()
|
||||||
|
|
||||||
# Inform all app subsystems in the same order they were
|
# Inform all app subsystems in the same order they were
|
||||||
# registered. Operate on a copy here because subsystems can
|
# registered. Operate on a copy here because subsystems can
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
"""Provides the AppConfig class."""
|
"""Provides the AppConfig class."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _babase
|
import _babase
|
||||||
@ -120,33 +121,24 @@ def read_app_config() -> tuple[AppConfig, bool]:
|
|||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
config_file_healthy = True
|
config_file_healthy = True
|
||||||
|
|
||||||
except Exception as exc:
|
except Exception:
|
||||||
print(
|
logging.exception(
|
||||||
(
|
"Error reading config file at time %.3f: '%s'.",
|
||||||
'error reading config file at time '
|
_babase.apptime(),
|
||||||
+ str(_babase.apptime())
|
config_file_path,
|
||||||
+ ': \''
|
|
||||||
+ config_file_path
|
|
||||||
+ '\':\n'
|
|
||||||
),
|
|
||||||
exc,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Whenever this happens lets back up the broken one just in case it
|
# Whenever this happens lets back up the broken one just in case it
|
||||||
# gets overwritten accidentally.
|
# gets overwritten accidentally.
|
||||||
print(
|
logging.info(
|
||||||
(
|
"Backing up current config file to '%s.broken'", config_file_path
|
||||||
'backing up current config file to \''
|
|
||||||
+ config_file_path
|
|
||||||
+ ".broken\'"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
shutil.copyfile(config_file_path, config_file_path + '.broken')
|
shutil.copyfile(config_file_path, config_file_path + '.broken')
|
||||||
except Exception as exc2:
|
except Exception:
|
||||||
print('EXC copying broken config:', exc2)
|
logging.exception('Error copying broken config.')
|
||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
|
|
||||||
# Now attempt to read one of our 'prev' backup copies.
|
# Now attempt to read one of our 'prev' backup copies.
|
||||||
@ -159,9 +151,9 @@ def read_app_config() -> tuple[AppConfig, bool]:
|
|||||||
else:
|
else:
|
||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
config_file_healthy = True
|
config_file_healthy = True
|
||||||
print('successfully read backup config.')
|
logging.info('Successfully read backup config.')
|
||||||
except Exception as exc2:
|
except Exception:
|
||||||
print('EXC reading prev backup config:', exc2)
|
logging.exception('Error reading prev backup config.')
|
||||||
return config, config_file_healthy
|
return config, config_file_healthy
|
||||||
|
|
||||||
|
|
||||||
@ -176,7 +168,7 @@ def commit_app_config(force: bool = False) -> None:
|
|||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
if not _babase.app.config_file_healthy and not force:
|
if not _babase.app.config_file_healthy and not force:
|
||||||
print(
|
logging.warning(
|
||||||
'Current config file is broken; '
|
'Current config file is broken; '
|
||||||
'skipping write to avoid losing settings.'
|
'skipping write to avoid losing settings.'
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from bacommon.app import AppExperience
|
||||||
from babase._appintent import AppIntent
|
from babase._appintent import AppIntent
|
||||||
|
|
||||||
|
|
||||||
@ -17,16 +18,33 @@ class AppMode:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_intent(cls, intent: AppIntent) -> bool:
|
def get_app_experience(cls) -> AppExperience:
|
||||||
"""Return whether our mode can handle the provided intent."""
|
"""Return the overall experience provided by this mode."""
|
||||||
del intent
|
raise NotImplementedError('AppMode subclasses must override this.')
|
||||||
|
|
||||||
# Say no to everything by default. Let's make mode explicitly
|
@classmethod
|
||||||
# lay out everything they *do* support.
|
def can_handle_intent(cls, intent: AppIntent) -> bool:
|
||||||
return False
|
"""Return whether this mode can handle the provided intent.
|
||||||
|
|
||||||
|
For this to return True, the AppMode must claim to support the
|
||||||
|
provided intent (via its _supports_intent() method) AND the
|
||||||
|
AppExperience associated with the AppMode must be supported by
|
||||||
|
the current app and runtime environment.
|
||||||
|
"""
|
||||||
|
return cls._supports_intent(intent)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _supports_intent(cls, intent: AppIntent) -> bool:
|
||||||
|
"""Return whether our mode can handle the provided intent.
|
||||||
|
|
||||||
|
AppModes should override this to define what they can handle.
|
||||||
|
Note that AppExperience does not have to be considered here; that
|
||||||
|
is handled automatically by the can_handle_intent() call."""
|
||||||
|
raise NotImplementedError('AppMode subclasses must override this.')
|
||||||
|
|
||||||
def handle_intent(self, intent: AppIntent) -> None:
|
def handle_intent(self, intent: AppIntent) -> None:
|
||||||
"""Handle an intent."""
|
"""Handle an intent."""
|
||||||
|
raise NotImplementedError('AppMode subclasses must override this.')
|
||||||
|
|
||||||
def on_activate(self) -> None:
|
def on_activate(self) -> None:
|
||||||
"""Called when the mode is being activated."""
|
"""Called when the mode is being activated."""
|
||||||
|
|||||||
@ -18,15 +18,15 @@ class AppModeSelector:
|
|||||||
The app calls an instance of this class when passed an AppIntent to
|
The app calls an instance of this class when passed an AppIntent to
|
||||||
determine which AppMode to use to handle the intent. Plugins or
|
determine which AppMode to use to handle the intent. Plugins or
|
||||||
spinoff projects can modify high level app behavior by replacing or
|
spinoff projects can modify high level app behavior by replacing or
|
||||||
modifying this.
|
modifying the app's mode-selector.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def app_mode_for_intent(self, intent: AppIntent) -> type[AppMode]:
|
def app_mode_for_intent(self, intent: AppIntent) -> type[AppMode] | None:
|
||||||
"""Given an AppIntent, return the AppMode that should handle it.
|
"""Given an AppIntent, return the AppMode that should handle it.
|
||||||
|
|
||||||
If None is returned, the AppIntent will be ignored.
|
If None is returned, the AppIntent will be ignored.
|
||||||
|
|
||||||
This is called in a background thread, so avoid any calls
|
This may be called in a background thread, so avoid any calls
|
||||||
limited to logic thread use/etc.
|
limited to logic thread use/etc.
|
||||||
"""
|
"""
|
||||||
raise RuntimeError('app_mode_for_intent() should be overridden.')
|
raise NotImplementedError('app_mode_for_intent() should be overridden.')
|
||||||
|
|||||||
@ -5,6 +5,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from bacommon.app import AppExperience
|
||||||
|
|
||||||
import _babase
|
import _babase
|
||||||
from babase._appmode import AppMode
|
from babase._appmode import AppMode
|
||||||
from babase._appintent import AppIntentExec, AppIntentDefault
|
from babase._appintent import AppIntentExec, AppIntentDefault
|
||||||
@ -17,7 +19,11 @@ class EmptyAppMode(AppMode):
|
|||||||
"""An empty app mode that can be used as a fallback/etc."""
|
"""An empty app mode that can be used as a fallback/etc."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_intent(cls, intent: AppIntent) -> bool:
|
def get_app_experience(cls) -> AppExperience:
|
||||||
|
return AppExperience.EMPTY
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _supports_intent(cls, intent: AppIntent) -> bool:
|
||||||
# We support default and exec intents currently.
|
# We support default and exec intents currently.
|
||||||
return isinstance(intent, AppIntentExec | AppIntentDefault)
|
return isinstance(intent, AppIntentExec | AppIntentDefault)
|
||||||
|
|
||||||
@ -30,8 +36,8 @@ class EmptyAppMode(AppMode):
|
|||||||
|
|
||||||
def on_activate(self) -> None:
|
def on_activate(self) -> None:
|
||||||
# Let the native layer do its thing.
|
# Let the native layer do its thing.
|
||||||
_babase.empty_app_mode_activate()
|
_babase.on_empty_app_mode_activate()
|
||||||
|
|
||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
# Let the native layer do its thing.
|
# Let the native layer do its thing.
|
||||||
_babase.empty_app_mode_deactivate()
|
_babase.on_empty_app_mode_deactivate()
|
||||||
|
|||||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
# Build number and version of the ballistica binary we expect to be
|
# Build number and version of the ballistica binary we expect to be
|
||||||
# using.
|
# using.
|
||||||
TARGET_BALLISTICA_BUILD = 21299
|
TARGET_BALLISTICA_BUILD = 21303
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.28'
|
TARGET_BALLISTICA_VERSION = '1.7.28'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,9 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from bacommon.app import AppExperience
|
||||||
from babase import AppMode, AppIntentExec, AppIntentDefault
|
from babase import AppMode, AppIntentExec, AppIntentDefault
|
||||||
|
|
||||||
import _bascenev1
|
import _bascenev1
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -16,7 +18,11 @@ class SceneV1AppMode(AppMode):
|
|||||||
"""Our app-mode."""
|
"""Our app-mode."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_intent(cls, intent: AppIntent) -> bool:
|
def get_app_experience(cls) -> AppExperience:
|
||||||
|
return AppExperience.MELEE
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _supports_intent(cls, intent: AppIntent) -> bool:
|
||||||
# We support default and exec intents currently.
|
# We support default and exec intents currently.
|
||||||
return isinstance(intent, AppIntentExec | AppIntentDefault)
|
return isinstance(intent, AppIntentExec | AppIntentDefault)
|
||||||
|
|
||||||
@ -29,8 +35,8 @@ class SceneV1AppMode(AppMode):
|
|||||||
|
|
||||||
def on_activate(self) -> None:
|
def on_activate(self) -> None:
|
||||||
# Let the native layer do its thing.
|
# Let the native layer do its thing.
|
||||||
_bascenev1.app_mode_activate()
|
_bascenev1.on_app_mode_activate()
|
||||||
|
|
||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
# Let the native layer do its thing.
|
# Let the native layer do its thing.
|
||||||
_bascenev1.app_mode_deactivate()
|
_bascenev1.on_app_mode_deactivate()
|
||||||
|
|||||||
@ -371,5 +371,5 @@ def register_map(maptype: type[Map]) -> None:
|
|||||||
"""Register a map class with the game."""
|
"""Register a map class with the game."""
|
||||||
assert babase.app.classic is not None
|
assert babase.app.classic is not None
|
||||||
if maptype.name in babase.app.classic.maps:
|
if maptype.name in babase.app.classic.maps:
|
||||||
raise RuntimeError('map "' + maptype.name + '" already registered')
|
raise RuntimeError(f'Map "{maptype.name}" is already registered.')
|
||||||
babase.app.classic.maps[maptype.name] = maptype
|
babase.app.classic.maps[maptype.name] = maptype
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
# Released under the MIT License. See LICENSE for details.
|
# Released under the MIT License. See LICENSE for details.
|
||||||
#
|
#
|
||||||
"""Snippets of code for use by the c++ layer."""
|
"""Snippets of code for use by the native layer."""
|
||||||
|
|
||||||
# (most of these are self-explanatory)
|
|
||||||
# pylint: disable=missing-function-docstring
|
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
def hello_world() -> None:
|
def hello_world() -> None:
|
||||||
|
"""The usual example."""
|
||||||
print('HELLO WORLD FROM TemplateFs!')
|
print('HELLO WORLD FROM TemplateFs!')
|
||||||
|
|||||||
@ -991,12 +991,13 @@ void Graphics::ClearFrameDefDeleteList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::FadeScreen(bool to, millisecs_t time, PyObject* endcall) {
|
void Graphics::FadeScreen(bool to, millisecs_t time, PyObject* endcall) {
|
||||||
|
BA_PRECONDITION(g_base->InLogicThread());
|
||||||
// If there's an ourstanding fade-end command, go ahead and run it.
|
// If there's an ourstanding fade-end command, go ahead and run it.
|
||||||
// (otherwise, overlapping fades can cause things to get lost)
|
// (otherwise, overlapping fades can cause things to get lost)
|
||||||
if (fade_end_call_.Exists()) {
|
if (fade_end_call_.Exists()) {
|
||||||
if (g_buildconfig.debug_build()) {
|
if (g_buildconfig.debug_build()) {
|
||||||
Log(LogLevel::kWarning,
|
Log(LogLevel::kWarning,
|
||||||
"2 fades overlapping; running first fade-end-call early");
|
"2 fades overlapping; running first fade-end-call early.");
|
||||||
}
|
}
|
||||||
fade_end_call_->Schedule();
|
fade_end_call_->Schedule();
|
||||||
fade_end_call_.Clear();
|
fade_end_call_.Clear();
|
||||||
@ -1089,7 +1090,7 @@ void Graphics::ApplyCamera(FrameDef* frame_def) {
|
|||||||
void Graphics::DrawWorld(FrameDef* frame_def) {
|
void Graphics::DrawWorld(FrameDef* frame_def) {
|
||||||
assert(!g_core->HeadlessMode());
|
assert(!g_core->HeadlessMode());
|
||||||
|
|
||||||
// Draw all session contents (nodes, etc.)
|
// Draw the world.
|
||||||
overlay_node_z_depth_ = -0.95f;
|
overlay_node_z_depth_ = -0.95f;
|
||||||
g_base->app_mode()->DrawWorld(frame_def);
|
g_base->app_mode()->DrawWorld(frame_def);
|
||||||
g_base->bg_dynamics->Draw(frame_def);
|
g_base->bg_dynamics->Draw(frame_def);
|
||||||
@ -1120,9 +1121,6 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
// layer is fully bootstrapped.
|
// layer is fully bootstrapped.
|
||||||
BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete());
|
BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete());
|
||||||
|
|
||||||
// This should no longer be necessary..
|
|
||||||
WaitForRendererToExist();
|
|
||||||
|
|
||||||
millisecs_t app_time_millisecs = g_core->GetAppTimeMillisecs();
|
millisecs_t app_time_millisecs = g_core->GetAppTimeMillisecs();
|
||||||
|
|
||||||
// Store how much time this frame_def represents.
|
// Store how much time this frame_def represents.
|
||||||
@ -1132,8 +1130,9 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
millisecs_t{50}, display_time_millisecs - last_create_frame_def_time_);
|
millisecs_t{50}, display_time_millisecs - last_create_frame_def_time_);
|
||||||
last_create_frame_def_time_ = display_time_millisecs;
|
last_create_frame_def_time_ = display_time_millisecs;
|
||||||
|
|
||||||
// This probably should not be here. Though I guess we get the most up-to-date
|
// This probably should not be here. Though I guess we get the most
|
||||||
// values possible this way. But it should probably live in g_input.
|
// up-to-date values possible this way. But it should probably live in
|
||||||
|
// g_input.
|
||||||
UpdateGyro(app_time_millisecs, elapsed);
|
UpdateGyro(app_time_millisecs, elapsed);
|
||||||
|
|
||||||
FrameDef* frame_def = GetEmptyFrameDef();
|
FrameDef* frame_def = GetEmptyFrameDef();
|
||||||
@ -1184,9 +1183,9 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
// Draw our light/shadow images to the screen if desired.
|
// Draw our light/shadow images to the screen if desired.
|
||||||
DrawDebugBuffers(overlay_pass);
|
DrawDebugBuffers(overlay_pass);
|
||||||
|
|
||||||
// In high-quality modes we draw a screen-quad as a catch-all for blitting
|
// In high-quality modes we draw a screen-quad as a catch-all for
|
||||||
// the world buffer to the screen (other nodes can add their own blitters
|
// blitting the world buffer to the screen (other nodes can add their
|
||||||
// such as distortion shapes which will have priority).
|
// own blitters such as distortion shapes which will have priority).
|
||||||
if (frame_def->quality() >= GraphicsQuality::kHigh) {
|
if (frame_def->quality() >= GraphicsQuality::kHigh) {
|
||||||
PostProcessComponent c(frame_def->blit_pass());
|
PostProcessComponent c(frame_def->blit_pass());
|
||||||
c.DrawScreenQuad();
|
c.DrawScreenQuad();
|
||||||
@ -1195,8 +1194,8 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
|
|
||||||
DrawFades(frame_def, app_time_millisecs);
|
DrawFades(frame_def, app_time_millisecs);
|
||||||
|
|
||||||
// Sanity test: If we're in VR, the only reason we should have stuff in the
|
// Sanity test: If we're in VR, the only reason we should have stuff in
|
||||||
// flat overlay pass is if there's windows present (we want to avoid
|
// the flat overlay pass is if there's windows present (we want to avoid
|
||||||
// drawing/blitting the 2d UI buffer during gameplay for efficiency).
|
// drawing/blitting the 2d UI buffer during gameplay for efficiency).
|
||||||
if (g_core->IsVRMode()) {
|
if (g_core->IsVRMode()) {
|
||||||
if (frame_def->GetOverlayFlatPass()->HasDrawCommands()) {
|
if (frame_def->GetOverlayFlatPass()->HasDrawCommands()) {
|
||||||
@ -1219,9 +1218,9 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
|
|
||||||
frame_def->Finalize();
|
frame_def->Finalize();
|
||||||
|
|
||||||
// Include all mesh-data loads and unloads that have accumulated up to this
|
// Include all mesh-data loads and unloads that have accumulated up to
|
||||||
// point the graphics thread will have to handle these before rendering the
|
// this point the graphics thread will have to handle these before
|
||||||
// frame_def.
|
// rendering the frame_def.
|
||||||
frame_def->set_mesh_data_creates(mesh_data_creates_);
|
frame_def->set_mesh_data_creates(mesh_data_creates_);
|
||||||
mesh_data_creates_.clear();
|
mesh_data_creates_.clear();
|
||||||
frame_def->set_mesh_data_destroys(mesh_data_destroys_);
|
frame_def->set_mesh_data_destroys(mesh_data_destroys_);
|
||||||
@ -1327,7 +1326,7 @@ void Graphics::UpdateAndDrawProgressBar(FrameDef* frame_def,
|
|||||||
/ static_cast<float>(progress_bar_loads_));
|
/ static_cast<float>(progress_bar_loads_));
|
||||||
DrawProgressBar(pass, 1.0f);
|
DrawProgressBar(pass, 1.0f);
|
||||||
|
|
||||||
// If we were drawing a progress bar, see if everything is now loaded.. if
|
// If we were drawing a progress bar, see if everything is now loaded. If
|
||||||
// so, start rendering normally next frame.
|
// so, start rendering normally next frame.
|
||||||
int count = g_base->assets->GetGraphicalPendingLoadCount();
|
int count = g_base->assets->GetGraphicalPendingLoadCount();
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
@ -1570,8 +1569,8 @@ void Graphics::AddMeshDataCreate(MeshData* d) {
|
|||||||
assert(g_base->graphics);
|
assert(g_base->graphics);
|
||||||
|
|
||||||
// Add this to our list of new-mesh-datas. We'll include this with our
|
// Add this to our list of new-mesh-datas. We'll include this with our
|
||||||
// next frame_def to have the graphics thread load before it processes
|
// next frame_def to have the graphics thread load before it processes the
|
||||||
// the frame_def.
|
// frame_def.
|
||||||
mesh_data_creates_.push_back(d);
|
mesh_data_creates_.push_back(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1580,8 +1579,8 @@ void Graphics::AddMeshDataDestroy(MeshData* d) {
|
|||||||
assert(g_base->graphics);
|
assert(g_base->graphics);
|
||||||
|
|
||||||
// Add this to our list of delete-mesh-datas; we'll include this with our
|
// Add this to our list of delete-mesh-datas; we'll include this with our
|
||||||
// next frame_def to have the graphics thread kill before it processes
|
// next frame_def to have the graphics thread kill before it processes the
|
||||||
// the frame_def.
|
// frame_def.
|
||||||
mesh_data_destroys_.push_back(d);
|
mesh_data_destroys_.push_back(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1635,24 +1634,6 @@ void Graphics::ToggleDebugDraw() {
|
|||||||
|
|
||||||
void Graphics::ReleaseFadeEndCommand() { fade_end_call_.Clear(); }
|
void Graphics::ReleaseFadeEndCommand() { fade_end_call_.Clear(); }
|
||||||
|
|
||||||
void Graphics::WaitForRendererToExist() {
|
|
||||||
// Conceivably we could hit this point before our graphics thread has created
|
|
||||||
// the renderer. In that case lets wait a moment.
|
|
||||||
int sleep_count = 0;
|
|
||||||
while (g_base->graphics_server == nullptr
|
|
||||||
|| g_base->graphics_server->renderer() == nullptr) {
|
|
||||||
BA_LOG_ONCE(
|
|
||||||
LogLevel::kWarning,
|
|
||||||
"BuildAndPushFrameDef() called before renderer is up; spinning...");
|
|
||||||
core::CorePlatform::SleepMillisecs(100);
|
|
||||||
sleep_count++;
|
|
||||||
if (sleep_count > 100) {
|
|
||||||
throw Exception(
|
|
||||||
"Aborting waiting for renderer to come up in BuildAndPushFrameDef()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Graphics::ValueTest(const std::string& arg, double* absval,
|
auto Graphics::ValueTest(const std::string& arg, double* absval,
|
||||||
double* deltaval, double* outval) -> bool {
|
double* deltaval, double* outval) -> bool {
|
||||||
return false;
|
return false;
|
||||||
@ -1737,20 +1718,17 @@ void Graphics::DoDrawBlotch(std::vector<uint16_t>* indices,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::DrawRadialMeter(MeshIndexedSimpleFull* m, float amt) {
|
void Graphics::DrawRadialMeter(MeshIndexedSimpleFull* m, float amt) {
|
||||||
// FIXME - we're updating this every frame so we should use pure dynamic data;
|
// FIXME - we're updating this every frame so we should use pure dynamic
|
||||||
// not a mix of static and dynamic.
|
// data; not a mix of static and dynamic.
|
||||||
|
|
||||||
if (amt >= 0.999f) {
|
if (amt >= 0.999f) {
|
||||||
// clang-format off
|
|
||||||
uint16_t indices[] = {0, 1, 2, 1, 3, 2};
|
uint16_t indices[] = {0, 1, 2, 1, 3, 2};
|
||||||
VertexSimpleFull vertices[] = {
|
VertexSimpleFull vertices[] = {
|
||||||
{-1, -1, 0, 0, 65535},
|
{-1, -1, 0, 0, 65535},
|
||||||
{1, -1, 0, 65535, 65535},
|
{1, -1, 0, 65535, 65535},
|
||||||
{-1, 1, 0, 0, 0},
|
{-1, 1, 0, 0, 0},
|
||||||
{1, 1, 0, 65535, 0,
|
{1, 1, 0, 65535, 0},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
||||||
m->SetIndexData(Object::New<MeshIndexBuffer16>(6, indices));
|
m->SetIndexData(Object::New<MeshIndexBuffer16>(6, indices));
|
||||||
m->SetData(Object::New<MeshBuffer<VertexSimpleFull>>(4, vertices));
|
m->SetData(Object::New<MeshBuffer<VertexSimpleFull>>(4, vertices));
|
||||||
|
|
||||||
|
|||||||
@ -322,7 +322,6 @@ class Graphics {
|
|||||||
void DrawCursor(RenderPass* pass, millisecs_t real_time);
|
void DrawCursor(RenderPass* pass, millisecs_t real_time);
|
||||||
void DrawFades(FrameDef* frame_def, millisecs_t real_time);
|
void DrawFades(FrameDef* frame_def, millisecs_t real_time);
|
||||||
void DrawDebugBuffers(RenderPass* pass);
|
void DrawDebugBuffers(RenderPass* pass);
|
||||||
void WaitForRendererToExist();
|
|
||||||
|
|
||||||
void UpdateAndDrawProgressBar(FrameDef* frame_def, millisecs_t real_time);
|
void UpdateAndDrawProgressBar(FrameDef* frame_def, millisecs_t real_time);
|
||||||
void DoDrawBlotch(std::vector<uint16_t>* indices,
|
void DoDrawBlotch(std::vector<uint16_t>* indices,
|
||||||
@ -344,7 +343,7 @@ class Graphics {
|
|||||||
std::vector<MeshData*> mesh_data_creates_;
|
std::vector<MeshData*> mesh_data_creates_;
|
||||||
std::vector<MeshData*> mesh_data_destroys_;
|
std::vector<MeshData*> mesh_data_destroys_;
|
||||||
bool has_supports_high_quality_graphics_value_{};
|
bool has_supports_high_quality_graphics_value_{};
|
||||||
bool supports_high_quality_graphics_ = false;
|
bool supports_high_quality_graphics_{};
|
||||||
millisecs_t last_create_frame_def_time_{};
|
millisecs_t last_create_frame_def_time_{};
|
||||||
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
||||||
Vector2f shadow_scale_{1.0f, 1.0f};
|
Vector2f shadow_scale_{1.0f, 1.0f};
|
||||||
|
|||||||
@ -1370,9 +1370,9 @@ static PyMethodDef PyUserAgentStringDef = {
|
|||||||
"(internal)\n",
|
"(internal)\n",
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------- empty_app_mode_activate -----------------------------
|
// --------------------- on_empty_app_mode_activate ----------------------------
|
||||||
|
|
||||||
static auto PyEmptyAppModeActivate(PyObject* self) -> PyObject* {
|
static auto PyOnEmptyAppModeActivate(PyObject* self) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
BA_PRECONDITION(g_base->InLogicThread());
|
BA_PRECONDITION(g_base->InLogicThread());
|
||||||
g_base->set_app_mode(AppModeEmpty::GetSingleton());
|
g_base->set_app_mode(AppModeEmpty::GetSingleton());
|
||||||
@ -1382,19 +1382,19 @@ static auto PyEmptyAppModeActivate(PyObject* self) -> PyObject* {
|
|||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef PyEmptyAppModeActivateDef = {
|
static PyMethodDef PyOnEmptyAppModeActivateDef = {
|
||||||
"empty_app_mode_activate", // name
|
"on_empty_app_mode_activate", // name
|
||||||
(PyCFunction)PyEmptyAppModeActivate, // method
|
(PyCFunction)PyOnEmptyAppModeActivate, // method
|
||||||
METH_NOARGS, // flags
|
METH_NOARGS, // flags
|
||||||
|
|
||||||
"empty_app_mode_activate() -> None\n"
|
"on_empty_app_mode_activate() -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)\n",
|
"(internal)\n",
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------- empty_app_mode_deactivate ---------------------------
|
// --------------------- on_empty_app_mode_deactivate --------------------------
|
||||||
|
|
||||||
static auto PyEmptyAppModeDeactivate(PyObject* self) -> PyObject* {
|
static auto PyOnEmptyAppModeDeactivate(PyObject* self) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
BA_PRECONDITION(g_base->InLogicThread());
|
BA_PRECONDITION(g_base->InLogicThread());
|
||||||
// Currently doing nothing.
|
// Currently doing nothing.
|
||||||
@ -1402,12 +1402,12 @@ static auto PyEmptyAppModeDeactivate(PyObject* self) -> PyObject* {
|
|||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef PyEmptyAppModeDeactivateDef = {
|
static PyMethodDef PyOnEmptyAppModeDeactivateDef = {
|
||||||
"empty_app_mode_deactivate", // name
|
"on_empty_app_mode_deactivate", // name
|
||||||
(PyCFunction)PyEmptyAppModeDeactivate, // method
|
(PyCFunction)PyOnEmptyAppModeDeactivate, // method
|
||||||
METH_NOARGS, // flags
|
METH_NOARGS, // flags
|
||||||
|
|
||||||
"empty_app_mode_deactivate() -> None\n"
|
"on_empty_app_mode_deactivate() -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)\n",
|
"(internal)\n",
|
||||||
};
|
};
|
||||||
@ -1598,8 +1598,8 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
|
|||||||
PyOnInitialAppModeSetDef,
|
PyOnInitialAppModeSetDef,
|
||||||
PyReachedEndOfBaBaseDef,
|
PyReachedEndOfBaBaseDef,
|
||||||
PyUserAgentStringDef,
|
PyUserAgentStringDef,
|
||||||
PyEmptyAppModeActivateDef,
|
PyOnEmptyAppModeActivateDef,
|
||||||
PyEmptyAppModeDeactivateDef,
|
PyOnEmptyAppModeDeactivateDef,
|
||||||
PyEmptyAppModeHandleIntentDefaultDef,
|
PyEmptyAppModeHandleIntentDefaultDef,
|
||||||
PyEmptyAppModeHandleIntentExecDef,
|
PyEmptyAppModeHandleIntentExecDef,
|
||||||
PyGetImmediateReturnCodeDef,
|
PyGetImmediateReturnCodeDef,
|
||||||
|
|||||||
@ -525,8 +525,7 @@ static auto PyFadeScreen(PyObject* self, PyObject* args, PyObject* keywds)
|
|||||||
-> PyObject* {
|
-> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
|
|
||||||
// This can only be called in the UI context.
|
int fade{};
|
||||||
int fade{0};
|
|
||||||
float time{0.25f};
|
float time{0.25f};
|
||||||
PyObject* endcall = nullptr;
|
PyObject* endcall = nullptr;
|
||||||
static const char* kwlist[] = {"to", "time", "endcall", nullptr};
|
static const char* kwlist[] = {"to", "time", "endcall", nullptr};
|
||||||
|
|||||||
@ -1614,9 +1614,9 @@ static PyMethodDef PySetInternalMusicDef = {
|
|||||||
"(internal).",
|
"(internal).",
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------- app_mode_activate -------------------------------
|
// -------------------------- on_app_mode_activate -----------------------------
|
||||||
|
|
||||||
static auto PyAppModeActivate(PyObject* self) -> PyObject* {
|
static auto PyOnAppModeActivate(PyObject* self) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
BA_PRECONDITION(g_base->InLogicThread());
|
BA_PRECONDITION(g_base->InLogicThread());
|
||||||
g_base->set_app_mode(SceneV1AppMode::GetSingleton());
|
g_base->set_app_mode(SceneV1AppMode::GetSingleton());
|
||||||
@ -1624,19 +1624,19 @@ static auto PyAppModeActivate(PyObject* self) -> PyObject* {
|
|||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef PyAppModeActivateDef = {
|
static PyMethodDef PyOnAppModeActivateDef = {
|
||||||
"app_mode_activate", // name
|
"on_app_mode_activate", // name
|
||||||
(PyCFunction)PyAppModeActivate, // method
|
(PyCFunction)PyOnAppModeActivate, // method
|
||||||
METH_NOARGS, // flags
|
METH_NOARGS, // flags
|
||||||
|
|
||||||
"app_mode_activate() -> None\n"
|
"on_app_mode_activate() -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)\n",
|
"(internal)\n",
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------------- app_mode_deactivate ------------------------------
|
// ------------------------- on_app_mode_deactivate ----------------------------
|
||||||
|
|
||||||
static auto PyAppModeDeactivate(PyObject* self) -> PyObject* {
|
static auto PyOnAppModeDeactivate(PyObject* self) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
BA_PRECONDITION(g_base->InLogicThread());
|
BA_PRECONDITION(g_base->InLogicThread());
|
||||||
// Currently doing nothing.
|
// Currently doing nothing.
|
||||||
@ -1644,12 +1644,12 @@ static auto PyAppModeDeactivate(PyObject* self) -> PyObject* {
|
|||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef PyAppModeDeactivateDef = {
|
static PyMethodDef PyOnAppModeDeactivateDef = {
|
||||||
"app_mode_deactivate", // name
|
"on_app_mode_deactivate", // name
|
||||||
(PyCFunction)PyAppModeDeactivate, // method
|
(PyCFunction)PyOnAppModeDeactivate, // method
|
||||||
METH_NOARGS, // flags
|
METH_NOARGS, // flags
|
||||||
|
|
||||||
"app_mode_deactivate() -> None\n"
|
"on_app_mode_deactivate() -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)\n",
|
"(internal)\n",
|
||||||
};
|
};
|
||||||
@ -1771,8 +1771,8 @@ auto PythonMethodsScene::GetMethods() -> std::vector<PyMethodDef> {
|
|||||||
PyBaseTimeDef,
|
PyBaseTimeDef,
|
||||||
PyBaseTimerDef,
|
PyBaseTimerDef,
|
||||||
PyLsInputDevicesDef,
|
PyLsInputDevicesDef,
|
||||||
PyAppModeActivateDef,
|
PyOnAppModeActivateDef,
|
||||||
PyAppModeDeactivateDef,
|
PyOnAppModeDeactivateDef,
|
||||||
PyHandleAppIntentDefaultDef,
|
PyHandleAppIntentDefaultDef,
|
||||||
PyHandleAppIntentExecDef,
|
PyHandleAppIntentExecDef,
|
||||||
PyProtocolVersionDef,
|
PyProtocolVersionDef,
|
||||||
|
|||||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
|||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
// These are set automatically via script; don't modify them here.
|
// These are set automatically via script; don't modify them here.
|
||||||
const int kEngineBuildNumber = 21299;
|
const int kEngineBuildNumber = 21303;
|
||||||
const char* kEngineVersion = "1.7.28";
|
const char* kEngineVersion = "1.7.28";
|
||||||
const int kEngineApiVersion = 8;
|
const int kEngineApiVersion = 8;
|
||||||
|
|
||||||
|
|||||||
35
tools/bacommon/app.py
Normal file
35
tools/bacommon/app.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Common high level values/functionality related to apps."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AppExperience(Enum):
|
||||||
|
"""Overall experience that can be provided by a Ballistica app.
|
||||||
|
|
||||||
|
This corresponds generally, but not exactly, to distinct apps built
|
||||||
|
with Ballistica. However, a single app may support multiple experiences,
|
||||||
|
or there may be multiple apps targeting one experience. Cloud components
|
||||||
|
such as leagues are generally associated with an AppExperience.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# A special experience category that is supported everywhere. Used
|
||||||
|
# for the default empty AppMode when starting the app, etc.
|
||||||
|
EMPTY = 'empty'
|
||||||
|
|
||||||
|
# The traditional BombSquad experience: multiple players using
|
||||||
|
# controllers in a single arena small enough for all action to be
|
||||||
|
# viewed on a single screen.
|
||||||
|
MELEE = 'melee'
|
||||||
|
|
||||||
|
# The traditional BombSquad Remote experience; buttons on a
|
||||||
|
# touch-screen allowing a mobile device to be used as a game
|
||||||
|
# controller.
|
||||||
|
REMOTE = 'remote'
|
||||||
@ -166,12 +166,12 @@ def generate_app_module(
|
|||||||
|
|
||||||
if 'scene_v1' in fsets:
|
if 'scene_v1' in fsets:
|
||||||
contents += (
|
contents += (
|
||||||
'if bascenev1.SceneV1AppMode.supports_intent(intent):\n'
|
'if bascenev1.SceneV1AppMode.can_handle_intent(intent):\n'
|
||||||
' return bascenev1.SceneV1AppMode\n\n'
|
' return bascenev1.SceneV1AppMode\n\n'
|
||||||
)
|
)
|
||||||
if 'base' in fsets:
|
if 'base' in fsets:
|
||||||
contents += (
|
contents += (
|
||||||
'if babase.EmptyAppMode.supports_intent(intent):\n'
|
'if babase.EmptyAppMode.can_handle_intent(intent):\n'
|
||||||
' return babase.EmptyAppMode\n\n'
|
' return babase.EmptyAppMode\n\n'
|
||||||
)
|
)
|
||||||
contents += (
|
contents += (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user