almost final mac app store update build

This commit is contained in:
Eric 2023-11-13 15:43:54 -08:00
parent e6d3e7dff2
commit f06ad6b9ba
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
49 changed files with 499 additions and 480 deletions

100
.efrocachemap generated
View File

@ -421,7 +421,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "dca47b4976752e76e852f7a4be2c7aa3", "build/assets/ba_data/data/langdata.json": "02522e0d2593baf2e57a97fbfbfe3368",
"build/assets/ba_data/data/languages/arabic.json": "e0001d8542c904bc3c98a174f256efd9", "build/assets/ba_data/data/languages/arabic.json": "e0001d8542c904bc3c98a174f256efd9",
"build/assets/ba_data/data/languages/belarussian.json": "7fe38341815ca6ff4d95224196e7a67e", "build/assets/ba_data/data/languages/belarussian.json": "7fe38341815ca6ff4d95224196e7a67e",
"build/assets/ba_data/data/languages/chinese.json": "4e2f4f1f38216940953fcbee4da1563e", "build/assets/ba_data/data/languages/chinese.json": "4e2f4f1f38216940953fcbee4da1563e",
@ -439,22 +439,22 @@
"build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3",
"build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6",
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
"build/assets/ba_data/data/languages/indonesian.json": "ba39cade3c965b2ddbee122880b6f0db", "build/assets/ba_data/data/languages/indonesian.json": "97657eb2ab75d821045387b6d7a2b52d",
"build/assets/ba_data/data/languages/italian.json": "cda5760f247500657722c279bc2f2bc7", "build/assets/ba_data/data/languages/italian.json": "cda5760f247500657722c279bc2f2bc7",
"build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2", "build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2",
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
"build/assets/ba_data/data/languages/persian.json": "4f448b29ba04f2b789329600cb7f9ab7", "build/assets/ba_data/data/languages/persian.json": "4f448b29ba04f2b789329600cb7f9ab7",
"build/assets/ba_data/data/languages/polish.json": "8bb8f7baa5efcf6cdd627140d209c2b2", "build/assets/ba_data/data/languages/polish.json": "8bb8f7baa5efcf6cdd627140d209c2b2",
"build/assets/ba_data/data/languages/portuguese.json": "7374b6a5cadcf573ee4ab4a5b4bc8c0a", "build/assets/ba_data/data/languages/portuguese.json": "c738cc76396305060d4f94cb77db5bec",
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
"build/assets/ba_data/data/languages/russian.json": "9e068a3afdec43b207c83aedfb812e82", "build/assets/ba_data/data/languages/russian.json": "cdaac43afde13ab622babe403b9858a4",
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef", "build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
"build/assets/ba_data/data/languages/spanish.json": "f73b0d4d534f030f95c00385bb06cbc1", "build/assets/ba_data/data/languages/spanish.json": "f73b0d4d534f030f95c00385bb06cbc1",
"build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac", "build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac",
"build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c", "build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c",
"build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc", "build/assets/ba_data/data/languages/thai.json": "77755219bbf5fb7eea0d6b226684f403",
"build/assets/ba_data/data/languages/turkish.json": "c3674336e746bf7b23617a6ff296c69a", "build/assets/ba_data/data/languages/turkish.json": "326bcc54b69cb6a1bda4abb732f9f56f",
"build/assets/ba_data/data/languages/ukrainian.json": "e5c861187c4c6db37d1a033f4ef3dd5a", "build/assets/ba_data/data/languages/ukrainian.json": "e5c861187c4c6db37d1a033f4ef3dd5a",
"build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4", "build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4",
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba", "build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
@ -4056,50 +4056,50 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "66647fb41b54b221cf4189161a696698", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "96ba5c40a9216f4efed502e29a0bc762",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "81a9bec829a30860a260df58c258b7d0", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "bbe152b83087e223b9f9f0336d4f03d3",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "1930fa43a702b2fd3601b032afd9ad31", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "c22b27747e16c1dfa7e7a43264555cd5",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "e9fdc1e724495d36a1ae9c1898b2dbeb", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "06b779dfd042cb832e4546b177b333a7",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "5cb78d708e8dc3911d1e5a345e535bd2", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "a18464f5e02af14e3b34ccb2154fb1de",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "9aa815a258a476f02490cf58db28340a", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "56d0b3ff53e9d4ac46c8ef2aa4d729b6",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "dd932540bbef37a3e0580ef81206090c", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "7d00156ec8e56af0d8a39ea7eb20f6fd",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "d34c3fcf54ae4c362dafb442e5e2e57a", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "b933746e1b64608aab7e6bf8ebf32a8d",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a74979683c4e58bfefde5235996551db", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "824515c2fc33e06c7ecb866a2818a546",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "cbbecde45fb204a8f39cbf5448d248a2", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "d0a8783b736e196cfaaefbb62271e337",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "37d71f1f72191bb29645146a5d7fdd09", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "741f777205eddf8a2500625e3ba18ee6",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "10cb64bd655ad3ff562496bb66693dd6", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "01697d3e58c63d3f23c74720f7738da6",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "7d9ab35e63602e682a533495022728d3", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a86b1855a709c6b654195a8a0e308057",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "d98edee305c488c3a082ef98deae8a6c", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "9567d63a4c02d393a8110953f1c2e9b5",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "a12f0a05ed17ef48554356b6087cdee0", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "7199a245c7e946222125f0e8640285a0",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "de7e6c726c6ace4bba28f59a84cdf6b5", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "a5e0788917285460f40d1beacabd0ca2",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "fd7b381ca67b31c088d4e98b6c0ddfe1", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "4cc6912cd58e026baa523d8081411506",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1d074c3b15b2bdf6c32e145ea83f1fa2", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "754fed064c8a87448617ef7b9c3479cb",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "0b47cfab278418386ac29009402c9f59", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "047c6dcda71e7c4e0c4ffa5f1aac5bfa",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "213a68414bac47cbe051db9fbb0cbb43", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "56976efa146ae9972dd6ba53ec75d451",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "a5e255155289f502a6662e5f9bb7819c", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "dc8d1e0f82fe799cbbacfd89bbf04498",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "ae044789e56e5d2999f55e2f4eeb6a4d", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c6be3757c2ee85a7f4f8a66d327a24a0",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "a5e255155289f502a6662e5f9bb7819c", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "dc8d1e0f82fe799cbbacfd89bbf04498",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "ae044789e56e5d2999f55e2f4eeb6a4d", "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "c6be3757c2ee85a7f4f8a66d327a24a0",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "48d81af91942519355b066d7bf8d3468", "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "859470a05f3d968031ae9843bdf818c3",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "2c4f37722cb283a8405f35a0c9bbbfbb", "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "bd8926fb9d12b7f4972870efea006d54",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "48d81af91942519355b066d7bf8d3468", "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "859470a05f3d968031ae9843bdf818c3",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "2c4f37722cb283a8405f35a0c9bbbfbb", "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "bd8926fb9d12b7f4972870efea006d54",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "09abcf532a2c0fba00e5e7860f495ba8", "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "11eeb74f8cb307ed673768c0629ca302",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "699291d36e42e3214946aab9798446ea", "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "5f6ed20081020d554b1866389136b712",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "09abcf532a2c0fba00e5e7860f495ba8", "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "11eeb74f8cb307ed673768c0629ca302",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "699291d36e42e3214946aab9798446ea", "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "5f6ed20081020d554b1866389136b712",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "ef1356360fb3701b0976a0ef37eae4bf", "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "d9407d62ab82cdf25e970e3fde8971fa",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "50cfe82580f1ef2698c5508f46bd2e4c", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "856a05aadbe4b75baee3048296aa8eef",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "7b6afdb6b8d8722cbcee3bff944ec038", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "c5eb4a9161b68775876c4d19bff1cc1b",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "50cfe82580f1ef2698c5508f46bd2e4c", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "856a05aadbe4b75baee3048296aa8eef",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "b29d085453e251a7e6866ac7efcd0513", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "767e7b15de08ffe850d3bbc7def2fab2",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "e8da891dd0f5a441d781793f641f215d", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d482806656749efd090c6c28c124eecf",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "982dc78eabf4eca6ccbfd3bf2537c706", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "07abac6aa3c528bd594bdf5b53e9c823",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "d02505b956c8a0d5b2cb310408492df6", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "b16b8780811a583824491b80a45b839d",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "c95c26eed8a2c5e8573d35c58b2c99f2", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "33806447e8ab2bd3a55509d8a5d8b64c",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "d5a04d68e7818912b1f689fb1a3e8b53", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "786967e43a719120d339de9cd791e58b",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b612531dedbb057f48868e43ce05636a", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "70162e33973c253efdc386e421c50ebe",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "499914dfdd9a5fd051013ab5ae845f41", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "4ab0adfd6cc8934f0340d4bb6c73b78d",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "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.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -1,4 +1,4 @@
### 1.7.28 (build 21585, api 8, 2023-11-10) ### 1.7.28 (build 21588, api 8, 2023-11-13)
- Turning off ticket continues on all platforms. I'll be moving the game towards - Turning off ticket continues on all platforms. I'll be moving the game towards
a new monetization scheme mostly based on cosmetics and this has always felt a a new monetization scheme mostly based on cosmetics and this has always felt a
@ -209,6 +209,13 @@
- The V2 account id for the signed in account is now available at - The V2 account id for the signed in account is now available at
`ba*.app.plus.accounts.primary.accountid` (alongside some other existing `ba*.app.plus.accounts.primary.accountid` (alongside some other existing
account info). account info).
- (build 21585) Fixed an issue where some navigation key presses were getting
incorrectly absorbed by text widgets. (Thanks for the heads-up Temp!)
- (build 21585) Fixed an issue where texture quality changes would not take
effect until next launch.
- Added a 'glow_type' arg to `bauiv1.textwidget()` to adjust the glow used when
the text is selected. The default is 'gradient' but there is now a 'uniform'
option which may look better in some circumstances.
### 1.7.27 (build 21282, api 8, 2023-08-30) ### 1.7.27 (build 21282, api 8, 2023-08-30)

View File

@ -26,6 +26,11 @@ DEBUG_LOG = False
class CloudSubsystem(AppSubsystem): class CloudSubsystem(AppSubsystem):
"""Manages communication with cloud components.""" """Manages communication with cloud components."""
@property
def connected(self) -> bool:
"""Property equivalent of CloudSubsystem.is_connected()."""
return self.is_connected()
def is_connected(self) -> bool: def is_connected(self) -> bool:
"""Return whether a connection to the cloud is present. """Return whether a connection to the cloud is present.

View File

@ -104,8 +104,8 @@ def show_user_scripts() -> None:
_error.print_exception('error writing about_this_folder stuff') _error.print_exception('error writing about_this_folder stuff')
# On a few platforms we try to open the dir in the UI. # On platforms that support it, open the dir in the UI.
if app.classic is not None and app.classic.platform in ['mac', 'windows']: if _babase.supports_open_dir_externally():
_babase.open_dir_externally(env.python_directory_user) _babase.open_dir_externally(env.python_directory_user)
# Otherwise we just print a pretty version of it. # Otherwise we just print a pretty version of it.

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21585 TARGET_BALLISTICA_BUILD = 21588
TARGET_BALLISTICA_VERSION = '1.7.28' TARGET_BALLISTICA_VERSION = '1.7.28'

View File

