diff options
| -rw-r--r-- | CMakeLists.txt | 6 | ||||
| -rw-r--r-- | CMakeModules/CopyYuzuQt5Deps.cmake | 7 | ||||
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 71 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.h | 12 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 12 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.h | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_camera.cpp | 126 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_camera.h | 52 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_camera.ui | 170 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_advanced.cpp | 3 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_advanced.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_advanced.ui | 14 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 9 | 
15 files changed, 491 insertions, 4 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f7dcc924..40ca8b149 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,7 +196,7 @@ if(ENABLE_QT)      # Check for system Qt on Linux, fallback to bundled Qt      if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")          if (NOT YUZU_USE_BUNDLED_QT) -            find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus) +            find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus Multimedia)          endif()          if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)              # Check for dependencies, then enable bundled Qt download @@ -300,9 +300,9 @@ if(ENABLE_QT)          set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")      endif()      if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND YUZU_USE_BUNDLED_QT) -        find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent DBus ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH}) +        find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent Multimedia DBus ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})      else() -        find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH}) +        find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent Multimedia ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})      endif()      if (YUZU_USE_QT_WEB_ENGINE)          find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets) diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake index 0c27d51a6..4702a504c 100644 --- a/CMakeModules/CopyYuzuQt5Deps.cmake +++ b/CMakeModules/CopyYuzuQt5Deps.cmake @@ -10,11 +10,13 @@ function(copy_yuzu_Qt5_deps target_dir)      set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")      set(Qt5_PLATFORMTHEMES_DIR "${Qt5_DIR}/../../../plugins/platformthemes/")      set(Qt5_PLATFORMINPUTCONTEXTS_DIR "${Qt5_DIR}/../../../plugins/platforminputcontexts/") +    set(Qt5_MEDIASERVICE_DIR "${Qt5_DIR}/../../../plugins/mediaservice/")      set(Qt5_XCBGLINTEGRATIONS_DIR "${Qt5_DIR}/../../../plugins/xcbglintegrations/")      set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")      set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")      set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")      set(PLATFORMS ${DLL_DEST}plugins/platforms/) +    set(MEDIASERVICE ${DLL_DEST}mediaservice/)      set(STYLES ${DLL_DEST}plugins/styles/)      set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)      if (MSVC) @@ -22,6 +24,7 @@ function(copy_yuzu_Qt5_deps target_dir)              Qt5Core$<$<CONFIG:Debug>:d>.*              Qt5Gui$<$<CONFIG:Debug>:d>.*              Qt5Widgets$<$<CONFIG:Debug>:d>.* +            Qt5Multimedia$<$<CONFIG:Debug>:d>.*          )          if (YUZU_USE_QT_WEB_ENGINE) @@ -53,6 +56,10 @@ function(copy_yuzu_Qt5_deps target_dir)              qjpeg$<$<CONFIG:Debug>:d>.*              qgif$<$<CONFIG:Debug>:d>.*          ) +        windows_copy_files(yuzu ${Qt5_MEDIASERVICE_DIR} ${MEDIASERVICE} +            dsengine$<$<CONFIG:Debug>:d>.* +            wmfengine$<$<CONFIG:Debug>:d>.* +        )      else()          set(Qt5_DLLS              "${Qt5_DLL_DIR}libQt5Core.so.5" diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 242867a4f..a11a3b908 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -43,6 +43,9 @@ add_executable(yuzu      configuration/configure_audio.cpp      configuration/configure_audio.h      configuration/configure_audio.ui +    configuration/configure_camera.cpp +    configuration/configure_camera.h +    configuration/configure_camera.ui      configuration/configure_cpu.cpp      configuration/configure_cpu.h      configuration/configure_cpu.ui @@ -254,7 +257,7 @@ endif()  create_target_directory_groups(yuzu)  target_link_libraries(yuzu PRIVATE common core input_common video_core) -target_link_libraries(yuzu PRIVATE Boost::boost glad Qt::Widgets) +target_link_libraries(yuzu PRIVATE Boost::boost glad Qt::Widgets Qt::Multimedia)  target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)  target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 01acda22b..774085809 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -5,6 +5,8 @@  #include <glad/glad.h>  #include <QApplication> +#include <QCameraImageCapture> +#include <QCameraInfo>  #include <QHBoxLayout>  #include <QMessageBox>  #include <QPainter> @@ -31,6 +33,7 @@  #include "core/core.h"  #include "core/cpu_manager.h"  #include "core/frontend/framebuffer_layout.h" +#include "input_common/drivers/camera.h"  #include "input_common/drivers/keyboard.h"  #include "input_common/drivers/mouse.h"  #include "input_common/drivers/tas_input.h" @@ -801,6 +804,74 @@ void GRenderWindow::TouchEndEvent() {      input_subsystem->GetTouchScreen()->ReleaseAllTouch();  } +void GRenderWindow::InitializeCamera() { +    if (!Settings::values.enable_ir_sensor) { +        return; +    } + +    bool camera_found = false; +    const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); +    for (const QCameraInfo& cameraInfo : cameras) { +        if (Settings::values.ir_sensor_device.GetValue() == cameraInfo.deviceName().toStdString() || +            Settings::values.ir_sensor_device.GetValue() == "Auto") { +            camera = std::make_unique<QCamera>(cameraInfo); +            camera_found = true; +            break; +        } +    } + +    if (!camera_found) { +        return; +    } + +    camera_capture = std::make_unique<QCameraImageCapture>(camera.get()); +    connect(camera_capture.get(), &QCameraImageCapture::imageCaptured, this, +            &GRenderWindow::OnCameraCapture); +    camera->unload(); +    camera->setCaptureMode(QCamera::CaptureViewfinder); +    camera->load(); + +    camera_timer = std::make_unique<QTimer>(); +    connect(camera_timer.get(), &QTimer::timeout, [this] { RequestCameraCapture(); }); +    // This timer should be dependent of camera resolution 5ms for every 100 pixels +    camera_timer->start(100); +} + +void GRenderWindow::FinalizeCamera() { +    if (camera_timer) { +        camera_timer->stop(); +    } +    if (camera) { +        camera->unload(); +    } +} + +void GRenderWindow::RequestCameraCapture() { +    if (!Settings::values.enable_ir_sensor) { +        return; +    } + +    // Idealy one should only call capture but Qt refuses to take a second capture without +    // stopping the camera +    camera->stop(); +    camera->start(); + +    camera_capture->capture(); +} + +void GRenderWindow::OnCameraCapture(int requestId, const QImage& img) { +    constexpr std::size_t camera_width = 320; +    constexpr std::size_t camera_height = 240; +    const auto converted = +        img.scaled(camera_width, camera_height, Qt::AspectRatioMode::IgnoreAspectRatio, +                   Qt::TransformationMode::SmoothTransformation) +            .mirrored(false, true); +    std::vector<u32> camera_data{}; +    camera_data.resize(camera_width * camera_height); +    std::memcpy(camera_data.data(), converted.bits(), camera_width * camera_height * sizeof(u32)); +    input_subsystem->GetCamera()->SetCameraData(camera_width, camera_height, camera_data); +} +  bool GRenderWindow::event(QEvent* event) {      if (event->type() == QEvent::TouchBegin) {          TouchBeginEvent(static_cast<QTouchEvent*>(event)); diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 81fe52c0e..346201768 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -20,6 +20,8 @@  class GRenderWindow;  class GMainWindow; +class QCamera; +class QCameraImageCapture;  class QKeyEvent;  namespace Core { @@ -164,6 +166,9 @@ public:      void mouseReleaseEvent(QMouseEvent* event) override;      void wheelEvent(QWheelEvent* event) override; +    void InitializeCamera(); +    void FinalizeCamera(); +      bool event(QEvent* event) override;      void focusOutEvent(QFocusEvent* event) override; @@ -207,6 +212,9 @@ private:      void TouchUpdateEvent(const QTouchEvent* event);      void TouchEndEvent(); +    void RequestCameraCapture(); +    void OnCameraCapture(int requestId, const QImage& img); +      void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;      bool InitializeOpenGL(); @@ -232,6 +240,10 @@ private:      bool first_frame = false;      InputCommon::TasInput::TasState last_tas_state; +    std::unique_ptr<QCamera> camera; +    std::unique_ptr<QCameraImageCapture> camera_capture; +    std::unique_ptr<QTimer> camera_timer; +      Core::System& system;  protected: diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 2840bc5eb..1f76e86b9 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -368,6 +368,11 @@ void Config::ReadHidbusValues() {      }  } +void Config::ReadIrCameraValues() { +    ReadBasicSetting(Settings::values.enable_ir_sensor); +    ReadBasicSetting(Settings::values.ir_sensor_device); +} +  void Config::ReadAudioValues() {      qt_config->beginGroup(QStringLiteral("Audio")); @@ -393,6 +398,7 @@ void Config::ReadControlValues() {      ReadTouchscreenValues();      ReadMotionTouchValues();      ReadHidbusValues(); +    ReadIrCameraValues();  #ifdef _WIN32      ReadBasicSetting(Settings::values.enable_raw_input); @@ -1005,6 +1011,11 @@ void Config::SaveHidbusValues() {                   QString::fromStdString(default_param));  } +void Config::SaveIrCameraValues() { +    WriteBasicSetting(Settings::values.enable_ir_sensor); +    WriteBasicSetting(Settings::values.ir_sensor_device); +} +  void Config::SaveValues() {      if (global) {          SaveControlValues(); @@ -1047,6 +1058,7 @@ void Config::SaveControlValues() {      SaveTouchscreenValues();      SaveMotionTouchValues();      SaveHidbusValues(); +    SaveIrCameraValues();      WriteGlobalSetting(Settings::values.use_docked_mode);      WriteGlobalSetting(Settings::values.vibration_enabled); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index d511b3dbd..a71eabe8e 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -68,6 +68,7 @@ private:      void ReadTouchscreenValues();      void ReadMotionTouchValues();      void ReadHidbusValues(); +    void ReadIrCameraValues();      // Read functions bases off the respective config section names.      void ReadAudioValues(); @@ -96,6 +97,7 @@ private:      void SaveTouchscreenValues();      void SaveMotionTouchValues();      void SaveHidbusValues(); +    void SaveIrCameraValues();      // Save functions based off the respective config section names.      void SaveAudioValues(); diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp new file mode 100644 index 000000000..97febb33c --- /dev/null +++ b/src/yuzu/configuration/configure_camera.cpp @@ -0,0 +1,126 @@ +// Text : Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <memory> +#include <QCameraImageCapture> +#include <QCameraInfo> +#include <QStandardItemModel> +#include <QTimer> + +#include "input_common/drivers/camera.h" +#include "input_common/main.h" +#include "ui_configure_camera.h" +#include "yuzu/configuration/config.h" +#include "yuzu/configuration/configure_camera.h" + +ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_) +    : QDialog(parent), input_subsystem{input_subsystem_}, +      ui(std::make_unique<Ui::ConfigureCamera>()) { +    ui->setupUi(this); + +    connect(ui->restore_defaults_button, &QPushButton::clicked, this, +            &ConfigureCamera::RestoreDefaults); +    connect(ui->preview_button, &QPushButton::clicked, this, &ConfigureCamera::PreviewCamera); + +    auto blank_image = QImage(320, 240, QImage::Format::Format_RGB32); +    blank_image.fill(Qt::black); +    DisplayCapturedFrame(0, blank_image); + +    LoadConfiguration(); +    resize(0, 0); +} + +ConfigureCamera::~ConfigureCamera() = default; + +void ConfigureCamera::PreviewCamera() { +    const auto index = ui->ir_sensor_combo_box->currentIndex(); +    bool camera_found = false; +    const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); +    for (const QCameraInfo& cameraInfo : cameras) { +        if (input_devices[index] == cameraInfo.deviceName().toStdString() || +            input_devices[index] == "Auto") { +            LOG_ERROR(Frontend, "Selected Camera {} {}", cameraInfo.description().toStdString(), +                      cameraInfo.deviceName().toStdString()); +            camera = std::make_unique<QCamera>(cameraInfo); +            camera_found = true; +            break; +        } +    } + +    // Clear previous frame +    auto blank_image = QImage(320, 240, QImage::Format::Format_RGB32); +    blank_image.fill(Qt::black); +    DisplayCapturedFrame(0, blank_image); + +    if (!camera_found) { +        return; +    } + +    camera_capture = std::make_unique<QCameraImageCapture>(camera.get()); +    connect(camera_capture.get(), &QCameraImageCapture::imageCaptured, this, +            &ConfigureCamera::DisplayCapturedFrame); +    camera->unload(); +    camera->setCaptureMode(QCamera::CaptureViewfinder); +    camera->load(); + +    camera_timer = std::make_unique<QTimer>(); +    connect(camera_timer.get(), &QTimer::timeout, [this] { +        camera->stop(); +        camera->start(); + +        camera_capture->capture(); +    }); + +    camera_timer->start(250); +} + +void ConfigureCamera::DisplayCapturedFrame(int requestId, const QImage& img) { +    LOG_ERROR(Frontend, "ImageCaptured {} {}", img.width(), img.height()); +    const auto converted = img.scaled(320, 240, Qt::AspectRatioMode::IgnoreAspectRatio, +                                      Qt::TransformationMode::SmoothTransformation); +    ui->preview_box->setPixmap(QPixmap::fromImage(converted)); +} + +void ConfigureCamera::changeEvent(QEvent* event) { +    if (event->type() == QEvent::LanguageChange) { +        RetranslateUI(); +    } + +    QDialog::changeEvent(event); +} + +void ConfigureCamera::RetranslateUI() { +    ui->retranslateUi(this); +} + +void ConfigureCamera::ApplyConfiguration() { +    const auto index = ui->ir_sensor_combo_box->currentIndex(); +    Settings::values.ir_sensor_device.SetValue(input_devices[index]); +} + +void ConfigureCamera::LoadConfiguration() { +    input_devices.clear(); +    ui->ir_sensor_combo_box->clear(); +    input_devices.push_back("Auto"); +    ui->ir_sensor_combo_box->addItem(tr("Auto")); +    const auto cameras = QCameraInfo::availableCameras(); +    for (const QCameraInfo& cameraInfo : cameras) { +        input_devices.push_back(cameraInfo.deviceName().toStdString()); +        ui->ir_sensor_combo_box->addItem(cameraInfo.description()); +    } + +    const auto current_device = Settings::values.ir_sensor_device.GetValue(); + +    const auto devices_it = std::find_if( +        input_devices.begin(), input_devices.end(), +        [current_device](const std::string& device) { return device == current_device; }); +    const int device_index = +        devices_it != input_devices.end() +            ? static_cast<int>(std::distance(input_devices.begin(), devices_it)) +            : 0; +    ui->ir_sensor_combo_box->setCurrentIndex(device_index); +} + +void ConfigureCamera::RestoreDefaults() { +    ui->ir_sensor_combo_box->setCurrentIndex(0); +} diff --git a/src/yuzu/configuration/configure_camera.h b/src/yuzu/configuration/configure_camera.h new file mode 100644 index 000000000..af7551c03 --- /dev/null +++ b/src/yuzu/configuration/configure_camera.h @@ -0,0 +1,52 @@ +// Text : Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <memory> +#include <QDialog> + +class QTimer; +class QCamera; +class QCameraImageCapture; + +namespace InputCommon { +class InputSubsystem; +} // namespace InputCommon + +namespace Ui { +class ConfigureCamera; +} + +class ConfigureCamera : public QDialog { +    Q_OBJECT + +public: +    explicit ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_); +    ~ConfigureCamera() override; + +    void ApplyConfiguration(); + +private: +    void changeEvent(QEvent* event) override; +    void RetranslateUI(); + +    /// Load configuration settings. +    void LoadConfiguration(); + +    /// Restore all buttons to their default values. +    void RestoreDefaults(); + +    void DisplayCapturedFrame(int requestId, const QImage& img); + +    /// Loads and signals the current selected camera to display a frame +    void PreviewCamera(); + +    InputCommon::InputSubsystem* input_subsystem; + +    std::unique_ptr<QCamera> camera; +    std::unique_ptr<QCameraImageCapture> camera_capture; +    std::unique_ptr<QTimer> camera_timer; +    std::vector<std::string> input_devices; +    std::unique_ptr<Ui::ConfigureCamera> ui; +}; diff --git a/src/yuzu/configuration/configure_camera.ui b/src/yuzu/configuration/configure_camera.ui new file mode 100644 index 000000000..976a9b1ec --- /dev/null +++ b/src/yuzu/configuration/configure_camera.ui @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ConfigureCamera</class> + <widget class="QDialog" name="ConfigureCamera"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>298</width> +    <height>339</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Configure Infrared Camera</string> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout"> +   <item> +    <widget class="QLabel" name="label_2"> +     <property name="minimumSize"> +      <size> +       <width>280</width> +       <height>0</height> +      </size> +     </property> +     <property name="text"> +      <string>Select where the image of the emulated camera comes from. It may be a virtual camera or a real camera.</string> +     </property> +     <property name="wordWrap"> +      <bool>true</bool> +     </property> +    </widget> +   </item> +   <item> +    <spacer name="verticalSpacer_2"> +     <property name="orientation"> +      <enum>Qt::Vertical</enum> +     </property> +     <property name="sizeType"> +      <enum>QSizePolicy::Fixed</enum> +     </property> +     <property name="sizeHint" stdset="0"> +      <size> +       <width>20</width> +       <height>20</height> +      </size> +     </property> +    </spacer> +   </item> +   <item> +    <widget class="QGroupBox" name="gridGroupBox"> +     <property name="title"> +      <string>Camera Image Source:</string> +     </property> +     <layout class="QGridLayout" name="gridLayout"> +      <item row="0" column="0"> +       <spacer name="horizontalSpacer"> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +        <property name="sizeHint" stdset="0"> +         <size> +          <width>40</width> +          <height>20</height> +         </size> +        </property> +       </spacer> +      </item> +       <item row="0" column="1"> +         <widget class="QLabel" name="label_3"> +           <property name="text"> +             <string>Input device:</string> +           </property> +         </widget> +       </item> +       <item row="0" column="2"> +         <widget class="QComboBox" name="ir_sensor_combo_box"/> +       </item> +      <item row="0" column="3"> +       <spacer name="horizontalSpacer_2"> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +        <property name="sizeHint" stdset="0"> +         <size> +          <width>40</width> +          <height>20</height> +         </size> +        </property> +       </spacer> +      </item> +     </layout> +    </widget> +   </item><item> +    <widget class="QGroupBox" name="previewBox"> +     <property name="title"> +      <string>Preview</string> +     </property> +     <layout class="QVBoxLayout" name="verticalLayout_3"> +      <item> +       <widget class="QLabel" name="preview_box"> +         <property name="minimumSize"> +           <size> +             <width>320</width> +             <height>240</height> +           </size> +         </property> +        <property name="toolTip"> +         <string>Resolution: 320*240</string> +        </property> +       </widget> +      </item> +      <item> +       <widget class="QPushButton" name="preview_button"> +        <property name="text"> +         <string>Click to preview</string> +        </property> +       </widget> +      </item> +     </layout> +    </widget> +   </item> +   <item> +    <spacer name="verticalSpacer"> +     <property name="orientation"> +      <enum>Qt::Vertical</enum> +     </property> +     <property name="sizeHint" stdset="0"> +      <size> +       <width>20</width> +       <height>40</height> +      </size> +     </property> +    </spacer> +   </item> +   <item> +    <layout class="QHBoxLayout" name="horizontalLayout"> +     <item> +      <widget class="QPushButton" name="restore_defaults_button"> +       <property name="text"> +        <string>Restore Defaults</string> +       </property> +      </widget> +     </item> +     <item> +      <widget class="QDialogButtonBox" name="buttonBox"> +       <property name="standardButtons"> +        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> +       </property> +      </widget> +     </item> +    </layout> +   </item> +  </layout> + </widget> + <resources/> + <connections> +  <connection> +   <sender>buttonBox</sender> +   <signal>accepted()</signal> +   <receiver>ConfigureCamera</receiver> +   <slot>accept()</slot> +  </connection> +  <connection> +   <sender>buttonBox</sender> +   <signal>rejected()</signal> +   <receiver>ConfigureCamera</receiver> +   <slot>reject()</slot> +   </connection> + </connections> +</ui> diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 73d7ba24b..f1b061b13 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -15,6 +15,7 @@  #include "ui_configure_input.h"  #include "ui_configure_input_advanced.h"  #include "ui_configure_input_player.h" +#include "yuzu/configuration/configure_camera.h"  #include "yuzu/configuration/configure_debug_controller.h"  #include "yuzu/configuration/configure_input.h"  #include "yuzu/configuration/configure_input_advanced.h" @@ -163,6 +164,10 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,              [this, input_subsystem, &hid_core] {                  CallConfigureDialog<ConfigureRingController>(*this, input_subsystem, hid_core);              }); +    connect(advanced, &ConfigureInputAdvanced::CallCameraDialog, +            [this, input_subsystem, &hid_core] { +                CallConfigureDialog<ConfigureCamera>(*this, input_subsystem); +            });      connect(ui->vibrationButton, &QPushButton::clicked,              [this, &hid_core] { CallConfigureDialog<ConfigureVibration>(*this, hid_core); }); diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index f14bdc831..10f841b98 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -89,6 +89,7 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)              [this] { CallMotionTouchConfigDialog(); });      connect(ui->ring_controller_configure, &QPushButton::clicked, this,              [this] { CallRingControllerDialog(); }); +    connect(ui->camera_configure, &QPushButton::clicked, this, [this] { CallCameraDialog(); });  #ifndef _WIN32      ui->enable_raw_input->setVisible(false); @@ -136,6 +137,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {      Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked();      Settings::values.controller_navigation = ui->controller_navigation->isChecked();      Settings::values.enable_ring_controller = ui->enable_ring_controller->isChecked(); +    Settings::values.enable_ir_sensor = ui->enable_ir_sensor->isChecked();  }  void ConfigureInputAdvanced::LoadConfiguration() { @@ -169,6 +171,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {      ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue());      ui->controller_navigation->setChecked(Settings::values.controller_navigation.GetValue());      ui->enable_ring_controller->setChecked(Settings::values.enable_ring_controller.GetValue()); +    ui->enable_ir_sensor->setChecked(Settings::values.enable_ir_sensor.GetValue());      UpdateUIEnabled();  } diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h index 644e56dd8..fc1230284 100644 --- a/src/yuzu/configuration/configure_input_advanced.h +++ b/src/yuzu/configuration/configure_input_advanced.h @@ -29,6 +29,7 @@ signals:      void CallTouchscreenConfigDialog();      void CallMotionTouchConfigDialog();      void CallRingControllerDialog(); +    void CallCameraDialog();  private:      void changeEvent(QEvent* event) override; diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 14403cb10..fac8cf827 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2617,6 +2617,20 @@                   </property>                  </widget>                 </item> +               <item row="5" column="0"> +                <widget class="QCheckBox" name="enable_ir_sensor"> +                 <property name="text"> +                  <string>Infrared Camera</string> +                 </property> +                </widget> +               </item> +               <item row="5" column="2"> +                <widget class="QPushButton" name="camera_configure"> +                 <property name="text"> +                  <string>Configure</string> +                 </property> +                </widget> +               </item>                </layout>               </widget>              </item> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a120f2662..08ccc1555 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1542,6 +1542,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t          mouse_hide_timer.start();      } +    render_window->InitializeCamera(); +      std::string title_name;      std::string title_version;      const auto res = system->GetGameName(title_name); @@ -1623,6 +1625,7 @@ void GMainWindow::ShutdownGame() {      tas_label->clear();      input_subsystem->GetTas()->Stop();      OnTasStateChanged(); +    render_window->FinalizeCamera();      // Enable all controllers      system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); @@ -2862,6 +2865,12 @@ void GMainWindow::OnConfigure() {          mouse_hide_timer.start();      } +    // Restart camera config +    if (emulation_running) { +        render_window->FinalizeCamera(); +        render_window->InitializeCamera(); +    } +      if (!UISettings::values.has_broken_vulkan) {          renderer_status_button->setEnabled(!emulation_running);      } | 
