diff --git a/.efrocachemap b/.efrocachemap index 9b131e08..772e0a94 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4060,26 +4060,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "accfe77598232e6e7cabb654f9e9ca0b", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "22c2f0a9044cf96157ef19dba17eaa5c", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0f104075c5270088012c20634b4c4b53", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "f1ff6a5d060157cd561e8b7045b3ac5b", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "9d22975d45cdbf1fe70c096a09a2bd84", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6b5ef9ad5524bb0cc67562b43643fe1e", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "01e963e9f6d4e006bdf47947925b1e59", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "43c2c61d7a4d0b6a0fe65f23b4964aa2", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2114164d4fcb6766a9702397e3012810", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "67c4ecda6bd18a1de5ddcc62bddb486b", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d030cf1e4ca12b75b1b3fbfe0db2668a", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "022802e8aa2679864ee95af10ade0612", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "79525886ddef78e9c71698c1f6e0b7d9", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1155ff51a06813c846dc7494a221aaa0", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9f298a922a1342512adb113da69a7674", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "29179179655fb01220791b2e8320ee6c", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "f8e0f7099b0ed90bd2b35d5b06468842", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "0d880f0947d10de7ba3b6561d2d722cb", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "22e969bf3722c553db0e2c90acf8a720", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e98c4651be654bcdf891dbe7fb89aaac", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "53e4f0c08eb9dd46c972a25e0acdcd5a", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "3ef4e72b2493f014fd71c2d11d5f33eb", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0bf843bdd510d139b2652f6e8f161843", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7432662906bf0d068960c2986b645565", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "590c7763266e4e645b616e2d362be20e", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a39ef360900af1271d7f45ab1e001a97", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "d20010ab3d74cf7ab51c1e5d70755dc3", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a8b5df0a9afa3cb48fa3d20b49a7f3a9", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "9bc9ffd642f092ce45ab6b638696a77f", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "ff3a5a6e0506745bab006e7b88c3b429", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "73ebbddb334a1758adfd0b682f28d9e1", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "830a4a769a24e8e9f61287af350e23d3", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "e5ce86e2806cdc1500ae8b6fc901a0a3", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "b2181eba266c5fd763becdf0c6ed3c89", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "263216418f83ed24cf831c03b4929dbb", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c1441743d9aa4b3ee169d7df87092cb7", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "1ac4c86a479362da3da9308b14cad7dc", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1c74f29f81193d6592516a1fa1efd01c", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "3eb03b19effaedd686d0d4ba5588a9a0", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "7850820aeafe2ef0a124e91481271866", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "db535f0ca1e01af825f75f204fbc8928", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "97d51afca996ae15b61fd9f409a00459", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "db535f0ca1e01af825f75f204fbc8928", @@ -4096,18 +4096,18 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "452623f0495dd4375e5b5d9b80d643d5", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "ca49b32ed573feea11613d62cd89840c", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "452623f0495dd4375e5b5d9b80d643d5", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "1af7ac233ae61be912be9710eafb3c3a", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "7ddb4c8bf41a341a63c561d8dd13d35a", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "e4a63d2cf8a19a2778aea819423eeadf", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2c48a7cfc476526ce9ce75b4633dbc5d", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "7a95714de260a88f73f343fc411a28b1", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "be1f30593475b80aa55a7bc5b0c26c84", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "0133baed39774c154f097c74d1d2be6e", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "864f2f2639c7b785ebcda497abcc31bf", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ff81e6eeea861f59e71db628bc64918b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ba89e5949d1cdf2b857089feb901285c", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5e063f8acc0e0e9f35f82480d7dbf143", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "1f0d14fcc16dd0d4896d91c75e32be25", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "251d3dd0bc9a6418eb1cb5176bb5509c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "96c003edb87b3f506d1b15af461487c3", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "274ebd634f05b23653719ef973119cf5", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "796edace73f874ebf46054b2a1ff0ba1", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", - "src/ballistica/base/mgen/pyembed/binding_base_app.inc": "00f81f9bd92386ec12a6e60170678a98", + "src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc", "src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3", "src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69", "src/ballistica/core/mgen/pyembed/env.inc": "8be46e5818f360d10b7b0224a9e91d07", diff --git a/CHANGELOG.md b/CHANGELOG.md index 8807c252..cf18ace5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.32 (build 21739, api 8, 2023-12-20) +### 1.7.32 (build 21741, api 8, 2023-12-20) - Fixed a screen message that no one will ever see (Thanks vishal332008?...) - Plugins window now displays 'No Plugins Installed' when no plugins are present (Thanks vishal332008!) - Old messages are now displayed as soon as you press 'Unmute Chat' (Thanks vishal332008!) @@ -18,6 +18,11 @@ player play, dev testing, etc. Hopefully this strikes a good balance now. - Removed the player-rejoin-cooldown mechanism from the C++ layer since it was redundant with the Python level one and didn't cover as many cases. +- Restored the behavior from before 1.7.28 where backgrounding the app would + bring up the main menu and pause the action. Now it is implemented more + cleanly however (an `on_app_active_changed()` call in the `AppMode` class). + This means that it also applies to other platforms when the app reaches the + 'inactive' state; for instance when minimizing the window on the SDL build. ### 1.7.31 (build 21727, api 8, 2023-12-17) - Added `bascenev1.get_connection_to_host_info_2()` which is an improved diff --git a/src/assets/ba_data/python/babase/__init__.py b/src/assets/ba_data/python/babase/__init__.py index e1b7a32c..9d4379f3 100644 --- a/src/assets/ba_data/python/babase/__init__.py +++ b/src/assets/ba_data/python/babase/__init__.py @@ -60,6 +60,7 @@ from _babase import ( have_permission, in_logic_thread, increment_analytics_count, + invoke_main_menu, is_os_playing_music, is_xcode_build, lock_all_input, @@ -254,6 +255,7 @@ __all__ = [ 'increment_analytics_count', 'InputDeviceNotFoundError', 'InputType', + 'invoke_main_menu', 'is_browser_likely_available', 'is_browser_likely_available', 'is_os_playing_music', diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index 07bacfa6..4a021ab8 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -437,6 +437,12 @@ class App: self._native_shutdown_complete_called = True self._update_state() + def on_native_active_changed(self) -> None: + """Called by the native layer when the app active state changes.""" + assert _babase.in_logic_thread() + if self._mode is not None: + self._mode.on_app_active_changed() + def read_config(self) -> None: """(internal)""" from babase._appconfig import read_app_config diff --git a/src/assets/ba_data/python/babase/_appmode.py b/src/assets/ba_data/python/babase/_appmode.py index 1da43144..cfe01f7b 100644 --- a/src/assets/ba_data/python/babase/_appmode.py +++ b/src/assets/ba_data/python/babase/_appmode.py @@ -52,3 +52,10 @@ class AppMode: def on_deactivate(self) -> None: """Called when the mode is being deactivated.""" + + def on_app_active_changed(self) -> None: + """Called when babase.app.active changes. + + The app-mode may want to take action such as pausing a running + game in such cases. + """ diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index c8f23af9..64a149e1 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21739 +TARGET_BALLISTICA_BUILD = 21741 TARGET_BALLISTICA_VERSION = '1.7.32' diff --git a/src/assets/ba_data/python/bascenev1/_appmode.py b/src/assets/ba_data/python/bascenev1/_appmode.py index 10d1c320..9408865d 100644 --- a/src/assets/ba_data/python/bascenev1/_appmode.py +++ b/src/assets/ba_data/python/bascenev1/_appmode.py @@ -6,7 +6,13 @@ from __future__ import annotations from typing import TYPE_CHECKING from bacommon.app import AppExperience -from babase import AppMode, AppIntentExec, AppIntentDefault +from babase import ( + app, + AppMode, + AppIntentExec, + AppIntentDefault, + invoke_main_menu, +) import _bascenev1 @@ -40,3 +46,9 @@ class SceneV1AppMode(AppMode): def on_deactivate(self) -> None: # Let the native layer do its thing. _bascenev1.on_app_mode_deactivate() + + def on_app_active_changed(self) -> None: + # If we've gone inactive, bring up the main menu, which has the + # side effect of pausing the action (when possible). + if not app.active: + invoke_main_menu() diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index a174c575..09dbf208 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -402,24 +402,6 @@ void BaseFeatureSet::UnsuspendApp() { g_base->network_reader->OnAppUnsuspend(); g_base->networking->OnAppUnsuspend(); - // When resuming from a suspended state, we may want to pause whatever - // game was running when we last were active. - // - // TODO(efro): we should make this smarter so it doesn't happen if we're - // in a network game or something that we can't pause; bringing up the - // menu doesn't really accomplish anything there. - // - // In general this probably should be handled at a higher level. - // if (g_core->should_pause_active_game) { - // g_core->should_pause_active_game = false; - - // // If we've been completely backgrounded, send a menu-press command to - // // the game; this will bring up a pause menu if we're in the game/etc. - // if (!g_base->ui->MainMenuVisible()) { - // g_base->ui->PushMainMenuPressCall(nullptr); - // } - // } - if (g_buildconfig.debug_build()) { Log(LogLevel::kDebug, "UnsuspendApp() completed in " @@ -974,20 +956,30 @@ auto BaseFeatureSet::ClipboardGetText() -> std::string { void BaseFeatureSet::SetAppActive(bool active) { assert(InMainThread()); + + // Note: in some cases I'm seeing repeat active/inactive sets; for example + // on Mac SDL if I hide the app and then click on it in the dock I get a + // 'inactive' for the hide followed by a 'active', 'inactive', 'active' on + // the dock click. So our strategy here to filter that out is just to tell + // the logic thread that it has changed but have them directly read the + // shared atomic value, so they should generally skip over flip-flops like + // that and will just read the final value a few times in a row. + g_core->platform->LowLevelDebugLog( "SetAppActive(" + std::to_string(active) + ")@" + std::to_string(core::CorePlatform::GetCurrentMillisecs())); - printf("APP ACTIVE %d\n", static_cast(active)); - // Issue a gentle warning if they are feeding us the same state twice in a - // row; might imply faulty logic. + // row; might imply faulty logic on an app-adapter or whatnot. if (app_active_set_ && app_active_ == active) { Log(LogLevel::kWarning, "SetAppActive called with state " + std::to_string(active) + " twice in a row."); } app_active_set_ = true; app_active_ = active; + + g_base->logic->event_loop()->PushCall( + [] { g_base->logic->OnAppActiveChanged(); }); } } // namespace ballistica::base diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index 5bea0e93..00ac6262 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -3,6 +3,7 @@ #ifndef BALLISTICA_BASE_BASE_H_ #define BALLISTICA_BASE_BASE_H_ +#include #include #include #include @@ -815,7 +816,7 @@ class BaseFeatureSet : public FeatureSetNativeComponent, // Non-const bits (fixme: clean up access to these). TouchInput* touch_input{}; - auto app_active() const { return app_active_; } + auto app_active() -> bool const { return app_active_; } private: BaseFeatureSet(); @@ -831,7 +832,6 @@ class BaseFeatureSet : public FeatureSetNativeComponent, bool have_clipboard_is_supported_{}; bool clipboard_is_supported_{}; bool app_active_set_{}; - bool app_active_{true}; bool app_suspended_{}; bool shutdown_suppress_disallowed_{}; bool tried_importing_plus_{}; @@ -844,6 +844,10 @@ class BaseFeatureSet : public FeatureSetNativeComponent, bool base_native_import_completed_{}; bool basn_log_behavior_{}; bool server_wrapper_managed_{}; + /// Main thread informs logic thread when this changes, but then logic + /// reads original value set by main. need to be sure they never read + /// stale values. + std::atomic_bool app_active_{true}; int shutdown_suppress_count_{}; }; diff --git a/src/ballistica/base/input/device/touch_input.cc b/src/ballistica/base/input/device/touch_input.cc index ab61955a..c89a7900 100644 --- a/src/ballistica/base/input/device/touch_input.cc +++ b/src/ballistica/base/input/device/touch_input.cc @@ -8,6 +8,7 @@ #include "ballistica/base/python/base_python.h" #include "ballistica/base/support/app_config.h" #include "ballistica/base/ui/ui.h" +#include "ballistica/shared/foundation/macros.h" namespace ballistica::base { @@ -47,20 +48,20 @@ void TouchInput::HandleTouchEvent(TouchEvent::Type type, void* touch, float x, switch (type) { case TouchEvent::Type::kDown: { HandleTouchDown(touch, x, y); - break; + return; } case TouchEvent::Type::kCanceled: case TouchEvent::Type::kUp: { HandleTouchUp(touch, x, y); - break; + return; } case TouchEvent::Type::kMoved: { HandleTouchMoved(touch, x, y); - break; + return; } - default: - throw Exception(); } + BA_LOG_ERROR_NATIVE_TRACE_ONCE("Unhandled touch event type " + + std::to_string(static_cast(type))); } TouchInput::TouchInput() { @@ -119,7 +120,13 @@ void TouchInput::UpdateButtons(bool new_touch) { } else if (pickup_mag == max_mag) { closest_to_pickup = true; } else { - throw Exception(); + char buffer[256]; + snprintf(buffer, sizeof(buffer), + "TouchInput closest-to logic fail; bomb_mag=%f" + " punch_mag=%f jump_mag=%f pickup_mag=%f max_mag=%f", + bomb_mag, punch_mag, jump_mag, pickup_mag, max_mag); + BA_LOG_ERROR_NATIVE_TRACE_ONCE(buffer); + closest_to_bomb = true; } if (buttons_touch_) { last_buttons_touch_time_ = g_core->GetAppTimeMillisecs(); diff --git a/src/ballistica/base/logic/logic.cc b/src/ballistica/base/logic/logic.cc index 13dfef5b..12f03435 100644 --- a/src/ballistica/base/logic/logic.cc +++ b/src/ballistica/base/logic/logic.cc @@ -691,4 +691,21 @@ void Logic::ProcessPendingWork_() { UpdatePendingWorkTimer_(); } +void Logic::OnAppActiveChanged() { + assert(g_base->InLogicThread()); + + // Note: we keep our own active state here in the logic thread and + // simply refresh it from the atomic value from the main thread here. + // There are occasions where the main thread's value flip-flops back + // and forth quickly and we'll generally skip over those this way. + auto app_active = g_base->app_active(); + if (app_active != app_active_) { + app_active_ = app_active; + + // For now just informing Python (which informs Python level app-mode). + // Can expand this to inform everyone else if needed. + g_base->python->OnAppActiveChanged(); + } +} + } // namespace ballistica::base diff --git a/src/ballistica/base/logic/logic.h b/src/ballistica/base/logic/logic.h index 32872e63..2e389214 100644 --- a/src/ballistica/base/logic/logic.h +++ b/src/ballistica/base/logic/logic.h @@ -61,6 +61,8 @@ class Logic { void OnAppShutdown(); void OnAppShutdownComplete(); + void OnAppActiveChanged(); + void OnAppModeChanged(); void DoApplyAppConfig(); @@ -118,6 +120,8 @@ class Logic { auto graphics_ready() const { return graphics_ready_; } + auto app_active() const { return app_active_; } + private: void UpdateDisplayTimeForFrameDraw_(); void UpdateDisplayTimeForHeadlessMode_(); @@ -140,6 +144,9 @@ class Logic { seconds_t recent_display_time_increments_[kDisplayTimeSampleCount]{}; int recent_display_time_increments_index_{-1}; + /// The logic thread maintains its own app-active state which is + /// driven by the app-thread's state in g_base. + bool app_active_{true}; bool app_bootstrapping_complete_{}; bool have_pending_loads_{}; bool debug_log_display_time_{}; diff --git a/src/ballistica/base/python/base_python.cc b/src/ballistica/base/python/base_python.cc index 24b9c182..a22c126e 100644 --- a/src/ballistica/base/python/base_python.cc +++ b/src/ballistica/base/python/base_python.cc @@ -613,4 +613,9 @@ auto BasePython::CanPyStringEditAdapterBeReplaced(PyObject* o) -> bool { return false; } +void BasePython::OnAppActiveChanged() { + assert(g_base->InLogicThread()); + objs().Get(BasePython::ObjID::kAppOnNativeActiveChangedCall).Call(); +} + } // namespace ballistica::base diff --git a/src/ballistica/base/python/base_python.h b/src/ballistica/base/python/base_python.h index 870da85a..3d661f7a 100644 --- a/src/ballistica/base/python/base_python.h +++ b/src/ballistica/base/python/base_python.h @@ -23,6 +23,8 @@ class BasePython { void OnScreenSizeChange(); void StepDisplayTime(); + void OnAppActiveChanged(); + void Reset(); /// Specific Python objects we hold in objs_. @@ -113,6 +115,7 @@ class BasePython { kAppDevConsoleDoRefreshTabCall, kUnsupportedControllerMessageCall, kGetV2AccountIdCall, + kAppOnNativeActiveChangedCall, kLast // Sentinel; must be at end. }; diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index 3ce2f238..a440f0af 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -49,7 +49,11 @@ static PyMethodDef PyAppNameDef = { static auto PyAppIsActive(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - if (g_base->app_active()) { + // Note: we're limiting this to the logic thread and using the logic + // thread's version of app-active here. If we ever need the main thread's + // version we'll have to do something different. + BA_PRECONDITION(g_base->InLogicThread()); + if (g_base->logic->app_active()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -1666,6 +1670,31 @@ static PyMethodDef PyGraphicsShutdownIsCompleteDef = { "(internal)\n", }; +// --------------------------- invoke_main_menu -------------------------------- + +static auto PyInvokeMainMenu(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + + BA_PRECONDITION(g_base->InLogicThread()); + if (!g_base->ui->MainMenuVisible()) { + g_base->ui->PushMainMenuPressCall(nullptr); + } + Py_RETURN_NONE; + + BA_PYTHON_CATCH; +} + +static PyMethodDef PyInvokeMainMenuDef = { + "invoke_main_menu", // name + (PyCFunction)PyInvokeMainMenu, // method + METH_NOARGS, // flags + + "invoke_main_menu() -> None\n" + "\n" + "High level call to bring up the main menu if it is not present.\n" + "\n" + "This is essentially the same as pressing the menu button on a controller.", +}; // ----------------------------------------------------------------------------- auto PythonMethodsApp::GetMethods() -> std::vector { @@ -1724,6 +1753,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector { PyAudioShutdownIsCompleteDef, PyGraphicsShutdownBeginDef, PyGraphicsShutdownIsCompleteDef, + PyInvokeMainMenuDef, }; } diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 222ca239..ebac6dba 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21739; +const int kEngineBuildNumber = 21741; const char* kEngineVersion = "1.7.32"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/ui_v1/python/ui_v1_python.cc b/src/ballistica/ui_v1/python/ui_v1_python.cc index c1a014d7..bc914d47 100644 --- a/src/ballistica/ui_v1/python/ui_v1_python.cc +++ b/src/ballistica/ui_v1/python/ui_v1_python.cc @@ -85,7 +85,6 @@ void UIV1Python::ShowURL(const std::string& url) { } void UIV1Python::HandleDeviceMenuPress(base::InputDevice* device) { - assert(device); assert(objs().Exists(ObjID::kDeviceMenuPressCall)); // Ignore if input is locked or we've not yet got a root widget. diff --git a/src/meta/babasemeta/pyembed/binding_base_app.py b/src/meta/babasemeta/pyembed/binding_base_app.py index d5fcf519..da1cd286 100644 --- a/src/meta/babasemeta/pyembed/binding_base_app.py +++ b/src/meta/babasemeta/pyembed/binding_base_app.py @@ -18,6 +18,7 @@ values = [ app.on_native_unsuspend, # kAppOnNativeUnsuspendCall app.on_native_shutdown, # kAppOnNativeShutdownCall app.on_native_shutdown_complete, # kAppOnNativeShutdownCompleteCall + app.on_native_active_changed, # kAppOnNativeActiveChangedCall app.read_config, # kAppReadConfigCall app.devconsole.do_refresh_tab, # kAppDevConsoleDoRefreshTabCall ]