plugins and plugin-settings windows are now screen-size-responsive. Race minigame is now a cheap unlock for new accounts but already unlocked for existing ones.

This commit is contained in:
Eric Froemling 2025-01-25 15:42:24 -08:00
parent ee48a2fe12
commit 8fa95a9f24
No known key found for this signature in database
9 changed files with 209 additions and 142 deletions

60
.efrocachemap generated
View File

@ -432,12 +432,12 @@
"build/assets/ba_data/audio/zoeOw.ogg": "b2d705c31c9dcc1efdc71394764c3beb",
"build/assets/ba_data/audio/zoePickup01.ogg": "e9366dc2d2b8ab8b0c4e2c14c02d0789",
"build/assets/ba_data/audio/zoeScream01.ogg": "903e0e45ee9b3373e9d9ce20c814374e",
"build/assets/ba_data/data/langdata.json": "8d49fa91845f43ec8bff3ad3f4895e69",
"build/assets/ba_data/data/languages/arabic.json": "32b9849fb8389b8c7798f0b744620318",
"build/assets/ba_data/data/langdata.json": "1155a380ac3dafb994b4f7438a6efa4f",
"build/assets/ba_data/data/languages/arabic.json": "955758fcbd6ceaa19c8984ec04dc409b",
"build/assets/ba_data/data/languages/belarussian.json": "009b452aa308bf2b2f7e92d9b78ba5ff",
"build/assets/ba_data/data/languages/chinese.json": "5363a79f843e6be7ef47a840f47cc17d",
"build/assets/ba_data/data/languages/chinesetraditional.json": "bea0f9c17324591b8261015cbd80a265",
"build/assets/ba_data/data/languages/croatian.json": "66be7ada024c5d5cf813a07b75217e48",
"build/assets/ba_data/data/languages/croatian.json": "1ad9d43f30c6d7ed3b39e2a0e8bfae0b",
"build/assets/ba_data/data/languages/czech.json": "3418bee44e69be13b7f72996abe96921",
"build/assets/ba_data/data/languages/danish.json": "8e57db30c5250df2abff14a822f83ea7",
"build/assets/ba_data/data/languages/dutch.json": "4ba5bbcc0fecddd0aac6ee2c165d1e40",
@ -451,7 +451,7 @@
"build/assets/ba_data/data/languages/hindi.json": "567e6976b3c72f891431ad7fcc62ab16",
"build/assets/ba_data/data/languages/hungarian.json": "af801baffb2c06460635dfb04c34bb3e",
"build/assets/ba_data/data/languages/indonesian.json": "607ba358179185f032096ea1978e4448",
"build/assets/ba_data/data/languages/italian.json": "8ed7e5b3a277ed1576af100fc944ef7e",
"build/assets/ba_data/data/languages/italian.json": "656dbe1c77d0d4776f3b095384e8dda2",
"build/assets/ba_data/data/languages/korean.json": "360760d72832863e1a3451b0a514cb08",
"build/assets/ba_data/data/languages/malay.json": "0212e18e54efa202c17505376e5b82fb",
"build/assets/ba_data/data/languages/persian.json": "517217e679c768fff4ffec7f8000ab77",
@ -459,10 +459,10 @@
"build/assets/ba_data/data/languages/polish.json": "993b612c5854fc42a78726ed09c65251",
"build/assets/ba_data/data/languages/portuguese.json": "99eaba2900ab66b05f0e9f22da4792a2",
"build/assets/ba_data/data/languages/romanian.json": "b04345d8c7631d657a69c73eb7be755a",
"build/assets/ba_data/data/languages/russian.json": "780d1857df77ef59104d5dac75415bd6",
"build/assets/ba_data/data/languages/russian.json": "f2d5569c5924f21d02cfa45eabac758c",
"build/assets/ba_data/data/languages/serbian.json": "623fa4129a1154c2f32ed7867e56ff6a",
"build/assets/ba_data/data/languages/slovak.json": "c11c29708b3742cdc2a92b4fa0d6d29f",
"build/assets/ba_data/data/languages/spanish.json": "83baf596f8d29ebb965051bf280424c6",
"build/assets/ba_data/data/languages/spanish.json": "1e429102b451ccb8c392a352624e8a6c",
"build/assets/ba_data/data/languages/swedish.json": "3b179e7333183c70adb0811246b09959",
"build/assets/ba_data/data/languages/tamil.json": "ead39b864228696a9b0d19344bc4b5ec",
"build/assets/ba_data/data/languages/thai.json": "383540a1e9c7c131ac579f51afc87471",
@ -4174,22 +4174,22 @@
"build/assets/windows/Win32/ucrtbased.dll": "bfd1180c269d3950b76f35a63655e9e1",
"build/assets/windows/Win32/vc_redist.x86.exe": "15a5f1f876503885adbdf5b3989b3718",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "92bd286969030fdcc3f0b8ebad115c74",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "711ea2ab6d63356b03ea7a29899afcef",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "513f33f187e85b909793ddd2aa9732a5",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8e9824b44c359d404e2ad8fcf0f448f8",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "3409817015ddf936d5fc293d9d71c706",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "cb054db65cddf26f667d1842b17f2b7d",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "c97f0757f6282a46aad165ab2411818e",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "8302bf0d0ee175ae28c8fd2e24c71628",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "3f05bbbc8434cafe12b6692344cf5b6a",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "e367580ee6a85f7baf70f13f3e1b4867",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "cdf23977be0849e7e944e0a44cdaf140",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "23e305bc449464c6eef46867cd8c5363",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "0e5fc0e3f78ecc0a1cb382f00690829f",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "afcd6f10eca27f891a3c000fbfe80231",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "1c75953b11ccd3efe5396f2c0add5c9e",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "8d6c40f72e7d1abc922a0567c858b14f",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "e24bb1259608c728a356750e81c536e6",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "2f34a75859192d79062ddcef8b53959a",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "188c2627da68618f1757d7c6264c631a",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a5e1677bee69b8cdc49a34009dd100c1",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "48991687444dd243c6031e3cee4a1fa8",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6d664808b8c7644b32c41b25eeca0143",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "6c0ba3f4be9540c30fc09f13e8524fa4",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "378faae22a13d5ef4446fc3c6bb1ef90",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "407e1f9508f9cfeb72bea651c231e66f",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "b23c4ad8cc56228d58dab66e1387b615",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a6c73f1589742e19c0e9fd19a8bb4e52",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "48fed8f481ad390c12b094a41a0d07ac",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e5f1362531bab5b937545e149b6d4135",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "8d83a22f2fedcebc2b6327a81e02e7c8",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "fc2cf0933aaee17916c46cec57bff439",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "dc5927b762d684df558dfedf25e4fb70",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "2ee184af9b80d60afea7f97aba29cb16",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "37c5f795ccbaeffeb5d6ede4fe9f3c19",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "2ee184af9b80d60afea7f97aba29cb16",
@ -4202,14 +4202,14 @@
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d258789fd7bdc5092aab87ccb4601921",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "314516411d5ac8e991a6f742f399d4de",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d258789fd7bdc5092aab87ccb4601921",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "5393242850af9d26c0ee050765ee71cf",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "887c497ef3462b454bd00891e10da33b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "37afc11cbb5bb3d8d5c617d285fd2ccf",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "36ef12603f477db495d4be42ae8428dc",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "9a935afd3302e43b8c8da97a901ee736",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "d02591202dd1201d6dd2c631344c2396",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b079ea523eceb09c63f9269e1f2096dd",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "15693ffb865e33c99820ee4d4962a39c",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "728e7999dec1017d1e9f0e9e521885e4",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "6052cd644522f3e174f27db3d51396b1",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "2fe7bf4e33e98872e9f52c71fc061134",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "692d2b8e0e68ded67a935fa72f17f8d2",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a94e443fe7d96eb9d9e1684fc3a7af0b",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e8323acf80bcc48b27beab167f4f70f9",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "76645f01806e43775d376e45c84ef855",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "594f4d538e9e910a21c73a8b71e8aaab",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "06042d31df0ff9af96b99477162e2a91",

