Merge pull request #642 from vishal332008/master

A Button for Pausing Replay!
This commit is contained in:
Eric Froemling 2024-01-05 14:28:23 -08:00 committed by GitHub
commit 01c1207e13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 153 additions and 12 deletions

View File

@ -103,6 +103,7 @@ from _bascenev1 import (
host_scan_cycle, host_scan_cycle,
InputDevice, InputDevice,
is_in_replay, is_in_replay,
is_replay_paused,
ls_input_devices, ls_input_devices,
ls_objects, ls_objects,
Material, Material,
@ -112,11 +113,13 @@ from _bascenev1 import (
newactivity, newactivity,
newnode, newnode,
Node, Node,
pause_replay,
printnodes, printnodes,
protocol_version, protocol_version,
release_gamepad_input, release_gamepad_input,
release_keyboard_input, release_keyboard_input,
reset_random_player_names, reset_random_player_names,
resume_replay,
broadcastmessage, broadcastmessage,
SessionData, SessionData,
SessionPlayer, SessionPlayer,
@ -352,6 +355,7 @@ __all__ = [
'IntSetting', 'IntSetting',
'is_in_replay', 'is_in_replay',
'is_point_in_box', 'is_point_in_box',
'is_replay_paused',
'JoinActivity', 'JoinActivity',
'Level', 'Level',
'Lobby', 'Lobby',
@ -374,6 +378,7 @@ __all__ = [
'normalized_color', 'normalized_color',
'NotFoundError', 'NotFoundError',
'OutOfBoundsMessage', 'OutOfBoundsMessage',
'pause_replay',
'PickedUpMessage', 'PickedUpMessage',
'PickUpMessage', 'PickUpMessage',
'Player', 'Player',
@ -394,6 +399,7 @@ __all__ = [
'release_gamepad_input', 'release_gamepad_input',
'release_keyboard_input', 'release_keyboard_input',
'reset_random_player_names', 'reset_random_player_names',
'resume_replay',
'safecolor', 'safecolor',
'screenmessage', 'screenmessage',
'SceneV1AppMode', 'SceneV1AppMode',

View File

@ -70,6 +70,7 @@ class MainMenuWindow(bui.Window):
self._how_to_play_button: bui.Widget | None = None self._how_to_play_button: bui.Widget | None = None
self._credits_button: bui.Widget | None = None self._credits_button: bui.Widget | None = None
self._settings_button: bui.Widget | None = None self._settings_button: bui.Widget | None = None
self._pause_and_resume_image: bui.Widget | None = None
self._next_refresh_allow_time = 0.0 self._next_refresh_allow_time = 0.0
self._store_char_tex = self._get_store_char_tex() self._store_char_tex = self._get_store_char_tex()
@ -431,13 +432,15 @@ class MainMenuWindow(bui.Window):
# media players but this works for now). # media players but this works for now).
if bs.is_in_replay(): if bs.is_in_replay():
b_size = 50.0 b_size = 50.0
b_buffer = 10.0 b_buffer_1 = 50.0
b_buffer_2 = 10.0
t_scale = 0.75 t_scale = 0.75
assert bui.app.classic is not None assert bui.app.classic is not None
uiscale = bui.app.ui_v1.uiscale uiscale = bui.app.ui_v1.uiscale
if uiscale is bui.UIScale.SMALL: if uiscale is bui.UIScale.SMALL:
b_size *= 0.6 b_size *= 0.6
b_buffer *= 1.0 b_buffer_1 *= 0.8
b_buffer_2 *= 1.0
v_offs = -40 v_offs = -40
t_scale = 0.5 t_scale = 0.5
elif uiscale is bui.UIScale.MEDIUM: elif uiscale is bui.UIScale.MEDIUM:
@ -467,8 +470,8 @@ class MainMenuWindow(bui.Window):
btn = bui.buttonwidget( btn = bui.buttonwidget(
parent=self._root_widget, parent=self._root_widget,
position=( position=(
h - b_size - b_buffer, h - b_size - b_buffer_1,
v - b_size - b_buffer + v_offs, v - b_size - b_buffer_2 + v_offs,
), ),
button_type='square', button_type='square',
size=(b_size, b_size), size=(b_size, b_size),
@ -481,8 +484,8 @@ class MainMenuWindow(bui.Window):
draw_controller=btn, draw_controller=btn,
text='-', text='-',
position=( position=(
h - b_size * 0.5 - b_buffer, h - b_size * 0.5 - b_buffer_1,
v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs, v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs,
), ),
h_align='center', h_align='center',
v_align='center', v_align='center',
@ -491,7 +494,10 @@ class MainMenuWindow(bui.Window):
) )
btn = bui.buttonwidget( btn = bui.buttonwidget(
parent=self._root_widget, parent=self._root_widget,
position=(h + b_buffer, v - b_size - b_buffer + v_offs), position=(
h + b_buffer_1,
v - b_size - b_buffer_2 + v_offs
),
button_type='square', button_type='square',
size=(b_size, b_size), size=(b_size, b_size),
label='', label='',
@ -503,14 +509,38 @@ class MainMenuWindow(bui.Window):
draw_controller=btn, draw_controller=btn,
text='+', text='+',
position=( position=(
h + b_size * 0.5 + b_buffer, h + b_size * 0.5 + b_buffer_1,
v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs, v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs,
), ),
h_align='center', h_align='center',
v_align='center', v_align='center',
size=(0, 0), size=(0, 0),
scale=3.0 * t_scale, scale=3.0 * t_scale,
) )
btn = bui.buttonwidget(
parent=self._root_widget,
position=(
h - b_size * 0.5,
v - b_size - b_buffer_2 + v_offs
),
button_type='square',
size=(b_size, b_size),
label='',
autoselect=True,
on_activate_call=bui.Call(self._pause_or_resume_replay),
)
self._pause_and_resume_image = bui.imagewidget(
parent=self._root_widget,
size=(b_size, b_size),
draw_controller=btn,
position=(
h - b_size * 0.47,
v - b_size - b_buffer_2 + v_offs
),
texture=bui.gettexture(
'pauseIcon' if bs.is_replay_paused() else 'resumeIcon'
),
)
def _refresh_not_in_game( def _refresh_not_in_game(
self, positions: list[tuple[float, float, float]] self, positions: list[tuple[float, float, float]]
@ -1034,6 +1064,20 @@ class MainMenuWindow(bui.Window):
), ),
) )
def _pause_or_resume_replay(self) -> None:
if bs.is_replay_paused():
bs.resume_replay()
bui.imagewidget(
edit=self._pause_and_resume_image,
texture=bui.gettexture('resumeIcon'),
)
else:
bs.pause_replay()
bui.imagewidget(
edit=self._pause_and_resume_image,
texture=bui.gettexture('pauseIcon'),
)
def _quit(self) -> None: def _quit(self) -> None:
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
from bauiv1lib.confirm import QuitWindow from bauiv1lib.confirm import QuitWindow

View File

@ -1500,6 +1500,77 @@ static PyMethodDef PySetReplaySpeedExponentDef = {
"Set replay speed. Actual displayed speed is pow(2, speed).", "Set replay speed. Actual displayed speed is pow(2, speed).",
}; };
// -------------------------- is_replay_paused ---------------------------------
static auto PyIsReplayPaused(PyObject* self, PyObject* args)
-> PyObject* {
BA_PYTHON_TRY;
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
if (appmode->is_replay_paused()) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
BA_PYTHON_CATCH;
}
static PyMethodDef PyIsReplayPausedDef = {
"is_replay_paused", // name
PyIsReplayPaused, // method
METH_VARARGS, // flags
"is_replay_paused() -> bool\n"
"\n"
"(internal)\n"
"\n"
"Returns if Replay is paused or not.",
};
// ------------------------ pause_replay ---------------------------------------
static auto PyPauseReplay(PyObject* self, PyObject* args)
-> PyObject* {
BA_PYTHON_TRY;
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
appmode->PauseReplay();
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyPauseReplayDef = {
"pause_replay", // name
PyPauseReplay, // method
METH_VARARGS, // flags
"pause_replay() -> None\n"
"\n"
"(internal)\n"
"\n"
"Pauses replay.",
};
// ------------------------ resume_replay --------------------------------------
static auto PyResumeReplay(PyObject* self, PyObject* args)
-> PyObject* {
BA_PYTHON_TRY;
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
appmode->ResumeReplay();
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyResumeReplayDef = {
"resume_replay", // name
PyResumeReplay, // method
METH_VARARGS, // flags
"resume_replay() -> None\n"
"\n"
"(internal)\n"
"\n"
"Resumes replay.",
};
// ----------------------- reset_random_player_names --------------------------- // ----------------------- reset_random_player_names ---------------------------
static auto PyResetRandomPlayerNames(PyObject* self, PyObject* args, static auto PyResetRandomPlayerNames(PyObject* self, PyObject* args,
@ -1777,6 +1848,9 @@ auto PythonMethodsScene::GetMethods() -> std::vector<PyMethodDef> {
PyResetRandomPlayerNamesDef, PyResetRandomPlayerNamesDef,
PySetReplaySpeedExponentDef, PySetReplaySpeedExponentDef,
PyGetReplaySpeedExponentDef, PyGetReplaySpeedExponentDef,
PyIsReplayPausedDef,
PyPauseReplayDef,
PyResumeReplayDef,
PySetDebugSpeedExponentDef, PySetDebugSpeedExponentDef,
PyGetGameRosterDef, PyGetGameRosterDef,
PyGetForegroundHostActivityDef, PyGetForegroundHostActivityDef,

View File

@ -174,6 +174,11 @@ void ClientSession::Update(int time_advance_millisecs, double time_advance) {
if (shutting_down_) { if (shutting_down_) {
return; return;
} }
if (auto* appmode = SceneV1AppMode::GetActiveOrThrow()) {
if (appmode->is_replay_paused()) {
return;
}
}
// Allow replays to modulate speed, etc. // Allow replays to modulate speed, etc.
// Also plug in our more exact time-advance here instead of the old int one. // Also plug in our more exact time-advance here instead of the old int one.

View File

@ -36,7 +36,7 @@ ClientSessionReplay::~ClientSessionReplay() {
// we no longer are responsible for feeding clients to this device.. // we no longer are responsible for feeding clients to this device..
appmode->connections()->UnregisterClientController(this); appmode->connections()->UnregisterClientController(this);
appmode->ResumeReplay();
if (file_) { if (file_) {
fclose(file_); fclose(file_);
file_ = nullptr; file_ = nullptr;

View File

@ -1223,6 +1223,14 @@ void SceneV1AppMode::SetReplaySpeedExponent(int val) {
replay_speed_mult_ = powf(2.0f, static_cast<float>(replay_speed_exponent_)); replay_speed_mult_ = powf(2.0f, static_cast<float>(replay_speed_exponent_));
} }
void SceneV1AppMode::PauseReplay() {
replay_paused_ = true;
}
void SceneV1AppMode::ResumeReplay() {
replay_paused_ = false;
}
void SceneV1AppMode::SetDebugSpeedExponent(int val) { void SceneV1AppMode::SetDebugSpeedExponent(int val) {
debug_speed_exponent_ = val; debug_speed_exponent_ = val;
debug_speed_mult_ = powf(2.0f, static_cast<float>(debug_speed_exponent_)); debug_speed_mult_ = powf(2.0f, static_cast<float>(debug_speed_exponent_));

View File

@ -96,11 +96,14 @@ class SceneV1AppMode : public base::AppMode {
auto debug_speed_mult() const -> float { return debug_speed_mult_; } auto debug_speed_mult() const -> float { return debug_speed_mult_; }
auto replay_speed_exponent() const -> int { return replay_speed_exponent_; } auto replay_speed_exponent() const -> int { return replay_speed_exponent_; }
auto replay_speed_mult() const -> float { return replay_speed_mult_; } auto replay_speed_mult() const -> float { return replay_speed_mult_; }
auto is_replay_paused() const -> bool { return replay_paused_; }
void OnScreenSizeChange() override; void OnScreenSizeChange() override;
auto kick_idle_players() const -> bool { return kick_idle_players_; } auto kick_idle_players() const -> bool { return kick_idle_players_; }
void LanguageChanged() override; void LanguageChanged() override;
void SetDebugSpeedExponent(int val); void SetDebugSpeedExponent(int val);
void SetReplaySpeedExponent(int val); void SetReplaySpeedExponent(int val);
void PauseReplay();
void ResumeReplay();
void set_admin_public_ids(const std::set<std::string>& ids) { void set_admin_public_ids(const std::set<std::string>& ids) {
admin_public_ids_ = ids; admin_public_ids_ = ids;
} }
@ -223,6 +226,7 @@ class SceneV1AppMode : public base::AppMode {
bool game_roster_dirty_{}; bool game_roster_dirty_{};
bool kick_vote_in_progress_{}; bool kick_vote_in_progress_{};
bool kick_voting_enabled_{true}; bool kick_voting_enabled_{true};
bool replay_paused_{false};
cJSON* game_roster_{}; cJSON* game_roster_{};
millisecs_t last_game_roster_send_time_{}; millisecs_t last_game_roster_send_time_{};