mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-19 21:37:57 +08:00
getting make spinoff-test-base working
This commit is contained in:
parent
91cfa632c8
commit
4ae76a45f6
@ -4072,26 +4072,26 @@
|
||||
"build/assets/workspace/ninjafightplug.py": "https://files.ballistica.net/cache/ba1/c5/09/4f10b8a21ba87aa5509cff7a164b",
|
||||
"build/assets/workspace/onslaughtplug.py": "https://files.ballistica.net/cache/ba1/ff/0a/a354984f9c074dab0676ac7e4877",
|
||||
"build/assets/workspace/runaroundplug.py": "https://files.ballistica.net/cache/ba1/2a/1c/9ee5db6d1bceca7fa6638fb8abde",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/4f/46/80f41faa8a51075c2472d7429b77",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/30/cb/93ac10daaf9475d01f5d1064d358",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/34/4e/e2bf216edcd7d6a9a1bee3b55b69",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/5e/2b/c22b17ffa90f65bc906ae9e477d6",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/cf/ac/1485911ed48dac0c430b18687917",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/0d/99/2b9a15fa962b5ea354f8de27fe6c",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/03/e1/e795c72de227173711da1a162632",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/80/26/b82964ce5a5bb8509ca6d7516b71",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/2e/c8/67482dedb186c9dbca2dc66f7699",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/18/fa/c42a603705d7453279689706d2ee",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/bc/d2/89526b59dee86888c628028a406c",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/1d/e5/7425978a2c0112a46192a76563ce",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/ff/cd/21d36a06bbc2322d8e944f392ef0",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/97/ee/e2c3b4a6ee9abb170bd98f38c7de",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/be/13/229e4c027d0ca4b037dbf67134bd",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/53/bb/acf5f4b58a156c53e6ff8f0b58ad",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/f3/d7/426c5cd3ec71438a98474f39ba2c",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/90/79/74d6111711d655963a1e9a2728c5",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/c1/f7/95ff199637a86fe138309e3a5275",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/61/f0/9447fe7637ed96ce1840aa277271",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/b0/77/0fb608a5a11844433c94237b80fd",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/6b/37/9122b03565ee2d08d9fc6d30a221",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/a4/11/0f7c0fe6af5d5e46795f33b53f8e",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/59/f4/7e5d155abb264a76b633d6f4225f",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/dc/0a/131caf082f3877e5878ae349746d",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/fb/46/34eada1e570cce2107cb55a033e8",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/1d/3e/be779b3740cda2a7d98418d4007a",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/18/b7/4389f6000decbcde1044180b134a",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/4a/91/2c3bf6cca0baecc16138db7fe7ff",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/01/b4/31635bc46cbda94cc73fc019d28c",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/13/3d/50286e4d2fe1fc7507ba20b45ca2",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d7/17/7f186bd856ea7bd18b2fc8d64639",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/b9/63/640aa2e767450800ff481c51b665",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/19/ca/ae8153fb5fd0ea1045d386c31134",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/70/e8/796d18c51690f54efcb3df22c048",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/e2/8a/0ae529b92bcf4afe5d1c9c797e96",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/a3/d7/f415b115cd0e348be8aa75e28101",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/58/77/7244f67e35fcb0ab4047d5cc6f5e",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/91/de/bef5f0a5b9a0c6d50f4e2922a959",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/75/a5/42ad0f7c2944b1033e5b12395743",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/d4/6a/dd303a200b98a56ba3b100277057",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/fc/2c/2996c558fb408a548fdd37398c9a",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/ed/28/b7a72be7ae1bd2b58dda4b6902a0",
|
||||
@ -4108,14 +4108,14 @@
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/71/f6/691482915ad58ea1e953cc23d74c",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/b8/2b/6ec8c78980a62e3e0ee4b36ece04",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/4e/56/a95c987b2a371759896b037fea86",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/2d/55/0b7f8677e535082c9224259aa9d7",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/63/2f/b4b402d2f3a47dad74a077db036c",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/b6/e4/fffa1b46696ecc804b5a66896359",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/ca/70/e5eec4f437e387d61ceba7f9fffe",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/47/8c/0142dfbee4871619a8d404898eef",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/f8/d9/9facb83ac8c0ef39c97c3211ebd2",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/4d/90/79a005d72aa7a4277d06571dcdb5",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/ff/3a/e319ce586b9cb93ac29282569184",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/60/31/7c82d61f768515a6f5f8f20a967b",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/ba/38/d98a316972f47a5509be6ab28a96",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/a5/8d/8120340f79d9f9244013ef24c9da",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/84/47/90ccac6eb182c16a973855a160ee",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/5f/7b/ea3d74c27c2272084b459814986f",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/f6/a9/a780cd9b23e680a9f5cc87e5ac21",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/8c/9e/3902170e5e8662ec1fccc720ed48",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/c9/d4/5fa5dc68d04b906ef22a10eae5ae",
|
||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/52/c6/c11130af7b10d6c0321add5518fa",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/38/c3/1dedd5e74f2508efc5974c8815a1",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/d5/4a/0e480a855ce83709bd7f6761107d",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
### 1.7.20 (build 21041, api 8, 2023-06-02)
|
||||
### 1.7.20 (build 21042, api 8, 2023-06-02)
|
||||
|
||||
- This seems like a good time for a `refactoring` release in anticipation of
|
||||
changes coming in 1.8. Basically this means that a lot of things will be
|
||||
|
||||
@ -13,3 +13,5 @@ from batools.featureset import FeatureSet
|
||||
fset = FeatureSet.get_active()
|
||||
|
||||
fset.requirements = {'core'}
|
||||
|
||||
fset.soft_requirements = {'classic', 'plus'}
|
||||
|
||||
@ -13,3 +13,9 @@ from batools.featureset import FeatureSet
|
||||
fset = FeatureSet.get_active()
|
||||
|
||||
fset.requirements = {'base', 'scene_v1', 'ui_v1'}
|
||||
|
||||
# We provide 'babase.app.classic'.
|
||||
fset.has_python_app_subsystem = True
|
||||
|
||||
# We want things to work without us.
|
||||
fset.allow_as_soft_requirement = True
|
||||
|
||||
@ -14,3 +14,9 @@ fset = FeatureSet.get_active()
|
||||
|
||||
fset.requirements = {'base'}
|
||||
fset.internal = True
|
||||
|
||||
# We provide 'babase.app.plus'.
|
||||
fset.has_python_app_subsystem = True
|
||||
|
||||
# We want things to work without us.
|
||||
fset.allow_as_soft_requirement = True
|
||||
|
||||
@ -98,13 +98,27 @@ ctx.src_unchecked_paths = {
|
||||
'ballisticakit-android/BallisticaKit/src/*/assets',
|
||||
}
|
||||
|
||||
# Files at or under these paths are considered 'project' files.
|
||||
# Paths/names/suffixes we consider 'project' files.
|
||||
# These files are synced after all other files and go through
|
||||
# batools.project.Updater class as part of their filtering.
|
||||
# This allows them to update themselves in the same way as they
|
||||
# do when running 'make update' for the project; adding the final
|
||||
# filtered set of project source files to themself, etc.
|
||||
ctx.project_file_paths = set()
|
||||
ctx.project_file_paths = {'src/assets/ba_data/python/babase/_app.py'}
|
||||
ctx.project_file_names = {
|
||||
'Makefile',
|
||||
'CMakeLists.txt',
|
||||
'.meta_manifest_public.json',
|
||||
'.meta_manifest_private.json',
|
||||
'.asset_manifest_public.json',
|
||||
'.asset_manifest_private.json',
|
||||
}
|
||||
|
||||
ctx.project_file_suffixes = {
|
||||
'.vcxproj',
|
||||
'.vcxproj.filters',
|
||||
'.pbxproj',
|
||||
}
|
||||
|
||||
# Everything actually synced into dst will use the following filter rules:
|
||||
|
||||
|
||||
@ -33,12 +33,13 @@ if TYPE_CHECKING:
|
||||
from babase._appintent import AppIntent
|
||||
from babase._appmode import AppMode
|
||||
|
||||
# WOULD-AUTOGEN-BEGIN
|
||||
# __FEATURESET_APP_SUBSYSTEM_IMPORTS_BEGIN__
|
||||
# This section autogenerated by project-update.
|
||||
|
||||
from baclassic import ClassicSubsystem
|
||||
from baplus import PlusSubsystem
|
||||
|
||||
# WOULD-AUTOGEN-END
|
||||
# __FEATURESET_APP_SUBSYSTEM_IMPORTS_END__
|
||||
|
||||
|
||||
class App:
|
||||
@ -301,18 +302,6 @@ class App:
|
||||
# some of this stuff might try importing babase.app and that doesn't
|
||||
# exist yet as of our __init__() call.
|
||||
|
||||
# Init classic if present.
|
||||
# classic_subsystem_type: type[ClassicSubsystem] | None
|
||||
# try:
|
||||
# from baclassic import ClassicSubsystem
|
||||
|
||||
# classic_subsystem_type = ClassicSubsystem
|
||||
# except ImportError:
|
||||
# classic_subsystem_type = None
|
||||
|
||||
# if classic_subsystem_type is not None:
|
||||
# self._classic = classic_subsystem_type()
|
||||
|
||||
def _threadpool_no_wait_done(self, fut: Future) -> None:
|
||||
try:
|
||||
fut.result()
|
||||
@ -330,7 +319,8 @@ class App:
|
||||
fut = self.threadpool.submit(call)
|
||||
fut.add_done_callback(self._threadpool_no_wait_done)
|
||||
|
||||
# WOULD-AUTOGEN-BEGIN
|
||||
# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__
|
||||
# This section autogenerated by project-update.
|
||||
|
||||
@cached_property
|
||||
def classic(self) -> ClassicSubsystem | None:
|
||||
@ -343,7 +333,7 @@ class App:
|
||||
except ImportError:
|
||||
return None
|
||||
except Exception:
|
||||
logging.exception('Error importing baclassic')
|
||||
logging.exception('Error importing baclassic.')
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
@ -357,10 +347,10 @@ class App:
|
||||
except ImportError:
|
||||
return None
|
||||
except Exception:
|
||||
logging.exception('Error importing baplus')
|
||||
logging.exception('Error importing baplus.')
|
||||
return None
|
||||
|
||||
# WOULD-AUTOGEN-END
|
||||
# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_END__
|
||||
|
||||
def set_intent(self, intent: AppIntent) -> None:
|
||||
"""Set the intent for the app.
|
||||
@ -514,13 +504,14 @@ class App:
|
||||
"""Decides which app modes to use to handle intents."""
|
||||
|
||||
def app_mode_for_intent(self, intent: AppIntent) -> type[AppMode]:
|
||||
# WOULD-AUTOGEN-BEGIN
|
||||
# __DEFAULT_APP_MODE_SELECTION_BEGIN__
|
||||
# This section autogenerated by project-update.
|
||||
|
||||
import bascenev1
|
||||
|
||||
return bascenev1.SceneV1AppMode
|
||||
|
||||
# WOULD-AUTOGEN-END
|
||||
# __DEFAULT_APP_MODE_SELECTION_END__
|
||||
|
||||
def on_app_running(self) -> None:
|
||||
"""Called when initially entering the running state."""
|
||||
|
||||
@ -30,7 +30,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21041
|
||||
TARGET_BALLISTICA_BUILD = 21042
|
||||
TARGET_BALLISTICA_VERSION = '1.7.20'
|
||||
|
||||
_g_env_config: EnvConfig | None = None
|
||||
|
||||
@ -37,6 +37,7 @@ class UIV1SoftInterface {
|
||||
virtual void OnLanguageChange() = 0;
|
||||
virtual auto GetRootWidget() -> ui_v1::Widget* = 0;
|
||||
virtual auto SendWidgetMessage(const WidgetMessage& m) -> int = 0;
|
||||
virtual void ApplyAppConfig() = 0;
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -8,12 +8,10 @@
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/ui_v1_soft.h"
|
||||
#include "ballistica/base/ui/console.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/ui_v1/widget/root_widget.h"
|
||||
#include "ballistica/ui_v1/widget/stack_widget.h"
|
||||
#include "ballistica/ui_v1/widget/text_widget.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -87,9 +85,9 @@ void UI::OnAppShutdown() { assert(g_base->InLogicThread()); }
|
||||
|
||||
void UI::ApplyAppConfig() {
|
||||
assert(g_base->InLogicThread());
|
||||
ui_v1::TextWidget::set_always_use_internal_keyboard(
|
||||
g_base->app_config->Resolve(
|
||||
AppConfig::BoolID::kAlwaysUseInternalKeyboard));
|
||||
if (g_base->HaveUIV1()) {
|
||||
g_base->ui_v1()->ApplyAppConfig();
|
||||
}
|
||||
}
|
||||
|
||||
auto UI::MainMenuVisible() const -> bool {
|
||||
@ -227,16 +225,6 @@ auto UI::SendWidgetMessage(const WidgetMessage& m) -> int {
|
||||
return false;
|
||||
}
|
||||
|
||||
void UI::DeleteWidget(ui_v1::Widget* widget) {
|
||||
assert(widget);
|
||||
if (widget) {
|
||||
ui_v1::ContainerWidget* parent = widget->parent_widget();
|
||||
if (parent) {
|
||||
parent->DeleteWidget(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UI::OnScreenSizeChange() {
|
||||
if (g_base->HaveUIV1()) {
|
||||
g_base->ui_v1()->OnScreenSizeChange();
|
||||
|
||||
@ -84,9 +84,6 @@ class UI {
|
||||
// Send message to the active widget.
|
||||
auto SendWidgetMessage(const WidgetMessage& msg) -> int;
|
||||
|
||||
// Use this to destroy any named widget (even those in containers).
|
||||
void DeleteWidget(ui_v1::Widget* widget);
|
||||
|
||||
void SetUIInputDevice(InputDevice* input_device);
|
||||
|
||||
// Returns the input-device that currently owns the menu; otherwise nullptr.
|
||||
|
||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kEngineBuildNumber = 21041;
|
||||
const int kEngineBuildNumber = 21042;
|
||||
const char* kEngineVersion = "1.7.20";
|
||||
|
||||
auto MonolithicMain(const core::CoreConfig& core_config) -> int {
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/ui_v1/ui_v1.h"
|
||||
|
||||
#include "ballistica/base/app/app_config.h"
|
||||
#include "ballistica/base/app/app_mode.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
@ -12,6 +13,7 @@
|
||||
#include "ballistica/ui_v1/widget/container_widget.h"
|
||||
#include "ballistica/ui_v1/widget/root_widget.h"
|
||||
#include "ballistica/ui_v1/widget/stack_widget.h"
|
||||
#include "ballistica/ui_v1/widget/text_widget.h"
|
||||
|
||||
namespace ballistica::ui_v1 {
|
||||
|
||||
@ -74,7 +76,7 @@ void UIV1FeatureSet::DoHandleDeviceMenuPress(base::InputDevice* device) {
|
||||
void UIV1FeatureSet::DoShowURL(const std::string& url) { python->ShowURL(url); }
|
||||
|
||||
void UIV1FeatureSet::DoQuitWindow() {
|
||||
g_ui_v1->python->objs().Get(ui_v1::UIV1Python::ObjID::kQuitWindowCall).Call();
|
||||
g_ui_v1->python->objs().Get(UIV1Python::ObjID::kQuitWindowCall).Call();
|
||||
}
|
||||
|
||||
RootUI* UIV1FeatureSet::NewRootUI() { return new RootUI(); }
|
||||
@ -195,7 +197,7 @@ void UIV1FeatureSet::Reset() {
|
||||
screen_root_widget_.Clear();
|
||||
|
||||
// (Re)create our screen-root widget.
|
||||
auto sw(Object::New<ui_v1::StackWidget>());
|
||||
auto sw(Object::New<StackWidget>());
|
||||
sw->set_is_main_window_stack(true);
|
||||
sw->SetWidth(g_base->graphics->screen_virtual_width());
|
||||
sw->SetHeight(g_base->graphics->screen_virtual_height());
|
||||
@ -203,7 +205,7 @@ void UIV1FeatureSet::Reset() {
|
||||
screen_root_widget_ = sw;
|
||||
|
||||
// (Re)create our screen-overlay widget.
|
||||
auto ow(Object::New<ui_v1::StackWidget>());
|
||||
auto ow(Object::New<StackWidget>());
|
||||
ow->set_is_overlay_window_stack(true);
|
||||
ow->SetWidth(g_base->graphics->screen_virtual_width());
|
||||
ow->SetHeight(g_base->graphics->screen_virtual_height());
|
||||
@ -211,7 +213,7 @@ void UIV1FeatureSet::Reset() {
|
||||
overlay_root_widget_ = ow;
|
||||
|
||||
// (Re)create our abs-root widget.
|
||||
auto rw(Object::New<ui_v1::RootWidget>());
|
||||
auto rw(Object::New<RootWidget>());
|
||||
root_widget_ = rw;
|
||||
rw->SetWidth(g_base->graphics->screen_virtual_width());
|
||||
rw->SetHeight(g_base->graphics->screen_virtual_height());
|
||||
@ -267,4 +269,19 @@ auto UIV1FeatureSet::SendWidgetMessage(const base::WidgetMessage& m) -> int {
|
||||
return root_widget_->HandleMessage(m);
|
||||
}
|
||||
|
||||
void UIV1FeatureSet::DeleteWidget(Widget* widget) {
|
||||
assert(widget);
|
||||
if (widget) {
|
||||
ContainerWidget* parent = widget->parent_widget();
|
||||
if (parent) {
|
||||
parent->DeleteWidget(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIV1FeatureSet::ApplyAppConfig() {
|
||||
TextWidget::set_always_use_internal_keyboard(g_base->app_config->Resolve(
|
||||
base::AppConfig::BoolID::kAlwaysUseInternalKeyboard));
|
||||
}
|
||||
|
||||
} // namespace ballistica::ui_v1
|
||||
|
||||
@ -95,10 +95,13 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
|
||||
// If a parent is provided, the widget is added to it; otherwise it is added
|
||||
// to the root widget.
|
||||
void AddWidget(Widget* w, ContainerWidget* to);
|
||||
void DeleteWidget(Widget* widget);
|
||||
|
||||
void OnScreenSizeChange() override;
|
||||
void OnLanguageChange() override;
|
||||
auto GetRootWidget() -> ui_v1::Widget* override;
|
||||
auto SendWidgetMessage(const base::WidgetMessage& m) -> int override;
|
||||
void ApplyAppConfig() override;
|
||||
|
||||
private:
|
||||
UIV1FeatureSet();
|
||||
|
||||
@ -820,7 +820,9 @@ void ContainerWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
|
||||
Object::WeakRef<Widget> weakref(this);
|
||||
g_base->logic->event_loop()->PushCall([weakref] {
|
||||
Widget* w = weakref.Get();
|
||||
if (w) g_base->ui->DeleteWidget(w);
|
||||
if (w) {
|
||||
g_ui_v1->DeleteWidget(w);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -875,7 +877,9 @@ void ContainerWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
|
||||
Object::WeakRef<Widget> weakref(this);
|
||||
g_base->logic->event_loop()->PushCall([weakref] {
|
||||
Widget* w = weakref.Get();
|
||||
if (w) g_base->ui->DeleteWidget(w);
|
||||
if (w) {
|
||||
g_ui_v1->DeleteWidget(w);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ def _get_targets(
|
||||
def _get_py_targets(
|
||||
projroot: str,
|
||||
meta_manifests: dict[str, str],
|
||||
explicit_sources: set[str],
|
||||
src: str,
|
||||
dst: str,
|
||||
py_targets: list[str],
|
||||
@ -66,14 +67,17 @@ def _get_py_targets(
|
||||
) -> None:
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
py_generated_root = f'{ASSETS_SRC}/ba_data/python/babase/_mgen'
|
||||
|
||||
def _do_get_targets(proot: str, fnames: list[str]) -> None:
|
||||
def _do_get_targets(
|
||||
proot: str, fnames: list[str], is_explicit: bool = False
|
||||
) -> None:
|
||||
# Special case: ignore temp py files in data src.
|
||||
if proot == f'{ASSETS_SRC}/ba_data/data/maps':
|
||||
return
|
||||
assert proot.startswith(src)
|
||||
assert proot.startswith(src), f'{proot} does not start with {src}'
|
||||
assert dst.startswith(BUILD_DIR)
|
||||
dstrootvar = (
|
||||
'$(BUILD_DIR)'
|
||||
@ -90,6 +94,16 @@ def _get_py_targets(
|
||||
):
|
||||
continue
|
||||
|
||||
# Ignore any files in the list of explicit sources we got;
|
||||
# we explicitly add those at the end and don't want to do it
|
||||
# twice (since we don't know if this one will always exist
|
||||
# anyway).
|
||||
if (
|
||||
os.path.join(proot, fname) in explicit_sources
|
||||
and not is_explicit
|
||||
):
|
||||
continue
|
||||
|
||||
if proot.startswith(f'{ASSETS_SRC}/ba_data/python-site-packages'):
|
||||
in_subset = 'private-common'
|
||||
elif proot.startswith(f'{ASSETS_SRC}/ba_data') or proot.startswith(
|
||||
@ -122,7 +136,9 @@ def _get_py_targets(
|
||||
# gamedata pass includes only data; otherwise do all else
|
||||
|
||||
# .py:
|
||||
all_targets.add(os.path.join(dstfin, fname))
|
||||
targetpath = os.path.join(dstfin, fname)
|
||||
assert targetpath not in all_targets
|
||||
all_targets.add(targetpath)
|
||||
py_targets.append(os.path.join(dstrootvar, fname))
|
||||
|
||||
# and .pyc:
|
||||
@ -173,14 +189,25 @@ def _get_py_targets(
|
||||
proot=os.path.dirname(target), fnames=[os.path.basename(target)]
|
||||
)
|
||||
|
||||
# Now create targets for any explicitly passed paths.
|
||||
for expsrc in explicit_sources:
|
||||
if expsrc.startswith(f'{src}/'):
|
||||
_do_get_targets(
|
||||
proot=os.path.dirname(expsrc),
|
||||
fnames=[os.path.basename(expsrc)],
|
||||
is_explicit=True,
|
||||
)
|
||||
|
||||
|
||||
def _get_py_targets_subset(
|
||||
projroot: str,
|
||||
meta_manifests: dict[str, str],
|
||||
explicit_sources: set[str],
|
||||
all_targets: set[str],
|
||||
subset: str,
|
||||
suffix: str,
|
||||
) -> str:
|
||||
# pylint: disable=too-many-locals
|
||||
if subset == 'public_tools':
|
||||
src = 'tools'
|
||||
dst = f'{BUILD_DIR}/ba_data/python'
|
||||
@ -197,6 +224,7 @@ def _get_py_targets_subset(
|
||||
_get_py_targets(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
src,
|
||||
dst,
|
||||
py_targets,
|
||||
@ -368,6 +396,7 @@ def generate_assets_makefile(
|
||||
fname: str,
|
||||
existing_data: str,
|
||||
meta_manifests: dict[str, str],
|
||||
explicit_sources: set[str],
|
||||
) -> dict[str, str]:
|
||||
"""Main script entry point."""
|
||||
# pylint: disable=too-many-locals
|
||||
@ -377,8 +406,6 @@ def generate_assets_makefile(
|
||||
public = getconfig(Path(projroot))['public']
|
||||
assert isinstance(public, bool)
|
||||
|
||||
# with open(fname, encoding='utf-8') as infile:
|
||||
# original = infile.read()
|
||||
original = existing_data
|
||||
lines = original.splitlines()
|
||||
|
||||
@ -395,6 +422,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_public,
|
||||
subset='public',
|
||||
suffix='_PUBLIC',
|
||||
@ -402,6 +430,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_public,
|
||||
subset='public_tools',
|
||||
suffix='_PUBLIC_TOOLS',
|
||||
@ -416,6 +445,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_private,
|
||||
subset='private-apple',
|
||||
suffix='_PRIVATE_APPLE',
|
||||
@ -423,6 +453,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_private,
|
||||
subset='private-android',
|
||||
suffix='_PRIVATE_ANDROID',
|
||||
@ -430,6 +461,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_private,
|
||||
subset='private-common',
|
||||
suffix='_PRIVATE_COMMON',
|
||||
@ -437,6 +469,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_private,
|
||||
subset='private-windows-Win32',
|
||||
suffix='_PRIVATE_WIN_WIN32',
|
||||
@ -444,6 +477,7 @@ def generate_assets_makefile(
|
||||
_get_py_targets_subset(
|
||||
projroot,
|
||||
meta_manifests,
|
||||
explicit_sources,
|
||||
all_targets_private,
|
||||
subset='private-windows-x64',
|
||||
suffix='_PRIVATE_WIN_X64',
|
||||
@ -470,7 +504,11 @@ def generate_assets_makefile(
|
||||
all_targets_private,
|
||||
),
|
||||
_get_targets(
|
||||
projroot, 'PEM_TARGETS', '.pem', '.pem', all_targets_private
|
||||
projroot,
|
||||
'PEM_TARGETS',
|
||||
'.pem',
|
||||
'.pem',
|
||||
all_targets_private,
|
||||
),
|
||||
_get_targets(
|
||||
projroot,
|
||||
@ -481,7 +519,11 @@ def generate_assets_makefile(
|
||||
limit_to_prefix='ba_data/data',
|
||||
),
|
||||
_get_targets(
|
||||
projroot, 'AUDIO_TARGETS', '.wav', '.ogg', all_targets_private
|
||||
projroot,
|
||||
'AUDIO_TARGETS',
|
||||
'.wav',
|
||||
'.ogg',
|
||||
all_targets_private,
|
||||
),
|
||||
_get_targets(
|
||||
projroot,
|
||||
|
||||
@ -28,49 +28,50 @@ class FeatureSet:
|
||||
|
||||
_active_feature_set: FeatureSet | None = None
|
||||
|
||||
@classmethod
|
||||
def get_all_for_project(cls, project_root: str) -> list[FeatureSet]:
|
||||
"""Return all feature-sets for the current project."""
|
||||
project_root_abs = os.path.abspath(project_root)
|
||||
|
||||
# Only do this once per project.
|
||||
if project_root_abs not in _g_feature_sets:
|
||||
_g_feature_sets[project_root_abs] = _build_feature_set_list(
|
||||
project_root_abs
|
||||
)
|
||||
return _g_feature_sets[project_root_abs]
|
||||
|
||||
@classmethod
|
||||
def resolve_requirements(
|
||||
cls, featuresets: list[FeatureSet], reqs: set[str]
|
||||
) -> set[str]:
|
||||
"""Resolve all required feature-sets based on a given set of them.
|
||||
|
||||
Throws descriptive CleanErrors if any are missing.
|
||||
"""
|
||||
fsets = {f.name: f for f in featuresets}
|
||||
reqs_out = set[str]()
|
||||
for req in reqs:
|
||||
cls._resolve_requirements(fsets, reqs_out, req)
|
||||
return reqs_out
|
||||
|
||||
@classmethod
|
||||
def _resolve_requirements(
|
||||
cls, featuresets: dict[str, FeatureSet], reqs_out: set[str], req: str
|
||||
) -> None:
|
||||
if req in reqs_out:
|
||||
return
|
||||
featureset = featuresets.get(req)
|
||||
if featureset is None:
|
||||
raise CleanError(f"Required featureset '{req}' not found.")
|
||||
reqs_out.add(req)
|
||||
for sub_req in featureset.requirements:
|
||||
cls._resolve_requirements(featuresets, reqs_out, sub_req)
|
||||
|
||||
def __init__(self, name: str):
|
||||
self.requirements = set[str]()
|
||||
# (internal; don't set this)
|
||||
self.internal = False
|
||||
|
||||
# Other feature-sets this one requires. Any spinoff project this
|
||||
# feature-set is included in will implicitly include these as
|
||||
# well.
|
||||
self.requirements = set[str]()
|
||||
|
||||
# Feature-sets this one can use but can survive without. Note
|
||||
# that each of these requirements must have
|
||||
# 'allow_as_soft_requirement' enabled. While it is possible to
|
||||
# programmatically check for the presence of *any* feature-set,
|
||||
# officially listing soft-requirements ensures that any expected
|
||||
# python-app-subsystems are in place even for feature-sets not
|
||||
# included in the spinoff project (though be aware their type
|
||||
# annotations will be 'Any | None' in that case instead of the
|
||||
# usual 'FooBarSubsystem | None' due to 'FooBarSubsystem' not
|
||||
# actually existing).
|
||||
self.soft_requirements = set[str]()
|
||||
|
||||
# Whether this featureset defines a native Python module within
|
||||
# its C++ code. The build process will try to create dummy
|
||||
# modules for all native modules you must tell it if you don't
|
||||
# have one.
|
||||
self.has_native_python_module = True
|
||||
|
||||
# If True, for feature-set 'foo_bar', the build system will
|
||||
# define a 'babase.app.foo_bar' attr which points to a lazy
|
||||
# loaded instance of type 'bafoobar.FooBarSubsystem'.
|
||||
self.has_python_app_subsystem = False
|
||||
|
||||
# If True, feature-set 'foo_bar', will be allowed to be listed
|
||||
# as a soft-requirement of other feature sets and its
|
||||
# python-app-subsystem will be annotated as type
|
||||
# 'bafoobar.FooBarSubsystem | None' instead of simply
|
||||
# 'bafoobar.FooBarSubsystem'. This forces type-checked code to
|
||||
# account for the possibility that it will not be present. Note
|
||||
# that this currently requires has_python_app_subsystem to be
|
||||
# True (because if a soft-required feature-set is missing we
|
||||
# must assume that is the case anyway because there's no way to
|
||||
# know).
|
||||
self.allow_as_soft_requirement = False
|
||||
|
||||
self.validate_name(name)
|
||||
|
||||
# Paths of files we should disable c++ namespace checks for.
|
||||
@ -228,6 +229,45 @@ class FeatureSet:
|
||||
assert type(self)._active_feature_set is self
|
||||
type(self)._active_feature_set = None
|
||||
|
||||
@classmethod
|
||||
def get_all_for_project(cls, project_root: str) -> list[FeatureSet]:
|
||||
"""Return all feature-sets for the current project."""
|
||||
project_root_abs = os.path.abspath(project_root)
|
||||
|
||||
# Only do this once per project.
|
||||
if project_root_abs not in _g_feature_sets:
|
||||
_g_feature_sets[project_root_abs] = _build_feature_set_list(
|
||||
project_root_abs
|
||||
)
|
||||
return _g_feature_sets[project_root_abs]
|
||||
|
||||
@classmethod
|
||||
def resolve_requirements(
|
||||
cls, featuresets: list[FeatureSet], reqs: set[str]
|
||||
) -> set[str]:
|
||||
"""Resolve all required feature-sets based on a given set of them.
|
||||
|
||||
Throws descriptive CleanErrors if any are missing.
|
||||
"""
|
||||
fsets = {f.name: f for f in featuresets}
|
||||
reqs_out = set[str]()
|
||||
for req in reqs:
|
||||
cls._resolve_requirements(fsets, reqs_out, req)
|
||||
return reqs_out
|
||||
|
||||
@classmethod
|
||||
def _resolve_requirements(
|
||||
cls, featuresets: dict[str, FeatureSet], reqs_out: set[str], req: str
|
||||
) -> None:
|
||||
if req in reqs_out:
|
||||
return
|
||||
featureset = featuresets.get(req)
|
||||
if featureset is None:
|
||||
raise CleanError(f"Required featureset '{req}' not found.")
|
||||
reqs_out.add(req)
|
||||
for sub_req in featureset.requirements:
|
||||
cls._resolve_requirements(featuresets, reqs_out, sub_req)
|
||||
|
||||
|
||||
def _build_feature_set_list(project_root: str) -> list[FeatureSet]:
|
||||
featuresets: list[FeatureSet] = []
|
||||
@ -246,28 +286,56 @@ def _build_feature_set_list(project_root: str) -> list[FeatureSet]:
|
||||
featureset.apply_config(os.path.join(fsdir, filename))
|
||||
featuresets.append(featureset)
|
||||
|
||||
# Run some sanity checks to make sure our featuresets don't have
|
||||
# clashing names/etc. (for instance, foo_v1 and foov_1 would resolve
|
||||
# to the same foov1 py module name).
|
||||
# Run some sanity checks to make sure our full set of featuresets
|
||||
# don't have clashing names/etc. (for instance, foo_v1 and foov_1
|
||||
# would resolve to the same foov1 py module name).
|
||||
|
||||
fsnames = {f.name for f in featuresets}
|
||||
assert len(fsnames) == len(featuresets)
|
||||
featuresets_by_name = {f.name: f for f in featuresets}
|
||||
assert len(featuresets_by_name) == len(featuresets)
|
||||
|
||||
assert len({f.name_compact for f in featuresets}) == len(featuresets)
|
||||
assert len({f.name_compact for f in featuresets}) == len(featuresets)
|
||||
|
||||
for featureset in featuresets:
|
||||
# Require soft-req-enabled feature-sets to have app subsystems
|
||||
# enabled (see above for explanation).
|
||||
if featureset.allow_as_soft_requirement:
|
||||
if not featureset.has_python_app_subsystem:
|
||||
raise CleanError(
|
||||
f"Feature-set '{featureset.name}'"
|
||||
" has 'allow_as_soft_requirement' set to True but"
|
||||
" 'has_python_app_subsystem' set to False;"
|
||||
' soft-requireable feature-sets currently MUST'
|
||||
' provide a subsystem.'
|
||||
)
|
||||
|
||||
for req in featureset.requirements:
|
||||
if req == featureset.name:
|
||||
raise CleanError(
|
||||
f"Feature-set '{featureset.name}'"
|
||||
f' lists itself as a requirement; this is not allowed.'
|
||||
)
|
||||
if req not in fsnames:
|
||||
if req not in featuresets_by_name:
|
||||
raise CleanError(
|
||||
f"Undefined feature-set '{req}'"
|
||||
f' listed as a requirement of feature-set'
|
||||
f" '{featureset.name}'."
|
||||
)
|
||||
for req in featureset.soft_requirements:
|
||||
if req == featureset.name:
|
||||
raise CleanError(
|
||||
f"Feature-set '{featureset.name}'"
|
||||
f' lists itself as a soft-requirement; this is not allowed.'
|
||||
)
|
||||
if (
|
||||
req in featuresets_by_name
|
||||
and not featuresets_by_name[req].allow_as_soft_requirement
|
||||
):
|
||||
raise CleanError(
|
||||
f"Feature-set '{req}'"
|
||||
f' is listed as a soft-requirement of feature-set'
|
||||
f" '{featureset.name}' but is not allowed to be soft"
|
||||
' required.'
|
||||
)
|
||||
|
||||
return featuresets
|
||||
|
||||
@ -111,6 +111,7 @@ class ProjectUpdater:
|
||||
self._update_cmake_files()
|
||||
self._update_visual_studio_projects()
|
||||
self._update_xcode_projects()
|
||||
self._update_app_module()
|
||||
|
||||
@property
|
||||
def source_files(self) -> list[str]:
|
||||
@ -401,6 +402,8 @@ class ProjectUpdater:
|
||||
self._generate_resources_makefile(path, existing_data)
|
||||
elif path == 'src/meta/Makefile':
|
||||
self._generate_meta_makefile(existing_data)
|
||||
elif path == 'src/assets/ba_data/python/babase/_app.py':
|
||||
self._generate_app_module(path, existing_data)
|
||||
elif path.startswith('src/meta/.meta_manifest_'):
|
||||
# These are always generated as a side-effect of the
|
||||
# meta Makefile.
|
||||
@ -414,6 +417,9 @@ class ProjectUpdater:
|
||||
assert path in self._generated_files
|
||||
return self._generated_files[path]
|
||||
|
||||
def _update_app_module(self) -> None:
|
||||
self.enqueue_update('src/assets/ba_data/python/babase/_app.py')
|
||||
|
||||
def _update_xcode_projects(self) -> None:
|
||||
# from batools.xcode import update_xcode_project
|
||||
|
||||
@ -652,7 +658,7 @@ class ProjectUpdater:
|
||||
def _generate_assets_makefile(self, path: str, existing_data: str) -> None:
|
||||
from batools.assetsmakefile import generate_assets_makefile
|
||||
|
||||
# We need to now what files meta will be creating (since they
|
||||
# We need to know what files meta will be creating (since they
|
||||
# can be asset sources).
|
||||
meta_manifests: dict[str, str] = {}
|
||||
for mantype in ['public', 'private']:
|
||||
@ -661,8 +667,17 @@ class ProjectUpdater:
|
||||
manifest_file_name
|
||||
)
|
||||
|
||||
# Special case; the app module file in the base feature set
|
||||
# is created/updated here as a project file. It may or may not
|
||||
# exist on disk, but we want to ignore it if it does and add it
|
||||
# explicitly similarly to meta-manifests.
|
||||
if 'base' in self.feature_sets:
|
||||
explicit_sources = {'src/assets/ba_data/python/babase/_app.py'}
|
||||
else:
|
||||
explicit_sources = set()
|
||||
|
||||
outfiles = generate_assets_makefile(
|
||||
self.projroot, path, existing_data, meta_manifests
|
||||
self.projroot, path, existing_data, meta_manifests, explicit_sources
|
||||
)
|
||||
|
||||
for out_path, out_contents in outfiles.items():
|
||||
@ -680,6 +695,120 @@ class ProjectUpdater:
|
||||
self.projroot, existing_data
|
||||
)
|
||||
|
||||
def _generate_app_module(self, path: str, existing_data: str) -> None:
|
||||
# pylint: disable=too-many-locals
|
||||
import textwrap
|
||||
|
||||
from efrotools import replace_section
|
||||
|
||||
fsets = self.feature_sets
|
||||
|
||||
out = existing_data
|
||||
|
||||
info = '# This section autogenerated by project-update.'
|
||||
indent = ' '
|
||||
|
||||
# Import modules we need for feature-set subsystems.
|
||||
contents = ''
|
||||
for _fsname, fset in sorted(fsets.items()):
|
||||
if fset.has_python_app_subsystem:
|
||||
modname = fset.name_python_package
|
||||
classname = f'{fset.name_camel}Subsystem'
|
||||
contents += f'from {modname} import {classname}\n'
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_IMPORTS_BEGIN__\n',
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_IMPORTS_END__\n',
|
||||
textwrap.indent(f'{info}\n\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Calc which feature-sets are soft-required by any of the ones here
|
||||
# but not included here. For those we'll expose app-subsystems that
|
||||
# always return None.
|
||||
missing_soft_fset_names = set[str]()
|
||||
|
||||
for fset in fsets.values():
|
||||
for softreq in fset.soft_requirements:
|
||||
if softreq not in fsets:
|
||||
missing_soft_fset_names.add(softreq)
|
||||
|
||||
all_fset_names = missing_soft_fset_names | fsets.keys()
|
||||
|
||||
# Add properties to instantiate feature-set subsystems.
|
||||
contents = ''
|
||||
|
||||
for fsetname in sorted(all_fset_names):
|
||||
# for _fsname, fset in sorted(fsets.items()):
|
||||
if fsetname in missing_soft_fset_names:
|
||||
contents += (
|
||||
f'\n'
|
||||
f'@cached_property\n'
|
||||
f'def {fsetname}(self) -> Any | None:\n'
|
||||
f' """Our {fsetname} subsystem (not available)."""\n'
|
||||
f'\n'
|
||||
f' return None\n'
|
||||
)
|
||||
else:
|
||||
fset = fsets[fsetname]
|
||||
if fset.has_python_app_subsystem:
|
||||
if not fset.allow_as_soft_requirement:
|
||||
raise CleanError(
|
||||
f'allow_as_soft_requirement is False for'
|
||||
f' feature-set {fset.name};'
|
||||
f' this is not yet supported.'
|
||||
)
|
||||
modname = fset.name_python_package
|
||||
classname = f'{fset.name_camel}Subsystem'
|
||||
contents += (
|
||||
f'\n'
|
||||
f'@cached_property\n'
|
||||
f'def {fset.name}(self) -> {classname} | None:\n'
|
||||
f' """Our {fset.name} subsystem (if available)."""\n'
|
||||
f'\n'
|
||||
f' try:\n'
|
||||
f' from {modname} import {classname}\n'
|
||||
f'\n'
|
||||
f' return {classname}()\n'
|
||||
f' except ImportError:\n'
|
||||
f' return None\n'
|
||||
f' except Exception:\n'
|
||||
f" logging.exception('Error importing"
|
||||
f" {modname}.')\n"
|
||||
f' return None\n'
|
||||
)
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__\n',
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_END__\n',
|
||||
textwrap.indent(f'{info}\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Set default app-mode-selection logic.
|
||||
|
||||
# TEMP - fill this out with proper logic/options.
|
||||
if 'scene_v1' in fsets:
|
||||
contents = 'import bascenev1\n\nreturn bascenev1.SceneV1AppMode\n'
|
||||
else:
|
||||
contents = "raise RuntimeError('FIXME: unimplemented.')\n"
|
||||
|
||||
indent = ' '
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __DEFAULT_APP_MODE_SELECTION_BEGIN__\n',
|
||||
f'{indent}# __DEFAULT_APP_MODE_SELECTION_END__\n',
|
||||
textwrap.indent(f'{info}\n\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Note: we *should* format this string, but because this code
|
||||
# runs with every project update I'm just gonna try to keep the
|
||||
# formatting correct manually for now to save a bit of time.
|
||||
# (project update time jumps from 0.3 to 0.5 seconds if I format
|
||||
# thie one file).
|
||||
self._generated_files[path] = out
|
||||
|
||||
def _update_meta_makefile(self) -> None:
|
||||
self.enqueue_update('src/meta/Makefile')
|
||||
|
||||
|
||||
@ -129,20 +129,10 @@ class SpinoffContext:
|
||||
|
||||
self._execution_error = False
|
||||
|
||||
self._project_file_names = {
|
||||
'Makefile',
|
||||
'CMakeLists.txt',
|
||||
'.meta_manifest_public.json',
|
||||
'.meta_manifest_private.json',
|
||||
'.asset_manifest_public.json',
|
||||
'.asset_manifest_private.json',
|
||||
}
|
||||
self.project_file_paths = set[str]()
|
||||
self.project_file_names = set[str]()
|
||||
self.project_file_suffixes = set[str]()
|
||||
|
||||
self._project_file_suffixes = {
|
||||
'.vcxproj',
|
||||
'.vcxproj.filters',
|
||||
'.pbxproj',
|
||||
}
|
||||
# Set of files/symlinks in src.
|
||||
self._src_entities: dict[str, SrcEntity] = {}
|
||||
|
||||
@ -1300,8 +1290,10 @@ class SpinoffContext:
|
||||
if path.startswith('tools/') or path.startswith('src/external'):
|
||||
return False
|
||||
bname = os.path.basename(path)
|
||||
return bname in self._project_file_names or any(
|
||||
bname.endswith(s) for s in self._project_file_suffixes
|
||||
return (
|
||||
path in self.project_file_paths
|
||||
or bname in self.project_file_names
|
||||
or any(bname.endswith(s) for s in self.project_file_suffixes)
|
||||
)
|
||||
|
||||
def _update(self) -> None:
|
||||
@ -1401,6 +1393,7 @@ class SpinoffContext:
|
||||
print_individual_updates: bool,
|
||||
is_project_file: bool = False,
|
||||
) -> None:
|
||||
# pylint: disable=too-many-locals
|
||||
src_entity = self._src_entities[src_path]
|
||||
dst_path = src_entity.dst
|
||||
src_path_full = os.path.join(self._src_root, src_path)
|
||||
@ -1465,10 +1458,12 @@ class SpinoffContext:
|
||||
f'{Clr.RED}Error removing failed dst file: {exc2}{Clr.RST}'
|
||||
)
|
||||
self._execution_error = True
|
||||
verbose_note = (
|
||||
'' if self._verbose else ' (use --verbose for full traceback)'
|
||||
)
|
||||
print(
|
||||
f'{Clr.RED}Error copying/filtering file:'
|
||||
f" '{src_path_full}'{Clr.RST}: {exc}"
|
||||
' (use --verbose for full traceback)',
|
||||
f" '{src_path_full}'{Clr.RST}: {exc}{verbose_note}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
if self._verbose:
|
||||
|
||||
@ -136,6 +136,7 @@ def replace_section(
|
||||
begin_marker: str,
|
||||
end_marker: str,
|
||||
replace_text: str = '',
|
||||
keep_markers: bool = False,
|
||||
error_if_missing: bool = True,
|
||||
) -> str:
|
||||
"""Replace all text between two marker strings (including the markers)."""
|
||||
@ -157,7 +158,9 @@ def replace_section(
|
||||
f'; found {text.count(end_marker)}.'
|
||||
)
|
||||
_before_end, after_end = splits
|
||||
return before_begin + replace_text + after_end
|
||||
if keep_markers:
|
||||
replace_text = f'{begin_marker}{replace_text}{end_marker}'
|
||||
return f'{before_begin}{replace_text}{after_end}'
|
||||
|
||||
|
||||
def get_public_license(style: str) -> str:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user