View File

@ -1,4 +1,4 @@
### 1.7.37 (build 22248, api 9, 2025-01-23)
### 1.7.37 (build 22251, api 9, 2025-01-25)
- Bumping api version to 9. As you'll see below, there's some UI changes that
will require a bit of work for any UI mods to adapt to. If your mods don't
touch UI stuff at all you can simply bump your api version and call it a day.

View File

@ -897,7 +897,7 @@ class ClassicAppSubsystem(babase.AppSubsystem):
return babase.Lstr(resource=rsrc)
def required_purchase_for_game(self, game: str) -> str | None:
def required_purchases_for_game(self, game: str) -> list[str]:
"""Return which purchase (if any) is required for a game."""
# pylint: disable=too-many-return-statements
@ -907,9 +907,9 @@ class ClassicAppSubsystem(babase.AppSubsystem):
):
# Special case: Pro used to unlock this.
return (
None
[]
if self.accounts.have_pro()
else 'upgrades.infinite_runaround'
else ['upgrades.infinite_runaround']
)
if game in (
'Challenges:Infinite Onslaught',
@ -917,48 +917,52 @@ class ClassicAppSubsystem(babase.AppSubsystem):
):
# Special case: Pro used to unlock this.
return (
None
[]
if self.accounts.have_pro()
else 'upgrades.infinite_onslaught'
else ['upgrades.infinite_onslaught']
)
if game in (
'Challenges:Meteor Shower',
'Challenges:Epic Meteor Shower',
):
return 'games.meteor_shower'
return ['games.meteor_shower']
if game in (
'Challenges:Target Practice',
'Challenges:Target Practice B',
):
return 'games.target_practice'
return ['games.target_practice']
if game in (
'Challenges:Ninja Fight',
'Challenges:Pro Ninja Fight',
):
return 'games.ninja_fight'
return ['games.ninja_fight']
if game in ('Challenges:Race', 'Challenges:Pro Race'):
return ['games.race']
if game in ('Challenges:Lake Frigid Race',):
return 'maps.lake_frigid'
return ['games.race', 'maps.lake_frigid']
if game in (
'Challenges:Easter Egg Hunt',
'Challenges:Pro Easter Egg Hunt',
):
return 'games.easter_egg_hunt'
return ['games.easter_egg_hunt']
return None
return []
def is_game_unlocked(self, game: str) -> bool:
"""Is a particular game unlocked?"""
plus = babase.app.plus
assert plus is not None
purchase = self.required_purchase_for_game(game)
if purchase is None:
purchases = self.required_purchases_for_game(game)
if not purchases:
return True
out = plus.get_v1_account_product_purchased(purchase)
assert isinstance(out, bool)
return out
for purchase in purchases:
if not plus.get_v1_account_product_purchased(purchase):
return False
return True

