mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-09 01:09:40 +08:00
Wired up private hosting playlist selection
This commit is contained in:
parent
49f8e4ddba
commit
398158f5f5
@ -3936,22 +3936,22 @@
|
|||||||
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d2/41/e8362cfe9f6fd6dc882858021874",
|
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d2/41/e8362cfe9f6fd6dc882858021874",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/83/ff/29cf07587f212d5278bb5ed92e75",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/83/ff/29cf07587f212d5278bb5ed92e75",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/90/e7/c4834a3b41d8f9d837071dc0800a",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/90/e7/c4834a3b41d8f9d837071dc0800a",
|
||||||
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ce/3d/0febcd4db42fe5dedb701c60bddf",
|
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/7b/a8/9890f10c94576c95314f8af13691",
|
||||||
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c5/d8/3d7ca6668af72200a6eea00c6d84",
|
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c1/5b/6f127d8dab6ee7926970fc6a608a",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/79/f2/3381ea14e11854a9e8804953bb06",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/48/23/07790e69616cb6b4cc363d6387f3",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/80/00/a02fdfe67796bc04a78dbd6ed353",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/97/45/3b791f71346eaa3336ce6d272710",
|
||||||
"build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/19/36/ebf5f0f1c7a2923f7e3c4ee292ad",
|
"build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/a2/a0/0f9815da065672d14b75b078a2d7",
|
||||||
"build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fb/4f/fbddddae2d5963a1ec6f97234db3",
|
"build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fb/4f/fbddddae2d5963a1ec6f97234db3",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/0d/32/8755d570c2e74316497bdd290f0d",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ff/3f/73f4d04c55fdc6ed0c94bfee3acc",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/24/30/863f0c9948669219f66b117502bc",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/24/30/863f0c9948669219f66b117502bc",
|
||||||
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3c/dc/317d57caa8b27d5b685193cf3de9",
|
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b5/27/9acf2ec153e1ce69bc695065014e",
|
||||||
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/cd/8a/3fc0cca1383b6af2a4f8a5ae2cfe",
|
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/cd/8a/3fc0cca1383b6af2a4f8a5ae2cfe",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/20/16/c0cf342b1971dcbc757abd29bdc5",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4b/24/a951fe7baf708257f00d992624f4",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1b/06/f81485b10ac37b58a012bc158952",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1b/06/f81485b10ac37b58a012bc158952",
|
||||||
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/85/44/92172591b72302dc4909b0e91108",
|
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/e9/27/5e1dae33935559c07c35af56e201",
|
||||||
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d4/e6/8d5a9ffcf32588f8b770a88a80d5",
|
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/f8/af/4304308263b7fa98aaa5d430e753",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/c7/9c/e55d58caf88ad6bb88f1a5ebfdbf",
|
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/74/fd/099a83595d8843537e945373fe99",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/f2/6e/981553869590e8367854b5df2802",
|
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/a2/cb/1590daac51edd95af2e1e243f435",
|
||||||
"build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/21/016123d9ec8293ce92ba910dd00a",
|
"build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/21/016123d9ec8293ce92ba910dd00a",
|
||||||
"build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6f/f8/cf46e7c33a0a237e2c6f19ef4f92",
|
"build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6f/f8/cf46e7c33a0a237e2c6f19ef4f92",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/10/67/5a3d6131d1b1fdf9f629301b68db",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/10/67/5a3d6131d1b1fdf9f629301b68db",
|
||||||
@ -3960,12 +3960,12 @@
|
|||||||
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/7c/b5f26ca01907df6ea80ff3ae5861",
|
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/7c/b5f26ca01907df6ea80ff3ae5861",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/76/9ea770a68773fd4a08fb78855fbb",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/76/9ea770a68773fd4a08fb78855fbb",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1d/b3/329956f15f5cb76a63bd4fd3e0cc",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1d/b3/329956f15f5cb76a63bd4fd3e0cc",
|
||||||
"build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/30/04/7b7c4f847fd992b23719f755981a",
|
"build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c6/90/79c30dd05db52cd4d47c69a89f24",
|
||||||
"build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/bc/20/e13686c62052e3e388431d4859aa",
|
"build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3f/1e/21c32a8bbcd86b1005c5125bfbf6",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a3/a1/1bb8a1926628e34054aeca5a0178",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9d/68/36828f4dbd36530a5c45d5b3cdaa",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5a/33/c232d2c633bf70915e1a8eecdf95",
|
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/68/24/667e0f09f4e5fc7a7498f571dc38",
|
||||||
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/84/8c/2930553d642210c81b6342bffb9f",
|
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/47/8d/f3bfac44ac9cae60574949c2770a",
|
||||||
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/68/22/cc580cef75b9e452de66095ba62b",
|
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/31/19/d117f00a867c7725148b6e1d3932",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/93/2d/b6482a7ce6957156fe050f4cc9dc",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/8e/c7bf8dfe338e75eb0026ec81691c",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d1/a2/1d592f5d21dd39d7b16da8f1c8c4"
|
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fc/ba/555e3d9c823d4cb19541169a514a"
|
||||||
}
|
}
|
||||||
3
.idea/dictionaries/ericf.xml
generated
3
.idea/dictionaries/ericf.xml
generated
@ -974,6 +974,7 @@
|
|||||||
<w>homebrew</w>
|
<w>homebrew</w>
|
||||||
<w>hometest</w>
|
<w>hometest</w>
|
||||||
<w>hostconfig</w>
|
<w>hostconfig</w>
|
||||||
|
<w>hostingconfig</w>
|
||||||
<w>hostingstate</w>
|
<w>hostingstate</w>
|
||||||
<w>hostuser</w>
|
<w>hostuser</w>
|
||||||
<w>hout</w>
|
<w>hout</w>
|
||||||
@ -1458,6 +1459,7 @@
|
|||||||
<w>oghashes</w>
|
<w>oghashes</w>
|
||||||
<w>ogval</w>
|
<w>ogval</w>
|
||||||
<w>oival</w>
|
<w>oival</w>
|
||||||
|
<w>okbtn</w>
|
||||||
<w>oldlady</w>
|
<w>oldlady</w>
|
||||||
<w>onln</w>
|
<w>onln</w>
|
||||||
<w>onscreencountdown</w>
|
<w>onscreencountdown</w>
|
||||||
@ -1893,6 +1895,7 @@
|
|||||||
<w>sessionteam's</w>
|
<w>sessionteam's</w>
|
||||||
<w>sessionteams</w>
|
<w>sessionteams</w>
|
||||||
<w>sessiontype</w>
|
<w>sessiontype</w>
|
||||||
|
<w>sessiontypestr</w>
|
||||||
<w>setactivity</w>
|
<w>setactivity</w>
|
||||||
<w>setalpha</w>
|
<w>setalpha</w>
|
||||||
<w>setbuild</w>
|
<w>setbuild</w>
|
||||||
|
|||||||
@ -57,6 +57,11 @@ class UISubsystem:
|
|||||||
self.heading_color = (0.72, 0.7, 0.75)
|
self.heading_color = (0.72, 0.7, 0.75)
|
||||||
self.infotextcolor = (0.7, 0.9, 0.7)
|
self.infotextcolor = (0.7, 0.9, 0.7)
|
||||||
|
|
||||||
|
# Switch our overall game selection UI flow between Play and
|
||||||
|
# Private-party playlist selection modes; should do this in
|
||||||
|
# a more elegant way once we revamp high level UI stuff a bit.
|
||||||
|
self.selecting_private_party_playlist: bool = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def uiscale(self) -> ba.UIScale:
|
def uiscale(self) -> ba.UIScale:
|
||||||
"""Current ui scale for the app."""
|
"""Current ui scale for the app."""
|
||||||
|
|||||||
@ -217,6 +217,15 @@ class GatherWindow(ba.Window):
|
|||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
_ba.set_party_icon_always_visible(False)
|
_ba.set_party_icon_always_visible(False)
|
||||||
|
|
||||||
|
def playlist_select(self, origin_widget: ba.Widget) -> None:
|
||||||
|
"""Called by the private-hosting tab to select a playlist."""
|
||||||
|
from bastd.ui.play import PlayWindow
|
||||||
|
self._save_state()
|
||||||
|
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
|
ba.app.ui.selecting_private_party_playlist = True
|
||||||
|
ba.app.ui.set_main_menu_window(
|
||||||
|
PlayWindow(origin_widget=origin_widget).get_root_widget())
|
||||||
|
|
||||||
def _set_tab(self, tab_id: TabID) -> None:
|
def _set_tab(self, tab_id: TabID) -> None:
|
||||||
if self._current_tab is tab_id:
|
if self._current_tab is tab_id:
|
||||||
return
|
return
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import os
|
|||||||
import copy
|
import copy
|
||||||
import time
|
import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, asdict
|
||||||
from typing import TYPE_CHECKING, cast
|
from typing import TYPE_CHECKING, cast
|
||||||
|
|
||||||
import ba
|
import ba
|
||||||
@ -18,7 +18,7 @@ from bastd.ui.gather import GatherTab
|
|||||||
from bastd.ui import getcurrency
|
from bastd.ui import getcurrency
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Optional, Dict, Any, List
|
from typing import Optional, Dict, Any, List, Type
|
||||||
from bastd.ui.gather import GatherWindow
|
from bastd.ui.gather import GatherWindow
|
||||||
|
|
||||||
# Print a bit of info about queries, etc.
|
# Print a bit of info about queries, etc.
|
||||||
@ -56,6 +56,18 @@ class HostingState:
|
|||||||
free_host_minutes_remaining: Optional[float] = None
|
free_host_minutes_remaining: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class HostingConfig:
|
||||||
|
"""Config we provide when hosting."""
|
||||||
|
session_type: str = 'ffa'
|
||||||
|
playlist_name: str = 'Unknown'
|
||||||
|
randomize: bool = False
|
||||||
|
tutorial: bool = False
|
||||||
|
custom_team_names: Optional[List[str]] = None
|
||||||
|
custom_team_colors: Optional[List[List[float]]] = None
|
||||||
|
playlist: Optional[List[Dict[str, Any]]] = None
|
||||||
|
|
||||||
|
|
||||||
class PrivateGatherTab(GatherTab):
|
class PrivateGatherTab(GatherTab):
|
||||||
"""The private tab in the gather UI"""
|
"""The private tab in the gather UI"""
|
||||||
|
|
||||||
@ -82,6 +94,12 @@ class PrivateGatherTab(GatherTab):
|
|||||||
self._showing_not_signed_in_screen = False
|
self._showing_not_signed_in_screen = False
|
||||||
self._create_time = time.time()
|
self._create_time = time.time()
|
||||||
self._last_action_send_time: Optional[float] = None
|
self._last_action_send_time: Optional[float] = None
|
||||||
|
self._connect_press_time: Optional[float] = None
|
||||||
|
try:
|
||||||
|
self._hostingconfig = self._build_hosting_config()
|
||||||
|
except Exception:
|
||||||
|
ba.print_exception('Error building hosting config')
|
||||||
|
self._hostingconfig = HostingConfig()
|
||||||
|
|
||||||
def on_activate(
|
def on_activate(
|
||||||
self,
|
self,
|
||||||
@ -159,6 +177,55 @@ class PrivateGatherTab(GatherTab):
|
|||||||
|
|
||||||
return self._container
|
return self._container
|
||||||
|
|
||||||
|
def _build_hosting_config(self) -> HostingConfig:
|
||||||
|
from bastd.ui.playlist import PlaylistTypeVars
|
||||||
|
from ba.internal import filter_playlist
|
||||||
|
hcfg = HostingConfig()
|
||||||
|
cfg = ba.app.config
|
||||||
|
sessiontypestr = cfg.get('Private Party Host Session Type')
|
||||||
|
if not isinstance(sessiontypestr, str):
|
||||||
|
raise RuntimeError(f'Invalid sessiontype {sessiontypestr}')
|
||||||
|
hcfg.session_type = sessiontypestr
|
||||||
|
|
||||||
|
sessiontype: Type[ba.Session]
|
||||||
|
if hcfg.session_type == 'ffa':
|
||||||
|
sessiontype = ba.FreeForAllSession
|
||||||
|
elif hcfg.session_type == 'teams':
|
||||||
|
sessiontype = ba.DualTeamSession
|
||||||
|
else:
|
||||||
|
raise RuntimeError('fInvalid sessiontype: {hcfg.session_type}')
|
||||||
|
pvars = PlaylistTypeVars(sessiontype)
|
||||||
|
|
||||||
|
playlist_name = ba.app.config.get(
|
||||||
|
f'{pvars.config_name} Playlist Selection')
|
||||||
|
if not isinstance(playlist_name, str):
|
||||||
|
playlist_name = '__default__'
|
||||||
|
hcfg.playlist_name = (pvars.default_list_name.evaluate()
|
||||||
|
if playlist_name == '__default__' else
|
||||||
|
playlist_name)
|
||||||
|
|
||||||
|
if playlist_name == '__default__':
|
||||||
|
playlist = pvars.get_default_list_call()
|
||||||
|
else:
|
||||||
|
playlist = cfg[f'{pvars.config_name} Playlists'][playlist_name]
|
||||||
|
hcfg.playlist = filter_playlist(playlist, sessiontype)
|
||||||
|
|
||||||
|
randomize = cfg.get(f'{pvars.config_name} Playlist Randomize')
|
||||||
|
if not isinstance(randomize, bool):
|
||||||
|
randomize = False
|
||||||
|
hcfg.randomize = randomize
|
||||||
|
|
||||||
|
tutorial = cfg.get('Show Tutorial')
|
||||||
|
if not isinstance(tutorial, bool):
|
||||||
|
tutorial = False
|
||||||
|
hcfg.tutorial = tutorial
|
||||||
|
|
||||||
|
if hcfg.session_type == 'teams':
|
||||||
|
hcfg.custom_team_names = copy.copy(cfg.get('Custom Team Names'))
|
||||||
|
hcfg.custom_team_colors = copy.copy(cfg.get('Custom Team Colors'))
|
||||||
|
|
||||||
|
return hcfg
|
||||||
|
|
||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
self._update_timer = None
|
self._update_timer = None
|
||||||
|
|
||||||
@ -344,7 +411,7 @@ class PrivateGatherTab(GatherTab):
|
|||||||
'manualConnectText'),
|
'manualConnectText'),
|
||||||
position=(self._c_width * 0.5 - 150,
|
position=(self._c_width * 0.5 - 150,
|
||||||
self._c_height - 350),
|
self._c_height - 350),
|
||||||
on_activate_call=self._connect_press,
|
on_activate_call=self._join_connect_press,
|
||||||
autoselect=True)
|
autoselect=True)
|
||||||
ba.textwidget(edit=self._join_party_code_text,
|
ba.textwidget(edit=self._join_party_code_text,
|
||||||
on_return_press_call=btn.activate)
|
on_return_press_call=btn.activate)
|
||||||
@ -358,7 +425,6 @@ class PrivateGatherTab(GatherTab):
|
|||||||
# overlay layer so we'd show up above it).
|
# overlay layer so we'd show up above it).
|
||||||
getcurrency.GetCurrencyWindow(modal=True,
|
getcurrency.GetCurrencyWindow(modal=True,
|
||||||
origin_widget=self._get_tickets_button)
|
origin_widget=self._get_tickets_button)
|
||||||
# self._transition_out()
|
|
||||||
|
|
||||||
def _build_host_tab(self) -> None:
|
def _build_host_tab(self) -> None:
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
@ -457,12 +523,18 @@ class PrivateGatherTab(GatherTab):
|
|||||||
size=(400, 70),
|
size=(400, 70),
|
||||||
color=(0.6, 0.5, 0.6),
|
color=(0.6, 0.5, 0.6),
|
||||||
textcolor=(0.8, 0.75, 0.8),
|
textcolor=(0.8, 0.75, 0.8),
|
||||||
label='Default Free-For-All Playlist',
|
label=self._hostingconfig.playlist_name,
|
||||||
on_activate_call=lambda: ba.screenmessage(
|
on_activate_call=self._playlist_press,
|
||||||
'TODO: WIRE UP PLAYLIST SELECTION'),
|
|
||||||
position=(self._c_width * 0.5 - 200, v - 35),
|
position=(self._c_width * 0.5 - 200, v - 35),
|
||||||
up_widget=self._host_sub_tab_text,
|
up_widget=self._host_sub_tab_text,
|
||||||
autoselect=True)
|
autoselect=True)
|
||||||
|
|
||||||
|
# If it appears we're coming back from playlist selection,
|
||||||
|
# re-select our playlist button.
|
||||||
|
if ba.app.ui.selecting_private_party_playlist:
|
||||||
|
ba.containerwidget(edit=self._container,
|
||||||
|
selected_child=self._host_playlist_button)
|
||||||
|
ba.app.ui.selecting_private_party_playlist = False
|
||||||
else:
|
else:
|
||||||
# We've got a current party; show its info.
|
# We've got a current party; show its info.
|
||||||
ba.textwidget(
|
ba.textwidget(
|
||||||
@ -641,6 +713,10 @@ class PrivateGatherTab(GatherTab):
|
|||||||
on_activate_call=self._host_button_press,
|
on_activate_call=self._host_button_press,
|
||||||
autoselect=True)
|
autoselect=True)
|
||||||
|
|
||||||
|
def _playlist_press(self) -> None:
|
||||||
|
assert self._host_playlist_button is not None
|
||||||
|
self.window.playlist_select(origin_widget=self._host_playlist_button)
|
||||||
|
|
||||||
def _host_copy_press(self) -> None:
|
def _host_copy_press(self) -> None:
|
||||||
assert self._hostingstate.party_code is not None
|
assert self._hostingstate.party_code is not None
|
||||||
ba.clipboard_set_text(self._hostingstate.party_code)
|
ba.clipboard_set_text(self._hostingstate.party_code)
|
||||||
@ -656,6 +732,17 @@ class PrivateGatherTab(GatherTab):
|
|||||||
f'{time.time()-self._create_time:.2f}')
|
f'{time.time()-self._create_time:.2f}')
|
||||||
|
|
||||||
def _connect_to_party_code(self, code: str) -> None:
|
def _connect_to_party_code(self, code: str) -> None:
|
||||||
|
|
||||||
|
# Ignore attempted followup sends for a few seconds.
|
||||||
|
# (this will reset if we get a response)
|
||||||
|
now = time.time()
|
||||||
|
if (self._connect_press_time is not None
|
||||||
|
and now - self._connect_press_time < 5.0):
|
||||||
|
self._debug_server_comm(
|
||||||
|
'not sending private party connect (too soon)')
|
||||||
|
return
|
||||||
|
self._connect_press_time = now
|
||||||
|
|
||||||
self._debug_server_comm('sending private party connect')
|
self._debug_server_comm('sending private party connect')
|
||||||
_ba.add_transaction(
|
_ba.add_transaction(
|
||||||
{
|
{
|
||||||
@ -697,9 +784,12 @@ class PrivateGatherTab(GatherTab):
|
|||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
return
|
return
|
||||||
self._last_action_send_time = time.time()
|
self._last_action_send_time = time.time()
|
||||||
_ba.add_transaction({'type': 'PRIVATE_PARTY_START'},
|
_ba.add_transaction(
|
||||||
callback=ba.WeakCall(
|
{
|
||||||
self._hosting_state_response))
|
'type': 'PRIVATE_PARTY_START',
|
||||||
|
'config': asdict(self._hostingconfig)
|
||||||
|
},
|
||||||
|
callback=ba.WeakCall(self._hosting_state_response))
|
||||||
_ba.run_transactions()
|
_ba.run_transactions()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -713,7 +803,9 @@ class PrivateGatherTab(GatherTab):
|
|||||||
self._waiting_for_hosting_state = True
|
self._waiting_for_hosting_state = True
|
||||||
self._refresh_sub_tab()
|
self._refresh_sub_tab()
|
||||||
|
|
||||||
def _connect_press(self) -> None:
|
def _join_connect_press(self) -> None:
|
||||||
|
|
||||||
|
# Error immediately if its an empty code.
|
||||||
code: Optional[str] = None
|
code: Optional[str] = None
|
||||||
if self._join_party_code_text:
|
if self._join_party_code_text:
|
||||||
code = cast(str, ba.textwidget(query=self._join_party_code_text))
|
code = cast(str, ba.textwidget(query=self._join_party_code_text))
|
||||||
@ -723,10 +815,12 @@ class PrivateGatherTab(GatherTab):
|
|||||||
color=(1, 0, 0))
|
color=(1, 0, 0))
|
||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
return
|
return
|
||||||
|
|
||||||
self._connect_to_party_code(code)
|
self._connect_to_party_code(code)
|
||||||
|
|
||||||
def _connect_response(self, result: Optional[Dict[str, Any]]) -> None:
|
def _connect_response(self, result: Optional[Dict[str, Any]]) -> None:
|
||||||
try:
|
try:
|
||||||
|
self._connect_press_time = None
|
||||||
if result is None:
|
if result is None:
|
||||||
raise RuntimeError()
|
raise RuntimeError()
|
||||||
cresult = dataclass_from_dict(ConnectResult, result)
|
cresult = dataclass_from_dict(ConnectResult, result)
|
||||||
|
|||||||
@ -1027,6 +1027,8 @@ class MainMenuWindow(ba.Window):
|
|||||||
from bastd.ui.play import PlayWindow
|
from bastd.ui.play import PlayWindow
|
||||||
self._save_state()
|
self._save_state()
|
||||||
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
|
|
||||||
|
ba.app.ui.selecting_private_party_playlist = False
|
||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
PlayWindow(origin_widget=self._start_button).get_root_widget())
|
PlayWindow(origin_widget=self._start_button).get_root_widget())
|
||||||
|
|
||||||
|
|||||||
@ -27,11 +27,14 @@ class PlayWindow(ba.Window):
|
|||||||
# have a visual hitch when the user taps them.
|
# have a visual hitch when the user taps them.
|
||||||
threading.Thread(target=self._preload_modules).start()
|
threading.Thread(target=self._preload_modules).start()
|
||||||
|
|
||||||
new_style = True
|
# We can currently be used either for main menu duty or for selecting
|
||||||
|
# playlists (should make this more elegant/general).
|
||||||
|
self._is_main_menu = not ba.app.ui.selecting_private_party_playlist
|
||||||
|
|
||||||
uiscale = ba.app.ui.uiscale
|
uiscale = ba.app.ui.uiscale
|
||||||
width = 1000 if uiscale is ba.UIScale.SMALL else 800
|
width = 1000 if uiscale is ba.UIScale.SMALL else 800
|
||||||
x_offs = 100 if uiscale is ba.UIScale.SMALL else 0
|
x_offs = 100 if uiscale is ba.UIScale.SMALL else 0
|
||||||
height = 550 if new_style else 400
|
height = 550
|
||||||
button_width = 400
|
button_width = 400
|
||||||
|
|
||||||
scale_origin: Optional[Tuple[float, float]]
|
scale_origin: Optional[Tuple[float, float]]
|
||||||
@ -50,14 +53,12 @@ class PlayWindow(ba.Window):
|
|||||||
transition=transition,
|
transition=transition,
|
||||||
toolbar_visibility='menu_full',
|
toolbar_visibility='menu_full',
|
||||||
scale_origin_stack_offset=scale_origin,
|
scale_origin_stack_offset=scale_origin,
|
||||||
scale=((1.6 if new_style else 1.52) if uiscale is ba.UIScale.SMALL
|
scale=(1.6 if uiscale is ba.UIScale.SMALL else
|
||||||
else 0.9 if uiscale is ba.UIScale.MEDIUM else 0.8),
|
0.9 if uiscale is ba.UIScale.MEDIUM else 0.8),
|
||||||
stack_offset=((0, 0) if new_style else (
|
stack_offset=(0, 0) if uiscale is ba.UIScale.SMALL else (0, 0)))
|
||||||
10, 7)) if uiscale is ba.UIScale.SMALL else (0, 0)))
|
|
||||||
self._back_button = back_button = btn = ba.buttonwidget(
|
self._back_button = back_button = btn = ba.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(55 + x_offs, height - 132) if new_style else
|
position=(55 + x_offs, height - 132),
|
||||||
(55, height - 92),
|
|
||||||
size=(120, 60),
|
size=(120, 60),
|
||||||
scale=1.1,
|
scale=1.1,
|
||||||
text_res_scale=1.5,
|
text_res_scale=1.5,
|
||||||
@ -66,11 +67,15 @@ class PlayWindow(ba.Window):
|
|||||||
label=ba.Lstr(resource='backText'),
|
label=ba.Lstr(resource='backText'),
|
||||||
button_type='back')
|
button_type='back')
|
||||||
|
|
||||||
txt = ba.textwidget(parent=self._root_widget,
|
txt = ba.textwidget(
|
||||||
position=(width * 0.5,
|
parent=self._root_widget,
|
||||||
height - (101 if new_style else 61)),
|
position=(width * 0.5, height - 101),
|
||||||
|
# position=(width * 0.5, height -
|
||||||
|
# (101 if main_menu else 61)),
|
||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
text=ba.Lstr(resource=self._r + '.titleText'),
|
text=ba.Lstr(resource=(
|
||||||
|
self._r +
|
||||||
|
'.titleText') if self._is_main_menu else 'playlistsText'),
|
||||||
scale=1.7,
|
scale=1.7,
|
||||||
res_scale=2.0,
|
res_scale=2.0,
|
||||||
maxwidth=400,
|
maxwidth=400,
|
||||||
@ -85,14 +90,14 @@ class PlayWindow(ba.Window):
|
|||||||
if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
|
if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
|
||||||
ba.textwidget(edit=txt, text='')
|
ba.textwidget(edit=txt, text='')
|
||||||
|
|
||||||
v = height - (110 if new_style else 60)
|
v = height - (110 if self._is_main_menu else 60)
|
||||||
v -= 100
|
v -= 100
|
||||||
clr = (0.6, 0.7, 0.6, 1.0)
|
clr = (0.6, 0.7, 0.6, 1.0)
|
||||||
v -= 280 if new_style else 180
|
v -= 280 if self._is_main_menu else 180
|
||||||
v += (30
|
v += (30
|
||||||
if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL else 0)
|
if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL else 0)
|
||||||
hoffs = x_offs + 80 if new_style else 0
|
hoffs = x_offs + 80 if self._is_main_menu else 0
|
||||||
scl = 1.13 if new_style else 0.68
|
scl = 1.13 if self._is_main_menu else 0.68
|
||||||
|
|
||||||
self._lineup_tex = ba.gettexture('playerLineup')
|
self._lineup_tex = ba.gettexture('playerLineup')
|
||||||
angry_computer_transparent_model = ba.getmodel(
|
angry_computer_transparent_model = ba.getmodel(
|
||||||
@ -107,10 +112,14 @@ class PlayWindow(ba.Window):
|
|||||||
'playerLineup4Transparent')
|
'playerLineup4Transparent')
|
||||||
self._eyes_model = ba.getmodel('plasticEyesTransparent')
|
self._eyes_model = ba.getmodel('plasticEyesTransparent')
|
||||||
|
|
||||||
|
self._coop_button: Optional[ba.Widget] = None
|
||||||
|
# Only show coop button in main-menu variant.
|
||||||
|
if self._is_main_menu:
|
||||||
self._coop_button = btn = ba.buttonwidget(
|
self._coop_button = btn = ba.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(hoffs, v + (scl * 15 if new_style else 0)),
|
position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)),
|
||||||
size=(scl * button_width, scl * (300 if new_style else 360)),
|
size=(scl * button_width,
|
||||||
|
scl * (300 if self._is_main_menu else 360)),
|
||||||
extra_touch_border_scale=0.1,
|
extra_touch_border_scale=0.1,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label='',
|
label='',
|
||||||
@ -123,7 +132,8 @@ class PlayWindow(ba.Window):
|
|||||||
left_widget=_ba.get_special_widget('back_button'))
|
left_widget=_ba.get_special_widget('back_button'))
|
||||||
ba.widget(edit=btn,
|
ba.widget(edit=btn,
|
||||||
up_widget=_ba.get_special_widget('account_button'))
|
up_widget=_ba.get_special_widget('account_button'))
|
||||||
ba.widget(edit=btn,
|
ba.widget(
|
||||||
|
edit=btn,
|
||||||
down_widget=_ba.get_special_widget('settings_button'))
|
down_widget=_ba.get_special_widget('settings_button'))
|
||||||
|
|
||||||
self._draw_dude(0,
|
self._draw_dude(0,
|
||||||
@ -165,7 +175,8 @@ class PlayWindow(ba.Window):
|
|||||||
draw_controller=btn,
|
draw_controller=btn,
|
||||||
position=(hoffs + scl * (-10), v + scl * 95),
|
position=(hoffs + scl * (-10), v + scl * 95),
|
||||||
size=(scl * button_width, scl * 50),
|
size=(scl * button_width, scl * 50),
|
||||||
text=ba.Lstr(resource='playModes.singlePlayerCoopText',
|
text=ba.Lstr(
|
||||||
|
resource='playModes.singlePlayerCoopText',
|
||||||
fallback_resource='playModes.coopText'),
|
fallback_resource='playModes.coopText'),
|
||||||
maxwidth=scl * button_width * 0.7,
|
maxwidth=scl * button_width * 0.7,
|
||||||
res_scale=1.5,
|
res_scale=1.5,
|
||||||
@ -178,7 +189,8 @@ class PlayWindow(ba.Window):
|
|||||||
draw_controller=btn,
|
draw_controller=btn,
|
||||||
position=(hoffs + scl * (-10), v + (scl * 54)),
|
position=(hoffs + scl * (-10), v + (scl * 54)),
|
||||||
size=(scl * button_width, scl * 30),
|
size=(scl * button_width, scl * 30),
|
||||||
text=ba.Lstr(resource=self._r + '.oneToFourPlayersText'),
|
text=ba.Lstr(resource=self._r +
|
||||||
|
'.oneToFourPlayersText'),
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
scale=0.83 * scl,
|
scale=0.83 * scl,
|
||||||
@ -186,14 +198,15 @@ class PlayWindow(ba.Window):
|
|||||||
maxwidth=scl * button_width * 0.7,
|
maxwidth=scl * button_width * 0.7,
|
||||||
color=clr)
|
color=clr)
|
||||||
|
|
||||||
scl = 0.5 if new_style else 0.68
|
scl = 0.5 if self._is_main_menu else 0.68
|
||||||
hoffs += 440 if new_style else 260
|
hoffs += 440 if self._is_main_menu else 216
|
||||||
v += 180 if new_style else 0
|
v += 180 if self._is_main_menu else -68
|
||||||
|
|
||||||
self._teams_button = btn = ba.buttonwidget(
|
self._teams_button = btn = ba.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(hoffs, v + (scl * 15 if new_style else 0)),
|
position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)),
|
||||||
size=(scl * button_width, scl * (300 if new_style else 360)),
|
size=(scl * button_width,
|
||||||
|
scl * (300 if self._is_main_menu else 360)),
|
||||||
extra_touch_border_scale=0.1,
|
extra_touch_border_scale=0.1,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label='',
|
label='',
|
||||||
@ -292,12 +305,13 @@ class PlayWindow(ba.Window):
|
|||||||
maxwidth=scl * button_width * 0.7,
|
maxwidth=scl * button_width * 0.7,
|
||||||
color=clr)
|
color=clr)
|
||||||
|
|
||||||
hoffs += 0 if new_style else 260
|
hoffs += 0 if self._is_main_menu else 300
|
||||||
v -= 155 if new_style else 0
|
v -= 155 if self._is_main_menu else 0
|
||||||
self._free_for_all_button = btn = ba.buttonwidget(
|
self._free_for_all_button = btn = ba.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(hoffs, v + (scl * 15 if new_style else 0)),
|
position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)),
|
||||||
size=(scl * button_width, scl * (300 if new_style else 360)),
|
size=(scl * button_width,
|
||||||
|
scl * (300 if self._is_main_menu else 360)),
|
||||||
extra_touch_border_scale=0.1,
|
extra_touch_border_scale=0.1,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label='',
|
label='',
|
||||||
@ -391,12 +405,14 @@ class PlayWindow(ba.Window):
|
|||||||
back_button.delete()
|
back_button.delete()
|
||||||
ba.containerwidget(edit=self._root_widget,
|
ba.containerwidget(edit=self._root_widget,
|
||||||
on_cancel_call=self._back,
|
on_cancel_call=self._back,
|
||||||
selected_child=self._coop_button)
|
selected_child=self._coop_button
|
||||||
|
if self._is_main_menu else self._teams_button)
|
||||||
else:
|
else:
|
||||||
ba.buttonwidget(edit=back_button, on_activate_call=self._back)
|
ba.buttonwidget(edit=back_button, on_activate_call=self._back)
|
||||||
ba.containerwidget(edit=self._root_widget,
|
ba.containerwidget(edit=self._root_widget,
|
||||||
cancel_button=back_button,
|
cancel_button=back_button,
|
||||||
selected_child=self._coop_button)
|
selected_child=self._coop_button
|
||||||
|
if self._is_main_menu else self._teams_button)
|
||||||
|
|
||||||
self._restore_state()
|
self._restore_state()
|
||||||
|
|
||||||
@ -410,12 +426,20 @@ class PlayWindow(ba.Window):
|
|||||||
|
|
||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
if self._is_main_menu:
|
||||||
from bastd.ui.mainmenu import MainMenuWindow
|
from bastd.ui.mainmenu import MainMenuWindow
|
||||||
self._save_state()
|
self._save_state()
|
||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget())
|
MainMenuWindow(transition='in_left').get_root_widget())
|
||||||
ba.containerwidget(edit=self._root_widget,
|
ba.containerwidget(edit=self._root_widget,
|
||||||
transition=self._transition_out)
|
transition=self._transition_out)
|
||||||
|
else:
|
||||||
|
from bastd.ui.gather import GatherWindow
|
||||||
|
self._save_state()
|
||||||
|
ba.app.ui.set_main_menu_window(
|
||||||
|
GatherWindow(transition='in_left').get_root_widget())
|
||||||
|
ba.containerwidget(edit=self._root_widget,
|
||||||
|
transition=self._transition_out)
|
||||||
|
|
||||||
def _coop(self) -> None:
|
def _coop(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
@ -532,7 +556,7 @@ class PlayWindow(ba.Window):
|
|||||||
sel = self._root_widget.get_selected_child()
|
sel = self._root_widget.get_selected_child()
|
||||||
if sel == self._teams_button:
|
if sel == self._teams_button:
|
||||||
sel_name = 'Team Games'
|
sel_name = 'Team Games'
|
||||||
elif sel == self._coop_button:
|
elif self._coop_button is not None and sel == self._coop_button:
|
||||||
sel_name = 'Co-op Games'
|
sel_name = 'Co-op Games'
|
||||||
elif sel == self._free_for_all_button:
|
elif sel == self._free_for_all_button:
|
||||||
sel_name = 'Free-for-All Games'
|
sel_name = 'Free-for-All Games'
|
||||||
@ -549,14 +573,15 @@ class PlayWindow(ba.Window):
|
|||||||
sel_name = ba.app.ui.window_states.get(type(self))
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'Team Games':
|
if sel_name == 'Team Games':
|
||||||
sel = self._teams_button
|
sel = self._teams_button
|
||||||
elif sel_name == 'Co-op Games':
|
elif sel_name == 'Co-op Games' and self._coop_button is not None:
|
||||||
sel = self._coop_button
|
sel = self._coop_button
|
||||||
elif sel_name == 'Free-for-All Games':
|
elif sel_name == 'Free-for-All Games':
|
||||||
sel = self._free_for_all_button
|
sel = self._free_for_all_button
|
||||||
elif sel_name == 'Back':
|
elif sel_name == 'Back':
|
||||||
sel = self._back_button
|
sel = self._back_button
|
||||||
else:
|
else:
|
||||||
sel = self._coop_button
|
sel = (self._coop_button if self._coop_button is not None else
|
||||||
|
self._teams_button)
|
||||||
ba.containerwidget(edit=self._root_widget, selected_child=sel)
|
ba.containerwidget(edit=self._root_widget, selected_child=sel)
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error restoring state for {self}.')
|
ba.print_exception(f'Error restoring state for {self}.')
|
||||||
|
|||||||
@ -53,6 +53,91 @@ class PlaylistBrowserWindow(ba.Window):
|
|||||||
self._sub_width: Optional[float] = None
|
self._sub_width: Optional[float] = None
|
||||||
self._sub_height: Optional[float] = None
|
self._sub_height: Optional[float] = None
|
||||||
|
|
||||||
|
self._ensure_standard_playlists_exist()
|
||||||
|
|
||||||
|
# Get the current selection (if any).
|
||||||
|
self._selected_playlist = ba.app.config.get(self._pvars.config_name +
|
||||||
|
' Playlist Selection')
|
||||||
|
|
||||||
|
uiscale = ba.app.ui.uiscale
|
||||||
|
self._width = 900 if uiscale is ba.UIScale.SMALL else 800
|
||||||
|
x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
|
||||||
|
self._height = (480 if uiscale is ba.UIScale.SMALL else
|
||||||
|
510 if uiscale is ba.UIScale.MEDIUM else 580)
|
||||||
|
|
||||||
|
top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
|
||||||
|
|
||||||
|
super().__init__(root_widget=ba.containerwidget(
|
||||||
|
size=(self._width, self._height + top_extra),
|
||||||
|
transition=transition,
|
||||||
|
toolbar_visibility='menu_full',
|
||||||
|
scale_origin_stack_offset=scale_origin,
|
||||||
|
scale=(1.69 if uiscale is ba.UIScale.SMALL else
|
||||||
|
1.05 if uiscale is ba.UIScale.MEDIUM else 0.9),
|
||||||
|
stack_offset=(0, -26) if uiscale is ba.UIScale.SMALL else (0, 0)))
|
||||||
|
|
||||||
|
self._back_button: Optional[ba.Widget] = ba.buttonwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(59 + x_inset, self._height - 70),
|
||||||
|
size=(120, 60),
|
||||||
|
scale=1.0,
|
||||||
|
on_activate_call=self._on_back_press,
|
||||||
|
autoselect=True,
|
||||||
|
label=ba.Lstr(resource='backText'),
|
||||||
|
button_type='back')
|
||||||
|
ba.containerwidget(edit=self._root_widget,
|
||||||
|
cancel_button=self._back_button)
|
||||||
|
txt = self._title_text = ba.textwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(self._width * 0.5, self._height - 41),
|
||||||
|
size=(0, 0),
|
||||||
|
text=self._pvars.window_title_name,
|
||||||
|
scale=1.3,
|
||||||
|
res_scale=1.5,
|
||||||
|
color=ba.app.ui.heading_color,
|
||||||
|
h_align='center',
|
||||||
|
v_align='center')
|
||||||
|
if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
|
||||||
|
ba.textwidget(edit=txt, text='')
|
||||||
|
|
||||||
|
ba.buttonwidget(edit=self._back_button,
|
||||||
|
button_type='backSmall',
|
||||||
|
size=(60, 54),
|
||||||
|
position=(59 + x_inset, self._height - 67),
|
||||||
|
label=ba.charstr(ba.SpecialChar.BACK))
|
||||||
|
|
||||||
|
if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
|
||||||
|
self._back_button.delete()
|
||||||
|
self._back_button = None
|
||||||
|
ba.containerwidget(edit=self._root_widget,
|
||||||
|
on_cancel_call=self._on_back_press)
|
||||||
|
scroll_offs = 33
|
||||||
|
else:
|
||||||
|
scroll_offs = 0
|
||||||
|
self._scroll_width = self._width - (100 + 2 * x_inset)
|
||||||
|
self._scroll_height = (self._height -
|
||||||
|
(146 if uiscale is ba.UIScale.SMALL
|
||||||
|
and ba.app.ui.use_toolbars else 136))
|
||||||
|
self._scrollwidget = ba.scrollwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
highlight=False,
|
||||||
|
size=(self._scroll_width, self._scroll_height),
|
||||||
|
position=((self._width - self._scroll_width) * 0.5,
|
||||||
|
65 + scroll_offs))
|
||||||
|
ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
|
||||||
|
self._subcontainer: Optional[ba.Widget] = None
|
||||||
|
self._config_name_full = self._pvars.config_name + ' Playlists'
|
||||||
|
self._last_config = None
|
||||||
|
|
||||||
|
# Update now and once per second.
|
||||||
|
# (this should do our initial refresh)
|
||||||
|
self._update()
|
||||||
|
self._update_timer = ba.Timer(1.0,
|
||||||
|
ba.WeakCall(self._update),
|
||||||
|
timetype=ba.TimeType.REAL,
|
||||||
|
repeat=True)
|
||||||
|
|
||||||
|
def _ensure_standard_playlists_exist(self) -> None:
|
||||||
# On new installations, go ahead and create a few playlists
|
# On new installations, go ahead and create a few playlists
|
||||||
# besides the hard-coded default one:
|
# besides the hard-coded default one:
|
||||||
if not _ba.get_account_misc_val('madeStandardPlaylists', False):
|
if not _ba.get_account_misc_val('madeStandardPlaylists', False):
|
||||||
@ -196,88 +281,6 @@ class PlaylistBrowserWindow(ba.Window):
|
|||||||
})
|
})
|
||||||
_ba.run_transactions()
|
_ba.run_transactions()
|
||||||
|
|
||||||
# Get the current selection (if any).
|
|
||||||
self._selected_playlist = ba.app.config.get(self._pvars.config_name +
|
|
||||||
' Playlist Selection')
|
|
||||||
|
|
||||||
uiscale = ba.app.ui.uiscale
|
|
||||||
self._width = 900 if uiscale is ba.UIScale.SMALL else 800
|
|
||||||
x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
|
|
||||||
self._height = (480 if uiscale is ba.UIScale.SMALL else
|
|
||||||
510 if uiscale is ba.UIScale.MEDIUM else 580)
|
|
||||||
|
|
||||||
top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
|
|
||||||
|
|
||||||
super().__init__(root_widget=ba.containerwidget(
|
|
||||||
size=(self._width, self._height + top_extra),
|
|
||||||
transition=transition,
|
|
||||||
toolbar_visibility='menu_full',
|
|
||||||
scale_origin_stack_offset=scale_origin,
|
|
||||||
scale=(1.69 if uiscale is ba.UIScale.SMALL else
|
|
||||||
1.05 if uiscale is ba.UIScale.MEDIUM else 0.9),
|
|
||||||
stack_offset=(0, -26) if uiscale is ba.UIScale.SMALL else (0, 0)))
|
|
||||||
|
|
||||||
self._back_button: Optional[ba.Widget] = ba.buttonwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
position=(59 + x_inset, self._height - 70),
|
|
||||||
size=(120, 60),
|
|
||||||
scale=1.0,
|
|
||||||
on_activate_call=self._on_back_press,
|
|
||||||
autoselect=True,
|
|
||||||
label=ba.Lstr(resource='backText'),
|
|
||||||
button_type='back')
|
|
||||||
ba.containerwidget(edit=self._root_widget,
|
|
||||||
cancel_button=self._back_button)
|
|
||||||
txt = self._title_text = ba.textwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
position=(self._width * 0.5, self._height - 41),
|
|
||||||
size=(0, 0),
|
|
||||||
text=self._pvars.window_title_name,
|
|
||||||
scale=1.3,
|
|
||||||
res_scale=1.5,
|
|
||||||
color=ba.app.ui.heading_color,
|
|
||||||
h_align='center',
|
|
||||||
v_align='center')
|
|
||||||
if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
|
|
||||||
ba.textwidget(edit=txt, text='')
|
|
||||||
|
|
||||||
ba.buttonwidget(edit=self._back_button,
|
|
||||||
button_type='backSmall',
|
|
||||||
size=(60, 54),
|
|
||||||
position=(59 + x_inset, self._height - 67),
|
|
||||||
label=ba.charstr(ba.SpecialChar.BACK))
|
|
||||||
|
|
||||||
if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
|
|
||||||
self._back_button.delete()
|
|
||||||
self._back_button = None
|
|
||||||
ba.containerwidget(edit=self._root_widget,
|
|
||||||
on_cancel_call=self._on_back_press)
|
|
||||||
scroll_offs = 33
|
|
||||||
else:
|
|
||||||
scroll_offs = 0
|
|
||||||
self._scroll_width = self._width - (100 + 2 * x_inset)
|
|
||||||
self._scroll_height = (self._height -
|
|
||||||
(146 if uiscale is ba.UIScale.SMALL
|
|
||||||
and ba.app.ui.use_toolbars else 136))
|
|
||||||
self._scrollwidget = ba.scrollwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
highlight=False,
|
|
||||||
size=(self._scroll_width, self._scroll_height),
|
|
||||||
position=((self._width - self._scroll_width) * 0.5,
|
|
||||||
65 + scroll_offs))
|
|
||||||
ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
|
|
||||||
self._subcontainer: Optional[ba.Widget] = None
|
|
||||||
self._config_name_full = self._pvars.config_name + ' Playlists'
|
|
||||||
self._last_config = None
|
|
||||||
|
|
||||||
# Update now and once per second.
|
|
||||||
# (this should do our initial refresh)
|
|
||||||
self._update()
|
|
||||||
self._update_timer = ba.Timer(1.0,
|
|
||||||
ba.WeakCall(self._update),
|
|
||||||
timetype=ba.TimeType.REAL,
|
|
||||||
repeat=True)
|
|
||||||
|
|
||||||
def _refresh(self) -> None:
|
def _refresh(self) -> None:
|
||||||
# FIXME: Should tidy this up.
|
# FIXME: Should tidy this up.
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
@ -285,9 +288,7 @@ class PlaylistBrowserWindow(ba.Window):
|
|||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
# pylint: disable=too-many-nested-blocks
|
# pylint: disable=too-many-nested-blocks
|
||||||
from efro.util import asserttype
|
from efro.util import asserttype
|
||||||
from ba.internal import (get_map_class,
|
from ba.internal import get_map_class, filter_playlist
|
||||||
get_default_free_for_all_playlist,
|
|
||||||
get_default_teams_playlist, filter_playlist)
|
|
||||||
if not self._root_widget:
|
if not self._root_widget:
|
||||||
return
|
return
|
||||||
if self._subcontainer is not None:
|
if self._subcontainer is not None:
|
||||||
@ -415,13 +416,7 @@ class PlaylistBrowserWindow(ba.Window):
|
|||||||
map_textures = []
|
map_textures = []
|
||||||
map_texture_entries = []
|
map_texture_entries = []
|
||||||
if name == '__default__':
|
if name == '__default__':
|
||||||
if self._sessiontype is ba.FreeForAllSession:
|
playlist = self._pvars.get_default_list_call()
|
||||||
playlist = (get_default_free_for_all_playlist())
|
|
||||||
elif self._sessiontype is ba.DualTeamSession:
|
|
||||||
playlist = get_default_teams_playlist()
|
|
||||||
else:
|
|
||||||
raise Exception('unrecognized session-type: ' +
|
|
||||||
str(self._sessiontype))
|
|
||||||
else:
|
else:
|
||||||
if name not in appconfig[self._pvars.config_name +
|
if name not in appconfig[self._pvars.config_name +
|
||||||
' Playlists']:
|
' Playlists']:
|
||||||
|
|||||||
@ -26,10 +26,7 @@ class PlayOptionsWindow(popup.PopupWindow):
|
|||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
from ba.internal import (getclass, get_default_teams_playlist,
|
from ba.internal import get_map_class, getclass, filter_playlist
|
||||||
get_default_free_for_all_playlist,
|
|
||||||
filter_playlist)
|
|
||||||
from ba.internal import get_map_class
|
|
||||||
from bastd.ui.playlist import PlaylistTypeVars
|
from bastd.ui.playlist import PlaylistTypeVars
|
||||||
|
|
||||||
self._r = 'gameListWindow'
|
self._r = 'gameListWindow'
|
||||||
@ -37,6 +34,10 @@ class PlayOptionsWindow(popup.PopupWindow):
|
|||||||
self._pvars = PlaylistTypeVars(sessiontype)
|
self._pvars = PlaylistTypeVars(sessiontype)
|
||||||
self._transitioning_out = False
|
self._transitioning_out = False
|
||||||
|
|
||||||
|
# We behave differently if we're being used for playlist selection
|
||||||
|
# vs starting a game directly (should make this more elegant).
|
||||||
|
self._selecting_mode = ba.app.ui.selecting_private_party_playlist
|
||||||
|
|
||||||
self._do_randomize_val = (ba.app.config.get(
|
self._do_randomize_val = (ba.app.config.get(
|
||||||
self._pvars.config_name + ' Playlist Randomize', 0))
|
self._pvars.config_name + ' Playlist Randomize', 0))
|
||||||
|
|
||||||
@ -69,13 +70,7 @@ class PlayOptionsWindow(popup.PopupWindow):
|
|||||||
max_columns = 5
|
max_columns = 5
|
||||||
name = playlist
|
name = playlist
|
||||||
if name == '__default__':
|
if name == '__default__':
|
||||||
if self._sessiontype is ba.FreeForAllSession:
|
plst = self._pvars.get_default_list_call()
|
||||||
plst = get_default_free_for_all_playlist()
|
|
||||||
elif self._sessiontype is ba.DualTeamSession:
|
|
||||||
plst = get_default_teams_playlist()
|
|
||||||
else:
|
|
||||||
raise TypeError('unrecognized session-type: ' +
|
|
||||||
str(self._sessiontype))
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
plst = ba.app.config[self._pvars.config_name +
|
plst = ba.app.config[self._pvars.config_name +
|
||||||
@ -323,23 +318,24 @@ class PlayOptionsWindow(popup.PopupWindow):
|
|||||||
ba.widget(edit=self._show_tutorial_check_box,
|
ba.widget(edit=self._show_tutorial_check_box,
|
||||||
up_widget=self._custom_colors_names_button)
|
up_widget=self._custom_colors_names_button)
|
||||||
|
|
||||||
self._play_button = ba.buttonwidget(
|
self._ok_button = ba.buttonwidget(
|
||||||
parent=self.root_widget,
|
parent=self.root_widget,
|
||||||
position=(70, 44),
|
position=(70, 44),
|
||||||
size=(200, 45),
|
size=(200, 45),
|
||||||
scale=1.8,
|
scale=1.8,
|
||||||
text_res_scale=1.5,
|
text_res_scale=1.5,
|
||||||
on_activate_call=self._on_play_press,
|
on_activate_call=self._on_ok_press,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label=ba.Lstr(resource='playText'))
|
label=ba.Lstr(
|
||||||
|
resource='okText' if self._selecting_mode else 'playText'))
|
||||||
|
|
||||||
ba.widget(edit=self._play_button,
|
ba.widget(edit=self._ok_button,
|
||||||
up_widget=self._show_tutorial_check_box)
|
up_widget=self._show_tutorial_check_box)
|
||||||
|
|
||||||
ba.containerwidget(edit=self.root_widget,
|
ba.containerwidget(edit=self.root_widget,
|
||||||
start_button=self._play_button,
|
start_button=self._ok_button,
|
||||||
cancel_button=self._cancel_button,
|
cancel_button=self._cancel_button,
|
||||||
selected_child=self._play_button)
|
selected_child=self._ok_button)
|
||||||
|
|
||||||
# Update now and once per second.
|
# Update now and once per second.
|
||||||
self._update_timer = ba.Timer(1.0,
|
self._update_timer = ba.Timer(1.0,
|
||||||
@ -387,7 +383,7 @@ class PlayOptionsWindow(popup.PopupWindow):
|
|||||||
def _on_cancel_press(self) -> None:
|
def _on_cancel_press(self) -> None:
|
||||||
self._transition_out()
|
self._transition_out()
|
||||||
|
|
||||||
def _on_play_press(self) -> None:
|
def _on_ok_press(self) -> None:
|
||||||
|
|
||||||
# Disallow if our playlist has disappeared.
|
# Disallow if our playlist has disappeared.
|
||||||
if not self._does_target_playlist_exist():
|
if not self._does_target_playlist_exist():
|
||||||
@ -402,13 +398,33 @@ class PlayOptionsWindow(popup.PopupWindow):
|
|||||||
|
|
||||||
cfg = ba.app.config
|
cfg = ba.app.config
|
||||||
cfg[self._pvars.config_name + ' Playlist Selection'] = self._playlist
|
cfg[self._pvars.config_name + ' Playlist Selection'] = self._playlist
|
||||||
cfg.commit()
|
|
||||||
|
# Head back to the gather window in playlist-select mode
|
||||||
|
# or start the game in regular mode.
|
||||||
|
if self._selecting_mode:
|
||||||
|
from bastd.ui.gather import GatherWindow
|
||||||
|
if self._sessiontype is ba.FreeForAllSession:
|
||||||
|
typename = 'ffa'
|
||||||
|
elif self._sessiontype is ba.DualTeamSession:
|
||||||
|
typename = 'teams'
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Only teams and ffa currently supported')
|
||||||
|
cfg['Private Party Host Session Type'] = typename
|
||||||
|
ba.playsound(ba.getsound('gunCocking'))
|
||||||
|
ba.app.ui.set_main_menu_window(
|
||||||
|
GatherWindow(transition='in_right').get_root_widget())
|
||||||
|
self._transition_out(transition='out_left')
|
||||||
|
if self._delegate is not None:
|
||||||
|
self._delegate.on_play_options_window_run_game()
|
||||||
|
else:
|
||||||
_ba.fade_screen(False, endcall=self._run_selected_playlist)
|
_ba.fade_screen(False, endcall=self._run_selected_playlist)
|
||||||
_ba.lock_all_input()
|
_ba.lock_all_input()
|
||||||
self._transition_out(transition='out_left')
|
self._transition_out(transition='out_left')
|
||||||
if self._delegate is not None:
|
if self._delegate is not None:
|
||||||
self._delegate.on_play_options_window_run_game()
|
self._delegate.on_play_options_window_run_game()
|
||||||
|
|
||||||
|
cfg.commit()
|
||||||
|
|
||||||
def _run_selected_playlist(self) -> None:
|
def _run_selected_playlist(self) -> None:
|
||||||
_ba.unlock_all_input()
|
_ba.unlock_all_input()
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -90,15 +90,15 @@ class TeamNamesColorsWindow(popup.PopupWindow):
|
|||||||
on_activate_call=self._on_cancel_press,
|
on_activate_call=self._on_cancel_press,
|
||||||
size=(150, 50),
|
size=(150, 50),
|
||||||
position=(self._width * 0.5 - 200, 20))
|
position=(self._width * 0.5 - 200, 20))
|
||||||
savebtn = ba.buttonwidget(parent=self.root_widget,
|
okbtn = ba.buttonwidget(parent=self.root_widget,
|
||||||
label=ba.Lstr(resource='saveText'),
|
label=ba.Lstr(resource='okText'),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_activate_call=self._save,
|
on_activate_call=self._ok,
|
||||||
size=(150, 50),
|
size=(150, 50),
|
||||||
position=(self._width * 0.5 + 50, 20))
|
position=(self._width * 0.5 + 50, 20))
|
||||||
ba.containerwidget(edit=self.root_widget,
|
ba.containerwidget(edit=self.root_widget,
|
||||||
selected_child=self._color_buttons[0])
|
selected_child=self._color_buttons[0])
|
||||||
ba.widget(edit=savebtn, left_widget=cancelbtn)
|
ba.widget(edit=okbtn, left_widget=cancelbtn)
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def _color_click(self, i: int) -> None:
|
def _color_click(self, i: int) -> None:
|
||||||
@ -136,7 +136,7 @@ class TeamNamesColorsWindow(popup.PopupWindow):
|
|||||||
ba.textwidget(edit=self._color_text_fields[i],
|
ba.textwidget(edit=self._color_text_fields[i],
|
||||||
color=self._colors[i])
|
color=self._colors[i])
|
||||||
|
|
||||||
def _save(self) -> None:
|
def _ok(self) -> None:
|
||||||
from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
|
from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
|
||||||
cfg = ba.app.config
|
cfg = ba.app.config
|
||||||
|
|
||||||
@ -171,11 +171,10 @@ class TeamNamesColorsWindow(popup.PopupWindow):
|
|||||||
if key in cfg:
|
if key in cfg:
|
||||||
del cfg[key]
|
del cfg[key]
|
||||||
else:
|
else:
|
||||||
cfg['Custom Team Names'] = tuple(new_names)
|
cfg['Custom Team Names'] = list(new_names)
|
||||||
cfg['Custom Team Colors'] = tuple(self._colors)
|
cfg['Custom Team Colors'] = list(self._colors)
|
||||||
|
|
||||||
cfg.commit()
|
cfg.commit()
|
||||||
ba.playsound(ba.getsound('gunCocking'))
|
|
||||||
self._transition_out()
|
self._transition_out()
|
||||||
|
|
||||||
def _transition_out(self, transition: str = 'out_scale') -> None:
|
def _transition_out(self, transition: str = 'out_scale') -> None:
|
||||||
|
|||||||
@ -419,6 +419,7 @@
|
|||||||
<w>hostactivity</w>
|
<w>hostactivity</w>
|
||||||
<w>hostcmd</w>
|
<w>hostcmd</w>
|
||||||
<w>hostinfo</w>
|
<w>hostinfo</w>
|
||||||
|
<w>hostingconfig</w>
|
||||||
<w>hostingstate</w>
|
<w>hostingstate</w>
|
||||||
<w>hotkeys</w>
|
<w>hotkeys</w>
|
||||||
<w>hotplug</w>
|
<w>hotplug</w>
|
||||||
@ -627,6 +628,7 @@
|
|||||||
<w>offsx</w>
|
<w>offsx</w>
|
||||||
<w>offsy</w>
|
<w>offsy</w>
|
||||||
<w>oiffsss</w>
|
<w>oiffsss</w>
|
||||||
|
<w>okbtn</w>
|
||||||
<w>oldname</w>
|
<w>oldname</w>
|
||||||
<w>oooo</w>
|
<w>oooo</w>
|
||||||
<w>ooooooo</w>
|
<w>ooooooo</w>
|
||||||
@ -800,6 +802,7 @@
|
|||||||
<w>sessionplayer</w>
|
<w>sessionplayer</w>
|
||||||
<w>sessionteam</w>
|
<w>sessionteam</w>
|
||||||
<w>sessiontype</w>
|
<w>sessiontype</w>
|
||||||
|
<w>sessiontypestr</w>
|
||||||
<w>setactivity</w>
|
<w>setactivity</w>
|
||||||
<w>setattro</w>
|
<w>setattro</w>
|
||||||
<w>setattrofunc</w>
|
<w>setattrofunc</w>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||||
<h4><em>last updated on 2021-01-26 for Ballistica version 1.6.0 build 20278</em></h4>
|
<h4><em>last updated on 2021-01-26 for Ballistica version 1.6.0 build 20279</em></h4>
|
||||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user