mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-19 21:37:57 +08:00
lots of dev console terminal improvements
This commit is contained in:
parent
f0ebe2bce8
commit
11212bfb52
88
.efrocachemap
generated
88
.efrocachemap
generated
@ -4056,50 +4056,50 @@
|
||||
"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": "671499f10be5561b64b7c1e8551f71bc",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "8834461aaef9d915828b460426bb16b6",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9be5746f3cdb8fdbeb01c3fba0f3cd04",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1a4e1fb4230ffe937bc11890943bab67",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "809fd63da80c54076100f18c8cde6ba8",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "bb3574370f0d601abb9443dc2285689b",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2b1d99684649040257bfe95b0c5a21d9",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3a4eaac355dc1ed691aa946f9470fd80",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0cdebb143458f5248efb0227e875d5d4",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "a4eae535e631ac6d0aaa3fa9203656cf",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d2dcb9d5f1201e98ba83b547fb7a317e",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6cf3c416280b71e5b16516cfb063b198",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a01e3ef9ec790c0bc385995e598c18dd",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "427e518fd557950c4f8fec0b8fca3c86",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b6a2f1c128e3b1c035eff76f38100566",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "deb872ab495ab8e713ba564b7bc4f169",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c647c1e19b2c3a2bee028ef8215945d5",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ce133f1e838b8b6d3b9b4fd7c516d5d8",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "f41eb8f74e5cf7a36cc8bbda1eef1933",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "00ae0c9d9351140edc42ed18b719a2bf",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "5bd8bcd68e03939501d192b7cda55d64",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a8545c0c985eef9219c351773c5c6127",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "5bd8bcd68e03939501d192b7cda55d64",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a8545c0c985eef9219c351773c5c6127",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1e2c088713c47ff47d9aa312ebb0bd1a",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "e6bbe6c564c65cb498edc58daec1e084",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1e2c088713c47ff47d9aa312ebb0bd1a",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "e6bbe6c564c65cb498edc58daec1e084",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "98df65aba607e74eb5c0c7305903ac29",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "3314d791a9ab37ea81be824460c63d14",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "eda80e0bcb2332fb400e4487aa821fda",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ae70908e8821b275a7c62541288761c3",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4dcc80f1087a342df7f0e13225c6a0d8",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "e83c284f0ee5c9bf9e02bdd5e83de604",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "92bbe105f7bbff92ebe621710bb13629",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f3c9b10ab0dbc35214b20c3323255ea1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "df9efe46d688a585157edfe5d3b9e912",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3c76a27db96c7c277682430ec980d9ce",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6e54cc75974a155e910b1095f8f559a8",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "d097531acccd231becb2a2b5bb1d2f23",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "35b551aae90a7d75f75237db93544279",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d6081f21ed1100f44aeb4c36f7d28680",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1d181331c45918c6d7e71630430aa011",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "1b7671e483412e63304755961e328d3f",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8ee7a3b0674e89d286e6c28b5992da30",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a2dd4ce5321e0127bdc9e7a1c4354aa6",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d16e4cb4509fa427772c1894cc2db29d",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "7e5deafeec61b8520a4d22a5eef80f03",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "370fb623fa824ffad97750de5d1ff844",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "cf34e338f3c7d58afc70dc6742671584",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6a075263de9be1db381eeb5ea8874ba9",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0eef1925d2cf63eecad74e6932f624b1",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "de533e42f98a6081e96d1f7e96306fcd",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "91640f1b899fadf077d6844efdf6d37c",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c29e6e391970ede95bd90b9dec830ecc",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "2c1391f2da73fe58a2e1a815106eebf5",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "90532e99fc87ef4a8a9b1f5d9737d008",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a7bd331931da44fe268f4adda5cddb9b",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b46b30262b58e96e994211631b470efb",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "6cc41e3401daf2e72b884fbfe0fe92b3",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b46b30262b58e96e994211631b470efb",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "6cc41e3401daf2e72b884fbfe0fe92b3",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "b915f8a091643d99fd28e8d636063185",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "cb5de031162e4ff0cb5f030adf331a12",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "b915f8a091643d99fd28e8d636063185",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "cb5de031162e4ff0cb5f030adf331a12",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "be2a7322e1ddbb38ba0d22dd94a565e3",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "b257bbc06d82fc912653806c01a42c15",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "611631809a455737d7d9c0b04c89aa6b",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "bfe702cdf9cd260ab8cb4593afc6a3af",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4a367d3b2354d60259cc68fa25004eb0",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "fc5d98c16dbb42846ef653dc860f4508",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "683fafa75e39f0b33ef22cff53b124e6",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "1f9099d422aaed13d038e64b629e7827",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "76ee096dfbb8993cbb05a3425e429e0a",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "719478dd5e71b7096801f6bd0b701b4f",
|
||||
"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": "6df0f34207346d89a72924249ddd4706",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
### 1.7.28 (build 21516, api 8, 2023-10-26)
|
||||
### 1.7.28 (build 21522, api 8, 2023-10-26)
|
||||
|
||||
- Massively cleaned up code related to rendering and window systems (OpenGL,
|
||||
SDL, etc). This code had been growing into a nasty tangle for 15 years
|
||||
@ -164,6 +164,9 @@
|
||||
- Dev console no longer claims key events unless the Python tab is showing and
|
||||
there is a hardware keyboard attached. This allows showing dev console tabs
|
||||
above gameplay without interfering with it.
|
||||
- Added clipboard paste support to the dev console python terminal.
|
||||
- Added various text editing functionality to the dev console python terminal
|
||||
(cursor movement, deleting chars and words, etc.)
|
||||
|
||||
### 1.7.27 (build 21282, api 8, 2023-08-30)
|
||||
|
||||
|
||||
@ -436,6 +436,8 @@ set(BALLISTICA_SOURCES
|
||||
${BA_SRC_ROOT}/ballistica/base/support/app_config.cc
|
||||
${BA_SRC_ROOT}/ballistica/base/support/app_config.h
|
||||
${BA_SRC_ROOT}/ballistica/base/support/app_timer.h
|
||||
${BA_SRC_ROOT}/ballistica/base/support/base_build_switches.cc
|
||||
${BA_SRC_ROOT}/ballistica/base/support/base_build_switches.h
|
||||
${BA_SRC_ROOT}/ballistica/base/support/classic_soft.h
|
||||
${BA_SRC_ROOT}/ballistica/base/support/context.cc
|
||||
${BA_SRC_ROOT}/ballistica/base/support/context.h
|
||||
|
||||
@ -428,6 +428,8 @@
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\app_config.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\app_config.h" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\context.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\context.h" />
|
||||
|
||||
@ -718,6 +718,12 @@
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@ -423,6 +423,8 @@
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\app_config.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\app_config.h" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\context.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\context.h" />
|
||||
|
||||
@ -718,6 +718,12 @@
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h">
|
||||
<Filter>ballistica\base\support</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21516
|
||||
TARGET_BALLISTICA_BUILD = 21522
|
||||
TARGET_BALLISTICA_VERSION = '1.7.28'
|
||||
|
||||
|
||||
|
||||
@ -2,64 +2,17 @@
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
|
||||
#if BA_OSTYPE_ANDROID // Remove conditional once android sources are public.
|
||||
#include "ballistica/base/app_adapter/app_adapter_android.h"
|
||||
#endif
|
||||
#include "ballistica/base/app_adapter/app_adapter_apple.h"
|
||||
#include "ballistica/base/app_adapter/app_adapter_headless.h"
|
||||
#include "ballistica/base/app_adapter/app_adapter_sdl.h"
|
||||
#include "ballistica/base/app_adapter/app_adapter_vr.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/networking/network_reader.h"
|
||||
#include "ballistica/base/networking/networking.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/support/stress_test.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/python/python.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
auto AppAdapter::Create() -> AppAdapter* {
|
||||
assert(g_core);
|
||||
|
||||
// TEMP - need to init sdl on our legacy mac build even though its not
|
||||
// technically an SDL app. Kill this once the old mac build is gone.
|
||||
#if BA_LEGACY_MACOS_BUILD
|
||||
AppAdapterSDL::InitSDL();
|
||||
#endif
|
||||
|
||||
AppAdapter* app_adapter{};
|
||||
|
||||
#if BA_HEADLESS_BUILD
|
||||
app_adapter = new AppAdapterHeadless();
|
||||
#elif BA_OSTYPE_ANDROID
|
||||
app_adapter = new AppAdapterAndroid();
|
||||
#elif BA_XCODE_BUILD
|
||||
app_adapter = new AppAdapterApple();
|
||||
#elif BA_RIFT_BUILD
|
||||
// Rift build can spin up in either VR or regular mode.
|
||||
if (g_core->vr_mode) {
|
||||
app_adapter = new AppAdapterVR();
|
||||
} else {
|
||||
app_adapter = new AppAdapterSDL();
|
||||
}
|
||||
#elif BA_CARDBOARD_BUILD
|
||||
app_adapter = new AppAdapterVR();
|
||||
#elif BA_SDL_BUILD
|
||||
app_adapter = new AppAdapterSDL();
|
||||
#else
|
||||
#error No app adapter defined for this build.
|
||||
#endif
|
||||
|
||||
assert(app_adapter);
|
||||
return app_adapter;
|
||||
}
|
||||
|
||||
AppAdapter::AppAdapter() = default;
|
||||
|
||||
AppAdapter::~AppAdapter() = default;
|
||||
|
||||
@ -15,8 +15,7 @@ namespace ballistica::base {
|
||||
/// all might share the same CorePlatform and BasePlatform classes.
|
||||
class AppAdapter {
|
||||
public:
|
||||
/// Instantiate the AppAdapter subclass for the current build.
|
||||
static auto Create() -> AppAdapter*;
|
||||
AppAdapter();
|
||||
|
||||
/// Called in the main thread when the app is being started.
|
||||
virtual void OnMainThreadStartApp();
|
||||
@ -224,7 +223,6 @@ class AppAdapter {
|
||||
auto ClipboardGetText() -> std::string;
|
||||
|
||||
protected:
|
||||
AppAdapter();
|
||||
virtual ~AppAdapter();
|
||||
|
||||
/// Push a raw pointer Runnable to the platform's 'main' thread. The main
|
||||
|
||||
@ -247,38 +247,38 @@ auto AppAdapterApple::GetKeyRepeatInterval() -> float {
|
||||
}
|
||||
|
||||
auto AppAdapterApple::DoClipboardIsSupported() -> bool {
|
||||
#if BA_XCODE_BUILD
|
||||
#if BA_OSTYPE_MACOS
|
||||
return BallisticaKit::CocoaFromCpp::ClipboardIsSupported();
|
||||
#else
|
||||
return CorePlatform::DoClipboardIsSupported();
|
||||
return AppAdapter::DoClipboardIsSupported();
|
||||
#endif
|
||||
}
|
||||
|
||||
auto AppAdapterApple::DoClipboardHasText() -> bool {
|
||||
#if BA_XCODE_BUILD
|
||||
#if BA_OSTYPE_MACOS
|
||||
return BallisticaKit::CocoaFromCpp::ClipboardHasText();
|
||||
#else
|
||||
return CorePlatform::DoClipboardHasText();
|
||||
return AppAdapter::DoClipboardHasText();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppAdapterApple::DoClipboardSetText(const std::string& text) {
|
||||
#if BA_XCODE_BUILD
|
||||
#if BA_OSTYPE_MACOS
|
||||
BallisticaKit::CocoaFromCpp::ClipboardSetText(text);
|
||||
#else
|
||||
CorePlatform::DoClipboardSetText(text);
|
||||
AppAdapter::DoClipboardSetText(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto AppAdapterApple::DoClipboardGetText() -> std::string {
|
||||
#if BA_XCODE_BUILD
|
||||
#if BA_OSTYPE_MACOS
|
||||
auto contents = BallisticaKit::CocoaFromCpp::ClipboardGetText();
|
||||
if (contents) {
|
||||
return std::string(contents.get());
|
||||
}
|
||||
throw Exception("No text on clipboard.");
|
||||
#else
|
||||
return CorePlatform::DoClipboardGetText();
|
||||
return AppAdapter::DoClipboardGetText();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -807,23 +807,9 @@ void AppAdapterSDL::CursorPositionForDraw(float* x, float* y) {
|
||||
auto AppAdapterSDL::FullscreenControlAvailable() const -> bool { return true; }
|
||||
auto AppAdapterSDL::FullscreenControlKeyShortcut() const
|
||||
-> std::optional<std::string> {
|
||||
if (g_buildconfig.ostype_windows()) {
|
||||
// On Windows we support F11 and Alt+Enter to toggle fullscreen. Let's
|
||||
// mention Alt+Enter which seems like it might be more commonly used
|
||||
return "Alt+Enter";
|
||||
}
|
||||
if (g_buildconfig.ostype_macos()) {
|
||||
// The Mac+SDL situation is a bit of a mess. By default, there is 'Enter
|
||||
// Full Screen' in the window menu which is mapped to fn-F, but that
|
||||
// will only work if a window was created in SDL as windowed. If we
|
||||
// fullscreen that window and restart the app, we'll then have a *real*
|
||||
// fullscreen sdl window and that shortcut won't work anymore. So to
|
||||
// keep things consistent we advertise ctrl-f which we always handle
|
||||
// ourselves. Maybe this situation will be cleaned up in SDL 3, but its
|
||||
// not a huge deal anyway since our Cocoa Mac version behaves cleanly.
|
||||
return "Ctrl+F";
|
||||
}
|
||||
return {};
|
||||
// On our SDL build we support F11 and Alt+Enter to toggle fullscreen.
|
||||
// Let's mention Alt+Enter which seems like it might be more commonly used
|
||||
return "Alt+Enter";
|
||||
};
|
||||
|
||||
auto AppAdapterSDL::SupportsVSync() -> bool const { return true; }
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include "ballistica/base/assets/asset.h"
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/support/huffman.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
|
||||
|
||||
@ -20,12 +20,12 @@
|
||||
#include "ballistica/base/python/class/python_class_feature_set_data.h"
|
||||
#include "ballistica/base/python/support/python_context_call.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/support/base_build_switches.h"
|
||||
#include "ballistica/base/support/huffman.h"
|
||||
#include "ballistica/base/support/plus_soft.h"
|
||||
#include "ballistica/base/support/stdio_console.h"
|
||||
#include "ballistica/base/support/stress_test.h"
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/base/ui/ui_delegate.h"
|
||||
#include "ballistica/core/python/core_python.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
@ -39,7 +39,7 @@ core::CoreFeatureSet* g_core{};
|
||||
BaseFeatureSet* g_base{};
|
||||
|
||||
BaseFeatureSet::BaseFeatureSet()
|
||||
: app_adapter{AppAdapter::Create()},
|
||||
: app_adapter{BaseBuildSwitches::CreateAppAdapter()},
|
||||
app_config{new AppConfig()},
|
||||
app_mode_{AppModeEmpty::GetSingleton()},
|
||||
assets{new Assets()},
|
||||
@ -51,7 +51,7 @@ BaseFeatureSet::BaseFeatureSet()
|
||||
bg_dynamics_server{g_core->HeadlessMode() ? nullptr
|
||||
: new BGDynamicsServer},
|
||||
context_ref{new ContextRef(nullptr)},
|
||||
graphics{Graphics::Create()},
|
||||
graphics{BaseBuildSwitches::CreateGraphics()},
|
||||
graphics_server{new GraphicsServer()},
|
||||
huffman{new Huffman()},
|
||||
input{new Input()},
|
||||
@ -59,7 +59,7 @@ BaseFeatureSet::BaseFeatureSet()
|
||||
network_reader{new NetworkReader()},
|
||||
network_writer{new NetworkWriter()},
|
||||
networking{new Networking()},
|
||||
platform{BasePlatform::Create()},
|
||||
platform{BaseBuildSwitches::CreatePlatform()},
|
||||
python{new BasePython()},
|
||||
stdio_console{g_buildconfig.enable_stdio_console() ? new StdioConsole()
|
||||
: nullptr},
|
||||
|
||||
@ -5,28 +5,23 @@
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/dynamics/bg/bg_dynamics.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
#include "ballistica/base/graphics/component/post_process_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/component/special_component.h"
|
||||
#include "ballistica/base/graphics/component/sprite_component.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/graphics/graphics_vr.h"
|
||||
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
|
||||
#include "ballistica/base/graphics/support/camera.h"
|
||||
#include "ballistica/base/graphics/support/net_graph.h"
|
||||
#include "ballistica/base/graphics/text/text_graphics.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/support/python_context_call.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/core/core.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/shared/python/python.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -36,14 +31,6 @@ const float kProgressBarZDepth{0.0f};
|
||||
const int kProgressBarFadeTime{500};
|
||||
const float kDebugImgZDepth{-0.04f};
|
||||
|
||||
auto Graphics::Create() -> Graphics* {
|
||||
#if BA_VR_BUILD
|
||||
return new GraphicsVR();
|
||||
#else
|
||||
return new Graphics();
|
||||
#endif
|
||||
}
|
||||
|
||||
auto Graphics::IsShaderTransparent(ShadingType c) -> bool {
|
||||
switch (c) {
|
||||
case ShadingType::kSimpleColorTransparent:
|
||||
@ -231,11 +218,9 @@ auto Graphics::VSyncFromAppConfig() -> VSyncRequest {
|
||||
}
|
||||
|
||||
auto Graphics::GraphicsQualityFromAppConfig() -> GraphicsQualityRequest {
|
||||
// Graphics quality.
|
||||
std::string gqualstr =
|
||||
g_base->app_config->Resolve(AppConfig::StringID::kGraphicsQuality);
|
||||
GraphicsQualityRequest graphics_quality_requested;
|
||||
|
||||
if (gqualstr == "Auto") {
|
||||
graphics_quality_requested = GraphicsQualityRequest::kAuto;
|
||||
} else if (gqualstr == "Higher") {
|
||||
@ -361,33 +346,36 @@ auto Graphics::GetShadowDensity(float x, float y, float z) -> float {
|
||||
|
||||
class Graphics::ScreenMessageEntry {
|
||||
public:
|
||||
ScreenMessageEntry(std::string s_in, bool align_left_in, uint32_t c,
|
||||
const Vector3f& color_in, TextureAsset* texture_in,
|
||||
TextureAsset* tint_texture_in, const Vector3f& tint_in,
|
||||
const Vector3f& tint2_in)
|
||||
: align_left(align_left_in),
|
||||
ScreenMessageEntry(std::string text, bool top_style, uint32_t c,
|
||||
const Vector3f& color, TextureAsset* texture,
|
||||
TextureAsset* tint_texture, const Vector3f& tint,
|
||||
const Vector3f& tint2)
|
||||
: top_style(top_style),
|
||||
creation_time(c),
|
||||
s_raw(std::move(s_in)),
|
||||
color(color_in),
|
||||
texture(texture_in),
|
||||
tint_texture(tint_texture_in),
|
||||
tint(tint_in),
|
||||
tint2(tint2_in) {}
|
||||
s_raw(std::move(text)),
|
||||
color(color),
|
||||
texture(texture),
|
||||
tint_texture(tint_texture),
|
||||
tint(tint),
|
||||
tint2(tint2) {}
|
||||
auto GetText() -> TextGroup&;
|
||||
void UpdateTranslation();
|
||||
bool align_left;
|
||||
bool top_style;
|
||||
uint32_t creation_time;
|
||||
Vector3f color;
|
||||
Vector3f tint;
|
||||
Vector3f tint2;
|
||||
std::string s_raw;
|
||||
std::string s_translated;
|
||||
float str_width{};
|
||||
float str_height{};
|
||||
Object::Ref<TextureAsset> texture;
|
||||
Object::Ref<TextureAsset> tint_texture;
|
||||
float v_smoothed{};
|
||||
bool translation_dirty{true};
|
||||
bool mesh_dirty{true};
|
||||
millisecs_t smooth_time{};
|
||||
Object::Ref<NinePatchMesh> shadow_mesh_;
|
||||
|
||||
private:
|
||||
Object::Ref<TextGroup> s_mesh_;
|
||||
@ -578,7 +566,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
SimpleComponent c(pass);
|
||||
c.SetTransparent(true);
|
||||
c.SetTexture(
|
||||
g_base->assets->SysTexture(SysTextureID::kSoftRectVertical));
|
||||
// g_base->assets->SysTexture(SysTextureID::kSoftRectVertical));
|
||||
g_base->assets->SysTexture(SysTextureID::kShadowSharp));
|
||||
|
||||
float screen_width = g_base->graphics->screen_virtual_width();
|
||||
|
||||
@ -591,6 +580,10 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
// Update the translation if need be.
|
||||
i->UpdateTranslation();
|
||||
|
||||
// Don't actually need the text just yet but need shadow mesh
|
||||
// which is calculated as part of it.
|
||||
i->GetText();
|
||||
|
||||
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
|
||||
youngest_age = std::min(youngest_age, age);
|
||||
float s_extra = 1.0f;
|
||||
@ -609,9 +602,9 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
}
|
||||
a *= 0.8f;
|
||||
|
||||
if (vr) {
|
||||
a *= 0.8f;
|
||||
}
|
||||
// if (vr) {
|
||||
// a *= 0.8f;
|
||||
// }
|
||||
|
||||
if (i->translation_dirty) {
|
||||
BA_LOG_ONCE(
|
||||
@ -619,10 +612,9 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
"Found dirty translation on screenmessage draw pass 1; raw="
|
||||
+ i->s_raw);
|
||||
}
|
||||
float str_height =
|
||||
g_base->text_graphics->GetStringHeight(i->s_translated.c_str());
|
||||
float str_width =
|
||||
g_base->text_graphics->GetStringWidth(i->s_translated.c_str());
|
||||
|
||||
float str_height = i->str_height;
|
||||
float str_width = i->str_width;
|
||||
|
||||
if ((str_width * scale) > (screen_width - 40)) {
|
||||
s_extra *= ((screen_width - 40) / (str_width * scale));
|
||||
@ -639,7 +631,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
if (age < 100) {
|
||||
fade = 1.0f;
|
||||
} else {
|
||||
fade = std::max(0.0f, (200.0f - static_cast<float>(age)) / 100.0f);
|
||||
fade = std::max(0.07f, (200.0f - static_cast<float>(age)) / 100.0f);
|
||||
}
|
||||
c.SetColor(r * fade, g * fade, b * fade, a);
|
||||
|
||||
@ -663,22 +655,28 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
|
||||
c.Translate(screen_width * 0.5f, i->v_smoothed,
|
||||
vr ? 60 : kScreenMessageZDepth);
|
||||
if (vr) {
|
||||
// Let's drop down a bit in vr mode.
|
||||
c.Translate(0, -10.0f, 0);
|
||||
c.Scale((str_width + 60) * scale * s_extra,
|
||||
(str_height + 20) * scale * s_extra);
|
||||
|
||||
// Align our bottom with where we just scaled from.
|
||||
c.Translate(0, 0.5f, 0);
|
||||
} else {
|
||||
c.Scale((str_width + 110) * scale * s_extra,
|
||||
(str_height + 40) * scale * s_extra);
|
||||
// if (vr) {
|
||||
// // Let's drop down a bit in vr mode.
|
||||
// // c.Translate(0, -10.0f, 0);
|
||||
// // c.Scale((str_width + 60) * scale * s_extra,
|
||||
// // (str_height + 20) * scale * s_extra);
|
||||
// c.Scale(scale * s_extra, scale * s_extra);
|
||||
|
||||
// // Align our bottom with where we just scaled from.
|
||||
// c.Translate(0, 0.5f, 0);
|
||||
{
|
||||
// c.Scale((str_width + 110) * scale * s_extra,
|
||||
// (str_height + 40) * scale * s_extra);
|
||||
c.Scale(scale * s_extra, scale * s_extra);
|
||||
c.Translate(0, 20);
|
||||
|
||||
// Align our bottom with where we just scaled from.
|
||||
c.Translate(0, 0.5f, 0);
|
||||
}
|
||||
c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
|
||||
// c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
|
||||
assert(i->shadow_mesh_.Exists());
|
||||
c.DrawMesh(i->shadow_mesh_.Get());
|
||||
}
|
||||
|
||||
v += scale * (36 + str_height);
|
||||
@ -721,10 +719,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
|
||||
"Found dirty translation on screenmessage draw pass 2; raw="
|
||||
+ i->s_raw);
|
||||
}
|
||||
float str_height =
|
||||
g_base->text_graphics->GetStringHeight(i->s_translated.c_str());
|
||||
float str_width =
|
||||
g_base->text_graphics->GetStringWidth(i->s_translated.c_str());
|
||||
float str_height = i->str_height;
|
||||
float str_width = i->str_width;
|
||||
|
||||
if ((str_width * scale) > (screen_width - 40)) {
|
||||
s_extra *= ((screen_width - 40) / (str_width * scale));
|
||||
@ -1964,8 +1960,28 @@ auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& {
|
||||
if (mesh_dirty) {
|
||||
s_mesh_->SetText(
|
||||
s_translated,
|
||||
align_left ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter,
|
||||
top_style ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter,
|
||||
TextMesh::VAlign::kBottom);
|
||||
|
||||
str_width = g_base->text_graphics->GetStringWidth(s_translated.c_str());
|
||||
str_height = g_base->text_graphics->GetStringHeight(s_translated.c_str());
|
||||
|
||||
if (!top_style) {
|
||||
float x_extend = 40.0f;
|
||||
float y_extend = 40.0f;
|
||||
float y_offset = -10.0f;
|
||||
float corner_radius = 60.0f;
|
||||
float width_fin = str_width + x_extend * 2.0f;
|
||||
float height_fin = str_height + y_extend * 2.0f;
|
||||
float x_border =
|
||||
NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin);
|
||||
float y_border =
|
||||
NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin);
|
||||
shadow_mesh_ = Object::New<NinePatchMesh>(
|
||||
-0.5f * width_fin, -y_extend + y_offset, 0.0f, width_fin, height_fin,
|
||||
x_border, y_border, x_border, y_border);
|
||||
}
|
||||
|
||||
mesh_dirty = false;
|
||||
}
|
||||
return *s_mesh_;
|
||||
|
||||
@ -53,8 +53,7 @@ const float kCursorZDepth{0.9f};
|
||||
// Client class for graphics operations (used from the logic thread).
|
||||
class Graphics {
|
||||
public:
|
||||
/// Instantiate the Graphics subclass for the current build.
|
||||
static auto Create() -> Graphics*;
|
||||
Graphics();
|
||||
|
||||
void OnAppStart();
|
||||
void OnAppPause();
|
||||
@ -370,7 +369,6 @@ class Graphics {
|
||||
protected:
|
||||
class ScreenMessageEntry;
|
||||
|
||||
Graphics();
|
||||
virtual ~Graphics();
|
||||
virtual void DoDrawFade(FrameDef* frame_def, float amt);
|
||||
static void CalcVirtualRes_(float* x, float* y);
|
||||
|
||||
@ -18,7 +18,7 @@ class NinePatchMesh : public MeshIndexedSimpleFull {
|
||||
|
||||
/// Calculate a border value for a NinePatchMesh based on dimensions and a
|
||||
/// desired max corner radius. For calculating left or right borders,
|
||||
/// matching_dimension should be width and other_dimension should be
|
||||
/// `matching_dimension` should be width and `other_dimension` should be
|
||||
/// height. For top or bottom borders it is the opposite.
|
||||
static auto BorderForRadius(float corner_radius, float matching_dimension,
|
||||
float other_dimension) -> float {
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/shared/foundation/object.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -12,10 +12,8 @@
|
||||
#include "ballistica/base/input/device/touch_input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/buildconfig/buildconfig_common.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
|
||||
@ -838,6 +836,13 @@ void Input::PushTextInputEvent(const std::string& text) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore back-tick and tilde because we use that key to toggle the console.
|
||||
// FIXME: Perhaps should allow typing it if some control-character is
|
||||
// held?
|
||||
if (text == "`" || text == "~") {
|
||||
return;
|
||||
}
|
||||
|
||||
// We try to handle char filtering here (to keep it consistent across
|
||||
// platforms) but make a stink if they sent us something that we can't
|
||||
// at least translate to unicode.
|
||||
@ -1065,17 +1070,9 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
|
||||
// Explicitly handle fullscreen-toggles in some cases.
|
||||
if (g_base->app_adapter->FullscreenControlAvailable()) {
|
||||
bool do_toggle{};
|
||||
// On our Mac SDL builds we support ctrl+F for toggling fullscreen.
|
||||
// On our nice Cocoa build, fullscreening happens magically through the
|
||||
// view menu fullscreen control's shortcut.
|
||||
if (g_buildconfig.ostype_macos() && !g_buildconfig.xcode_build()) {
|
||||
if (keysym.sym == SDLK_f && ((keysym.mod & KMOD_CTRL))) {
|
||||
do_toggle = true;
|
||||
}
|
||||
}
|
||||
// On Windows and Linux we support both F11 and Alt+Enter for toggling
|
||||
// On our SDL builds we support both F11 and Alt+Enter for toggling
|
||||
// fullscreen.
|
||||
if (g_buildconfig.ostype_windows() || g_buildconfig.ostype_linux()) {
|
||||
if (g_buildconfig.sdl_build()) {
|
||||
if ((keysym.sym == SDLK_F11
|
||||
|| (keysym.sym == SDLK_RETURN && ((keysym.mod & KMOD_ALT))))) {
|
||||
do_toggle = true;
|
||||
@ -1089,6 +1086,19 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
|
||||
}
|
||||
}
|
||||
|
||||
// Ctrl-V or Cmd-V sends paste commands to the console or any interested
|
||||
// text fields.
|
||||
if (keysym.sym == SDLK_v
|
||||
&& ((keysym.mod & KMOD_CTRL) || (keysym.mod & KMOD_GUI))) {
|
||||
if (auto* console = g_base->ui->dev_console()) {
|
||||
if (console->PasteFromClipboard()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_base->ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste));
|
||||
return;
|
||||
}
|
||||
|
||||
// Dev Console.
|
||||
if (auto* console = g_base->ui->dev_console()) {
|
||||
if (keysym.sym == SDLK_BACKQUOTE || keysym.sym == SDLK_F2) {
|
||||
@ -1102,13 +1112,6 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
|
||||
}
|
||||
}
|
||||
|
||||
// Ctrl-V or Cmd-V sends paste commands to any interested text fields.
|
||||
if (keysym.sym == SDLK_v
|
||||
&& ((keysym.mod & KMOD_CTRL) || (keysym.mod & KMOD_GUI))) {
|
||||
g_base->ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste));
|
||||
return;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
|
||||
switch (keysym.sym) {
|
||||
|
||||
@ -16,73 +16,8 @@
|
||||
#include "ballistica/shared/python/python.h"
|
||||
#include "ballistica/shared/python/python_sys.h"
|
||||
|
||||
// ------------------------- PLATFORM SELECTION --------------------------------
|
||||
|
||||
// This ugly chunk of macros simply pulls in the correct platform class header
|
||||
// for each platform and defines the actual class g_base->platform will be.
|
||||
|
||||
// Android ---------------------------------------------------------------------
|
||||
|
||||
#if BA_OSTYPE_ANDROID
|
||||
#if BA_GOOGLE_BUILD
|
||||
#include "ballistica/base/platform/android/google/base_plat_andr_google.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroidGoogle
|
||||
#elif BA_AMAZON_BUILD
|
||||
#include "ballistica/base/platform/android/amazon/base_plat_andr_amazon.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroidAmazon
|
||||
#elif BA_CARDBOARD_BUILD
|
||||
#include "ballistica/base/platform/android/cardboard/base_pl_an_cardboard.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroidCardboard
|
||||
#else // Generic android.
|
||||
#include "ballistica/base/platform/android/base_platform_android.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroid
|
||||
#endif // (Android subplatform)
|
||||
|
||||
// Apple -----------------------------------------------------------------------
|
||||
|
||||
#elif BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS
|
||||
#include "ballistica/base/platform/apple/base_platform_apple.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformApple
|
||||
|
||||
// Windows ---------------------------------------------------------------------
|
||||
|
||||
#elif BA_OSTYPE_WINDOWS
|
||||
#if BA_RIFT_BUILD
|
||||
#include "ballistica/base/platform/windows/base_platform_windows_oculus.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformWindowsOculus
|
||||
#else // generic windows
|
||||
#include "ballistica/base/platform/windows/base_platform_windows.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformWindows
|
||||
#endif // windows subtype
|
||||
|
||||
// Linux -----------------------------------------------------------------------
|
||||
|
||||
#elif BA_OSTYPE_LINUX
|
||||
#include "ballistica/base/platform/linux/base_platform_linux.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformLinux
|
||||
#else
|
||||
|
||||
// Generic ---------------------------------------------------------------------
|
||||
|
||||
#define BA_PLATFORM_CLASS BasePlatform
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------- END PLATFORM SELECTION ------------------------------
|
||||
|
||||
#ifndef BA_PLATFORM_CLASS
|
||||
#error no BA_PLATFORM_CLASS defined for this platform
|
||||
#endif
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
auto BasePlatform::Create() -> BasePlatform* {
|
||||
auto platform = new BA_PLATFORM_CLASS();
|
||||
platform->PostInit();
|
||||
assert(platform->ran_base_post_init_);
|
||||
return platform;
|
||||
}
|
||||
|
||||
BasePlatform::BasePlatform() = default;
|
||||
|
||||
void BasePlatform::PostInit() {
|
||||
|
||||
@ -15,8 +15,12 @@ namespace ballistica::base {
|
||||
/// with a single platform (Windows, Mac, etc.).
|
||||
class BasePlatform {
|
||||
public:
|
||||
/// Instantiate the CorePlatform subclass for the current build.
|
||||
static auto Create() -> BasePlatform*;
|
||||
BasePlatform();
|
||||
|
||||
/// Called after our singleton has been instantiated. Any construction
|
||||
/// functionality requiring virtual functions resolving to their final
|
||||
/// class versions can go here.
|
||||
virtual void PostInit();
|
||||
|
||||
#pragma mark APP EVENTS / LIFECYCLE --------------------------------------------
|
||||
|
||||
@ -95,6 +99,8 @@ class BasePlatform {
|
||||
/// Must be called in the logic thread.
|
||||
void StringEditorCancel();
|
||||
|
||||
auto ran_base_post_init() const { return ran_base_post_init_; }
|
||||
|
||||
protected:
|
||||
/// Pop up a text edit dialog.
|
||||
virtual void DoInvokeStringEditor(const std::string& title,
|
||||
@ -107,15 +113,9 @@ class BasePlatform {
|
||||
/// Make a purchase.
|
||||
virtual void DoPurchase(const std::string& item);
|
||||
|
||||
BasePlatform();
|
||||
virtual ~BasePlatform();
|
||||
|
||||
private:
|
||||
/// Called after our singleton has been instantiated. Any construction
|
||||
/// functionality requiring virtual functions resolving to their final
|
||||
/// class versions can go here.
|
||||
virtual void PostInit();
|
||||
|
||||
bool ran_base_post_init_ : 1 {};
|
||||
PythonRef string_edit_adapter_{};
|
||||
std::string public_device_uuid_;
|
||||
|
||||
120
src/ballistica/base/support/base_build_switches.cc
Normal file
120
src/ballistica/base/support/base_build_switches.cc
Normal file
@ -0,0 +1,120 @@
|
||||
// Released under the MIT License. See LICENSE for details.
|
||||
|
||||
#include "ballistica/base/support/base_build_switches.h"
|
||||
|
||||
#if BA_OSTYPE_ANDROID
|
||||
#include "ballistica/base/app_adapter/app_adapter_android.h"
|
||||
#endif
|
||||
#include "ballistica/base/app_adapter/app_adapter_apple.h"
|
||||
#include "ballistica/base/app_adapter/app_adapter_headless.h"
|
||||
#include "ballistica/base/app_adapter/app_adapter_sdl.h"
|
||||
#include "ballistica/base/app_adapter/app_adapter_vr.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
#include "ballistica/base/graphics/graphics_vr.h"
|
||||
|
||||
// ------------------------- PLATFORM SELECTION --------------------------------
|
||||
|
||||
// This ugly chunk of macros simply pulls in the correct platform class header
|
||||
// for each platform and defines the actual class g_base->platform will be.
|
||||
|
||||
// Android ---------------------------------------------------------------------
|
||||
|
||||
#if BA_OSTYPE_ANDROID
|
||||
#if BA_GOOGLE_BUILD
|
||||
#include "ballistica/base/platform/android/google/base_plat_andr_google.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroidGoogle
|
||||
#elif BA_AMAZON_BUILD
|
||||
#include "ballistica/base/platform/android/amazon/base_plat_andr_amazon.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroidAmazon
|
||||
#elif BA_CARDBOARD_BUILD
|
||||
#include "ballistica/base/platform/android/cardboard/base_pl_an_cardboard.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroidCardboard
|
||||
#else // Generic android.
|
||||
#include "ballistica/base/platform/android/base_platform_android.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformAndroid
|
||||
#endif // (Android subplatform)
|
||||
|
||||
// Apple -----------------------------------------------------------------------
|
||||
|
||||
#elif BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS
|
||||
#include "ballistica/base/platform/apple/base_platform_apple.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformApple
|
||||
|
||||
// Windows ---------------------------------------------------------------------
|
||||
|
||||
#elif BA_OSTYPE_WINDOWS
|
||||
#if BA_RIFT_BUILD
|
||||
#include "ballistica/base/platform/windows/base_platform_windows_oculus.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformWindowsOculus
|
||||
#else // generic windows
|
||||
#include "ballistica/base/platform/windows/base_platform_windows.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformWindows
|
||||
#endif // windows subtype
|
||||
|
||||
// Linux -----------------------------------------------------------------------
|
||||
|
||||
#elif BA_OSTYPE_LINUX
|
||||
#include "ballistica/base/platform/linux/base_platform_linux.h"
|
||||
#define BA_PLATFORM_CLASS BasePlatformLinux
|
||||
#else
|
||||
|
||||
// Generic ---------------------------------------------------------------------
|
||||
|
||||
#define BA_PLATFORM_CLASS BasePlatform
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------- END PLATFORM SELECTION ------------------------------
|
||||
|
||||
#ifndef BA_PLATFORM_CLASS
|
||||
#error no BA_PLATFORM_CLASS defined for this platform
|
||||
#endif
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
auto BaseBuildSwitches::CreatePlatform() -> BasePlatform* {
|
||||
auto platform = new BA_PLATFORM_CLASS();
|
||||
platform->PostInit();
|
||||
assert(platform->ran_base_post_init());
|
||||
return platform;
|
||||
}
|
||||
|
||||
auto BaseBuildSwitches::CreateGraphics() -> Graphics* {
|
||||
#if BA_VR_BUILD
|
||||
return new GraphicsVR();
|
||||
#else
|
||||
return new Graphics();
|
||||
#endif
|
||||
}
|
||||
|
||||
auto BaseBuildSwitches::CreateAppAdapter() -> AppAdapter* {
|
||||
assert(g_core);
|
||||
|
||||
AppAdapter* app_adapter{};
|
||||
|
||||
#if BA_HEADLESS_BUILD
|
||||
app_adapter = new AppAdapterHeadless();
|
||||
#elif BA_OSTYPE_ANDROID
|
||||
app_adapter = new AppAdapterAndroid();
|
||||
#elif BA_XCODE_BUILD
|
||||
app_adapter = new AppAdapterApple();
|
||||
#elif BA_RIFT_BUILD
|
||||
// Rift build can spin up in either VR or regular mode.
|
||||
if (g_core->vr_mode) {
|
||||
app_adapter = new AppAdapterVR();
|
||||
} else {
|
||||
app_adapter = new AppAdapterSDL();
|
||||
}
|
||||
#elif BA_CARDBOARD_BUILD
|
||||
app_adapter = new AppAdapterVR();
|
||||
#elif BA_SDL_BUILD
|
||||
app_adapter = new AppAdapterSDL();
|
||||
#else
|
||||
#error No app adapter defined for this build.
|
||||
#endif
|
||||
|
||||
assert(app_adapter);
|
||||
return app_adapter;
|
||||
}
|
||||
|
||||
} // namespace ballistica::base
|
||||
20
src/ballistica/base/support/base_build_switches.h
Normal file
20
src/ballistica/base/support/base_build_switches.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Released under the MIT License. See LICENSE for details.
|
||||
|
||||
#ifndef BALLISTICA_BASE_SUPPORT_BASE_BUILD_SWITCHES_H_
|
||||
#define BALLISTICA_BASE_SUPPORT_BASE_BUILD_SWITCHES_H_
|
||||
|
||||
#include "ballistica/base/base.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
/// Constructs various app components based on the current build config.
|
||||
class BaseBuildSwitches {
|
||||
public:
|
||||
static auto CreateGraphics() -> Graphics*;
|
||||
static auto CreatePlatform() -> BasePlatform*;
|
||||
static auto CreateAppAdapter() -> AppAdapter*;
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
#endif // BALLISTICA_BASE_SUPPORT_BASE_BUILD_SWITCHES_H_
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "ballistica/base/support/repeater.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/support/app_timer.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
|
||||
#include "ballistica/base/graphics/text/text_graphics.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
@ -85,6 +84,11 @@ static auto XOffs(DevConsoleHAnchor_ attach) -> float {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static auto IsValidHungryChar_(uint32_t this_char) -> bool {
|
||||
return ((this_char >= 65 && this_char <= 90)
|
||||
|| (this_char >= 97 && this_char <= 122));
|
||||
}
|
||||
|
||||
static void DrawRect(RenderPass* pass, Mesh* mesh, float bottom, float x,
|
||||
float y, float width, float height,
|
||||
const Vector3f& bgcolor) {
|
||||
@ -677,6 +681,11 @@ void DevConsole::set_input_string(const std::string& val) {
|
||||
assert(g_base->InLogicThread());
|
||||
input_string_ = val;
|
||||
input_text_dirty_ = true;
|
||||
// Move carat to end.
|
||||
carat_char_ =
|
||||
static_cast<int>(Utils::UnicodeFromUTF8(input_string_, "fj43t").size());
|
||||
assert(CaratCharValid_());
|
||||
carat_dirty_ = true;
|
||||
}
|
||||
|
||||
void DevConsole::InputAdapterFinish() {
|
||||
@ -690,28 +699,11 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool {
|
||||
// Any presses or releases cancels repeat actions.
|
||||
key_repeater_.Clear();
|
||||
|
||||
// Handle our toggle buttons no matter whether we're active.
|
||||
// switch (keysym->sym) {
|
||||
// case kDevConsoleActivateKey1:
|
||||
// case kDevConsoleActivateKey2: {
|
||||
// if (!g_buildconfig.demo_build() && !g_buildconfig.arcade_build()) {
|
||||
// // (reset input so characters don't continue walking and stuff)
|
||||
// g_base->input->ResetHoldStates();
|
||||
// if (auto console = g_base->ui->dev_console()) {
|
||||
// console->ToggleState();
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
if (state_ == State_::kInactive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle some stuff only while active.
|
||||
// Stuff we always look for.
|
||||
switch (keysym->sym) {
|
||||
case SDLK_ESCAPE:
|
||||
Dismiss();
|
||||
@ -720,56 +712,228 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool {
|
||||
break;
|
||||
}
|
||||
|
||||
// If we support direct keyboard input, and python terminal is showing,
|
||||
// handle some keys directly.
|
||||
// Stuff we look for only when direct keyboard input is enabled and our
|
||||
// Python terminal is up.
|
||||
if (python_terminal_visible_ && g_base->ui->UIHasDirectKeyboardInput()) {
|
||||
bool do_carat_right{};
|
||||
bool do_hungry_carat_right{};
|
||||
bool do_carat_left{};
|
||||
bool do_hungry_carat_left{};
|
||||
bool do_history_up{};
|
||||
bool do_history_down{};
|
||||
bool do_backspace{};
|
||||
bool do_hungry_backspace{};
|
||||
bool do_move_to_end{};
|
||||
bool do_move_to_beginning{};
|
||||
bool do_kill_line{};
|
||||
switch (keysym->sym) {
|
||||
case SDLK_BACKSPACE: {
|
||||
key_repeater_ = Repeater::New(
|
||||
g_base->app_adapter->GetKeyRepeatDelay(),
|
||||
g_base->app_adapter->GetKeyRepeatInterval(), [this] {
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38");
|
||||
if (!unichars.empty()) {
|
||||
unichars.resize(unichars.size() - 1);
|
||||
input_string_ = Utils::UTF8FromUnicode(unichars);
|
||||
input_text_dirty_ = true;
|
||||
}
|
||||
});
|
||||
if (keysym->mod & KMOD_ALT) {
|
||||
do_hungry_backspace = true;
|
||||
} else {
|
||||
do_backspace = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_UP:
|
||||
case SDLK_DOWN: {
|
||||
if (input_history_.empty()) {
|
||||
break;
|
||||
}
|
||||
if (keysym->sym == SDLK_UP) {
|
||||
input_history_position_++;
|
||||
do_history_up = true;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
do_history_down = true;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if (keysym->mod & KMOD_ALT) {
|
||||
do_hungry_carat_right = true;
|
||||
} else {
|
||||
input_history_position_--;
|
||||
}
|
||||
int input_history_position_used =
|
||||
(input_history_position_ - 1)
|
||||
% static_cast<int>(input_history_.size());
|
||||
int j = 0;
|
||||
for (auto& i : input_history_) {
|
||||
if (j == input_history_position_used) {
|
||||
input_string_ = i;
|
||||
input_text_dirty_ = true;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
do_carat_right = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
if (keysym->mod & KMOD_ALT) {
|
||||
do_hungry_carat_left = true;
|
||||
} else {
|
||||
do_carat_left = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_KP_ENTER:
|
||||
case SDLK_RETURN: {
|
||||
Exec();
|
||||
break;
|
||||
}
|
||||
|
||||
// Wheeee emacs key shortcuts!!
|
||||
case SDLK_n:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_history_down = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_f:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_carat_right = true;
|
||||
} else if (keysym->mod & KMOD_ALT) {
|
||||
do_hungry_carat_right = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_b:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_carat_left = true;
|
||||
} else if (keysym->mod & KMOD_ALT) {
|
||||
do_hungry_carat_left = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_p:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_history_up = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_a:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_move_to_beginning = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_e:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_move_to_end = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_k:
|
||||
if (keysym->mod & KMOD_CTRL) {
|
||||
do_kill_line = true;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (do_kill_line) {
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38");
|
||||
assert(CaratCharValid_());
|
||||
unichars.resize(carat_char_);
|
||||
assert(CaratCharValid_());
|
||||
input_string_ = Utils::UTF8FromUnicode(unichars);
|
||||
input_text_dirty_ = true;
|
||||
carat_dirty_ = true;
|
||||
}
|
||||
if (do_move_to_beginning) {
|
||||
carat_char_ = 0;
|
||||
assert(CaratCharValid_());
|
||||
carat_dirty_ = true;
|
||||
}
|
||||
if (do_move_to_end) {
|
||||
// Move carat to end.
|
||||
carat_char_ = static_cast<int>(
|
||||
Utils::UnicodeFromUTF8(input_string_, "fj43t").size());
|
||||
assert(CaratCharValid_());
|
||||
carat_dirty_ = true;
|
||||
}
|
||||
if (do_hungry_backspace || do_hungry_carat_left) {
|
||||
auto do_delete = do_hungry_backspace;
|
||||
key_repeater_ = Repeater::New(
|
||||
g_base->app_adapter->GetKeyRepeatDelay(),
|
||||
g_base->app_adapter->GetKeyRepeatInterval(), [this, do_delete] {
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38");
|
||||
bool found_valid{};
|
||||
// Delete/move until we've found at least one valid char and the
|
||||
// stop at the first invalid one.
|
||||
while (carat_char_ > 0) {
|
||||
assert(CaratCharValid_());
|
||||
auto this_char = unichars[carat_char_ - 1];
|
||||
auto is_valid = IsValidHungryChar_(this_char);
|
||||
if (found_valid && !is_valid) {
|
||||
break;
|
||||
}
|
||||
if (is_valid) {
|
||||
found_valid = true;
|
||||
}
|
||||
if (do_delete) {
|
||||
unichars.erase(unichars.begin() + carat_char_ - 1);
|
||||
}
|
||||
carat_char_ -= 1;
|
||||
assert(CaratCharValid_());
|
||||
}
|
||||
input_string_ = Utils::UTF8FromUnicode(unichars);
|
||||
input_text_dirty_ = true;
|
||||
carat_dirty_ = true;
|
||||
});
|
||||
}
|
||||
if (do_hungry_carat_right) {
|
||||
key_repeater_ = Repeater::New(
|
||||
g_base->app_adapter->GetKeyRepeatDelay(),
|
||||
g_base->app_adapter->GetKeyRepeatInterval(), [this] {
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38");
|
||||
bool found_valid{};
|
||||
// Move until we've found at least one valid char and the
|
||||
// stop at the first invalid one.
|
||||
while (carat_char_ < unichars.size()) {
|
||||
assert(CaratCharValid_());
|
||||
auto this_char = unichars[carat_char_];
|
||||
auto is_valid = IsValidHungryChar_(this_char);
|
||||
if (found_valid && !is_valid) {
|
||||
break;
|
||||
}
|
||||
if (is_valid) {
|
||||
found_valid = true;
|
||||
}
|
||||
carat_char_ += 1;
|
||||
assert(CaratCharValid_());
|
||||
}
|
||||
carat_dirty_ = true;
|
||||
});
|
||||
}
|
||||
if (do_backspace) {
|
||||
key_repeater_ = Repeater::New(
|
||||
g_base->app_adapter->GetKeyRepeatDelay(),
|
||||
g_base->app_adapter->GetKeyRepeatInterval(), [this] {
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38");
|
||||
if (!unichars.empty() && carat_char_ > 0) {
|
||||
assert(CaratCharValid_());
|
||||
unichars.erase(unichars.begin() + carat_char_ - 1);
|
||||
input_string_ = Utils::UTF8FromUnicode(unichars);
|
||||
input_text_dirty_ = true;
|
||||
carat_char_ -= 1;
|
||||
assert(CaratCharValid_());
|
||||
carat_dirty_ = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (do_carat_left || do_carat_right) {
|
||||
key_repeater_ = Repeater::New(
|
||||
g_base->app_adapter->GetKeyRepeatDelay(),
|
||||
g_base->app_adapter->GetKeyRepeatInterval(),
|
||||
[do_carat_left, do_carat_right, this] {
|
||||
int offset = do_carat_right ? 1 : -1;
|
||||
carat_char_ = std::clamp(
|
||||
carat_char_ + offset, 0,
|
||||
static_cast<int>(
|
||||
Utils::UnicodeFromUTF8(input_string_, "fffwe").size()));
|
||||
assert(CaratCharValid_());
|
||||
carat_dirty_ = true;
|
||||
});
|
||||
}
|
||||
|
||||
if ((do_history_up || do_history_down) && !input_history_.empty()) {
|
||||
if (do_history_up) {
|
||||
input_history_position_++;
|
||||
} else {
|
||||
input_history_position_--;
|
||||
}
|
||||
int input_history_position_used =
|
||||
(input_history_position_ - 1)
|
||||
% static_cast<int>(input_history_.size());
|
||||
int j = 0;
|
||||
for (auto& i : input_history_) {
|
||||
if (j == input_history_position_used) {
|
||||
input_string_ = i;
|
||||
carat_char_ = static_cast<int>(
|
||||
Utils::UnicodeFromUTF8(input_string_, "fffwe").size());
|
||||
assert(CaratCharValid_());
|
||||
input_text_dirty_ = true;
|
||||
carat_dirty_ = true;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -778,6 +942,24 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto DevConsole::HandleTextEditing(const std::string& text) -> bool {
|
||||
assert(g_base->InLogicThread());
|
||||
if (state_ == State_::kInactive) {
|
||||
return false;
|
||||
}
|
||||
assert(CaratCharValid_());
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "jfof8");
|
||||
auto addunichars = Utils::UnicodeFromUTF8(text, "jfoef8");
|
||||
unichars.insert(unichars.begin() + carat_char_, addunichars.begin(),
|
||||
addunichars.end());
|
||||
input_string_ = Utils::UTF8FromUnicode(unichars);
|
||||
input_text_dirty_ = true;
|
||||
carat_char_ += addunichars.size();
|
||||
assert(CaratCharValid_());
|
||||
carat_dirty_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool {
|
||||
// Any presses or releases cancels repeat actions.
|
||||
key_repeater_.Clear();
|
||||
@ -804,7 +986,17 @@ void DevConsole::Exec() {
|
||||
input_history_.pop_back();
|
||||
}
|
||||
input_string_.resize(0);
|
||||
carat_char_ = 0;
|
||||
assert(CaratCharValid_());
|
||||
input_text_dirty_ = true;
|
||||
carat_dirty_ = true;
|
||||
}
|
||||
|
||||
// Just for sanity testing.
|
||||
auto DevConsole::CaratCharValid_() -> bool {
|
||||
return carat_char_ >= 0
|
||||
&& carat_char_
|
||||
<= Utils::UnicodeFromUTF8(input_string_, "fwewffe").size();
|
||||
}
|
||||
|
||||
void DevConsole::SubmitPythonCommand_(const std::string& command) {
|
||||
@ -871,24 +1063,6 @@ void DevConsole::ToggleState() {
|
||||
transition_start_ = g_base->logic->display_time();
|
||||
}
|
||||
|
||||
auto DevConsole::HandleTextEditing(const std::string& text) -> bool {
|
||||
assert(g_base->InLogicThread());
|
||||
if (state_ == State_::kInactive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore back-tick because we use that key to toggle the console.
|
||||
//
|
||||
// FIXME: Perhaps should allow typing it if some control-character is
|
||||
// held?
|
||||
if (text == "`") {
|
||||
return false;
|
||||
}
|
||||
input_string_ += text;
|
||||
input_text_dirty_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DevConsole::Print(const std::string& s_in) {
|
||||
assert(g_base->InLogicThread());
|
||||
std::string s = Utils::GetValidUTF8(s_in.c_str(), "cspr");
|
||||
@ -1013,13 +1187,14 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
if (input_text_dirty_) {
|
||||
input_text_group_.SetText(input_string_);
|
||||
input_text_dirty_ = false;
|
||||
last_input_text_change_time_ = pass->frame_def()->app_time_millisecs();
|
||||
}
|
||||
{
|
||||
SimpleComponent c(pass);
|
||||
c.SetFlatness(1.0f);
|
||||
c.SetTransparent(true);
|
||||
c.SetColor(0.4f, 0.33f, 0.45f, 0.8f);
|
||||
|
||||
// Build.
|
||||
int elem_count = built_text_group_.GetElementCount();
|
||||
for (int e = 0; e < elem_count; e++) {
|
||||
c.SetTexture(built_text_group_.GetElementTexture(e));
|
||||
@ -1031,6 +1206,8 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
c.DrawMesh(built_text_group_.GetElementMesh(e));
|
||||
}
|
||||
}
|
||||
|
||||
// Title.
|
||||
elem_count = title_text_group_.GetElementCount();
|
||||
for (int e = 0; e < elem_count; e++) {
|
||||
c.SetTexture(title_text_group_.GetElementTexture(e));
|
||||
@ -1041,6 +1218,8 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
c.DrawMesh(title_text_group_.GetElementMesh(e));
|
||||
}
|
||||
}
|
||||
|
||||
// Prompt.
|
||||
elem_count = prompt_text_group_.GetElementCount();
|
||||
for (int e = 0; e < elem_count; e++) {
|
||||
c.SetTexture(prompt_text_group_.GetElementTexture(e));
|
||||
@ -1052,6 +1231,8 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
c.DrawMesh(prompt_text_group_.GetElementMesh(e));
|
||||
}
|
||||
}
|
||||
|
||||
// Input line.
|
||||
elem_count = input_text_group_.GetElementCount();
|
||||
for (int e = 0; e < elem_count; e++) {
|
||||
c.SetTexture(input_text_group_.GetElementTexture(e));
|
||||
@ -1065,21 +1246,34 @@ void DevConsole::Draw(FrameDef* frame_def) {
|
||||
}
|
||||
|
||||
// Carat.
|
||||
if (!carat_mesh_.Exists()) {
|
||||
UpdateCarat_();
|
||||
}
|
||||
millisecs_t real_time = pass->frame_def()->app_time_millisecs();
|
||||
if (real_time % 200 < 100
|
||||
|| (real_time - last_input_text_change_time_ < 100)) {
|
||||
|| (real_time - last_carat_x_change_time_ < 100)) {
|
||||
SimpleComponent c(pass);
|
||||
c.SetTransparent(true);
|
||||
c.SetColor(1, 1, 1, 0.7f);
|
||||
c.SetTexture(g_base->assets->SysTexture(SysTextureID::kShadow));
|
||||
c.SetColor(0.8, 0.0, 1.0, 0.3f);
|
||||
// c.SetPremultiplied(true);
|
||||
{
|
||||
auto xf = c.ScopedTransform();
|
||||
c.Translate(
|
||||
(19.0f
|
||||
+ g_base->text_graphics->GetStringWidth(input_string_) * 0.5f)
|
||||
* bs,
|
||||
bottom + 22.5f * bs, kDevConsoleZDepth);
|
||||
c.Scale(6.0f * bs, 12.0f * bs, 1.0f);
|
||||
c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
|
||||
auto carat_x = GetCaratX_();
|
||||
c.Translate(15.0f * bs, bottom + 14.5f * bs, kDevConsoleZDepth);
|
||||
c.Scale(0.5f * bs, 0.5f * bs, 1.0f);
|
||||
c.Translate(carat_x, 0.0f, 0.0f);
|
||||
c.DrawMesh(carat_glow_mesh_.Get());
|
||||
}
|
||||
c.SetTexture(g_base->assets->SysTexture(SysTextureID::kShadowSharp));
|
||||
c.SetColor(1.0, 1.0, 1.0, 1.0f);
|
||||
{
|
||||
auto xf = c.ScopedTransform();
|
||||
auto carat_x = GetCaratX_();
|
||||
c.Translate(15.0f * bs, bottom + 14.5f * bs, kDevConsoleZDepth);
|
||||
c.Scale(0.5f * bs, 0.5f * bs, 1.0f);
|
||||
c.Translate(carat_x, 0.0f, 0.0f);
|
||||
c.DrawMesh(carat_mesh_.Get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1191,4 +1385,86 @@ void DevConsole::StepDisplayTime() {
|
||||
}
|
||||
}
|
||||
|
||||
auto DevConsole::PasteFromClipboard() -> bool {
|
||||
if (state_ != State_::kInactive) {
|
||||
if (python_terminal_visible_) {
|
||||
if (g_base->app_adapter->ClipboardIsSupported()) {
|
||||
if (g_base->app_adapter->ClipboardHasText()) {
|
||||
auto text = g_base->app_adapter->ClipboardGetText();
|
||||
if (strstr(text.c_str(), "\n") || strstr(text.c_str(), "\r")) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(SysSoundID::kErrorBeep));
|
||||
ScreenMessage("Can only paste single lines of text.",
|
||||
Vector3f(1.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
HandleTextEditing(text);
|
||||
}
|
||||
// Ok, we either pasted or complained, so consider it handled.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DevConsole::UpdateCarat_() {
|
||||
auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjfwef");
|
||||
auto unichars_clamped = unichars;
|
||||
|
||||
unichars_clamped.resize(carat_char_);
|
||||
auto clamped_str = Utils::UTF8FromUnicode(unichars_clamped);
|
||||
carat_x_ = g_base->text_graphics->GetStringWidth(clamped_str);
|
||||
|
||||
// Use a base width if we're not covering a char, and use the char's width
|
||||
// if we are.
|
||||
float width = 14.0f;
|
||||
if (carat_char_ < unichars.size()) {
|
||||
std::vector<uint32_t> covered_char{unichars[carat_char_]};
|
||||
auto covered_char_str = Utils::UTF8FromUnicode(covered_char);
|
||||
width =
|
||||
std::max(3.0f, g_base->text_graphics->GetStringWidth(covered_char_str));
|
||||
}
|
||||
|
||||
float height = 32.0f;
|
||||
float x_extend = 15.0f;
|
||||
float y_extend = 20.0f;
|
||||
float x_offset = 2.0f;
|
||||
float y_offset = -0.0f;
|
||||
float corner_radius = 20.0f;
|
||||
float width_fin = width + x_extend * 2.0f;
|
||||
float height_fin = height + y_extend * 2.0f;
|
||||
float x_border =
|
||||
NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin);
|
||||
float y_border =
|
||||
NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin);
|
||||
carat_glow_mesh_ = Object::New<NinePatchMesh>(
|
||||
-x_extend + x_offset, -y_extend + y_offset, 0.0f, width_fin, height_fin,
|
||||
x_border, y_border, x_border, y_border);
|
||||
|
||||
corner_radius = 3.0f;
|
||||
x_extend = 0.0f;
|
||||
y_extend = -3.0f;
|
||||
x_offset = 1.0f;
|
||||
y_offset = 0.0f;
|
||||
width_fin = width + x_extend * 2.0f;
|
||||
height_fin = height + y_extend * 2.0f;
|
||||
x_border =
|
||||
NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin);
|
||||
y_border =
|
||||
NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin);
|
||||
carat_mesh_ = Object::New<NinePatchMesh>(
|
||||
-x_extend + x_offset, -y_extend + y_offset, 0.0f, width_fin, height_fin,
|
||||
x_border, y_border, x_border, y_border);
|
||||
}
|
||||
|
||||
auto DevConsole::GetCaratX_() -> float {
|
||||
if (carat_dirty_) {
|
||||
last_carat_x_change_time_ = g_core->GetAppTimeMillisecs();
|
||||
UpdateCarat_();
|
||||
carat_dirty_ = false;
|
||||
}
|
||||
return carat_x_;
|
||||
}
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
#include "ballistica/shared/foundation/object.h"
|
||||
#include "ballistica/shared/python/python_ref.h"
|
||||
@ -32,6 +33,9 @@ class DevConsole {
|
||||
/// Tell the console to quietly go away no matter what state it is in.
|
||||
void Dismiss();
|
||||
|
||||
/// Attempt to Paste. Returns true if it happened.
|
||||
auto PasteFromClipboard() -> bool;
|
||||
|
||||
/// Print text to the console.
|
||||
void Print(const std::string& s_in);
|
||||
void Draw(FrameDef* frame_def);
|
||||
@ -75,6 +79,9 @@ class DevConsole {
|
||||
class OutputLine_;
|
||||
enum class State_ : uint8_t { kInactive, kMini, kFull };
|
||||
|
||||
auto CaratCharValid_() -> bool;
|
||||
auto GetCaratX_() -> float;
|
||||
void UpdateCarat_();
|
||||
auto Bottom_() const -> float;
|
||||
void SubmitPythonCommand_(const std::string& command);
|
||||
void InvokeStringEditor_();
|
||||
@ -82,17 +89,20 @@ class DevConsole {
|
||||
void RefreshTabContents_();
|
||||
|
||||
int input_history_position_{};
|
||||
int ui_lock_count_ : 1 {};
|
||||
int ui_lock_count_{};
|
||||
int carat_char_{0};
|
||||
State_ state_{State_::kInactive};
|
||||
State_ state_prev_{State_::kInactive};
|
||||
bool input_text_dirty_ : 1 {true};
|
||||
bool input_enabled_ : 1 {};
|
||||
bool last_line_mesh_dirty_ : 1 {true};
|
||||
bool python_terminal_visible_ : 1 {};
|
||||
bool python_terminal_pressed_ : 1 {};
|
||||
bool refresh_pending_ : 1 {};
|
||||
double transition_start_{};
|
||||
State_ state_{State_::kInactive};
|
||||
State_ state_prev_{State_::kInactive};
|
||||
millisecs_t last_input_text_change_time_{};
|
||||
bool carat_dirty_ : 1 {true};
|
||||
float carat_x_{};
|
||||
seconds_t transition_start_{};
|
||||
millisecs_t last_carat_x_change_time_{};
|
||||
ImageMesh bg_mesh_;
|
||||
ImageMesh stripe_mesh_;
|
||||
ImageMesh border_mesh_;
|
||||
@ -111,6 +121,8 @@ class DevConsole {
|
||||
std::vector<std::unique_ptr<Widget_> > tab_buttons_;
|
||||
Object::Ref<TextGroup> last_line_mesh_group_;
|
||||
Object::Ref<Repeater> key_repeater_;
|
||||
Object::Ref<NinePatchMesh> carat_mesh_;
|
||||
Object::Ref<NinePatchMesh> carat_glow_mesh_;
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include "ballistica/base/dynamics/bg/bg_dynamics_shadow.h"
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/graphics/support/area_of_interest.h"
|
||||
#include "ballistica/base/graphics/support/camera.h"
|
||||
#include "ballistica/scene_v1/assets/scene_texture.h"
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/support/plus_soft.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/scene_v1/connection/connection_set.h"
|
||||
#include "ballistica/scene_v1/connection/connection_to_client_udp.h"
|
||||
#include "ballistica/scene_v1/connection/connection_to_host.h"
|
||||
|
||||
@ -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 = 21516;
|
||||
const int kEngineBuildNumber = 21522;
|
||||
const char* kEngineVersion = "1.7.28";
|
||||
const int kEngineApiVersion = 8;
|
||||
|
||||
|
||||
@ -13,15 +13,8 @@ namespace ballistica {
|
||||
|
||||
/// Objects supporting strong and weak referencing and thread enforcement.
|
||||
class Object {
|
||||
protected:
|
||||
/// Our base constructor is marked protected because we *require* Objects
|
||||
/// to be dynamically allocated. This allows us extra measures of control
|
||||
/// over their construction and destruction, and it does not seem that
|
||||
/// there is a pressing use case for a statically allocated Object that
|
||||
/// would justify diluting that control.
|
||||
Object();
|
||||
|
||||
public:
|
||||
Object();
|
||||
virtual ~Object();
|
||||
|
||||
// Object classes can provide descriptive names for themselves; these are
|
||||
@ -575,6 +568,10 @@ class Object {
|
||||
[[nodiscard]] static auto New(ARGS&&... args) -> Object::Ref<TRETURN> {
|
||||
auto* ptr = new TALLOC(std::forward<ARGS>(args)...);
|
||||
#if BA_DEBUG_BUILD
|
||||
/// Objects assume they are statically allocated by default; it's up
|
||||
/// to us to tell them when they're not.
|
||||
ptr->object_is_static_allocated_ = false;
|
||||
|
||||
/// Make sure things aren't creating strong refs to themselves in their
|
||||
/// constructors.
|
||||
if (ptr->object_has_been_strong_reffed_) {
|
||||
@ -599,6 +596,10 @@ class Object {
|
||||
[[nodiscard]] static auto NewDeferred(ARGS&&... args) -> T* {
|
||||
T* ptr = new T(std::forward<ARGS>(args)...);
|
||||
#if BA_DEBUG_BUILD
|
||||
/// Objects assume they are statically allocated by default; it's up
|
||||
/// to us to tell them when they're not.
|
||||
ptr->object_is_static_allocated_ = false;
|
||||
|
||||
/// Make sure things aren't creating strong refs to themselves in their
|
||||
/// constructors.
|
||||
if (ptr->object_has_been_strong_reffed_) {
|
||||
@ -650,6 +651,9 @@ class Object {
|
||||
[[nodiscard]] static auto NewUnmanaged(ARGS&&... args) -> T* {
|
||||
T* ptr = new T(std::forward<ARGS>(args)...);
|
||||
#if BA_DEBUG_BUILD
|
||||
/// Objects assume they are statically allocated by default; it's up
|
||||
/// to us to tell them when they're not.
|
||||
ptr->object_is_static_allocated_ = false;
|
||||
ptr->object_is_unmanaged_ = true;
|
||||
#endif
|
||||
return ptr;
|
||||
@ -668,6 +672,7 @@ class Object {
|
||||
auto operator new(size_t size) -> void* { return new char[size]; }
|
||||
void ObjectUpdateForAcquire();
|
||||
|
||||
bool object_is_static_allocated_ : 1 {true};
|
||||
bool object_has_been_strong_reffed_ : 1 {};
|
||||
bool object_is_ref_counted_ : 1 {};
|
||||
bool object_is_pending_deferred_ : 1 {};
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "ballistica/ui_v1/python/ui_v1_python.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/input/device/keyboard_input.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
|
||||
@ -3,10 +3,8 @@
|
||||
#include "ballistica/ui_v1/ui_v1.h"
|
||||
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/ui_v1/python/ui_v1_python.h"
|
||||
#include "ballistica/ui_v1/support/root_ui.h"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user