bombsquad-plugin-manager/plugins/utilities/menu_theme.py

2076 lines
78 KiB
Python
Raw Normal View History

2023-08-26 09:27:47 +08:00
# ba_meta require api 8
"""
Working for v1.7.20+ only
2023-12-29 17:08:24 +05:30
Menu Theme v1.0.10
2023-08-26 09:27:47 +08:00
discord: riyukiiyan
I appreciate any kind of modification. So feel free to share, edit and change credit string... no problem
Credits are unnecessary but are a much-appreciated gesture to show support to others :D
[CHANGELOG]:
~ Support for BombSquad v1.7.26
~ Fixed "Show Logo Text" checkmark not updating on imports and reset
~ Music changes:
>> Turn off music by selecting 'None'
>> Removed dupes, renamed some and added 2 new musics
Special thanks to:
snowee, rikko, & unknown
"""
from __future__ import annotations
from typing import List, Sequence, Callable, Any, cast
2023-12-25 19:30:43 +05:30
from baenv import TARGET_BALLISTICA_BUILD
2023-08-26 09:27:47 +08:00
from bascenev1lib.mainmenu import MainMenuActivity, NewsDisplay, _preload1
from bauiv1lib.mainmenu import MainMenuWindow
from bauiv1lib.account.settings import AccountSettingsWindow
from bauiv1lib.colorpicker import ColorPicker, ColorPickerExact
from bauiv1lib.fileselector import FileSelectorWindow
from bauiv1lib.popup import PopupMenuWindow
2023-12-25 19:30:43 +05:30
import _bauiv1 as _bui
import _bascenev1 as _bs
2023-08-26 02:01:09 +00:00
import _babase as _ba
2023-12-25 19:30:43 +05:30
2023-08-26 02:01:09 +00:00
import babase as ba
import bascenev1 as bs
import bauiv1 as bui
import bascenev1lib.mainmenu as menu
2023-08-26 09:27:47 +08:00
import json
import os
import shutil
import random
import weakref
# defined version and author
__author__ = "Yann"
2023-12-25 19:30:43 +05:30
__version__ = "1.0.10"
if TARGET_BALLISTICA_BUILD < 21282:
# These attributes have been deprecated as of 1.7.27. For more info see:
# https://github.com/efroemling/ballistica/blob/master/CHANGELOG.md#1727-build-21282-api-8-2023-08-30
# Adding a compatibility layer here so older builds still work fine.
class Dummy:
pass
babase = ba
babase.app.env = Dummy()
babase.app.env.build_number = babase.app.build_number
babase.app.env.device_name = babase.app.device_name
babase.app.env.config_file_path = babase.app.config_file_path
babase.app.env.version = babase.app.version
babase.app.env.debug = babase.app.debug_build
babase.app.env.test = babase.app.test_build
babase.app.env.data_directory = babase.app.data_directory
babase.app.env.python_directory_user = babase.app.python_directory_user
babase.app.env.python_directory_app = babase.app.python_directory_app
babase.app.env.python_directory_app_site = babase.app.python_directory_app_site
babase.app.env.api_version = babase.app.api_version
babase.app.env.tv = babase.app.on_tv
babase.app.env.vr = babase.app.vr_mode
babase.app.env.arcade = babase.app.arcade_mode
babase.app.env.headless = babase.app.arcade_mode
babase.app.env.demo = babase.app.demo_mode
protocol_version = babase.app.protocol_version
toolbar_test = babase.app.toolbar_test
else:
protocol_version = _bs.protocol_version
toolbar_test = _bui.toolbar_test()
2023-08-26 09:27:47 +08:00
# frequently used variables references
config = bs.app.config
ui_type = bs.app.ui_v1.uiscale
ui_small = bs.UIScale.SMALL
ui_medium = bs.UIScale.MEDIUM
ui_large = bs.UIScale.LARGE
2023-08-26 02:01:09 +00:00
# method references
2023-08-26 09:27:47 +08:00
original_unlocked_pro = bs.app.classic.accounts.have_pro
original_account_init = AccountSettingsWindow.__init__
# define globals
GLOBALS_REFLECTION = {
'Powerup': 'powerup',
'Character': 'char',
'Soft': 'soft',
'None': 'none'
}
GLOBALS_MUSIC = {
'Menu': bs.MusicType.MENU,
'Epic': bs.MusicType.EPIC,
'Flag Catcher': bs.MusicType.FLAG_CATCHER,
'Flying': bs.MusicType.FLYING,
'Grand Romp': bs.MusicType.GRAND_ROMP,
'Lobby': bs.MusicType.CHAR_SELECT,
'Lobby Epic': bs.MusicType.SCORES,
'Marching Forward': bs.MusicType.FORWARD_MARCH,
'Marching Home': bs.MusicType.MARCHING,
'Run Away': bs.MusicType.RUN_AWAY,
'Scary': bs.MusicType.SCARY,
'Sports': bs.MusicType.SPORTS,
'Survival': bs.MusicType.SURVIVAL,
'To The Death': bs.MusicType.TO_THE_DEATH,
'None': None,
}
GLOBALS_MAPDATA = {
"The Pad (with trees)": {
"Camera Bounds": (0.3544110667, 4.493562578, -2.518391331, 16.64754831, 8.06138989, 18.5029888),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.3,
"Ambient": (1.14, 1.1, 1.0),
"Tint": (1.06, 1.04, 1.03),
"Vignette Outer": (0.45, 0.55, 0.54),
"Vignette Inner": (0.99, 0.98, 0.98)
},
"The Pad": {
"Camera Bounds": (0.3544110667, 4.493562578, -2.518391331, 16.64754831, 8.06138989, 18.5029888),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.3,
"Ambient": (1.1, 1.1, 1.0),
"Tint": (1.1, 1.1, 1.0),
"Vignette Outer": (0.7, 0.65, 0.75),
"Vignette Inner": (0.95, 0.95, 0.93)
},
"Big G": {
"Camera Bounds": (-0.4011866709, 2.331310176, -0.5426286416, 19.11746262, 10.19675564, 23.50119277),
"Map Color": (0.7, 0.7, 0.7),
"Map Reflection Scale": 0.0,
"Ambient": (1.1, 1.2, 1.3),
"Tint": (1.1, 1.2, 1.3),
"Vignette Outer": (0.65, 0.6, 0.55),
"Vignette Inner": (0.9, 0.9, 0.93)
},
"Bridgit": {
"Camera Bounds": (-0.2457963347, 3.828181068, -1.528362695, 19.14849937, 7.312788846, 8.436232726),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.1, 1.2, 1.3),
"Tint": (1.1, 1.2, 1.3),
"Vignette Outer": (0.65, 0.6, 0.55),
"Vignette Inner": (0.9, 0.9, 0.93)
},
"Courtyard": {
"Camera Bounds": (0.3544110667, 3.958431362, -2.175025358, 16.37702017, 7.755670126, 13.38680645),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.2, 1.17, 1.1),
"Tint": (1.2, 1.17, 1.1),
"Vignette Outer": (0.6, 0.6, 0.64),
"Vignette Inner": (0.95, 0.95, 0.93)
},
"Crag Castle": {
"Camera Bounds": (0.7033834902, 6.55869393, -3.153439808, 16.73648528, 14.94789935, 11.60063102),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.15, 1.05, 0.75),
"Tint": (1.15, 1.05, 0.75),
"Vignette Outer": (0.6, 0.65, 0.6),
"Vignette Inner": (0.95, 0.95, 0.95)
},
"Doom Shroom": {
"Camera Bounds": (0.4687647786, 2.320345088, -3.219423694, 21.34898078, 10.25529817, 14.67298352),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (0.9, 1.3, 1.1),
"Tint": (0.82, 1.10, 1.15),
"Vignette Outer": (0.76, 0.76, 0.76),
"Vignette Inner": (0.95, 0.95, 0.99)
},
"Happy Thoughts": {
"Camera Bounds": (-1.045859963, 12.67722855, -5.401537075, 34.46156851, 20.94044653, 0.6931564611),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.3, 1.23, 1.0),
"Tint": (1.3, 1.23, 1.0),
"Vignette Outer": (0.64, 0.59, 0.69),
"Vignette Inner": (0.95, 0.95, 0.93)
},
"Football Stadium": {
"Camera Bounds": (0.0, 1.185751251, 0.4326226188, 29.8180273, 11.57249038, 18.89134176),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.3, 1.2, 1.0),
"Tint": (1.3, 1.2, 1.0),
"Vignette Outer": (0.57, 0.57, 0.57),
"Vignette Inner": (0.9, 0.9, 0.9)
},
"Hockey Stadium": {
"Camera Bounds": (0.0, 0.7956858119, 0.0, 30.80223883, 0.5961646365, 13.88431707),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.3,
"Ambient": (1.15, 1.25, 1.6),
"Tint": (1.2, 1.3, 1.33),
"Vignette Outer": (0.66, 0.67, 0.73),
"Vignette Inner": (0.93, 0.93, 0.95)
},
"Lake Frigid": {
"Camera Bounds": (0.622753268, 3.958431362, -2.48708008, 20.62310543, 7.755670126, 12.33155049),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1, 1, 1),
"Tint": (1, 1, 1),
"Vignette Outer": (0.86, 0.86, 0.86),
"Vignette Inner": (0.95, 0.95, 0.99)
},
"Monkey Face": {
"Camera Bounds": (-1.657177611, 4.132574186, -1.580485661, 17.36258946, 10.49020453, 12.31460338),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.1, 1.2, 1.2),
"Tint": (1.1, 1.2, 1.2),
"Vignette Outer": (0.60, 0.62, 0.66),
"Vignette Inner": (0.97, 0.95, 0.93)
},
"Rampage": {
"Camera Bounds": (0.3544110667, 5.616383286, -4.066055072, 19.90053969, 10.34051135, 8.16221072),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.3, 1.2, 1.03),
"Tint": (1.2, 1.1, 0.97),
"Vignette Outer": (0.62, 0.64, 0.69),
"Vignette Inner": (0.97, 0.95, 0.93)
},
"Roundabout": {
"Camera Bounds": (-1.552280404, 3.189001207, -2.40908495, 11.96255385, 8.857531648, 9.531689995),
"Map Color": (0.7, 0.7, 0.7),
"Map Reflection Scale": 0.0,
"Ambient": (1.0, 1.05, 1.1),
"Tint": (1.0, 1.05, 1.1),
"Vignette Outer": (0.63, 0.65, 0.7),
"Vignette Inner": (0.97, 0.95, 0.93)
},
"Step Right Up": {
"Camera Bounds": (0.3544110667, 6.07676405, -2.271833016, 22.55121262, 10.14644532, 14.66087273),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.2, 1.1, 1.0),
"Tint": (1.2, 1.1, 1.0),
"Vignette Outer": (1.2, 1.1, 1.0),
"Vignette Inner": (0.95, 0.95, 0.93)
},
"Tower D": {
"Camera Bounds": (-0.4714933293, 2.887077774, -1.505479919, 17.90145968, 6.188484831, 15.96149117),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.2, 1.1, 1.0),
"Tint": (1.15, 1.11, 1.03),
"Vignette Outer": (1.2, 1.1, 1.0),
"Vignette Inner": (0.95, 0.95, 0.95)
},
"Tip Top": {
"Camera Bounds": (0.004375512593, 7.141135803, -0.01745294675, 21.12506141, 4.959977313, 16.6885592),
"Map Color": (0.7, 0.7, 0.7),
"Map Reflection Scale": 0.0,
"Ambient": (0.8, 0.9, 1.3),
"Tint": (0.8, 0.9, 1.3),
"Vignette Outer": (0.79, 0.79, 0.69),
"Vignette Inner": (0.97, 0.97, 0.99)
},
"Zig Zag": {
"Camera Bounds": (-1.807378035, 3.943412768, -1.61304303, 23.01413538, 13.27980464, 10.0098376),
"Map Color": (1.0, 1.0, 1.0),
"Map Reflection Scale": 0.0,
"Ambient": (1.0, 1.15, 1.15),
"Tint": (1.0, 1.15, 1.15),
"Vignette Outer": (0.57, 0.59, 0.63),
"Vignette Inner": (0.97, 0.95, 0.93)
}
}
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
class CustomColorPicker(ColorPicker):
def _select_other(self):
from bauiv1lib import purchase
CustomColorPickerExact(parent=self._parent,
position=self._position,
initial_color=self._initial_color,
delegate=self._delegate,
scale=self._scale,
offset=self._offset,
tag=self._tag)
self._delegate = None
self._transition_out()
class CustomColorPickerExact(ColorPickerExact):
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
def _color_change_press(self, color_name: str, increasing: bool):
current_time = bui.apptime()
since_last = current_time - self._last_press_time
if (
since_last < 0.2
and self._last_press_color_name == color_name
and self._last_press_increasing == increasing
):
self._change_speed += 0.25
else:
self._change_speed = 1.0
self._last_press_time = current_time
self._last_press_color_name = color_name
self._last_press_increasing = increasing
color_index = ('r', 'g', 'b').index(color_name)
offs = int(self._change_speed) * (0.01 if increasing else -0.01)
self._color[color_index] = max(
-1.0, min(2.55, self._color[color_index] + offs)
)
self._update_for_color()
class ConfigCheckBox:
widget: bui.Widget
def __init__(
self,
parent: bui.Widget,
configkey: str,
position: tuple[float, float],
size: tuple[float, float],
displayname: str | bs.Lstr | None = None,
scale: float | None = None,
maxwidth: float | None = None,
autoselect: bool = True,
value_change_call: Callable[[Any], Any] | None = None):
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
if displayname is None:
displayname = configkey
self._value_change_call = value_change_call
self._configkey = configkey
self.widget = bui.checkboxwidget(
parent=parent,
autoselect=autoselect,
position=position,
size=size,
text=displayname,
textcolor=(0.8, 0.8, 0.8),
value=bs.app.config[configkey],
on_value_change_call=self._value_changed,
scale=scale,
maxwidth=maxwidth,
)
# complain if we outlive our checkbox
bui.uicleanupcheck(self, self.widget)
def _value_changed(self, val: bool):
cfg = bs.app.config
cfg[self._configkey] = val
if self._value_change_call is not None:
self._value_change_call(val)
cfg.apply_and_commit()
class FreeEditWindow(bui.Window):
def _do_enter(self):
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
def _error() -> None:
bui.getsound('error').play(volume=2.0)
bui.screenmessage('error ' + u'😑😑', color=(1.0, 0.0, 0.0))
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
try:
if self.name_only:
value = bui.textwidget(query=self._text_field)
if not value.strip():
return _error()
self.delegate._export(self, txt=value)
else:
value = round(float(bui.textwidget(query=self._text_field)), 4)
self.delegate.free_edit_enter(self, c=self.config_name, txt=value)
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
except ValueError:
return _error()
bui.containerwidget(edit=self._root_widget, transition=self._transition_out)
def _activate_enter_button(self):
self._enter_button.activate()
def _do_back(self):
bui.containerwidget(edit=self._root_widget, transition=self._transition_out)
def __init__(self, delegate: Any = None, config_name: str = 'Menu Map', whitelist: List = [], name_only: bool = False, origin_widget: bui.widget = None):
self._transition_out = 'out_scale' if origin_widget else 'out_right'
scale_origin = origin_widget.get_screen_space_center() if origin_widget else None
transition = 'in_scale' if origin_widget else 'in_right'
width, height = 450, 230
uiscale = bs.app.ui_v1.uiscale
super().__init__(root_widget=bui.containerwidget(
size=(width, height),
transition=transition,
toolbar_visibility='menu_minimal_no_back',
scale_origin_stack_offset=scale_origin,
scale=(2.0 if uiscale is bs.UIScale.SMALL else
1.5 if uiscale is bs.UIScale.MEDIUM else 1.0)))
btn = bui.buttonwidget(parent=self._root_widget,
2023-08-26 02:01:09 +00:00
scale=0.5,
position=(40, height - 40),
size=(60, 60),
label='',
on_activate_call=self._do_back,
autoselect=True,
color=(0.55, 0.5, 0.6),
icon=bui.gettexture('crossOut'),
iconscale=1.2)
2023-08-26 09:27:47 +08:00
self.config_name, self.delegate, self.name_only = config_name, delegate, name_only
self._text_field = bui.textwidget(
parent=self._root_widget,
position=(125, height - 121),
size=(280, 46),
text='',
h_align='left',
v_align='center',
color=(0.9, 0.9, 0.9, 1.0),
description='',
editable=True,
padding=4,
max_chars=20 if name_only else 5,
on_return_press_call=self._activate_enter_button)
bui.textwidget(parent=self._root_widget,
2023-08-26 02:01:09 +00:00
text='Current: ' + str(config[config_name]) if not name_only else 'Save as',
position=(220, height - 44),
color=(0.5, 0.5, 0.5, 1.0),
size=(90, 30),
h_align='right')
2023-08-26 09:27:47 +08:00
bui.widget(edit=btn, down_widget=self._text_field)
b_width = 200
self._enter_button = btn2 = bui.buttonwidget(
parent=self._root_widget,
position=(width * 0.5 - b_width * 0.5, height - 200),
size=(b_width, 60),
scale=1.0,
label='Enter',
on_activate_call=self._do_enter)
bui.containerwidget(edit=self._root_widget,
2023-08-26 02:01:09 +00:00
cancel_button=btn,
start_button=btn2,
selected_child=self._text_field)
2023-08-26 09:27:47 +08:00
class MenuThemeWindow:
def __init__(self, origin_widget: bui.widget = None, accounts_window=None):
if origin_widget is not None:
self._transition_out = 'out_scale'
scale_origin = origin_widget.get_screen_space_center()
transition = 'in_scale'
else:
self._transition_out = 'out_right'
scale_origin = None
transition = 'in_right'
self._choice_page: str = None
self._accounts_window = accounts_window
height = 500 if ui_type is ui_small else 772
self._root_widget = bui.containerwidget(
size=(445, 365) if ui_type is ui_small else (799, 576),
transition=transition,
toolbar_visibility='menu_minimal',
scale_origin_stack_offset=scale_origin,
scale=2.23 if ui_type is ui_small else 1.0,
stack_offset=(0, -35) if ui_type is ui_small else (0, 0)
)
self._scroll_border_parent = bui.scrollwidget(
parent=self._root_widget,
position=(39, 58) if ui_type is ui_small else (86, 39),
size=(375, 240) if ui_type is ui_small else (645, 463),
color=(0.52, 0.48, 0.63)
)
self._scroll_parent = bui.containerwidget(
parent=self._scroll_border_parent,
size=(450, height),
background=False,
claims_left_right=False,
claims_tab=False
)
2023-08-26 02:01:09 +00:00
2023-08-26 09:27:47 +08:00
self._back_button = bui.buttonwidget(
parent=self._root_widget,
position=(23, 310) if ui_type is ui_small else (80, 511),
size=(35, 35) if ui_type is ui_small else (55, 55),
color=(0.76, 0.42, 0.38),
button_type="backSmall",
textcolor=(1, 1, 1),
text_scale=0.8 if ui_type is ui_small else 1.0,
label="",
autoselect=True,
on_activate_call=bs.Call(self.close)
)
self._home_button = bui.buttonwidget(
parent=self._root_widget,
position=(383, 308) if ui_type is ui_small else (688, 511),
size=(60, 60) if ui_type is ui_small else (55, 55),
color=(0.76, 0.42, 0.38),
icon=bui.gettexture('crossOut'),
iconscale=1.2,
scale=0.59 if ui_type is ui_small else 0.92,
label="",
autoselect=True,
on_activate_call=bs.Call(self.close_all)
)
# menutheme title
bui.textwidget(
parent=self._root_widget,
position=(225, 327) if ui_type is ui_small else (415, 547),
size=(0, 0),
text="Menu Theme",
color=(0.8, 0.8, 0.8, 0.76),
maxwidth=290,
scale=0.95 if ui_type is ui_small else 1.25,
h_align='center',
v_align='center'
)
bui.textwidget(
parent=self._root_widget,
position=(225, 309) if ui_type is ui_small else (415, 517),
size=(0, 0),
text=f"version: {__version__}",
color=(0.6, 0.6, 0.6, 0.8),
maxwidth=290,
scale=0.454 if ui_type is ui_small else 0.653,
h_align='center',
v_align='center'
)
# settings txt
bui.textwidget(
parent=self._scroll_parent,
position=(10, height - 27) if ui_type is ui_small else (30, height - 47),
size=(0, 0),
text="Map Type:",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.7 if ui_type is ui_small else 1.3,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(10, height - 65) if ui_type is ui_small else (30, height - 104),
size=(0, 0),
text="Music:",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.7 if ui_type is ui_small else 1.3,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(25, height - 147) if ui_type is ui_small else (45, height - 239),
size=(0, 0),
text="tint",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.5 if ui_type is ui_small else 1.0,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(81, height - 147) if ui_type is ui_small else (140, height - 239),
size=(0, 0),
text="ambient",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.5 if ui_type is ui_small else 1.0,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(147, height - 156) if ui_type is ui_small else (262, height - 258),
size=(0, 0),
text="vignette\n outer",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.5 if ui_type is ui_small else 1.0,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(213, height - 156) if ui_type is ui_small else (382, height - 258),
size=(0, 0),
text="vignette\n inner",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.5 if ui_type is ui_small else 1.0,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(279, height - 156) if ui_type is ui_small else (500, height - 258),
size=(0, 0),
text="reflection\n color",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.5 if ui_type is ui_small else 1.0,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(10, height - 193) if ui_type is ui_small else (30, height - 320),
size=(0, 0),
text="Reflection Type:",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.7 if ui_type is ui_small else 1.3,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(10, height - 227) if ui_type is ui_small else (30, height - 373),
size=(0, 0),
text="Reflection Scale:",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.7 if ui_type is ui_small else 1.3,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(10, height - 260) if ui_type is ui_small else (30, height - 423),
size=(0, 0),
text="Camera Mode:",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.7 if ui_type is ui_small else 1.3,
h_align='left',
v_align='center'
)
bui.textwidget(
parent=self._scroll_parent,
position=(10, height - 294) if ui_type is ui_small else (30, height - 480),
size=(0, 0),
text="Show Logo Text:",
color=(1, 1, 1, 0.8),
maxwidth=290,
scale=0.7 if ui_type is ui_small else 1.3,
h_align='left',
v_align='center'
)
# prioritize this first for:
# >> handling config-errors
# >> debugging
self._menu_configreset_button = bui.buttonwidget(
parent=self._scroll_parent,
2023-08-26 02:01:09 +00:00
position=(5, height - 486) if ui_type is ui_small else (12, height - 765),
2023-08-26 09:27:47 +08:00
size=(329, 50) if ui_type is ui_small else (600, 80),
color=(0.0, 0.67, 0.85),
textcolor=(0.8, 0.8, 0.8),
button_type="regular",
label="Reset to Default Settings",
text_scale=0.7 if ui_type is ui_small else 1.0,
on_activate_call=bs.Call(self.reset_config)
)
# settings buttons
self._menu_map_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(112, height - 38) if ui_type is ui_small else (206, height - 67),
size=(87, 24) if ui_type is ui_small else (149, 40),
button_type="regular",
label=config["Menu Map"],
on_activate_call=bs.Call(self.choice_window, 'Map')
)
self._menu_music_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(85, height - 75) if ui_type is ui_small else (149, height - 123),
size=(87, 24) if ui_type is ui_small else (149, 40),
button_type="regular",
label=config["Menu Music"],
text_scale=0.6 if ui_type is ui_small else 1.0,
on_activate_call=bs.Call(self.choice_window, 'Music')
)
self._menu_tint_button = bui.buttonwidget(
parent=self._scroll_parent,
color=config["Menu Tint"],
position=(15, height - 136) if ui_type is ui_small else (30, height - 220),
size=(40, 40) if ui_type is ui_small else (70, 70),
button_type="square",
label="",
on_activate_call=bs.WeakCall(self.color_picker_popup, "Menu Tint")
)
self._menu_ambient_button = bui.buttonwidget(
parent=self._scroll_parent,
color=config["Menu Ambient"],
position=(81, height - 136) if ui_type is ui_small else (150, height - 220),
size=(40, 40) if ui_type is ui_small else (70, 70),
button_type="square",
label="",
on_activate_call=bs.WeakCall(self.color_picker_popup, "Menu Ambient")
)
self._menu_vignetteO_button = bui.buttonwidget(
parent=self._scroll_parent,
color=config["Menu Vignette Outer"],
position=(147, height - 136) if ui_type is ui_small else (270, height - 220),
size=(40, 40) if ui_type is ui_small else (70, 70),
button_type="square",
label="",
on_activate_call=bs.WeakCall(self.color_picker_popup, "Menu Vignette Outer")
)
self._menu_vignetteI_button = bui.buttonwidget(
parent=self._scroll_parent,
color=config["Menu Vignette Inner"],
position=(213, height - 136) if ui_type is ui_small else (390, height - 220),
size=(40, 40) if ui_type is ui_small else (70, 70),
button_type="square",
label="",
on_activate_call=bs.WeakCall(self.color_picker_popup, "Menu Vignette Inner")
)
self._menu_rcolor_button = bui.buttonwidget(
parent=self._scroll_parent,
color=config["Menu Map Color"],
position=(279, height - 136) if ui_type is ui_small else (510, height - 220),
size=(40, 40) if ui_type is ui_small else (70, 70),
button_type="square",
label="",
on_activate_call=bs.WeakCall(self.color_picker_popup, "Menu Map Color")
)
self._menu_reflectiont_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(148, height - 204) if ui_type is ui_small else (287, height - 339),
size=(87, 24) if ui_type is ui_small else (149, 40),
button_type="regular",
label=config["Menu Reflection Type"],
text_scale=0.6 if ui_type is ui_small else 1.0,
on_activate_call=bs.Call(self.choice_window, 'Reflection Type')
)
self._menu_reflections_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(153, height - 237) if ui_type is ui_small else (289, height - 392),
size=(87, 24) if ui_type is ui_small else (149, 40),
button_type="regular",
label=str(config["Menu Reflection Scale"]),
text_scale=0.6 if ui_type is ui_small else 1.0,
2023-08-26 02:01:09 +00:00
on_activate_call=lambda: FreeEditWindow(
delegate=self, whitelist=['num'], config_name='Menu Reflection Scale')
2023-08-26 09:27:47 +08:00
)
self._menu_cameramode_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(138, height - 272) if ui_type is ui_small else (265, height - 444),
size=(87, 24) if ui_type is ui_small else (149, 40),
button_type="regular",
label=str(config["Menu Camera Mode"]),
text_scale=0.6 if ui_type is ui_small else 1.0,
on_activate_call=bs.Call(self.choice_window, 'Camera Mode')
)
self._menu_logotext_button = ConfigCheckBox(
parent=self._scroll_parent,
configkey="Menu Logo Text",
position=(151, height - 308) if ui_type is ui_small else (287, height - 520),
size=(40, 40) if ui_type is ui_small else (56, 56),
2023-08-26 02:01:09 +00:00
scale=0.62 if ui_type is ui_small else 1.4,
2023-08-26 09:27:47 +08:00
displayname=""
)
self._menu_load_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(11, height - 365) if ui_type is ui_small else (22, height - 590),
size=(155, 45) if ui_type is ui_small else (280, 75),
textcolor=(0.8, 0.8, 0.8),
button_type="regular",
label="Load Theme",
text_scale=0.7 if ui_type is ui_small else 1.0,
on_activate_call=bs.Call(self.popup_fileselector)
)
self._menu_save_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(178, height - 365) if ui_type is ui_small else (312, height - 590),
size=(155, 45) if ui_type is ui_small else (280, 75),
textcolor=(0.8, 0.8, 0.8),
button_type="regular",
label="Save Theme",
text_scale=0.7 if ui_type is ui_small else 1.0,
on_activate_call=lambda: FreeEditWindow(delegate=self, name_only=True)
)
self._menu_mapdata_button = bui.buttonwidget(
parent=self._scroll_parent,
position=(5, height - 425) if ui_type is ui_small else (12, height - 677),
size=(329, 50) if ui_type is ui_small else (600, 80),
color=(0.23, 0.27, 0.55),
textcolor=(0.8, 0.8, 0.8),
button_type="regular",
label="Map Data Overrides",
text_scale=0.7 if ui_type is ui_small else 1.0,
on_activate_call=bs.Call(self.checkbox_window)
)
def checkbox_window(self):
self._root_widget_checkbox = bui.containerwidget(
size=(800, 740),
transition='in_scale',
toolbar_visibility='menu_minimal',
scale_origin_stack_offset=(0, 0),
scale=0.6 if ui_type is ui_large else 0.88 if ui_type is ui_small else 0.76,
color=(0.17, 0.2, 0.25),
on_outside_click_call=bs.Call(self.checkbox_window_out),
claim_outside_clicks=True,
stack_offset=(0, -35) if ui_type is ui_small else (0, 0)
)
self._button_tint = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="tint",
position=(88, 600),
size=(380, 40),
scale=1.9,
displayname='Tint'
)
self._button_ambient = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="ambient_color",
position=(88, 510),
size=(380, 40),
scale=1.9,
displayname='Ambient Color'
)
self._button_vignette_outer = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="vignette_outer",
position=(88, 420),
size=(380, 40),
scale=1.9,
displayname='Vignette Outer'
)
self._button_vignette_inner = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="vignette_inner",
position=(88, 330),
size=(380, 40),
scale=1.9,
displayname='Vignette Inner'
)
self._button_map_color = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="map_color",
position=(88, 240),
size=(380, 40),
scale=1.9,
displayname='Map Color'
)
self._button_map_reflection_scale = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="map_reflection_scale",
position=(88, 150),
size=(380, 40),
scale=1.9,
displayname='Map Reflection Scale'
)
self._button_map_reflection_type = ConfigCheckBox(
parent=self._root_widget_checkbox,
configkey="map_reflection_type",
position=(88, 60),
size=(380, 40),
scale=1.9,
displayname='Map Reflection Type'
)
def checkbox_window_out(self):
# Memory-leak prevention
bui.containerwidget(edit=self._root_widget_checkbox, transition='out_scale')
del self._button_tint
del self._button_ambient
del self._button_vignette_outer
del self._button_vignette_inner
del self._button_map_color
del self._button_map_reflection_scale
del self._button_map_reflection_type
def choice_window(self, category: str):
choices_map = {
'Map': [
'Big G',
'Bridgit',
'Courtyard',
'Crag Castle',
'Doom Shroom',
'Football Stadium',
'Happy Thoughts',
'Hockey Stadium',
'Lake Frigid',
'Monkey Face',
'Rampage',
'Roundabout',
'Step Right Up',
'The Pad',
'The Pad (with trees)',
'Tower D',
'Tip Top',
'Zig Zag'
],
'Camera Mode': [
'rotate',
'static'
],
'Reflection Type': [
'Soft',
'None',
'Powerup',
'Character'
],
'Music': [
'Menu',
'Epic',
'Flag Catcher',
'Flying',
'Grand Romp',
'Lobby',
'Lobby Epic',
'Marching Forward',
'Marching Home',
'Run Away',
'Scary',
'Sports',
'Survival',
'To The Death',
'None'
]
}
if category in choices_map:
PopupMenuWindow(
position=(0, 0),
scale=2.0 if ui_type is ui_small else 1.0,
delegate=self,
current_choice=bs.app.config[f"Menu {category}"],
choices=choices_map[category]
)
self._choice_page = category
def popup_menu_selected_choice(self, window: PopupMenuWindow, choice: str):
if self._choice_page == 'Map':
bs.app.config['Menu Map'] = choice
if config["tint"]:
bs.app.config["Menu Tint"] = GLOBALS_MAPDATA.get(config["Menu Map"]).get("Tint")
if config["ambient_color"]:
2023-08-26 02:01:09 +00:00
bs.app.config["Menu Ambient"] = GLOBALS_MAPDATA.get(
config["Menu Map"]).get("Ambient")
2023-08-26 09:27:47 +08:00
if config["vignette_outer"]:
2023-08-26 02:01:09 +00:00
bs.app.config["Menu Vignette Outer"] = GLOBALS_MAPDATA.get(
config["Menu Map"]).get("Vignette Outer")
2023-08-26 09:27:47 +08:00
if config["vignette_inner"]:
2023-08-26 02:01:09 +00:00
bs.app.config["Menu Vignette Inner"] = GLOBALS_MAPDATA.get(
config["Menu Map"]).get("Vignette Inner")
2023-08-26 09:27:47 +08:00
if config["map_color"]:
2023-08-26 02:01:09 +00:00
bs.app.config["Menu Map Color"] = GLOBALS_MAPDATA.get(
config["Menu Map"]).get("Map Color")
2023-08-26 09:27:47 +08:00
if config["map_reflection_scale"]:
2023-08-26 02:01:09 +00:00
bs.app.config["Menu Reflection Scale"] = GLOBALS_MAPDATA.get(
config["Menu Map"]).get("Map Reflection Scale")
2023-08-26 09:27:47 +08:00
if config["map_reflection_type"]:
bs.app.config["Menu Reflection Type"] = 'Soft'
elif self._choice_page == 'Music':
bs.app.config['Menu Music'] = choice
elif self._choice_page == 'Reflection Type':
bs.app.config['Menu Reflection Type'] = choice
elif self._choice_page == 'Camera Mode':
bs.app.config['Menu Camera Mode'] = choice
bs.app.config.apply_and_commit()
self.update_buttons()
def popup_menu_closing(self, window: PopupMenuWindow):
self._choice_page = None
self.update_buttons()
def popup_fileselector(self):
self._file_selector = FileSelectorWindow(
2023-08-26 02:01:09 +00:00
path=str(_ba.env()['python_directory_user']),
callback=self._import,
show_base_path=True,
valid_file_extensions=['json'],
allow_folders=False
)
2023-08-26 09:27:47 +08:00
def _import(self, path: str = None):
try:
self.path = path + '/'
self.path = self.path[:-1]
with open(self.path, 'r') as imported:
selected = json.load(imported)
handle_config([
2023-08-26 02:01:09 +00:00
selected["Menu Map"],
selected["Menu Tint"],
selected["Menu Ambient"],
selected["Menu Vignette Outer"],
selected["Menu Vignette Inner"],
selected["Menu Music"],
selected["Menu Map Color"],
selected["Menu Reflection Scale"],
selected["Menu Reflection Type"],
selected["Menu Camera Mode"],
selected["Menu Logo Text"],
selected["vignette_outer"],
selected["vignette_inner"],
selected["ambient_color"],
selected["tint"],
selected["map_reflection_scale"],
selected["map_reflection_type"],
selected["map_color"]],
False
2023-08-26 09:27:47 +08:00
)
self.update_buttons()
2023-08-26 02:01:09 +00:00
bui.screenmessage(
f"Loaded {os.path.splitext(os.path.basename(self.path))[0]}!", color=(0.2, 0.4, 1.0))
except:
pass
2023-08-26 09:27:47 +08:00
del self._file_selector
def _export(self, window: FreeEditWindow, txt: Any):
path = _ba.env()['python_directory_user'] + "/_menutheme/"
try:
a = _ba.env()['python_directory_user'] + "/_menutheme"
2023-08-26 02:01:09 +00:00
os.makedirs(a, exist_ok=False)
except:
pass
2023-08-26 09:27:47 +08:00
with open(path + txt + '.json', 'w') as file:
my_config = {
2023-08-26 02:01:09 +00:00
"Menu Map": config["Menu Map"],
"Menu Tint": config["Menu Tint"],
"Menu Ambient": config["Menu Ambient"],
"Menu Vignette Outer": config["Menu Vignette Outer"],
"Menu Vignette Inner": config["Menu Vignette Inner"],
"Menu Music": config["Menu Music"],
"Menu Map Color": config["Menu Map Color"],
"Menu Reflection Scale": config["Menu Reflection Scale"],
"Menu Reflection Type": config["Menu Reflection Type"],
"Menu Camera Mode": config["Menu Camera Mode"],
"Menu Logo Text": config["Menu Logo Text"],
"vignette_outer": config["vignette_outer"],
"vignette_inner": config["vignette_inner"],
"ambient_color": config["ambient_color"],
"tint": config["tint"],
"map_color": config["map_color"],
"map_reflection_scale": config["map_reflection_scale"],
"map_reflection_type": config["map_reflection_type"]
}
2023-08-26 09:27:47 +08:00
json.dump(my_config, file, indent=4)
2023-08-26 02:01:09 +00:00
bui.screenmessage(
f"Saved {os.path.splitext(os.path.basename(path+txt+'.json'))[0]}!", color=(0.2, 0.4, 1.0))
2023-08-26 09:27:47 +08:00
bui.getsound('gunCocking').play()
def color_picker_popup(self, tag: str):
bs.app.classic.accounts.have_pro = lambda: True
CustomColorPicker(parent=self._root_widget,
2023-08-26 02:01:09 +00:00
position=(0, 0),
2023-08-26 09:27:47 +08:00
initial_color=config[tag],
delegate=self,
tag=tag)
def color_picker_selected_color(self, picker: CustomColorPicker, color: Sequence[float, float, float]):
if not self._root_widget:
return
self.update_color(tag=picker.get_tag(), color=color)
self.update_buttons()
def color_picker_closing(self, picker: ColorPicker):
bs.app.classic.accounts.have_pro = original_unlocked_pro
def free_edit_enter(self, window: FreeEditWindow, c: Any, txt: Any):
bs.app.config[c] = float(txt)
bs.app.config.apply_and_commit()
self.update_buttons()
def update_buttons(self):
# menu labels
bui.buttonwidget(edit=self._menu_map_button, label=config['Menu Map'])
bui.buttonwidget(edit=self._menu_music_button, label=config['Menu Music'])
bui.buttonwidget(edit=self._menu_reflectiont_button, label=config['Menu Reflection Type'])
# menu colors
bui.buttonwidget(edit=self._menu_tint_button, color=config['Menu Tint'])
bui.buttonwidget(edit=self._menu_ambient_button, color=config['Menu Ambient'])
bui.buttonwidget(edit=self._menu_vignetteO_button, color=config['Menu Vignette Outer'])
bui.buttonwidget(edit=self._menu_vignetteI_button, color=config['Menu Vignette Inner'])
bui.buttonwidget(edit=self._menu_rcolor_button, color=config['Menu Map Color'])
# menu values
2023-08-26 02:01:09 +00:00
bui.buttonwidget(edit=self._menu_reflections_button,
label=str(config['Menu Reflection Scale']))
2023-08-26 09:27:47 +08:00
bui.buttonwidget(edit=self._menu_cameramode_button, label=str(config['Menu Camera Mode']))
bui.checkboxwidget(edit=self._menu_logotext_button.widget, value=config['Menu Logo Text'])
def update_color(self, tag: str, color: tuple[float, float, float]):
bs.app.config[tag] = color
bs.app.config.apply_and_commit()
def reset_config(self):
handle_config([
"The Pad (with trees)",
(1.14, 1.1, 1.0), (1.06, 1.04, 1.03),
(0.45, 0.55, 0.54), (0.99, 0.98, 0.98), "Menu",
(1.0, 1.0, 1.0), 0.3, 'None', 'rotate',
True, True, True, True, True, True, True, True, True
2023-08-26 02:01:09 +00:00
], False
2023-08-26 09:27:47 +08:00
)
self.update_buttons()
bui.screenmessage('Reset Settings', color=(0, 1, 0))
def close(self):
self._accounts_window = None
bui.containerwidget(edit=self._root_widget, transition='out_scale')
def close_all(self):
accounts_window = self._accounts_window
bui.containerwidget(edit=self._root_widget, transition='out_scale')
accounts_window._back(False)
class MainMenuTheme(MainMenuActivity):
def _start_preloads(self):
if self.expired:
return
with self.context:
_preload1()
bui.apptimer(0.5, self._start_menu_music)
def _start_menu_music(self):
music = GLOBALS_MUSIC.get(config['Menu Music'])
if music is not None:
bs.setmusic(music)
def _make_word(self, *args, **kwargs) -> None:
2023-08-26 02:01:09 +00:00
if not config['Menu Logo Text']:
return
2023-08-26 09:27:47 +08:00
super()._make_word(*args, **kwargs)
def _make_logo(self, *args, **kwargs) -> None:
2023-08-26 02:01:09 +00:00
if not config['Menu Logo Text']:
return
2023-08-26 09:27:47 +08:00
super()._make_logo(*args, **kwargs)
def on_transition_in(self):
bs.Activity.on_transition_in(self)
random.seed(123)
app = bs.app
2023-12-25 19:30:43 +05:30
env = ba.app.env
2023-08-26 09:27:47 +08:00
assert app.classic is not None
plus = bui.app.plus
assert plus is not None
2023-12-25 19:30:43 +05:30
vr_mode = env.vr
2023-08-26 09:27:47 +08:00
2023-12-25 19:30:43 +05:30
if not toolbar_test:
2023-08-26 09:27:47 +08:00
color = (1.0, 1.0, 1.0, 1.0) if vr_mode else (0.5, 0.6, 0.5, 0.6)
scale = (
0.9
if (app.ui_v1.uiscale is bs.UIScale.SMALL or vr_mode)
else 0.7
)
self.my_name = bs.NodeActor(
bs.newnode(
'text',
attrs={
'v_attach': 'bottom',
'h_align': 'center',
'color': color,
'flatness': 1.0,
'shadow': 1.0 if vr_mode else 0.5,
'scale': scale,
'position': (0, 10),
'vr_depth': -10,
'text': '\xa9 2011-2023 Eric Froemling',
},
)
)
tval = bs.Lstr(
resource='hostIsNavigatingMenusText',
subs=[('${HOST}', plus.get_v1_account_display_string())],
)
self._host_is_navigating_text = bs.NodeActor(
bs.newnode(
'text',
attrs={
'text': tval,
'client_only': True,
'position': (0, -200),
'flatness': 1.0,
'h_align': 'center',
},
)
)
if not app.classic.main_menu_did_initial_transition and hasattr(
self, 'my_name'
):
assert self.my_name is not None
assert self.my_name.node
bs.animate(self.my_name.node, 'opacity', {2.3: 0, 3.0: 1.0})
2023-12-25 19:30:43 +05:30
vr_mode = env.vr
uiscale = bui.UIV1Subsystem.uiscale
2023-08-26 09:27:47 +08:00
force_show_build_number = False
2023-12-25 19:30:43 +05:30
if not toolbar_test:
if env.debug or env.test or force_show_build_number:
if env.debug:
2023-08-26 09:27:47 +08:00
text = bs.Lstr(
value='${V} (${B}) (${D})',
subs=[
2023-12-25 19:30:43 +05:30
('${V}', env.version),
('${B}', str(env.build_number)),
2023-08-26 09:27:47 +08:00
('${D}', bs.Lstr(resource='debugText')),
],
)
else:
text = bs.Lstr(
value='${V} (${B})',
subs=[
2023-12-25 19:30:43 +05:30
('${V}', env.version),
('${B}', str(env.build_number)),
2023-08-26 09:27:47 +08:00
],
)
else:
2023-12-25 19:30:43 +05:30
text = bs.Lstr(value='${V}', subs=[('${V}', env.version)])
2023-08-26 09:27:47 +08:00
scale = 0.9 if (uiscale is bs.UIScale.SMALL or vr_mode) else 0.7
color = (1, 1, 1, 1) if vr_mode else (0.5, 0.6, 0.5, 0.7)
self.version = bs.NodeActor(
bs.newnode(
'text',
attrs={
'v_attach': 'bottom',
'h_attach': 'right',
'h_align': 'right',
'flatness': 1.0,
'vr_depth': -10,
'shadow': 1.0 if vr_mode else 0.5,
'color': color,
'scale': scale,
'position': (-260, 10) if vr_mode else (-10, 10),
'text': text,
},
)
)
if not app.classic.main_menu_did_initial_transition:
assert self.version.node
bs.animate(self.version.node, 'opacity', {2.3: 0, 3.0: 1.0})
self.beta_info = self.beta_info_2 = None
2023-12-25 19:30:43 +05:30
if env.test and not (env.demo or env.arcade) and config['Menu Logo Text']:
2023-08-26 09:27:47 +08:00
pos = (230, 35)
self.beta_info = bs.NodeActor(
bs.newnode(
'text',
attrs={
'v_attach': 'center',
'h_align': 'center',
'color': (1, 1, 1, 1),
'shadow': 0.5,
'flatness': 0.5,
'scale': 1,
'vr_depth': -60,
'position': pos,
'text': bs.Lstr(resource='testBuildText'),
},
)
)
if not app.classic.main_menu_did_initial_transition:
assert self.beta_info.node
bs.animate(self.beta_info.node, 'opacity', {1.3: 0, 1.8: 1.0})
b = GLOBALS_MAPDATA.get(config["Menu Map"]).get("Camera Bounds")
b = (
2023-08-26 02:01:09 +00:00
b[0] - b[3] / 2.0,
b[1] - b[4] / 2.0,
b[2] - b[5] / 2.0,
b[0] + b[3] / 2.0,
b[1] + b[4] / 2.0,
b[2] + b[5] / 2.0
)
2023-08-26 09:27:47 +08:00
gnode = self.globalsnode
gnode.camera_mode = 'follow' if config["Menu Camera Mode"] == 'static' else 'rotate'
self.load_map_stuff()
gnode.tint = config["Menu Tint"]
gnode.ambient_color = config["Menu Ambient"]
gnode.vignette_outer = config["Menu Vignette Outer"]
gnode.vignette_inner = config["Menu Vignette Inner"]
gnode.area_of_interest_bounds = b
self.main.node.color = config["Menu Map Color"]
self.main.node.reflection = GLOBALS_REFLECTION[config["Menu Reflection Type"]]
self.main.node.reflection_scale = [float(config["Menu Reflection Scale"])]
self._update_timer = bs.Timer(1.0, self._update, repeat=True)
self._update()
bui.add_clean_frame_callback(bs.WeakCall(self._start_preloads))
random.seed()
2023-12-25 19:30:43 +05:30
if not (env.demo or env.arcade) and not toolbar_test:
2023-08-26 09:27:47 +08:00
self._news = NewsDisplay(self)
with bs.ContextRef.empty():
from bauiv1lib import specialoffer
assert bs.app.classic is not None
if bool(False):
uicontroller = bs.app.ui_v1.controller
assert uicontroller is not None
uicontroller.show_main_menu()
else:
main_menu_location = bs.app.ui_v1.get_main_menu_location()
# When coming back from a kiosk-mode game, jump to
# the kiosk start screen.
2023-12-25 19:30:43 +05:30
if env.demo or env.arcade:
2023-08-26 09:27:47 +08:00
# pylint: disable=cyclic-import
from bauiv1lib.kiosk import KioskWindow
2023-12-26 18:44:09 +05:30
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
KioskWindow().get_root_widget(),
2023-12-29 17:04:31 +05:30
)
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
KioskWindow().get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
# ..or in normal cases go back to the main menu
else:
if main_menu_location == 'Gather':
# pylint: disable=cyclic-import
from bauiv1lib.gather import GatherWindow
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
GatherWindow(transition=None).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
GatherWindow(transition=None).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
elif main_menu_location == 'Watch':
# pylint: disable=cyclic-import
from bauiv1lib.watch import WatchWindow
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
WatchWindow(transition=None).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
WatchWindow(transition=None).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
elif main_menu_location == 'Team Game Select':
# pylint: disable=cyclic-import
from bauiv1lib.playlist.browser import (
PlaylistBrowserWindow,
)
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
PlaylistBrowserWindow(
sessiontype=bs.DualTeamSession, transition=None
).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
PlaylistBrowserWindow(
sessiontype=bs.DualTeamSession, transition=None
).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
elif main_menu_location == 'Free-for-All Game Select':
# pylint: disable=cyclic-import
from bauiv1lib.playlist.browser import (
PlaylistBrowserWindow,
)
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
PlaylistBrowserWindow(
sessiontype=bs.FreeForAllSession,
transition=None,
).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
PlaylistBrowserWindow(
sessiontype=bs.FreeForAllSession,
transition=None,
).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
elif main_menu_location == 'Coop Select':
# pylint: disable=cyclic-import
from bauiv1lib.coop.browser import CoopBrowserWindow
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
CoopBrowserWindow(transition=None).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
CoopBrowserWindow(transition=None).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
elif main_menu_location == 'Benchmarks & Stress Tests':
# pylint: disable=cyclic-import
from bauiv1lib.debug import DebugWindow
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
DebugWindow(transition=None).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
DebugWindow(transition=None).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
else:
# pylint: disable=cyclic-import
from bauiv1lib.mainmenu import MainMenuWindow
if TARGET_BALLISTICA_BUILD < 21697:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
MainMenuWindow(transition=None).get_root_widget(),
)
2023-12-29 17:04:31 +05:30
else:
bs.app.ui_v1.set_main_menu_window(
2023-12-29 17:08:24 +05:30
MainMenuWindow(transition=None).get_root_widget(), from_window = False
)
2023-12-29 17:04:31 +05:30
if not specialoffer.show_offer():
def try_again():
if not specialoffer.show_offer():
bui.apptimer(2.0, specialoffer.show_offer)
bui.apptimer(2.0, try_again)
app.classic.main_menu_did_initial_transition = True
def load_map_stuff(self):
m = bs.getmesh
t = bs.gettexture
map_type = config["Menu Map"]
if map_type == "The Pad (with trees)":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('thePadLevel'),
'color_texture': t('thePadLevelColor'),
'reflection': 'soft',
'reflection_scale': [0.3]
}))
self.trees = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('trees'),
'lighting': False,
'reflection': 'char',
'reflection_scale': [0.1],
'color_texture': t('treesColor')
}))
self.bgterrain = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadBG'),
'color': (0.92, 0.91, 0.9),
'lighting': False,
'background': True,
'color_texture': t('menuBG'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadLevelBottom'),
'lighting': False,
'reflection': 'soft',
'reflection_scale': [0.45],
'color_texture': t('thePadLevelColor')
}))
elif map_type == "The Pad":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('thePadLevel'),
'color_texture': t('thePadLevelColor'),
'reflection': 'soft',
'reflection_scale': [0.3]
}))
self.bgterrain = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadBG'),
'color': (0.92, 0.91, 0.9),
'lighting': False,
'background': True,
'color_texture': t("menuBG")
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadLevelBottom'),
'lighting': False,
'reflection': 'soft',
'reflection_scale': [0.45],
'color_texture': t('thePadLevelColor')
}))
elif map_type == "Hockey Stadium":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('hockeyStadiumOuter'),
'color_texture': t('hockeyStadium'),
'reflection': 'soft',
'reflection_scale': [0.3]
}))
self.inner = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('hockeyStadiumInner'),
'opacity': 0.92,
'opacity_in_low_or_ui_medium_quality': 1.0,
'color_texture': t('hockeyStadium')
}))
self.stands = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('hockeyStadiumStands'),
'visible_in_reflections': False,
'color_texture': t('footballStadium')
}))
elif map_type == "Football Stadium":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('footballStadium'),
'color_texture': t('footballStadium'),
}))
elif map_type == "Bridgit":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('bridgitLevelTop'),
'color_texture': t('bridgitLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('bridgitLevelBottom'),
'lighting': False,
'color_texture': t('bridgitLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('natureBackground'),
'lighting': False,
'background': True,
'color_texture': t('natureBackgroundColor'),
}))
elif map_type == "Big G":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('bigG'),
'color': (0.7, 0.7, 0.7),
'color_texture': t('bigG'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('bigGBottom'),
'lighting': False,
'color': (0.7, 0.7, 0.7),
'color_texture': t('bigG'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('natureBackground'),
'lighting': False,
'background': True,
'color_texture': t('natureBackgroundColor'),
}))
elif map_type == "Roundabout":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('roundaboutLevel'),
'color': (0.7, 0.7, 0.7),
'color_texture': t('roundaboutLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('roundaboutLevelBottom'),
'lighting': False,
'color': (0.7, 0.7, 0.7),
'color_texture': t('roundaboutLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('natureBackground'),
'lighting': False,
'background': True,
'color_texture': t('natureBackgroundColor'),
}))
elif map_type == "Monkey Face":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('monkeyFaceLevel'),
'color_texture': t('monkeyFaceLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('monkeyFaceLevelBottom'),
'lighting': False,
'color_texture': t('monkeyFaceLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('natureBackground'),
'lighting': False,
'color_texture': t('natureBackgroundColor'),
}))
elif map_type == "Monkey Face":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('monkeyFaceLevel'),
'color_texture': t('monkeyFaceLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('monkeyFaceLevelBottom'),
'lighting': False,
'color_texture': t('monkeyFaceLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('natureBackground'),
'lighting': False,
'color_texture': t('natureBackgroundColor'),
}))
elif map_type == "Zig Zag":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('zigZagLevel'),
'color_texture': t('zigZagLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('zigZagLevelBottom'),
'lighting': False,
'color_texture': t('zigZagLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('natureBackground'),
'lighting': False,
'color_texture': t('natureBackgroundColor'),
}))
elif map_type == "Doom Shroom":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('doomShroomLevel'),
'color_texture': t('doomShroomLevelColor'),
}))
self.stem = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('doomShroomStem'),
'lighting': False,
'color_texture': t('doomShroomLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('doomShroomBG'),
'lighting': False,
'background': True,
'color_texture': t('doomShroomBGColor'),
}))
elif map_type == "Lake Frigid":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('lakeFrigid'),
'color_texture': t('lakeFrigid'),
}))
self.top = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('lakeFrigidTop'),
'lighting': False,
'color_texture': t('lakeFrigid'),
}))
self.reflections = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('lakeFrigidReflections'),
'lighting': False,
'overlay': True,
'opacity': 0.15,
'color_texture': t('lakeFrigidReflections'),
}))
elif map_type == "Tip Top":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('tipTopLevel'),
'color': (0.7, 0.7, 0.7),
'color_texture': t('tipTopLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('tipTopLevelBottom'),
'lighting': False,
'color': (0.7, 0.7, 0.7),
'color_texture': t('tipTopLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('tipTopBG'),
'lighting': False,
'color': (0.4, 0.4, 0.4),
'background': True,
'color_texture': t('tipTopBGColor'),
}))
elif map_type == "Crag Castle":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('cragCastleLevel'),
'color_texture': t('cragCastleLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('cragCastleLevelBottom'),
'lighting': False,
'color_texture': t('cragCastleLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadBG'),
'lighting': False,
'background': True,
'color_texture': t('menuBG'),
}))
elif map_type == "Tower D":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('towerDLevel'),
'color_texture': t('towerDLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('towerDLevelBottom'),
'lighting': False,
'color_texture': t('towerDLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadBG'),
'lighting': False,
'background': True,
'color_texture': t('menuBG'),
}))
elif map_type == "Happy Thoughts":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('alwaysLandLevel'),
'color_texture': t('alwaysLandLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('alwaysLandLevelBottom'),
'lighting': False,
'color_texture': t('alwaysLandLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('alwaysLandBG'),
'lighting': False,
'background': True,
'color_texture': t('alwaysLandBGColor'),
}))
elif map_type == "Step Right Up":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('stepRightUpLevel'),
'color_texture': t('stepRightUpLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('stepRightUpLevelBottom'),
'lighting': False,
'color_texture': t('stepRightUpLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadBG'),
'lighting': False,
'background': True,
'color_texture': t('menuBG'),
}))
elif map_type == "Courtyard":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('courtyardLevel'),
'color_texture': t('courtyardLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('courtyardLevelBottom'),
'lighting': False,
'color_texture': t('courtyardLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('thePadBG'),
'lighting': False,
'background': True,
'color_texture': t('menuBG'),
}))
elif map_type == "Rampage":
self.main = bs.NodeActor(bs.newnode(
'terrain',
delegate=self,
attrs={
'mesh': m('rampageLevel'),
'color_texture': t('rampageLevelColor'),
}))
self.bottom = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('rampageLevelBottom'),
'lighting': False,
'color_texture': t('rampageLevelColor'),
}))
self.background = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('rampageBG'),
'lighting': False,
'background': True,
'color_texture': t('rampageBGColor'),
}))
self.background_2 = bs.NodeActor(bs.newnode(
'terrain',
attrs={
'mesh': m('rampageBG2'),
'lighting': False,
'background': True,
'color_texture': t('rampageBGColor2'),
}))
def menu_theme(self):
this_class = self
MenuThemeWindow(accounts_window=this_class)
def handle_config(keys: List[str], adding: bool = False):
our_config = {
"Menu Map": keys[0],
"Menu Tint": keys[1],
"Menu Ambient": keys[2],
"Menu Vignette Outer": keys[3],
"Menu Vignette Inner": keys[4],
"Menu Music": keys[5],
"Menu Map Color": keys[6],
"Menu Reflection Scale": keys[7],
"Menu Reflection Type": keys[8],
"Menu Camera Mode": keys[9],
"Menu Logo Text": keys[10],
"vignette_outer": keys[11],
"vignette_inner": keys[12],
"ambient_color": keys[13],
"tint": keys[14],
"map_color": keys[15],
"map_reflection_scale": keys[16],
"map_reflection_type": keys[17]
}
config_keys = list(our_config.keys())
p = 0
for cf in config_keys:
if cf not in bs.app.config and adding:
config[cf] = keys[p]
elif our_config[cf] is not None and not adding:
config[cf] = keys[p]
p += 1
bs.app.config.apply_and_commit()
def new_init(self, *args, **kwargs):
original_account_init(self, *args, **kwargs)
self._menu_theme = bui.buttonwidget(
parent=self._root_widget,
position=((470, 330) if ui_type is ui_small else
(420, 434) if ui_type is ui_large else (445, 374)),
scale=(1.2 if ui_type is ui_small else
1.3 if ui_type is ui_large else 1.0),
size=(160, 30) if ui_type is ui_small else (167, 30),
color=(0.55, 0.7, 0.63),
text_scale=(0.7 if ui_type is ui_medium else
0.65 if ui_type is ui_large else 0.5),
autoselect=False,
button_type="regular",
label="Menu Theme",
on_activate_call=self.menu_theme
)
self.previous_config = {
"Menu Map": config["Menu Map"],
"Menu Tint": config["Menu Tint"],
"Menu Ambient": config["Menu Ambient"],
"Menu Vignette Outer": config["Menu Vignette Outer"],
"Menu Vignette Inner": config["Menu Vignette Inner"],
"Menu Music": config["Menu Music"],
"Menu Map Color": config["Menu Map Color"],
"Menu Reflection Scale": config["Menu Reflection Scale"],
"Menu Reflection Type": config["Menu Reflection Type"],
"Menu Camera Mode": config["Menu Camera Mode"],
"Menu Logo Text": config["Menu Logo Text"]
}
def new_back(self, save_state: bool = True):
assert bui.app.classic is not None
if save_state:
self._save_state()
bui.containerwidget(edit=self._root_widget, transition=self._transition_out)
main_menu_window = MainMenuWindow(transition='in_left').get_root_widget()
if TARGET_BALLISTICA_BUILD < 21697:
bui.app.ui_v1.set_main_menu_window(main_menu_window,)
else:
2023-12-29 17:08:24 +05:30
bui.app.ui_v1.set_main_menu_window(main_menu_window, from_window = False)
2023-12-29 17:04:31 +05:30
current_config = {
"Menu Map": config["Menu Map"],
"Menu Tint": config["Menu Tint"],
"Menu Ambient": config["Menu Ambient"],
"Menu Vignette Outer": config["Menu Vignette Outer"],
"Menu Vignette Inner": config["Menu Vignette Inner"],
"Menu Music": config["Menu Music"],
"Menu Map Color": config["Menu Map Color"],
"Menu Reflection Scale": config["Menu Reflection Scale"],
"Menu Reflection Type": config["Menu Reflection Type"],
"Menu Camera Mode": config["Menu Camera Mode"],
"Menu Logo Text": config["Menu Logo Text"]
}
for x in self.previous_config:
if current_config[x] != self.previous_config[x]:
bs.pushcall(lambda: bs.new_host_session(menu.MainMenuSession))
break
2023-08-26 09:27:47 +08:00
# ba_meta export plugin
class Plugin(ba.Plugin):
def on_app_running(self):
AccountSettingsWindow.__init__ = new_init
AccountSettingsWindow._back = new_back
AccountSettingsWindow.menu_theme = menu_theme
menu.MainMenuActivity = MainMenuTheme
handle_config([
"The Pad (with trees)",
(1.14, 1.1, 1.0), (1.06, 1.04, 1.03),
(0.45, 0.55, 0.54), (0.99, 0.98, 0.98), "Menu",
(1.0, 1.0, 1.0), 0.3, 'None', 'rotate',
True, True, True, True, True, True, True, True, True
2023-08-26 02:01:09 +00:00
], True
2023-08-26 09:27:47 +08:00
)