Compare commits
2 Commits
hidbus
...
controller
Author | SHA1 | Date | |
---|---|---|---|
b6478b2de9 | |||
3055ebc9a0 |
@ -14,22 +14,11 @@ constexpr Result VibrationInvalidStyleIndex{ErrorModule::HID, 122};
|
||||
constexpr Result VibrationInvalidNpadId{ErrorModule::HID, 123};
|
||||
constexpr Result VibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
|
||||
constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};
|
||||
|
||||
constexpr Result ResultMcuInvalidHandle{ErrorModule::HID, 541};
|
||||
constexpr Result ResultMcuNotEnabled{ErrorModule::HID, 542};
|
||||
constexpr Result ResultMcuNoDeviceConnected{ErrorModule::HID, 543};
|
||||
constexpr Result ResultMcuUnknown544{ErrorModule::HID, 544};
|
||||
constexpr Result ResultMcuUnknown546{ErrorModule::HID, 546};
|
||||
constexpr Result ResultMcuUnknown548{ErrorModule::HID, 548};
|
||||
|
||||
constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601};
|
||||
constexpr Result NpadIsSameType{ErrorModule::HID, 602};
|
||||
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
|
||||
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
|
||||
constexpr Result InvalidArraySize{ErrorModule::HID, 715};
|
||||
|
||||
constexpr Result ResultControllerUpdateFailed{ErrorModule::HID, 3201};
|
||||
|
||||
constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302};
|
||||
|
||||
} // namespace Service::HID
|
||||
@ -40,17 +29,3 @@ constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78};
|
||||
constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204};
|
||||
|
||||
} // namespace Service::IRS
|
||||
|
||||
namespace Service::HIDBUS {
|
||||
|
||||
constexpr Result ResultNotEnabled{ErrorModule::HIDBUS, 1};
|
||||
constexpr Result ResultControllerUpdateFailed{ErrorModule::HIDBUS, 3};
|
||||
constexpr Result ResultInvalidBusHandle{ErrorModule::HIDBUS, 4};
|
||||
constexpr Result ResultNoDeviceConnected{ErrorModule::HIDBUS, 5};
|
||||
constexpr Result ResultUknown6{ErrorModule::HIDBUS, 6};
|
||||
constexpr Result ResultPollingRecieveDataNotAvailable{ErrorModule::HIDBUS, 7};
|
||||
constexpr Result ResultDeviceEnabledNotSet{ErrorModule::HIDBUS, 8};
|
||||
constexpr Result ResultBusHandleAlreadyInitialized{ErrorModule::HIDBUS, 10};
|
||||
constexpr Result ResultInvalidBusType{ErrorModule::HIDBUS, 11};
|
||||
|
||||
} // namespace Service::HID
|
@ -12,8 +12,6 @@
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/service/hid/hidbus.h"
|
||||
#include "core/hle/service/hid/errors.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "core/hle/service/hid/hidbus/ringcon.h"
|
||||
#include "core/hle/service/hid/hidbus/starlink.h"
|
||||
#include "core/hle/service/hid/hidbus/stubbed.h"
|
||||
@ -49,9 +47,56 @@ HidBus::HidBus(Core::System& system_)
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Register update callbacks
|
||||
hidbus_update_event = Core::Timing::CreateEvent(
|
||||
"Hidbus::UpdateCallback",
|
||||
[this](std::uintptr_t user_data, s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
const auto guard = LockService();
|
||||
UpdateHidbus(user_data, ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns,
|
||||
hidbus_update_event);
|
||||
}
|
||||
|
||||
HidBus::~HidBus() {
|
||||
system.CoreTiming().UnscheduleEvent(hidbus_update_event, 0);
|
||||
}
|
||||
|
||||
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
if (is_hidbus_enabled) {
|
||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||
if (!devices[i].is_device_initializated) {
|
||||
continue;
|
||||
}
|
||||
auto& device = devices[i].device;
|
||||
device->OnUpdate();
|
||||
auto& cur_entry = hidbus_status.entries[devices[i].handle.internal_index];
|
||||
cur_entry.is_polling_mode = device->IsPollingMode();
|
||||
cur_entry.polling_mode = device->GetPollingMode();
|
||||
cur_entry.is_enabled = device->IsEnabled();
|
||||
|
||||
u8* shared_memory = system.Kernel().GetHidBusSharedMem().GetPointer();
|
||||
std::memcpy(shared_memory + (i * sizeof(HidbusStatusManagerEntry)), &hidbus_status,
|
||||
sizeof(HidbusStatusManagerEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||
const auto& device_handle = devices[i].handle;
|
||||
if (handle.abstracted_pad_id == device_handle.abstracted_pad_id &&
|
||||
handle.internal_index == device_handle.internal_index &&
|
||||
handle.player_number == device_handle.player_number &&
|
||||
handle.bus_type_id == device_handle.bus_type_id &&
|
||||
handle.is_valid == device_handle.is_valid) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
||||
@ -69,9 +114,38 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}",
|
||||
parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id);
|
||||
|
||||
if (parameters.bus_type >= BusType::MaxBusType) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(HIDBUS::ResultInvalidBusType);
|
||||
bool is_handle_found = 0;
|
||||
std::size_t handle_index = 0;
|
||||
|
||||
for (std::size_t i = 0; i < devices.size(); i++) {
|
||||
const auto& handle = devices[i].handle;
|
||||
if (!handle.is_valid) {
|
||||
continue;
|
||||
}
|
||||
if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id &&
|
||||
handle.bus_type_id == static_cast<u8>(parameters.bus_type)) {
|
||||
is_handle_found = true;
|
||||
handle_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle not found. Create a new one
|
||||
if (!is_handle_found) {
|
||||
for (std::size_t i = 0; i < devices.size(); i++) {
|
||||
if (devices[i].handle.is_valid) {
|
||||
continue;
|
||||
}
|
||||
devices[i].handle = {
|
||||
.abstracted_pad_id = static_cast<u8>(i),
|
||||
.internal_index = static_cast<u8>(i),
|
||||
.player_number = static_cast<u8>(parameters.npad_id),
|
||||
.bus_type_id = static_cast<u8>(parameters.bus_type),
|
||||
.is_valid = true,
|
||||
};
|
||||
handle_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct OutData {
|
||||
@ -81,8 +155,10 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
||||
};
|
||||
static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size.");
|
||||
|
||||
OutData out_data{};
|
||||
out_data.is_valid = GetBusHandleImpl(out_data.handle, parameters.npad_id, parameters.bus_type);
|
||||
const OutData out_data{
|
||||
.is_valid = true,
|
||||
.handle = devices[handle_index].handle,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -99,10 +175,21 @@ void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
auto result = TranslateHidErrorToHidBusError(ResultSuccess);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
const bool is_attached = device->IsDeviceActivated();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(is_attached);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -117,6 +204,40 @@ void HidBus::Initialize(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id);
|
||||
|
||||
is_hidbus_enabled = true;
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
const auto entry_index = devices[device_index.value()].handle.internal_index;
|
||||
auto& cur_entry = hidbus_status.entries[entry_index];
|
||||
|
||||
if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) {
|
||||
MakeDevice<RingController>(bus_handle_);
|
||||
devices[device_index.value()].is_device_initializated = true;
|
||||
devices[device_index.value()].device->ActivateDevice();
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = true;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
} else {
|
||||
MakeDevice<HidbusStubbed>(bus_handle_);
|
||||
devices[device_index.value()].is_device_initializated = true;
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = false;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
}
|
||||
|
||||
std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
||||
sizeof(hidbus_status));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -135,6 +256,27 @@ void HidBus::Finalize(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
const auto entry_index = devices[device_index.value()].handle.internal_index;
|
||||
auto& cur_entry = hidbus_status.entries[entry_index];
|
||||
auto& device = devices[device_index.value()].device;
|
||||
devices[device_index.value()].is_device_initializated = false;
|
||||
device->DeactivateDevice();
|
||||
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = false;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
||||
sizeof(hidbus_status));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -163,6 +305,16 @@ void HidBus::EnableExternalDevice(HLERequestContext& ctx) {
|
||||
parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval,
|
||||
parameters.applet_resource_user_id);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->Enable(parameters.enable);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -180,29 +332,21 @@ void HidBus::GetExternalDeviceId(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
u32 device_id{};
|
||||
auto result = SetEventForSendCommandAsycResult2();
|
||||
if (result.IsSuccess()) {
|
||||
if (1) {
|
||||
result = HIDBUS::ResultInvalidBusHandle;
|
||||
}
|
||||
}
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
// result = GetExternalDeviceIdImpl();
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
u32 device_id = device->GetDeviceId();
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(device_id);
|
||||
return;
|
||||
}
|
||||
|
||||
result = TranslateHidErrorToHidBusError(result);
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
void HidBus::SendCommandAsync(HLERequestContext& ctx) {
|
||||
@ -216,6 +360,16 @@ void HidBus::SendCommandAsync(HLERequestContext& ctx) {
|
||||
data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id,
|
||||
bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->SetCommand(data);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -233,6 +387,18 @@ void HidBus::GetSendCommandAsynceResult(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
const std::vector<u8> data = device->GetReply();
|
||||
const u64 data_size = ctx.WriteBuffer(data);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u64>(data_size);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -250,6 +416,16 @@ void HidBus::SetEventForSendCommandAsycResult(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(device->GetSendCommandAsycEvent());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
@ -291,6 +467,17 @@ void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) {
|
||||
t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id,
|
||||
bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->SetPollingMode(polling_mode_);
|
||||
device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -308,6 +495,16 @@ void HidBus::DisableJoyPollingReceiveMode(HLERequestContext& ctx) {
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->DisablePollingMode();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -324,59 +521,4 @@ void HidBus::SetStatusManagerType(HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
};
|
||||
|
||||
|
||||
bool HidBus::GetBusHandleImpl(BusHandle& handle, Core::HID::NpadIdType npad_id, BusType bus_type) {
|
||||
ASSERT_MSG(&handle != nullptr, "Handle is null");
|
||||
|
||||
if (!Controller_NPad::IsNpadIdValid(npad_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bus_type == BusType::LeftJoyRail || bus_type == BusType::RightJoyRail) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bus_type == BusType::InternalBus) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Result TranslateHidErrorToHidBusError(Result result) {
|
||||
if (result.IsSuccess()) {
|
||||
return result;
|
||||
}
|
||||
if (result.module != ErrorModule::HID) {
|
||||
return result;
|
||||
}
|
||||
if (result == ResultMcuNotEnabled) {
|
||||
return HIDBUS::ResultNotEnabled;
|
||||
}
|
||||
if (result == ResultMcuNoDeviceConnected) {
|
||||
return HIDBUS::ResultNoDeviceConnected;
|
||||
}
|
||||
if (result == ResultMcuUnknown544) {
|
||||
return HIDBUS::ResultUknown6;
|
||||
}
|
||||
if ((result.description & 0x1FFB) == 0x221) {
|
||||
return HIDBUS::ResultPollingRecieveDataNotAvailable;
|
||||
}
|
||||
if (result == ResultMcuInvalidHandle) {
|
||||
return HIDBUS::ResultInvalidBusHandle;
|
||||
}
|
||||
if (result == ResultMcuUnknown546) {
|
||||
return HIDBUS::ResultDeviceEnabledNotSet;
|
||||
}
|
||||
if (result == ResultMcuUnknown548) {
|
||||
return HIDBUS::ResultInvalidBusHandle;
|
||||
}
|
||||
if (result == ResultControllerUpdateFailed) {
|
||||
return HIDBUS::ResultControllerUpdateFailed;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Service::HID
|
||||
|
@ -108,12 +108,21 @@ private:
|
||||
void DisableJoyPollingReceiveMode(HLERequestContext& ctx);
|
||||
void SetStatusManagerType(HLERequestContext& ctx);
|
||||
|
||||
bool GetBusHandleImpl(BusHandle& handle, Core::HID::NpadIdType npad_id, BusType bus_type);
|
||||
Result TranslateHidErrorToHidBusError(Result result);
|
||||
Result SetEventForSendCommandAsycResult2();
|
||||
void UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const;
|
||||
|
||||
template <typename T>
|
||||
void MakeDevice(BusHandle handle) {
|
||||
const auto device_index = GetDeviceIndexFromHandle(handle);
|
||||
if (device_index) {
|
||||
devices[device_index.value()].device = std::make_unique<T>(system, service_context);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_hidbus_enabled{false};
|
||||
HidbusStatusManager hidbus_status{};
|
||||
std::array<HidbusDevice, max_number_of_handles> devices{};
|
||||
std::shared_ptr<Core::Timing::EventType> hidbus_update_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
};
|
||||
|
||||
|
@ -199,6 +199,14 @@ add_executable(yuzu
|
||||
util/clickable_label.h
|
||||
util/controller_navigation.cpp
|
||||
util/controller_navigation.h
|
||||
util/controller_viewer/common_shapes.cpp
|
||||
util/controller_viewer/common_shapes.h
|
||||
util/controller_viewer/controller_base.cpp
|
||||
util/controller_viewer/controller_base.h
|
||||
util/controller_viewer/controller_viewer.cpp
|
||||
util/controller_viewer/controller_viewer.h
|
||||
util/controller_viewer/pro_controller.cpp
|
||||
util/controller_viewer/pro_controller.h
|
||||
util/limitable_input_dialog.cpp
|
||||
util/limitable_input_dialog.h
|
||||
util/overlay_dialog.cpp
|
||||
|
407
src/yuzu/util/controller_viewer/common_shapes.cpp
Normal file
407
src/yuzu/util/controller_viewer/common_shapes.cpp
Normal file
@ -0,0 +1,407 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
|
||||
#include "common/input.h"
|
||||
#include "yuzu/util/controller_viewer/common_shapes.h"
|
||||
|
||||
namespace ControllerViewer {
|
||||
|
||||
void CommonShapes::DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery,
|
||||
QColor outline, QColor battery_color, QColor charging_outline,
|
||||
QColor charging_color) {
|
||||
if (battery == Common::Input::BatteryLevel::None) {
|
||||
return;
|
||||
}
|
||||
// Draw outline
|
||||
p.setPen(QPen(outline, 5));
|
||||
p.setBrush(Qt::transparent);
|
||||
p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2);
|
||||
|
||||
p.setPen(QPen(outline, 3));
|
||||
p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);
|
||||
|
||||
// Draw Battery shape
|
||||
p.setPen(QPen(battery_color, 3));
|
||||
p.setBrush(Qt::transparent);
|
||||
p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2);
|
||||
|
||||
p.setPen(QPen(battery_color, 1));
|
||||
p.setBrush(battery_color);
|
||||
p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);
|
||||
switch (battery) {
|
||||
case Common::Input::BatteryLevel::Charging:
|
||||
p.drawRect(center.x(), center.y(), 34, 16);
|
||||
p.setPen(charging_outline);
|
||||
p.setBrush(charging_color);
|
||||
DrawSymbol(p, center + QPointF(17.0f, 8.0f), Symbol::Charging, 2.1f);
|
||||
break;
|
||||
case Common::Input::BatteryLevel::Full:
|
||||
p.drawRect(center.x(), center.y(), 34, 16);
|
||||
break;
|
||||
case Common::Input::BatteryLevel::Medium:
|
||||
p.drawRect(center.x(), center.y(), 25, 16);
|
||||
break;
|
||||
case Common::Input::BatteryLevel::Low:
|
||||
p.drawRect(center.x(), center.y(), 17, 16);
|
||||
break;
|
||||
case Common::Input::BatteryLevel::Critical:
|
||||
p.drawRect(center.x(), center.y(), 6, 16);
|
||||
break;
|
||||
case Common::Input::BatteryLevel::Empty:
|
||||
p.drawRect(center.x(), center.y(), 3, 16);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CommonShapes::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol, float icon_size) {
|
||||
std::array<QPointF, house.size() / 2> house_icon;
|
||||
std::array<QPointF, symbol_a.size() / 2> a_icon;
|
||||
std::array<QPointF, symbol_b.size() / 2> b_icon;
|
||||
std::array<QPointF, symbol_x.size() / 2> x_icon;
|
||||
std::array<QPointF, symbol_y.size() / 2> y_icon;
|
||||
std::array<QPointF, symbol_l.size() / 2> l_icon;
|
||||
std::array<QPointF, symbol_r.size() / 2> r_icon;
|
||||
std::array<QPointF, symbol_c.size() / 2> c_icon;
|
||||
std::array<QPointF, symbol_zl.size() / 2> zl_icon;
|
||||
std::array<QPointF, symbol_sl.size() / 2> sl_icon;
|
||||
std::array<QPointF, symbol_zr.size() / 2> zr_icon;
|
||||
std::array<QPointF, symbol_sr.size() / 2> sr_icon;
|
||||
std::array<QPointF, symbol_charging.size() / 2> charging_icon;
|
||||
switch (symbol) {
|
||||
case Symbol::House:
|
||||
for (std::size_t point = 0; point < house.size() / 2; ++point) {
|
||||
house_icon[point] = center + QPointF(house[point * 2] * icon_size,
|
||||
(house[point * 2 + 1] - 0.025f) * icon_size);
|
||||
}
|
||||
p.drawPolygon(house_icon.data(), static_cast<int>(house_icon.size()));
|
||||
break;
|
||||
case Symbol::A:
|
||||
for (std::size_t point = 0; point < symbol_a.size() / 2; ++point) {
|
||||
a_icon[point] = center + QPointF(symbol_a[point * 2] * icon_size,
|
||||
symbol_a[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(a_icon.data(), static_cast<int>(a_icon.size()));
|
||||
break;
|
||||
case Symbol::B:
|
||||
for (std::size_t point = 0; point < symbol_b.size() / 2; ++point) {
|
||||
b_icon[point] = center + QPointF(symbol_b[point * 2] * icon_size,
|
||||
symbol_b[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(b_icon.data(), static_cast<int>(b_icon.size()));
|
||||
break;
|
||||
case Symbol::X:
|
||||
for (std::size_t point = 0; point < symbol_x.size() / 2; ++point) {
|
||||
x_icon[point] = center + QPointF(symbol_x[point * 2] * icon_size,
|
||||
symbol_x[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(x_icon.data(), static_cast<int>(x_icon.size()));
|
||||
break;
|
||||
case Symbol::Y:
|
||||
for (std::size_t point = 0; point < symbol_y.size() / 2; ++point) {
|
||||
y_icon[point] = center + QPointF(symbol_y[point * 2] * icon_size,
|
||||
(symbol_y[point * 2 + 1] - 1.0f) * icon_size);
|
||||
}
|
||||
p.drawPolygon(y_icon.data(), static_cast<int>(y_icon.size()));
|
||||
break;
|
||||
case Symbol::L:
|
||||
for (std::size_t point = 0; point < symbol_l.size() / 2; ++point) {
|
||||
l_icon[point] = center + QPointF(symbol_l[point * 2] * icon_size,
|
||||
(symbol_l[point * 2 + 1] - 1.0f) * icon_size);
|
||||
}
|
||||
p.drawPolygon(l_icon.data(), static_cast<int>(l_icon.size()));
|
||||
break;
|
||||
case Symbol::R:
|
||||
for (std::size_t point = 0; point < symbol_r.size() / 2; ++point) {
|
||||
r_icon[point] = center + QPointF(symbol_r[point * 2] * icon_size,
|
||||
(symbol_r[point * 2 + 1] - 1.0f) * icon_size);
|
||||
}
|
||||
p.drawPolygon(r_icon.data(), static_cast<int>(r_icon.size()));
|
||||
break;
|
||||
case Symbol::C:
|
||||
for (std::size_t point = 0; point < symbol_c.size() / 2; ++point) {
|
||||
c_icon[point] = center + QPointF(symbol_c[point * 2] * icon_size,
|
||||
(symbol_c[point * 2 + 1] - 1.0f) * icon_size);
|
||||
}
|
||||
p.drawPolygon(c_icon.data(), static_cast<int>(c_icon.size()));
|
||||
break;
|
||||
case Symbol::ZL:
|
||||
for (std::size_t point = 0; point < symbol_zl.size() / 2; ++point) {
|
||||
zl_icon[point] = center + QPointF(symbol_zl[point * 2] * icon_size,
|
||||
symbol_zl[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(zl_icon.data(), static_cast<int>(zl_icon.size()));
|
||||
break;
|
||||
case Symbol::SL:
|
||||
for (std::size_t point = 0; point < symbol_sl.size() / 2; ++point) {
|
||||
sl_icon[point] = center + QPointF(symbol_sl[point * 2] * icon_size,
|
||||
symbol_sl[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(sl_icon.data(), static_cast<int>(sl_icon.size()));
|
||||
break;
|
||||
case Symbol::ZR:
|
||||
for (std::size_t point = 0; point < symbol_zr.size() / 2; ++point) {
|
||||
zr_icon[point] = center + QPointF(symbol_zr[point * 2] * icon_size,
|
||||
symbol_zr[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(zr_icon.data(), static_cast<int>(zr_icon.size()));
|
||||
break;
|
||||
case Symbol::SR:
|
||||
for (std::size_t point = 0; point < symbol_sr.size() / 2; ++point) {
|
||||
sr_icon[point] = center + QPointF(symbol_sr[point * 2] * icon_size,
|
||||
symbol_sr[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size()));
|
||||
break;
|
||||
case Symbol::Charging:
|
||||
for (std::size_t point = 0; point < symbol_charging.size() / 2; ++point) {
|
||||
charging_icon[point] = center + QPointF(symbol_charging[point * 2] * icon_size,
|
||||
symbol_charging[point * 2 + 1] * icon_size);
|
||||
}
|
||||
p.drawPolygon(charging_icon.data(), static_cast<int>(charging_icon.size()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CommonShapes::DrawArrow(QPainter& p, const QPointF center, const Direction direction,
|
||||
float size) {
|
||||
|
||||
std::array<QPointF, up_arrow_symbol.size() / 2> arrow_symbol;
|
||||
|
||||
for (std::size_t point = 0; point < up_arrow_symbol.size() / 2; ++point) {
|
||||
const float up_arrow_x = up_arrow_symbol[point * 2 + 0];
|
||||
const float up_arrow_y = up_arrow_symbol[point * 2 + 1];
|
||||
|
||||
switch (direction) {
|
||||
case Direction::Up:
|
||||
arrow_symbol[point] = center + QPointF(up_arrow_x * size, up_arrow_y * size);
|
||||
break;
|
||||
case Direction::Left:
|
||||
arrow_symbol[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size);
|
||||
break;
|
||||
case Direction::Right:
|
||||
arrow_symbol[point] = center + QPointF(-up_arrow_y * size, up_arrow_x * size);
|
||||
break;
|
||||
case Direction::Down:
|
||||
arrow_symbol[point] = center + QPointF(up_arrow_x * size, -up_arrow_y * size);
|
||||
break;
|
||||
case Direction::None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DrawPolygon(p, arrow_symbol);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void CommonShapes::DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon) {
|
||||
p.drawPolygon(polygon.data(), static_cast<int>(polygon.size()));
|
||||
}
|
||||
|
||||
void CommonShapes::DrawCircle(QPainter& p, const QPointF center, float size) {
|
||||
p.drawEllipse(center, size, size);
|
||||
}
|
||||
|
||||
void CommonShapes::DrawRectangle(QPainter& p, const QPointF center, float width, float height) {
|
||||
const QRectF rect = QRectF(center.x() - (width / 2), center.y() - (height / 2), width, height);
|
||||
p.drawRect(rect);
|
||||
}
|
||||
void CommonShapes::DrawRoundRectangle(QPainter& p, const QPointF center, float width, float height,
|
||||
float round) {
|
||||
const QRectF rect = QRectF(center.x() - (width / 2), center.y() - (height / 2), width, height);
|
||||
p.drawRoundedRect(rect, round, round);
|
||||
}
|
||||
|
||||
void CommonShapes::DrawText(QPainter& p, const QPointF center, float text_size,
|
||||
const QString& text) {
|
||||
SetTextFont(p, text_size);
|
||||
const QFontMetrics fm(p.font());
|
||||
const QPointF offset = {fm.horizontalAdvance(text) / 2.0f, -text_size / 2.0f};
|
||||
p.drawText(center - offset, text);
|
||||
}
|
||||
|
||||
void CommonShapes::SetTextFont(QPainter& p, float text_size, const QString& font_family) {
|
||||
QFont font = p.font();
|
||||
font.setPointSizeF(text_size);
|
||||
font.setFamily(font_family);
|
||||
p.setFont(font);
|
||||
}
|
||||
|
||||
constexpr std::array<float, 13 * 2> symbol_a = {
|
||||
-1.085f, -5.2f, 1.085f, -5.2f, 5.085f, 5.0f, 2.785f, 5.0f, 1.785f,
|
||||
2.65f, -1.785f, 2.65f, -2.785f, 5.0f, -5.085f, 5.0f, -1.4f, 1.0f,
|
||||
0.0f, -2.8f, 1.4f, 1.0f, -1.4f, 1.0f, -5.085f, 5.0f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 134 * 2> symbol_b = {
|
||||
-4.0f, 0.0f, -4.0f, 0.0f, -4.0f, -0.1f, -3.8f, -5.1f, 1.8f, -5.0f, 2.3f, -4.9f, 2.6f,
|
||||
-4.8f, 2.8f, -4.7f, 2.9f, -4.6f, 3.1f, -4.5f, 3.2f, -4.4f, 3.4f, -4.3f, 3.4f, -4.2f,
|
||||
3.5f, -4.1f, 3.7f, -4.0f, 3.7f, -3.9f, 3.8f, -3.8f, 3.8f, -3.7f, 3.9f, -3.6f, 3.9f,
|
||||
-3.5f, 4.0f, -3.4f, 4.0f, -3.3f, 4.1f, -3.1f, 4.1f, -3.0f, 4.0f, -2.0f, 4.0f, -1.9f,
|
||||
3.9f, -1.7f, 3.9f, -1.6f, 3.8f, -1.5f, 3.8f, -1.4f, 3.7f, -1.3f, 3.7f, -1.2f, 3.6f,
|
||||
-1.1f, 3.6f, -1.0f, 3.5f, -0.9f, 3.3f, -0.8f, 3.3f, -0.7f, 3.2f, -0.6f, 3.0f, -0.5f,
|
||||
2.9f, -0.4f, 2.7f, -0.3f, 2.9f, -0.2f, 3.2f, -0.1f, 3.3f, 0.0f, 3.5f, 0.1f, 3.6f,
|
||||
0.2f, 3.8f, 0.3f, 3.9f, 0.4f, 4.0f, 0.6f, 4.1f, 0.7f, 4.3f, 0.8f, 4.3f, 0.9f,
|
||||
4.4f, 1.0f, 4.4f, 1.1f, 4.5f, 1.3f, 4.5f, 1.4f, 4.6f, 1.6f, 4.6f, 1.7f, 4.5f,
|
||||
2.8f, 4.5f, 2.9f, 4.4f, 3.1f, 4.4f, 3.2f, 4.3f, 3.4f, 4.3f, 3.5f, 4.2f, 3.6f,
|
||||
4.2f, 3.7f, 4.1f, 3.8f, 4.1f, 3.9f, 4.0f, 4.0f, 3.9f, 4.2f, 3.8f, 4.3f, 3.6f,
|
||||
4.4f, 3.6f, 4.5f, 3.4f, 4.6f, 3.3f, 4.7f, 3.1f, 4.8f, 2.8f, 4.9f, 2.6f, 5.0f,
|
||||
2.1f, 5.1f, -4.0f, 5.0f, -4.0f, 4.9f,
|
||||
|
||||
-4.0f, 0.0f, 1.1f, 3.4f, 1.1f, 3.4f, 1.5f, 3.3f, 1.8f, 3.2f, 2.0f, 3.1f, 2.1f,
|
||||
3.0f, 2.3f, 2.9f, 2.3f, 2.8f, 2.4f, 2.7f, 2.4f, 2.6f, 2.5f, 2.3f, 2.5f, 2.2f,
|
||||
2.4f, 1.7f, 2.4f, 1.6f, 2.3f, 1.4f, 2.3f, 1.3f, 2.2f, 1.2f, 2.2f, 1.1f, 2.1f,
|
||||
1.0f, 1.9f, 0.9f, 1.6f, 0.8f, 1.4f, 0.7f, -1.9f, 0.6f, -1.9f, 0.7f, -1.8f, 3.4f,
|
||||
1.1f, 3.4f, -4.0f, 0.0f,
|
||||
|
||||
0.3f, -1.1f, 0.3f, -1.1f, 1.3f, -1.2f, 1.5f, -1.3f, 1.8f, -1.4f, 1.8f, -1.5f, 1.9f,
|
||||
-1.6f, 2.0f, -1.8f, 2.0f, -1.9f, 2.1f, -2.0f, 2.1f, -2.1f, 2.0f, -2.7f, 2.0f, -2.8f,
|
||||
1.9f, -2.9f, 1.9f, -3.0f, 1.8f, -3.1f, 1.6f, -3.2f, 1.6f, -3.3f, 1.3f, -3.4f, -1.9f,
|
||||
-3.3f, -1.9f, -3.2f, -1.8f, -1.0f, 0.2f, -1.1f, 0.3f, -1.1f, -4.0f, 0.0f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 9 * 2> symbol_y = {
|
||||
-4.79f, -4.9f, -2.44f, -4.9f, 0.0f, -0.9f, 2.44f, -4.9f, 4.79f,
|
||||
-4.9f, 1.05f, 1.0f, 1.05f, 5.31f, -1.05f, 5.31f, -1.05f, 1.0f,
|
||||
|
||||
};
|
||||
|
||||
constexpr std::array<float, 12 * 2> symbol_x = {
|
||||
-4.4f, -5.0f, -2.0f, -5.0f, 0.0f, -1.7f, 2.0f, -5.0f, 4.4f, -5.0f, 1.2f, 0.0f,
|
||||
4.4f, 5.0f, 2.0f, 5.0f, 0.0f, 1.7f, -2.0f, 5.0f, -4.4f, 5.0f, -1.2f, 0.0f,
|
||||
|
||||
};
|
||||
|
||||
constexpr std::array<float, 7 * 2> symbol_l = {
|
||||
2.4f, -3.23f, 2.4f, 2.1f, 5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 98 * 2> symbol_r = {
|
||||
1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f, -2.9f,
|
||||
5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f, 6.2f, -2.1f,
|
||||
6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f, -0.5f, 6.0f, -0.4f,
|
||||
6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f, 5.4f, 0.2f, 5.1f, 0.3f,
|
||||
4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f, 0.8f, 5.2f, 0.9f, 5.3f, 1.0f,
|
||||
5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f, 5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f,
|
||||
6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f, 2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f,
|
||||
6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f, 6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f,
|
||||
5.1f, 2.9f, 5.0f, 2.7f, 4.9f, 2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f,
|
||||
4.4f, 1.8f, 4.3f, 1.7f, 4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f,
|
||||
3.6f, 0.8f, 3.5f, 0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f,
|
||||
1.0f, 3.2f, 1.0f, 3.1f, 1.0f, 0.0f,
|
||||
|
||||
4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, -1.1f, 5.0f, -1.2f,
|
||||
4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, 4.3f, -2.2f, 2.3f, -2.1f,
|
||||
2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 18 * 2> symbol_zl = {
|
||||
-2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f,
|
||||
-0.7f, 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f, 2.4f, -3.23f, 2.4f, 2.1f,
|
||||
5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f, -6.0f, 2.12f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 57 * 2> symbol_sl = {
|
||||
-3.0f, -3.65f, -2.76f, -4.26f, -2.33f, -4.76f, -1.76f, -5.09f, -1.13f, -5.26f, -0.94f,
|
||||
-4.77f, -0.87f, -4.11f, -1.46f, -3.88f, -1.91f, -3.41f, -2.05f, -2.78f, -1.98f, -2.13f,
|
||||
-1.59f, -1.61f, -0.96f, -1.53f, -0.56f, -2.04f, -0.38f, -2.67f, -0.22f, -3.31f, 0.0f,
|
||||
-3.93f, 0.34f, -4.49f, 0.86f, -4.89f, 1.49f, -5.05f, 2.14f, -4.95f, 2.69f, -4.6f,
|
||||
3.07f, -4.07f, 3.25f, -3.44f, 3.31f, -2.78f, 3.25f, -2.12f, 3.07f, -1.49f, 2.7f,
|
||||
-0.95f, 2.16f, -0.58f, 1.52f, -0.43f, 1.41f, -0.99f, 1.38f, -1.65f, 1.97f, -1.91f,
|
||||
2.25f, -2.49f, 2.25f, -3.15f, 1.99f, -3.74f, 1.38f, -3.78f, 1.06f, -3.22f, 0.88f,
|
||||
-2.58f, 0.71f, -1.94f, 0.49f, -1.32f, 0.13f, -0.77f, -0.4f, -0.4f, -1.04f, -0.25f,
|
||||
-1.69f, -0.32f, -2.28f, -0.61f, -2.73f, -1.09f, -2.98f, -1.69f, -3.09f, -2.34f,
|
||||
|
||||
3.23f, 2.4f, -2.1f, 2.4f, -2.1f, 5.43f, -3.22f, 5.43f, -3.22f, 0.98f, 3.23f,
|
||||
0.98f, 3.23f, 2.4f, -3.09f, -2.34f,
|
||||
};
|
||||
constexpr std::array<float, 109 * 2> symbol_zr = {
|
||||
-2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f, -0.7f,
|
||||
2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f,
|
||||
|
||||
1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f,
|
||||
-2.9f, 5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f,
|
||||
6.2f, -2.1f, 6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f,
|
||||
-0.5f, 6.0f, -0.4f, 6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f,
|
||||
5.4f, 0.2f, 5.1f, 0.3f, 4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f,
|
||||
0.8f, 5.2f, 0.9f, 5.3f, 1.0f, 5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f,
|
||||
5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f, 6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f,
|
||||
2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f, 6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f,
|
||||
6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f, 5.1f, 2.9f, 5.0f, 2.7f, 4.9f,
|
||||
2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f, 4.4f, 1.8f, 4.3f, 1.7f,
|
||||
4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f, 3.6f, 0.8f, 3.5f,
|
||||
0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f, 1.0f, 3.2f,
|
||||
1.0f, 3.1f, 1.0f, 0.0f,
|
||||
|
||||
4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, -1.1f, 5.0f,
|
||||
-1.2f, 4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, 4.3f, -2.2f,
|
||||
2.3f, -2.1f, 2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f, -6.0f, 2.12f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 148 * 2> symbol_sr = {
|
||||
-3.0f, -3.65f, -2.76f, -4.26f, -2.33f, -4.76f, -1.76f, -5.09f, -1.13f, -5.26f, -0.94f, -4.77f,
|
||||
-0.87f, -4.11f, -1.46f, -3.88f, -1.91f, -3.41f, -2.05f, -2.78f, -1.98f, -2.13f, -1.59f, -1.61f,
|
||||
-0.96f, -1.53f, -0.56f, -2.04f, -0.38f, -2.67f, -0.22f, -3.31f, 0.0f, -3.93f, 0.34f, -4.49f,
|
||||
0.86f, -4.89f, 1.49f, -5.05f, 2.14f, -4.95f, 2.69f, -4.6f, 3.07f, -4.07f, 3.25f, -3.44f,
|
||||
3.31f, -2.78f, 3.25f, -2.12f, 3.07f, -1.49f, 2.7f, -0.95f, 2.16f, -0.58f, 1.52f, -0.43f,
|
||||
1.41f, -0.99f, 1.38f, -1.65f, 1.97f, -1.91f, 2.25f, -2.49f, 2.25f, -3.15f, 1.99f, -3.74f,
|
||||
1.38f, -3.78f, 1.06f, -3.22f, 0.88f, -2.58f, 0.71f, -1.94f, 0.49f, -1.32f, 0.13f, -0.77f,
|
||||
-0.4f, -0.4f, -1.04f, -0.25f, -1.69f, -0.32f, -2.28f, -0.61f, -2.73f, -1.09f, -2.98f, -1.69f,
|
||||
-3.09f, -2.34f,
|
||||
|
||||
-1.0f, 0.0f, 0.1f, 1.0f, 3.3f, 1.1f, 3.2f, 4.3f, 3.1f, 5.1f, 3.0f, 5.4f,
|
||||
2.9f, 5.6f, 2.8f, 5.7f, 2.7f, 5.9f, 2.6f, 5.9f, 2.5f, 6.0f, 2.3f, 6.1f,
|
||||
2.2f, 6.2f, 2.1f, 6.2f, 2.0f, 6.3f, 1.9f, 6.3f, 0.8f, 6.2f, 0.7f, 6.2f,
|
||||
0.6f, 6.1f, 0.5f, 6.1f, 0.4f, 6.0f, 0.3f, 6.0f, 0.2f, 5.9f, 0.1f, 5.7f,
|
||||
0.0f, 5.7f, -0.1f, 5.6f, -0.2f, 5.4f, -0.3f, 5.1f, -0.4f, 4.7f, -0.5f, 4.7f,
|
||||
-0.6f, 4.9f, -0.7f, 5.0f, -0.8f, 5.2f, -0.9f, 5.2f, -1.0f, 5.3f, -1.1f, 5.5f,
|
||||
-1.2f, 5.5f, -1.3f, 5.6f, -1.5f, 5.7f, -1.6f, 5.8f, -1.8f, 5.9f, -1.9f, 6.0f,
|
||||
-2.1f, 6.1f, -2.2f, 6.2f, -2.3f, 6.2f, -2.4f, 6.3f, -2.6f, 6.4f, -2.7f, 6.5f,
|
||||
-2.9f, 6.6f, -3.0f, 6.7f, -3.1f, 6.7f, -3.2f, 6.8f, -3.3f, 6.8f, -3.2f, 5.3f,
|
||||
-3.1f, 5.2f, -3.0f, 5.2f, -2.9f, 5.1f, -2.7f, 5.0f, -2.6f, 4.9f, -2.4f, 4.8f,
|
||||
-2.3f, 4.7f, -2.1f, 4.6f, -2.0f, 4.5f, -1.8f, 4.4f, -1.7f, 4.3f, -1.4f, 4.1f,
|
||||
-1.3f, 4.0f, -1.1f, 3.9f, -1.0f, 3.8f, -0.9f, 3.6f, -0.8f, 3.6f, -0.7f, 3.5f,
|
||||
-0.6f, 3.3f, -0.5f, 2.9f, -0.6f, 2.3f, -0.7f, 2.3f, -3.3f, 2.2f, -3.2f, 1.0f,
|
||||
-3.1f, 1.0f, 0.0f, 1.0f,
|
||||
|
||||
0.5f, 4.2f, 0.6f, 4.4f, 0.7f, 4.7f, 0.8f, 4.8f, 1.0f, 4.9f, 1.1f, 5.0f,
|
||||
1.2f, 5.0f, 1.7f, 4.9f, 1.8f, 4.9f, 1.9f, 4.8f, 2.0f, 4.8f, 2.1f, 4.6f,
|
||||
2.2f, 4.3f, 2.1f, 2.3f, 2.0f, 2.3f, 0.5f, 2.4f, 0.5f, 4.2f, -0.0f, 1.0f,
|
||||
-3.09f, -2.34f,
|
||||
|
||||
};
|
||||
|
||||
constexpr std::array<float, 30 * 2> symbol_c = {
|
||||
2.86f, 7.57f, 0.99f, 7.94f, -0.91f, 7.87f, -2.73f, 7.31f, -4.23f, 6.14f, -5.2f, 4.51f,
|
||||
-5.65f, 2.66f, -5.68f, 0.75f, -5.31f, -1.12f, -4.43f, -2.81f, -3.01f, -4.08f, -1.24f, -4.78f,
|
||||
0.66f, -4.94f, 2.54f, -4.67f, 4.33f, -4.0f, 4.63f, -2.27f, 3.37f, -2.7f, 1.6f, -3.4f,
|
||||
-0.3f, -3.5f, -2.09f, -2.87f, -3.34f, -1.45f, -3.91f, 0.37f, -3.95f, 2.27f, -3.49f, 4.12f,
|
||||
-2.37f, 5.64f, -0.65f, 6.44f, 1.25f, 6.47f, 3.06f, 5.89f, 4.63f, 4.92f, 4.63f, 6.83f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 6 * 2> symbol_charging = {
|
||||
6.5f, -1.0f, 1.0f, -1.0f, 1.0f, -3.0f, -6.5f, 1.0f, -1.0f, 1.0f, -1.0f, 3.0f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 12 * 2> house = {
|
||||
-1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f,
|
||||
0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 11 * 2> up_arrow_button = {
|
||||
9.1f, -9.1f, 9.1f, -30.0f, 8.1f, -30.1f, 7.7f, -30.1f, -8.6f, -30.0f, -9.0f,
|
||||
-29.8f, -9.3f, -29.5f, -9.5f, -29.1f, -9.1f, -28.7f, -9.1f, -9.1f, 0.0f, 0.6f,
|
||||
};
|
||||
|
||||
constexpr std::array<float, 3 * 2> up_arrow_symbol = {
|
||||
0.0f, -3.0f, -3.0f, 2.0f, 3.0f, 2.0f,
|
||||
};
|
||||
|
||||
} // namespace ControllerViewer
|
65
src/yuzu/util/controller_viewer/common_shapes.h
Normal file
65
src/yuzu/util/controller_viewer/common_shapes.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <QColor>
|
||||
#include <QPointer>
|
||||
|
||||
#include "common\common_types.h"
|
||||
|
||||
namespace Common::Input {
|
||||
enum class BatteryLevel : u32;
|
||||
}
|
||||
|
||||
namespace ControllerViewer {
|
||||
|
||||
// Widget for representing controller animations
|
||||
class CommonShapes {
|
||||
|
||||
enum class Direction : std::size_t {
|
||||
None,
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Left,
|
||||
};
|
||||
|
||||
enum class Symbol {
|
||||
House,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
L,
|
||||
R,
|
||||
C,
|
||||
SL,
|
||||
ZL,
|
||||
ZR,
|
||||
SR,
|
||||
Charging,
|
||||
};
|
||||
|
||||
// Draw battery functions
|
||||
void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery,
|
||||
QColor outline, QColor battery_color, QColor charging_outline,
|
||||
QColor charging_color);
|
||||
|
||||
// Draw icon functions
|
||||
void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);
|
||||
void DrawArrow(QPainter& p, QPointF center, Direction direction, float size);
|
||||
|
||||
// Draw primitive types
|
||||
template <size_t N>
|
||||
void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon);
|
||||
void DrawCircle(QPainter& p, QPointF center, float size);
|
||||
void DrawRectangle(QPainter& p, QPointF center, float width, float height);
|
||||
void DrawRoundRectangle(QPainter& p, QPointF center, float width, float height, float round);
|
||||
void DrawText(QPainter& p, QPointF center, float text_size, const QString& text);
|
||||
void SetTextFont(QPainter& p, float text_size,
|
||||
const QString& font_family = QStringLiteral("sans-serif"));
|
||||
};
|
||||
} // namespace ControllerViewer
|
0
src/yuzu/util/controller_viewer/controller_base.cpp
Normal file
0
src/yuzu/util/controller_viewer/controller_base.cpp
Normal file
77
src/yuzu/util/controller_viewer/controller_base.h
Normal file
77
src/yuzu/util/controller_viewer/controller_base.h
Normal file
@ -0,0 +1,77 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <QColor>
|
||||
#include <QPainter>
|
||||
#include <QPointer>
|
||||
|
||||
#include "common/input.h"
|
||||
#include "common/settings_input.h"
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_types.h"
|
||||
|
||||
namespace ControllerViewer {
|
||||
|
||||
using AnalogParam = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
|
||||
using ButtonParam = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
|
||||
|
||||
enum class Theme {
|
||||
White,
|
||||
Dark,
|
||||
Midnight,
|
||||
};
|
||||
|
||||
// Widget for representing controller animations
|
||||
class ControllerBase {
|
||||
struct ColorMapping {
|
||||
QColor outline{};
|
||||
QColor primary{};
|
||||
QColor left{};
|
||||
QColor right{};
|
||||
QColor button{};
|
||||
QColor button2{};
|
||||
QColor font{};
|
||||
QColor font2{};
|
||||
QColor highlight{};
|
||||
QColor highlight2{};
|
||||
QColor transparent{};
|
||||
QColor indicator{};
|
||||
QColor indicator2{};
|
||||
QColor led_on{};
|
||||
QColor led_off{};
|
||||
QColor slider{};
|
||||
QColor slider_button{};
|
||||
QColor slider_arrow{};
|
||||
QColor deadzone{};
|
||||
QColor charging{};
|
||||
};
|
||||
|
||||
void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right);
|
||||
void DrawJoystickProperties(QPainter& p, QPointF center,
|
||||
const Common::Input::AnalogProperties& properties);
|
||||
|
||||
bool is_controller_set{};
|
||||
bool is_connected{};
|
||||
bool needs_redraw{};
|
||||
Core::HID::NpadStyleIndex controller_type;
|
||||
|
||||
bool mapping_active{};
|
||||
int blink_counter{};
|
||||
int callback_key;
|
||||
QColor button_color{};
|
||||
ColorMapping colors{};
|
||||
Core::HID::LedPattern led_pattern{0, 0, 0, 0};
|
||||
std::size_t player_index{};
|
||||
Core::HID::EmulatedController* controller;
|
||||
std::size_t button_mapping_index{Settings::NativeButton::NumButtons};
|
||||
std::size_t analog_mapping_index{Settings::NativeAnalog::NumAnalogs};
|
||||
Core::HID::ButtonValues button_values{};
|
||||
Core::HID::SticksValues stick_values{};
|
||||
Core::HID::TriggerValues trigger_values{};
|
||||
Core::HID::BatteryValues battery_values{};
|
||||
};
|
||||
|
||||
} // namespace ControllerViewer
|
112
src/yuzu/util/controller_viewer/controller_viewer.cpp
Normal file
112
src/yuzu/util/controller_viewer/controller_viewer.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2022 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "yuzu/util/controller_viewer/controller_viewer.h"
|
||||
|
||||
namespace ControllerViewer {
|
||||
ControllerViewer::ControllerViewer(QWidget* parent) : QFrame(parent) {
|
||||
is_controller_set = false;
|
||||
QTimer* timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, QOverload<>::of(&ControllerViewer::UpdateInput));
|
||||
|
||||
// refresh at 60hz
|
||||
timer->start(16);
|
||||
}
|
||||
|
||||
ControllerViewer::~ControllerViewer() {
|
||||
UnloadController();
|
||||
};
|
||||
|
||||
void ControllerViewer::SetController(Core::HID::EmulatedController* controller_) {
|
||||
UnloadController();
|
||||
is_controller_set = true;
|
||||
controller = controller_;
|
||||
Core::HID::ControllerUpdateCallback engine_callback{
|
||||
.on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
|
||||
.is_npad_service = false,
|
||||
};
|
||||
callback_key = controller->SetCallback(engine_callback);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::All);
|
||||
}
|
||||
|
||||
void ControllerViewer::UnloadController() {
|
||||
if (is_controller_set) {
|
||||
controller->DeleteCallback(callback_key);
|
||||
is_controller_set = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerViewer::BeginMappingButton(std::size_t button_id) {
|
||||
controller_view.BeginMappingButton(button_id);
|
||||
}
|
||||
|
||||
void ControllerViewer::BeginMappingAnalog(std::size_t stick_id) {
|
||||
controller_view.BeginMappingAnalog(stick_id);
|
||||
}
|
||||
|
||||
void ControllerViewer::EndMapping() {
|
||||
controller_view.EndMapping();
|
||||
}
|
||||
|
||||
void ControllerViewer::UpdateColors() {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
controller_view.UpdateColors(Theme::Midnight);
|
||||
return;
|
||||
}
|
||||
|
||||
if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
controller_view.UpdateColors(Theme::Midnight);
|
||||
return;
|
||||
}
|
||||
|
||||
controller_view.UpdateColors(Theme::White);
|
||||
}
|
||||
|
||||
void ControllerViewer::ResetInputs() {
|
||||
controller_view.ResetInputs();
|
||||
}
|
||||
|
||||
void ControllerViewer::ControllerUpdate(Core::HID::ControllerTriggerType type) {
|
||||
if (type == Core::HID::ControllerTriggerType::All) {
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Color);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Type);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Connected);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Button);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Stick);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Trigger);
|
||||
ControllerUpdate(Core::HID::ControllerTriggerType::Battery);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case Core::HID::ControllerTriggerType::Type:
|
||||
controller_type = controller->GetNpadStyleIndex(true);
|
||||
needs_redraw = true;
|
||||
break;
|
||||
default:
|
||||
controller_view.ControllerUpdate(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerViewer::UpdateInput() {
|
||||
controller_view.UpdateInput();
|
||||
}
|
||||
|
||||
void ControllerViewer::paintEvent(QPaintEvent* event) {
|
||||
QFrame::paintEvent(event);
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
const QPointF center = rect().center();
|
||||
|
||||
controller_view.DrawController(p, center);
|
||||
}
|
||||
|
||||
} // namespace ControllerViewer
|
64
src/yuzu/util/controller_viewer/controller_viewer.h
Normal file
64
src/yuzu/util/controller_viewer/controller_viewer.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2022 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <QFrame>
|
||||
#include <QPointer>
|
||||
|
||||
#include "common/input.h"
|
||||
#include "common/settings_input.h"
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_types.h"
|
||||
#include "yuzu/util/controller_viewer/controller_base.h"
|
||||
|
||||
namespace ControllerViewer {
|
||||
|
||||
// Widget for representing controller animations
|
||||
class ControllerViewer : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ControllerViewer(QWidget* parent);
|
||||
~ControllerViewer() override;
|
||||
|
||||
// Sets the emulated controller to be displayed
|
||||
void SetController(Core::HID::EmulatedController* controller);
|
||||
|
||||
// Disables events from the emulated controller
|
||||
void UnloadController();
|
||||
|
||||
// Starts blinking animation at the button specified
|
||||
void BeginMappingButton(std::size_t button_id);
|
||||
|
||||
// Starts moving animation at the stick specified
|
||||
void BeginMappingAnalog(std::size_t stick_id);
|
||||
|
||||
// Stops any ongoing animation
|
||||
void EndMapping();
|
||||
|
||||
// Handles emulated controller events
|
||||
void ControllerUpdate(Core::HID::ControllerTriggerType type);
|
||||
|
||||
// Updates input on sheduled interval
|
||||
void UpdateInput();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
void UpdateColors();
|
||||
void ResetInputs();
|
||||
|
||||
bool is_controller_set{};
|
||||
bool is_connected{};
|
||||
bool needs_redraw{};
|
||||
|
||||
int callback_key;
|
||||
ControllerBase controller_view;
|
||||
Core::HID::EmulatedController* controller;
|
||||
};
|
||||
|
||||
} // namespace ControllerViewer
|
2134
src/yuzu/util/controller_viewer/pro_controller.cpp
Normal file
2134
src/yuzu/util/controller_viewer/pro_controller.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
src/yuzu/util/controller_viewer/pro_controller.h
Normal file
28
src/yuzu/util/controller_viewer/pro_controller.h
Normal file
@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <QFrame>
|
||||
#include <QPointer>
|
||||
|
||||
#include "util\controller_viewer\controller_base.h"
|
||||
|
||||
// Widget for representing controller animations
|
||||
class ProController : public PlayerControllerBase {
|
||||
void UpdateColors();
|
||||
void ResetInputs();
|
||||
|
||||
void DrawProController(QPainter& p, QPointF center);
|
||||
|
||||
void DrawGCBody(QPainter& p, QPointF center);
|
||||
|
||||
// Draw triggers functions
|
||||
void DrawProTriggers(QPainter& p, QPointF center,
|
||||
const Common::Input::ButtonStatus& left_pressed,
|
||||
const Common::Input::ButtonStatus& right_pressed);
|
||||
|
||||
void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar,
|
||||
const Common::Input::ButtonStatus& pressed);
|
||||
};
|
Reference in New Issue
Block a user