View File

@ -90,10 +90,11 @@ class StoreSubsystem:
assert babase.app.classic is not None
if babase.app.classic.store_items is None:
from bascenev1lib.game import ninjafight
from bascenev1lib.game import meteorshower
from bascenev1lib.game import targetpractice
from bascenev1lib.game import easteregghunt
from bascenev1lib.game.race import RaceGame
from bascenev1lib.game.ninjafight import NinjaFightGame
from bascenev1lib.game.meteorshower import MeteorShowerGame
from bascenev1lib.game.targetpractice import TargetPracticeGame
from bascenev1lib.game.easteregghunt import EasterEggHuntGame
# IMPORTANT - need to keep this synced with the master server.
# (doing so manually for now)
@ -122,24 +123,28 @@ class StoreSubsystem:
'merch': {},
'pro': {},
'maps.lake_frigid': {'map_type': maps.LakeFrigid},
'games.race': {
'gametype': RaceGame,
'previewTex': 'bigGPreview',
},
'games.ninja_fight': {
'gametype': ninjafight.NinjaFightGame,
'gametype': NinjaFightGame,
'previewTex': 'courtyardPreview',
},
'games.meteor_shower': {
'gametype': meteorshower.MeteorShowerGame,
'gametype': MeteorShowerGame,
'previewTex': 'rampagePreview',
},
'games.infinite_onslaught': {
'gametype': meteorshower.MeteorShowerGame,
'gametype': MeteorShowerGame,
'previewTex': 'rampagePreview',
},
'games.target_practice': {
'gametype': targetpractice.TargetPracticeGame,
'gametype': TargetPracticeGame,
'previewTex': 'doomShroomPreview',
},
'games.easter_egg_hunt': {
'gametype': easteregghunt.EasterEggHuntGame,
'gametype': EasterEggHuntGame,
'previewTex': 'towerDPreview',
},
'icons.flag_us': {
@ -380,6 +385,7 @@ class StoreSubsystem:
store_layout['minigames'] = [
{
'items': [
'games.race',
'games.ninja_fight',
'games.meteor_shower',
'games.target_practice',

View File

@ -53,7 +53,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 22248
TARGET_BALLISTICA_BUILD = 22251
TARGET_BALLISTICA_VERSION = '1.7.37'

View File

@ -1022,19 +1022,33 @@ class CoopBrowserWindow(bui.MainWindow):
)
return
required_purchase = bui.app.classic.required_purchase_for_game(game)
required_purchases = bui.app.classic.required_purchases_for_game(game)
if (
required_purchase is not None
and not plus.get_v1_account_product_purchased(required_purchase)
):
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
else:
PurchaseWindow(
items=[required_purchase], origin_widget=origin_widget
)
return
# Show pop-up to allow purchasing any required stuff we don't have.
for purchase in required_purchases:
if not plus.get_v1_account_product_purchased(purchase):
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
else:
PurchaseWindow(
items=[purchase], origin_widget=origin_widget
)
return
# if required_purchases and not all(
# plus.get_v1_account_product_purchased(p)
# for p in required_purchases
# ):
# if plus.get_v1_account_state() != 'signed_in':
# show_sign_in_prompt()
# else:
# # Hmm just ask about the first I guess.. They can pop
# # this window back up to the next if they purchase the
# # first.
# PurchaseWindow(
# items=[required_purchases[0]], origin_widget=origin_widget
# )
# return
self._save_state()
@ -1107,18 +1121,34 @@ class CoopBrowserWindow(bui.MainWindow):
if tournament_button.game is not None and not classic.is_game_unlocked(
tournament_button.game
):
required_purchase = classic.required_purchase_for_game(
required_purchases = classic.required_purchases_for_game(
tournament_button.game
)
assert required_purchase is not None
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
else:
PurchaseWindow(
items=[required_purchase],
origin_widget=tournament_button.button,
)
return
# We gotta be missing *something* if its locked.
assert required_purchases
for purchase in required_purchases:
if not plus.get_v1_account_product_purchased(purchase):
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
else:
PurchaseWindow(
items=[purchase],
origin_widget=tournament_button.button,
)
return
# assert required_purchases
# if plus.get_v1_account_state() != 'signed_in':
# show_sign_in_prompt()
# else:
# # Hmm; just show the first requirement. They can come
# # back to see more after they purchase the first.
# PurchaseWindow(
# items=[required_purchases[0]],
# origin_widget=tournament_button.button,
# )
# return
if tournament_button.time_remaining <= 0:
bui.screenmessage(

View File

@ -36,46 +36,58 @@ class PluginWindow(bui.MainWindow):
transition: str | None = 'in_right',
origin_widget: bui.Widget | None = None,
):
# pylint: disable=too-many-locals
app = bui.app
self._category = Category.ALL
assert bui.app.classic is not None
uiscale = bui.app.ui_v1.uiscale
self._width = 870.0 if uiscale is bui.UIScale.SMALL else 670.0
x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
yoffs = -55.0 if uiscale is bui.UIScale.SMALL else 0
self._width = 1200.0 if uiscale is bui.UIScale.SMALL else 670.0
self._height = (
450.0
900.0
if uiscale is bui.UIScale.SMALL
else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0
)
top_extra = 0 if uiscale is bui.UIScale.SMALL else 0
# Do some fancy math to fill all available screen area up to the
# size of our backing container. This lets us fit to the exact
# screen shape at small ui scale.
screensize = bui.get_virtual_screen_size()
scale = (
1.9
if uiscale is bui.UIScale.SMALL
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
)
# Calc screen size in our local container space and clamp to a
# bit smaller than our container size.
target_width = min(self._width - 80, screensize[0] / scale)
target_height = min(self._height - 80, screensize[1] / scale)
# To get top/left coords, go to the center of our window and
# offset by half the width/height of our target area.
yoffs = 0.5 * self._height + 0.5 * target_height + 20.0
self._scroll_width = target_width
self._scroll_height = target_height - 40
self._scroll_bottom = yoffs - 64 - self._scroll_height
super().__init__(
root_widget=bui.containerwidget(
size=(self._width, self._height + top_extra),
size=(self._width, self._height),
toolbar_visibility=(
'menu_minimal'
if uiscale is bui.UIScale.SMALL
else 'menu_full'
),
scale=(
1.9
if uiscale is bui.UIScale.SMALL
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
),
stack_offset=(
(0, 0) if uiscale is bui.UIScale.SMALL else (0, 0)
),
scale=scale,
),
transition=transition,
origin_widget=origin_widget,
# We're affected by screen size only at small ui-scale.
refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
)
self._scroll_width = self._width - (100 + 2 * x_inset)
self._scroll_height = self._height - (
200.0 if uiscale is bui.UIScale.SMALL else 115.0
)
self._sub_width = self._scroll_width * 0.95
self._sub_height = 724.0
@ -88,12 +100,12 @@ class PluginWindow(bui.MainWindow):
else:
self._back_button = bui.buttonwidget(
parent=self._root_widget,
position=(53 + x_inset, self._height - 60 + yoffs),
size=(140, 60),
position=(53, yoffs - 49),
size=(60, 60),
scale=0.8,
autoselect=True,
label=bui.Lstr(resource='backText'),
button_type='back',
label=bui.charstr(bui.SpecialChar.BACK),
button_type='backSmall',
on_activate_call=self.main_window_back,
)
bui.containerwidget(
@ -102,7 +114,10 @@ class PluginWindow(bui.MainWindow):
self._title_text = bui.textwidget(
parent=self._root_widget,
position=(self._width * 0.5, self._height - 41 + yoffs),
position=(
self._width * 0.5,
yoffs - (42 if uiscale is bui.UIScale.SMALL else 30),
),
size=(0, 0),
text=bui.Lstr(resource='pluginsText'),
color=app.ui_v1.title_color,
@ -111,19 +126,16 @@ class PluginWindow(bui.MainWindow):
v_align='center',
)
if self._back_button is not None:
bui.buttonwidget(
edit=self._back_button,
button_type='backSmall',
size=(60, 60),
label=bui.charstr(bui.SpecialChar.BACK),
)
settings_button_x = 670 if uiscale is bui.UIScale.SMALL else 570
settings_button_x = (
self._width * 0.5
+ self._scroll_width * 0.5
- (100 if uiscale is bui.UIScale.SMALL else 40)
)
button_row_yoffs = yoffs + (-2 if uiscale is bui.UIScale.SMALL else 10)
self._num_plugins_text = bui.textwidget(
parent=self._root_widget,
position=(settings_button_x - 130, self._height - 41 + yoffs),
position=(settings_button_x - 130, button_row_yoffs - 41),
size=(0, 0),
text='',
h_align='center',
@ -133,7 +145,7 @@ class PluginWindow(bui.MainWindow):
self._category_button = bui.buttonwidget(
parent=self._root_widget,
scale=0.7,
position=(settings_button_x - 105, self._height - 60 + yoffs),
position=(settings_button_x - 105, button_row_yoffs - 60),
size=(130, 60),
label=bui.Lstr(resource='allText'),
autoselect=True,
@ -144,7 +156,7 @@ class PluginWindow(bui.MainWindow):
self._settings_button = bui.buttonwidget(
parent=self._root_widget,
position=(settings_button_x, self._height - 58 + yoffs),
position=(settings_button_x, button_row_yoffs - 58),
size=(40, 40),
label='',
on_activate_call=self._open_settings,
@ -152,7 +164,7 @@ class PluginWindow(bui.MainWindow):
bui.imagewidget(
parent=self._root_widget,
position=(settings_button_x + 3, self._height - 57 + yoffs),
position=(settings_button_x + 3, button_row_yoffs - 57),
draw_controller=self._settings_button,
size=(35, 35),
texture=bui.gettexture('settingsIcon'),
@ -166,15 +178,16 @@ class PluginWindow(bui.MainWindow):
self._scrollwidget = bui.scrollwidget(
parent=self._root_widget,
size=(self._scroll_width, self._scroll_height),
position=(
50 + x_inset,
(135 if uiscale is bui.UIScale.SMALL else 50) + yoffs,
self._width * 0.5 - self._scroll_width * 0.5,
self._scroll_bottom,
),
simple_culling_v=20.0,
highlight=False,
size=(self._scroll_width, self._scroll_height),
selection_loops_to_parent=True,
claims_left_right=True,
border_opacity=0.4,
)
bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)

View File

@ -21,42 +21,52 @@ class PluginSettingsWindow(bui.MainWindow):
assert bui.app.classic is not None
uiscale = bui.app.ui_v1.uiscale
width = 750.0 if uiscale is bui.UIScale.SMALL else 470.0
height = 400.0 if uiscale is bui.UIScale.SMALL else 300.0
yoffs = -20 if uiscale is bui.UIScale.SMALL else 0
self._width = 1200.0 if uiscale is bui.UIScale.SMALL else 470.0
self._height = 900.0 if uiscale is bui.UIScale.SMALL else 360.0
# Do some fancy math to fill all available screen area up to the
# size of our backing container. This lets us fit to the exact
# screen shape at small ui scale.
screensize = bui.get_virtual_screen_size()
scale = (
2.06
if uiscale is bui.UIScale.SMALL
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
)
# Calc screen size in our local container space and clamp to a
# bit smaller than our container size.
# target_width = min(self._width - 60, screensize[0] / scale)
target_height = min(self._height - 100, screensize[1] / scale)
# To get top/left coords, go to the center of our window and
# offset by half the width/height of our target area.
self._yoffs = 0.5 * self._height + 0.5 * target_height + 30.0
super().__init__(
root_widget=bui.containerwidget(
size=(width, height),
size=(self._width, self._height),
toolbar_visibility=(
'menu_minimal'
if uiscale is bui.UIScale.SMALL
else 'menu_full'
),
scale=(
2.06
if uiscale is bui.UIScale.SMALL
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
),
stack_offset=(
(0, 0) if uiscale is bui.UIScale.SMALL else (0, 0)
),
scale=scale,
),
transition=transition,
origin_widget=origin_widget,
# We're affected by screen size only at small ui-scale.
refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
)
if uiscale is bui.UIScale.SMALL:
xoffs = 135
self._back_button = bui.get_special_widget('back_button')
bui.containerwidget(
edit=self._root_widget, on_cancel_call=self.main_window_back
)
else:
xoffs = 0
self._back_button = bui.buttonwidget(
parent=self._root_widget,
position=(53, height - 60 + yoffs),
position=(55, self._yoffs - 33),
size=(60, 60),
scale=0.8,
autoselect=True,
@ -71,20 +81,24 @@ class PluginSettingsWindow(bui.MainWindow):
self._title_text = bui.textwidget(
parent=self._root_widget,
position=(
width * 0.5,
height - (55 if uiscale is bui.UIScale.SMALL else 35) + yoffs,
self._width * 0.5,
self._yoffs - (55 if uiscale is bui.UIScale.SMALL else 10),
),
size=(0, 0),
text=bui.Lstr(resource='pluginSettingsText'),
maxwidth=230,
color=bui.app.ui_v1.title_color,
h_align='center',
v_align='center',
)
self._y_position = height - 140 + yoffs
# Roughly center our few bits of content.
x = self._width * 0.5 - 175
y = self._height * 0.5 + 30
self._enable_plugins_button = bui.buttonwidget(
parent=self._root_widget,
position=(xoffs + 65, self._y_position + yoffs),
position=(x, y),
size=(350, 60),
autoselect=True,
label=bui.Lstr(resource='pluginsEnableAllText'),
@ -94,10 +108,10 @@ class PluginSettingsWindow(bui.MainWindow):
),
)
self._y_position -= 70
y -= 70
self._disable_plugins_button = bui.buttonwidget(
parent=self._root_widget,
position=(xoffs + 65, self._y_position + yoffs),
position=(x, y),
size=(350, 60),
autoselect=True,
label=bui.Lstr(resource='pluginsDisableAllText'),
@ -107,10 +121,10 @@ class PluginSettingsWindow(bui.MainWindow):
),
)
self._y_position -= 70
y -= 70
self._enable_new_plugins_check_box = bui.checkboxwidget(
parent=self._root_widget,
position=(xoffs + 65, self._y_position + yoffs),
position=(x, y),
size=(350, 60),
value=bui.app.config.get(
bui.app.plugins.AUTO_ENABLE_NEW_PLUGINS_CONFIG_KEY,

View File

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