@ -486,20 +486,21 @@ class AccountSettingsWindow(bui.Window):
self._account_name_what_is_text = bui.textwidget( self._account_name_what_is_text = bui.textwidget(
parent=self._subcontainer, parent=self._subcontainer,
position=(0.0, self._account_name_what_is_y), position=(0.0, self._account_name_what_is_y),
size=(200.0, 60), size=(220.0, 60),
text=bui.Lstr( text=bui.Lstr(
value='${WHAT} -->', value='${WHAT} -->',
subs=[('${WHAT}', bui.Lstr(resource='whatIsThisText'))], subs=[('${WHAT}', bui.Lstr(resource='whatIsThisText'))],
), ),
scale=0.6, scale=0.6,
color=(0.3, 0.7, 0.05), color=(0.3, 0.7, 0.05),
maxwidth=200.0, maxwidth=130.0,
h_align='right', h_align='right',
v_align='center', v_align='center',
autoselect=True, autoselect=True,
selectable=True, selectable=True,
on_activate_call=show_what_is_v2_page, on_activate_call=show_what_is_v2_page,
click_activate=True, click_activate=True,
glow_type='uniform',
) )
if first_selectable is None: if first_selectable is None:
first_selectable = self._account_name_what_is_text first_selectable = self._account_name_what_is_text
@ -1281,11 +1282,21 @@ class AccountSettingsWindow(bui.Window):
show_what_is_v2_page() show_what_is_v2_page()
def _on_manage_account_press(self) -> None: def _on_manage_account_press(self) -> None:
bui.screenmessage(bui.Lstr(resource='oneMomentText'))
plus = bui.app.plus plus = bui.app.plus
assert plus is not None assert plus is not None
# Preemptively fail if it looks like we won't be able to talk to
# the server anyway.
if not plus.cloud.connected:
bui.screenmessage(
bui.Lstr(resource='internal.unavailableNoConnectionText'),
color=(1, 0, 0),
)
bui.getsound('error').play()
return
bui.screenmessage(bui.Lstr(resource='oneMomentText'))
# We expect to have a v2 account signed in if we get here. # We expect to have a v2 account signed in if we get here.
if plus.accounts.primary is None: if plus.accounts.primary is None:
logging.exception( logging.exception(
@ -1445,7 +1456,7 @@ class AccountSettingsWindow(bui.Window):
swidth = bui.get_string_width(name_str, suppress_warning=True) swidth = bui.get_string_width(name_str, suppress_warning=True)
# Eww; number-fudging. Need to recalibrate this if # Eww; number-fudging. Need to recalibrate this if
# account name scaling changes. # account name scaling changes.
x = self._sub_width * 0.5 - swidth * 0.75 - 170 x = self._sub_width * 0.5 - swidth * 0.75 - 190
bui.textwidget( bui.textwidget(
edit=self._account_name_what_is_text, edit=self._account_name_what_is_text,

View File

@ -142,6 +142,7 @@ class ManualGatherTab(GatherTab):
playsound=True, playsound=True,
), ),
text=bui.Lstr(resource='gatherWindow.manualJoinSectionText'), text=bui.Lstr(resource='gatherWindow.manualJoinSectionText'),
glow_type='uniform',
) )
self._favorites_text = bui.textwidget( self._favorites_text = bui.textwidget(
parent=self._container, parent=self._container,
@ -162,6 +163,7 @@ class ManualGatherTab(GatherTab):
playsound=True, playsound=True,
), ),
text=bui.Lstr(resource='gatherWindow.favoritesText'), text=bui.Lstr(resource='gatherWindow.favoritesText'),
glow_type='uniform',
) )
bui.widget(edit=self._join_by_address_text, up_widget=tab_button) bui.widget(edit=self._join_by_address_text, up_widget=tab_button)
bui.widget( bui.widget(
@ -316,7 +318,7 @@ class ManualGatherTab(GatherTab):
self._check_button = bui.textwidget( self._check_button = bui.textwidget(
parent=self._container, parent=self._container,
size=(250, 60), size=(250, 60),
text=bui.Lstr(resource='gatherWindow.' 'showMyAddressText'), text=bui.Lstr(resource='gatherWindow.showMyAddressText'),
v_align='center', v_align='center',
h_align='center', h_align='center',
click_activate=True, click_activate=True,
@ -331,6 +333,7 @@ class ManualGatherTab(GatherTab):
self._container, self._container,
c_width, c_width,
), ),
glow_type='uniform',
) )
bui.widget(edit=self._check_button, up_widget=btn) bui.widget(edit=self._check_button, up_widget=btn)

View File

