mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-12 17:14:52 -07:00
[Move refactor] Reparent orphan classes (#6236)
* Move orphaned classes to their correct parent folders. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
parent
1ef07309d6
commit
d9c65d4ae0
143 changed files with 171 additions and 169 deletions
150
cockatrice/src/interface/widgets/replay/replay_manager.cpp
Normal file
150
cockatrice/src/interface/widgets/replay/replay_manager.cpp
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
#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->getGame()->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(EventProcessingOptions options)
|
||||
{
|
||||
game->getGame()->getGameEventHandler()->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"));
|
||||
}
|
||||
}
|
||||
48
cockatrice/src/interface/widgets/replay/replay_manager.h
Normal file
48
cockatrice/src/interface/widgets/replay/replay_manager.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* @file replay_manager.h
|
||||
* @ingroup Core
|
||||
* @ingroup Replay
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef REPLAY_MANAGER_H
|
||||
#define REPLAY_MANAGER_H
|
||||
|
||||
#include "replay_timeline_widget.h"
|
||||
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
||||
|
||||
class TabGame;
|
||||
|
||||
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(EventProcessingOptions options);
|
||||
void replayFinished();
|
||||
void replayPlayButtonToggled(bool checked);
|
||||
void replayFastForwardButtonToggled(bool checked);
|
||||
void replayRewind();
|
||||
void refreshShortcuts();
|
||||
};
|
||||
|
||||
#endif // REPLAY_MANAGER_H
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
#include "replay_timeline_widget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPalette>
|
||||
#include <QTimer>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent)
|
||||
: QWidget(parent), maxBinValue(1), maxTime(1), timeScaleFactor(1.0), currentVisualTime(0), currentProcessedTime(0),
|
||||
currentEvent(0)
|
||||
{
|
||||
replayTimer = new QTimer(this);
|
||||
connect(replayTimer, &QTimer::timeout, this, &ReplayTimelineWidget::replayTimerTimeout);
|
||||
|
||||
rewindBufferingTimer = new QTimer(this);
|
||||
rewindBufferingTimer->setSingleShot(true);
|
||||
connect(rewindBufferingTimer, &QTimer::timeout, this, &ReplayTimelineWidget::processRewind);
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
|
||||
{
|
||||
replayTimeline = _replayTimeline;
|
||||
histogram.clear();
|
||||
int binEndTime = BIN_LENGTH - 1;
|
||||
int binValue = 0;
|
||||
for (int i : replayTimeline) {
|
||||
if (i > binEndTime) {
|
||||
histogram.append(binValue);
|
||||
if (binValue > maxBinValue)
|
||||
maxBinValue = binValue;
|
||||
while (i > binEndTime + BIN_LENGTH) {
|
||||
histogram.append(0);
|
||||
binEndTime += BIN_LENGTH;
|
||||
}
|
||||
binValue = 1;
|
||||
binEndTime += BIN_LENGTH;
|
||||
} else
|
||||
++binValue;
|
||||
}
|
||||
histogram.append(binValue);
|
||||
if (!replayTimeline.isEmpty())
|
||||
maxTime = replayTimeline.last();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.drawRect(0, 0, width() - 1, height() - 1);
|
||||
|
||||
qreal binWidth = (qreal)width() / histogram.size();
|
||||
QPainterPath path;
|
||||
path.moveTo(0, height() - 1);
|
||||
for (int i = 0; i < histogram.size(); ++i)
|
||||
path.lineTo(qRound(i * binWidth), (height() - 1) * (1.0 - (qreal)histogram[i] / maxBinValue));
|
||||
path.lineTo(width() - 1, height() - 1);
|
||||
path.lineTo(0, height() - 1);
|
||||
painter.fillPath(path, Qt::black);
|
||||
|
||||
const QColor barColor = QColor::fromHsv(120, 255, 255, 100);
|
||||
quint64 w = (quint64)(width() - 1) * (quint64)currentVisualTime / maxTime;
|
||||
painter.fillRect(0, 0, static_cast<int>(w), height() - 1, barColor);
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->position().x() / width());
|
||||
#else
|
||||
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->x() / width());
|
||||
#endif
|
||||
// don't buffer rewinds from clicks, since clicks usually don't happen fast enough to require buffering
|
||||
skipToTime(newTime, false);
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::skipToTime(int newTime, bool doRewindBuffering)
|
||||
{
|
||||
// check boundary conditions
|
||||
if (newTime < 0) {
|
||||
newTime = 0;
|
||||
}
|
||||
if (newTime > maxTime) {
|
||||
newTime = maxTime;
|
||||
}
|
||||
|
||||
newTime -= newTime % TIMER_INTERVAL_MS; // Time should always be a multiple of the interval
|
||||
|
||||
const bool isBackwardsSkip = newTime < currentProcessedTime;
|
||||
currentVisualTime = newTime;
|
||||
|
||||
if (isBackwardsSkip) {
|
||||
handleBackwardsSkip(doRewindBuffering);
|
||||
} else {
|
||||
processNewEvents(FORWARD_SKIP);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
/// @param doRewindBuffering When true, if multiple backward skips are made in quick succession, only a single rewind
|
||||
/// is processed at the end. When false, the backwards skip will always cause an immediate rewind
|
||||
void ReplayTimelineWidget::handleBackwardsSkip(bool doRewindBuffering)
|
||||
{
|
||||
if (doRewindBuffering) {
|
||||
// We use a one-shot timer to implement the rewind buffering.
|
||||
// The rewind only happens once the timer runs out.
|
||||
// If another backwards skip happens, the timer will just get reset instead of rewinding.
|
||||
rewindBufferingTimer->stop();
|
||||
rewindBufferingTimer->start(SettingsCache::instance().getRewindBufferingMs());
|
||||
} else {
|
||||
// otherwise, process the rewind immediately
|
||||
processRewind();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::processRewind()
|
||||
{
|
||||
// stop any queued-up rewinds
|
||||
rewindBufferingTimer->stop();
|
||||
|
||||
// process the rewind
|
||||
currentEvent = 0;
|
||||
emit rewound();
|
||||
processNewEvents(BACKWARD_SKIP);
|
||||
}
|
||||
|
||||
QSize ReplayTimelineWidget::sizeHint() const
|
||||
{
|
||||
return {-1, 50};
|
||||
}
|
||||
|
||||
QSize ReplayTimelineWidget::minimumSizeHint() const
|
||||
{
|
||||
return {400, 50};
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::replayTimerTimeout()
|
||||
{
|
||||
currentVisualTime += TIMER_INTERVAL_MS;
|
||||
|
||||
processNewEvents(NORMAL_PLAYBACK);
|
||||
|
||||
if (!(currentVisualTime % 1000))
|
||||
update();
|
||||
}
|
||||
|
||||
/// Processes all unprocessed events up to the current time.
|
||||
void ReplayTimelineWidget::processNewEvents(PlaybackMode playbackMode)
|
||||
{
|
||||
currentProcessedTime = currentVisualTime;
|
||||
|
||||
while ((currentEvent < replayTimeline.size()) && (replayTimeline[currentEvent] < currentProcessedTime)) {
|
||||
EventProcessingOptions options;
|
||||
|
||||
// backwards skip => always skip reveal windows
|
||||
// forwards skip => skip reveal windows that don't happen within a big skip of the target
|
||||
if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS)
|
||||
options |= SKIP_REVEAL_WINDOW;
|
||||
|
||||
// backwards skip => always skip tap animation
|
||||
if (playbackMode == BACKWARD_SKIP)
|
||||
options |= SKIP_TAP_ANIMATION;
|
||||
|
||||
emit processNextEvent(options);
|
||||
++currentEvent;
|
||||
}
|
||||
if (currentEvent == replayTimeline.size()) {
|
||||
emit replayFinished();
|
||||
replayTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::setTimeScaleFactor(qreal _timeScaleFactor)
|
||||
{
|
||||
timeScaleFactor = _timeScaleFactor;
|
||||
replayTimer->setInterval(static_cast<int>(TIMER_INTERVAL_MS / timeScaleFactor));
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::startReplay()
|
||||
{
|
||||
replayTimer->start(static_cast<int>(TIMER_INTERVAL_MS / timeScaleFactor));
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::stopReplay()
|
||||
{
|
||||
replayTimer->stop();
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::skipByAmount(int amount)
|
||||
{
|
||||
skipToTime(currentVisualTime + amount, amount < 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* @file replay_timeline_widget.h
|
||||
* @ingroup Replay
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef REPLAY_TIMELINE_WIDGET
|
||||
#define REPLAY_TIMELINE_WIDGET
|
||||
|
||||
#include "../../../game/player/event_processing_options.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMouseEvent>
|
||||
#include <QWidget>
|
||||
|
||||
class QPaintEvent;
|
||||
class QTimer;
|
||||
|
||||
class ReplayTimelineWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void processNextEvent(EventProcessingOptions options);
|
||||
void replayFinished();
|
||||
void rewound();
|
||||
|
||||
private:
|
||||
enum PlaybackMode
|
||||
{
|
||||
NORMAL_PLAYBACK,
|
||||
FORWARD_SKIP,
|
||||
BACKWARD_SKIP
|
||||
};
|
||||
|
||||
static constexpr int TIMER_INTERVAL_MS = 200;
|
||||
static constexpr int BIN_LENGTH = 5000;
|
||||
|
||||
QTimer *replayTimer;
|
||||
QTimer *rewindBufferingTimer;
|
||||
QList<int> replayTimeline;
|
||||
QList<int> histogram;
|
||||
int maxBinValue, maxTime;
|
||||
qreal timeScaleFactor;
|
||||
int currentVisualTime; // time currently displayed by the timeline
|
||||
int currentProcessedTime; // time that events are currently processed up to. Could differ from visual time due to
|
||||
// rewind buffering
|
||||
int currentEvent;
|
||||
|
||||
void skipToTime(int newTime, bool doRewindBuffering);
|
||||
void handleBackwardsSkip(bool doRewindBuffering);
|
||||
void processRewind();
|
||||
void processNewEvents(PlaybackMode playbackMode);
|
||||
private slots:
|
||||
void replayTimerTimeout();
|
||||
|
||||
public:
|
||||
static constexpr int SMALL_SKIP_MS = 1000;
|
||||
static constexpr int BIG_SKIP_MS = 10000;
|
||||
static constexpr qreal FAST_FORWARD_SCALE_FACTOR = 10.0;
|
||||
|
||||
explicit ReplayTimelineWidget(QWidget *parent = nullptr);
|
||||
void setTimeline(const QList<int> &_replayTimeline);
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
void setTimeScaleFactor(qreal _timeScaleFactor);
|
||||
int getCurrentEvent() const
|
||||
{
|
||||
return currentEvent;
|
||||
}
|
||||
public slots:
|
||||
void startReplay();
|
||||
void stopReplay();
|
||||
void skipByAmount(int amount); // use a negative amount to skip backwards
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue