Merge pull request #12492 from AdmiralCurtiss/wiimote-ir-passthrough

Implement IR passthrough for emulated Wiimotes
This commit is contained in:
Admiral H. Curtiss 2024-03-12 03:27:07 +01:00 committed by GitHub
commit 72bcdadc16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 242 additions and 25 deletions

View File

@ -7,6 +7,19 @@ Buttons/2 = `2`
Buttons/- = `-`
Buttons/+ = `+`
Buttons/Home = `HOME`
IRPassthrough/Enabled = False
IRPassthrough/Object 1 X = `IR Object 1 X`
IRPassthrough/Object 1 Y = `IR Object 1 Y`
IRPassthrough/Object 1 Size = `IR Object 1 Size`
IRPassthrough/Object 2 X = `IR Object 2 X`
IRPassthrough/Object 2 Y = `IR Object 2 Y`
IRPassthrough/Object 2 Size = `IR Object 2 Size`
IRPassthrough/Object 3 X = `IR Object 3 X`
IRPassthrough/Object 3 Y = `IR Object 3 Y`
IRPassthrough/Object 3 Size = `IR Object 3 Size`
IRPassthrough/Object 4 X = `IR Object 4 X`
IRPassthrough/Object 4 Y = `IR Object 4 Y`
IRPassthrough/Object 4 Size = `IR Object 4 Size`
IMUAccelerometer/Up = `Accel Up`
IMUAccelerometer/Down = `Accel Down`
IMUAccelerometer/Left = `Accel Left`

View File