@ -120,6 +120,7 @@ class PrivateGatherTab(GatherTab):
playsound=True, playsound=True,
), ),
text=bui.Lstr(resource='gatherWindow.privatePartyJoinText'), text=bui.Lstr(resource='gatherWindow.privatePartyJoinText'),
glow_type='uniform',
) )
self._host_sub_tab_text = bui.textwidget( self._host_sub_tab_text = bui.textwidget(
parent=self._container, parent=self._container,
@ -138,6 +139,7 @@ class PrivateGatherTab(GatherTab):
playsound=True, playsound=True,
), ),
text=bui.Lstr(resource='gatherWindow.privatePartyHostText'), text=bui.Lstr(resource='gatherWindow.privatePartyHostText'),
glow_type='uniform',
) )
bui.widget(edit=self._join_sub_tab_text, up_widget=tab_button) bui.widget(edit=self._join_sub_tab_text, up_widget=tab_button)
bui.widget( bui.widget(

View File

@ -114,7 +114,7 @@ class UIRow:
self._name_widget = bui.textwidget( self._name_widget = bui.textwidget(
text=bui.Lstr(value=party.name), text=bui.Lstr(value=party.name),
parent=columnwidget, parent=columnwidget,
size=(sub_scroll_width * 0.63, 20), size=(sub_scroll_width * 0.46, 20),
position=(0 + hpos, 4 + vpos), position=(0 + hpos, 4 + vpos),
selectable=True, selectable=True,
on_select_call=bui.WeakCall( on_select_call=bui.WeakCall(
@ -248,6 +248,7 @@ class AddrFetchThread(Thread):
self._call = call self._call = call
def run(self) -> None: def run(self) -> None:
sock: socket.socket | None = None
try: try:
# FIXME: Update this to work with IPv6 at some point. # FIXME: Update this to work with IPv6 at some point.
import socket import socket
@ -255,7 +256,6 @@ class AddrFetchThread(Thread):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(('8.8.8.8', 80)) sock.connect(('8.8.8.8', 80))
val = sock.getsockname()[0] val = sock.getsockname()[0]
sock.close()
bui.pushcall(bui.Call(self._call, val), from_other_thread=True) bui.pushcall(bui.Call(self._call, val), from_other_thread=True)
except Exception as exc: except Exception as exc:
from efro.error import is_udp_communication_error from efro.error import is_udp_communication_error
@ -265,6 +265,9 @@ class AddrFetchThread(Thread):
pass pass
else: else:
logging.exception('Error in addr-fetch-thread') logging.exception('Error in addr-fetch-thread')
finally:
if sock is not None:
sock.close()
class PingThread(Thread): class PingThread(Thread):
@ -432,6 +435,7 @@ class PublicGatherTab(GatherTab):
text=bui.Lstr( text=bui.Lstr(
resource='gatherWindow.' 'joinPublicPartyDescriptionText' resource='gatherWindow.' 'joinPublicPartyDescriptionText'
), ),
glow_type='uniform',
) )
self._host_text = bui.textwidget( self._host_text = bui.textwidget(
parent=self._container, parent=self._container,
@ -454,6 +458,7 @@ class PublicGatherTab(GatherTab):
text=bui.Lstr( text=bui.Lstr(
resource='gatherWindow.' 'hostPublicPartyDescriptionText' resource='gatherWindow.' 'hostPublicPartyDescriptionText'
), ),
glow_type='uniform',
) )
bui.widget(edit=self._join_text, up_widget=tab_button) bui.widget(edit=self._join_text, up_widget=tab_button)
bui.widget( bui.widget(

View File

@ -198,7 +198,7 @@ class PlaylistAddGameWindow(bui.Window):
txt = bui.textwidget( txt = bui.textwidget(
parent=self._column, parent=self._column,
position=(0, 0), position=(0, 0),
size=(self._width - 88, 24), size=(self._scroll_width * 1.1, 24),
text=gametype.get_display_string(), text=gametype.get_display_string(),
h_align='left', h_align='left',
v_align='center', v_align='center',

View File

@ -382,12 +382,12 @@ class ProfileBrowserWindow(bui.Window):
txtw = bui.textwidget( txtw = bui.textwidget(
parent=self._columnwidget, parent=self._columnwidget,
position=(0, 32), position=(0, 32),
size=((self._width - 40) / scl, 28), size=((self._width - 210) / scl, 28),
text=bui.Lstr(value=tval), text=bui.Lstr(value=tval),
h_align='left', h_align='left',
v_align='center', v_align='center',
on_select_call=bui.WeakCall(self._select, p_name, index), on_select_call=bui.WeakCall(self._select, p_name, index),
maxwidth=self._scroll_width * 0.92, maxwidth=self._scroll_width * 0.86,
corner_scale=scl, corner_scale=scl,
color=bui.safecolor(color, 0.4), color=bui.safecolor(color, 0.4),
always_highlight=True, always_highlight=True,

View File

@ -90,6 +90,7 @@ class NetGraph;
class Networking; class Networking;
class NetworkReader; class NetworkReader;
class NetworkWriter; class NetworkWriter;
class NinePatchMesh;
class ObjectComponent; class ObjectComponent;
class PythonClassUISound; class PythonClassUISound;
class PythonContextCall; class PythonContextCall;

View File

@ -11,8 +11,7 @@ namespace ballistica::base {
// transform/scissor/etc state changes. // transform/scissor/etc state changes.
class EmptyComponent : public RenderComponent { class EmptyComponent : public RenderComponent {
public: public:
explicit EmptyComponent(RenderPass* pass) explicit EmptyComponent(RenderPass* pass) : RenderComponent(pass) {}
: RenderComponent(pass), transparent_(false) {}
void SetTransparent(bool val) { void SetTransparent(bool val) {
EnsureConfiguring(); EnsureConfiguring();
transparent_ = val; transparent_ = val;
@ -22,7 +21,7 @@ class EmptyComponent : public RenderComponent {
void WriteConfig() override { ConfigForEmpty(transparent_); } void WriteConfig() override { ConfigForEmpty(transparent_); }
private: private:
bool transparent_; bool transparent_{};
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -113,6 +113,14 @@ class ObjectComponent : public RenderComponent {
void WriteConfig() override; void WriteConfig() override;
protected: protected:
ReflectionType reflection_{ReflectionType::kNone};
LightShadowType light_shadow_{LightShadowType::kObject};
bool world_space_ : 1 {};
bool transparent_ : 1 {};
bool premultiplied_ : 1 {};
bool have_color_add_ : 1 {};
bool double_sided_ : 1 {};
bool do_colorize_2_ : 1 {};
float color_r_{1.0f}; float color_r_{1.0f};
float color_g_{1.0f}; float color_g_{1.0f};
float color_b_{1.0f}; float color_b_{1.0f};
@ -133,14 +141,6 @@ class ObjectComponent : public RenderComponent {
float reflection_scale_b_{1.0f}; float reflection_scale_b_{1.0f};
Object::Ref<TextureAsset> texture_; Object::Ref<TextureAsset> texture_;
Object::Ref<TextureAsset> colorize_texture_; Object::Ref<TextureAsset> colorize_texture_;
ReflectionType reflection_{ReflectionType::kNone};
LightShadowType light_shadow_{LightShadowType::kObject};
bool world_space_{};
bool transparent_{};
bool premultiplied_{};
bool have_color_add_{};
bool double_sided_{};
bool do_colorize_2_{};
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -9,8 +9,7 @@ namespace ballistica::base {
class PostProcessComponent : public RenderComponent { class PostProcessComponent : public RenderComponent {
public: public:
explicit PostProcessComponent(RenderPass* pass) explicit PostProcessComponent(RenderPass* pass) : RenderComponent(pass) {}
: RenderComponent(pass), normal_distort_(0.0f), eyes_(false) {}
void SetNormalDistort(float d) { void SetNormalDistort(float d) {
EnsureConfiguring(); EnsureConfiguring();
normal_distort_ = d; normal_distort_ = d;
@ -22,8 +21,8 @@ class PostProcessComponent : public RenderComponent {
protected: protected:
void WriteConfig() override; void WriteConfig() override;
bool eyes_; bool eyes_ : 1 {};
float normal_distort_; float normal_distort_{};
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -7,35 +7,10 @@
namespace ballistica::base { namespace ballistica::base {
// used for UI and overlays and things - no world tinting/etc is applied /// Used for UI and overlays and things; no world tinting/etc is applied.
class SimpleComponent : public RenderComponent { class SimpleComponent : public RenderComponent {
public: public:
explicit SimpleComponent(RenderPass* pass) explicit SimpleComponent(RenderPass* pass) : RenderComponent(pass) {}
: RenderComponent(pass),
color_r_(1.0f),
color_g_(1.0f),
color_b_(1.0f),
color_a_(1.0f),
colorize_color_r_(1.0f),
colorize_color_g_(1.0f),
colorize_color_b_(1.0f),
colorize_color_a_(1.0f),
colorize_color2_r_(1.0f),
colorize_color2_g_(1.0f),
colorize_color2_b_(1.0f),
colorize_color2_a_(1.0f),
shadow_offset_x_(0.0f),
shadow_offset_y_(0.0f),
shadow_blur_(0.0f),
shadow_opacity_(0.0f),
glow_amount_(0.0f),
glow_blur_(0.0f),
flatness_(0.0f),
transparent_(false),
premultiplied_(false),
have_color_(false),
double_sided_(false),
do_colorize_2_(false) {}
void SetPremultiplied(bool val) { void SetPremultiplied(bool val) {
EnsureConfiguring(); EnsureConfiguring();
@ -56,16 +31,16 @@ class SimpleComponent : public RenderComponent {
EnsureConfiguring(); EnsureConfiguring();
texture_ = t; texture_ = t;
} }
// used with colorize color 1 and 2
// red areas of the texture will get multiplied by colorize-color1 /// Used with colorize color 1 and 2. Red areas of the texture will get
// and green areas by colorize-color2 /// multiplied by colorize-color1 and green areas by colorize-color2.
void SetColorizeTexture(TextureAsset* t) { void SetColorizeTexture(TextureAsset* t) {
EnsureConfiguring(); EnsureConfiguring();
colorize_texture_ = t; colorize_texture_ = t;
} }
// Red multiplies source color, green adds colorize1-color, and blue adds /// Red multiplies source color, green adds colorize1-color, and blue adds
// white (currently requires colorize1 and colorize 2 to be set). /// white (currently requires colorize1 and colorize 2 to be set).
void SetMaskTexture(TextureAsset* t) { void SetMaskTexture(TextureAsset* t) {
EnsureConfiguring(); EnsureConfiguring();
mask_texture_ = t; mask_texture_ = t;
@ -124,10 +99,10 @@ class SimpleComponent : public RenderComponent {
do_colorize_2_ = true; do_colorize_2_ = true;
} }
void SetShadow(float offsetX, float offsetY, float blur, float opacity) { void SetShadow(float offset_x, float offset_y, float blur, float opacity) {
EnsureConfiguring(); EnsureConfiguring();
shadow_offset_x_ = offsetX; shadow_offset_x_ = offset_x;
shadow_offset_y_ = offsetY; shadow_offset_y_ = offset_y;
shadow_blur_ = blur; shadow_blur_ = blur;
shadow_opacity_ = opacity; shadow_opacity_ = opacity;
} }
@ -147,23 +122,34 @@ class SimpleComponent : public RenderComponent {
void WriteConfig() override; void WriteConfig() override;
protected: protected:
float color_r_, color_g_, color_b_, color_a_; bool do_colorize_2_ : 1 {};
float colorize_color_r_, colorize_color_g_, colorize_color_b_, bool transparent_ : 1 {};
colorize_color_a_; bool premultiplied_ : 1 {};
float colorize_color2_r_, colorize_color2_g_, colorize_color2_b_, bool have_color_ : 1 {};
colorize_color2_a_; bool double_sided_ : 1 {};
float shadow_offset_x_, shadow_offset_y_, shadow_blur_, shadow_opacity_; float color_r_{1.0f};
float glow_amount_, glow_blur_; float color_g_{1.0f};
float flatness_; float color_b_{1.0f};
float color_a_{1.0f};
float colorize_color_r_{1.0f};
float colorize_color_g_{1.0f};
float colorize_color_b_{1.0f};
float colorize_color_a_{1.0f};
float colorize_color2_r_{1.0f};
float colorize_color2_g_{1.0f};
float colorize_color2_b_{1.0f};
float colorize_color2_a_{1.0f};
float shadow_offset_x_{};
float shadow_offset_y_{};
float shadow_blur_{};
float shadow_opacity_{};
float glow_amount_{};
float glow_blur_{};
float flatness_{};
Object::Ref<TextureAsset> texture_; Object::Ref<TextureAsset> texture_;
Object::Ref<TextureAsset> colorize_texture_; Object::Ref<TextureAsset> colorize_texture_;
Object::Ref<TextureAsset> mask_texture_; Object::Ref<TextureAsset> mask_texture_;
Object::Ref<TextureAsset> mask_uv2_texture_; Object::Ref<TextureAsset> mask_uv2_texture_;
bool do_colorize_2_;
bool transparent_;
bool premultiplied_;
bool have_color_;
bool double_sided_;
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -9,13 +9,8 @@ namespace ballistica::base {
class SmokeComponent : public RenderComponent { class SmokeComponent : public RenderComponent {
public: public:
explicit SmokeComponent(RenderPass* pass) explicit SmokeComponent(RenderPass* pass) : RenderComponent(pass) {}
: RenderComponent(pass),
color_r_(1.0f),
color_g_(1.0f),
color_b_(1.0f),
color_a_(1.0f),
overlay_(false) {}
void SetColor(float r, float g, float b, float a = 1.0f) { void SetColor(float r, float g, float b, float a = 1.0f) {
EnsureConfiguring(); EnsureConfiguring();
color_r_ = r; color_r_ = r;
@ -23,6 +18,7 @@ class SmokeComponent : public RenderComponent {
color_b_ = b; color_b_ = b;
color_a_ = a; color_a_ = a;
} }
void SetOverlay(bool overlay) { void SetOverlay(bool overlay) {
EnsureConfiguring(); EnsureConfiguring();
overlay_ = overlay; overlay_ = overlay;
@ -30,8 +26,12 @@ class SmokeComponent : public RenderComponent {
protected: protected:
void WriteConfig() override; void WriteConfig() override;
float color_r_, color_g_, color_b_, color_a_;
bool overlay_; bool overlay_ : 1 {};
float color_r_{1.0f};
float color_g_{1.0f};
float color_b_{1.0f};
float color_a_{1.0f};
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -37,9 +37,9 @@ class SpriteComponent : public RenderComponent {
protected: protected:
void WriteConfig() override; void WriteConfig() override;
bool have_color_{}; bool have_color_ : 1 {};
bool camera_aligned_{}; bool camera_aligned_ : 1 {};
bool overlay_{}; bool overlay_ : 1 {};
uint8_t exponent_{1}; uint8_t exponent_{1};
float color_r_{1.0f}; float color_r_{1.0f};
float color_g_{1.0f}; float color_g_{1.0f};

View File

@ -106,8 +106,6 @@ void Graphics::DoApplyAppConfig() {
show_fps_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowFPS); show_fps_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowFPS);
show_ping_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowPing); show_ping_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowPing);
// tv_border_ =
// g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder);
bool disable_camera_shake = bool disable_camera_shake =
g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraShake); g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraShake);
@ -133,6 +131,7 @@ void Graphics::UpdateInitialGraphicsSettingsSend_() {
// We need to send an initial graphics-settings to the server to kick // We need to send an initial graphics-settings to the server to kick
// things off, but we need a few things to be in place first. // things off, but we need a few things to be in place first.
auto app_config_ready = applied_app_config_; auto app_config_ready = applied_app_config_;
// At some point we may want to wait to know our actual screen res before // At some point we may want to wait to know our actual screen res before
// sending. This won't apply everywhere though since on some platforms the // sending. This won't apply everywhere though since on some platforms the
// screen doesn't exist until we send this. // screen doesn't exist until we send this.
@ -149,7 +148,7 @@ void Graphics::UpdateInitialGraphicsSettingsSend_() {
// explicitly increment its refcount here in the logic thread now and // explicitly increment its refcount here in the logic thread now and
// then push a call back here to decrement it when we're done. // then push a call back here to decrement it when we're done.
settings->ObjectIncrementStrongRefCount(); settings->ObjectIncrementStrongRefCount();
// auto* s = settings_.Get();
g_base->app_adapter->PushGraphicsContextCall([settings] { g_base->app_adapter->PushGraphicsContextCall([settings] {
assert(g_base->app_adapter->InGraphicsContext()); assert(g_base->app_adapter->InGraphicsContext());
g_base->graphics_server->ApplySettings(settings->Get()); g_base->graphics_server->ApplySettings(settings->Get());
@ -466,9 +465,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
if (now - it->second->LastUsedTime() > 1000) { if (now - it->second->LastUsedTime() > 1000) {
it = debug_graphs_.erase(it); it = debug_graphs_.erase(it);
} else { } else {
it->second->Draw(pass, it->second->Draw(pass, g_base->logic->display_time() * 1000.0, 50.0f,
static_cast<double>(g_core->GetAppTimeMillisecs()), debug_graph_y, 500.0f, 100.0f);
50.0f, debug_graph_y, 500.0f, 100.0f);
debug_graph_y += 110.0f; debug_graph_y += 110.0f;
++it; ++it;
@ -581,6 +579,9 @@ auto Graphics::GetGraphicsSettingsSnapshot() -> Snapshot<GraphicsSettings>* {
new_settings->index = next_settings_index_++; new_settings->index = next_settings_index_++;
settings_snapshot_ = Object::New<Snapshot<GraphicsSettings>>(new_settings); settings_snapshot_ = Object::New<Snapshot<GraphicsSettings>>(new_settings);
graphics_settings_dirty_ = false; graphics_settings_dirty_ = false;
// This can affect placeholder settings; keep those up to date.
UpdatePlaceholderSettings();
} }
assert(settings_snapshot_.Exists()); assert(settings_snapshot_.Exists());
return settings_snapshot_.Get(); return settings_snapshot_.Get();
@ -1618,7 +1619,6 @@ void Graphics::LanguageChanged() {
Log(LogLevel::kWarning, Log(LogLevel::kWarning,
"Graphics::LanguageChanged() called during draw; should not happen."); "Graphics::LanguageChanged() called during draw; should not happen.");
} }
screenmessages->ClearScreenMessageTranslations(); screenmessages->ClearScreenMessageTranslations();
} }
@ -1665,19 +1665,31 @@ auto Graphics::TextureQualityFromRequest(TextureQualityRequest request,
void Graphics::set_client_context(Snapshot<GraphicsClientContext>* context) { void Graphics::set_client_context(Snapshot<GraphicsClientContext>* context) {
assert(g_base->InLogicThread()); assert(g_base->InLogicThread());
// Currently we only expect this to be set once. That will change // Currently we only expect this to be set once. That will change once we
// once we support renderer swapping/etc. // support renderer swapping/etc.
assert(!g_base->logic->graphics_ready()); assert(!g_base->logic->graphics_ready());
assert(!client_context_snapshot_.Exists()); assert(!client_context_snapshot_.Exists());
client_context_snapshot_ = context; client_context_snapshot_ = context;
// Update our static placeholder value (we don't want to calc it dynamically // Placeholder settings are affected by client context, so update them
// since it can be accessed from other threads). // when it changes.
texture_quality_placeholder_ = TextureQualityFromRequest( UpdatePlaceholderSettings();
settings()->texture_quality, client_context()->auto_texture_quality);
// Let the logic system know its free to proceed beyond bootstrapping. // Let the logic system know its free to proceed beyond bootstrapping.
g_base->logic->OnGraphicsReady(); g_base->logic->OnGraphicsReady();
} }
// This call exists for the graphics-server to call when they've changed
void Graphics::UpdatePlaceholderSettings() {
assert(g_base->InLogicThread());
// Need both of these in place.
if (!settings_snapshot_.Exists() || !has_client_context()) {
return;
}
texture_quality_placeholder_ = TextureQualityFromRequest(
settings()->texture_quality, client_context()->auto_texture_quality);
}
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -320,6 +320,8 @@ class Graphics {
/// Called by the graphics-server when a new client context is ready. /// Called by the graphics-server when a new client context is ready.
void set_client_context(Snapshot<GraphicsClientContext>* context); void set_client_context(Snapshot<GraphicsClientContext>* context);
void UpdatePlaceholderSettings();
auto has_client_context() -> bool { auto has_client_context() -> bool {
return client_context_snapshot_.Exists(); return client_context_snapshot_.Exists();
} }

View File

@ -66,7 +66,8 @@ void GraphicsServer::ApplySettings(const GraphicsSettings* settings) {
// gathered for themself. // gathered for themself.
g_base->app_adapter->ApplyGraphicsSettings(settings); g_base->app_adapter->ApplyGraphicsSettings(settings);
// Lastly, if we've not yet sent a context to the client, do so. // If we've not yet sent a context to the client, do so. At some point we
// may support re-sending this if there are settings that change.
if (client_context_ == nullptr) { if (client_context_ == nullptr) {
set_client_context(g_base->app_adapter->GetGraphicsClientContext()); set_client_context(g_base->app_adapter->GetGraphicsClientContext());
} }
@ -387,58 +388,6 @@ void GraphicsServer::UnloadRenderer() {
renderer_loaded_ = false; renderer_loaded_ = false;
} }
// Given physical res, calculate virtual res.
// void GraphicsServer::CalcVirtualRes_(float* x, float* y) {
// float x_in = *x;
// float y_in = *y;
// if (*x / *y > static_cast<float>(kBaseVirtualResX)
// / static_cast<float>(kBaseVirtualResY)) {
// *y = kBaseVirtualResY;
// *x = *y * (x_in / y_in);
// } else {
// *x = kBaseVirtualResX;
// *y = *x * (y_in / x_in);
// }
// }
// void GraphicsServer::UpdateVirtualScreenRes_() {
// assert(g_base->app_adapter->InGraphicsContext());
// // In vr mode our virtual res is independent of our screen size.
// // (since it gets drawn to an overlay)
// if (g_core->IsVRMode()) {
// res_x_virtual_ = kBaseVirtualResX;
// res_y_virtual_ = kBaseVirtualResY;
// } else {
// res_x_virtual_ = res_x_;
// res_y_virtual_ = res_y_;
// CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_);
// }
// }
// void GraphicsServer::SetScreenResolution(float h, float v) {
// assert(g_base->app_adapter->InGraphicsContext());
// // Ignore redundant sets.
// if (res_x_ == h && res_y_ == v) {
// return;
// }
// res_x_ = h;
// res_y_ = v;
// // UpdateVirtualScreenRes_();
// // Inform renderer of the change.
// if (renderer_) {
// renderer_->OnScreenSizeChange();
// }
// // Inform all logic thread bits of this change.
// g_base->logic->event_loop()->PushCall(
// [vx = res_x_virtual_, vy = res_y_virtual_, x = res_x_, y = res_y_] {
// g_base->graphics->SetScreenSize(vx, vy, x, y);
// });
// }
// FIXME: Shouldn't have android-specific code in here. // FIXME: Shouldn't have android-specific code in here.
void GraphicsServer::HandlePushAndroidRes(const std::string& android_res) { void GraphicsServer::HandlePushAndroidRes(const std::string& android_res) {
if (g_buildconfig.ostype_android()) { if (g_buildconfig.ostype_android()) {
@ -578,16 +527,6 @@ void GraphicsServer::PushReloadMediaCall() {
g_base->app_adapter->PushGraphicsContextCall([this] { ReloadMedia_(); }); g_base->app_adapter->PushGraphicsContextCall([this] { ReloadMedia_(); });
} }
// void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) {
// g_base->app_adapter->PushGraphicsContextCall([this, pixel_scale] {
// assert(g_base->app_adapter->InGraphicsContext());
// if (!renderer_) {
// return;
// }
// renderer_->set_pixel_scale(pixel_scale);
// });
// }
void GraphicsServer::PushComponentUnloadCall( void GraphicsServer::PushComponentUnloadCall(
const std::vector<Object::Ref<Asset>*>& components) { const std::vector<Object::Ref<Asset>*>& components) {
g_base->app_adapter->PushGraphicsContextCall([components] { g_base->app_adapter->PushGraphicsContextCall([components] {

View File

@ -330,7 +330,6 @@ class GraphicsServer {
bool cam_orient_matrix_dirty_ : 1 {true}; bool cam_orient_matrix_dirty_ : 1 {true};
bool shutting_down_ : 1 {}; bool shutting_down_ : 1 {};
bool shutdown_completed_ : 1 {}; bool shutdown_completed_ : 1 {};
Snapshot<GraphicsClientContext>* client_context_{};
float res_x_{}; float res_x_{};
float res_y_{}; float res_y_{};
float res_x_virtual_{}; float res_x_virtual_{};
@ -353,6 +352,7 @@ class GraphicsServer {
Vector3f cam_target_{0.0f, 0.0f, 0.0f}; Vector3f cam_target_{0.0f, 0.0f, 0.0f};
Matrix44f light_shadow_projection_matrix_{kMatrix44fIdentity}; Matrix44f light_shadow_projection_matrix_{kMatrix44fIdentity};
Matrix44f cam_orient_matrix_ = kMatrix44fIdentity; Matrix44f cam_orient_matrix_ = kMatrix44fIdentity;
Snapshot<GraphicsClientContext>* client_context_{};
std::vector<Matrix44f> model_view_stack_; std::vector<Matrix44f> model_view_stack_;
std::list<MeshData*> mesh_datas_; std::list<MeshData*> mesh_datas_;
Renderer* renderer_{}; Renderer* renderer_{};

View File

@ -48,42 +48,30 @@ auto InputDevice::GetPersistentIdentifier() const -> std::string {
InputDevice::~InputDevice() { assert(g_base->InLogicThread()); } InputDevice::~InputDevice() { assert(g_base->InLogicThread()); }
// Called to let the current host/client-session know that we'd like to control // Called to let the current host/client-session know that we'd like to
// something please. // control something please.
void InputDevice::RequestPlayer() { void InputDevice::RequestPlayer() {
assert(g_base->InLogicThread()); assert(g_base->InLogicThread());
// Make note that we're being used in some way. // Make note that we're being used in some way.
last_input_time_millisecs_ = last_input_time_millisecs_ =
static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0); static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0);
// Tracking down a bug.
BA_PRECONDITION_FATAL(delegate_.Exists());
delegate_->RequestPlayer(); delegate_->RequestPlayer();
} }
// If we're attached to a remote player, ship completed packets every now and // If we're attached to a remote player, ship completed packets every now
// then. // and then.
void InputDevice::Update() { void InputDevice::Update() { delegate_->Update(); }
// Tracking down a bug.
BA_PRECONDITION_FATAL(delegate_.Exists());
delegate_->Update();
}
auto InputDevice::AttachedToPlayer() const -> bool { auto InputDevice::AttachedToPlayer() const -> bool {
// Tracking down a bug.
BA_PRECONDITION_FATAL(delegate_.Exists());
return delegate_->AttachedToPlayer(); return delegate_->AttachedToPlayer();
} }
void InputDevice::DetachFromPlayer() { void InputDevice::DetachFromPlayer() { delegate_->DetachFromPlayer(); }
// Tracking down a bug.
BA_PRECONDITION_FATAL(delegate_.Exists());
delegate_->DetachFromPlayer();
}
void InputDevice::UpdateLastInputTime() { void InputDevice::UpdateLastInputTime() {
// Keep our own individual time, and also let // Keep our own individual time, and also let the overall input system
// the overall input system know something happened. // know something happened.
last_input_time_millisecs_ = last_input_time_millisecs_ =
static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0); static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0);
g_base->input->MarkInputActive(); g_base->input->MarkInputActive();
@ -95,8 +83,6 @@ void InputDevice::InputCommand(InputType type, float value) {
// Make note that we're being used in some way. // Make note that we're being used in some way.
UpdateLastInputTime(); UpdateLastInputTime();
// Tracking down a bug.
BA_PRECONDITION_FATAL(delegate_.Exists());
delegate_->InputCommand(type, value); delegate_->InputCommand(type, value);
} }

View File

@ -112,10 +112,11 @@ auto Input::GetNewNumberedIdentifier_(const std::string& name,
} }
if (!in_use) { if (!in_use) {
// Ok so far its unused.. however input devices that provide non-empty // Ok so far its unused.. however input devices that provide non-empty
// identifiers (serial number, usb-id, etc) reserve their number for the // identifiers (serial number, usb-id, etc) reserve their number for
// duration of the game, so we need to check against all reserved numbers // the duration of the game, so we need to check against all reserved
// so we don't steal someones... (so that if they disconnect and reconnect // numbers so we don't steal someones... (so that if they disconnect
// they'll get the same number and thus the same name, etc) // and reconnect they'll get the same number and thus the same name,
// etc)
if (!identifier.empty()) { if (!identifier.empty()) {
auto i = reserved_identifiers_.find(name); auto i = reserved_identifiers_.find(name);
if (i != reserved_identifiers_.end()) { if (i != reserved_identifiers_.end()) {
@ -144,10 +145,6 @@ auto Input::GetNewNumberedIdentifier_(const std::string& name,
return full_id; return full_id;
} }
// void Input::CreateTouchInput() {
// assert(g_core->InMainThread());
// }
void Input::AnnounceConnects_() { void Input::AnnounceConnects_() {
assert(g_base->InLogicThread()); assert(g_base->InLogicThread());
@ -308,10 +305,10 @@ void Input::AddInputDevice(InputDevice* device, bool standard_message) {
} }
// We also want to give this input-device as unique an identifier as // We also want to give this input-device as unique an identifier as
// possible. We ask it for its own string which hopefully includes a serial // possible. We ask it for its own string which hopefully includes a
// or something, but if it doesn't and thus matches an already-existing one, // serial or something, but if it doesn't and thus matches an
// we tack an index on to it. that way we can at least uniquely address them // already-existing one, we tack an index on to it. that way we can at
// based off how many are connected. // least uniquely address them based off how many are connected.
device->set_number(GetNewNumberedIdentifier_(device->GetRawDeviceName(), device->set_number(GetNewNumberedIdentifier_(device->GetRawDeviceName(),
device->GetDeviceIdentifier())); device->GetDeviceIdentifier()));
@ -325,23 +322,11 @@ void Input::AddInputDevice(InputDevice* device, bool standard_message) {
device->UpdateMapping(); device->UpdateMapping();
// Need to do this after updating controls, as some control settings can // Need to do this after updating controls, as some control settings can
// affect things we count (such as whether start activates default button). // affect things we count (such as whether start activates default
// button).
UpdateInputDeviceCounts_(); UpdateInputDeviceCounts_();
} }
if (g_buildconfig.ostype_macos()) {
// Special case: on mac, the first time a iOS/Mac controller is connected,
// let the user know they may want to enable them if they're currently set
// as ignored. (the default at the moment is to only use classic device
// support).
static bool printed_ios_mac_controller_warning = false;
if (!printed_ios_mac_controller_warning && ignore_mfi_controllers_
&& device->IsMFiController()) {
ScreenMessage(R"({"r":"macControllerSubsystemMFiNoteText"})", {1, 1, 0});
printed_ios_mac_controller_warning = true;
}
}
if (standard_message && !device->ShouldBeHiddenFromUser()) { if (standard_message && !device->ShouldBeHiddenFromUser()) {
ShowStandardInputDeviceConnectedMessage_(device); ShowStandardInputDeviceConnectedMessage_(device);
} }
@ -362,16 +347,16 @@ void Input::RemoveInputDevice(InputDevice* input, bool standard_message) {
ShowStandardInputDeviceDisconnectedMessage_(input); ShowStandardInputDeviceDisconnectedMessage_(input);
} }
// Just look for it in our list.. if we find it, simply clear the ref // Just look for it in our list.. if we find it, simply clear the ref (we
// (we need to keep the ref around so our list indices don't change). // need to keep the ref around so our list indices don't change).
for (auto& input_device : input_devices_) { for (auto& input_device : input_devices_) {
if (input_device.Exists() && (input_device.Get() == input)) { if (input_device.Exists() && (input_device.Get() == input)) {
// Pull it off the list before killing it (in case it tries to trigger // Pull it off the list before killing it (in case it tries to trigger
// another kill itself). // another kill itself).
auto device = Object::Ref<InputDevice>(input_device); auto device = Object::Ref<InputDevice>(input_device);
// Ok we cleared its slot in our vector; now we just have // Ok we cleared its slot in our vector; now we just have the local
// the local variable 'device' keeping it alive. // variable 'device' keeping it alive.
input_device.Clear(); input_device.Clear();
// Tell it to detach from anything it is controlling. // Tell it to detach from anything it is controlling.
@ -519,41 +504,7 @@ auto Input::GetConfigurableGamePads() -> std::vector<InputDevice*> {
auto Input::ShouldCompletelyIgnoreInputDevice(InputDevice* input_device) auto Input::ShouldCompletelyIgnoreInputDevice(InputDevice* input_device)
-> bool { -> bool {
if (g_buildconfig.ostype_macos()) { return false;
if (ignore_mfi_controllers_ && input_device->IsMFiController()) {
return true;
}
}
return ignore_sdl_controllers_ && input_device->IsSDLController();
}
void Input::UpdateEnabledControllerSubsystems_() {
assert(g_base);
// First off, on mac, let's update whether we want to completely ignore
// either the classic or the iOS/Mac controller subsystems.
//
// UPDATE - these days we're mfi-only on our xcode builds (which should
// support older controllers too). So we don't need to touch ignore vals
// anywhere since we'll not get sdl ones on those builds.
// if (g_buildconfig.ostype_macos()) {
// std::string sys = g_base->app_config->Resolve(
// AppConfig::StringID::kMacControllerSubsystem);
// if (sys == "Classic") {
// ignore_mfi_controllers_ = true;
// ignore_sdl_controllers_ = false;
// } else if (sys == "MFi") {
// ignore_mfi_controllers_ = false;
// ignore_sdl_controllers_ = true;
// } else if (sys == "Both") {
// ignore_mfi_controllers_ = false;
// ignore_sdl_controllers_ = false;
// } else {
// BA_LOG_ONCE(LogLevel::kError,
// "Invalid mac-controller-subsystem value: '" + sys + "'");
// }
// }
} }
void Input::OnAppStart() { void Input::OnAppStart() {
@ -577,8 +528,6 @@ void Input::OnAppShutdownComplete() { assert(g_base->InLogicThread()); }
void Input::DoApplyAppConfig() { void Input::DoApplyAppConfig() {
assert(g_base->InLogicThread()); assert(g_base->InLogicThread());
UpdateEnabledControllerSubsystems_();
// It's technically possible that updating these controls will add or // It's technically possible that updating these controls will add or
// remove devices, thus changing the input_devices_ list, so lets work // remove devices, thus changing the input_devices_ list, so lets work
// with a copy of it. // with a copy of it.
@ -612,10 +561,11 @@ void Input::StepDisplayTime() {
} }
} }
// We now need to update our input-device numbers dynamically since they're // We now need to update our input-device numbers dynamically since
// based on recently-active devices. // they're based on recently-active devices. We do this much more often
// ..we do this much more often for the first few seconds to keep // for the first few seconds to keep controller-usage from being as
// controller-usage from being as annoying. // annoying.
// millisecs_t incr = (real_time > 10000) ? 468 : 98; // millisecs_t incr = (real_time > 10000) ? 468 : 98;
// Update: don't remember why that was annoying; trying a single value for // Update: don't remember why that was annoying; trying a single value for
// now. // now.
@ -780,18 +730,18 @@ void Input::PushTextInputEvent(const std::string& text) {
return; return;
} }
// Also ignore if there are any mod keys being held. // Also ignore if there are any mod keys being held. We process some of
// We process some of our own keyboard shortcuts and don't // our own keyboard shortcuts and don't want text input to come through
// want text input to come through at the same time. // at the same time.
if (keys_held_.contains(SDLK_LCTRL) || keys_held_.contains(SDLK_RCTRL) if (keys_held_.contains(SDLK_LCTRL) || keys_held_.contains(SDLK_RCTRL)
|| keys_held_.contains(SDLK_LALT) || keys_held_.contains(SDLK_RALT) || keys_held_.contains(SDLK_LALT) || keys_held_.contains(SDLK_RALT)
|| keys_held_.contains(SDLK_LGUI) || keys_held_.contains(SDLK_RGUI)) { || keys_held_.contains(SDLK_LGUI) || keys_held_.contains(SDLK_RGUI)) {
return; return;
} }
// Ignore back-tick and tilde because we use that key to toggle the console. // Ignore back-tick and tilde because we use that key to toggle the
// FIXME: Perhaps should allow typing it if some control-character is // console. FIXME: Perhaps should allow typing it if some
// held? // control-character is held?
if (text == "`" || text == "~") { if (text == "`" || text == "~") {
return; return;
} }
@ -958,10 +908,9 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
return; return;
} }
// Nowadays we don't want the OS to deliver repeat events to us, // Nowadays we don't want the OS to deliver repeat events to us, so filter
// so filter out any that we get and make noise that they should stop. We // out any that we get and make noise that they should stop. We explicitly
// explicitly handle repeats for UI purposes at the InputDevice or Widget // handle repeats for UI purposes at the InputDevice or Widget level now.
// level now.
if (keys_held_.find(keysym.sym) != keys_held_.end()) { if (keys_held_.find(keysym.sym) != keys_held_.end()) {
// Look out for several repeats coming in within the span of a few // Look out for several repeats coming in within the span of a few
// seconds and complain if it happens. This should allow for the random // seconds and complain if it happens. This should allow for the random
@ -993,9 +942,9 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
} }
} }
// Regardless of what else we do, keep track of mod key states. // Regardless of what else we do, keep track of mod key states. (for
// (for things like manual camera moves. For individual key presses // things like manual camera moves. For individual key presses ideally we
// ideally we should use the modifiers bundled with the key presses) // should use the modifiers bundled with the key presses)
UpdateModKeyStates_(&keysym, true); UpdateModKeyStates_(&keysym, true);
// Mobile-specific stuff. // Mobile-specific stuff.
@ -1317,9 +1266,9 @@ void Input::HandleMouseMotion_(const Vector2f& position) {
last_mouse_move_time_ = g_core->GetAppTimeSeconds(); last_mouse_move_time_ = g_core->GetAppTimeSeconds();
mouse_move_count_++; mouse_move_count_++;
// If we have a touch-input in editing mode, pass along events to it. // If we have a touch-input in editing mode, pass along events to it. (it
// (it usually handles its own events but here we want it to play nice // usually handles its own events but here we want it to play nice with
// with stuff under it by blocking touches, etc) // stuff under it by blocking touches, etc)
if (touch_input_ && touch_input_->editing()) { if (touch_input_ && touch_input_->editing()) {
touch_input_->HandleTouchMoved(reinterpret_cast<void*>(1), cursor_pos_x_, touch_input_->HandleTouchMoved(reinterpret_cast<void*>(1), cursor_pos_x_,
cursor_pos_y_); cursor_pos_y_);

View File

@ -157,7 +157,6 @@ class Input {
void UpdateInputDeviceCounts_(); void UpdateInputDeviceCounts_();
auto GetNewNumberedIdentifier_(const std::string& name, auto GetNewNumberedIdentifier_(const std::string& name,
const std::string& identifier) -> int; const std::string& identifier) -> int;
void UpdateEnabledControllerSubsystems_();
void AnnounceConnects_(); void AnnounceConnects_();
void AnnounceDisconnects_(); void AnnounceDisconnects_();
void HandleKeyPressSimple_(int keycode); void HandleKeyPressSimple_(int keycode);
@ -190,8 +189,6 @@ class Input {
bool have_button_using_inputs_ : 1 {}; bool have_button_using_inputs_ : 1 {};
bool have_start_activated_default_button_inputs_ : 1 {}; bool have_start_activated_default_button_inputs_ : 1 {};
bool have_non_touch_inputs_ : 1 {}; bool have_non_touch_inputs_ : 1 {};
bool ignore_mfi_controllers_ : 1 {};
bool ignore_sdl_controllers_ : 1 {};
millisecs_t input_idle_time_{}; millisecs_t input_idle_time_{};
millisecs_t last_get_local_active_input_device_count_check_time_{}; millisecs_t last_get_local_active_input_device_count_check_time_{};
float cursor_pos_x_{}; float cursor_pos_x_{};

View File

@ -93,6 +93,30 @@ void BasePlatformApple::LoginAdapterBackEndActiveChange(
#endif #endif
} }
auto BasePlatformApple::SupportsOpenDirExternally() -> bool {
#if BA_XCODE_BUILD && BA_OSTYPE_MACOS
return true;
#else
return BasePlatform::SupportsOpenDirExternally();
#endif
}
void BasePlatformApple::OpenDirExternally(const std::string& path) {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
BallisticaKit::CocoaFromCpp::openDirExternally(path);
#else
BasePlatform::OpenDirExternally(path);
#endif
}
void BasePlatformApple::OpenFileExternally(const std::string& path) {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
BallisticaKit::CocoaFromCpp::openFileExternally(path);
#else
BasePlatform::OpenFileExternally(path);
#endif
}
} // namespace ballistica::base } // namespace ballistica::base
#endif // BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS #endif // BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS

View File

@ -20,6 +20,9 @@ class BasePlatformApple : public BasePlatform {
int attempt_id) override; int attempt_id) override;
void LoginAdapterBackEndActiveChange(const std::string& login_type, void LoginAdapterBackEndActiveChange(const std::string& login_type,
bool active) override; bool active) override;
auto SupportsOpenDirExternally() -> bool override;
void OpenDirExternally(const std::string& path) override;
void OpenFileExternally(const std::string& path) override;
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -221,4 +221,14 @@ void BasePlatform::DoInvokeStringEditor(const std::string& title,
Log(LogLevel::kError, "FIXME: DoInvokeStringEditor() unimplemented"); Log(LogLevel::kError, "FIXME: DoInvokeStringEditor() unimplemented");
} }
auto BasePlatform::SupportsOpenDirExternally() -> bool { return false; }
void BasePlatform::OpenDirExternally(const std::string& path) {
Log(LogLevel::kError, "OpenDirExternally() unimplemented");
}
void BasePlatform::OpenFileExternally(const std::string& path) {
Log(LogLevel::kError, "OpenFileExternally() unimplemented");
}
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -98,6 +98,16 @@ class BasePlatform {
auto ran_base_post_init() const { return ran_base_post_init_; } auto ran_base_post_init() const { return ran_base_post_init_; }
/// Do we support opening dirs exteranlly? (via finder, windows explorer,
/// etc.)
virtual auto SupportsOpenDirExternally() -> bool;
/// Open a directory using the system default method (Finder, etc.)
virtual void OpenDirExternally(const std::string& path);
/// Open a file using the system default method (in another app, etc.)
virtual void OpenFileExternally(const std::string& path);
protected: protected:
/// Pop up a text edit dialog. /// Pop up a text edit dialog.
virtual void DoInvokeStringEditor(const std::string& title, virtual void DoInvokeStringEditor(const std::string& title,

View File

@ -17,6 +17,26 @@ void BasePlatformLinux::DoOpenURL(const std::string& url) {
BasePlatform::DoOpenURL(url); BasePlatform::DoOpenURL(url);
} }
auto BasePlatformLinux::SupportsOpenDirExternally() -> bool { return true; }
void BasePlatformLinux::OpenDirExternally(const std::string& path) {
std::string cmd = std::string("xdg-open \"") + path + "\"";
int result = system(cmd.c_str());
if (result != 0) {
Log(LogLevel::kError, "Got return value " + std::to_string(result)
+ " on xdg-open cmd '" + cmd + "'");
}
}
void BasePlatformLinux::OpenFileExternally(const std::string& path) {
std::string cmd = std::string("xdg-open \"") + path + "\"";
int result = system(cmd.c_str());
if (result != 0) {
Log(LogLevel::kError, "Got return value " + std::to_string(result)
+ " on xdg-open cmd '" + cmd + "'");
}
}
} // namespace ballistica::base } // namespace ballistica::base
#endif // BA_OSTYPE_LINUX #endif // BA_OSTYPE_LINUX

View File

@ -14,6 +14,9 @@ class BasePlatformLinux : public BasePlatform {
public: public:
BasePlatformLinux(); BasePlatformLinux();
void DoOpenURL(const std::string& url) override; void DoOpenURL(const std::string& url) override;
auto SupportsOpenDirExternally() -> bool override;
void OpenDirExternally(const std::string& path) override;
void OpenFileExternally(const std::string& path) override;
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -15,6 +15,7 @@
#include "ballistica/base/logic/logic.h" #include "ballistica/base/logic/logic.h"
#include "ballistica/core/platform/windows/core_platform_windows.h" #include "ballistica/core/platform/windows/core_platform_windows.h"
#include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/generic/utils.h"
namespace ballistica::base { namespace ballistica::base {
@ -62,6 +63,30 @@ void BasePlatformWindows::SetupInterruptHandling() {
} }
} }
auto BasePlatformWindows::SupportsOpenDirExternally() -> bool { return true; }
void BasePlatformWindows::OpenDirExternally(const std::string& path) {
auto r = reinterpret_cast<intptr_t>(
ShellExecute(nullptr, _T("open"), _T("explorer.exe"),
core::CorePlatformWindows::UTF8Decode(path).c_str(), nullptr,
SW_SHOWNORMAL));
if (r <= 32) {
Log(LogLevel::kError, "Error " + std::to_string(r)
+ " on open_dir_externally for '" + path + "'");
}
}
void BasePlatformWindows::OpenFileExternally(const std::string& path) {
auto r = reinterpret_cast<intptr_t>(
ShellExecute(nullptr, _T("open"), _T("notepad.exe"),
core::CorePlatformWindows::UTF8Decode(path).c_str(), nullptr,
SW_SHOWNORMAL));
if (r <= 32) {
Log(LogLevel::kError, "Error " + std::to_string(r)
+ " on open_file_externally for '" + path + "'");
}
}
} // namespace ballistica::base } // namespace ballistica::base
#endif // BA_OSTYPE_WINDOWS #endif // BA_OSTYPE_WINDOWS

View File

@ -16,6 +16,9 @@ class BasePlatformWindows : public BasePlatform {
BasePlatformWindows(); BasePlatformWindows();
void DoOpenURL(const std::string& url) override; void DoOpenURL(const std::string& url) override;
void SetupInterruptHandling() override; void SetupInterruptHandling() override;
auto SupportsOpenDirExternally() -> bool override;
void OpenDirExternally(const std::string& path) override;
void OpenFileExternally(const std::string& path) override;
}; };
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -1395,6 +1395,31 @@ static PyMethodDef PyNativeStackTraceDef = {
"Only use them for debugging.", "Only use them for debugging.",
}; };
// --------------------- supports_open_dir_externally --------------------------
static auto PySupportsOpenDirExternally(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY;
if (g_base->platform->SupportsOpenDirExternally()) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
BA_PYTHON_CATCH;
}
static PyMethodDef PySupportsOpenDirExternallyDef = {
"supports_open_dir_externally", // name
(PyCFunction)PySupportsOpenDirExternally, // method
METH_NOARGS, // flags
"supports_open_dir_externally() -> bool\n"
"\n"
"(internal)\n"
"\n"
"Return whether the current app/platform supports opening dirs externally\n"
"(in the Mac Finder, Windows Explorer, etc.).",
};
// -------------------------- open_dir_externally ------------------------------ // -------------------------- open_dir_externally ------------------------------
static auto PyOpenDirExternally(PyObject* self, PyObject* args, static auto PyOpenDirExternally(PyObject* self, PyObject* args,
@ -1406,7 +1431,7 @@ static auto PyOpenDirExternally(PyObject* self, PyObject* args,
const_cast<char**>(kwlist), &path)) { const_cast<char**>(kwlist), &path)) {
return nullptr; return nullptr;
} }
g_core->platform->OpenDirExternally(path); g_base->platform->OpenDirExternally(path);
Py_RETURN_NONE; Py_RETURN_NONE;
BA_PYTHON_CATCH; BA_PYTHON_CATCH;
} }
@ -1816,6 +1841,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector<PyMethodDef> {
PyGetSimpleSoundDef, PyGetSimpleSoundDef,
PyHasTouchScreenDef, PyHasTouchScreenDef,
PyNativeStackTraceDef, PyNativeStackTraceDef,
PySupportsOpenDirExternallyDef,
PyOpenDirExternallyDef, PyOpenDirExternallyDef,
PyFatalErrorDef, PyFatalErrorDef,
PyDevConsoleAddButtonDef, PyDevConsoleAddButtonDef,

View File

@ -6,6 +6,7 @@
#include "ballistica/base/app_mode/app_mode.h" #include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/simple_component.h" #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/graphics/text/text_graphics.h"
#include "ballistica/base/logic/logic.h" #include "ballistica/base/logic/logic.h"
#include "ballistica/base/platform/base_platform.h" #include "ballistica/base/platform/base_platform.h"

View File

@ -8,7 +8,6 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/renderer/renderer.h" #include "ballistica/base/graphics/renderer/renderer.h"
#include "ballistica/shared/foundation/object.h" #include "ballistica/shared/foundation/object.h"
#include "ballistica/shared/python/python_ref.h" #include "ballistica/shared/python/python_ref.h"

View File

@ -25,13 +25,14 @@ namespace ballistica::core {
CorePlatformApple::CorePlatformApple() = default; CorePlatformApple::CorePlatformApple() = default;
auto CorePlatformApple::GetDeviceV1AccountUUIDPrefix() -> std::string { auto CorePlatformApple::GetDeviceV1AccountUUIDPrefix() -> std::string {
#if BA_OSTYPE_MACOS if (g_buildconfig.ostype_macos()) {
return "m"; return "m";
#elif BA_OSTYPE_IOS_TVOS } else if (g_buildconfig.ostype_ios_tvos()) {
return "i"; return "i";
#else } else {
#error FIXME FatalError("Unhandled V1 UUID case.");
#endif return "";
}
} }
auto CorePlatformApple::DoGetDeviceName() -> std::string { auto CorePlatformApple::DoGetDeviceName() -> std::string {
@ -349,22 +350,6 @@ auto CorePlatformApple::IsOSPlayingMusic() -> bool {
#endif #endif
} }
void CorePlatformApple::OpenFileExternally(const std::string& path) {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
BallisticaKit::CocoaFromCpp::openFileExternally(path);
#else
CorePlatform::OpenFileExternally(path);
#endif
}
void CorePlatformApple::OpenDirExternally(const std::string& path) {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
BallisticaKit::CocoaFromCpp::openDirExternally(path);
#else
CorePlatform::OpenDirExternally(path);
#endif
}
void CorePlatformApple::MacMusicAppInit() { void CorePlatformApple::MacMusicAppInit() {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD #if BA_OSTYPE_MACOS && BA_XCODE_BUILD
BallisticaKit::CocoaFromCpp::macMusicAppInit(); BallisticaKit::CocoaFromCpp::macMusicAppInit();

View File

@ -44,10 +44,7 @@ class CorePlatformApple : public CorePlatform {
void ShowOnlineScoreUI(const std::string& show, const std::string& game, void ShowOnlineScoreUI(const std::string& show, const std::string& game,
const std::string& game_version) override; const std::string& game_version) override;
void ResetAchievements() override; void ResetAchievements() override;
// void GameCenterLogin() override;
auto IsOSPlayingMusic() -> bool override; auto IsOSPlayingMusic() -> bool override;
void OpenFileExternally(const std::string& path) override;
void OpenDirExternally(const std::string& path) override;
void MacMusicAppInit() override; void MacMusicAppInit() override;
auto MacMusicAppGetVolume() -> int override; auto MacMusicAppGetVolume() -> int override;
void MacMusicAppSetVolume(int volume) override; void MacMusicAppSetVolume(int volume) override;

View File

@ -804,14 +804,6 @@ void CorePlatform::SignOutV1() {
Log(LogLevel::kError, "SignOutV1() unimplemented"); Log(LogLevel::kError, "SignOutV1() unimplemented");
} }
void CorePlatform::OpenFileExternally(const std::string& path) {
Log(LogLevel::kError, "OpenFileExternally() unimplemented");
}
void CorePlatform::OpenDirExternally(const std::string& path) {
Log(LogLevel::kError, "OpenDirExternally() unimplemented");
}
void CorePlatform::MacMusicAppInit() { void CorePlatform::MacMusicAppInit() {
Log(LogLevel::kError, "MacMusicAppInit() unimplemented"); Log(LogLevel::kError, "MacMusicAppInit() unimplemented");
} }

View File

@ -384,12 +384,6 @@ class CorePlatform {
/// Pass platform-specific misc-read-vals along to the OS (as a json string). /// Pass platform-specific misc-read-vals along to the OS (as a json string).
virtual void SetPlatformMiscReadVals(const std::string& vals); virtual void SetPlatformMiscReadVals(const std::string& vals);
/// Open a file using the system default method (in another app, etc.)
virtual void OpenFileExternally(const std::string& path);
/// Open a directory using the system default method (Finder, etc.)
virtual void OpenDirExternally(const std::string& path);
/// Set the name of the current thread (for debugging). /// Set the name of the current thread (for debugging).
virtual void SetCurrentThreadName(const std::string& name); virtual void SetCurrentThreadName(const std::string& name);

View File

@ -100,24 +100,6 @@ auto CorePlatformLinux::GetDeviceUUIDInputs() -> std::list<std::string> {
bool CorePlatformLinux::DoHasTouchScreen() { return false; } bool CorePlatformLinux::DoHasTouchScreen() { return false; }
void CorePlatformLinux::OpenFileExternally(const std::string& path) {
std::string cmd = std::string("xdg-open \"") + path + "\"";
int result = system(cmd.c_str());
if (result != 0) {
Log(LogLevel::kError, "Got return value " + std::to_string(result)
+ " on xdg-open cmd '" + cmd + "'");
}
}
void CorePlatformLinux::OpenDirExternally(const std::string& path) {
std::string cmd = std::string("xdg-open \"") + path + "\"";
int result = system(cmd.c_str());
if (result != 0) {
Log(LogLevel::kError, "Got return value " + std::to_string(result)
+ " on xdg-open cmd '" + cmd + "'");
}
}
std::string CorePlatformLinux::GetPlatformName() { return "linux"; } std::string CorePlatformLinux::GetPlatformName() { return "linux"; }
std::string CorePlatformLinux::GetSubplatformName() { std::string CorePlatformLinux::GetSubplatformName() {

View File

@ -16,8 +16,6 @@ class CorePlatformLinux : public CorePlatform {
auto GetDeviceV1AccountUUIDPrefix() -> std::string override { return "l"; } auto GetDeviceV1AccountUUIDPrefix() -> std::string override { return "l"; }
auto GenerateUUID() -> std::string override; auto GenerateUUID() -> std::string override;
auto DoHasTouchScreen() -> bool override; auto DoHasTouchScreen() -> bool override;
void OpenFileExternally(const std::string& path) override;
void OpenDirExternally(const std::string& path) override;
auto GetPlatformName() -> std::string override; auto GetPlatformName() -> std::string override;
auto GetSubplatformName() -> std::string override; auto GetSubplatformName() -> std::string override;
auto GetDeviceUUIDInputs() -> std::list<std::string> override; auto GetDeviceUUIDInputs() -> std::list<std::string> override;

View File

@ -964,26 +964,6 @@ std::string CorePlatformWindows::GetCWD() {
return UTF8Encode(buffer); return UTF8Encode(buffer);
} }
void CorePlatformWindows::OpenFileExternally(const std::string& path) {
auto r = reinterpret_cast<intptr_t>(
ShellExecute(nullptr, _T("open"), _T("notepad.exe"),
UTF8Decode(path).c_str(), nullptr, SW_SHOWNORMAL));
if (r <= 32) {
Log(LogLevel::kError, "Error " + std::to_string(r)
+ " on open_file_externally for '" + path + "'");
}
}
void CorePlatformWindows::OpenDirExternally(const std::string& path) {
auto r = reinterpret_cast<intptr_t>(
ShellExecute(nullptr, _T("open"), _T("explorer.exe"),
UTF8Decode(path).c_str(), nullptr, SW_SHOWNORMAL));
if (r <= 32) {
Log(LogLevel::kError, "Error " + std::to_string(r)
+ " on open_dir_externally for '" + path + "'");
}
}
void CorePlatformWindows::Unlink(const char* path) { _unlink(path); } void CorePlatformWindows::Unlink(const char* path) { _unlink(path); }
void CorePlatformWindows::CloseSocket(int socket) { closesocket(socket); } void CorePlatformWindows::CloseSocket(int socket) { closesocket(socket); }

View File

@ -49,8 +49,6 @@ class CorePlatformWindows : public CorePlatform {
auto GetIsStdinATerminal() -> bool override; auto GetIsStdinATerminal() -> bool override;
auto GetOSVersionString() -> std::string override; auto GetOSVersionString() -> std::string override;
auto GetCWD() -> std::string override; auto GetCWD() -> std::string override;
void OpenFileExternally(const std::string& path) override;
void OpenDirExternally(const std::string& path) override;
void Unlink(const char* path) override; void Unlink(const char* path) override;
void CloseSocket(int socket) override; void CloseSocket(int socket) override;
auto GetBroadcastAddrs() -> std::vector<uint32_t> override; auto GetBroadcastAddrs() -> std::vector<uint32_t> override;

View File

@ -5,6 +5,7 @@
#include "ballistica/base/assets/assets_server.h" #include "ballistica/base/assets/assets_server.h"
#include "ballistica/base/graphics/graphics.h" #include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/support/net_graph.h" #include "ballistica/base/graphics/support/net_graph.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/scene_v1/connection/connection_to_host.h" #include "ballistica/scene_v1/connection/connection_to_host.h"
#include "ballistica/scene_v1/support/scene_v1_app_mode.h" #include "ballistica/scene_v1/support/scene_v1_app_mode.h"
@ -118,24 +119,27 @@ void ClientSessionNet::UpdateBuffering() {
set_consume_rate(new_consume_rate); set_consume_rate(new_consume_rate);
if (g_base->graphics->network_debug_info_display_enabled()) { if (g_base->graphics->network_debug_info_display_enabled()) {
// Plug display time into these graphs to get smoother looking updates.
auto now_d = g_base->logic->display_time() * 1000.0;
if (auto* graph = if (auto* graph =
g_base->graphics->GetDebugGraph("1: packet delay", false)) { g_base->graphics->GetDebugGraph("1: packet delay", false)) {
graph->AddSample(now, current_delay_); graph->AddSample(now_d, current_delay_);
} }
if (auto* graph = if (auto* graph =
g_base->graphics->GetDebugGraph("2: max delay bucketed", false)) { g_base->graphics->GetDebugGraph("2: max delay bucketed", false)) {
graph->AddSample(now, last_bucket_max_delay_); graph->AddSample(now_d, last_bucket_max_delay_);
} }
if (auto* graph = if (auto* graph =
g_base->graphics->GetDebugGraph("3: filtered delay", false)) { g_base->graphics->GetDebugGraph("3: filtered delay", false)) {
graph->AddSample(now, max_delay_smoothed_); graph->AddSample(now_d, max_delay_smoothed_);
} }
if (auto* graph = g_base->graphics->GetDebugGraph("4: run rate", false)) { if (auto* graph = g_base->graphics->GetDebugGraph("4: run rate", false)) {
graph->AddSample(now, new_consume_rate); graph->AddSample(now_d, new_consume_rate);
} }
if (auto* graph = if (auto* graph =
g_base->graphics->GetDebugGraph("5: time buffered", true)) { g_base->graphics->GetDebugGraph("5: time buffered", true)) {
graph->AddSample(now, base_time_buffered()); graph->AddSample(now_d, base_time_buffered());
} }
} }
} }

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21585; const int kEngineBuildNumber = 21588;
const char* kEngineVersion = "1.7.28"; const char* kEngineVersion = "1.7.28";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;

View File

@ -1868,6 +1868,7 @@ static auto PyTextWidget(PyObject* self, PyObject* args, PyObject* keywds)
PyObject* query_max_chars_obj = Py_None; PyObject* query_max_chars_obj = Py_None;
PyObject* query_description_obj = Py_None; PyObject* query_description_obj = Py_None;
PyObject* adapter_finished_obj = Py_None; PyObject* adapter_finished_obj = Py_None;
PyObject* glow_type_obj = Py_None;
static const char* kwlist[] = {"edit", static const char* kwlist[] = {"edit",
"parent", "parent",
@ -1907,9 +1908,10 @@ static auto PyTextWidget(PyObject* self, PyObject* args, PyObject* keywds)
"query_max_chars", "query_max_chars",
"query_description", "query_description",
"adapter_finished", "adapter_finished",
"glow_type",
nullptr}; nullptr};
if (!PyArg_ParseTupleAndKeywords( if (!PyArg_ParseTupleAndKeywords(
args, keywds, "|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", args, keywds, "|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
const_cast<char**>(kwlist), &edit_obj, &parent_obj, &size_obj, const_cast<char**>(kwlist), &edit_obj, &parent_obj, &size_obj,
&pos_obj, &text_obj, &v_align_obj, &h_align_obj, &editable_obj, &pos_obj, &text_obj, &v_align_obj, &h_align_obj, &editable_obj,
&padding_obj, &on_return_press_call_obj, &on_activate_call_obj, &padding_obj, &on_return_press_call_obj, &on_activate_call_obj,
@ -1920,7 +1922,7 @@ static auto PyTextWidget(PyObject* self, PyObject* args, PyObject* keywds)
&shadow_obj, &autoselect_obj, &rotate_obj, &enabled_obj, &shadow_obj, &autoselect_obj, &rotate_obj, &enabled_obj,
&force_internal_editing_obj, &always_show_carat_obj, &big_obj, &force_internal_editing_obj, &always_show_carat_obj, &big_obj,
&extra_touch_border_scale_obj, &res_scale_obj, &query_max_chars_obj, &extra_touch_border_scale_obj, &res_scale_obj, &query_max_chars_obj,
&query_description_obj, &adapter_finished_obj)) &query_description_obj, &adapter_finished_obj, &glow_type_obj))
return nullptr; return nullptr;
if (!g_base->CurrentContext().IsEmpty()) { if (!g_base->CurrentContext().IsEmpty()) {
@ -2123,8 +2125,20 @@ static auto PyTextWidget(PyObject* self, PyObject* args, PyObject* keywds)
throw Exception("Unexpected value for adapter_finished"); throw Exception("Unexpected value for adapter_finished");
} }
} }
if (glow_type_obj != Py_None) {
auto glow_type_s = Python::GetPyString(glow_type_obj);
TextWidget::GlowType glow_type;
if (glow_type_s == "uniform") {
glow_type = TextWidget::GlowType::kUniform;
} else if (glow_type_s == "gradient") {
glow_type = TextWidget::GlowType::kGradient;
} else {
throw Exception("Invalid glow_type: " + glow_type_s, PyExcType::kValue);
}
widget->set_glow_type(glow_type);
}
// if making a new widget add it at the end // If making a new widget, add it at the end.
if (edit_obj == Py_None) { if (edit_obj == Py_None) {
g_ui_v1->AddWidget(widget.Get(), parent_widget); g_ui_v1->AddWidget(widget.Get(), parent_widget);
} }
@ -2175,7 +2189,8 @@ static PyMethodDef PyTextWidgetDef = {
" res_scale: float | None = None," " res_scale: float | None = None,"
" query_max_chars: bauiv1.Widget | None = None,\n" " query_max_chars: bauiv1.Widget | None = None,\n"
" query_description: bauiv1.Widget | None = None,\n" " query_description: bauiv1.Widget | None = None,\n"
" adapter_finished: bool | None = None)\n" " adapter_finished: bool | None = None,\n"
" glow_type: str | None = None)\n"
" -> bauiv1.Widget\n" " -> bauiv1.Widget\n"
"\n" "\n"
"Create or edit a text widget.\n" "Create or edit a text widget.\n"
@ -2725,7 +2740,7 @@ static auto PyOpenFileExternally(PyObject* self, PyObject* args,
const_cast<char**>(kwlist), &path)) { const_cast<char**>(kwlist), &path)) {
return nullptr; return nullptr;
} }
g_core->platform->OpenFileExternally(path); g_base->platform->OpenFileExternally(path);
Py_RETURN_NONE; Py_RETURN_NONE;
BA_PYTHON_CATCH; BA_PYTHON_CATCH;
} }

View File

@ -6,6 +6,7 @@
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/graphics/component/empty_component.h"
#include "ballistica/base/graphics/component/simple_component.h" #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/graphics/text/text_graphics.h"
#include "ballistica/base/input/device/keyboard_input.h" #include "ballistica/base/input/device/keyboard_input.h"
#include "ballistica/base/input/input.h" #include "ballistica/base/input/input.h"
@ -114,8 +115,9 @@ void TextWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
// another component at the end with the matching pop. This only works // another component at the end with the matching pop. This only works
// because the components in the middle wind up writing to the same draw // because the components in the middle wind up writing to the same draw
// list, but there is nothing checking or enforcing that so it would be // list, but there is nothing checking or enforcing that so it would be
// easy to break. Should improve this somehow. (perhaps by using a single // easy to break. Should improve this somehow. (perhaps by using a
// component and enforcing list uniformity between push/pop blocks?) // single component and enforcing list uniformity between push/pop
// blocks?)
c.PushTransform(); c.PushTransform();
// Move to middle, scale down, move back. // Move to middle, scale down, move back.
@ -159,34 +161,68 @@ void TextWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
} }
if (highlight_dirty_) { if (highlight_dirty_) {
float l_border, r_border, b_border, t_border; if (glow_type_ == GlowType::kGradient) {
float l2 = bound_l; float l_border, r_border, b_border, t_border;
float r2 = bound_r; float l2 = bound_l;
float t2 = bound_t; float r2 = bound_r;
float b2 = bound_b; float t2 = bound_t;
l_border = std::max(10.0f, (r2 - l2) * 0.05f); float b2 = bound_b;
r_border = 0; l_border = std::max(10.0f, (r2 - l2) * 0.05f);
b_border = std::max(16.0f, (t2 - b2) * 0.16f); r_border = 0;
t_border = std::max(14.0f, (t2 - b2) * 0.14f); b_border = std::max(16.0f, (t2 - b2) * 0.16f);
highlight_width_ = r2 - l2 + l_border + r_border; t_border = std::max(14.0f, (t2 - b2) * 0.14f);
highlight_height_ = t2 - b2 + b_border + t_border; highlight_width_ = r2 - l2 + l_border + r_border;
highlight_center_x_ = l2 - l_border + highlight_width_ * 0.5f; highlight_height_ = t2 - b2 + b_border + t_border;
highlight_center_y_ = b2 - b_border + highlight_height_ * 0.5f; highlight_center_x_ = l2 - l_border + highlight_width_ * 0.5f;
highlight_center_y_ = b2 - b_border + highlight_height_ * 0.5f;
highlight_mesh_.Clear();
} else {
assert(glow_type_ == GlowType::kUniform);
float corner_radius{30.0f};
float width{bound_r - bound_l};
float height{bound_t - bound_b};
float x_extend{12.0f};
float y_extend{6.0f};
float x_offset{0.0f};
float width_fin = width + x_extend * 2.0f;
float height_fin = height + y_extend * 2.0f;
float x_border = base::NinePatchMesh::BorderForRadius(
corner_radius, width_fin, height_fin);
float y_border = base::NinePatchMesh::BorderForRadius(
corner_radius, height_fin, width_fin);
highlight_mesh_ = Object::New<base::NinePatchMesh>(
-x_extend + x_offset, -y_extend, 0.0f, width_fin, height_fin,
x_border, y_border, x_border, y_border);
}
highlight_dirty_ = false; highlight_dirty_ = false;
} }
base::SimpleComponent c(pass); if (glow_type_ == GlowType::kGradient) {
c.SetTransparent(true); base::SimpleComponent c(pass);
c.SetPremultiplied(true); c.SetTransparent(true);
c.SetColor(0.25f * m, 0.3f * m, 0, 0.3f * m); c.SetPremultiplied(true);
c.SetTexture(g_base->assets->SysTexture(base::SysTextureID::kGlow)); c.SetColor(0.25f * m, 0.3f * m, 0, 0.3f * m);
{ c.SetTexture(g_base->assets->SysTexture(base::SysTextureID::kGlow));
auto xf = c.ScopedTransform(); {
c.Translate(highlight_center_x_, highlight_center_y_, 0.1f); auto xf = c.ScopedTransform();
c.Scale(highlight_width_, highlight_height_); c.Translate(highlight_center_x_, highlight_center_y_, 0.1f);
c.DrawMeshAsset(g_base->assets->SysMesh(base::SysMeshID::kImage4x1)); c.Scale(highlight_width_, highlight_height_);
c.DrawMeshAsset(g_base->assets->SysMesh(base::SysMeshID::kImage4x1));
}
} else {
assert(glow_type_ == GlowType::kUniform);
base::SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(0.9 * m, 1.0f * m, 0, 0.3f * m);
c.SetTexture(
g_base->assets->SysTexture(base::SysTextureID::kShadowSharp));
{
auto xf = c.ScopedTransform();
c.Translate(bound_l, bound_b, 0.1f);
c.DrawMesh(highlight_mesh_.Get());
}
} }
c.Submit();
} }
// Outline. // Outline.
@ -660,7 +696,7 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
} }
} }
// If we're doing inline editing, handle some key events. // If we're doing inline editing, handle some key events.
if (m.has_keysym && !ShouldUseStringEditor_()) { if (editable() && m.has_keysym && !ShouldUseStringEditor_()) {
last_carat_change_time_millisecs_ = last_carat_change_time_millisecs_ =
static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0); static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0);
text_group_dirty_ = true; text_group_dirty_ = true;

View File

@ -21,8 +21,9 @@ class TextWidget : public Widget {
void SetHeight(float heightIn); void SetHeight(float heightIn);
auto GetWidth() -> float override; auto GetWidth() -> float override;
auto GetHeight() -> float override; auto GetHeight() -> float override;
enum class HAlign { kLeft, kCenter, kRight }; enum class HAlign : uint8_t { kLeft, kCenter, kRight };
enum class VAlign { kTop, kCenter, kBottom }; enum class VAlign : uint8_t { kTop, kCenter, kBottom };
enum class GlowType : uint8_t { kGradient, kUniform };
auto HandleMessage(const base::WidgetMessage& m) -> bool override; auto HandleMessage(const base::WidgetMessage& m) -> bool override;
auto IsSelectable() -> bool override { auto IsSelectable() -> bool override {
return (enabled_ && (editable_ || selectable_)); return (enabled_ && (editable_ || selectable_));
@ -87,6 +88,13 @@ class TextWidget : public Widget {
void set_extra_touch_border_scale(float scale) { void set_extra_touch_border_scale(float scale) {
extra_touch_border_scale_ = scale; extra_touch_border_scale_ = scale;
} }
void set_glow_type(GlowType glow_type) {
if (glow_type == glow_type_) {
return;
}
glow_type_ = glow_type;
highlight_dirty_ = true;
}
private: private:
auto ScaleAdjustedX_(float x) -> float; auto ScaleAdjustedX_(float x) -> float;
@ -101,18 +109,35 @@ class TextWidget : public Widget {
float max_height_scale); float max_height_scale);
void DoDrawText_(base::RenderPass* pass, float x_offset, float y_offset, void DoDrawText_(base::RenderPass* pass, float x_offset, float y_offset,
float max_width_scale, float max_height_scale); float max_width_scale, float max_height_scale);
HAlign alignment_h_{HAlign::kLeft};
VAlign alignment_v_{VAlign::kTop};
GlowType glow_type_{GlowType::kGradient};
bool enabled_ : 1 {true};
bool big_ : 1 {};
bool force_internal_editing_ : 1 {};
bool always_show_carat_ : 1 {};
bool highlight_dirty_ : 1 {true};
bool text_translation_dirty_ : 1 {true};
bool text_group_dirty_ : 1 {true};
bool outline_dirty_ : 1 {true};
bool click_activate_ : 1 {};
bool mouse_over_ : 1 {};
bool pressed_ : 1 {};
bool pressed_activate_ : 1 {};
bool always_highlight_ : 1 {};
bool editable_ : 1 {};
bool selectable_ : 1 {};
bool clear_pressed_ : 1 {};
bool clear_mouse_over_ : 1 {};
bool do_clear_button_ : 1 {true};
int carat_position_{9999};
int max_chars_{99999};
float res_scale_{1.0f}; float res_scale_{1.0f};
bool enabled_{true};
millisecs_t birth_time_millisecs_{};
float transition_delay_{}; float transition_delay_{};
float max_width_{-1.0f}; float max_width_{-1.0f};
float max_height_{-1.0f}; float max_height_{-1.0f};
float extra_touch_border_scale_{1.0f}; float extra_touch_border_scale_{1.0f};
Object::Ref<base::TextGroup> text_group_;
bool big_{};
bool force_internal_editing_{};
bool always_show_carat_{};
std::string description_{"Text"};
float highlight_width_{}; float highlight_width_{};
float highlight_height_{}; float highlight_height_{};
float highlight_center_x_{}; float highlight_center_x_{};
@ -124,42 +149,28 @@ class TextWidget : public Widget {
float text_width_{}; float text_width_{};
float text_height_{}; float text_height_{};
float rotate_{}; float rotate_{};
bool highlight_dirty_{true};
bool text_translation_dirty_{true};
bool text_group_dirty_{true};
bool outline_dirty_{true};
bool click_activate_{};
int max_chars_{99999};
float color_r_{1.0f}; float color_r_{1.0f};
float color_g_{1.0f}; float color_g_{1.0f};
float color_b_{1.0f}; float color_b_{1.0f};
float color_a_{1.0f}; float color_a_{1.0f};
bool mouse_over_{}; float flatness_{};
float shadow_{0.5f};
float padding_{}; float padding_{};
bool pressed_{};
bool pressed_activate_{};
bool always_highlight_{};
int carat_position_{9999};
bool editable_{};
bool selectable_{};
float width_{50.0f}; float width_{50.0f};
float height_{30.0f}; float height_{30.0f};
bool clear_pressed_{};
bool clear_mouse_over_{};
bool do_clear_button_{true};
float center_scale_{1.0f}; float center_scale_{1.0f};
std::string text_raw_; std::string text_raw_;
std::string text_translated_; std::string text_translated_;
HAlign alignment_h_{HAlign::kLeft}; millisecs_t birth_time_millisecs_{};
VAlign alignment_v_{VAlign::kTop};
float flatness_{};
float shadow_{0.5f};
millisecs_t last_activate_time_millisecs_{}; millisecs_t last_activate_time_millisecs_{};
millisecs_t last_carat_change_time_millisecs_{}; millisecs_t last_carat_change_time_millisecs_{};
std::string description_{"Text"};
Object::Ref<base::TextGroup> text_group_;
// We keep these at the bottom so they're torn down first. // We keep these at the bottom so they're torn down first.
Object::Ref<base::PythonContextCall> on_return_press_call_; Object::Ref<base::PythonContextCall> on_return_press_call_;
Object::Ref<base::PythonContextCall> on_activate_call_; Object::Ref<base::PythonContextCall> on_activate_call_;
Object::Ref<base::NinePatchMesh> highlight_mesh_;
PythonRef string_edit_adapter_; PythonRef string_edit_adapter_;
}; };