From f66b29f043e108fb81476a2571a609b0a2d166b3 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 21 Oct 2021 01:47:59 +0200 Subject: [PATCH] cellCamera: Implement dynamic camera selection --- rpcs3/Emu/system_config.h | 1 + rpcs3/rpcs3qt/emu_settings_type.h | 2 + rpcs3/rpcs3qt/qt_camera_handler.cpp | 76 ++++++++++++++---- rpcs3/rpcs3qt/qt_camera_handler.h | 3 +- rpcs3/rpcs3qt/settings_dialog.cpp | 34 +++++++- rpcs3/rpcs3qt/settings_dialog.ui | 116 ++++++++++++++-------------- rpcs3/rpcs3qt/tooltips.h | 1 + 7 files changed, 161 insertions(+), 72 deletions(-) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index e08b863625..1cd654b404 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -244,6 +244,7 @@ struct cfg_root : cfg::node cfg::_enum camera{ this, "Camera", camera_handler::null }; cfg::_enum camera_type{ this, "Camera type", fake_camera_type::unknown }; cfg::_enum camera_flip{ this, "Camera flip", camera_flip::none, true }; + cfg::string camera_id{ this, "Camera ID", "Default", true }; cfg::_enum move{ this, "Move", move_handler::null }; cfg::_enum buzz{ this, "Buzz emulated controller", buzz_handler::null }; cfg::_enum turntable{this, "Turntable emulated controller", turntable_handler::null}; diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 158ced6633..db64d90737 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -126,6 +126,7 @@ enum class emu_settings_type Camera, CameraType, CameraFlip, + CameraID, Move, Buzz, Turntable, @@ -281,6 +282,7 @@ inline static const QMap settings_location = { emu_settings_type::Camera, { "Input/Output", "Camera"}}, { emu_settings_type::CameraType, { "Input/Output", "Camera type"}}, { emu_settings_type::CameraFlip, { "Input/Output", "Camera flip"}}, + { emu_settings_type::CameraID, { "Input/Output", "Camera ID"}}, { emu_settings_type::Move, { "Input/Output", "Move" }}, { emu_settings_type::Buzz, { "Input/Output", "Buzz emulated controller" }}, { emu_settings_type::Turntable, { "Input/Output", "Turntable emulated controller" }}, diff --git a/rpcs3/rpcs3qt/qt_camera_handler.cpp b/rpcs3/rpcs3qt/qt_camera_handler.cpp index ed6e39b648..20914b7a2f 100644 --- a/rpcs3/rpcs3qt/qt_camera_handler.cpp +++ b/rpcs3/rpcs3qt/qt_camera_handler.cpp @@ -1,6 +1,6 @@ #include "stdafx.h" #include "qt_camera_handler.h" -#include "Emu/System.h" +#include "Emu/system_config.h" #include #include @@ -21,22 +21,24 @@ qt_camera_handler::~qt_camera_handler() close_camera(); } -void qt_camera_handler::set_camera(const QCameraInfo& cameraInfo) +void qt_camera_handler::set_camera(const QCameraInfo& camera_info) { - if (cameraInfo.isNull()) + if (camera_info.isNull()) { - camera_log.warning("No camera present"); + m_surface.reset(); + m_camera.reset(); + m_error_handler.reset(); return; } // Determine if the camera is front facing, in which case we will need to flip the image horizontally. - const bool front_facing = cameraInfo.position() == QCamera::Position::FrontFace; + const bool front_facing = camera_info.position() == QCamera::Position::FrontFace; - camera_log.success("Using camera: name=\"%s\", description=\"%s\", front_facing=%d", cameraInfo.deviceName().toStdString(), cameraInfo.description().toStdString(), front_facing); + camera_log.success("Using camera: name=\"%s\", description=\"%s\", front_facing=%d", camera_info.deviceName().toStdString(), camera_info.description().toStdString(), front_facing); // Create camera and video surface m_surface.reset(new qt_camera_video_surface(front_facing, nullptr)); - m_camera.reset(new QCamera(cameraInfo)); + m_camera.reset(new QCamera(camera_info)); m_error_handler.reset(new qt_camera_error_handler(m_camera, [this](QCamera::Status status) { @@ -72,14 +74,42 @@ void qt_camera_handler::set_camera(const QCameraInfo& cameraInfo) void qt_camera_handler::open_camera() { - // Let's use the default camera for now - set_camera(QCameraInfo::defaultCamera()); - camera_log.notice("Loading camera"); + if (const std::string camera_id = g_cfg.io.camera_id.to_string(); + m_camera_id != camera_id) + { + camera_log.notice("Switching camera from %s to %s", camera_id, m_camera_id); + camera_log.notice("Unloading old camera..."); + if (m_camera) m_camera->unload(); + m_camera_id = camera_id; + } + + QCameraInfo selected_camera; + + if (m_camera_id == g_cfg.io.camera_id.def) + { + selected_camera = QCameraInfo::defaultCamera(); + } + else if (!m_camera_id.empty()) + { + const QString camera_id = QString::fromStdString(m_camera_id); + for (const QCameraInfo& camera_info : QCameraInfo::availableCameras()) + { + if (camera_id == camera_info.deviceName()) + { + selected_camera = camera_info; + break; + } + } + } + + set_camera(selected_camera); + if (!m_camera) { - camera_log.error("No camera found"); + if (m_camera_id.empty()) camera_log.notice("Camera disabled"); + else camera_log.error("No camera found"); m_state = camera_handler_state::not_available; return; } @@ -117,7 +147,8 @@ void qt_camera_handler::close_camera() if (!m_camera) { - camera_log.error("No camera found"); + if (m_camera_id.empty()) camera_log.notice("Camera disabled"); + else camera_log.error("No camera found"); m_state = camera_handler_state::not_available; return; } @@ -138,7 +169,8 @@ void qt_camera_handler::start_camera() if (!m_camera) { - camera_log.error("No camera found"); + if (m_camera_id.empty()) camera_log.notice("Camera disabled"); + else camera_log.error("No camera found"); m_state = camera_handler_state::not_available; return; } @@ -165,7 +197,8 @@ void qt_camera_handler::stop_camera() if (!m_camera) { - camera_log.error("No camera found"); + if (m_camera_id.empty()) camera_log.notice("Camera disabled"); + else camera_log.error("No camera found"); m_state = camera_handler_state::not_available; return; } @@ -222,6 +255,21 @@ camera_handler_base::camera_handler_state qt_camera_handler::get_image(u8* buf, frame_number = 0; bytes_read = 0; + if (const std::string camera_id = g_cfg.io.camera_id.to_string(); + m_camera_id != camera_id) + { + camera_log.notice("Switching cameras"); + m_state = camera_handler_state::not_available; + return camera_handler_state::not_available; + } + + if (m_camera_id.empty()) + { + camera_log.notice("Camera disabled"); + m_state = camera_handler_state::not_available; + return camera_handler_state::not_available; + } + if (!m_camera || !m_surface) { camera_log.fatal("Error: camera invalid"); diff --git a/rpcs3/rpcs3qt/qt_camera_handler.h b/rpcs3/rpcs3qt/qt_camera_handler.h index edbd2aff9f..0b4f707354 100644 --- a/rpcs3/rpcs3qt/qt_camera_handler.h +++ b/rpcs3/rpcs3qt/qt_camera_handler.h @@ -14,7 +14,7 @@ public: qt_camera_handler(); virtual ~qt_camera_handler(); - void set_camera(const QCameraInfo& cameraInfo); + void set_camera(const QCameraInfo& camera_info); void open_camera() override; void close_camera() override; @@ -30,6 +30,7 @@ public: private: void update_camera_settings(); + std::string m_camera_id; std::shared_ptr m_camera; std::unique_ptr m_surface; std::unique_ptr m_error_handler; diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index bf4677238e..7c43962361 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -958,6 +959,37 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceComboBox(ui->cameraFlipBox, emu_settings_type::CameraFlip); SubscribeTooltip(ui->gb_camera_flip, tooltips.settings.camera_flip); + { + const std::string default_camera = m_emu_settings->GetSettingDefault(emu_settings_type::CameraID); + const std::string selected_camera = m_emu_settings->GetSetting(emu_settings_type::CameraID); + ui->cameraIdBox->addItem(tr("None", "Camera Device"), ""); + ui->cameraIdBox->addItem(tr("Default", "Camera Device"), qstr(default_camera)); + for (const QCameraInfo& camera_info : QCameraInfo::availableCameras()) + { + if (!camera_info.isNull()) + ui->cameraIdBox->addItem(camera_info.description(), camera_info.deviceName()); + } + if (const int index = ui->cameraIdBox->findData(qstr(selected_camera)); index >= 0) + { + ui->cameraIdBox->setCurrentIndex(index); + } + else + { + cfg_log.error("The selected camera was not found. Selecting default camera as fallback."); + ui->cameraIdBox->setCurrentIndex(ui->cameraIdBox->findData(qstr(default_camera))); + } + connect(ui->cameraIdBox, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) + { + if (index >= 0) m_emu_settings->SetSetting(emu_settings_type::CameraID, ui->cameraIdBox->itemData(index).toString().toStdString()); + }); + connect(m_emu_settings.get(), &emu_settings::RestoreDefaultsSignal, [this, default_camera]() + { + m_emu_settings->SetSetting(emu_settings_type::CameraID, default_camera); + ui->cameraIdBox->setCurrentIndex(ui->cameraIdBox->findData(qstr(default_camera))); + }); + SubscribeTooltip(ui->gb_camera_id, tooltips.settings.camera_id); + } + m_emu_settings->EnhanceComboBox(ui->moveBox, emu_settings_type::Move); SubscribeTooltip(ui->gb_move_handler, tooltips.settings.move); @@ -1134,7 +1166,7 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std SnapSlider(ui->clockScale, 10); ui->clockScale->setPageStep(50); const int clocks_scale_def = stoi(m_emu_settings->GetSettingDefault(emu_settings_type::ClocksScale)); - connect(ui->clockScaleReset, &QAbstractButton::clicked, [=, this]() + connect(ui->clockScaleReset, &QAbstractButton::clicked, [clocks_scale_def, this]() { ui->clockScale->setValue(clocks_scale_def); }); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index b46b6c96ca..3b89c7b8de 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -1412,10 +1412,10 @@ I/O - + - - + + Keyboard Handler @@ -1427,35 +1427,7 @@ - - - - Camera Input - - - - - - - - - - - - Move Handler - - - - - - - - - - - - - + Mouse Handler @@ -1467,19 +1439,7 @@ - - - - Camera Settings - - - - - - - - - + Buzz! emulated controller @@ -1491,11 +1451,7 @@ - - - - - + DJ Hero emulated turntable @@ -1507,7 +1463,43 @@ - + + + + Camera Input + + + + + + + + + + + + Camera Flip + + + + + + + + + + + + Camera Handler + + + + + + + + + Guitar Hero Live emulated guitar @@ -1519,14 +1511,26 @@ - - + + - Camera Flip + Move Handler - + - + + + + + + + + + Camera + + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index f09419919a..5d26f10642 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -195,6 +195,7 @@ public: const QString camera = tr("Select Qt Camera to use the default camera device of your operating system."); const QString camera_type = tr("Depending on the game, you may need to select a specific camera type."); const QString camera_flip = tr("Flips the camera image either horizontally, vertically, or on both axis."); + const QString camera_id = tr("Select the camera that you want to use during gameplay."); const QString move = tr("PlayStation Move support.\nFake: Experimental! This maps Move controls to DS3 controller mappings.\nMouse: Emulate PSMove with Mouse handler."); const QString buzz = tr("Buzz! support.\nSelect 1 or 2 controllers if the game requires Buzz! controllers and you don't have real controllers.\nSelect Null if the game has support for DualShock or if you have real Buzz! controllers."); const QString turntable = tr("DJ Hero Turntable controller support.\nSelect 1 or 2 controllers if the game requires DJ Hero Turntable controllers and you don't have real turntable controllers.\nSelect Null if the game has support for DualShock or if you have real turntable controllers.\nA real turntable controller can be used at the same time as an emulated turntable controller.");