mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-15 03:28:49 -07:00
Refactor replay code in TabGame to replayManager (#6026)
* Refactor replay code to replayManager * Lint. * Refresh shortcuts. Took 13 minutes --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de> Co-authored-by: Zach H <zahalpern+github@gmail.com>
This commit is contained in:
parent
70b4843bc4
commit
b9f16e8cce
5 changed files with 227 additions and 159 deletions
|
|
@ -17,6 +17,7 @@ set(cockatrice_SOURCES
|
||||||
src/client/network/sets_model.cpp
|
src/client/network/sets_model.cpp
|
||||||
src/client/network/spoiler_background_updater.cpp
|
src/client/network/spoiler_background_updater.cpp
|
||||||
src/client/network/parsers/deck_link_to_api_transformer.cpp
|
src/client/network/parsers/deck_link_to_api_transformer.cpp
|
||||||
|
src/client/replay_manager.cpp
|
||||||
src/client/sound_engine.cpp
|
src/client/sound_engine.cpp
|
||||||
src/client/tabs/abstract_tab_deck_editor.cpp
|
src/client/tabs/abstract_tab_deck_editor.cpp
|
||||||
src/client/tabs/api/edhrec/tab_edhrec.cpp
|
src/client/tabs/api/edhrec/tab_edhrec.cpp
|
||||||
|
|
|
||||||
149
cockatrice/src/client/replay_manager.cpp
Normal file
149
cockatrice/src/client/replay_manager.cpp
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
#include "replay_manager.h"
|
||||||
|
|
||||||
|
#include "tabs/tab_game.h"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
|
ReplayManager::ReplayManager(TabGame *parent, GameReplay *_replay)
|
||||||
|
: QWidget(parent), game(parent), replay(_replay), replayPlayButton(nullptr), replayFastForwardButton(nullptr),
|
||||||
|
aReplaySkipForward(nullptr), aReplaySkipBackward(nullptr), aReplaySkipForwardBig(nullptr),
|
||||||
|
aReplaySkipBackwardBig(nullptr)
|
||||||
|
{
|
||||||
|
if (replay) {
|
||||||
|
game->loadReplay(replay);
|
||||||
|
|
||||||
|
// Create list: event number -> time [ms]
|
||||||
|
// Distribute simultaneous events evenly across 1 second.
|
||||||
|
unsigned int lastEventTimestamp = 0;
|
||||||
|
const int eventCount = replay->event_list_size();
|
||||||
|
for (int i = 0; i < eventCount; ++i) {
|
||||||
|
int j = i + 1;
|
||||||
|
while ((j < eventCount) && (replay->event_list(j).seconds_elapsed() == lastEventTimestamp))
|
||||||
|
++j;
|
||||||
|
|
||||||
|
const int numberEventsThisSecond = j - i;
|
||||||
|
for (int k = 0; k < numberEventsThisSecond; ++k)
|
||||||
|
replayTimeline.append(replay->event_list(i + k).seconds_elapsed() * 1000 +
|
||||||
|
(int)((qreal)k / (qreal)numberEventsThisSecond * 1000));
|
||||||
|
|
||||||
|
if (j < eventCount)
|
||||||
|
lastEventTimestamp = replay->event_list(j).seconds_elapsed();
|
||||||
|
i += numberEventsThisSecond - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeline widget
|
||||||
|
timelineWidget = new ReplayTimelineWidget;
|
||||||
|
timelineWidget->setTimeline(replayTimeline);
|
||||||
|
connect(timelineWidget, &ReplayTimelineWidget::processNextEvent, this, &ReplayManager::replayNextEvent);
|
||||||
|
connect(timelineWidget, &ReplayTimelineWidget::replayFinished, this, &ReplayManager::replayFinished);
|
||||||
|
connect(timelineWidget, &ReplayTimelineWidget::rewound, this, &ReplayManager::replayRewind);
|
||||||
|
|
||||||
|
// timeline skip shortcuts
|
||||||
|
aReplaySkipForward = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipForward);
|
||||||
|
connect(aReplaySkipForward, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||||
|
|
||||||
|
aReplaySkipBackward = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipBackward);
|
||||||
|
connect(aReplaySkipBackward, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||||
|
|
||||||
|
aReplaySkipForwardBig = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipForwardBig);
|
||||||
|
connect(aReplaySkipForwardBig, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||||
|
|
||||||
|
aReplaySkipBackwardBig = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipBackwardBig);
|
||||||
|
connect(aReplaySkipBackwardBig, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
replayPlayButton = new QToolButton;
|
||||||
|
replayPlayButton->setIconSize(QSize(32, 32));
|
||||||
|
QIcon playButtonIcon = QIcon();
|
||||||
|
playButtonIcon.addPixmap(QPixmap("theme:replay/start"), QIcon::Normal, QIcon::Off);
|
||||||
|
playButtonIcon.addPixmap(QPixmap("theme:replay/pause"), QIcon::Normal, QIcon::On);
|
||||||
|
replayPlayButton->setIcon(playButtonIcon);
|
||||||
|
replayPlayButton->setCheckable(true);
|
||||||
|
connect(replayPlayButton, &QToolButton::toggled, this, &ReplayManager::replayPlayButtonToggled);
|
||||||
|
|
||||||
|
replayFastForwardButton = new QToolButton;
|
||||||
|
replayFastForwardButton->setIconSize(QSize(32, 32));
|
||||||
|
replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward"));
|
||||||
|
replayFastForwardButton->setCheckable(true);
|
||||||
|
connect(replayFastForwardButton, &QToolButton::toggled, this, &ReplayManager::replayFastForwardButtonToggled);
|
||||||
|
|
||||||
|
// putting everything together
|
||||||
|
auto replayControlLayout = new QHBoxLayout;
|
||||||
|
replayControlLayout->addWidget(timelineWidget, 10);
|
||||||
|
replayControlLayout->addWidget(replayPlayButton);
|
||||||
|
replayControlLayout->addWidget(replayFastForwardButton);
|
||||||
|
|
||||||
|
setObjectName("replayControlWidget");
|
||||||
|
setLayout(replayControlLayout);
|
||||||
|
|
||||||
|
connect(this, &ReplayManager::requestChatAndPhaseReset, game, &TabGame::resetChatAndPhase);
|
||||||
|
|
||||||
|
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
|
||||||
|
&ReplayManager::refreshShortcuts);
|
||||||
|
refreshShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayManager::replayNextEvent(Player::EventProcessingOptions options)
|
||||||
|
{
|
||||||
|
game->processGameEventContainer(replay->event_list(timelineWidget->getCurrentEvent()), nullptr, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayManager::replayFinished()
|
||||||
|
{
|
||||||
|
replayPlayButton->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayManager::replayPlayButtonToggled(bool checked)
|
||||||
|
{
|
||||||
|
if (checked) { // start replay
|
||||||
|
timelineWidget->startReplay();
|
||||||
|
} else { // pause replay
|
||||||
|
timelineWidget->stopReplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayManager::replayFastForwardButtonToggled(bool checked)
|
||||||
|
{
|
||||||
|
timelineWidget->setTimeScaleFactor(checked ? ReplayTimelineWidget::FAST_FORWARD_SCALE_FACTOR : 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles everything that needs to be reset when doing a replay rewind.
|
||||||
|
*/
|
||||||
|
void ReplayManager::replayRewind()
|
||||||
|
{
|
||||||
|
emit requestChatAndPhaseReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayManager::refreshShortcuts()
|
||||||
|
{
|
||||||
|
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
|
||||||
|
if (aReplaySkipForward) {
|
||||||
|
aReplaySkipForward->setShortcuts(shortcuts.getShortcut("Replays/aSkipForward"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipBackward) {
|
||||||
|
aReplaySkipBackward->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackward"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipForwardBig) {
|
||||||
|
aReplaySkipForwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipForwardBig"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipBackwardBig) {
|
||||||
|
aReplaySkipBackwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackwardBig"));
|
||||||
|
}
|
||||||
|
if (replayPlayButton) {
|
||||||
|
replayPlayButton->setShortcut(shortcuts.getSingleShortcut("Replays/playButton"));
|
||||||
|
}
|
||||||
|
if (replayFastForwardButton) {
|
||||||
|
replayFastForwardButton->setShortcut(shortcuts.getSingleShortcut("Replays/fastForwardButton"));
|
||||||
|
}
|
||||||
|
}
|
||||||
37
cockatrice/src/client/replay_manager.h
Normal file
37
cockatrice/src/client/replay_manager.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef REPLAY_MANAGER_H
|
||||||
|
#define REPLAY_MANAGER_H
|
||||||
|
#include "network/replay_timeline_widget.h"
|
||||||
|
#include "pb/game_replay.pb.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class ReplayManager : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReplayManager(TabGame *parent, GameReplay *replay);
|
||||||
|
TabGame *game;
|
||||||
|
GameReplay *replay;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void requestChatAndPhaseReset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Replay related members
|
||||||
|
int currentReplayStep = 0;
|
||||||
|
QList<int> replayTimeline;
|
||||||
|
ReplayTimelineWidget *timelineWidget;
|
||||||
|
QToolButton *replayPlayButton, *replayFastForwardButton;
|
||||||
|
QAction *aReplaySkipForward, *aReplaySkipBackward, *aReplaySkipForwardBig, *aReplaySkipBackwardBig;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void replayNextEvent(Player::EventProcessingOptions options);
|
||||||
|
void replayFinished();
|
||||||
|
void replayPlayButtonToggled(bool checked);
|
||||||
|
void replayFastForwardButtonToggled(bool checked);
|
||||||
|
void replayRewind();
|
||||||
|
void refreshShortcuts();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REPLAY_MANAGER_H
|
||||||
|
|
@ -69,38 +69,16 @@
|
||||||
TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
||||||
: Tab(_tabSupervisor), secondsElapsed(0), hostId(-1), localPlayerId(-1),
|
: Tab(_tabSupervisor), secondsElapsed(0), hostId(-1), localPlayerId(-1),
|
||||||
isLocalGame(_tabSupervisor->getIsLocalGame()), spectator(true), judge(false), gameStateKnown(false),
|
isLocalGame(_tabSupervisor->getIsLocalGame()), spectator(true), judge(false), gameStateKnown(false),
|
||||||
resuming(false), currentPhase(-1), activeCard(nullptr), gameClosed(false), replay(_replay), currentReplayStep(0),
|
resuming(false), currentPhase(-1), activeCard(nullptr), gameClosed(false), sayLabel(nullptr), sayEdit(nullptr)
|
||||||
sayLabel(nullptr), sayEdit(nullptr)
|
|
||||||
{
|
{
|
||||||
// THIS CTOR IS USED ON REPLAY
|
// THIS CTOR IS USED ON REPLAY
|
||||||
gameInfo.CopyFrom(replay->game_info());
|
|
||||||
gameInfo.set_spectators_omniscient(true);
|
|
||||||
|
|
||||||
// Create list: event number -> time [ms]
|
|
||||||
// Distribute simultaneous events evenly across 1 second.
|
|
||||||
unsigned int lastEventTimestamp = 0;
|
|
||||||
const int eventCount = replay->event_list_size();
|
|
||||||
for (int i = 0; i < eventCount; ++i) {
|
|
||||||
int j = i + 1;
|
|
||||||
while ((j < eventCount) && (replay->event_list(j).seconds_elapsed() == lastEventTimestamp))
|
|
||||||
++j;
|
|
||||||
|
|
||||||
const int numberEventsThisSecond = j - i;
|
|
||||||
for (int k = 0; k < numberEventsThisSecond; ++k)
|
|
||||||
replayTimeline.append(replay->event_list(i + k).seconds_elapsed() * 1000 +
|
|
||||||
(int)((qreal)k / (qreal)numberEventsThisSecond * 1000));
|
|
||||||
|
|
||||||
if (j < eventCount)
|
|
||||||
lastEventTimestamp = replay->event_list(j).seconds_elapsed();
|
|
||||||
i += numberEventsThisSecond - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
createCardInfoDock(true);
|
createCardInfoDock(true);
|
||||||
createPlayerListDock(true);
|
createPlayerListDock(true);
|
||||||
createMessageDock(true);
|
createMessageDock(true);
|
||||||
createPlayAreaWidget(true);
|
createPlayAreaWidget(true);
|
||||||
createDeckViewContainerWidget(true);
|
createDeckViewContainerWidget(true);
|
||||||
createReplayDock();
|
createReplayDock(_replay);
|
||||||
|
|
||||||
addDockWidget(Qt::RightDockWidgetArea, cardInfoDock);
|
addDockWidget(Qt::RightDockWidgetArea, cardInfoDock);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, playerListDock);
|
addDockWidget(Qt::RightDockWidgetArea, playerListDock);
|
||||||
|
|
@ -131,9 +109,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
|
||||||
gameInfo(event.game_info()), roomGameTypes(_roomGameTypes), hostId(event.host_id()),
|
gameInfo(event.game_info()), roomGameTypes(_roomGameTypes), hostId(event.host_id()),
|
||||||
localPlayerId(event.player_id()), isLocalGame(_tabSupervisor->getIsLocalGame()), spectator(event.spectator()),
|
localPlayerId(event.player_id()), isLocalGame(_tabSupervisor->getIsLocalGame()), spectator(event.spectator()),
|
||||||
judge(event.judge()), gameStateKnown(false), resuming(event.resuming()), currentPhase(-1), activeCard(nullptr),
|
judge(event.judge()), gameStateKnown(false), resuming(event.resuming()), currentPhase(-1), activeCard(nullptr),
|
||||||
gameClosed(false), replay(nullptr), replayPlayButton(nullptr), replayFastForwardButton(nullptr),
|
gameClosed(false)
|
||||||
aReplaySkipForward(nullptr), aReplaySkipBackward(nullptr), aReplaySkipForwardBig(nullptr),
|
|
||||||
aReplaySkipBackwardBig(nullptr), replayDock(nullptr)
|
|
||||||
{
|
{
|
||||||
// THIS CTOR IS USED ON GAMES
|
// THIS CTOR IS USED ON GAMES
|
||||||
gameInfo.set_started(false);
|
gameInfo.set_started(false);
|
||||||
|
|
@ -143,10 +119,12 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
|
||||||
createMessageDock();
|
createMessageDock();
|
||||||
createPlayAreaWidget();
|
createPlayAreaWidget();
|
||||||
createDeckViewContainerWidget();
|
createDeckViewContainerWidget();
|
||||||
|
createReplayDock(nullptr);
|
||||||
|
|
||||||
addDockWidget(Qt::RightDockWidgetArea, cardInfoDock);
|
addDockWidget(Qt::RightDockWidgetArea, cardInfoDock);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, playerListDock);
|
addDockWidget(Qt::RightDockWidgetArea, playerListDock);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, messageLayoutDock);
|
addDockWidget(Qt::RightDockWidgetArea, messageLayoutDock);
|
||||||
|
replayDock->setHidden(true);
|
||||||
|
|
||||||
mainWidget = new QStackedWidget(this);
|
mainWidget = new QStackedWidget(this);
|
||||||
mainWidget->addWidget(deckViewContainerWidget);
|
mainWidget->addWidget(deckViewContainerWidget);
|
||||||
|
|
@ -168,6 +146,12 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
|
||||||
QTimer::singleShot(0, this, &TabGame::loadLayout);
|
QTimer::singleShot(0, this, &TabGame::loadLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabGame::loadReplay(GameReplay *replay)
|
||||||
|
{
|
||||||
|
gameInfo.CopyFrom(replay->game_info());
|
||||||
|
gameInfo.set_spectators_omniscient(true);
|
||||||
|
}
|
||||||
|
|
||||||
void TabGame::addMentionTag(const QString &value)
|
void TabGame::addMentionTag(const QString &value)
|
||||||
{
|
{
|
||||||
sayEdit->insert(value + " ");
|
sayEdit->insert(value + " ");
|
||||||
|
|
@ -180,6 +164,15 @@ void TabGame::linkCardToChat(const QString &cardName)
|
||||||
sayEdit->setFocus();
|
sayEdit->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabGame::resetChatAndPhase()
|
||||||
|
{
|
||||||
|
// reset chat log
|
||||||
|
messageLog->clearChat();
|
||||||
|
|
||||||
|
// reset phase markers
|
||||||
|
setActivePhase(-1);
|
||||||
|
}
|
||||||
|
|
||||||
void TabGame::emitUserEvent()
|
void TabGame::emitUserEvent()
|
||||||
{
|
{
|
||||||
bool globalEvent = !spectator || SettingsCache::instance().getSpectatorNotificationsEnabled();
|
bool globalEvent = !spectator || SettingsCache::instance().getSpectatorNotificationsEnabled();
|
||||||
|
|
@ -189,12 +182,13 @@ void TabGame::emitUserEvent()
|
||||||
|
|
||||||
TabGame::~TabGame()
|
TabGame::~TabGame()
|
||||||
{
|
{
|
||||||
delete replay;
|
delete replayManager->replay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::updatePlayerListDockTitle()
|
void TabGame::updatePlayerListDockTitle()
|
||||||
{
|
{
|
||||||
QString tabText = " | " + (replay ? tr("Replay") : tr("Game")) + " #" + QString::number(gameInfo.game_id());
|
QString tabText =
|
||||||
|
" | " + (replayManager->replay ? tr("Replay") : tr("Game")) + " #" + QString::number(gameInfo.game_id());
|
||||||
QString userCountInfo = QString(" %1/%2").arg(players.size()).arg(gameInfo.max_players());
|
QString userCountInfo = QString(" %1/%2").arg(players.size()).arg(gameInfo.max_players());
|
||||||
playerListDock->setWindowTitle(tr("Player List") + userCountInfo +
|
playerListDock->setWindowTitle(tr("Player List") + userCountInfo +
|
||||||
(playerListDock->isWindow() ? tabText : QString()));
|
(playerListDock->isWindow() ? tabText : QString()));
|
||||||
|
|
@ -208,7 +202,8 @@ bool TabGame::isMainPlayerConceded() const
|
||||||
|
|
||||||
void TabGame::retranslateUi()
|
void TabGame::retranslateUi()
|
||||||
{
|
{
|
||||||
QString tabText = " | " + (replay ? tr("Replay") : tr("Game")) + " #" + QString::number(gameInfo.game_id());
|
QString tabText =
|
||||||
|
" | " + (replayManager->replay ? tr("Replay") : tr("Game")) + " #" + QString::number(gameInfo.game_id());
|
||||||
|
|
||||||
updatePlayerListDockTitle();
|
updatePlayerListDockTitle();
|
||||||
cardInfoDock->setWindowTitle(tr("Card Info") + (cardInfoDock->isWindow() ? tabText : QString()));
|
cardInfoDock->setWindowTitle(tr("Card Info") + (cardInfoDock->isWindow() ? tabText : QString()));
|
||||||
|
|
@ -379,24 +374,6 @@ void TabGame::refreshShortcuts()
|
||||||
if (aFocusChat) {
|
if (aFocusChat) {
|
||||||
aFocusChat->setShortcuts(shortcuts.getShortcut("Player/aFocusChat"));
|
aFocusChat->setShortcuts(shortcuts.getShortcut("Player/aFocusChat"));
|
||||||
}
|
}
|
||||||
if (aReplaySkipForward) {
|
|
||||||
aReplaySkipForward->setShortcuts(shortcuts.getShortcut("Replays/aSkipForward"));
|
|
||||||
}
|
|
||||||
if (aReplaySkipBackward) {
|
|
||||||
aReplaySkipBackward->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackward"));
|
|
||||||
}
|
|
||||||
if (aReplaySkipForwardBig) {
|
|
||||||
aReplaySkipForwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipForwardBig"));
|
|
||||||
}
|
|
||||||
if (aReplaySkipBackwardBig) {
|
|
||||||
aReplaySkipBackwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackwardBig"));
|
|
||||||
}
|
|
||||||
if (replayPlayButton) {
|
|
||||||
replayPlayButton->setShortcut(shortcuts.getSingleShortcut("Replays/playButton"));
|
|
||||||
}
|
|
||||||
if (replayFastForwardButton) {
|
|
||||||
replayFastForwardButton->setShortcut(shortcuts.getSingleShortcut("Replays/fastForwardButton"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::closeRequest(bool forced)
|
void TabGame::closeRequest(bool forced)
|
||||||
|
|
@ -410,42 +387,6 @@ void TabGame::closeRequest(bool forced)
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::replayNextEvent(Player::EventProcessingOptions options)
|
|
||||||
{
|
|
||||||
processGameEventContainer(replay->event_list(timelineWidget->getCurrentEvent()), nullptr, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabGame::replayFinished()
|
|
||||||
{
|
|
||||||
replayPlayButton->setChecked(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabGame::replayPlayButtonToggled(bool checked)
|
|
||||||
{
|
|
||||||
if (checked) { // start replay
|
|
||||||
timelineWidget->startReplay();
|
|
||||||
} else { // pause replay
|
|
||||||
timelineWidget->stopReplay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabGame::replayFastForwardButtonToggled(bool checked)
|
|
||||||
{
|
|
||||||
timelineWidget->setTimeScaleFactor(checked ? ReplayTimelineWidget::FAST_FORWARD_SCALE_FACTOR : 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles everything that needs to be reset when doing a replay rewind.
|
|
||||||
*/
|
|
||||||
void TabGame::replayRewind()
|
|
||||||
{
|
|
||||||
// reset chat log
|
|
||||||
messageLog->clearChat();
|
|
||||||
|
|
||||||
// reset phase markers
|
|
||||||
setActivePhase(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabGame::incrementGameTime()
|
void TabGame::incrementGameTime()
|
||||||
{
|
{
|
||||||
int seconds = ++secondsElapsed;
|
int seconds = ++secondsElapsed;
|
||||||
|
|
@ -513,7 +454,7 @@ bool TabGame::leaveGame()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!replay)
|
if (!replayManager->replay)
|
||||||
sendGameCommand(Command_LeaveGame());
|
sendGameCommand(Command_LeaveGame());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1231,7 +1172,7 @@ QString TabGame::getTabText() const
|
||||||
QString gameId(QString::number(gameInfo.game_id()));
|
QString gameId(QString::number(gameInfo.game_id()));
|
||||||
|
|
||||||
QString tabText;
|
QString tabText;
|
||||||
if (replay)
|
if (replayManager->replay)
|
||||||
tabText.append(tr("Replay") + " ");
|
tabText.append(tr("Replay") + " ");
|
||||||
if (!gameTypeInfo.isEmpty())
|
if (!gameTypeInfo.isEmpty())
|
||||||
tabText.append(gameTypeInfo + " ");
|
tabText.append(gameTypeInfo + " ");
|
||||||
|
|
@ -1418,7 +1359,7 @@ void TabGame::createViewMenuItems()
|
||||||
void TabGame::loadLayout()
|
void TabGame::loadLayout()
|
||||||
{
|
{
|
||||||
LayoutsSettings &layouts = SettingsCache::instance().layouts();
|
LayoutsSettings &layouts = SettingsCache::instance().layouts();
|
||||||
if (replayDock) {
|
if (replayManager->replay) {
|
||||||
restoreGeometry(layouts.getReplayPlayAreaGeometry());
|
restoreGeometry(layouts.getReplayPlayAreaGeometry());
|
||||||
restoreState(layouts.getReplayPlayAreaLayoutState());
|
restoreState(layouts.getReplayPlayAreaLayoutState());
|
||||||
|
|
||||||
|
|
@ -1454,7 +1395,7 @@ void TabGame::loadLayout()
|
||||||
aMessageLayoutDockFloating->setChecked(messageLayoutDock->isFloating());
|
aMessageLayoutDockFloating->setChecked(messageLayoutDock->isFloating());
|
||||||
aPlayerListDockFloating->setChecked(playerListDock->isFloating());
|
aPlayerListDockFloating->setChecked(playerListDock->isFloating());
|
||||||
|
|
||||||
if (replayDock) {
|
if (replayManager->replay) {
|
||||||
aReplayDockVisible->setChecked(replayDock->isVisible());
|
aReplayDockVisible->setChecked(replayDock->isVisible());
|
||||||
aReplayDockFloating->setEnabled(aReplayDockVisible->isChecked());
|
aReplayDockFloating->setEnabled(aReplayDockVisible->isChecked());
|
||||||
aReplayDockFloating->setChecked(replayDock->isFloating());
|
aReplayDockFloating->setChecked(replayDock->isFloating());
|
||||||
|
|
@ -1547,67 +1488,15 @@ void TabGame::createPlayAreaWidget(bool bReplay)
|
||||||
gamePlayAreaWidget->setLayout(gamePlayAreaVBox);
|
gamePlayAreaWidget->setLayout(gamePlayAreaVBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::createReplayDock()
|
void TabGame::createReplayDock(GameReplay *replay)
|
||||||
{
|
{
|
||||||
// timeline widget
|
replayManager = new ReplayManager(this, replay);
|
||||||
timelineWidget = new ReplayTimelineWidget;
|
|
||||||
timelineWidget->setTimeline(replayTimeline);
|
|
||||||
connect(timelineWidget, &ReplayTimelineWidget::processNextEvent, this, &TabGame::replayNextEvent);
|
|
||||||
connect(timelineWidget, &ReplayTimelineWidget::replayFinished, this, &TabGame::replayFinished);
|
|
||||||
connect(timelineWidget, &ReplayTimelineWidget::rewound, this, &TabGame::replayRewind);
|
|
||||||
|
|
||||||
// timeline skip shortcuts
|
|
||||||
aReplaySkipForward = new QAction(timelineWidget);
|
|
||||||
timelineWidget->addAction(aReplaySkipForward);
|
|
||||||
connect(aReplaySkipForward, &QAction::triggered, this,
|
|
||||||
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::SMALL_SKIP_MS); });
|
|
||||||
|
|
||||||
aReplaySkipBackward = new QAction(timelineWidget);
|
|
||||||
timelineWidget->addAction(aReplaySkipBackward);
|
|
||||||
connect(aReplaySkipBackward, &QAction::triggered, this,
|
|
||||||
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::SMALL_SKIP_MS); });
|
|
||||||
|
|
||||||
aReplaySkipForwardBig = new QAction(timelineWidget);
|
|
||||||
timelineWidget->addAction(aReplaySkipForwardBig);
|
|
||||||
connect(aReplaySkipForwardBig, &QAction::triggered, this,
|
|
||||||
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::BIG_SKIP_MS); });
|
|
||||||
|
|
||||||
aReplaySkipBackwardBig = new QAction(timelineWidget);
|
|
||||||
timelineWidget->addAction(aReplaySkipBackwardBig);
|
|
||||||
connect(aReplaySkipBackwardBig, &QAction::triggered, this,
|
|
||||||
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::BIG_SKIP_MS); });
|
|
||||||
|
|
||||||
// buttons
|
|
||||||
replayPlayButton = new QToolButton;
|
|
||||||
replayPlayButton->setIconSize(QSize(32, 32));
|
|
||||||
QIcon playButtonIcon = QIcon();
|
|
||||||
playButtonIcon.addPixmap(QPixmap("theme:replay/start"), QIcon::Normal, QIcon::Off);
|
|
||||||
playButtonIcon.addPixmap(QPixmap("theme:replay/pause"), QIcon::Normal, QIcon::On);
|
|
||||||
replayPlayButton->setIcon(playButtonIcon);
|
|
||||||
replayPlayButton->setCheckable(true);
|
|
||||||
connect(replayPlayButton, &QToolButton::toggled, this, &TabGame::replayPlayButtonToggled);
|
|
||||||
|
|
||||||
replayFastForwardButton = new QToolButton;
|
|
||||||
replayFastForwardButton->setIconSize(QSize(32, 32));
|
|
||||||
replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward"));
|
|
||||||
replayFastForwardButton->setCheckable(true);
|
|
||||||
connect(replayFastForwardButton, &QToolButton::toggled, this, &TabGame::replayFastForwardButtonToggled);
|
|
||||||
|
|
||||||
// putting everything together
|
|
||||||
auto replayControlLayout = new QHBoxLayout;
|
|
||||||
replayControlLayout->addWidget(timelineWidget, 10);
|
|
||||||
replayControlLayout->addWidget(replayPlayButton);
|
|
||||||
replayControlLayout->addWidget(replayFastForwardButton);
|
|
||||||
|
|
||||||
auto replayControlWidget = new QWidget();
|
|
||||||
replayControlWidget->setObjectName("replayControlWidget");
|
|
||||||
replayControlWidget->setLayout(replayControlLayout);
|
|
||||||
|
|
||||||
replayDock = new QDockWidget(this);
|
replayDock = new QDockWidget(this);
|
||||||
replayDock->setObjectName("replayDock");
|
replayDock->setObjectName("replayDock");
|
||||||
replayDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
replayDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
||||||
QDockWidget::DockWidgetMovable);
|
QDockWidget::DockWidgetMovable);
|
||||||
replayDock->setWidget(replayControlWidget);
|
replayDock->setWidget(replayManager);
|
||||||
replayDock->setFloating(false);
|
replayDock->setFloating(false);
|
||||||
|
|
||||||
replayDock->installEventFilter(this);
|
replayDock->installEventFilter(this);
|
||||||
|
|
@ -1765,7 +1654,7 @@ void TabGame::createMessageDock(bool bReplay)
|
||||||
void TabGame::hideEvent(QHideEvent *event)
|
void TabGame::hideEvent(QHideEvent *event)
|
||||||
{
|
{
|
||||||
LayoutsSettings &layouts = SettingsCache::instance().layouts();
|
LayoutsSettings &layouts = SettingsCache::instance().layouts();
|
||||||
if (replay) {
|
if (replayManager->replay) {
|
||||||
layouts.setReplayPlayAreaState(saveState());
|
layouts.setReplayPlayAreaState(saveState());
|
||||||
layouts.setReplayPlayAreaGeometry(saveGeometry());
|
layouts.setReplayPlayAreaGeometry(saveGeometry());
|
||||||
layouts.setReplayCardInfoSize(cardInfoDock->size());
|
layouts.setReplayCardInfoSize(cardInfoDock->size());
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../../client/tearoff_menu.h"
|
#include "../../client/tearoff_menu.h"
|
||||||
#include "../../game/player/player.h"
|
#include "../../game/player/player.h"
|
||||||
|
#include "../replay_manager.h"
|
||||||
#include "../ui/widgets/visual_deck_storage/visual_deck_storage_widget.h"
|
#include "../ui/widgets/visual_deck_storage/visual_deck_storage_widget.h"
|
||||||
#include "pb/event_leave.pb.h"
|
#include "pb/event_leave.pb.h"
|
||||||
#include "pb/serverinfo_game.pb.h"
|
#include "pb/serverinfo_game.pb.h"
|
||||||
|
|
@ -20,6 +21,7 @@ class AbstractClient;
|
||||||
class CardDatabase;
|
class CardDatabase;
|
||||||
class GameView;
|
class GameView;
|
||||||
class GameScene;
|
class GameScene;
|
||||||
|
class ReplayManager;
|
||||||
class CardInfoFrameWidget;
|
class CardInfoFrameWidget;
|
||||||
class MessageLogWidget;
|
class MessageLogWidget;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
@ -88,19 +90,12 @@ private:
|
||||||
int activePlayer;
|
int activePlayer;
|
||||||
CardItem *activeCard;
|
CardItem *activeCard;
|
||||||
bool gameClosed;
|
bool gameClosed;
|
||||||
|
ReplayManager *replayManager;
|
||||||
QStringList gameTypes;
|
QStringList gameTypes;
|
||||||
QCompleter *completer;
|
QCompleter *completer;
|
||||||
QStringList autocompleteUserList;
|
QStringList autocompleteUserList;
|
||||||
QStackedWidget *mainWidget;
|
QStackedWidget *mainWidget;
|
||||||
|
|
||||||
// Replay related members
|
|
||||||
GameReplay *replay;
|
|
||||||
int currentReplayStep;
|
|
||||||
QList<int> replayTimeline;
|
|
||||||
ReplayTimelineWidget *timelineWidget;
|
|
||||||
QToolButton *replayPlayButton, *replayFastForwardButton;
|
|
||||||
QAction *aReplaySkipForward, *aReplaySkipBackward, *aReplaySkipForwardBig, *aReplaySkipBackwardBig;
|
|
||||||
|
|
||||||
CardInfoFrameWidget *cardInfoFrameWidget;
|
CardInfoFrameWidget *cardInfoFrameWidget;
|
||||||
PlayerListWidget *playerListWidget;
|
PlayerListWidget *playerListWidget;
|
||||||
QLabel *timeElapsedLabel;
|
QLabel *timeElapsedLabel;
|
||||||
|
|
@ -160,7 +155,7 @@ private:
|
||||||
void createMessageDock(bool bReplay = false);
|
void createMessageDock(bool bReplay = false);
|
||||||
void createPlayAreaWidget(bool bReplay = false);
|
void createPlayAreaWidget(bool bReplay = false);
|
||||||
void createDeckViewContainerWidget(bool bReplay = false);
|
void createDeckViewContainerWidget(bool bReplay = false);
|
||||||
void createReplayDock();
|
void createReplayDock(GameReplay *replay);
|
||||||
QString getLeaveReason(Event_Leave::LeaveReason reason);
|
QString getLeaveReason(Event_Leave::LeaveReason reason);
|
||||||
signals:
|
signals:
|
||||||
void gameClosing(TabGame *tab);
|
void gameClosing(TabGame *tab);
|
||||||
|
|
@ -171,13 +166,8 @@ signals:
|
||||||
void openMessageDialog(const QString &userName, bool focus);
|
void openMessageDialog(const QString &userName, bool focus);
|
||||||
void openDeckEditor(const DeckLoader *deck);
|
void openDeckEditor(const DeckLoader *deck);
|
||||||
void notIdle();
|
void notIdle();
|
||||||
private slots:
|
|
||||||
void replayNextEvent(Player::EventProcessingOptions options);
|
|
||||||
void replayFinished();
|
|
||||||
void replayPlayButtonToggled(bool checked);
|
|
||||||
void replayFastForwardButtonToggled(bool checked);
|
|
||||||
void replayRewind();
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
void incrementGameTime();
|
void incrementGameTime();
|
||||||
void adminLockChanged(bool lock);
|
void adminLockChanged(bool lock);
|
||||||
void newCardAdded(AbstractCardItem *card);
|
void newCardAdded(AbstractCardItem *card);
|
||||||
|
|
@ -217,6 +207,7 @@ public:
|
||||||
QList<AbstractClient *> &_clients,
|
QList<AbstractClient *> &_clients,
|
||||||
const Event_GameJoined &event,
|
const Event_GameJoined &event,
|
||||||
const QMap<int, QString> &_roomGameTypes);
|
const QMap<int, QString> &_roomGameTypes);
|
||||||
|
void loadReplay(GameReplay *replay);
|
||||||
TabGame(TabSupervisor *_tabSupervisor, GameReplay *replay);
|
TabGame(TabSupervisor *_tabSupervisor, GameReplay *replay);
|
||||||
~TabGame() override;
|
~TabGame() override;
|
||||||
void retranslateUi() override;
|
void retranslateUi() override;
|
||||||
|
|
@ -267,6 +258,7 @@ public slots:
|
||||||
void sendGameCommand(PendingCommand *pend, int playerId = -1);
|
void sendGameCommand(PendingCommand *pend, int playerId = -1);
|
||||||
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
|
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
|
||||||
void viewCardInfo(const CardRef &cardRef = {}) const;
|
void viewCardInfo(const CardRef &cardRef = {}) const;
|
||||||
|
void resetChatAndPhase();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue