mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 16:21:02 +00:00
Qt: Add custom pad configs
Add a custom pad config for every game.
This commit is contained in:
parent
cb78522620
commit
9aa08313e3
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Utilities/types.h"
|
#include "Utilities/types.h"
|
||||||
#include "Utilities/mutex.h"
|
#include "Utilities/mutex.h"
|
||||||
@ -633,8 +633,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emplace the object returned by provider() and return it if no object exists
|
// Emplace the object returned by provider() and return it if no object exists
|
||||||
template <typename T, typename F>
|
template <typename T, typename F, typename... Args>
|
||||||
static auto import(F&& provider) -> decltype(static_cast<std::shared_ptr<T>>(provider()))
|
static auto import(F&& provider, Args&&... args) -> decltype(static_cast<std::shared_ptr<T>>(provider(std::forward<Args>(args)...)))
|
||||||
{
|
{
|
||||||
std::shared_ptr<T> ptr;
|
std::shared_ptr<T> ptr;
|
||||||
{
|
{
|
||||||
@ -644,7 +644,7 @@ public:
|
|||||||
|
|
||||||
if (!cur)
|
if (!cur)
|
||||||
{
|
{
|
||||||
ptr = provider();
|
ptr = provider(std::forward<Args>(args)...);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
@ -662,8 +662,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emplace the object return by provider() (old object will be removed if it exists)
|
// Emplace the object return by provider() (old object will be removed if it exists)
|
||||||
template <typename T, typename F>
|
template <typename T, typename F, typename... Args>
|
||||||
static auto import_always(F&& provider) -> decltype(static_cast<std::shared_ptr<T>>(provider()))
|
static auto import_always(F&& provider, Args&&... args) -> decltype(static_cast<std::shared_ptr<T>>(provider(std::forward<Args>(args)...)))
|
||||||
{
|
{
|
||||||
std::shared_ptr<T> ptr;
|
std::shared_ptr<T> ptr;
|
||||||
std::shared_ptr<void> old;
|
std::shared_ptr<void> old;
|
||||||
@ -672,7 +672,7 @@ public:
|
|||||||
|
|
||||||
auto& cur = g_vec[get_type<T>()];
|
auto& cur = g_vec[get_type<T>()];
|
||||||
|
|
||||||
ptr = provider();
|
ptr = provider(std::forward<Args>(args)...);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "PadHandler.h"
|
#include "PadHandler.h"
|
||||||
|
#include "pad_thread.h"
|
||||||
|
|
||||||
cfg_input g_cfg_input;
|
cfg_input g_cfg_input;
|
||||||
|
|
||||||
@ -268,13 +269,25 @@ bool PadHandlerBase::has_led()
|
|||||||
return b_has_led;
|
return b_has_led;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PadHandlerBase::get_config_dir(pad_handler type)
|
std::string PadHandlerBase::get_config_dir(pad_handler type, const std::string& title_id)
|
||||||
{
|
{
|
||||||
|
if (!title_id.empty())
|
||||||
|
{
|
||||||
|
return Emu.GetCustomInputConfigDir(title_id) + fmt::format("%s", type) + "/";
|
||||||
|
}
|
||||||
return fs::get_config_dir() + "/InputConfigs/" + fmt::format("%s", type) + "/";
|
return fs::get_config_dir() + "/InputConfigs/" + fmt::format("%s", type) + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PadHandlerBase::get_config_filename(int i)
|
std::string PadHandlerBase::get_config_filename(int i, const std::string& title_id)
|
||||||
{
|
{
|
||||||
|
if (!title_id.empty() && fs::is_file(Emu.GetCustomInputConfigPath(title_id)))
|
||||||
|
{
|
||||||
|
const std::string path = Emu.GetCustomInputConfigDir(title_id) + g_cfg_input.player[i]->handler.to_string() + "/" + g_cfg_input.player[i]->profile.to_string() + ".yml";
|
||||||
|
if (fs::is_file(path))
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
return fs::get_config_dir() + "/InputConfigs/" + g_cfg_input.player[i]->handler.to_string() + "/" + g_cfg_input.player[i]->profile.to_string() + ".yml";
|
return fs::get_config_dir() + "/InputConfigs/" + g_cfg_input.player[i]->handler.to_string() + "/" + g_cfg_input.player[i]->profile.to_string() + ".yml";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +299,7 @@ void PadHandlerBase::init_configs()
|
|||||||
{
|
{
|
||||||
if (g_cfg_input.player[i]->handler == m_type)
|
if (g_cfg_input.player[i]->handler == m_type)
|
||||||
{
|
{
|
||||||
init_config(&m_pad_configs[index], get_config_filename(i));
|
init_config(&m_pad_configs[index], get_config_filename(i, pad::g_title_id));
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "Utilities/Config.h"
|
#include "Utilities/Config.h"
|
||||||
#include "Utilities/types.h"
|
#include "Utilities/types.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
|
#include "Emu/GameInfo.h"
|
||||||
|
|
||||||
// TODO: HLE info (constants, structs, etc.) should not be available here
|
// TODO: HLE info (constants, structs, etc.) should not be available here
|
||||||
|
|
||||||
@ -268,7 +269,7 @@ struct cfg_player final : cfg::node
|
|||||||
|
|
||||||
struct cfg_input final : cfg::node
|
struct cfg_input final : cfg::node
|
||||||
{
|
{
|
||||||
const std::string cfg_name = fs::get_config_dir() + "/config_input.yml";
|
std::string cfg_name = fs::get_config_dir() + "/config_input.yml";
|
||||||
|
|
||||||
cfg_player player1{ this, "Player 1 Input", pad_handler::keyboard };
|
cfg_player player1{ this, "Player 1 Input", pad_handler::keyboard };
|
||||||
cfg_player player2{ this, "Player 2 Input", pad_handler::null };
|
cfg_player player2{ this, "Player 2 Input", pad_handler::null };
|
||||||
@ -280,18 +281,32 @@ struct cfg_input final : cfg::node
|
|||||||
|
|
||||||
cfg_player *player[7]{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
|
cfg_player *player[7]{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
|
||||||
|
|
||||||
bool load()
|
bool load(const std::string& title_id = "")
|
||||||
{
|
{
|
||||||
if (fs::file cfg_file{ cfg_name, fs::read })
|
cfg_name = Emu.GetCustomInputConfigPath(title_id);
|
||||||
|
|
||||||
|
if (!fs::is_file(cfg_name))
|
||||||
|
{
|
||||||
|
cfg_name = fs::get_config_dir() + "/config_input.yml";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs::file cfg_file{cfg_name, fs::read})
|
||||||
{
|
{
|
||||||
return from_string(cfg_file.to_string());
|
return from_string(cfg_file.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save()
|
void save(const std::string& title_id = "")
|
||||||
{
|
{
|
||||||
|
if (title_id.empty())
|
||||||
|
{
|
||||||
|
cfg_name = fs::get_config_dir() + "/config_input.yml";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cfg_name = Emu.GetCustomInputConfigPath(title_id);
|
||||||
|
}
|
||||||
fs::file(cfg_name, fs::rewrite).write(to_string());
|
fs::file(cfg_name, fs::rewrite).write(to_string());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -460,8 +475,8 @@ public:
|
|||||||
bool has_deadzones();
|
bool has_deadzones();
|
||||||
bool has_led();
|
bool has_led();
|
||||||
|
|
||||||
static std::string get_config_dir(pad_handler type);
|
static std::string get_config_dir(pad_handler type, const std::string& title_id = "");
|
||||||
static std::string get_config_filename(int i);
|
static std::string get_config_filename(int i, const std::string& title_id = "");
|
||||||
|
|
||||||
virtual bool Init() { return true; }
|
virtual bool Init() { return true; }
|
||||||
PadHandlerBase(pad_handler type = pad_handler::null);
|
PadHandlerBase(pad_handler type = pad_handler::null);
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
|
|
||||||
#include "Utilities/GDBDebugServer.h"
|
#include "Utilities/GDBDebugServer.h"
|
||||||
|
|
||||||
#include "Utilities/sysinfo.h"
|
|
||||||
#include "Utilities/JIT.h"
|
#include "Utilities/JIT.h"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(HAVE_VULKAN)
|
#if defined(_WIN32) || defined(HAVE_VULKAN)
|
||||||
@ -303,31 +302,31 @@ void Emulator::Init()
|
|||||||
|
|
||||||
if (g_cfg.vfs.init_dirs)
|
if (g_cfg.vfs.init_dirs)
|
||||||
{
|
{
|
||||||
fs::create_path(dev_hdd0);
|
fs::create_path(dev_hdd0);
|
||||||
fs::create_path(dev_hdd1);
|
fs::create_path(dev_hdd1);
|
||||||
fs::create_path(dev_usb);
|
fs::create_path(dev_usb);
|
||||||
fs::create_dir(dev_hdd0 + "game/");
|
fs::create_dir(dev_hdd0 + "game/");
|
||||||
fs::create_dir(dev_hdd0 + "game/TEST12345/");
|
fs::create_dir(dev_hdd0 + "game/TEST12345/");
|
||||||
fs::create_dir(dev_hdd0 + "game/TEST12345/USRDIR/");
|
fs::create_dir(dev_hdd0 + "game/TEST12345/USRDIR/");
|
||||||
fs::create_dir(dev_hdd0 + "game/.locks/");
|
fs::create_dir(dev_hdd0 + "game/.locks/");
|
||||||
fs::create_dir(dev_hdd0 + "home/");
|
fs::create_dir(dev_hdd0 + "home/");
|
||||||
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/");
|
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/");
|
||||||
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/exdata/");
|
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/exdata/");
|
||||||
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/savedata/");
|
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/savedata/");
|
||||||
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/trophy/");
|
fs::create_dir(dev_hdd0 + "home/" + m_usr + "/trophy/");
|
||||||
fs::write_file(dev_hdd0 + "home/" + m_usr + "/localusername", fs::create + fs::excl + fs::write, "User"s);
|
fs::write_file(dev_hdd0 + "home/" + m_usr + "/localusername", fs::create + fs::excl + fs::write, "User"s);
|
||||||
fs::create_dir(dev_hdd0 + "disc/");
|
fs::create_dir(dev_hdd0 + "disc/");
|
||||||
fs::create_dir(dev_hdd0 + "savedata/");
|
fs::create_dir(dev_hdd0 + "savedata/");
|
||||||
fs::create_dir(dev_hdd0 + "savedata/vmc/");
|
fs::create_dir(dev_hdd0 + "savedata/vmc/");
|
||||||
fs::create_dir(dev_hdd1 + "cache/");
|
fs::create_dir(dev_hdd1 + "cache/");
|
||||||
fs::create_dir(dev_hdd1 + "game/");
|
fs::create_dir(dev_hdd1 + "game/");
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::create_path(fs::get_cache_dir() + "shaderlog/");
|
fs::create_path(fs::get_cache_dir() + "shaderlog/");
|
||||||
fs::create_path(fs::get_config_dir() + "captures/");
|
fs::create_path(fs::get_config_dir() + "captures/");
|
||||||
|
|
||||||
#ifdef WITH_GDB_DEBUGGER
|
#ifdef WITH_GDB_DEBUGGER
|
||||||
LOG_SUCCESS(GENERAL, "GDB debug server will be started and listening on %d upon emulator boot", (int) g_cfg.misc.gdb_server_port);
|
LOG_SUCCESS(GENERAL, "GDB debug server will be started and listening on %d upon emulator boot", (int)g_cfg.misc.gdb_server_port);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initialize patch engine
|
// Initialize patch engine
|
||||||
@ -506,7 +505,7 @@ bool Emulator::BootRsxCapture(const std::string& path)
|
|||||||
GetCallbacks().on_ready();
|
GetCallbacks().on_ready();
|
||||||
|
|
||||||
auto gsrender = fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render);
|
auto gsrender = fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render);
|
||||||
auto padhandler = fxm::import<pad_thread>(Emu.GetCallbacks().get_pad_handler);
|
auto padhandler = fxm::import<pad_thread>(Emu.GetCallbacks().get_pad_handler, "");
|
||||||
|
|
||||||
if (gsrender.get() == nullptr || padhandler.get() == nullptr)
|
if (gsrender.get() == nullptr || padhandler.get() == nullptr)
|
||||||
return false;
|
return false;
|
||||||
@ -727,6 +726,22 @@ std::string Emulator::GetCustomConfigPath(const std::string& title_id, bool get_
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Emulator::GetCustomInputConfigDir(const std::string& title_id)
|
||||||
|
{
|
||||||
|
// Notice: the extra folder for each title id may be removed at a later stage
|
||||||
|
// Warning: make sure to change any function that removes this directory as well
|
||||||
|
#ifdef _WIN32
|
||||||
|
return fs::get_config_dir() + "config/custom_input_configs/" + title_id + "/";
|
||||||
|
#else
|
||||||
|
return fs::get_config_dir() + "custom_input_configs/" + title_id + "/";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Emulator::GetCustomInputConfigPath(const std::string& title_id)
|
||||||
|
{
|
||||||
|
return GetCustomInputConfigDir(title_id) + "/config_input_" + title_id + ".yml";
|
||||||
|
}
|
||||||
|
|
||||||
void Emulator::SetForceBoot(bool force_boot)
|
void Emulator::SetForceBoot(bool force_boot)
|
||||||
{
|
{
|
||||||
m_force_boot = force_boot;
|
m_force_boot = force_boot;
|
||||||
@ -1343,7 +1358,7 @@ void Emulator::Load(bool add_only, bool force_global_config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
|
fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
|
||||||
fxm::import<pad_thread>(Emu.GetCallbacks().get_pad_handler);
|
fxm::import<pad_thread>(Emu.GetCallbacks().get_pad_handler, m_title_id);
|
||||||
network_thread_init();
|
network_thread_init();
|
||||||
}
|
}
|
||||||
else if (ppu_prx.open(elf_file) == elf_error::ok)
|
else if (ppu_prx.open(elf_file) == elf_error::ok)
|
||||||
|
@ -189,12 +189,12 @@ struct EmuCallbacks
|
|||||||
std::function<void()> on_stop;
|
std::function<void()> on_stop;
|
||||||
std::function<void()> on_ready;
|
std::function<void()> on_ready;
|
||||||
std::function<void()> exit;
|
std::function<void()> exit;
|
||||||
std::function<void()> reset_pads;
|
std::function<void(const std::string&)> reset_pads;
|
||||||
std::function<void(bool)> enable_pads;
|
std::function<void(bool)> enable_pads;
|
||||||
std::function<void(s32, s32)> handle_taskbar_progress; // (type, value) type: 0 for reset, 1 for increment, 2 for set_limit
|
std::function<void(s32, s32)> handle_taskbar_progress; // (type, value) type: 0 for reset, 1 for increment, 2 for set_limit
|
||||||
std::function<std::shared_ptr<class KeyboardHandlerBase>()> get_kb_handler;
|
std::function<std::shared_ptr<class KeyboardHandlerBase>()> get_kb_handler;
|
||||||
std::function<std::shared_ptr<class MouseHandlerBase>()> get_mouse_handler;
|
std::function<std::shared_ptr<class MouseHandlerBase>()> get_mouse_handler;
|
||||||
std::function<std::shared_ptr<class pad_thread>()> get_pad_handler;
|
std::function<std::shared_ptr<class pad_thread>(const std::string&)> get_pad_handler;
|
||||||
std::function<std::unique_ptr<class GSFrameBase>()> get_gs_frame;
|
std::function<std::unique_ptr<class GSFrameBase>()> get_gs_frame;
|
||||||
std::function<std::shared_ptr<class GSRender>()> get_gs_render;
|
std::function<std::shared_ptr<class GSRender>()> get_gs_render;
|
||||||
std::function<std::shared_ptr<class AudioBackend>()> get_audio;
|
std::function<std::shared_ptr<class AudioBackend>()> get_audio;
|
||||||
@ -326,6 +326,8 @@ public:
|
|||||||
|
|
||||||
static std::string GetCustomConfigDir();
|
static std::string GetCustomConfigDir();
|
||||||
static std::string GetCustomConfigPath(const std::string& title_id, bool get_deprecated_path = false);
|
static std::string GetCustomConfigPath(const std::string& title_id, bool get_deprecated_path = false);
|
||||||
|
static std::string GetCustomInputConfigDir(const std::string& title_id);
|
||||||
|
static std::string GetCustomInputConfigPath(const std::string& title_id);
|
||||||
|
|
||||||
void SetForceBoot(bool force_boot);
|
void SetForceBoot(bool force_boot);
|
||||||
|
|
||||||
|
BIN
rpcs3/Icons/combo_config_bordered.png
Normal file
BIN
rpcs3/Icons/combo_config_bordered.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
BIN
rpcs3/Icons/controllers_2.png
Normal file
BIN
rpcs3/Icons/controllers_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -14,6 +14,7 @@ namespace pad
|
|||||||
{
|
{
|
||||||
atomic_t<pad_thread*> g_current = nullptr;
|
atomic_t<pad_thread*> g_current = nullptr;
|
||||||
std::recursive_mutex g_pad_mutex;
|
std::recursive_mutex g_pad_mutex;
|
||||||
|
std::string g_title_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pad_setting
|
struct pad_setting
|
||||||
@ -23,8 +24,9 @@ struct pad_setting
|
|||||||
u32 device_type;
|
u32 device_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
pad_thread::pad_thread(void *_curthread, void *_curwindow) : curthread(_curthread), curwindow(_curwindow)
|
pad_thread::pad_thread(void *_curthread, void *_curwindow, const std::string& title_id) : curthread(_curthread), curwindow(_curwindow)
|
||||||
{
|
{
|
||||||
|
pad::g_title_id = title_id;
|
||||||
Init();
|
Init();
|
||||||
|
|
||||||
thread = std::make_shared<std::thread>(&pad_thread::ThreadFunc, this);
|
thread = std::make_shared<std::thread>(&pad_thread::ThreadFunc, this);
|
||||||
@ -65,7 +67,7 @@ void pad_thread::Init()
|
|||||||
|
|
||||||
handlers.clear();
|
handlers.clear();
|
||||||
|
|
||||||
g_cfg_input.load();
|
g_cfg_input.load(pad::g_title_id);
|
||||||
|
|
||||||
std::shared_ptr<keyboard_pad_handler> keyptr;
|
std::shared_ptr<keyboard_pad_handler> keyptr;
|
||||||
|
|
||||||
@ -142,8 +144,9 @@ void pad_thread::SetRumble(const u32 pad, u8 largeMotor, bool smallMotor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pad_thread::Reset()
|
void pad_thread::Reset(const std::string& title_id)
|
||||||
{
|
{
|
||||||
|
pad::g_title_id = title_id;
|
||||||
reset = active.load();
|
reset = active.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -16,14 +16,14 @@ struct PadInfo
|
|||||||
class pad_thread
|
class pad_thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
pad_thread(void *_curthread, void *_curwindow); // void * instead of QThread * and QWindow * because of include in emucore
|
pad_thread(void* _curthread, void* _curwindow, const std::string& title_id = ""); // void * instead of QThread * and QWindow * because of include in emucore
|
||||||
~pad_thread();
|
~pad_thread();
|
||||||
|
|
||||||
PadInfo& GetInfo() { return m_info; }
|
PadInfo& GetInfo() { return m_info; }
|
||||||
auto& GetPads() { return m_pads; }
|
auto& GetPads() { return m_pads; }
|
||||||
void SetRumble(const u32 pad, u8 largeMotor, bool smallMotor);
|
void SetRumble(const u32 pad, u8 largeMotor, bool smallMotor);
|
||||||
void Init();
|
void Init();
|
||||||
void Reset();
|
void Reset(const std::string& title_id = "");
|
||||||
void SetEnabled(bool enabled);
|
void SetEnabled(bool enabled);
|
||||||
void SetIntercepted(bool intercepted);
|
void SetIntercepted(bool intercepted);
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ namespace pad
|
|||||||
{
|
{
|
||||||
extern atomic_t<pad_thread*> g_current;
|
extern atomic_t<pad_thread*> g_current;
|
||||||
extern std::recursive_mutex g_pad_mutex;
|
extern std::recursive_mutex g_pad_mutex;
|
||||||
|
extern std::string g_title_id;
|
||||||
|
|
||||||
static inline class pad_thread* get_current_handler()
|
static inline class pad_thread* get_current_handler()
|
||||||
{
|
{
|
||||||
|
@ -18,5 +18,7 @@
|
|||||||
<file>Icons/open.png</file>
|
<file>Icons/open.png</file>
|
||||||
<file>Icons/custom_config.png</file>
|
<file>Icons/custom_config.png</file>
|
||||||
<file>Icons/custom_config_2.png</file>
|
<file>Icons/custom_config_2.png</file>
|
||||||
|
<file>Icons/controllers_2.png</file>
|
||||||
|
<file>Icons/combo_config_bordered.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -142,9 +142,9 @@ void rpcs3_app::InitializeCallbacks()
|
|||||||
RequestCallAfter(std::move(func));
|
RequestCallAfter(std::move(func));
|
||||||
};
|
};
|
||||||
|
|
||||||
callbacks.reset_pads = [this]()
|
callbacks.reset_pads = [this](const std::string& title_id = "")
|
||||||
{
|
{
|
||||||
pad::get_current_handler()->Reset();
|
pad::get_current_handler()->Reset(title_id);
|
||||||
};
|
};
|
||||||
callbacks.enable_pads = [this](bool enable)
|
callbacks.enable_pads = [this](bool enable)
|
||||||
{
|
{
|
||||||
@ -183,9 +183,9 @@ void rpcs3_app::InitializeCallbacks()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
callbacks.get_pad_handler = [this]() -> std::shared_ptr<pad_thread>
|
callbacks.get_pad_handler = [this](const std::string& title_id) -> std::shared_ptr<pad_thread>
|
||||||
{
|
{
|
||||||
return std::make_shared<pad_thread>(thread(), gameWindow);
|
return std::make_shared<pad_thread>(thread(), gameWindow, title_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
callbacks.get_gs_frame = [this]() -> std::unique_ptr<GSFrameBase>
|
callbacks.get_gs_frame = [this]() -> std::unique_ptr<GSFrameBase>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "game_list_frame.h"
|
#include "game_list_frame.h"
|
||||||
#include "qt_utils.h"
|
#include "qt_utils.h"
|
||||||
#include "settings_dialog.h"
|
#include "settings_dialog.h"
|
||||||
|
#include "pad_settings_dialog.h"
|
||||||
#include "table_item_delegate.h"
|
#include "table_item_delegate.h"
|
||||||
#include "custom_table_widget_item.h"
|
#include "custom_table_widget_item.h"
|
||||||
#include "input_dialog.h"
|
#include "input_dialog.h"
|
||||||
@ -114,6 +115,10 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
|
|||||||
QMenu* configure = new QMenu(this);
|
QMenu* configure = new QMenu(this);
|
||||||
configure->addActions(m_columnActs);
|
configure->addActions(m_columnActs);
|
||||||
configure->exec(mapToGlobal(pos));
|
configure->exec(mapToGlobal(pos));
|
||||||
|
|
||||||
|
QMenu* pad_configure = new QMenu(this);
|
||||||
|
pad_configure->addActions(m_columnActs);
|
||||||
|
pad_configure->exec(mapToGlobal(pos));
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_xgrid, &QTableWidget::itemDoubleClicked, this, &game_list_frame::doubleClickedSlot);
|
connect(m_xgrid, &QTableWidget::itemDoubleClicked, this, &game_list_frame::doubleClickedSlot);
|
||||||
@ -471,12 +476,14 @@ void game_list_frame::Refresh(const bool fromDrive, const bool scrollAfter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto compat = m_game_compat->GetCompatibility(game.serial);
|
const auto compat = m_game_compat->GetCompatibility(game.serial);
|
||||||
|
|
||||||
const bool hasCustomConfig = fs::is_file(Emu.GetCustomConfigPath(game.serial)) || fs::is_file(Emu.GetCustomConfigPath(game.serial, true));
|
const bool hasCustomConfig = fs::is_file(Emu.GetCustomConfigPath(game.serial)) || fs::is_file(Emu.GetCustomConfigPath(game.serial, true));
|
||||||
|
const bool hasCustomPadConfig = fs::is_file(Emu.GetCustomInputConfigPath(game.serial));
|
||||||
|
|
||||||
const QColor color = getGridCompatibilityColor(compat.color);
|
const QColor color = getGridCompatibilityColor(compat.color);
|
||||||
const QPixmap pxmap = PaintedPixmap(img, hasCustomConfig, color);
|
const QPixmap pxmap = PaintedPixmap(img, hasCustomConfig, hasCustomPadConfig, color);
|
||||||
|
|
||||||
m_game_data.push_back(game_info(new gui_game_info{ game, compat, img, pxmap, hasCustomConfig }));
|
m_game_data.push_back(game_info(new gui_game_info{game, compat, img, pxmap, hasCustomConfig, hasCustomPadConfig}));
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
@ -695,6 +702,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
|
|||||||
}
|
}
|
||||||
myMenu.addAction(boot);
|
myMenu.addAction(boot);
|
||||||
QAction* configure = myMenu.addAction(tr("&Configure"));
|
QAction* configure = myMenu.addAction(tr("&Configure"));
|
||||||
|
QAction* pad_configure = myMenu.addAction(tr("&Configure pads"));
|
||||||
QAction* createPPUCache = myMenu.addAction(tr("&Create PPU Cache"));
|
QAction* createPPUCache = myMenu.addAction(tr("&Create PPU Cache"));
|
||||||
myMenu.addSeparator();
|
myMenu.addSeparator();
|
||||||
QAction* renameTitle = myMenu.addAction(tr("&Rename In Game List"));
|
QAction* renameTitle = myMenu.addAction(tr("&Rename In Game List"));
|
||||||
@ -709,9 +717,20 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
|
|||||||
QAction* remove_custom_config = remove_menu->addAction(tr("&Remove Custom Configuration"));
|
QAction* remove_custom_config = remove_menu->addAction(tr("&Remove Custom Configuration"));
|
||||||
connect(remove_custom_config, &QAction::triggered, [=]()
|
connect(remove_custom_config, &QAction::triggered, [=]()
|
||||||
{
|
{
|
||||||
if (RemoveCustomConfiguration(currGame.serial, true))
|
if (RemoveCustomConfiguration(currGame.serial, gameinfo, true))
|
||||||
{
|
{
|
||||||
ShowCustomConfigIcon(item, false);
|
ShowCustomConfigIcon(item, config::type::emu);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (gameinfo->hasCustomPadConfig)
|
||||||
|
{
|
||||||
|
QAction* remove_custom_pad_config = remove_menu->addAction(tr("&Remove Custom Pad Configuration"));
|
||||||
|
connect(remove_custom_pad_config, &QAction::triggered, [=]()
|
||||||
|
{
|
||||||
|
if (RemoveCustomPadConfiguration(currGame.serial, gameinfo, true))
|
||||||
|
{
|
||||||
|
ShowCustomConfigIcon(item, config::type::pad);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -775,7 +794,33 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
|
|||||||
settings_dialog dlg(m_gui_settings, m_emu_settings, 0, this, &currGame);
|
settings_dialog dlg(m_gui_settings, m_emu_settings, 0, this, &currGame);
|
||||||
if (dlg.exec() == QDialog::Accepted && !gameinfo->hasCustomConfig)
|
if (dlg.exec() == QDialog::Accepted && !gameinfo->hasCustomConfig)
|
||||||
{
|
{
|
||||||
ShowCustomConfigIcon(item, true);
|
gameinfo->hasCustomConfig = true;
|
||||||
|
ShowCustomConfigIcon(item, config::type::emu);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(pad_configure, &QAction::triggered, [=]
|
||||||
|
{
|
||||||
|
if (!Emu.IsStopped())
|
||||||
|
{
|
||||||
|
Emu.GetCallbacks().enable_pads(false);
|
||||||
|
}
|
||||||
|
pad_settings_dialog dlg(this, &currGame);
|
||||||
|
connect(&dlg, &QDialog::finished, [this](int/* result*/)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Emu.GetCallbacks().reset_pads(Emu.GetTitleID());
|
||||||
|
});
|
||||||
|
if (dlg.exec() == QDialog::Accepted && !gameinfo->hasCustomPadConfig)
|
||||||
|
{
|
||||||
|
gameinfo->hasCustomPadConfig = true;
|
||||||
|
ShowCustomConfigIcon(item, config::type::pad);
|
||||||
|
}
|
||||||
|
if (!Emu.IsStopped())
|
||||||
|
{
|
||||||
|
Emu.GetCallbacks().enable_pads(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(hide_serial, &QAction::triggered, [=](bool checked)
|
connect(hide_serial, &QAction::triggered, [=](bool checked)
|
||||||
@ -801,7 +846,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox* mb = new QMessageBox(QMessageBox::Question, tr("Confirm %1 Removal").arg(qstr(currGame.category)), tr("Permanently remove %0 from drive?\nPath: %1").arg(name).arg(qstr(currGame.path)), QMessageBox::Yes | QMessageBox::No, this);
|
QMessageBox* mb = new QMessageBox(QMessageBox::Question, tr("Confirm %1 Removal").arg(qstr(currGame.category)), tr("Permanently remove %0 from drive?\nPath: %1").arg(name).arg(qstr(currGame.path)), QMessageBox::Yes | QMessageBox::No, this);
|
||||||
mb->setCheckBox(new QCheckBox(tr("Remove caches and custom config")));
|
mb->setCheckBox(new QCheckBox(tr("Remove caches and custom configs")));
|
||||||
mb->deleteLater();
|
mb->deleteLater();
|
||||||
if (mb->exec() == QMessageBox::Yes)
|
if (mb->exec() == QMessageBox::Yes)
|
||||||
{
|
{
|
||||||
@ -811,6 +856,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
|
|||||||
RemovePPUCache(cache_base_dir);
|
RemovePPUCache(cache_base_dir);
|
||||||
RemoveSPUCache(cache_base_dir);
|
RemoveSPUCache(cache_base_dir);
|
||||||
RemoveCustomConfiguration(currGame.serial);
|
RemoveCustomConfiguration(currGame.serial);
|
||||||
|
RemoveCustomPadConfiguration(currGame.serial);
|
||||||
}
|
}
|
||||||
fs::remove_all(currGame.path);
|
fs::remove_all(currGame.path);
|
||||||
m_game_data.erase(std::remove(m_game_data.begin(), m_game_data.end(), gameinfo), m_game_data.end());
|
m_game_data.erase(std::remove(m_game_data.begin(), m_game_data.end(), gameinfo), m_game_data.end());
|
||||||
@ -933,7 +979,7 @@ bool game_list_frame::CreatePPUCache(const std::string& path)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, bool is_interactive)
|
bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, game_info game, bool is_interactive)
|
||||||
{
|
{
|
||||||
const std::string config_path_new = Emu.GetCustomConfigPath(title_id);
|
const std::string config_path_new = Emu.GetCustomConfigPath(title_id);
|
||||||
const std::string config_path_old = Emu.GetCustomConfigPath(title_id, true);
|
const std::string config_path_old = Emu.GetCustomConfigPath(title_id, true);
|
||||||
@ -954,6 +1000,10 @@ bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, boo
|
|||||||
}
|
}
|
||||||
if (fs::remove_file(path))
|
if (fs::remove_file(path))
|
||||||
{
|
{
|
||||||
|
if (game)
|
||||||
|
{
|
||||||
|
game->hasCustomConfig = false;
|
||||||
|
}
|
||||||
LOG_SUCCESS(GENERAL, "Removed configuration file: %s", path);
|
LOG_SUCCESS(GENERAL, "Removed configuration file: %s", path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -971,6 +1021,41 @@ bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, boo
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game_list_frame::RemoveCustomPadConfiguration(const std::string& title_id, game_info game, bool is_interactive)
|
||||||
|
{
|
||||||
|
const std::string config_dir = Emu.GetCustomInputConfigDir(title_id);
|
||||||
|
|
||||||
|
if (!fs::is_dir(config_dir))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), (!Emu.IsStopped() && Emu.GetTitleID() == title_id)
|
||||||
|
? tr("Remove custom pad configuration?\nYour configuration will revert to the global pad settings.")
|
||||||
|
: tr("Remove custom pad configuration?")) != QMessageBox::Yes)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (QDir(qstr(config_dir)).removeRecursively())
|
||||||
|
{
|
||||||
|
if (game)
|
||||||
|
{
|
||||||
|
game->hasCustomPadConfig = false;
|
||||||
|
}
|
||||||
|
if (!Emu.IsStopped() && Emu.GetTitleID() == title_id)
|
||||||
|
{
|
||||||
|
Emu.GetCallbacks().enable_pads(false);
|
||||||
|
Emu.GetCallbacks().reset_pads(title_id);
|
||||||
|
Emu.GetCallbacks().enable_pads(true);
|
||||||
|
}
|
||||||
|
LOG_NOTICE(GENERAL, "Removed pad configuration directory: %s", config_dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (is_interactive)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Warning!"), tr("Failed to completely remove pad configuration directory!"));
|
||||||
|
LOG_FATAL(GENERAL, "Failed to completely remove pad configuration directory: %s\nError: %s", config_dir, fs::g_tls_error);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool game_list_frame::RemoveShadersCache(const std::string& base_dir, bool is_interactive)
|
bool game_list_frame::RemoveShadersCache(const std::string& base_dir, bool is_interactive)
|
||||||
{
|
{
|
||||||
if (!fs::is_dir(base_dir))
|
if (!fs::is_dir(base_dir))
|
||||||
@ -1260,6 +1345,52 @@ void game_list_frame::BatchRemoveCustomConfigurations()
|
|||||||
Refresh(true);
|
Refresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game_list_frame::BatchRemoveCustomPadConfigurations()
|
||||||
|
{
|
||||||
|
std::set<std::string> serials;
|
||||||
|
for (const auto& game : m_game_data)
|
||||||
|
{
|
||||||
|
if (game->hasCustomPadConfig && !serials.count(game->info.serial))
|
||||||
|
{
|
||||||
|
serials.emplace(game->info.serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const u32 total = serials.size();
|
||||||
|
|
||||||
|
if (total == 0)
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, tr("Custom Pad Configuration Batch Removal"), tr("No files found"), QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress_dialog* pdlg = new progress_dialog(tr("Removing all custom pad configurations"), tr("Cancel"), 0, total, this);
|
||||||
|
pdlg->setWindowTitle(tr("Custom Pad Configuration Batch Removal"));
|
||||||
|
pdlg->setAutoClose(false);
|
||||||
|
pdlg->setAutoReset(false);
|
||||||
|
pdlg->show();
|
||||||
|
|
||||||
|
u32 removed = 0;
|
||||||
|
for (const auto& serial : serials)
|
||||||
|
{
|
||||||
|
if (pdlg->wasCanceled())
|
||||||
|
{
|
||||||
|
LOG_NOTICE(GENERAL, "Custom Pad Configuration Batch Removal was canceled. %d/%d custom pad configurations cleared", removed, total);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QApplication::processEvents();
|
||||||
|
|
||||||
|
if (RemoveCustomPadConfiguration(serial))
|
||||||
|
{
|
||||||
|
pdlg->SetValue(++removed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdlg->setLabelText(tr("%0/%1 custom pad configurations cleared").arg(removed).arg(total));
|
||||||
|
pdlg->setCancelButtonText(tr("OK"));
|
||||||
|
QApplication::beep();
|
||||||
|
Refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
void game_list_frame::BatchRemoveShaderCaches()
|
void game_list_frame::BatchRemoveShaderCaches()
|
||||||
{
|
{
|
||||||
std::set<std::string> serials;
|
std::set<std::string> serials;
|
||||||
@ -1302,7 +1433,7 @@ void game_list_frame::BatchRemoveShaderCaches()
|
|||||||
QApplication::beep();
|
QApplication::beep();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap game_list_frame::PaintedPixmap(const QImage& img, bool paint_config_icon, const QColor& compatibility_color)
|
QPixmap game_list_frame::PaintedPixmap(const QImage& img, bool paint_config_icon, bool paint_pad_config_icon, const QColor& compatibility_color)
|
||||||
{
|
{
|
||||||
const int device_pixel_ratio = devicePixelRatio();
|
const int device_pixel_ratio = devicePixelRatio();
|
||||||
const QSize original_size = img.size();
|
const QSize original_size = img.size();
|
||||||
@ -1318,11 +1449,26 @@ QPixmap game_list_frame::PaintedPixmap(const QImage& img, bool paint_config_icon
|
|||||||
painter.drawImage(QPoint(0, 0), img);
|
painter.drawImage(QPoint(0, 0), img);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paint_config_icon && !m_isListLayout)
|
if (!m_isListLayout && (paint_config_icon || paint_pad_config_icon))
|
||||||
{
|
{
|
||||||
const int width = original_size.width() * 0.2;
|
const int width = original_size.width() * 0.2;
|
||||||
const QPoint origin = QPoint(original_size.width() - width, 0);
|
const QPoint origin = QPoint(original_size.width() - width, 0);
|
||||||
QImage custom_config_icon(":/Icons/custom_config_2.png");
|
QString icon_path;
|
||||||
|
|
||||||
|
if (paint_config_icon && paint_pad_config_icon)
|
||||||
|
{
|
||||||
|
icon_path = ":/Icons/combo_config_bordered.png";
|
||||||
|
}
|
||||||
|
else if (paint_config_icon)
|
||||||
|
{
|
||||||
|
icon_path = ":/Icons/custom_config_2.png";
|
||||||
|
}
|
||||||
|
else if (paint_pad_config_icon)
|
||||||
|
{
|
||||||
|
icon_path = ":/Icons/controllers_2.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage custom_config_icon(icon_path);
|
||||||
custom_config_icon.setDevicePixelRatio(device_pixel_ratio);
|
custom_config_icon.setDevicePixelRatio(device_pixel_ratio);
|
||||||
painter.drawImage(origin, custom_config_icon.scaled(QSize(width, width) * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
|
painter.drawImage(origin, custom_config_icon.scaled(QSize(width, width) * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
|
||||||
}
|
}
|
||||||
@ -1342,7 +1488,7 @@ QPixmap game_list_frame::PaintedPixmap(const QImage& img, bool paint_config_icon
|
|||||||
return QPixmap::fromImage(image.scaled(m_Icon_Size * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
|
return QPixmap::fromImage(image.scaled(m_Icon_Size * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list_frame::ShowCustomConfigIcon(QTableWidgetItem* item, bool enabled)
|
void game_list_frame::ShowCustomConfigIcon(QTableWidgetItem* item, config::type type)
|
||||||
{
|
{
|
||||||
auto game = GetGameInfoFromItem(item);
|
auto game = GetGameInfoFromItem(item);
|
||||||
if (game == nullptr)
|
if (game == nullptr)
|
||||||
@ -1350,24 +1496,22 @@ void game_list_frame::ShowCustomConfigIcon(QTableWidgetItem* item, bool enabled)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
game->hasCustomConfig = enabled;
|
|
||||||
const QColor color = getGridCompatibilityColor(game->compat.color);
|
|
||||||
game->pxmap = PaintedPixmap(game->icon, enabled, color);
|
|
||||||
|
|
||||||
if (!m_isListLayout)
|
if (!m_isListLayout)
|
||||||
{
|
{
|
||||||
|
const QColor color = getGridCompatibilityColor(game->compat.color);
|
||||||
|
game->pxmap = PaintedPixmap(game->icon, game->hasCustomConfig, game->hasCustomPadConfig, color);
|
||||||
int r = m_xgrid->currentItem()->row(), c = m_xgrid->currentItem()->column();
|
int r = m_xgrid->currentItem()->row(), c = m_xgrid->currentItem()->column();
|
||||||
m_xgrid->addItem(game->pxmap, qstr(game->info.name).simplified(), r, c);
|
m_xgrid->addItem(game->pxmap, qstr(game->info.name).simplified(), r, c);
|
||||||
m_xgrid->item(r, c)->setData(gui::game_role, QVariant::fromValue(game));
|
m_xgrid->item(r, c)->setData(gui::game_role, QVariant::fromValue(game));
|
||||||
}
|
}
|
||||||
else if (enabled)
|
else if (game->hasCustomConfig && game->hasCustomPadConfig)
|
||||||
{
|
m_gameList->item(item->row(), gui::column_name)->setIcon(QIcon(":/Icons/combo_config_bordered.png"));
|
||||||
|
else if (game->hasCustomConfig)
|
||||||
m_gameList->item(item->row(), gui::column_name)->setIcon(QIcon(":/Icons/custom_config.png"));
|
m_gameList->item(item->row(), gui::column_name)->setIcon(QIcon(":/Icons/custom_config.png"));
|
||||||
}
|
else if (game->hasCustomPadConfig)
|
||||||
|
m_gameList->item(item->row(), gui::column_name)->setIcon(QIcon(":/Icons/controllers.png"));
|
||||||
else
|
else
|
||||||
{
|
|
||||||
m_gameList->setItem(item->row(), gui::column_name, new custom_table_widget_item(game->info.name));
|
m_gameList->setItem(item->row(), gui::column_name, new custom_table_widget_item(game->info.name));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list_frame::ResizeIcons(const int& sliderPos)
|
void game_list_frame::ResizeIcons(const int& sliderPos)
|
||||||
@ -1395,7 +1539,7 @@ void game_list_frame::RepaintIcons(const bool& fromSettings)
|
|||||||
for (auto& game : m_game_data)
|
for (auto& game : m_game_data)
|
||||||
{
|
{
|
||||||
QColor color = getGridCompatibilityColor(game->compat.color);
|
QColor color = getGridCompatibilityColor(game->compat.color);
|
||||||
game->pxmap = PaintedPixmap(game->icon, game->hasCustomConfig, color);
|
game->pxmap = PaintedPixmap(game->icon, game->hasCustomConfig, game->hasCustomPadConfig, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
Refresh();
|
Refresh();
|
||||||
@ -1560,10 +1704,18 @@ int game_list_frame::PopulateGameList()
|
|||||||
|
|
||||||
// Title
|
// Title
|
||||||
custom_table_widget_item* title_item = new custom_table_widget_item(title);
|
custom_table_widget_item* title_item = new custom_table_widget_item(title);
|
||||||
if (game->hasCustomConfig)
|
if (game->hasCustomConfig && game->hasCustomPadConfig)
|
||||||
|
{
|
||||||
|
title_item->setIcon(QIcon(":/Icons/combo_config_bordered.png"));
|
||||||
|
}
|
||||||
|
else if (game->hasCustomConfig)
|
||||||
{
|
{
|
||||||
title_item->setIcon(QIcon(":/Icons/custom_config.png"));
|
title_item->setIcon(QIcon(":/Icons/custom_config.png"));
|
||||||
}
|
}
|
||||||
|
else if (game->hasCustomPadConfig)
|
||||||
|
{
|
||||||
|
title_item->setIcon(QIcon(":/Icons/controllers.png"));
|
||||||
|
}
|
||||||
|
|
||||||
// Serial
|
// Serial
|
||||||
custom_table_widget_item* serial_item = new custom_table_widget_item(game->info.serial);
|
custom_table_widget_item* serial_item = new custom_table_widget_item(game->info.serial);
|
||||||
|
@ -31,6 +31,15 @@ enum Category
|
|||||||
Others,
|
Others,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace config
|
||||||
|
{
|
||||||
|
enum class type
|
||||||
|
{
|
||||||
|
emu,
|
||||||
|
pad
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace category // (see PARAM.SFO in psdevwiki.com) TODO: Disc Categories
|
namespace category // (see PARAM.SFO in psdevwiki.com) TODO: Disc Categories
|
||||||
{
|
{
|
||||||
// PS3 bootable
|
// PS3 bootable
|
||||||
@ -171,6 +180,7 @@ struct gui_game_info
|
|||||||
QImage icon;
|
QImage icon;
|
||||||
QPixmap pxmap;
|
QPixmap pxmap;
|
||||||
bool hasCustomConfig;
|
bool hasCustomConfig;
|
||||||
|
bool hasCustomPadConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<gui_game_info> game_info;
|
typedef std::shared_ptr<gui_game_info> game_info;
|
||||||
@ -215,6 +225,7 @@ public Q_SLOTS:
|
|||||||
void BatchRemovePPUCaches();
|
void BatchRemovePPUCaches();
|
||||||
void BatchRemoveSPUCaches();
|
void BatchRemoveSPUCaches();
|
||||||
void BatchRemoveCustomConfigurations();
|
void BatchRemoveCustomConfigurations();
|
||||||
|
void BatchRemoveCustomPadConfigurations();
|
||||||
void BatchRemoveShaderCaches();
|
void BatchRemoveShaderCaches();
|
||||||
void SetListMode(const bool& isList);
|
void SetListMode(const bool& isList);
|
||||||
void SetSearchText(const QString& text);
|
void SetSearchText(const QString& text);
|
||||||
@ -234,9 +245,9 @@ protected:
|
|||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
bool eventFilter(QObject *object, QEvent *event) override;
|
bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
private:
|
private:
|
||||||
QPixmap PaintedPixmap(const QImage& img, bool paint_config_icon = false, const QColor& color = QColor());
|
QPixmap PaintedPixmap(const QImage& img, bool paint_config_icon = false, bool paint_pad_config_icon = false, const QColor& color = QColor());
|
||||||
QColor getGridCompatibilityColor(const QString& string);
|
QColor getGridCompatibilityColor(const QString& string);
|
||||||
void ShowCustomConfigIcon(QTableWidgetItem* item, bool enabled);
|
void ShowCustomConfigIcon(QTableWidgetItem* item, config::type type);
|
||||||
void PopulateGameGrid(int maxCols, const QSize& image_size, const QColor& image_color);
|
void PopulateGameGrid(int maxCols, const QSize& image_size, const QColor& image_color);
|
||||||
bool IsEntryVisible(const game_info& game);
|
bool IsEntryVisible(const game_info& game);
|
||||||
void SortGameList();
|
void SortGameList();
|
||||||
@ -244,7 +255,8 @@ private:
|
|||||||
int PopulateGameList();
|
int PopulateGameList();
|
||||||
bool SearchMatchesApp(const std::string& name, const std::string& serial);
|
bool SearchMatchesApp(const std::string& name, const std::string& serial);
|
||||||
|
|
||||||
bool RemoveCustomConfiguration(const std::string& base_dir, bool is_interactive = false);
|
bool RemoveCustomConfiguration(const std::string& title_id, game_info game = nullptr, bool is_interactive = false);
|
||||||
|
bool RemoveCustomPadConfiguration(const std::string& title_id, game_info game = nullptr, bool is_interactive = false);
|
||||||
bool RemoveShadersCache(const std::string& base_dir, bool is_interactive = false);
|
bool RemoveShadersCache(const std::string& base_dir, bool is_interactive = false);
|
||||||
bool RemovePPUCache(const std::string& base_dir, bool is_interactive = false);
|
bool RemovePPUCache(const std::string& base_dir, bool is_interactive = false);
|
||||||
bool RemoveSPUCache(const std::string& base_dir, bool is_interactive = false);
|
bool RemoveSPUCache(const std::string& base_dir, bool is_interactive = false);
|
||||||
|
@ -1247,6 +1247,7 @@ void main_window::CreateConnects()
|
|||||||
connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveSPUCaches);
|
connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveSPUCaches);
|
||||||
connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveShaderCaches);
|
connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveShaderCaches);
|
||||||
connect(ui->batchRemoveCustomConfigurationsAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveCustomConfigurations);
|
connect(ui->batchRemoveCustomConfigurationsAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveCustomConfigurations);
|
||||||
|
connect(ui->batchRemoveCustomPadConfigurationsAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveCustomPadConfigurations);
|
||||||
|
|
||||||
connect(ui->sysPauseAct, &QAction::triggered, this, &main_window::OnPlayOrPause);
|
connect(ui->sysPauseAct, &QAction::triggered, this, &main_window::OnPlayOrPause);
|
||||||
connect(ui->sysStopAct, &QAction::triggered, [=]() { Emu.Stop(); });
|
connect(ui->sysStopAct, &QAction::triggered, [=]() { Emu.Stop(); });
|
||||||
@ -1282,20 +1283,19 @@ void main_window::CreateConnects()
|
|||||||
|
|
||||||
auto openPadSettings = [this]
|
auto openPadSettings = [this]
|
||||||
{
|
{
|
||||||
auto resetPadHandlers = [this](int/* result*/)
|
|
||||||
{
|
|
||||||
if (Emu.IsStopped())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Emu.GetCallbacks().reset_pads();
|
|
||||||
};
|
|
||||||
if (!Emu.IsStopped())
|
if (!Emu.IsStopped())
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().enable_pads(false);
|
Emu.GetCallbacks().enable_pads(false);
|
||||||
}
|
}
|
||||||
pad_settings_dialog dlg(this);
|
pad_settings_dialog dlg(this);
|
||||||
connect(&dlg, &QDialog::finished, resetPadHandlers);
|
connect(&dlg, &QDialog::finished, [this](int/* result*/)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Emu.GetCallbacks().reset_pads(Emu.GetTitleID());
|
||||||
|
});
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
if (!Emu.IsStopped())
|
if (!Emu.IsStopped())
|
||||||
{
|
{
|
||||||
|
@ -141,7 +141,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1058</width>
|
<width>1058</width>
|
||||||
<height>21</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
@ -172,6 +172,7 @@
|
|||||||
<addaction name="batchCreatePPUCachesAct"/>
|
<addaction name="batchCreatePPUCachesAct"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="batchRemoveCustomConfigurationsAct"/>
|
<addaction name="batchRemoveCustomConfigurationsAct"/>
|
||||||
|
<addaction name="batchRemoveCustomPadConfigurationsAct"/>
|
||||||
<addaction name="batchRemovePPUCachesAct"/>
|
<addaction name="batchRemovePPUCachesAct"/>
|
||||||
<addaction name="batchRemoveSPUCachesAct"/>
|
<addaction name="batchRemoveSPUCachesAct"/>
|
||||||
<addaction name="batchRemoveShaderCachesAct"/>
|
<addaction name="batchRemoveShaderCachesAct"/>
|
||||||
@ -995,6 +996,11 @@
|
|||||||
<string>Remove Shader Caches</string>
|
<string>Remove Shader Caches</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="batchRemoveCustomPadConfigurationsAct">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove Custom Pad Configurations</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@ -29,19 +29,13 @@ constexpr auto qstr = QString::fromStdString;
|
|||||||
|
|
||||||
inline bool CreateConfigFile(const QString& dir, const QString& name)
|
inline bool CreateConfigFile(const QString& dir, const QString& name)
|
||||||
{
|
{
|
||||||
QString input_dir = qstr(fs::get_config_dir()) + "/InputConfigs/";
|
if (!QDir().mkpath(dir))
|
||||||
if (!QDir().mkdir(input_dir) && !QDir().exists(input_dir))
|
|
||||||
{
|
|
||||||
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(input_dir));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!QDir().mkdir(dir) && !QDir().exists(dir))
|
|
||||||
{
|
{
|
||||||
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(dir));
|
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(dir));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString filename = dir + name + ".yml";
|
const QString filename = dir + name + ".yml";
|
||||||
QFile new_file(filename);
|
QFile new_file(filename);
|
||||||
|
|
||||||
if (!new_file.open(QIODevice::WriteOnly))
|
if (!new_file.open(QIODevice::WriteOnly))
|
||||||
@ -54,16 +48,25 @@ inline bool CreateConfigFile(const QString& dir, const QString& name)
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
pad_settings_dialog::pad_settings_dialog(QWidget *parent)
|
pad_settings_dialog::pad_settings_dialog(QWidget *parent, const GameInfo *game)
|
||||||
: QDialog(parent), ui(new Ui::pad_settings_dialog)
|
: QDialog(parent), ui(new Ui::pad_settings_dialog)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
setWindowTitle(tr("Gamepads Settings"));
|
|
||||||
|
|
||||||
// load input config
|
// load input config
|
||||||
g_cfg_input.from_default();
|
g_cfg_input.from_default();
|
||||||
g_cfg_input.load();
|
|
||||||
|
if (game)
|
||||||
|
{
|
||||||
|
m_title_id = game->serial;
|
||||||
|
g_cfg_input.load(game->serial);
|
||||||
|
setWindowTitle(tr("Gamepads Settings: [%0] %1").arg(qstr(game->serial)).arg(qstr(game->name).simplified()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_cfg_input.load();
|
||||||
|
setWindowTitle(tr("Gamepads Settings"));
|
||||||
|
}
|
||||||
|
|
||||||
// Create tab widget for 7 players
|
// Create tab widget for 7 players
|
||||||
m_tabs = new QTabWidget;
|
m_tabs = new QTabWidget;
|
||||||
@ -153,7 +156,7 @@ pad_settings_dialog::pad_settings_dialog(QWidget *parent)
|
|||||||
QMessageBox::warning(this, tr("Error"), tr("Please choose a non-existing name"));
|
QMessageBox::warning(this, tr("Error"), tr("Please choose a non-existing name"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (CreateConfigFile(qstr(PadHandlerBase::get_config_dir(g_cfg_input.player[i]->handler)), friendlyName))
|
if (CreateConfigFile(qstr(PadHandlerBase::get_config_dir(g_cfg_input.player[i]->handler, m_title_id)), friendlyName))
|
||||||
{
|
{
|
||||||
ui->chooseProfile->addItem(friendlyName);
|
ui->chooseProfile->addItem(friendlyName);
|
||||||
ui->chooseProfile->setCurrentText(friendlyName);
|
ui->chooseProfile->setCurrentText(friendlyName);
|
||||||
@ -839,6 +842,7 @@ void pad_settings_dialog::OnPadButtonClicked(int id)
|
|||||||
|
|
||||||
void pad_settings_dialog::OnTabChanged(int index)
|
void pad_settings_dialog::OnTabChanged(int index)
|
||||||
{
|
{
|
||||||
|
// TODO: Do not save yet! But keep all profile changes until the dialog was saved.
|
||||||
// Save old profile
|
// Save old profile
|
||||||
SaveProfile();
|
SaveProfile();
|
||||||
|
|
||||||
@ -898,7 +902,7 @@ void pad_settings_dialog::ChangeInputType()
|
|||||||
if (!g_cfg_input.player[player]->handler.from_string(handler))
|
if (!g_cfg_input.player[player]->handler.from_string(handler))
|
||||||
{
|
{
|
||||||
// Something went wrong
|
// Something went wrong
|
||||||
LOG_ERROR(GENERAL, "Failed to convert input string:%s", handler);
|
LOG_ERROR(GENERAL, "Failed to convert input string: %s", handler);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -963,7 +967,7 @@ void pad_settings_dialog::ChangeInputType()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString profile_dir = qstr(PadHandlerBase::get_config_dir(m_handler->m_type));
|
QString profile_dir = qstr(PadHandlerBase::get_config_dir(m_handler->m_type, m_title_id));
|
||||||
QStringList profiles = gui::utils::get_dir_entries(QDir(profile_dir), QStringList() << "*.yml");
|
QStringList profiles = gui::utils::get_dir_entries(QDir(profile_dir), QStringList() << "*.yml");
|
||||||
|
|
||||||
if (profiles.isEmpty())
|
if (profiles.isEmpty())
|
||||||
@ -1021,7 +1025,7 @@ void pad_settings_dialog::ChangeProfile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Change handler
|
// Change handler
|
||||||
const std::string cfg_name = PadHandlerBase::get_config_dir(m_handler->m_type) + m_profile + ".yml";
|
const std::string cfg_name = PadHandlerBase::get_config_dir(m_handler->m_type, m_title_id) + m_profile + ".yml";
|
||||||
|
|
||||||
// Adjust to the different pad handlers
|
// Adjust to the different pad handlers
|
||||||
switch (m_handler->m_type)
|
switch (m_handler->m_type)
|
||||||
@ -1145,7 +1149,7 @@ void pad_settings_dialog::SaveExit()
|
|||||||
g_cfg_input.player[i]->profile.from_default();
|
g_cfg_input.player[i]->profile.from_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_cfg_input.save();
|
g_cfg_input.save(m_title_id);
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "Emu/Io/PadHandler.h"
|
#include "Emu/Io/PadHandler.h"
|
||||||
|
#include "Emu/GameInfo.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -85,7 +86,7 @@ class pad_settings_dialog : public QDialog
|
|||||||
const QString Disconnected_suffix = tr(" (disconnected)");
|
const QString Disconnected_suffix = tr(" (disconnected)");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit pad_settings_dialog(QWidget *parent = nullptr);
|
explicit pad_settings_dialog(QWidget *parent = nullptr, const GameInfo *game = nullptr);
|
||||||
~pad_settings_dialog();
|
~pad_settings_dialog();
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
@ -100,6 +101,7 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::pad_settings_dialog *ui;
|
Ui::pad_settings_dialog *ui;
|
||||||
|
std::string m_title_id;
|
||||||
|
|
||||||
// TabWidget
|
// TabWidget
|
||||||
QTabWidget* m_tabs;
|
QTabWidget* m_tabs;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user