@ -125,13 +125,14 @@ struct NoExt : virtual DataReportManipulator
u8* GetExtDataPtr() override { return nullptr; }
};
template <u32 Offset, u32 Length, u32 DataOffset = 0>
template <IRReportFormat Format, u32 Offset, u32 Length, u32 DataOffset = 0>
struct IncludeIR : virtual DataReportManipulator
{
u32 GetIRDataSize() const override { return Length; }
const u8* GetIRDataPtr() const override { return data_ptr + Offset; }
u8* GetIRDataPtr() override { return data_ptr + Offset; }
u32 GetIRDataFormatOffset() const override { return DataOffset; }
IRReportFormat GetIRReportFormat() const override { return Format; }
};
struct NoIR : virtual DataReportManipulator
@ -140,6 +141,7 @@ struct NoIR : virtual DataReportManipulator
const u8* GetIRDataPtr() const override { return nullptr; }
u8* GetIRDataPtr() override { return nullptr; }
u32 GetIRDataFormatOffset() const override { return 0; }
IRReportFormat GetIRReportFormat() const override { return IRReportFormat::None; }
};
#ifdef _MSC_VER
@ -162,7 +164,10 @@ struct ReportCoreExt8 : IncludeCore, NoAccel, NoIR, IncludeExt<2, 8>
{
};
struct ReportCoreAccelIR12 : IncludeCore, IncludeAccel, IncludeIR<5, 12>, NoExt
struct ReportCoreAccelIR12 : IncludeCore,
IncludeAccel,
IncludeIR<IRReportFormat::Extended, 5, 12>,
NoExt
{
u32 GetDataSize() const override { return 17; }
};
@ -175,11 +180,17 @@ struct ReportCoreAccelExt16 : IncludeCore, IncludeAccel, NoIR, IncludeExt<5, 16>
{
};
struct ReportCoreIR10Ext9 : IncludeCore, NoAccel, IncludeIR<2, 10>, IncludeExt<12, 9>
struct ReportCoreIR10Ext9 : IncludeCore,
NoAccel,
IncludeIR<IRReportFormat::Basic, 2, 10>,
IncludeExt<12, 9>
{
};
struct ReportCoreAccelIR10Ext6 : IncludeCore, IncludeAccel, IncludeIR<5, 10>, IncludeExt<15, 6>
struct ReportCoreAccelIR10Ext6 : IncludeCore,
IncludeAccel,
IncludeIR<IRReportFormat::Basic, 5, 10>,
IncludeExt<15, 6>
{
};
@ -187,7 +198,7 @@ struct ReportExt21 : NoCore, NoAccel, NoIR, IncludeExt<0, 21>
{
};
struct ReportInterleave1 : IncludeCore, IncludeIR<3, 18, 0>, NoExt
struct ReportInterleave1 : IncludeCore, IncludeIR<IRReportFormat::Full1, 3, 18, 0>, NoExt
{
// FYI: Only 8-bits of precision in this report, and no Y axis.
void GetAccelData(AccelData* accel) const override
@ -220,7 +231,7 @@ struct ReportInterleave1 : IncludeCore, IncludeIR<3, 18, 0>, NoExt
u32 GetDataSize() const override { return 21; }
};
struct ReportInterleave2 : IncludeCore, IncludeIR<3, 18, 18>, NoExt
struct ReportInterleave2 : IncludeCore, IncludeIR<IRReportFormat::Full2, 3, 18, 18>, NoExt
{
// FYI: Only 8-bits of precision in this report, and no X axis.
void GetAccelData(AccelData* accel) const override
@ -372,6 +383,11 @@ u32 DataReportBuilder::GetIRDataFormatOffset() const
return m_manip->GetIRDataFormatOffset();
}
IRReportFormat DataReportBuilder::GetIRReportFormat() const
{
return m_manip->GetIRReportFormat();
}
void DataReportBuilder::GetCoreData(CoreData* core) const
{
m_manip->GetCoreData(core);

View File

@ -39,6 +39,7 @@ public:
virtual const u8* GetIRDataPtr() const = 0;
virtual u32 GetIRDataSize() const = 0;
virtual u32 GetIRDataFormatOffset() const = 0;
virtual IRReportFormat GetIRReportFormat() const = 0;
virtual u8* GetExtDataPtr() = 0;
virtual const u8* GetExtDataPtr() const = 0;
@ -76,6 +77,7 @@ public:
u32 GetExtDataSize() const;
u32 GetIRDataFormatOffset() const;
IRReportFormat GetIRReportFormat() const;
void GetCoreData(CoreData*) const;
void GetAccelData(AccelData*) const;

View File

@ -50,6 +50,15 @@ enum class OutputReportID : u8
IRLogicEnable2 = 0x1a,
};
enum class IRReportFormat : u8
{
None,
Basic, // from ReportCoreIR10Ext9 or ReportCoreAccelIR10Ext6
Extended, // from ReportCoreAccelIR12
Full1, // from ReportInterleave1
Full2, // from ReportInterleave2
};
enum class LED : u8
{
None = 0x00,

View File

@ -59,7 +59,7 @@ CameraLogic::GetCameraPoints(const Common::Matrix44& transform, Common::Vec2 fie
using Common::Vec3;
using Common::Vec4;
const std::array<Vec3, NUM_POINTS> leds{
const std::array<Vec3, 2> leds{
Vec3{-SENSOR_BAR_LED_SEPARATION / 2, 0, 0},
Vec3{SENSOR_BAR_LED_SEPARATION / 2, 0, 0},
};
@ -68,7 +68,7 @@ CameraLogic::GetCameraPoints(const Common::Matrix44& transform, Common::Vec2 fie
Matrix44::Perspective(field_of_view.y, field_of_view.x / field_of_view.y, 0.001f, 1000) *
Matrix44::FromMatrix33(Matrix33::RotateX(float(MathUtil::TAU / 4))) * transform;
std::array<CameraPoint, leds.size()> camera_points;
std::array<CameraPoint, CameraLogic::NUM_POINTS> camera_points;
std::transform(leds.begin(), leds.end(), camera_points.begin(), [&](const Vec3& v) {
const auto point = camera_view * Vec4(v, 1.0);

View File

@ -126,7 +126,7 @@ public:
// FYI: A real wiimote normally only returns 1 point for each LED cluster (2 total).
// Sending all 4 points can actually cause some stuttering issues.
static constexpr int NUM_POINTS = 2;
static constexpr int NUM_POINTS = 4;
// Range from 0-15. Small values (2-4) seem to be very typical.
// This is reduced based on distance from sensor bar.

View File

@ -82,7 +82,7 @@ SerializedWiimoteState SerializeDesiredState(const DesiredWiimoteState& state)
if (has_camera)
{
for (size_t i = 0; i < 2; ++i)
for (size_t i = 0; i < state.camera_points.size(); ++i)
{
const u16 camera_x = state.camera_points[i].position.x; // 10 bits
const u16 camera_y = state.camera_points[i].position.y; // 10 bits
@ -178,7 +178,7 @@ bool DeserializeDesiredState(DesiredWiimoteState* state, const SerializedWiimote
else if (has_accel)
s += 4;
if (has_camera)
s += 6;
s += 12;
if (has_motion_plus)
s += 6;
switch (extension)
@ -260,7 +260,7 @@ bool DeserializeDesiredState(DesiredWiimoteState* state, const SerializedWiimote
if (has_camera)
{
for (size_t i = 0; i < 2; ++i)
for (size_t i = 0; i < state->camera_points.size(); ++i)
{
const u8 camera_misc = d[pos];
const u8 camera_x_high = d[pos + 1];

View File

@ -21,11 +21,12 @@ struct DesiredWiimoteState
{Wiimote::ACCEL_ZERO_G << 2, Wiimote::ACCEL_ZERO_G << 2, Wiimote::ACCEL_ONE_G << 2});
// No light detected by the IR camera.
static constexpr std::array<CameraPoint, 2> DEFAULT_CAMERA = {CameraPoint(), CameraPoint()};
static constexpr std::array<CameraPoint, 4> DEFAULT_CAMERA = {CameraPoint(), CameraPoint(),
CameraPoint(), CameraPoint()};
WiimoteCommon::ButtonData buttons{}; // non-button state in this is ignored
WiimoteCommon::AccelData acceleration = DEFAULT_ACCELERATION;
std::array<CameraPoint, 2> camera_points = DEFAULT_CAMERA;
std::array<CameraPoint, 4> camera_points = DEFAULT_CAMERA;
std::optional<MotionPlus::DataFormat::Data> motion_plus = std::nullopt;
DesiredExtensionState extension;
};
@ -34,7 +35,7 @@ struct DesiredWiimoteState
struct SerializedWiimoteState
{
u8 length;
std::array<u8, 24> data; // 12 bytes Wiimote, 6 bytes MotionPlus, 6 bytes Extension
std::array<u8, 30> data; // 18 bytes Wiimote, 6 bytes MotionPlus, 6 bytes Extension
};
SerializedWiimoteState SerializeDesiredState(const DesiredWiimoteState& state);

View File

@ -49,6 +49,7 @@
#include "InputCommon/ControllerEmu/ControlGroup/IMUAccelerometer.h"
#include "InputCommon/ControllerEmu/ControlGroup/IMUCursor.h"
#include "InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.h"
#include "InputCommon/ControllerEmu/ControlGroup/IRPassthrough.h"
#include "InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.h"
#include "InputCommon/ControllerEmu/ControlGroup/Tilt.h"
@ -250,6 +251,8 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), m_bt_device_index(i
_trans("Camera field of view (affects sensitivity of pointing).")},
fov_default.y, 0.01, 180);
groups.emplace_back(m_ir_passthrough = new ControllerEmu::IRPassthrough(
IR_PASSTHROUGH_GROUP, _trans("Point (Passthrough)")));
groups.emplace_back(m_imu_accelerometer = new ControllerEmu::IMUAccelerometer(
ACCELEROMETER_GROUP, _trans("Accelerometer")));
groups.emplace_back(m_imu_gyroscope =
@ -360,6 +363,8 @@ ControllerEmu::ControlGroup* Wiimote::GetWiimoteGroup(WiimoteGroup group) const
return m_imu_gyroscope;
case WiimoteGroup::IMUPoint:
return m_imu_ir;
case WiimoteGroup::IRPassthrough:
return m_ir_passthrough;
default:
ASSERT(false);
return nullptr;
@ -447,6 +452,33 @@ void Wiimote::UpdateButtonsStatus(const DesiredWiimoteState& target_state)
m_status.buttons.hex = target_state.buttons.hex & ButtonData::BUTTON_MASK;
}
static std::array<CameraPoint, CameraLogic::NUM_POINTS>
GetPassthroughCameraPoints(ControllerEmu::IRPassthrough* ir_passthrough)
{
std::array<CameraPoint, CameraLogic::NUM_POINTS> camera_points;
for (size_t i = 0; i < camera_points.size(); ++i)
{
const ControlState size = ir_passthrough->GetObjectSize(i);
if (size <= 0.0f)
continue;
const ControlState x = ir_passthrough->GetObjectPositionX(i);
const ControlState y = ir_passthrough->GetObjectPositionY(i);
camera_points[i].position.x =
std::clamp(std::lround(x * ControlState(CameraLogic::CAMERA_RES_X - 1)), long(0),
long(CameraLogic::CAMERA_RES_X - 1));
camera_points[i].position.y =
std::clamp(std::lround(y * ControlState(CameraLogic::CAMERA_RES_Y - 1)), long(0),
long(CameraLogic::CAMERA_RES_Y - 1));
camera_points[i].size =
std::clamp(std::lround(size * ControlState(CameraLogic::MAX_POINT_SIZE)), long(0),
long(CameraLogic::MAX_POINT_SIZE));
}
return camera_points;
}
void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state,
SensorBarState sensor_bar_state)
{
@ -470,7 +502,11 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state,
ConvertAccelData(GetTotalAcceleration(), ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2);
// Calculate IR camera state.
if (sensor_bar_state == SensorBarState::Enabled)
if (m_ir_passthrough->enabled)
{
target_state->camera_points = GetPassthroughCameraPoints(m_ir_passthrough);
}
else if (sensor_bar_state == SensorBarState::Enabled)
{
target_state->camera_points = CameraLogic::GetCameraPoints(
GetTotalTransformation(),
@ -762,6 +798,12 @@ void Wiimote::LoadDefaults(const ControllerInterface& ciface)
m_imu_gyroscope->SetControlExpression(3, "`Gyro Roll Right`");
m_imu_gyroscope->SetControlExpression(4, "`Gyro Yaw Left`");
m_imu_gyroscope->SetControlExpression(5, "`Gyro Yaw Right`");
for (int i = 0; i < 4; ++i)
{
m_ir_passthrough->SetControlExpression(i * 3 + 0, fmt::format("`IR Object {} X`", i + 1));
m_ir_passthrough->SetControlExpression(i * 3 + 1, fmt::format("`IR Object {} Y`", i + 1));
m_ir_passthrough->SetControlExpression(i * 3 + 2, fmt::format("`IR Object {} Size`", i + 1));
}
#endif
// Enable Nunchuk:

View File

@ -34,6 +34,7 @@ class Force;
class IMUAccelerometer;
class IMUGyroscope;
class IMUCursor;
class IRPassthrough;
class ModifySettingsButton;
class Output;
class Tilt;
@ -59,6 +60,7 @@ enum class WiimoteGroup
IMUAccelerometer,
IMUGyroscope,
IMUPoint,
IRPassthrough,
};
enum class NunchukGroup;
@ -121,6 +123,7 @@ public:
static constexpr const char* ACCELEROMETER_GROUP = "IMUAccelerometer";
static constexpr const char* GYROSCOPE_GROUP = "IMUGyroscope";
static constexpr const char* IR_GROUP = "IR";
static constexpr const char* IR_PASSTHROUGH_GROUP = "IRPassthrough";
static constexpr const char* A_BUTTON = "A";
static constexpr const char* B_BUTTON = "B";
@ -300,6 +303,7 @@ private:
ControllerEmu::IMUAccelerometer* m_imu_accelerometer;
ControllerEmu::IMUGyroscope* m_imu_gyroscope;
ControllerEmu::IMUCursor* m_imu_ir;
ControllerEmu::IRPassthrough* m_ir_passthrough;
ControllerEmu::SettingValue<bool> m_sideways_setting;
ControllerEmu::SettingValue<bool> m_upright_setting;

View File

@ -504,6 +504,7 @@
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\IMUAccelerometer.h" />
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\IMUCursor.h" />
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\IMUGyroscope.h" />
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\IRPassthrough.h" />
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\MixedTriggers.h" />
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\ModifySettingsButton.h" />
<ClInclude Include="InputCommon\ControllerEmu\ControlGroup\Slider.h" />
@ -1162,6 +1163,7 @@
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\IMUAccelerometer.cpp" />
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\IMUCursor.cpp" />
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\IMUGyroscope.cpp" />
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\IRPassthrough.cpp" />
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\MixedTriggers.cpp" />
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\ModifySettingsButton.cpp" />
<ClCompile Include="InputCommon\ControllerEmu\ControlGroup\Slider.cpp" />

View File

@ -48,6 +48,8 @@ void WiimoteEmuMotionControlIMU::CreateMainLayout()
auto* groups_layout = new QHBoxLayout();
groups_layout->addWidget(
CreateGroupBox(Wiimote::GetWiimoteGroup(GetPort(), WiimoteEmu::WiimoteGroup::IMUPoint)));
groups_layout->addWidget(
CreateGroupBox(Wiimote::GetWiimoteGroup(GetPort(), WiimoteEmu::WiimoteGroup::IRPassthrough)));
groups_layout->addWidget(CreateGroupBox(
Wiimote::GetWiimoteGroup(GetPort(), WiimoteEmu::WiimoteGroup::IMUAccelerometer)));
groups_layout->addWidget(

View File

@ -37,6 +37,8 @@ add_library(inputcommon
ControllerEmu/ControlGroup/IMUCursor.h
ControllerEmu/ControlGroup/IMUGyroscope.cpp
ControllerEmu/ControlGroup/IMUGyroscope.h
ControllerEmu/ControlGroup/IRPassthrough.cpp
ControllerEmu/ControlGroup/IRPassthrough.h
ControllerEmu/ControlGroup/MixedTriggers.cpp
ControllerEmu/ControlGroup/MixedTriggers.h
ControllerEmu/ControlGroup/ModifySettingsButton.cpp

View File

@ -49,7 +49,8 @@ enum class GroupType
Shake,
IMUAccelerometer,
IMUGyroscope,
IMUCursor
IMUCursor,
IRPassthrough,
};
class ControlGroup

View File

@ -0,0 +1,51 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "InputCommon/ControllerEmu/ControlGroup/IRPassthrough.h"
#include <memory>
#include <string>
#include "Common/Common.h"
#include "Common/MathUtil.h"
#include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerEmu/Control/Control.h"
#include "InputCommon/ControllerEmu/Control/Input.h"
namespace ControllerEmu
{
IRPassthrough::IRPassthrough(std::string name_, std::string ui_name_)
: ControlGroup(std::move(name_), std::move(ui_name_), GroupType::IRPassthrough,
ControlGroup::DefaultValue::Disabled)
{
AddInput(Translatability::Translate, _trans("Object 1 X"));
AddInput(Translatability::Translate, _trans("Object 1 Y"));
AddInput(Translatability::Translate, _trans("Object 1 Size"));
AddInput(Translatability::Translate, _trans("Object 2 X"));
AddInput(Translatability::Translate, _trans("Object 2 Y"));
AddInput(Translatability::Translate, _trans("Object 2 Size"));
AddInput(Translatability::Translate, _trans("Object 3 X"));
AddInput(Translatability::Translate, _trans("Object 3 Y"));
AddInput(Translatability::Translate, _trans("Object 3 Size"));
AddInput(Translatability::Translate, _trans("Object 4 X"));
AddInput(Translatability::Translate, _trans("Object 4 Y"));
AddInput(Translatability::Translate, _trans("Object 4 Size"));
}
ControlState IRPassthrough::GetObjectPositionX(size_t object_index) const
{
return controls[object_index * 3 + 0]->GetState();
}
ControlState IRPassthrough::GetObjectPositionY(size_t object_index) const
{
return controls[object_index * 3 + 1]->GetState();
}
ControlState IRPassthrough::GetObjectSize(size_t object_index) const
{
return controls[object_index * 3 + 2]->GetState();
}
} // namespace ControllerEmu

View File

@ -0,0 +1,23 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <string>
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"
namespace ControllerEmu
{
class IRPassthrough : public ControlGroup
{
public:
IRPassthrough(std::string name, std::string ui_name);
ControlState GetObjectPositionX(size_t object_index) const;
ControlState GetObjectPositionY(size_t object_index) const;
ControlState GetObjectSize(size_t object_index) const;
};
} // namespace ControllerEmu

View File

@ -201,6 +201,17 @@ Device::Device(std::unique_ptr<WiimoteReal::Wiimote> wiimote) : m_wiimote(std::m
AddInput(new UndetectableAnalogInput<float>(&m_ir_state.distance, "IR Distance", 1));
// Raw IR Objects.
for (std::size_t i = 0; i < 4; ++i)
{
AddInput(new UndetectableAnalogInput<float>(&m_ir_state.raw_ir_object_position[i].x,
fmt::format("IR Object {} X", i + 1), 1));
AddInput(new UndetectableAnalogInput<float>(&m_ir_state.raw_ir_object_position[i].y,
fmt::format("IR Object {} Y", i + 1), 1));
AddInput(new UndetectableAnalogInput<float>(&m_ir_state.raw_ir_object_size[i],
fmt::format("IR Object {} Size", i + 1), 1));
}
// Raw gyroscope.
static constexpr std::array<std::array<const char*, 2>, 3> gyro_names = {{
{"Gyro Pitch Down", "Gyro Pitch Up"},
@ -1178,8 +1189,7 @@ void Device::ProcessInputReport(WiimoteReal::Report& report)
// Process IR data.
if (manipulator->HasIR() && m_ir_state.IsFullyConfigured())
{
m_ir_state.ProcessData(
Common::BitCastPtr<std::array<WiimoteEmu::IRBasic, 2>>(manipulator->GetIRDataPtr()));
m_ir_state.ProcessData(*manipulator);
}
// Process extension data.
@ -1251,7 +1261,7 @@ void Device::UpdateOrientation()
float(MathUtil::PI);
}
void Device::IRState::ProcessData(const std::array<WiimoteEmu::IRBasic, 2>& data)
void Device::IRState::ProcessData(const DataReportManipulator& manipulator)
{
// A better implementation might extrapolate points when they fall out of camera view.
// But just averaging visible points actually seems to work very well.
@ -1263,18 +1273,54 @@ void Device::IRState::ProcessData(const std::array<WiimoteEmu::IRBasic, 2>& data
const auto camera_max = IRObject(WiimoteEmu::CameraLogic::CAMERA_RES_X - 1,
WiimoteEmu::CameraLogic::CAMERA_RES_Y - 1);
const auto add_point = [&](IRObject point) {
const auto add_point = [&](IRObject point, u8 size, size_t idx) {
// Non-visible points are 0xFF-filled.
if (point.y > camera_max.y)
{
raw_ir_object_position[idx].x = 0.0f;
raw_ir_object_position[idx].y = 0.0f;
raw_ir_object_size[idx] = 0.0f;
return;
}
raw_ir_object_position[idx].x = static_cast<float>(point.x) / camera_max.x;
raw_ir_object_position[idx].y = static_cast<float>(point.y) / camera_max.y;
raw_ir_object_size[idx] = static_cast<float>(size) / 15.0f;
points.Push(Common::Vec2(point));
};
for (auto& block : data)
size_t object_index = 0;
switch (manipulator.GetIRReportFormat())
{
add_point(block.GetObject1());
add_point(block.GetObject2());
case IRReportFormat::Basic:
{
const std::array<WiimoteEmu::IRBasic, 2> data =
Common::BitCastPtr<std::array<WiimoteEmu::IRBasic, 2>>(manipulator.GetIRDataPtr());
for (const auto& block : data)
{
// size is not reported by IRBasic, just assume a typical size
add_point(block.GetObject1(), 2, object_index);
++object_index;
add_point(block.GetObject2(), 2, object_index);
++object_index;
}
break;
}
case IRReportFormat::Extended:
{
const std::array<WiimoteEmu::IRExtended, 4> data =
Common::BitCastPtr<std::array<WiimoteEmu::IRExtended, 4>>(manipulator.GetIRDataPtr());
for (const auto& object : data)
{
add_point(object.GetPosition(), object.size, object_index);
++object_index;
}
break;
}
default:
// unsupported format
return;
}
is_hidden = !points.Count();

View File

@ -126,7 +126,7 @@ private:
{
static u32 GetDesiredIRSensitivity();
void ProcessData(const std::array<WiimoteEmu::IRBasic, 2>&);
void ProcessData(const DataReportManipulator& manipulator);
bool IsFullyConfigured() const;
u32 current_sensitivity = u32(-1);
@ -139,6 +139,9 @@ private:
float distance = 0;
bool is_hidden = true;
std::array<Common::Vec2, 4> raw_ir_object_position;
std::array<float, 4> raw_ir_object_size;
};
class ReportHandler