mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-26 08:27:51 -05:00
input_common/tas: Base playback & recording system
The base playback system supports up to 8 controllers (specified by `PLAYER_NUMBER` in `tas_input.h`), which all change their inputs simulataneously when `TAS::UpdateThread` is called. The recording system uses the controller debugger to read the state of the first controller and forwards that data to the TASing system for recording. Currently, this process sadly is not frame-perfect and pixel-accurate. Co-authored-by: Naii-the-Baf <sfabian200@gmail.com> Co-authored-by: Narr-the-Reg <juangerman-13@hotmail.com>
This commit is contained in:
@ -6,10 +6,13 @@
|
||||
#include <QLayout>
|
||||
#include <QString>
|
||||
#include "common/settings.h"
|
||||
#include "input_common/main.h"
|
||||
#include "input_common/tas/tas_input.h"
|
||||
#include "yuzu/configuration/configure_input_player_widget.h"
|
||||
#include "yuzu/debugger/controller.h"
|
||||
|
||||
ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
|
||||
ControllerDialog::ControllerDialog(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
|
||||
: QWidget(parent, Qt::Dialog), input_subsystem{input_subsystem_} {
|
||||
setObjectName(QStringLiteral("Controller"));
|
||||
setWindowTitle(tr("Controller P1"));
|
||||
resize(500, 350);
|
||||
@ -38,6 +41,9 @@ void ControllerDialog::refreshConfiguration() {
|
||||
constexpr std::size_t player = 0;
|
||||
widget->SetPlayerInputRaw(player, players[player].buttons, players[player].analogs);
|
||||
widget->SetControllerType(players[player].controller_type);
|
||||
ControllerCallback callback{[this](ControllerInput input) { InputController(input); }};
|
||||
widget->SetCallBack(callback);
|
||||
widget->repaint();
|
||||
widget->SetConnectedStatus(players[player].connected);
|
||||
}
|
||||
|
||||
@ -67,3 +73,17 @@ void ControllerDialog::hideEvent(QHideEvent* ev) {
|
||||
widget->SetConnectedStatus(false);
|
||||
QWidget::hideEvent(ev);
|
||||
}
|
||||
|
||||
void ControllerDialog::RefreshTasFile() {
|
||||
input_subsystem->GetTas()->RefreshTasFile();
|
||||
}
|
||||
|
||||
void ControllerDialog::InputController(ControllerInput input) {
|
||||
u32 buttons = 0;
|
||||
int index = 0;
|
||||
for (bool btn : input.button_values) {
|
||||
buttons += (btn ? 1 : 0) << index;
|
||||
index++;
|
||||
}
|
||||
input_subsystem->GetTas()->RecordInput(buttons, input.axis_values);
|
||||
}
|
@ -4,18 +4,36 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QWidget>
|
||||
#include "common/settings.h"
|
||||
|
||||
class QAction;
|
||||
class QHideEvent;
|
||||
class QShowEvent;
|
||||
class PlayerControlPreview;
|
||||
|
||||
namespace InputCommon {
|
||||
class InputSubsystem;
|
||||
}
|
||||
|
||||
struct ControllerInput {
|
||||
std::array<std::pair<float, float>, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{};
|
||||
std::array<bool, Settings::NativeButton::NumButtons> button_values{};
|
||||
bool changed{};
|
||||
};
|
||||
|
||||
struct ControllerCallback {
|
||||
std::function<void(ControllerInput)> input;
|
||||
std::function<void()> update;
|
||||
};
|
||||
|
||||
class ControllerDialog : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ControllerDialog(QWidget* parent = nullptr);
|
||||
explicit ControllerDialog(QWidget* parent = nullptr,
|
||||
InputCommon::InputSubsystem* input_subsystem_ = nullptr);
|
||||
|
||||
/// Returns a QAction that can be used to toggle visibility of this dialog.
|
||||
QAction* toggleViewAction();
|
||||
@ -26,6 +44,10 @@ protected:
|
||||
void hideEvent(QHideEvent* ev) override;
|
||||
|
||||
private:
|
||||
void RefreshTasFile();
|
||||
void InputController(ControllerInput input);
|
||||
QAction* toggle_view_action = nullptr;
|
||||
QFileSystemWatcher* watcher = nullptr;
|
||||
PlayerControlPreview* widget;
|
||||
InputCommon::InputSubsystem* input_subsystem;
|
||||
};
|
||||
|
Reference in New Issue
Block a user