diff --git a/src/assets/.asset_manifest_public.json b/src/assets/.asset_manifest_public.json index 9c4f56a5..4d72b271 100644 --- a/src/assets/.asset_manifest_public.json +++ b/src/assets/.asset_manifest_public.json @@ -371,6 +371,7 @@ "ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/debug.cpython-311.opt-1.pyc", + "ba_data/python/bauiv1lib/__pycache__/discord.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/feedback.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/fileselector.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/getcurrency.cpython-311.opt-1.pyc", @@ -432,6 +433,7 @@ "ba_data/python/bauiv1lib/coop/tournamentbutton.py", "ba_data/python/bauiv1lib/creditslist.py", "ba_data/python/bauiv1lib/debug.py", + "ba_data/python/bauiv1lib/discord.py", "ba_data/python/bauiv1lib/feedback.py", "ba_data/python/bauiv1lib/fileselector.py", "ba_data/python/bauiv1lib/gather/__init__.py", diff --git a/src/assets/Makefile b/src/assets/Makefile index 5af7a60c..2a6a7c45 100644 --- a/src/assets/Makefile +++ b/src/assets/Makefile @@ -351,6 +351,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/coop/tournamentbutton.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/creditslist.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/debug.py \ + $(BUILD_DIR)/ba_data/python/bauiv1lib/discord.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/feedback.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/fileselector.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/gather/__init__.py \ @@ -625,6 +626,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__pycache__/tournamentbutton.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/debug.cpython-311.opt-1.pyc \ + $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/discord.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/feedback.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/fileselector.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/gather/__pycache__/__init__.cpython-311.opt-1.pyc \ diff --git a/src/assets/ba_data/python/bauiv1lib/discord.py b/src/assets/ba_data/python/bauiv1lib/discord.py new file mode 100644 index 00000000..c1b17c86 --- /dev/null +++ b/src/assets/ba_data/python/bauiv1lib/discord.py @@ -0,0 +1,130 @@ +# Released under the MIT License. See LICENSE for details. +# +"""UI functionality for the Discord window.""" + +from __future__ import annotations + +import bauiv1 as bui + + +class DiscordWindow(bui.Window): + """Window for joining the Discord.""" + + def __init__( + self, + transition: str = 'in_right', + origin_widget: bui.Widget | None = None, + ): + # pylint: disable=too-many-statements + if bui.app.classic is None: + raise RuntimeError('This requires classic support.') + + app = bui.app + assert app.classic is not None + + # If they provided an origin-widget, scale up from that. + scale_origin: tuple[float, float] | 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 + + uiscale = bui.app.ui_v1.uiscale + self._width = 800 + x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 + self._height = 320 + top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 + super().__init__( + root_widget=bui.containerwidget( + size=(self._width, self._height + top_extra), + transition=transition, + toolbar_visibility='menu_minimal', + scale_origin_stack_offset=scale_origin, + scale=( + 1.6 + if uiscale is bui.UIScale.SMALL + else 1.3 + if uiscale is bui.UIScale.MEDIUM + else 1.0 + ), + stack_offset=(0, 5) if uiscale is bui.UIScale.SMALL else (0, 0), + ) + ) + + if app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: + bui.containerwidget( + edit=self._root_widget, on_cancel_call=self._do_back + ) + self._back_button = None + else: + self._back_button = bui.buttonwidget( + parent=self._root_widget, + position=(53 + x_inset, self._height - 60), + size=(140, 60), + scale=0.8, + autoselect=True, + label=bui.Lstr(resource='backText'), + button_type='back', + on_activate_call=self._do_back, + ) + bui.containerwidget( + edit=self._root_widget, cancel_button=self._back_button + ) + + self._title_text = bui.textwidget( + parent=self._root_widget, + position=(0, self._height - 52), + size=(self._width, 25), + text='Discord', + color=app.ui_v1.title_color, + h_align='center', + v_align='top', + ) + + min_size = min(self._width - 25, self._height - 25) + bui.imagewidget( + parent=self._root_widget, + position=(40, -15), + size=(min_size, min_size), + texture=bui.gettexture('discordPreview'), + ) + + bui.textwidget( + parent=self._root_widget, + position=(self._width / 2 - 60, self._height - 100), + text='We have our own Discord server where you can:\n- Find new' + ' friends and people to play with\n- Participate in Office' + ' Hours/Coffee with Eric\n- Share mods, plugins, art, and' + ' memes\n- Report bugs and make feature suggestions\n' + '- Troubleshoot issues', + maxwidth=(self._width - 10) / 2, + color=(1, 1, 1, 1), + h_align='left', + v_align='top', + ) + + bui.buttonwidget( + parent=self._root_widget, + position=(self._width / 2 - 30, 20), + size=(self._width / 2 - 60, 60), + autoselect=True, + label='Join The Discord', + text_scale=1.0, + on_activate_call=bui.Call( + bui.open_url, 'https://ballistica.net/discord' + ), + ) + + 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), + ) + + def _do_back(self) -> None: + bui.containerwidget(edit=self._root_widget, transition='out_scale') diff --git a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py index 66c3f480..67d02bcd 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py @@ -80,15 +80,12 @@ class AboutGatherTab(GatherTab): bui.textwidget( parent=self._container, - position=( - region_width * 0.5, - c_height_2 * (0.58 if include_invite else 0.5), - ), + position=(region_width * 0.5, c_height_2 * 0.58), color=(0.6, 1.0, 0.6), scale=msc_scale, size=(0, 0), maxwidth=region_width * 0.9, - max_height=c_height_2 * (0.7 if include_invite else 0.9), + max_height=c_height_2 * 0.7, h_align='center', v_align='center', text=message, @@ -97,7 +94,7 @@ class AboutGatherTab(GatherTab): if include_invite: bui.textwidget( parent=self._container, - position=(region_width * 0.57, 35), + position=(region_width * 0.57, 85), color=(0, 1, 0), scale=0.6, size=(0, 0), @@ -112,7 +109,7 @@ class AboutGatherTab(GatherTab): ) bui.buttonwidget( parent=self._container, - position=(region_width * 0.59, 10), + position=(region_width * 0.59, 60), size=(230, 50), color=(0.54, 0.42, 0.56), textcolor=(0, 1, 0), @@ -124,6 +121,32 @@ class AboutGatherTab(GatherTab): on_activate_call=bui.WeakCall(self._invite_to_try_press), up_widget=tab_button, ) + + bui.textwidget( + parent=self._container, + position=(region_width * 0.57, 15 if include_invite else 75), + color=(0.6, 0.6, 1), + scale=0.6, + size=(0, 0), + maxwidth=region_width * 0.5, + h_align='right', + v_align='center', + flatness=1.0, + text='Want to look for new people to play with?\nJoin our Discord' + ' and find new friends!', + ) + bui.buttonwidget( + parent=self._container, + position=(region_width * 0.59, -10 if include_invite else 50), + size=(230, 50), + color=(0.54, 0.42, 0.56), + textcolor=(0.6, 0.6, 1), + label='Join The Discord', + autoselect=True, + on_activate_call=bui.WeakCall(self._join_the_discord_press), + up_widget=tab_button, + ) + return self._container def _invite_to_try_press(self) -> None: @@ -137,3 +160,10 @@ class AboutGatherTab(GatherTab): show_sign_in_prompt() return handle_app_invites_press() + + def _join_the_discord_press(self) -> None: + # pylint: disable=cyclic-import + from bauiv1lib.discord import DiscordWindow + + assert bui.app.classic is not None + DiscordWindow().get_root_widget() diff --git a/src/assets/ba_data/python/bauiv1lib/mainmenu.py b/src/assets/ba_data/python/bauiv1lib/mainmenu.py index d1a00332..505484f1 100644 --- a/src/assets/ba_data/python/bauiv1lib/mainmenu.py +++ b/src/assets/ba_data/python/bauiv1lib/mainmenu.py @@ -105,6 +105,7 @@ class MainMenuWindow(bui.Window): import bauiv1lib.gather as _unused10 import bauiv1lib.watch as _unused11 import bauiv1lib.play as _unused12 + import bauiv1lib.discord as _unused13 def _show_remote_app_info_on_first_launch(self) -> None: app = bui.app @@ -217,7 +218,7 @@ class MainMenuWindow(bui.Window): self._have_store_button = not self._in_game - self._have_settings_button = ( + self._have_settings_button = self._have_discord_button = ( not self._in_game or not app.ui_v1.use_toolbars ) and not (self._is_demo or self._is_arcade) @@ -365,6 +366,24 @@ class MainMenuWindow(bui.Window): else: self._store_button = None + self._discord_button: bui.Widget | None + if self._have_discord_button: + h, v, scale = positions[self._p_index] + self._p_index += 1 + self._discord_button = bui.buttonwidget( + parent=self._root_widget, + position=(h - self._button_width * 0.5 * scale, v), + size=(self._button_width, self._button_height), + scale=scale, + autoselect=self._use_autoselect, + label='Discord', + transition_delay=self._tdelay, + on_activate_call=self._discord, + ) + self._tdelay += self._t_delay_inc + else: + self._discord_button = None + self._quit_button: bui.Widget | None if not self._in_game and self._have_quit_button: h, v, scale = positions[self._p_index] @@ -563,6 +582,8 @@ class MainMenuWindow(bui.Window): b_count = 3 # play, help, credits if self._have_settings_button: b_count += 1 + if self._have_discord_button: + b_count += 1 if enable_account_button: b_count += 1 if self._have_quit_button: @@ -1202,6 +1223,13 @@ class MainMenuWindow(bui.Window): ).get_root_widget() ) + def _discord(self) -> None: + # pylint: disable=cyclic-import + from bauiv1lib.discord import DiscordWindow + + assert bui.app.classic is not None + DiscordWindow(origin_widget=self._settings_button).get_root_widget() + def _resume_and_call(self, call: Callable[[], Any]) -> None: self._resume() call() @@ -1232,6 +1260,8 @@ class MainMenuWindow(bui.Window): ui.main_menu_selection = 'Credits' elif sel == self._settings_button: ui.main_menu_selection = 'Settings' + elif sel == self._discord_button: + ui.main_menu_selection = 'Discord' elif sel == self._account_button: ui.main_menu_selection = 'Account' elif sel == self._store_button: @@ -1265,6 +1295,8 @@ class MainMenuWindow(bui.Window): sel = self._credits_button elif sel_name == 'Settings': sel = self._settings_button + elif sel_name == 'Discord': + sel = self._discord_button elif sel_name == 'Account': sel = self._account_button elif sel_name == 'Store':