From e374853cf56ac2322f1c1046c340cb2cf2bee3a8 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 1 Jul 2020 00:35:13 +1000 Subject: [PATCH] HostInterface: Better configuration of custom crosshair/software cursor --- src/core/controller.cpp | 8 ++++ src/core/controller.h | 4 ++ src/core/host_interface.cpp | 76 +++++++++++++++++++------------------ src/core/host_interface.h | 16 +++----- src/core/namco_guncon.cpp | 56 +++++++++++++++++++++++---- src/core/namco_guncon.h | 6 +++ src/core/settings.cpp | 4 -- src/core/settings.h | 2 - 8 files changed, 110 insertions(+), 62 deletions(-) diff --git a/src/core/controller.cpp b/src/core/controller.cpp index 53d7fd22a..4f829fb69 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -41,6 +41,11 @@ float Controller::GetVibrationMotorStrength(u32 motor) void Controller::LoadSettings(HostInterface* host_interface, const char* section) {} +bool Controller::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale) +{ + return false; +} + std::unique_ptr Controller::Create(System* system, ControllerType type, u32 index) { switch (type) @@ -208,6 +213,9 @@ Controller::SettingList Controller::GetSettings(ControllerType type) case ControllerType::AnalogController: return AnalogController::StaticGetSettings(); + case ControllerType::NamcoGunCon: + return NamcoGunCon::StaticGetSettings(); + default: return {}; } diff --git a/src/core/controller.h b/src/core/controller.h index 1f9ca51b8..2c8913460 100644 --- a/src/core/controller.h +++ b/src/core/controller.h @@ -1,4 +1,5 @@ #pragma once +#include "common/image.h" #include "settings.h" #include "types.h" #include @@ -54,6 +55,9 @@ public: /// Loads/refreshes any per-controller settings. virtual void LoadSettings(HostInterface* host_interface, const char* section); + /// Returns the software cursor to use for this controller, if any. + virtual bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale); + /// Creates a new controller of the specified type. static std::unique_ptr Create(System* system, ControllerType type, u32 index); diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 047d2f717..dad42599a 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -4,8 +4,10 @@ #include "common/audio_stream.h" #include "common/byte_stream.h" #include "common/file_system.h" +#include "common/image.h" #include "common/log.h" #include "common/string_util.h" +#include "controller.h" #include "dma.h" #include "gpu.h" #include "host_display.h" @@ -89,6 +91,7 @@ bool HostInterface::BootSystem(const SystemBootParameters& parameters) return false; } + UpdateSoftwareCursor(); OnSystemCreated(); m_audio_stream->PauseOutput(false); @@ -117,6 +120,7 @@ void HostInterface::DestroySystem() m_system.reset(); m_audio_stream.reset(); + UpdateSoftwareCursor(); ReleaseHostDisplay(); OnSystemDestroyed(); OnRunningGameChanged(); @@ -352,8 +356,6 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetBoolValue("Display", "ShowSpeed", false); si.SetBoolValue("Display", "Fullscreen", false); si.SetBoolValue("Display", "VSync", true); - si.SetStringValue("Display", "SoftwareCursorPath", ""); - si.SetFloatValue("Display", "SoftwareCursorScale", 1.0f); si.SetBoolValue("CDROM", "ReadThread", true); si.SetBoolValue("CDROM", "RegionCheck", true); @@ -476,6 +478,7 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings) if (m_system && !controllers_updated) { m_system->UpdateControllers(); + UpdateSoftwareCursor(); controllers_updated = true; } @@ -483,7 +486,10 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings) } if (m_system && !controllers_updated) + { m_system->UpdateControllerSettings(); + UpdateSoftwareCursor(); + } } if (m_display && m_settings.display_linear_filtering != old_settings.display_linear_filtering) @@ -491,21 +497,6 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings) if (m_display && m_settings.display_integer_scaling != old_settings.display_integer_scaling) m_display->SetDisplayIntegerScaling(m_settings.display_integer_scaling); - - if (m_software_cursor_use_count > 0 && m_display && - (m_settings.display_software_cursor_path != old_settings.display_software_cursor_path || - m_settings.display_software_cursor_scale != old_settings.display_software_cursor_scale)) - { - if (m_settings.display_software_cursor_path.empty()) - { - m_display->ClearSoftwareCursor(); - } - else - { - m_display->SetSoftwareCursor(m_settings.display_software_cursor_path.c_str(), - m_settings.display_software_cursor_scale); - } - } } void HostInterface::SetUserDirectoryToProgramDirectory() @@ -580,7 +571,7 @@ bool HostInterface::GetBooleanSettingValue(const char* section, const char* key, return bool_value.value_or(default_value); } -bool HostInterface::GetIntegerSettingValue(const char* section, const char* key, s32 default_value /*= 0*/) +s32 HostInterface::GetIntegerSettingValue(const char* section, const char* key, s32 default_value /*= 0*/) { std::string value = GetSettingValue(section, key, ""); if (value.empty()) @@ -590,7 +581,7 @@ bool HostInterface::GetIntegerSettingValue(const char* section, const char* key, return int_value.value_or(default_value); } -bool HostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/) +float HostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/) { std::string value = GetSettingValue(section, key, ""); if (value.empty()) @@ -628,6 +619,35 @@ void HostInterface::ModifyResolutionScale(s32 increment) m_system->GetGPU()->UpdateSettings(); } +void HostInterface::UpdateSoftwareCursor() +{ + if (!m_system) + { + m_display->ClearSoftwareCursor(); + return; + } + + const Common::RGBA8Image* image = nullptr; + float image_scale = 1.0f; + + for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) + { + Controller* controller = m_system->GetController(i); + if (controller && controller->GetSoftwareCursor(&image, &image_scale)) + break; + } + + if (image && image->IsValid()) + { + m_display->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetByteStride(), + image_scale); + } + else + { + m_display->ClearSoftwareCursor(); + } +} + void HostInterface::RecreateSystem() { std::unique_ptr stream = ByteStream_CreateGrowableMemoryStream(nullptr, 8 * 1024); @@ -657,22 +677,4 @@ void HostInterface::DisplayLoadingScreen(const char* message, int progress_min / Log_InfoPrintf("Loading: %s %d of %d-%d", message, progress_value, progress_min, progress_max); } -void HostInterface::EnableSoftwareCursor() -{ - if (m_software_cursor_use_count++ > 0 || m_settings.display_software_cursor_path.empty()) - return; - - m_display->SetSoftwareCursor(m_settings.display_software_cursor_path.c_str(), - m_settings.display_software_cursor_scale); -} - -void HostInterface::DisableSoftwareCursor() -{ - DebugAssert(m_software_cursor_use_count > 0); - if (--m_software_cursor_use_count > 0) - return; - - m_display->ClearSoftwareCursor(); -} - void HostInterface::GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) {} diff --git a/src/core/host_interface.h b/src/core/host_interface.h index 42194dca2..ba8aaf03e 100644 --- a/src/core/host_interface.h +++ b/src/core/host_interface.h @@ -110,17 +110,10 @@ public: bool GetBooleanSettingValue(const char* section, const char* key, bool default_value = false); /// Returns an integer setting from the configuration. - bool GetIntegerSettingValue(const char* section, const char* key, s32 default_value = 0); + s32 GetIntegerSettingValue(const char* section, const char* key, s32 default_value = 0); /// Returns a float setting from the configuration. - bool GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); - - /// Enables the software cursor. Can be called multiple times, but must be matched by a call to - /// DisableSoftwareCursor(). - void EnableSoftwareCursor(); - - /// Disables the software cursor, preventing it from being renderered. - void DisableSoftwareCursor(); + float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); protected: virtual bool AcquireHostDisplay() = 0; @@ -164,6 +157,9 @@ protected: /// Adjusts the internal (render) resolution of the hardware backends. void ModifyResolutionScale(s32 increment); + /// Updates software cursor state, based on controllers. + void UpdateSoftwareCursor(); + bool SaveState(const char* filename); void CreateAudioStream(); @@ -173,6 +169,4 @@ protected: Settings m_settings; std::string m_program_directory; std::string m_user_directory; - - u32 m_software_cursor_use_count = 0; }; diff --git a/src/core/namco_guncon.cpp b/src/core/namco_guncon.cpp index 1eeb60a27..965b4a9ea 100644 --- a/src/core/namco_guncon.cpp +++ b/src/core/namco_guncon.cpp @@ -5,19 +5,14 @@ #include "gpu.h" #include "host_display.h" #include "host_interface.h" +#include "resources.h" #include "system.h" #include Log_SetChannel(NamcoGunCon); -NamcoGunCon::NamcoGunCon(System* system) : m_system(system) -{ - m_system->GetHostInterface()->EnableSoftwareCursor(); -} +NamcoGunCon::NamcoGunCon(System* system) : m_system(system) {} -NamcoGunCon::~NamcoGunCon() -{ - m_system->GetHostInterface()->DisableSoftwareCursor(); -} +NamcoGunCon::~NamcoGunCon() = default; ControllerType NamcoGunCon::GetType() const { @@ -226,3 +221,48 @@ u32 NamcoGunCon::StaticGetVibrationMotorCount() { return 0; } + +Controller::SettingList NamcoGunCon::StaticGetSettings() +{ + static constexpr std::array settings = { + {{SettingInfo::Type::Path, "CrosshairImagePath", "Crosshair Image Path", + "Path to an image to use as a crosshair/cursor."}, + {SettingInfo::Type::Float, "CrosshairScale", "Crosshair Image Scale", "Scale of crosshair image on screen.", "1.0", + "0.0001", "100.0"}}}; + + return SettingList(settings.begin(), settings.end()); +} + +void NamcoGunCon::LoadSettings(HostInterface* host_interface, const char* section) +{ + Controller::LoadSettings(host_interface, section); + + std::string path = host_interface->GetSettingValue(section, "CrosshairImagePath"); + if (path != m_crosshair_image_path) + { + m_crosshair_image_path = std::move(path); + if (m_crosshair_image_path.empty() || + !Common::LoadImageFromFile(&m_crosshair_image, m_crosshair_image_path.c_str())) + { + m_crosshair_image.Invalidate(); + } + } + + if (!m_crosshair_image.IsValid()) + { + m_crosshair_image.SetPixels(Resources::CROSSHAIR_IMAGE_WIDTH, Resources::CROSSHAIR_IMAGE_HEIGHT, + Resources::CROSSHAIR_IMAGE_DATA.data()); + } + + m_crosshair_image_scale = host_interface->GetFloatSettingValue(section, "CrosshairScale", 1.0f); +} + +bool NamcoGunCon::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale) +{ + if (!m_crosshair_image.IsValid()) + return false; + + *image = &m_crosshair_image; + *image_scale = m_crosshair_image_scale; + return true; +} diff --git a/src/core/namco_guncon.h b/src/core/namco_guncon.h index 341e986dd..a8c70506d 100644 --- a/src/core/namco_guncon.h +++ b/src/core/namco_guncon.h @@ -24,6 +24,7 @@ public: static AxisList StaticGetAxisNames(); static ButtonList StaticGetButtonNames(); static u32 StaticGetVibrationMotorCount(); + static SettingList StaticGetSettings(); ControllerType GetType() const override; std::optional GetAxisCodeByName(std::string_view axis_name) const override; @@ -31,6 +32,8 @@ public: void Reset() override; bool DoState(StateWrapper& sw) override; + void LoadSettings(HostInterface* host_interface, const char* section) override; + bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale) override; void SetAxisState(s32 axis_code, float value) override; void SetButtonState(s32 button_code, bool pressed) override; @@ -56,6 +59,9 @@ private: }; System* m_system; + Common::RGBA8Image m_crosshair_image; + std::string m_crosshair_image_path; + float m_crosshair_image_scale = 1.0f; // buttons are active low u16 m_button_state = UINT16_C(0xFFFF); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 5dfce7501..4974ae075 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -113,8 +113,6 @@ void Settings::Load(SettingsInterface& si) display_show_vps = si.GetBoolValue("Display", "ShowVPS", false); display_show_speed = si.GetBoolValue("Display", "ShowSpeed", false); video_sync_enabled = si.GetBoolValue("Display", "VSync", true); - display_software_cursor_path = si.GetStringValue("Display", "SoftwareCursorPath", ""); - display_software_cursor_scale = si.GetFloatValue("Display", "SoftwareCursorScale", 1.0f); cdrom_read_thread = si.GetBoolValue("CDROM", "ReadThread", true); cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", true); @@ -211,8 +209,6 @@ void Settings::Save(SettingsInterface& si) const si.SetBoolValue("Display", "ShowVPS", display_show_vps); si.SetBoolValue("Display", "ShowSpeed", display_show_speed); si.SetBoolValue("Display", "VSync", video_sync_enabled); - si.SetStringValue("Display", "SoftwareCursorPath", display_software_cursor_path.c_str()); - si.SetFloatValue("Display", "SoftwareCursorScale", display_software_cursor_scale); si.SetBoolValue("CDROM", "ReadThread", cdrom_read_thread); si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check); diff --git a/src/core/settings.h b/src/core/settings.h index f2c97bc0c..2f364d312 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -97,8 +97,6 @@ struct Settings bool display_show_vps = false; bool display_show_speed = false; bool video_sync_enabled = true; - std::string display_software_cursor_path; - float display_software_cursor_scale = 1.0f; bool cdrom_read_thread = true; bool cdrom_region_check = true;