HostInterface: Better configuration of custom crosshair/software cursor
This commit is contained in:
parent
f0c1dfefe7
commit
e374853cf5
|
@ -41,6 +41,11 @@ float Controller::GetVibrationMotorStrength(u32 motor)
|
||||||
|
|
||||||
void Controller::LoadSettings(HostInterface* host_interface, const char* section) {}
|
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> Controller::Create(System* system, ControllerType type, u32 index)
|
std::unique_ptr<Controller> Controller::Create(System* system, ControllerType type, u32 index)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -208,6 +213,9 @@ Controller::SettingList Controller::GetSettings(ControllerType type)
|
||||||
case ControllerType::AnalogController:
|
case ControllerType::AnalogController:
|
||||||
return AnalogController::StaticGetSettings();
|
return AnalogController::StaticGetSettings();
|
||||||
|
|
||||||
|
case ControllerType::NamcoGunCon:
|
||||||
|
return NamcoGunCon::StaticGetSettings();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "common/image.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -54,6 +55,9 @@ public:
|
||||||
/// Loads/refreshes any per-controller settings.
|
/// Loads/refreshes any per-controller settings.
|
||||||
virtual void LoadSettings(HostInterface* host_interface, const char* section);
|
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.
|
/// Creates a new controller of the specified type.
|
||||||
static std::unique_ptr<Controller> Create(System* system, ControllerType type, u32 index);
|
static std::unique_ptr<Controller> Create(System* system, ControllerType type, u32 index);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
#include "common/audio_stream.h"
|
#include "common/audio_stream.h"
|
||||||
#include "common/byte_stream.h"
|
#include "common/byte_stream.h"
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
|
#include "common/image.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
#include "controller.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
|
@ -89,6 +91,7 @@ bool HostInterface::BootSystem(const SystemBootParameters& parameters)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateSoftwareCursor();
|
||||||
OnSystemCreated();
|
OnSystemCreated();
|
||||||
|
|
||||||
m_audio_stream->PauseOutput(false);
|
m_audio_stream->PauseOutput(false);
|
||||||
|
@ -117,6 +120,7 @@ void HostInterface::DestroySystem()
|
||||||
|
|
||||||
m_system.reset();
|
m_system.reset();
|
||||||
m_audio_stream.reset();
|
m_audio_stream.reset();
|
||||||
|
UpdateSoftwareCursor();
|
||||||
ReleaseHostDisplay();
|
ReleaseHostDisplay();
|
||||||
OnSystemDestroyed();
|
OnSystemDestroyed();
|
||||||
OnRunningGameChanged();
|
OnRunningGameChanged();
|
||||||
|
@ -352,8 +356,6 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
|
||||||
si.SetBoolValue("Display", "ShowSpeed", false);
|
si.SetBoolValue("Display", "ShowSpeed", false);
|
||||||
si.SetBoolValue("Display", "Fullscreen", false);
|
si.SetBoolValue("Display", "Fullscreen", false);
|
||||||
si.SetBoolValue("Display", "VSync", true);
|
si.SetBoolValue("Display", "VSync", true);
|
||||||
si.SetStringValue("Display", "SoftwareCursorPath", "");
|
|
||||||
si.SetFloatValue("Display", "SoftwareCursorScale", 1.0f);
|
|
||||||
|
|
||||||
si.SetBoolValue("CDROM", "ReadThread", true);
|
si.SetBoolValue("CDROM", "ReadThread", true);
|
||||||
si.SetBoolValue("CDROM", "RegionCheck", true);
|
si.SetBoolValue("CDROM", "RegionCheck", true);
|
||||||
|
@ -476,6 +478,7 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
if (m_system && !controllers_updated)
|
if (m_system && !controllers_updated)
|
||||||
{
|
{
|
||||||
m_system->UpdateControllers();
|
m_system->UpdateControllers();
|
||||||
|
UpdateSoftwareCursor();
|
||||||
controllers_updated = true;
|
controllers_updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +486,10 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_system && !controllers_updated)
|
if (m_system && !controllers_updated)
|
||||||
|
{
|
||||||
m_system->UpdateControllerSettings();
|
m_system->UpdateControllerSettings();
|
||||||
|
UpdateSoftwareCursor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_display && m_settings.display_linear_filtering != old_settings.display_linear_filtering)
|
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)
|
if (m_display && m_settings.display_integer_scaling != old_settings.display_integer_scaling)
|
||||||
m_display->SetDisplayIntegerScaling(m_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()
|
void HostInterface::SetUserDirectoryToProgramDirectory()
|
||||||
|
@ -580,7 +571,7 @@ bool HostInterface::GetBooleanSettingValue(const char* section, const char* key,
|
||||||
return bool_value.value_or(default_value);
|
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, "");
|
std::string value = GetSettingValue(section, key, "");
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
|
@ -590,7 +581,7 @@ bool HostInterface::GetIntegerSettingValue(const char* section, const char* key,
|
||||||
return int_value.value_or(default_value);
|
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, "");
|
std::string value = GetSettingValue(section, key, "");
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
|
@ -628,6 +619,35 @@ void HostInterface::ModifyResolutionScale(s32 increment)
|
||||||
m_system->GetGPU()->UpdateSettings();
|
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()
|
void HostInterface::RecreateSystem()
|
||||||
{
|
{
|
||||||
std::unique_ptr<ByteStream> stream = ByteStream_CreateGrowableMemoryStream(nullptr, 8 * 1024);
|
std::unique_ptr<ByteStream> 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);
|
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) {}
|
void HostInterface::GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) {}
|
||||||
|
|
|
@ -110,17 +110,10 @@ public:
|
||||||
bool GetBooleanSettingValue(const char* section, const char* key, bool default_value = false);
|
bool GetBooleanSettingValue(const char* section, const char* key, bool default_value = false);
|
||||||
|
|
||||||
/// Returns an integer setting from the configuration.
|
/// 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.
|
/// Returns a float setting from the configuration.
|
||||||
bool GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f);
|
float 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();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool AcquireHostDisplay() = 0;
|
virtual bool AcquireHostDisplay() = 0;
|
||||||
|
@ -164,6 +157,9 @@ protected:
|
||||||
/// Adjusts the internal (render) resolution of the hardware backends.
|
/// Adjusts the internal (render) resolution of the hardware backends.
|
||||||
void ModifyResolutionScale(s32 increment);
|
void ModifyResolutionScale(s32 increment);
|
||||||
|
|
||||||
|
/// Updates software cursor state, based on controllers.
|
||||||
|
void UpdateSoftwareCursor();
|
||||||
|
|
||||||
bool SaveState(const char* filename);
|
bool SaveState(const char* filename);
|
||||||
void CreateAudioStream();
|
void CreateAudioStream();
|
||||||
|
|
||||||
|
@ -173,6 +169,4 @@ protected:
|
||||||
Settings m_settings;
|
Settings m_settings;
|
||||||
std::string m_program_directory;
|
std::string m_program_directory;
|
||||||
std::string m_user_directory;
|
std::string m_user_directory;
|
||||||
|
|
||||||
u32 m_software_cursor_use_count = 0;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,19 +5,14 @@
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
#include "host_interface.h"
|
||||||
|
#include "resources.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
Log_SetChannel(NamcoGunCon);
|
Log_SetChannel(NamcoGunCon);
|
||||||
|
|
||||||
NamcoGunCon::NamcoGunCon(System* system) : m_system(system)
|
NamcoGunCon::NamcoGunCon(System* system) : m_system(system) {}
|
||||||
{
|
|
||||||
m_system->GetHostInterface()->EnableSoftwareCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
NamcoGunCon::~NamcoGunCon()
|
NamcoGunCon::~NamcoGunCon() = default;
|
||||||
{
|
|
||||||
m_system->GetHostInterface()->DisableSoftwareCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerType NamcoGunCon::GetType() const
|
ControllerType NamcoGunCon::GetType() const
|
||||||
{
|
{
|
||||||
|
@ -226,3 +221,48 @@ u32 NamcoGunCon::StaticGetVibrationMotorCount()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Controller::SettingList NamcoGunCon::StaticGetSettings()
|
||||||
|
{
|
||||||
|
static constexpr std::array<SettingInfo, 2> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
static AxisList StaticGetAxisNames();
|
static AxisList StaticGetAxisNames();
|
||||||
static ButtonList StaticGetButtonNames();
|
static ButtonList StaticGetButtonNames();
|
||||||
static u32 StaticGetVibrationMotorCount();
|
static u32 StaticGetVibrationMotorCount();
|
||||||
|
static SettingList StaticGetSettings();
|
||||||
|
|
||||||
ControllerType GetType() const override;
|
ControllerType GetType() const override;
|
||||||
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
|
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
|
||||||
|
@ -31,6 +32,8 @@ public:
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
bool DoState(StateWrapper& sw) 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 SetAxisState(s32 axis_code, float value) override;
|
||||||
void SetButtonState(s32 button_code, bool pressed) override;
|
void SetButtonState(s32 button_code, bool pressed) override;
|
||||||
|
@ -56,6 +59,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
System* m_system;
|
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
|
// buttons are active low
|
||||||
u16 m_button_state = UINT16_C(0xFFFF);
|
u16 m_button_state = UINT16_C(0xFFFF);
|
||||||
|
|
|
@ -113,8 +113,6 @@ void Settings::Load(SettingsInterface& si)
|
||||||
display_show_vps = si.GetBoolValue("Display", "ShowVPS", false);
|
display_show_vps = si.GetBoolValue("Display", "ShowVPS", false);
|
||||||
display_show_speed = si.GetBoolValue("Display", "ShowSpeed", false);
|
display_show_speed = si.GetBoolValue("Display", "ShowSpeed", false);
|
||||||
video_sync_enabled = si.GetBoolValue("Display", "VSync", true);
|
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_read_thread = si.GetBoolValue("CDROM", "ReadThread", true);
|
||||||
cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", 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", "ShowVPS", display_show_vps);
|
||||||
si.SetBoolValue("Display", "ShowSpeed", display_show_speed);
|
si.SetBoolValue("Display", "ShowSpeed", display_show_speed);
|
||||||
si.SetBoolValue("Display", "VSync", video_sync_enabled);
|
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", "ReadThread", cdrom_read_thread);
|
||||||
si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check);
|
si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check);
|
||||||
|
|
|
@ -97,8 +97,6 @@ struct Settings
|
||||||
bool display_show_vps = false;
|
bool display_show_vps = false;
|
||||||
bool display_show_speed = false;
|
bool display_show_speed = false;
|
||||||
bool video_sync_enabled = true;
|
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_read_thread = true;
|
||||||
bool cdrom_region_check = true;
|
bool cdrom_region_check = true;
|
||||||
|
|
Loading…
Reference in New Issue