Commit f9968ff4 authored by 957dd's avatar 957dd

Initial commit

parents
# Visual Studio
.vs/
[Dd]ebug/
[Rr]elease/
x64/
x86/
ARM/
ARM64/
*.aps
*.bak
*.cache
*.db
*.opendb
*.sdf
*.suo
*.user
*.userosscache
*.sln.docstates
*.exe.WebView2/
# Build Output
*.exe
*.dll
*.pdb
*.ilk
*.exp
*.lib
*.obj
*.iobj
*.ipdb
*.log
*.tlog
# Project Specific
config.ini
steer_url/x64/
steer_url/Debug/
steer_url/Release/
# External / Local
packages/
node_modules/
temp/
tmp/
# MozaR3CenterOnly - WebView2 赛车终助手
本项目是一个高性能的 Windows 应用程序,它封装了一个赛车网页 (`https://fcrs.tentmall.cn/flyPC/#/`),并集成了 **MOZA R3** 方向盘硬件,实现了用力反馈 (FFB) 和输入控制。
## 项目特性
- **500Hz 硬件轮询**:提供极速、丝滑的方向盘和踏板数据读取。
- **无边框全屏**:沉浸式 Kiosk 模式(按 **ESC** 键可一键退出到窗口模式进行设置)。
- **开机自启**:可选集成到 Windows 启动项。
- **后台自动重连**:当程序从后台切换回前台时,自动重新挂载硬件,无需手动操作。
- **个性化品牌**:完美集成自定义赛车图标。
## 开发环境与准备工作
要编译本项目,您需要 **Visual Studio 2019 或 2022**,并安装 **“使用 C++ 的桌面开发”** 工作负载。
### 1. 安装 WebView2 SDK (必须)
浏览器引擎依赖于微软的 WebView2 SDK:
1. 在 Visual Studio 中打开解决方案 (`steer_url.sln`)。
2. 在解决方案资源管理器中右键点击 **steer_url** 项目。
3. 选择 **“管理 NuGet 程序包...”**
4. 搜索 **`Microsoft.Web.WebView2`**
5. 点击 **“安装”**
### 2. MOZA SDK (已包含)
MOZA 硬件 SDK 已通过 `third_party/moza` 目录集成到项目代码中,**无需**额外下载或安装任何库。
## 编译指南
1. 将配置设置为 **Release**,平台设置为 **x64**
2. 点击 **生成 (Build)** -> **重新生成解决方案 (Rebuild Solution)**
3. 编译成功的 .exe 文件和必要的 DLL 将位于 `x64/Release/` 目录下。
## 运行与发布
发布时,请确保以下文件位于同一目录下:
- `steer_url.exe` (主程序)
- `MOZA_SDK.dll` (硬件驱动库,需从 `third_party/moza/bin/x64` 复制到此处)
- `WebView2Loader.dll` (浏览器核心)
> **贴士**:为了方便开发,您可以在 VS 项目属性的 **“生成事件 -> 生成后事件”** 中添加以下命令,让系统自动为您复制 DLL:
> `copy /Y "$(ProjectDir)third_party\moza\bin\x64\MOZA_SDK.dll" "$(OutDir)MOZA_SDK.dll"`
- `www/` (资源文件夹,包含图标)
- `config.ini` (保存您的设置)
---
*专为 MOZA R3 硬件集成定制。*

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36623.8 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "steer_url", "steer_url\steer_url.vcxproj", "{7F3B8DDD-AD8D-417B-8193-A02B136442F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Debug|x64.ActiveCfg = Debug|x64
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Debug|x64.Build.0 = Debug|x64
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Debug|x86.ActiveCfg = Debug|Win32
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Debug|x86.Build.0 = Debug|Win32
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Release|x64.ActiveCfg = Release|x64
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Release|x64.Build.0 = Release|x64
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Release|x86.ActiveCfg = Release|Win32
{7F3B8DDD-AD8D-417B-8193-A02B136442F2}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {90990069-BBDD-49BA-9099-DB1933840305}
EndGlobalSection
EndGlobal
#include "MozaController.h"
#include <iostream>
#include <chrono>
#include <cmath>
#include <algorithm>
#include <string>
#include <sstream>
namespace {
void DebugLog(const std::string& msg) {
OutputDebugStringA(("[MOZA] " + msg + "\n").c_str());
}
const char* ErrorCodeToString(ERRORCODE code) {
switch (code) {
case NORMAL: return "NORMAL";
case NOINSTALLSDK: return "NOINSTALLSDK";
case NODEVICES: return "NODEVICES";
case OUTOFRANGE: return "OUTOFRANGE";
case PARAMETERERR: return "PARAMETERERR";
case COLLECTIONCYCLEDATALOSS: return "COLLECTIONCYCLEDATALOSS";
case CREATEFFECTERR: return "CREATEFFECTERR";
case ENCODINGFAILED: return "ENCODINGFAILED";
case FFBERR: return "FFBERR";
case FIRMWARETOOOLD: return "FIRMWARETOOOLD";
case PITHOUSENOTREADY: return "PITHOUSENOTREADY";
default: return "UNKNOWN";
}
}
void PrintError(const char* step, ERRORCODE code) {
std::stringstream ss;
ss << "[ERROR] " << step << " failed: " << ErrorCodeToString(code) << " (" << static_cast<int>(code) << ")";
DebugLog(ss.str());
}
template <typename Fn>
bool TryEffectCall(const char* step, Fn&& fn) {
try {
fn();
return true;
} catch (const std::exception& e) {
std::stringstream ss;
ss << "[WARN] " << step << " exception: " << e.what();
DebugLog(ss.str());
} catch (...) {
DebugLog(std::string("[WARN] ") + step + " unknown exception.");
}
return false;
}
}
MozaController::MozaController()
: m_sdkInstalled(false), m_running(false), m_hwnd(nullptr), m_lastAngle(0.0f), m_hasLastAngle(false) {
m_lastTs = std::chrono::steady_clock::now();
m_nextRenewTime = m_lastTs;
m_nextPrintTime = m_lastTs;
}
MozaController::~MozaController() {
Stop();
}
void MozaController::InitializeHardware(HWND hWnd) {
m_hwnd = hWnd;
moza::installMozaSDK();
m_sdkInstalled = true;
m_running = false;
DebugLog("SDK Installed. Waiting for wheelbase asynchronously...");
}
void MozaController::Update() {
if (!m_sdkInstalled) return;
const auto now = std::chrono::steady_clock::now();
if (!m_running) {
if (now >= m_nextRenewTime) {
ERRORCODE err = NORMAL;
const char* wheelbase = moza::getDeviceParent(PRODUCT_WHEELBASE, err);
if (err == NORMAL && wheelbase != nullptr && wheelbase[0] != '\0') {
std::stringstream ss;
ss << "Wheelbase detected: " << wheelbase;
DebugLog(ss.str());
HWND desktopHwnd = GetDesktopWindow();
if (CreateAndStartCenterForce(m_hwnd, desktopHwnd)) {
// Standard settings
moza::setMotorFfbStrength(100);
moza::setMotorPeakTorque(100);
moza::setMotorSpringStrength(0);
moza::setMotorNaturalDamper(45);
moza::setMotorSpeedDamping(15);
moza::setMotorHandsOffProtection(0);
m_running = true;
m_nextRenewTime = now + std::chrono::milliseconds(59800);
DebugLog("Hardware Ready. Main thread control active.");
} else {
DebugLog("[ERROR] Failed to start center force. Will retry...");
}
} else {
DebugLog("Waiting for wheelbase connection...");
}
if (!m_running) {
m_nextRenewTime = now + std::chrono::milliseconds(500);
}
}
return;
}
ERRORCODE hidErr = NORMAL;
const HIDData* hid = moza::getHIDData(hidErr);
float angleDeg = 0.0f;
bool angleValid = false;
float velocityDegPerSec = 0.0f;
if (hidErr == NORMAL && hid != nullptr) {
if (!std::isnan(hid->fSteeringWheelAngle)) {
angleDeg = hid->fSteeringWheelAngle;
angleValid = true;
}
if (!std::isnan(hid->fSteeringWheelVelocity)) {
velocityDegPerSec = hid->fSteeringWheelVelocity;
}
}
if (angleValid) {
if (std::isnan(velocityDegPerSec) || velocityDegPerSec == 0.0f) {
if (m_hasLastAngle) {
const float dt = std::chrono::duration<float>(now - m_lastTs).count();
if (dt > 0.0001f) {
velocityDegPerSec = (angleDeg - m_lastAngle) / dt;
}
}
}
m_lastAngle = angleDeg;
m_lastTs = now;
m_hasLastAngle = true;
} else if (m_hasLastAngle) {
angleDeg = m_lastAngle;
angleValid = true;
}
constexpr float kDeadzoneDeg = 1.5f;
constexpr float kKp = 50.0f;
constexpr float kKd = 0.8f;
constexpr float kMaxTorque = 6500.0f;
float torque = 0.0f;
if (angleValid && std::fabs(angleDeg) > kDeadzoneDeg) {
const float command = (kKp * angleDeg + kKd * velocityDegPerSec);
torque = kMaxTorque * std::tanh(command / kMaxTorque);
}
torque = std::clamp(torque, -kMaxTorque, kMaxTorque);
if (m_centerForce) {
bool magnitudeOk = TryEffectCall("centerForce->setMagnitude", [&]() {
m_centerForce->setMagnitude(static_cast<long>(torque));
});
if (!magnitudeOk) {
DebugLog("[WARN] Effect lost (likely backgrounded). Dropping connection to standby mode...");
moza::stopForceFeedback();
m_centerForce.reset();
m_running = false;
}
}
if (m_running && now >= m_nextRenewTime) {
if (m_centerForce && !TryEffectCall("centerForce->start(renew)", [&]() { m_centerForce->start(); })) {
DebugLog("[WARN] Effect renew failed (likely backgrounded). Dropping connection to standby mode...");
moza::stopForceFeedback();
m_centerForce.reset();
m_running = false;
} else {
m_nextRenewTime = now + std::chrono::milliseconds(59800);
}
}
if (now >= m_nextPrintTime) {
std::stringstream ss;
ss << "[CENTER] angle=" << angleDeg
<< " vel=" << velocityDegPerSec
<< " torque=" << static_cast<long>(torque);
DebugLog(ss.str());
m_nextPrintTime = now + std::chrono::milliseconds(1000);
}
}
void MozaController::Stop() {
m_running = false;
if (m_centerForce) {
m_centerForce.reset();
}
moza::stopForceFeedback();
moza::removeMozaSDK();
}
bool MozaController::CreateAndStartCenterForce(HWND primaryHwnd, HWND desktopHwnd) {
ERRORCODE err = NORMAL;
// 恢复为尝试主窗口 -> 桌面窗口,不使用全局 nullptr 避免按键被驱动全局吃掉
const HWND startHandles[2] = { primaryHwnd, desktopHwnd };
const char* startNames[2] = { "app-window", "desktop-window" };
constexpr unsigned long kDurationMs = 60000;
for (int i = 0; i < 2; ++i) {
if (startHandles[i] == nullptr) continue;
err = NORMAL;
m_centerForce = moza::createWheelbaseETConstantForce(startHandles[i], err);
if (m_centerForce == nullptr || err != NORMAL) {
PrintError("createWheelbaseETConstantForce", err);
continue;
}
m_centerForce->setGain(10000);
m_centerForce->setDuration(kDurationMs);
m_centerForce->setAttackTime(5);
m_centerForce->setFadeTime(10);
m_centerForce->setMagnitude(0);
if (TryEffectCall("centerForce->start", [&]() { m_centerForce->start(); })) {
std::stringstream ss;
ss << "[INFO] Center force started with " << startNames[i];
DebugLog(ss.str());
return true;
}
}
return false;
}
#pragma once
#include <windows.h>
#include <memory>
#include <thread>
#include <atomic>
#include "mozaAPI.h"
class MozaController {
public:
MozaController();
~MozaController();
void InitializeHardware(HWND hWnd);
void Update(); // 每一帧调用的更新逻辑
void Stop();
private:
bool CreateAndStartCenterForce(HWND primaryHwnd, HWND desktopHwnd);
std::shared_ptr<RS21::direct_input::ETConstantForce> m_centerForce;
std::atomic<bool> m_running;
bool m_sdkInstalled;
HWND m_hwnd;
// 状态追踪 (用于模拟程序循环逻辑)
float m_lastAngle;
std::chrono::steady_clock::time_point m_lastTs;
std::chrono::steady_clock::time_point m_nextRenewTime;
std::chrono::steady_clock::time_point m_nextPrintTime;
bool m_hasLastAngle;
};
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 使用者 steer_url.rc
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_STEERURL_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_STEERURL 107
#define IDI_SMALL 108
#define IDC_STEERURL 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
// 新对象的下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 130
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
// header.h: 标准系统包含文件的包含文件,
// 或特定于项目的包含文件
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MOZA R3 Control Dashboard</title>
<style>
:root {
--primary: #00f2fe;
--secondary: #4facfe;
--bg: #0f172a;
--card: #1e293b;
}
body {
background: var(--bg);
color: white;
font-family: 'Outfit', -apple-system, sans-serif;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
}
.dashboard {
background: var(--card);
padding: 2rem;
border-radius: 1.5rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
backdrop-filter: blur(10px);
width: 80%;
max-width: 500px;
}
h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
background: linear-gradient(to right, var(--primary), var(--secondary));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.status {
display: inline-block;
padding: 0.5rem 1rem;
background: rgba(16, 185, 129, 0.2);
color: #10b981;
border-radius: 2rem;
font-size: 0.875rem;
margin: 1rem 0;
border: 1px solid rgba(16, 185, 129, 0.2);
}
.controls {
margin-top: 2rem;
}
.info {
color: #94a3b8;
font-size: 0.9rem;
line-height: 1.5;
}
.visual {
width: 150px;
height: 150px;
margin: 1.5rem auto;
border: 4px solid var(--primary);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
position: relative;
animation: pulse 2s infinite;
}
.visual::after {
content: '';
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 30px solid var(--primary);
position: absolute;
top: 20px;
}
@keyframes pulse {
0% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(0, 242, 254, 0.4);
}
70% {
transform: scale(1.05);
box-shadow: 0 0 0 15px rgba(0, 242, 254, 0);
}
100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(0, 242, 254, 0);
}
}
</style>
</head>
<body>
<div class="dashboard">
<h1>MOZA R3 Center Force</h1>
<div class="status">System Active</div>
<div class="visual"></div>
<div class="info">
<p>Background controller thread is running.</p>
<p>Direct Input center force enabled for desktop and app windows.</p>
</div>
<div class="controls">
<p style="color: #64748b; font-size: 0.8rem;">UI rendered with WebView2</p>
</div>
</div>
</body>
</html>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.WebView2" version="1.0.3856.49" targetFramework="native" />
</packages>
\ No newline at end of file
// steer_url.cpp : 定义应用程序的入口点。
//
#include "framework.h"
#include "steer_url.h"
#include "MozaController.h"
#include <wrl.h>
#include <WebView2.h>
#include <string>
using namespace Microsoft::WRL;
#include <fstream>
#include <shlwapi.h>
struct AppSettings {
bool enableFullscreen = true;
bool enableAutoStart = false;
} g_Settings;
std::wstring GetSettingsPath() {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
std::wstring strPath(path);
size_t pos = strPath.find_last_of(L"\\/");
if (pos != std::wstring::npos) {
return strPath.substr(0, pos) + L"\\config.ini";
}
return L"config.ini";
}
void LoadSettings() {
std::wstring path = GetSettingsPath();
g_Settings.enableFullscreen = GetPrivateProfileIntW(L"Settings", L"Fullscreen", 1, path.c_str()) != 0;
g_Settings.enableAutoStart = GetPrivateProfileIntW(L"Settings", L"AutoStart", 0, path.c_str()) != 0;
}
void SaveSettings() {
std::wstring path = GetSettingsPath();
WritePrivateProfileStringW(L"Settings", L"Fullscreen", g_Settings.enableFullscreen ? L"1" : L"0", path.c_str());
WritePrivateProfileStringW(L"Settings", L"AutoStart", g_Settings.enableAutoStart ? L"1" : L"0", path.c_str());
}
void ToggleAutoStart(bool enable) {
HKEY hKey;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) {
if (enable) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
std::wstring quotePath = L"\"" + std::wstring(path) + L"\"";
RegSetValueExW(hKey, L"MozaR3Worker", 0, REG_SZ, (const BYTE*)quotePath.c_str(), (DWORD)((quotePath.length() + 1) * sizeof(WCHAR)));
} else {
RegDeleteValueW(hKey, L"MozaR3Worker");
}
RegCloseKey(hKey);
}
}
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
MozaController g_Controller; // MOZA 控制器
ComPtr<ICoreWebView2Controller> g_WebViewController;
ComPtr<ICoreWebView2> g_WebView;
#define IDM_TOGGLE_FULLSCREEN 1001
#define IDM_TOGGLE_LAUNCH_FULLSCREEN 1002
#define IDM_TOGGLE_AUTOSTART 1003
bool g_IsFullscreen = false;
HMENU g_hMenu = nullptr;
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitWebView(HWND hWnd);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadSettings();
ToggleAutoStart(g_Settings.enableAutoStart);
// 初始化 COM 库 (修复 0x800401F0 错误)
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
// 初始化全局字符串 (使用和原始程序一致的类名和标题)
wcscpy_s(szTitle, L"MozaR3CenterOnly");
wcscpy_s(szWindowClass, L"MozaR3WorkerClass");
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_STEERURL));
MSG msg;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 停止控制器
g_Controller.Stop();
// 显式释放 WebView2 COM 对象,防止在 CoUninitialize 后析构导致崩溃
g_WebView.Reset();
g_WebViewController.Reset();
// 释放 COM 库
CoUninitialize();
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_STEERURL));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = nullptr; // 移除自带菜单以获得现代外观
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
void ToggleFullscreenMode(HWND hWnd, bool fullscreen) {
g_IsFullscreen = fullscreen;
if (fullscreen) {
SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetMenu(hWnd, nullptr);
SetWindowPos(hWnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
} else {
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
SetMenu(hWnd, g_hMenu);
SetWindowPos(hWnd, HWND_TOP, 100, 100, 1024, 768, SWP_FRAMECHANGED);
}
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 1024, 768, nullptr, nullptr, hInstance, nullptr);
if (!hWnd) return FALSE;
HMENU hMenu = CreateMenu();
HMENU hSettingsMenu = CreatePopupMenu();
AppendMenuW(hSettingsMenu, MF_STRING, IDM_TOGGLE_FULLSCREEN, L"\u8FDB\u5165\u5168\u5C4F (ESC\u9000\u51FA)");
AppendMenuW(hSettingsMenu, g_Settings.enableFullscreen ? (MF_STRING | MF_CHECKED) : MF_STRING, IDM_TOGGLE_LAUNCH_FULLSCREEN, L"\u542F\u52A8\u65F6\u5168\u5C4F");
AppendMenuW(hSettingsMenu, g_Settings.enableAutoStart ? (MF_STRING | MF_CHECKED) : MF_STRING, IDM_TOGGLE_AUTOSTART, L"\u5F00\u673A\u81EA\u542F");
AppendMenuW(hMenu, MF_POPUP, (UINT_PTR)hSettingsMenu, L"\u8BBE\u7F6E");
g_hMenu = hMenu;
SetMenu(hWnd, hMenu);
ToggleFullscreenMode(hWnd, g_Settings.enableFullscreen);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// 3. 注册硬件句柄 (非阻塞,由 Timer 中的 Update 接管初始化)
g_Controller.InitializeHardware(hWnd);
// 4. 初始化浏览器
InitWebView(hWnd);
// 5. 启动后台处理计时器 (提高刷新率到 ~200-500Hz)
SetTimer(hWnd, 1, 2, nullptr);
return TRUE;
}
void InitWebView(HWND hWnd) {
HRESULT res = CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hWnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
if (FAILED(result) || !env) {
WCHAR msg[256];
swprintf_s(msg, L"WebView2 Environment Init Failed (HRESULT: 0x%08X). Please install Runtime.", result);
MessageBoxW(hWnd, msg, L"Init Error", MB_ICONERROR);
return result;
}
env->CreateCoreWebView2Controller(hWnd,
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[hWnd](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
if (FAILED(result) || !controller) {
WCHAR msg[256];
swprintf_s(msg, L"Failed to create browser controller (HRESULT: 0x%08X).", result);
MessageBoxW(hWnd, msg, L"Renderer Error", MB_ICONERROR);
return result;
}
g_WebViewController = controller;
g_WebViewController->get_CoreWebView2(&g_WebView);
if (g_WebView) {
ICoreWebView2Settings* Settings;
g_WebView->get_Settings(&Settings);
if (Settings) {
Settings->put_IsScriptEnabled(TRUE);
Settings->put_AreDefaultContextMenusEnabled(FALSE);
Settings->put_IsStatusBarEnabled(FALSE);
}
// 调整 WebView2 大小
RECT bounds;
GetClientRect(hWnd, &bounds);
g_WebViewController->put_Bounds(bounds);
g_WebViewController->add_AcceleratorKeyPressed(Callback<ICoreWebView2AcceleratorKeyPressedEventHandler>(
[hWnd](ICoreWebView2Controller* controller, ICoreWebView2AcceleratorKeyPressedEventArgs* args) -> HRESULT {
COREWEBVIEW2_KEY_EVENT_KIND kind;
args->get_KeyEventKind(&kind);
if (kind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN || kind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN) {
UINT virtualKey;
args->get_VirtualKey(&virtualKey);
if (virtualKey == VK_ESCAPE && g_IsFullscreen) {
ToggleFullscreenMode(hWnd, false);
args->put_Handled(TRUE);
}
}
return S_OK;
}).Get(), nullptr);
g_WebView->add_NavigationCompleted(Callback<ICoreWebView2NavigationCompletedEventHandler>(
[](ICoreWebView2* webview, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT {
g_WebViewController->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
return S_OK;
}).Get(), nullptr);
// 加载远程网址
std::wstring url = L"https://fcrs.tentmall.cn/flyPC/#/";
OutputDebugStringW((L"[DEBUG] Navigating to: " + url + L"\n").c_str());
g_WebView->Navigate(url.c_str());
// 初次获取焦点
g_WebViewController->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
}
return S_OK;
}).Get());
return S_OK;
}).Get());
if (FAILED(res)) {
WCHAR msg[256];
swprintf_s(msg, L"Failed to start browser environment creation (HRESULT: 0x%08X).", res);
MessageBoxW(hWnd, msg, L"Startup Error", MB_ICONERROR);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDM_TOGGLE_FULLSCREEN:
ToggleFullscreenMode(hWnd, true);
break;
case IDM_TOGGLE_LAUNCH_FULLSCREEN:
g_Settings.enableFullscreen = !g_Settings.enableFullscreen;
CheckMenuItem(g_hMenu, IDM_TOGGLE_LAUNCH_FULLSCREEN, MF_BYCOMMAND | (g_Settings.enableFullscreen ? MF_CHECKED : MF_UNCHECKED));
SaveSettings();
break;
case IDM_TOGGLE_AUTOSTART:
g_Settings.enableAutoStart = !g_Settings.enableAutoStart;
CheckMenuItem(g_hMenu, IDM_TOGGLE_AUTOSTART, MF_BYCOMMAND | (g_Settings.enableAutoStart ? MF_CHECKED : MF_UNCHECKED));
ToggleAutoStart(g_Settings.enableAutoStart);
SaveSettings();
break;
}
}
break;
case WM_ACTIVATE:
// 当程序从后台回到前台时,自动将焦点还给网页,让网页恢复读取方向盘的信号
if (LOWORD(wParam) != WA_INACTIVE && g_WebViewController != nullptr) {
g_WebViewController->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
}
break;
case WM_SIZE:
if (g_WebViewController != nullptr) {
RECT bounds;
GetClientRect(hWnd, &bounds);
g_WebViewController->put_Bounds(bounds);
}
break;
case WM_TIMER:
if (wParam == 1) {
g_Controller.Update();
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
#pragma once
#include "resource.h"
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{7f3b8ddd-ad8d-417b-8193-a02b136442f2}</ProjectGuid>
<RootNamespace>steerurl</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)third_party\moza\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(ProjectDir)third_party\moza\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>MOZA_SDK.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)third_party\moza\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MOZA_SDK.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)third_party\moza\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="MozaController.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="steer_url.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="third_party\moza\include\effects.h" />
<ClInclude Include="third_party\moza\include\effects\Effect.h" />
<ClInclude Include="third_party\moza\include\effects\EffectException.h" />
<ClInclude Include="third_party\moza\include\effects\ETConstantForce.h" />
<ClInclude Include="third_party\moza\include\effects\ETDamper.h" />
<ClInclude Include="third_party\moza\include\effects\ETFriction.h" />
<ClInclude Include="third_party\moza\include\effects\ETInertia.h" />
<ClInclude Include="third_party\moza\include\effects\ETSine.h" />
<ClInclude Include="third_party\moza\include\effects\ETSpring.h" />
<ClInclude Include="third_party\moza\include\effects\WinDirectInputApiException.h" />
<ClInclude Include="third_party\moza\include\enumCode.h" />
<ClInclude Include="third_party\moza\include\hid_device.h" />
<ClInclude Include="third_party\moza\include\hid_struct.h" />
<ClInclude Include="third_party\moza\include\macros.h" />
<ClInclude Include="third_party\moza\include\mozaAPI.h" />
<ClInclude Include="third_party\moza\include\shifter_device.h" />
<ClInclude Include="third_party\moza\include\switches_device.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="MozaController.cpp" />
<ClCompile Include="steer_url.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="steer_url.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="small.ico" />
<Image Include="steer_url.ico" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Web.WebView2.1.0.3856.49\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\packages\Microsoft.Web.WebView2.1.0.3856.49\build\native\Microsoft.Web.WebView2.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Web.WebView2.1.0.3856.49\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Web.WebView2.1.0.3856.49\build\native\Microsoft.Web.WebView2.targets'))" />
</Target>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="源文件\third_party">
<UniqueIdentifier>{b8208d23-10cc-4fe2-9b0d-a1043305db4c}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\third_party\moza">
<UniqueIdentifier>{8152eacf-b9f2-450a-9993-ed3de2203a27}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\third_party\moza\effect">
<UniqueIdentifier>{0fb51518-2ff6-4f0a-877e-91e076264408}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\www">
<UniqueIdentifier>{e197ad14-d224-4309-b764-b2f6706bfd46}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\www\image">
<UniqueIdentifier>{ccb9fb77-adb1-4588-9ade-f376d61e1686}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="steer_url.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\Effect.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\EffectException.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\ETConstantForce.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\ETDamper.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\ETFriction.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\ETInertia.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\ETSine.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\ETSpring.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects\WinDirectInputApiException.h">
<Filter>源文件\third_party\moza\effect</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\effects.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\enumCode.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\hid_device.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\hid_struct.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\macros.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\mozaAPI.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\shifter_device.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="third_party\moza\include\switches_device.h">
<Filter>源文件\third_party\moza</Filter>
</ClInclude>
<ClInclude Include="MozaController.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="steer_url.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="MozaController.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="steer_url.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="small.ico">
<Filter>资源文件</Filter>
</Image>
<Image Include="steer_url.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>
\ No newline at end of file
#pragma once
// // 包含 SDKDDKVer.h 可定义可用的最高版本的 Windows 平台。
// 如果希望为之前的 Windows 平台构建应用程序,在包含 SDKDDKVer.h 之前请先包含 WinSDKVer.h 并
// 将 _WIN32_WINNT 宏设置为想要支持的平台。
#include <SDKDDKVer.h>
#pragma once
#include"effects/Effect.h"
#include"effects/ETConstantForce.h"
#include"effects/ETDamper.h"
#include"effects/ETFriction.h"
#include"effects/ETInertia.h"
#include"effects/ETSine.h"
#include"effects/ETSpring.h"
#pragma once
#include <dinput.h>
#include "Effect.h"
namespace RS21::direct_input {
/**
* @if english
* @brief Constant force effect class
* 1.Specialization attribute: magnitude
* @else
* @brief The ETConstantForce class 常量力效果类
* 1. 特化属性:强度,magnitude
* @endif
*/
class WIN_API ETConstantForce: public Effect
{
public:
ETConstantForce(Device* device);
/**
* @if english
* @brief Obtain the strength of the current ETConstantForce
* @return The strength of the current ETConstantForce
* @else
* @brief 获取当前ETConstantForce的强度
* @return 当前ETConstantForce的强度
* @endif
*/
long magnitude();
/**
* @if english
* @brief set the strength of the current ETConstantForce
* @param newMagnitude The strength of the current ETConstantForce
* @else
* @brief 设置当前ETConstantForce的强度
* @param newMagnitude 设置的ETConstantForce的强度值
* @endif
*/
void setMagnitude(long newMagnitude);
protected:
/**
* @if english
* @brief Device creation force (initialization)
* @param device win Device interface instance
* @else
* @brief 设备创建力(初始化)
* @param device win设备接口实例
* @endif
*/
void downloadToDevice(LPDIRECTINPUTDEVICE8 device) override;
DICONSTANTFORCE m_diPeriodic;
};
}//RS21::directInput

#pragma once
#include <dinput.h>
#include "Effect.h"
#include <iostream>
namespace RS21::direct_input {
/**
* @if english
* @brief Damping force effect class
* @else
* @brief The ETDamper class 阻尼力效果类
* @endif
*/
class WIN_API ETDamper : public Effect
{
public:
ETDamper(Device* device);
/**
* @if english
* @brief Obtain offset for the condition
* @return Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 获取条件的偏移量
* @return 条件的偏移量,范围从-10000到10000
* @endif
*/
long offset();
/**
* @if english
* @brief Obtain coefficient constant on the positive side of the offset
* @return coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 获取偏移正侧的系数常数
* @return 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
long positiveCoefficient();
/**
* @if english
* @brief Obtain Coefficient constant on the negative side of the offset
* @return Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 获取偏移负侧的系数常数
* @return 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
long negativeCoefficient();
/**
* @if english
* @brief Obtain maximum force output on the positive side of the offset
* @return Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 获得偏移正侧的最大力输出
* @return 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
unsigned long positiveSaturation();
/**
* @if english
* @brief Obtain maximum force output on the negative side of the offset
* @return Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 获取偏移负侧的最大力输出
* @return 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
unsigned long negativeSaturation();
/**
* @if english
* @brief Obtain region around lOffset in which the condition is not active
* @return Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 获取lOffset周围条件未激活的区域
* @return lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
long deadBand();
/**
* @if english
* @brief set offset for the condition
* @param offset Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 设置条件的偏移量
* @param offset 条件的偏移量,范围从-10000到10000
* @endif
*/
void setOffset(long offset);
/**
* @if english
* @brief set coefficient constant on the positive side of the offset
* @param newPositiveCoefficient coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 设置偏移正侧的系数常数
* @param newPositiveCoefficient 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
void setPositiveCoefficient(long newPositiveCoefficient);
/**
* @if english
* @brief set Coefficient constant on the negative side of the offset
* @param newNegativeCoefficient Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 设置偏移负侧的系数常数
* @param newNegativeCoefficient 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
void setNegativeCoefficient(long newNegativeCoefficient);
/**
* @if english
* @brief set maximum force output on the positive side of the offset
* @param newPositiveSaturation Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 设置偏移正侧的最大力输出
* @param newPositiveSaturation 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
void setPositiveSaturation(unsigned long newPositiveSaturation);
/**
* @if english
* @brief set maximum force output on the negative side of the offset
* @param newNegativeSaturation Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 设置偏移负侧的最大力输出
* @param newNegativeSaturation 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
void setNegativeSaturation(unsigned long newNegativeSaturation);
/**
* @if english
* @brief set region around lOffset in which the condition is not active
* @param newDeadBand Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 设置lOffset周围条件未激活的区域
* @param newDeadBand lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
void setDeadBand(long newDeadBand);
protected:
// /**
// * @if english
// * @brief Device creation force (initialization)
// * @param device win Device interface instance
// * @else
// * @brief 设备创建力(初始化)
// * @param device win设备接口实例
// * @endif
// */
virtual void downloadToDevice(LPDIRECTINPUTDEVICE8 device) override;
DICONDITION m_diPeriodic;
};
}//RS21::directInput

#pragma once
#include <dinput.h>
#include "Effect.h"
namespace RS21::direct_input {
/**
* @if english
* @brief Mechanical friction force effect class
* @else
* @brief The ETFriction class 机械摩擦力效果类
* @endif
*/
class WIN_API ETFriction: public Effect
{
public:
ETFriction(Device* device);
//查看参数
/**
* @if english
* @brief Obtain offset for the condition
* @return Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 获取条件的偏移量
* @return 条件的偏移量,范围从-10000到10000
* @endif
*/
long offset();
/**
* @if english
* @brief Obtain coefficient constant on the positive side of the offset
* @return coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 获取偏移正侧的系数常数
* @return 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
long positiveCoefficient();
/**
* @if english
* @brief Obtain Coefficient constant on the negative side of the offset
* @return Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 获取偏移负侧的系数常数
* @return 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
long negativeCoefficient();
/**
* @if english
* @brief Obtain maximum force output on the positive side of the offset
* @return Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 获得偏移正侧的最大力输出
* @return 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
unsigned long positiveSaturation();
/**
* @if english
* @brief Obtain maximum force output on the negative side of the offset
* @return Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 获取偏移负侧的最大力输出
* @return 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
unsigned long negativeSaturation();
/**
* @if english
* @brief Obtain region around lOffset in which the condition is not active
* @return Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 获取lOffset周围条件未激活的区域
* @return lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
long deadBand();
/**
* @if english
* @brief set offset for the condition
* @param offset Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 设置条件的偏移量
* @param offset 条件的偏移量,范围从-10000到10000
* @endif
*/
void setOffset(long offset);
/**
* @if english
* @brief set coefficient constant on the positive side of the offset
* @param newPositiveCoefficient coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 设置偏移正侧的系数常数
* @param newPositiveCoefficient 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
void setPositiveCoefficient(long newPositiveCoefficient);
/**
* @if english
* @brief set Coefficient constant on the negative side of the offset
* @param newNegativeCoefficient Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 设置偏移负侧的系数常数
* @param newNegativeCoefficient 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
void setNegativeCoefficient(long newNegativeCoefficient);
/**
* @if english
* @brief set maximum force output on the positive side of the offset
* @param newPositiveSaturation Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 设置偏移正侧的最大力输出
* @param newPositiveSaturation 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
void setPositiveSaturation(unsigned long newPositiveSaturation);
/**
* @if english
* @brief set maximum force output on the negative side of the offset
* @param newNegativeSaturation Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 设置偏移负侧的最大力输出
* @param newNegativeSaturation 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
void setNegativeSaturation(unsigned long newNegativeSaturation);
/**
* @if english
* @brief set region around lOffset in which the condition is not active
* @param newDeadBand Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 设置lOffset周围条件未激活的区域
* @param newDeadBand lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
void setDeadBand(long newDeadBand);
protected:
virtual void downloadToDevice(LPDIRECTINPUTDEVICE8 device) override;
DICONDITION m_diPeriodic;
};
}//rs21::direct_input

#pragma once
#include "Effect.h"
namespace RS21::direct_input {
/**
* @if english
* @brief Inertia effect class
* @else
* @brief The ETDamper class 惯量效果类
* @endif
*/
class WIN_API ETInertia: public Effect
{
public:
ETInertia(Device* device);
//查看参数
/**
* @if english
* @brief Obtain offset for the condition
* @return Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 获取条件的偏移量
* @return 条件的偏移量,范围从-10000到10000
* @endif
*/
long offset();
/**
* @if english
* @brief Obtain coefficient constant on the positive side of the offset
* @return coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 获取偏移正侧的系数常数
* @return 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
long positiveCoefficient();
/**
* @if english
* @brief Obtain Coefficient constant on the negative side of the offset
* @return Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 获取偏移负侧的系数常数
* @return 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
long negativeCoefficient();
/**
* @if english
* @brief Obtain maximum force output on the positive side of the offset
* @return Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 获得偏移正侧的最大力输出
* @return 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
unsigned long positiveSaturation();
/**
* @if english
* @brief Obtain maximum force output on the negative side of the offset
* @return Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 获取偏移负侧的最大力输出
* @return 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
unsigned long negativeSaturation();
/**
* @if english
* @brief Obtain region around lOffset in which the condition is not active
* @return Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 获取lOffset周围条件未激活的区域
* @return lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
long deadBand();
/**
* @if english
* @brief set offset for the condition
* @param offset Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 设置条件的偏移量
* @param offset 条件的偏移量,范围从-10000到10000
* @endif
*/
void setOffset(long offset);
/**
* @if english
* @brief set coefficient constant on the positive side of the offset
* @param newPositiveCoefficient coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 设置偏移正侧的系数常数
* @param newPositiveCoefficient 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
void setPositiveCoefficient(long newPositiveCoefficient);
/**
* @if english
* @brief set Coefficient constant on the negative side of the offset
* @param newNegativeCoefficient Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 设置偏移负侧的系数常数
* @param newNegativeCoefficient 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
void setNegativeCoefficient(long newNegativeCoefficient);
/**
* @if english
* @brief set maximum force output on the positive side of the offset
* @param newPositiveSaturation Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 设置偏移正侧的最大力输出
* @param newPositiveSaturation 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
void setPositiveSaturation(unsigned long newPositiveSaturation);
/**
* @if english
* @brief set maximum force output on the negative side of the offset
* @param newNegativeSaturation Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 设置偏移负侧的最大力输出
* @param newNegativeSaturation 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
void setNegativeSaturation(unsigned long newNegativeSaturation);
/**
* @if english
* @brief set region around lOffset in which the condition is not active
* @param newDeadBand Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 设置lOffset周围条件未激活的区域
* @param newDeadBand lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
void setDeadBand(long newDeadBand);
protected:
virtual void downloadToDevice(LPDIRECTINPUTDEVICE8 device) override;
DICONDITION m_diPeriodic;
};
}//rs21::direct_input

#pragma once
#include "Effect.h"
#include <dinput.h>
#include <iostream>
namespace RS21::direct_input{
/**
* @if english
* @brief Sinusoidal force effect class
* @else
* @brief The ETSine class 正弦力效果类
* @endif
*/
class WIN_API ETSine : public Effect
{
public:
ETSine(Device* device);
/**
* @if english
* @brief Obtain the strength of the current ETSine
* @return The strength of the current ETSine
* @else
* @brief magnitude 获取当前ETSine的强度
* @return 当前ETSine的强度
* @endif
*/
unsigned long magnitude();
/**
* @if english
* @brief set the strength of the current ETSine
* @param newMagnitude The strength of the current ETSine
* @else
* @brief setMagnitude 设置当前ETSine的强度
* @param newMagnitude 设置的ETSine的强度值
* @endif
*/
void setMagnitude(unsigned long newMagnitude);
/**
* @if english
* @brief Obtain offset for the condition
* @return Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 获取条件的偏移量
* @return 条件的偏移量,范围从-10000到10000
* @endif
*/
long offset();
/**
* @if english
* @brief set offset for the condition
* @param offset Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 设置条件的偏移量
* @param offset 条件的偏移量,范围从-10000到10000
* @endif
*/
void setOffset(long newOffset);
/**
* @if english
* @brief Obtain the current phase of ETSine
* @return Current phase of ETSine
* @else
* @brief phase 获取当前ETSine相位
* @return 当前ETSine的相位
* @endif
*/
unsigned long phase();
/**
* @if english
* @brief set the current phase of ETSine
* @param newPhase current phase of ETSine
* @else
* @brief 设置当前ETSine的相位
* @param newPhase 设置的ETSine的相位
* @endif
*/
void setPhase(unsigned long newPhase);
/**
* @if english
* @brief Obtain the cycle of the current ETSine
* @return cycle of the current ETSine
* @else
* @brief 获取当前ETSine的周期
* @return 当前ETSine的周期
* @endif
*/
unsigned long period();
/**
* @if english
* @brief set the cycle of the current ETSine
* @param newPhase cycle of the current ETSine
* @else
* @brief 设置当前ETSine的周期
* @param newPeriod 设置的周期
* @endif
*/
void setPeriod(unsigned long newPeriod);
protected:
virtual void downloadToDevice(LPDIRECTINPUTDEVICE8 device) override;
DIPERIODIC m_diPeriodic;
};
}//RS21::directInput

#pragma once
#include "Effect.h"
namespace RS21::direct_input {
/**
* @if english
* @brief Centripetal force effect class
* @else
* @brief The ETSpring class 回中力效果类
* @endif
*/
class WIN_API ETSpring: public Effect
{
public:
ETSpring(Device* device);
//查看参数
/**
* @if english
* @brief Obtain offset for the condition
* @return Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 获取条件的偏移量
* @return 条件的偏移量,范围从-10000到10000
* @endif
*/
long offset();
/**
* @if english
* @brief Obtain coefficient constant on the positive side of the offset
* @return coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 获取偏移正侧的系数常数
* @return 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
long positiveCoefficient();
/**
* @if english
* @brief Obtain Coefficient constant on the negative side of the offset
* @return Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 获取偏移负侧的系数常数
* @return 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
long negativeCoefficient();
/**
* @if english
* @brief Obtain maximum force output on the positive side of the offset
* @return Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 获得偏移正侧的最大力输出
* @return 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
unsigned long positiveSaturation();
/**
* @if english
* @brief Obtain maximum force output on the negative side of the offset
* @return Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 获取偏移负侧的最大力输出
* @return 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
unsigned long negativeSaturation();
/**
* @if english
* @brief Obtain region around lOffset in which the condition is not active
* @return Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 获取lOffset周围条件未激活的区域
* @return lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
long deadBand();
/**
* @if english
* @brief set offset for the condition
* @param offset Offset for the condition, in the range from - 10,000 through 10,000.
* @else
* @brief 设置条件的偏移量
* @param offset 条件的偏移量,范围从-10000到10000
* @endif
*/
void setOffset(long offset);
/**
* @if english
* @brief set coefficient constant on the positive side of the offset
* @param newPositiveCoefficient coefficient constant on the positive side of the offset, in the range from - 10,000 through 10,000.
* @else
* @brief 设置偏移正侧的系数常数
* @param newPositiveCoefficient 偏移正侧的系数常数,范围从-10000到10000
* @endif
*/
void setPositiveCoefficient(long newPositiveCoefficient);
/**
* @if english
* @brief set Coefficient constant on the negative side of the offset
* @param newNegativeCoefficient Coefficient constant on the negative side of the offset, in the range from - 10,000 through 10,000
* If the device does not support separate positive and negative coefficients, the value of lNegativeCoefficient is ignored,
* and the value of lPositiveCoefficient is used as both the positive and negative coefficients
* @else
* @brief 设置偏移负侧的系数常数
* @param newNegativeCoefficient 偏移负侧的系数常数,范围从-10000到10000。
* 如果设备不支持单独的正系数和负系数,则忽略lNegativeCoefficient的值,并将lPositiveCoefficiency的值用作正系数和负值
* @endif
*/
void setNegativeCoefficient(long newNegativeCoefficient);
/**
* @if english
* @brief set maximum force output on the positive side of the offset
* @param newPositiveSaturation Maximum force output on the positive side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* @else
* @brief 设置偏移正侧的最大力输出
* @param newPositiveSaturation 偏移正侧的最大力输出,范围从0到10000。如果设备不支持力饱和,则忽略此成员的值。
* @endif
*/
void setPositiveSaturation(unsigned long newPositiveSaturation);
/**
* @if english
* @brief set maximum force output on the negative side of the offset
* @param newNegativeSaturation Maximum force output on the negative side of the offset, in the range from 0 through 10,000.
* If the device does not support force saturation, the value of this member is ignored.
* If the device does not support separate positive and negative saturation, the value of dwNegativeSaturation is ignored, and the value of dwPositiveSaturation is used as both the positive and negative saturation.
* @else
* @brief 设置偏移负侧的最大力输出
* @param newNegativeSaturation 偏移负侧的最大力输出,范围从0到10000。
* 如果设备不支持力饱和,则忽略此成员的值。
* 如果设备不支持单独的正饱和和负饱和,则忽略dwNegativeSaturation的值,并使用dwPositiveSaturation值作为正饱和和负饱和。
* @endif
*/
void setNegativeSaturation(unsigned long newNegativeSaturation);
/**
* @if english
* @brief set region around lOffset in which the condition is not active
* @param newDeadBand Region around lOffset in which the condition is not active, in the range from 0 through 10,000. In other words,
* the condition is not active between lOffset minus lDeadBand and lOffset plus lDeadBand.
* @else
* @brief 设置lOffset周围条件未激活的区域
* @param newDeadBand lOffset周围条件未激活的区域,范围从0到10000。换句话说,在lOffset减去lDeadBand和lOffset加上lDeadBnd之间,条件不活动。
* @endif
*/
void setDeadBand(long newDeadBand);
protected:
virtual void downloadToDevice(LPDIRECTINPUTDEVICE8 device) override;
DICONDITION m_diPeriodic;
};
}//rs21::direct_input
#pragma once
#include "../macros.h"
#include <cstdint>
#include <string>
#include <dinput.h>
#include <memory>
#include <map>
namespace RS21::direct_input{
class Device;
extern unsigned int DI_MSECONDS;
/**
* @if english
* @brief Effect Abstract Class
* 1. Provide API for effect start and end
* 2. Provide interfaces for obtaining and modifying general parameters
* @else
* @brief The Effect class 效果抽象类
* 1. 提供效果开始、结束API
* 2. 提供通用参数的获取、修改接口
* @endif
*/
class WIN_API Effect
{
public:
/**
* @if english
* @brief start Force effect
* @else
* @brief 力效果启动
* @endif
*/
void start();
/**
* @if english
* @brief stop Force effect
* @else
* @brief stop 停止力效果
* @endif
*/
void stop();
/**
* @if english
* @brief Set the power level
* @param newAttackLevel Power level
* @else
* @brief 设置发力级别
* @param newAttackLevel 发力级别
* @endif
*/
void setAttackLevel(const unsigned long newAttackLevel = 0);
/**
* @if english
* @brief Obtain Power Level
* @return Power level
* @else
* @brief 获取发力级别
* @return 发力级别
* @endif
*/
unsigned long attackLevel() const;
/**
* @if english
* @brief Obtain Power time
* @return Power time,Unit: ms
* @else
* @brief 获取发力时间
* @return 发力时间,单位:ms
* @endif
*/
unsigned long attackTime() const;
/**
* @if english
* @brief set Power time
* @param newAttackTime Power time,Unit: ms
* @else
* @brief 设置发力时间
* @param newAttackTime 发力时间,单位:ms
* @endif
*/
void setAttackTime(const unsigned long newAttackTime = 500);//单位:s
/**
* @if english
* @brief Obtain attenuation level
* @return attenuation level
* @else
* @brief fadeLevel 获取衰减级别
* @return 衰减级别
* @endif
*/
unsigned long fadeLevel() const;
/**
* @if english
* @brief Set attenuation level
* @param newFadeLevel attenuation level
* @else
* @brief 设置衰减级别
* @param newFadeLevel 衰减级别
* @endif
*/
void setFadeLevel(const unsigned long newFadeLevel = 0);
/**
* @if english
* @brief Obtain attenuation time
* @return attenuation time,Unit: ms
* @else
* @brief fadeTime 获取衰减时间,单位:ms
* @return 衰减时间
* @endif
*/
unsigned long fadeTime()const;
/**
* @if english
* @brief Set attenuation time
* @param newFadeLevel attenuation time,Unit: ms
* @else
* @brief setFadeTime 设置衰减时间
* @param newFadeTime 衰减时间,单位:ms
* @endif
*/
void setFadeTime(const unsigned long newFadeTime = 1000 );//
/**
* @if english
* @brief Obtain attenuation duration
* @return attenuation duration,Unit: ms
* @else
* @brief duration 获取效果持续时间
* @return 效果持续时间,单位:ms
* @endif
*/
unsigned long duration() const;
/**
* @if english
* @brief set attenuation duration
* @param newDuration attenuation duration,Unit: ms
* @else
* @brief setDuration 设置效果持续时间
* @param newDuration 效果持续时间,单位:ms
* @endif
*/
void setDuration(const unsigned long newDuration = 2000);
/**
* @if english
* @brief Obtain sampling period
* @return sampling period,Unit: ms
* @else
* @brief 获取采样周期
* @return 采样周期,单位:ms
* @endif
*/
unsigned long samplePeriod() const;
/**
* @if english
* @brief set sampling period
* @param newSamplePeriod sampling period,Unit: ms
* @else
* @brief setSamplePeriod 设置采样周期
* @param newSamplePeriod 采样周期值,单位:ms
* @endif
*/
void setSamplePeriod(const unsigned long newSamplePeriod = 0);
/**
* @if english
* @brief Obtain Gain
* @return Gain value (according to report descriptor: 0-10000)
* @else
* @brief 获取增益
* @return 增益值(根据报告描述符:0~10000)
* @endif
*/
unsigned long gain() const;
/**
* @if english
* @brief set Gain
* @return newGain Gain value (according to report descriptor: 0-10000)
* @else
* @brief 设置增益值
* @param newGain 增益值(根据报告描述符:0~10000)
*/
void setGain(const unsigned long newGain = DI_FFNOMINALMAX);
/**
* @if english
* @brief Obtain departure effect button
* @return departure effect button
* @else
* @brief 获取出发效果按钮
* @return 效果按钮
* @endif
*/
unsigned long triggerButton() const;
/**
* @if english
* @brief set departure effect button
* @param newButtonIndex departure effect button
* @else
* @brief 设置触发效果按钮
* @param newButtonIndex 触发效果按钮
* @endif
*/
void setTriggerButton(const unsigned long newButtonIndex = DIEB_NOTRIGGER);
/**
* @if english
* @brief Obtain trigger effect repetition interval
* @return Trigger effect repetition interval
* @else
* @brief 获取触发效果重复间隔
* @return 触发效果重复间隔
* @endif
*/
unsigned long triggerRepeatInterval() const;
/**
* @if english
* @brief Set trigger effect repetition interval
* @param newRepeatInterval Trigger effect interval
* @else
* @brief 设置触发效果间隔
* @param newRepeatInterval 触发效果间隔
* @endif
*/
void setTriggerRepeatInterval(const unsigned long newRepeatInterval = 0);
// void setCAxes(const unsigned long newCAxes = 2);
/**
* @if english
* @brief Number of effect related axes
* @return number of axles
* @else
* @brief 效果相关轴数
* @return 轴数
* @endif
*/
unsigned long rgdAxesCount();
/**
* @if english
* @brief Obtain relevant axis array
* @return Related Axis Array
* @else
* @brief 获取相关轴数组
* @return 相关轴数组
* @endif
*/
unsigned long* rgdAxes();
/**
* @if english
* @brief Set related axes
* @param axes Related axis array pointer
* @param size Length of related axis array
* @else
* @brief 设置相关轴
* @param axes 相关轴数组指针
* @param size 相关轴数组长度
* @endif
*/
void setRgdAxes(unsigned long* axes, unsigned long size);//设置轴,运行时不能修改,不建议修改,使用默认
/**
* @if english
* @brief Obtain the angle of the effect in the x-axis
* @return The angle of the effect on the x-axis
* @else
* @brief 获取effect在x轴向的角度
* @return effect在x轴的角度
* @endif
*/
long xDirection();
/**
* @if english
* @brief Set the angle of the effect in the x-axis
* @param newDegree The angle of the effect on the x-axis
* @else
* @brief 设置effect在x轴向的角度
* @param newDegree x轴向的角度
* @endif
*/
void setXDirection(long newDegree = 1 );//设置x轴方向,单位:度
// void setEnvelope();//设置封装
// void virtual setCbTypeSpecificParams() = 0;//设置特殊参数长度
// void virtual setTypeSpecificParams() = 0;//设置特殊参数长度
/**
* @if english
* @brief Obtain the name of the current effect
* @return The name of the current effect
* @else
* @brief 获取当前effect的名称
* @return 当前effect的名称
* @endif
*/
std::string effectName() const;
/**
* @if english
* @brief set the name of the current effect
* @param newEffectName The name of the effect
* @else
* @brief 设置effect别名
* @param newEffectName effect的别名
* @endif
*/
void setEffectName(const std::string &newEffectName);
/**
* @if english
* @brief Obtain the index of the current effect
* @return The index of the current effect
* @else
* @brief 获取当前effect的index
* @return 当前effect的index
* @endif
*/
int index() const;
/**
* @if english
* @brief set the index of the current effect
* @param The index of the current effect,index >= 0
* @else
* @brief 设置当前effect的index
* @param newIndex 当前effect的index,index >= 0
* @endif
*/
void setIndex( unsigned int newIndex);
bool m_isRunning = false;
protected:
Effect(Device* device);//抽象类,但是没有虚函数
~Effect();//生命周期由device管理
virtual void downloadToDevice(LPDIRECTINPUTDEVICE8 device) = 0;
std::map<std::string, std::string> allGeneralEffectInfo();
protected:
uint16_t m_effectId;
std::string m_effectName;
LPDIRECTINPUTEFFECT m_effect = NULL;
DIEFFECT m_diEffect; //effect_info
DIENVELOPE m_diEnvelope; //effect_instance
LONG* m_lDirection = nullptr;
DWORD *m_dwAxes = nullptr;
Device* m_device = nullptr;//parent
unsigned int m_index = 0;
};
}//RS21::directInput

#pragma once
#include "../macros.h"
#include <exception>
#include <string>
namespace RS21::direct_input {
class WIN_API EffectException : public std::exception
{
public:
EffectException(const std::string& errorMessage);
EffectException(const char* errorMessage);
virtual const char* what() const override{return m_errorStr.c_str();}
private:
std::string m_errorStr;
};
}//namespace
#pragma once
#include "../macros.h"
#include <exception>
#include <string>
#include "Windows.h" //DWORD
#include "winbase.h"
namespace RS21::direct_input {
class WIN_API WinDirectInputApiException : public std::exception
{
public:
WinDirectInputApiException(HRESULT newHResult, std::string additionalString);
WinDirectInputApiException(HRESULT newHResult, const char* additionalString);
long hResult() const throw()
{
return m_hResult;
}
virtual const char* what() const throw() override
{
return m_errorString.c_str();
}
private:
HRESULT m_hResult;
std::string m_errorString;
std::string ConvertWStringToString(wchar_t* wstr);
};
}//rs21::direct_input
#ifndef ENUMCODE_H
#define ENUMCODE_H
enum ERRORCODE
{
NORMAL = 0,
NOINSTALLSDK,
NODEVICES,
OUTOFRANGE,
PARAMETERERR,
COLLECTIONCYCLEDATALOSS, //采集周期太长导致数据丢失
CREATEFFECTERR,
ENCODINGFAILED,
FFBERR,
FIRMWARETOOOLD, //固件版本过低
PITHOUSENOTREADY, // PitHouse未准备好
};
enum PRODUCTTYPE
{
PRODUCT_WHEELBASE = 0,
PRODUCT_STEERINGWHEEL,
PRODUCT_DISPLAYSCREEN,
PRODUCT_PEDALS,
PRODUCT_METER,
PRODUCT_ADAPTER,
PRODUCT_HANDBRAKE,
PRODUCT_GEARSHIFTER,
PRODUCT_UNKNOWDEVICE,
};
#endif // BASESINGLETON_H
#pragma once
#include "macros.h"
#include <string>
#include <vector>
namespace moza {
/**
* @if english
* @brief HID device class
* @else
* @brief HID设备类
* @endif
*/
class WIN_API HidDevice
{
public:
/**
* @if english
* @brief Default constructor
* @else
* @brief 无参构造
* @endif
*/
HidDevice();
/**
* @if english
* @brief Constructs with a device instance path
* @param path device instance path
* @else
* @brief 从一个设备实例路径构造
* @param path 设备实例路径
* @endif
*/
explicit HidDevice(const std::string& path);
/**
* @if english
* @brief Destructor, automatically closes the device and releases resources
* @else
* @brief 析构函数,内部会自动关闭设备并释放资源
* @endif
*/
virtual ~HidDevice();
// Copying is disabled
HidDevice(const HidDevice&) = delete;
HidDevice& operator=(const HidDevice&) = delete;
// Move only
HidDevice(HidDevice&& other) noexcept;
HidDevice& operator=(HidDevice&& other) noexcept;
/**
* @if english
* @brief Get the device instance path
* @return device instance path
* @else
* @brief 获取设备实例路径
* @return 设备实例路径
* @endif
*/
const std::string& path() const;
/**
* @if english
* @brief Set the device instance path
* @param path device instance path
* @else
* @brief 设置设备实例路径
* @param path 设备实例路径
* @endif
*/
void setPath(const std::string& path);
/**
* @if english
* @brief Check if the device is already opened (only indicates the opened state, does not guarantee the connection state; use isConnected function to check the connection state)
* @return Returns true if the device is opened; otherwise, returns false
* @else
* @brief 判断设备是否已被打开(仅表示打开状态,不保证连接状态,若需检查连接状态请使用isConnected函数)
* @return 如果设备已经打开,则返回true;否则返回false
* @endif
*/
bool isOpen() const;
/**
* @if english
* @brief Check if the device is in a connected state, useful for determining if the device is disconnected
* @note Internally, this is determined based on the error code of the last device operation.
* It is recommended to use this function if a call to the button state retrieval function returns empty,
* to confirm whether the device has been disconnected
* @return Returns true if the device is connected; otherwise, returns false
* @else
* @brief 判断设备是否处于已连接状态,可用于判断设备是否断连
* @note 内部通过上一次设备操作的错误码判断。建议在执行获取按钮状态函数后返回值为空时,通过此函数加以判断设备是否已经断开连接
* @return 如果设备已连接,则返回true;否则返回false
* @endif
*/
bool isConnected() const;
/**
* @if english
* @brief Open the device using the device instance path
* @return Returns true if the device was successfully opened; otherwise, returns false
* @else
* @brief 通过设备实例路径打开设备
* @return 如果设备打开成功,则返回true;否则返回false
* @endif
*/
virtual bool open();
/**
* @if english
* @brief Close the device
* @else
* @brief 关闭设备
* @endif
*/
virtual void close();
private:
class HidDevicePrivate* m_impl;
protected:
size_t getReportSize() const;
size_t getNumInputReports() const;
std::vector<uint8_t> read(size_t size) const;
std::vector<uint8_t> readLatestReport() const;
};
inline HidDevice::HidDevice(HidDevice&& other) noexcept : m_impl() { std::swap(m_impl, other.m_impl); }
inline HidDevice& HidDevice::operator=(HidDevice&& other) noexcept
{
if (this != &other)
{
std::swap(m_impl, other.m_impl);
}
return *this;
}
}
#ifndef HID_STRUCT_H
#define HID_STRUCT_H
#include <vector>
enum ROCKERMODE
{
UNKNOW = 0,
CROSSKEY,
KEY,
};
enum KNOBMODE
{
UNKNOWKNOB = 0,
KNOB,
MULTIKEY,
};
enum CLUTCHPICKMODE
{
UNKNOWCLUTCHPICK = 0,
COMPOSITEAXIS,
INDEPENDENTAXIS,
};
enum ROCKEREDIR
{
UP = 0,
RIGHTUP,
RIGHT,
RIGHTDOWM,
DOWM,
LEFTDOWM,
LEFT,
LEFTUP,
NONEDIR
};
//enum ERRORCODE
//{
// NORMAL = 0,
// NOINSTALLSDK,
// NODEVICES,
// COLLECTIONCYCLEDATALOSS,
//};
struct HIDButton
{
bool startValue = 0;
int changeNum = -1;
bool isPressed() const{
if(changeNum == -1)
return startValue;
return startValue || changeNum;
};
bool lastPressState() const{
return (changeNum & 1) == 0 || changeNum == -1 ? startValue : !startValue;
}
int pressNum(){
return changeNum == -1 ? 0 : changeNum/2 + changeNum&0x01;
}
};
//没有操作为空,8同样表示没有操作,但vector第一个数据不会为8
struct HIDRocker
{
std::vector<ROCKEREDIR> rockerDatas;
ROCKEREDIR lastDir() const
{
return rockerDatas.empty()? NONEDIR : rockerDatas.back();
}
};
struct HIDKnob
{
std::vector<int> knobDatas;
int getOffset() const{
int res = 0;
for(auto var : knobDatas)
res += var;
return res;
}
};
struct HIDMultiSegmentKnob : public HIDKnob
{
int getLastKey() const
{
return knobDatas.empty()? 0 : knobDatas.back();
}
};
enum GEAR
{
R = 0,
GEAR1st,
GEAR2nd,
GEAR3rf,
GEAR4th,
GEAR5th,
GEAR6th,
GEAR7th,
GEAR0th,
};
struct HIDData
{
float fSteeringWheelAngle = NAN; // 方向盘角度
float fSteeringWheelVelocity = NAN; // 方向盘速度(度每秒,基座固件版本需大于等于1.2.4.x)
float fSteeringWheelAcceleration = NAN; // 方向盘加速度(度每二次方秒,基座固件版本需大于等于1.2.4.x)
int16_t steeringWheelAxle = 0x8001;
int16_t clutchSynthesisShaft = 0x8001;
int16_t clutchIndependentShaftL = 0x8001;
int16_t clutchIndependentShaftR = 0x8001;
int16_t throttle = 0x8000;
int16_t clutch = 0x8000;
int16_t brake = 0x8000;
int16_t handbrake = 0x8001;
HIDButton buttons[128];
HIDRocker leftRocker5_8;
HIDRocker rightRocker9_12;
HIDKnob knobL45_46;
HIDKnob knobR47_48;
// HIDKnob knob2L;
// HIDKnob knob2R;
HIDMultiSegmentKnob multiSegmentKnob26_27or53_64;
HIDMultiSegmentKnob multiSegmentKnob28_29or65_76;
HIDMultiSegmentKnob multiSegmentKnob30_31or77_88;
HIDMultiSegmentKnob multiSegmentKnob39_40or89_100;
HIDMultiSegmentKnob multiSegmentKnob43_44or101_112;
GEAR shift = GEAR0th;
bool buttonHandbrake = false;
};
#endif // HID_STRUCT_H
#pragma once
#ifdef DLL_EXPORTS
#define WIN_API __declspec(dllexport)
#else
#define WIN_API __declspec(dllimport)
#endif
#pragma once
#include "effects.h"
#include "enumCode.h"
#include "hid_struct.h"
#include "macros.h"
#include <iostream>
#include <map>
#include <string>
namespace moza {
class SwitchesDevice;
class ShifterDevice;
/**
* @if english
* @brief load sdk
* @else
* @brief 加载sdk
* @endif
*/
WIN_API void installMozaSDK();
/**
* @if english
* @brief remove sdk
* @else
* @brief 卸载sdk
* @endif
*/
WIN_API void removeMozaSDK();
//力反馈
/**
* @if english
* @brief Create a sinusoidal force effector
* @param id Window id
* @param err Error code
* @return Sinusoidal force effector
* @else
* @brief 创建正弦力效果器
* @param id 窗口id
* @param err 错误码
* @return 正弦力效果器
* @endif
*/
WIN_API std::shared_ptr<RS21::direct_input::ETSine> createWheelbaseETSine(HWND id, ERRORCODE& err);
/**
* @if english
* @brief Create a constant Force effector
* @param id Window id
* @param err Error code
* @return Constant force effector
* @else
* @brief 创建恒定力效果器
* @param id 窗口id
* @param err 错误码
* @return 恒定力效果器
* @endif
*/
WIN_API std::shared_ptr<RS21::direct_input::ETConstantForce> createWheelbaseETConstantForce(HWND id, ERRORCODE& err);
/**
* @if english
* @brief Create a return force effector
* @param id Window id
* @param err Error code
* @return Return force effector
* @else
* @brief 创建回中力效果器
* @param id 窗口id
* @param err 错误码
* @return 回中力效果器
* @endif
*/
WIN_API std::shared_ptr<RS21::direct_input::ETSpring> createWheelbaseETSpring(HWND id, ERRORCODE& err);
/**
* @if english
* @brief Create a dampener
* @param id Window id
* @param err Error code
* @return dampener
* @else
* @brief 创建阻尼效果器
* @param id 窗口id
* @param err 错误码
* @return 阻尼效果器
* @endif
*/
WIN_API std::shared_ptr<RS21::direct_input::ETDamper> createWheelbaseETDamper(HWND id, ERRORCODE& err);
/**
* @if english
* @brief Create an inertia effector
* @param id Window id
* @param err Error code
* @return Inertia effector
* @else
* @brief 创建惯性效果器
* @param id 窗口id
* @param err 错误码
* @return 惯性效果器
* @endif
*/
WIN_API std::shared_ptr<RS21::direct_input::ETInertia> createWheelbaseETInertia(HWND id, ERRORCODE& err);
/**
* @if english
* @brief Create a friction effector
* @param id Window id
* @param err Error code
* @return friction effector
* @else
* @brief 创建摩擦力效果器
* @param id 窗口id
* @param err 错误码
* @return 摩擦力效果器
* @endif
*/
WIN_API std::shared_ptr<RS21::direct_input::ETFriction> createWheelbaseETFriction(HWND id, ERRORCODE &err);
/**
* @if english
* @brief Stop the force feedback effects of the wheelbase
* @return Error code
* @else
* @brief 停止基座的力反馈效果
* @return 错误码
* @endif
*/
WIN_API ERRORCODE stopForceFeedback();
//HID
/**
* @if english
* @brief Gets all hid data during the cycle
* @param err Error code
* @return hid data
* @else
* @brief 获取周期内hid的所有数据
* @param err 错误码
* @return hid数据
* @endif
*/
WIN_API const HIDData* getHIDData(ERRORCODE& err);
/**
* @if english
* @brief Gets the enumerated value of the connected device
* @param dev Device enum
* @param err Error code
* @return Device name,Empty as unconnected
* @else
* @brief 获取所连接设备的枚举值
* @param dev 设备枚举值
* @param err 错误码
* @return 设备名,空为未连接
* @endif
*/
WIN_API const char* getDeviceParent(PRODUCTTYPE dev, ERRORCODE& err);
//电机
/**
* @if english
* @brief Get the motor limit Angle
* @param err Error code
* @return Motor limit Angle, effective range 90-2700
* @else
* @brief 获取电机的限位角度
* @param err 错误码
* @return 电机的限位角度,有效范围90-2700
* @endif
*/
WIN_API const std::pair<int, int>* getMotorLimitAngle(ERRORCODE& err);
/**
* @if english
* @brief Get the motor limit Angle
* @param id Window id
* @param angle target angle,unit deg(degree)
* @param speed target speed,unit rpm(Revolutions Per Minute)
* @param err Error code
* @return success
* @else
* @brief 电机转至角度
* @param id 窗口id
* @param angle 目标角度,单位:deg(degree)
* @param speed 目标速度,单位:rpm(Revolutions Per Minute)
* @param err 错误码
* @return 是否执行成功
* @endif
*/
WIN_API void motorMoveTo(HWND id,float angle, float speed, ERRORCODE &err);
WIN_API void motorStopMove();
/**
* @if english
* @brief Get the road sensitivity of the motor
* @param err Error code
* @return Motor road sensitivity, effective range 0-10
* @else
* @brief 获取电机的路感灵敏度
* @param err 错误码
* @return 电机的路感灵敏度,有效范围0-10
* @endif
*/
WIN_API int getMotorRoadSensitivity(ERRORCODE& err);
/**
* @if english
* @brief Get the game force feedback intensity of the motor
* @param err Error code
* @return The game force feedback intensity of the motor, effective range 0-100
* @else
* @brief 获取电机的游戏力回馈强度
* @param err 错误码
* @return 电机的游戏力回馈强度,有效范围0-100
* @endif
*/
WIN_API int getMotorFfbStrength(ERRORCODE& err);
/**
* @if english
* @brief Get the maximum steering wheel speed of the motor
* @param err Error code
* @return Motor steering wheel maximum speed, effective range 10-100
* @else
* @brief 获取电机的方向盘最大转速
* @param err 错误码
* @return 电机的方向盘最大转速,有效范围10-100
* @endif
*/
WIN_API int getMotorLimitWheelSpeed(ERRORCODE& err);
/**
* @if english
* @brief Get the mechanical return strength of the motor
* @param err Error code
* @return Mechanical return strength of the motor, effective range 0-100
* @else
* @brief 获取电机的机械回中强度
* @param err 错误码
* @return 电机的机械回中强度,有效范围0-100
* @endif
*/
WIN_API int getMotorSpringStrength(ERRORCODE& err);
/**
* @if english
* @brief Get the mechanical damping of the motor
* @param err Error code
* @return Mechanical damping of motor, effective range 0-100
* @else
* @brief 获取获取电机的机械阻尼
* @param err 错误码
* @return 电机的机械阻尼,有效范围0-100
* @endif
*/
WIN_API int getMotorNaturalDamper(ERRORCODE& err);
/**
* @if english
* @brief Get the mechanical friction of the motor
* @param err Error code
* @return Mechanical friction of motor, effective range 0-100
* @else
* @brief 获取获取电机的机械摩擦
* @param err 错误码
* @return 电机的机械摩擦,有效范围0-100
* @endif
*/
WIN_API int getMotorNaturalFriction(ERRORCODE& err);
/**
* @if english
* @brief Get the velocity damping of the motor
* @param err Error code
* @return Motor damping with speed, effective range 0-100
* @else
* @brief 获取电机的随速阻尼
* @param err 错误码
* @return 电机的随速阻尼,有效范围0-100
* @endif
*/
WIN_API int getMotorSpeedDamping(ERRORCODE& err);
/**
* @if english
* @brief Get the maximum output torque limit of the motor
* @param err Error code
* @return Motor maximum output torque limit, effective range 50-100
* @else
* @brief 获取电机的最大输出扭矩限制
* @param err 错误码
* @return 电机的最大输出扭矩限制,有效范围50-100
* @endif
*/
WIN_API int getMotorPeakTorque(ERRORCODE& err);
/**
* @if english
* @brief Get the actual steering wheel inertia ratio of the motor
* @param err Error code
* @return The actual inertia ratio of the steering wheel of the motor, effective range 100-4000
* @else
* @brief 获取电机的方向盘实际惯量比
* @param err 错误码
* @return 电机的方向盘实际惯量比,有效范围100-4000
* @endif
*/
WIN_API int getMotorNaturalInertiaRatio(ERRORCODE& err);
/**
* @if english
* @brief Get the natural inertia of the motor
* @param err Error code
* @return Natural inertia of the motor, effective range 100-500
* @else
* @brief 获取电机的自然惯量
* @param err 错误码
* @return 电机的自然惯量,有效范围100-500
* @endif
*/
WIN_API int getMotorNaturalInertia(ERRORCODE& err);
/**
* @if english
* @brief Get the velocity damping starting point of the motor
* @param err Error code
* @return Velocity damping starting point of the motor, effective range 0-400
* @else
* @brief 获取电机的随速阻尼起始点
* @param err 错误码
* @return 电机的随速阻尼起始点,有效范围0-400
* @endif
*/
WIN_API int getMotorSpeedDampingStartPoint(ERRORCODE& err);
/**
* @if english
* @brief Get the motor hand off the protective switch
* @param err Error code
* @return Motor hand off protection switch, effective range 0-1
* @else
* @brief 获取电机的手离开保护开关
* @param err 错误码
* @return 电机的手离开保护开关,有效范围0-1
* @endif
*/
WIN_API int getMotorHandsOffProtection(ERRORCODE& err);
/**
* @if english
* @brief Get the motor's game force reverse switch
* @param err Error code
* @return Motor game force reverse switch, effective range 0-1
* @else
* @brief 获取电机的游戏力反向开关
* @param err 错误码
* @return 电机的游戏力反向开关,有效范围0-1
* @endif
*/
WIN_API int getMotorFfbReverse(ERRORCODE& err);
/**
* @if english
* @brief Get the frequency of the motor's road awareness equalizer
* @param err Error code
* @return Frequency of road sensing equalizer of motor,EqualizerAmp7_5; EqualizerAmp13 EqualizerAmp22_5, EqualizerAmp39 EqualizerAmp55, [0,500], EqualizerAmp100 [0100]
* @else
* @brief 获取电机的路面感知均衡器频点
* @param err 错误码
* @return 电机的路面感知均衡器频点,EqualizerAmp7_5;EqualizerAmp13,EqualizerAmp22_5,EqualizerAmp39,EqualizerAmp55,[0,500],EqualizerAmp100[0,100]
* @endif
*/
WIN_API const std::map<std::string, int>* getMotorEqualizerAmp(ERRORCODE& err);
/**
* @if english
* @brief Set the motor limit Angle
* @param limitAngle Motor limitAngle, effective range 90-2000
* @param gameMaximumAngle game limitAngle, effective range 90-limitAngle
* @return Error code
* @else
* @brief 设置电机的限位角度
* @param limitAngle 电机的限位角度,有效范围90-2000
* @param gameMaximumAngle 游戏限位角度,有效范围90-limitAngle
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorLimitAngle(int limitAngle, int gameMaximumAngle);
/**
* @if english
* @brief Set the road sensitivity of the motor
* @param v Motor road sensitivity, effective range 0-10
* @return Error code
* @else
* @brief 设置电机的路感灵敏度
* @param v 电机的路感灵敏度,有效范围0-10
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorRoadSensitivity(int v);
/**
* @if english
* @brief Set the game force feedback intensity of the motor
* @param v The game force feedback intensity of the motor, effective range 0-100
* @return Error code
* @else
* @brief 设置电机的游戏力回馈强度
* @param v 电机的游戏力回馈强度,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorFfbStrength(int v);
/**
* @if english
* @brief Set the maximum steering wheel speed of the motor
* @param v Motor steering wheel maximum speed, effective range 10-100
* @return Error code
* @else
* @brief 设置电机的方向盘最大转速
* @param v 电机的方向盘最大转速,有效范围10-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorLimitWheelSpeed(int v);
/**
* @if english
* @brief Set the mechanical return strength of the motor
* @param v Mechanical return strength of the motor, effective range 0-100
* @return Error code
* @else
* @brief 设置电机的机械回中强度
* @param v 电机的机械回中强度,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorSpringStrength(int v);
/**
* @if english
* @brief Set to get the mechanical damping of the motor
* @param v Mechanical damping of motor, effective range 0-100
* @return Error code
* @else
* @brief 设置获取电机的机械阻尼
* @param v 电机的机械阻尼,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorNaturalDamper(int v);
/**
* @if english
* @brief Set to get the mechanical friction of the motor
* @param v Mechanical friction of motor, effective range 0-100
* @return Error code
* @else
* @brief 设置获取电机的机械摩擦
* @param v 电机的机械摩擦,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorNaturalFriction(int v);
/**
* @if english
* @brief Set the speed damping of the motor
* @param v Motor damping with speed, effective range 0-100
* @return Error code
* @else
* @brief 设置电机的随速阻尼
* @param v 电机的随速阻尼,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorSpeedDamping(int v);
/**
* @if english
* @brief Set the maximum output torque limit of the motor
* @param v Motor maximum output torque limit, effective range 50-100
* @return Error code
* @else
* @brief 设置电机的最大输出扭矩限制
* @param v 电机的最大输出扭矩限制,有效范围50-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorPeakTorque(int v);
/**
* @if english
* @brief Set the actual steering wheel inertia ratio of the motor
* @param v The actual inertia ratio of the steering wheel of the motor, effective range 100-4000
* @return Error code
* @else
* @brief 设置电机的方向盘实际惯量比
* @param v 电机的方向盘实际惯量比,有效范围100-4000
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorNaturalInertiaRatio(int v);
/**
* @if english
* @brief Set the natural inertia of the motor
* @param v Natural inertia of the motor, effective range 100-500
* @return Error code
* @else
* @brief 设置电机的自然惯量
* @param v 电机的自然惯量,有效范围100-500
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorNaturalInertia(int v);
/**
* @if english
* @brief Set the velocity damping starting point of the motor
* @param v Velocity damping starting point of the motor, effective range 0-400
* @return Error code
* @else
* @brief 设置电机的随速阻尼起始点
* @param v 电机的随速阻尼起始点,有效范围0-400
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorSpeedDampingStartPoint(int v);
/**
* @if english
* @brief Set motor hand off protection switch
* @param v Motor hand off protection switch, effective range 0-1
* @return Error code
* @else
* @brief 设置电机的手离开保护开关
* @param v 电机的手离开保护开关,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorHandsOffProtection(int v);
/**
* @if english
* @brief Set the game force reverse switch of the motor
* @param v Motor game force reverse switch, effective range 0-1
* @return Error code
* @else
* @brief 设置电机的游戏力反向开关
* @param v 电机的游戏力反向开关,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorFfbReverse(int v);
/**
* @if english
* @brief Set the frequency of the motor's road awareness equalizer
* @param v Frequency of the motor's road sense equalizer,EqualizerAmp7_5;EqualizerAmp13,EqualizerAmp22_5,EqualizerAmp39,EqualizerAmp55,[0,500],EqualizerAmp100[0,100]
* @return Error code
* @else
* @brief 设置电机的路面感知均衡器频点
* @param v 电机的路面感知均衡器频点,EqualizerAmp7_5;EqualizerAmp13,EqualizerAmp22_5,EqualizerAmp39,EqualizerAmp55,[0,500],EqualizerAmp100[0,100]
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setMotorEqualizerAmp(const std::map<std::string, int>& v);
/**
* @if english
* @brief Soft restart of motor
* @return Error code
* @else
* @brief 电机软重启
* @return 错误码
* @endif
*/
WIN_API ERRORCODE SoftReboot();
//方向盘
/**
* @if english
* @brief Steering wheel alignment
* @return Error code
* @else
* @brief 方向盘对中
* @return 错误码
* @endif
*/
WIN_API ERRORCODE CenterWheel();
/**
* @if english
* @brief Get steering wheel indicator brightness
* @param err Error code
* @return Steering wheel indicator brightness, effective range 0-100
* @else
* @brief 获取方向盘的指示灯亮度
* @param err 错误码
* @return 方向盘的指示灯亮度,有效范围0-100
* @endif
*/
WIN_API int getSteeringWheelShiftIndicatorBrightness(ERRORCODE& err);
/**
* @if english
* @brief Get the steering wheel's clutch pattern
* @param err Error code
* @return Steering wheel clutch mode, effective range 1-3
* @else
* @brief 获取方向盘的离合拨片模式
* @param err 错误码
* @return 方向盘的离合拨片模式,有效范围1-3
* @endif
*/
WIN_API int getSteeringWheelClutchPaddleAxisMode(ERRORCODE& err);
/**
* @if english
* @brief Get the clutch combination value of the steering wheel
* @param err Error code
* @return Steering wheel clutch combination value, effective range 0-100
* @else
* @brief 获取方向盘的离合拨片组合值
* @param err 错误码
* @return 方向盘的离合拨片组合值,有效范围0-100
* @endif
*/
WIN_API int getSteeringWheelClutchPaddleCombinePos(ERRORCODE& err);
/**
* @if english
* @brief Get the steering wheel's band knob mode
* @param err Error code
* @return Steering wheel's band knob mode, effective range 0-1
* @else
* @brief 获取方向盘的波段旋钮模式
* @param err 错误码
* @return 方向盘的波段旋钮模式,有效范围0-1
* @endif
*/
WIN_API int getSteeringWheelKnobMode(ERRORCODE& err);
/**
* @if english
* @brief Get the joystick pattern for the steering wheel
* @param err Error code
* @return Rocker mode for steering wheel, effective range 0-1
* @else
* @brief 获取方向盘的摇杆模式
* @param err 错误码
* @return 方向盘的摇杆模式,有效范围0-1
* @endif
*/
WIN_API int getSteeringWheelJoystickHatswitchMode(ERRORCODE& err);
/**
* @if english
* @brief Get the steering wheel's indicator switch mode
* @param err Error code
* @return Steering wheel indicator switch mode, effective range 1-3
* @else
* @brief 获取方向盘的指示灯开关模式
* @param err 错误码
* @return 方向盘的指示灯开关模式,有效范围1-3
* @endif
*/
WIN_API int getSteeringWheelShiftIndicatorSwitch(ERRORCODE& err);
/**
* @if english
* @brief Get the steering wheel indicator display mode
* @param err Error code
* @return Steering wheel indicator display mode, effective range 0-1
* @else
* @brief 获取方向盘的指示灯显示模式
* @param err 错误码
* @return 方向盘的指示灯显示模式,有效范围0-1
* @endif
*/
WIN_API int getSteeringWheelShiftIndicatorMode(ERRORCODE& err);
/**
* @if english
* @brief Get the steering wheel indicator color
* @param err Error code
* @return Indicator color
* @else
* @brief 获取方向盘的指示灯颜色
* @param err 错误码
* @return 指示灯颜色
* @endif
*/
WIN_API const std::vector<std::string>* getSteeringWheelShiftIndicatorColor(ERRORCODE& err);
/**
* @if english
* @brief Gets the steering wheel's indicator speed indication percentage
* @param err Error code
* @return Steering wheel indicator speed indicates percentage
* @else
* @brief 获取方向盘的指示灯转速提示百分比
* @param err 错误码
* @return 方向盘的指示灯转速提示百分比
* @endif
*/
WIN_API const std::vector<int>* getSteeringWheelShiftIndicatorLightRpm(ERRORCODE& err);
/**
* @if english
* @brief Gets the speed unit of the display
* @param err Error code
* @return The speed unit of the display, effective range 0-1
* @else
* @brief 获取显示屏的速度单位
* @param err 错误码
* @return 显示屏的速度单位,有效范围0-1
* @endif
*/
WIN_API int getSteeringWheelSpeedUnit(ERRORCODE& err);
/**
* @if english
* @brief Get the temperature unit of the display
* @param err Error code
* @return Temperature unit of the display, effective range 0-1
* @else
* @brief 获取显示屏的温度单位
* @param err 错误码
* @return 显示屏的温度单位,有效范围0-1
* @endif
*/
WIN_API int getSteeringWheelTemperatureUnit(ERRORCODE& err);
/**
* @if english
* @brief Gets the screen brightness of the display
* @param err Error code
* @return Display screen brightness, effective range 0-100
* @else
* @brief 获取显示屏的屏幕亮度
* @param err 错误码
* @return 显示屏的屏幕亮度,有效范围0-100
* @endif
*/
WIN_API int getSteeringWheelScreenBrightness(ERRORCODE& err);
/**
* @if english
* @brief Get UI list
* @param err Error code
* @return UI list
* @else
* @brief 获取UI列表
* @param err 错误码
* @return UI列表
* @endif
*/
WIN_API const std::map<int, std::string>* getSteeringWheelScreenUIList(ERRORCODE& err);
/**
* @if english
* @brief Get the current UI
* @param err Error code
* @return current UI
* @else
* @brief 获取当前UI
* @param err 错误码
* @return 当前UI
* @endif
*/
WIN_API int getSteeringWheelScreenCurrentUI(ERRORCODE& err);
/**
* @if english
* @brief Set steering wheel indicator brightness
* @param v Steering wheel indicator brightness, effective range 0-100
* @return Error code
* @else
* @brief 设置方向盘的指示灯亮度
* @param v 方向盘的指示灯亮度,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelShiftIndicatorBrightness(int v);
/**
* @if english
* @brief Set the steering wheel's clutch pattern
* @param v Steering wheel clutch mode, effective range 1-3
* @return Error code
* @else
* @brief 设置方向盘的离合拨片模式
* @param v 方向盘的离合拨片模式,有效范围1-3
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelClutchPaddleAxisMode(int v);
/**
* @if english
* @brief Set the clutch combination value of the steering wheel
* @param v Steering wheel clutch combination value, effective range 0-100
* @return Error code
* @else
* @brief 设置方向盘的离合拨片组合值
* @param v 方向盘的离合拨片组合值,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelClutchPaddleCombinePos(int v);
/**
* @if english
* @brief Set the steering wheel's band knob mode
* @param v Steering wheel's band knob mode, effective range 0-1
* @return Error code
* @else
* @brief 设置方向盘的波段旋钮模式
* @param v 方向盘的波段旋钮模式,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelKnobMode(int v);
/**
* @if english
* @brief Set the rocker mode for the steering wheel
* @param v Rocker mode for steering wheel, effective range 0-1
* @return Error code
* @else
* @brief 设置方向盘的摇杆模式
* @param v 方向盘的摇杆模式,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelJoystickHatswitchMode(int v);
/**
* @if english
* @brief Set the steering wheel indicator switch mode
* @param v Steering wheel indicator switch mode, effective range 1-3
* @return Error code
* @else
* @brief 设置方向盘的指示灯开关模式
* @param v 方向盘的指示灯开关模式,有效范围1-3
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelShiftIndicatorSwitch(int v);
/**
* @if english
* @brief Set the steering wheel indicator display mode
* @param v Steering wheel indicator display mode, effective range 0-1
* @return Error code
* @else
* @brief 设置方向盘的指示灯显示模式
* @param v 方向盘的指示灯显示模式,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelShiftIndicatorMode(int v);
/**
* @if english
* @brief Set the steering wheel indicator color
* @param v Indicator color
* @return Error code
* @else
* @brief 设置方向盘的指示灯颜色
* @param v 指示灯颜色
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelShiftIndicatorColor(const std::vector<std::string>& v);
/**
* @if english
* @brief Set the steering wheel's indicator speed indication percentage
* @param v Steering wheel indicator speed indication percentage, effective range 0-100
* @return Error code
* @else
* @brief 设置方向盘的指示灯转速提示百分比
* @param v 方向盘的指示灯转速提示百分比,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelShiftIndicatorLightRpm(const std::vector<int>& v);
/**
* @if english
* @brief Set the speed unit of the display
* @param v The speed unit of the display, effective range 0-1
* @return Error code
* @else
* @brief 设置显示屏的速度单位
* @param v 显示屏的速度单位,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelSpeedUnit(int v);
/**
* @if english
* @brief Set the temperature unit of the display
* @param v Temperature unit of the display, effective range 0-1
* @return Error code
* @else
* @brief 设置显示屏的温度单位
* @param v 显示屏的温度单位,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelTemperatureUnit(int v);
/**
* @if english
* @brief Set the screen brightness of the display
* @param v Display screen brightness, effective range 0-100
* @return Error code
* @else
* @brief 设置显示屏的屏幕亮度
* @param v 显示屏的屏幕亮度,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelScreenBrightness(int v);
/**
* @if english
* @brief Set current UI
* @param v current UI
* @return Error code
* @else
* @brief 设置当前UI
* @param v 当前UI
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setSteeringWheelScreenCurrentUI(int v);
//显示器
/**
* @if english
* @brief Get the speed unit of the display
* @param err Error code
* @return The speed unit of the display, effective range 0-1, 0-metric 1-imperial
* @else
* @brief 获取显示屏的速度单位
* @param err 错误码
* @return 显示屏的速度单位,有效范围0-1,0-公制 1-英制
* @endif
*/
WIN_API int getDisplayScreenSpeedUnit(ERRORCODE& err);
/**
* @if english
* @brief Get the temperature unit of the display
* @param err Error code
* @return Temperature unit of the display, effective range 0-1, 0-degrees Celsius, 1-degrees Fahrenheit
* @else
* @brief 获取显示屏的温度单位
* @param err 错误码
* @return 显示屏的温度单位,有效范围0-1,0-摄氏度 1-华氏度
* @endif
*/
WIN_API int getDisplayScreenTemperatureUnit(ERRORCODE& err);
/**
* @if english
* @brief Get the screen brightness of the display
* @param err Error code
* @return Display screen brightness, effective range 0-100
* @else
* @brief 获取显示屏的屏幕亮度
* @param err 错误码
* @return 显示屏的屏幕亮度,有效范围0-100
* @endif
*/
WIN_API int getDisplayScreenScreenBrightness(ERRORCODE& err);
/**
* @if english
* @brief Get the display UI list
* @param err Error code
* @return UI list
* @else
* @brief 获取显示屏UI列表
* @param err 错误码
* @return UI列表
* @endif
*/
WIN_API const std::map<int, std::string>* getDisplayScreenScreenUIList(ERRORCODE& err);
/**
* @if english
* @brief Get the current UI of the display
* @param err Error code
* @return current UI
* @else
* @brief 获取显示屏当前UI
* @param err 错误码
* @return 当前UI
* @endif
*/
WIN_API int getDisplayScreenScreenCurrentUI(ERRORCODE& err);
/**
* @if english
* @brief Set the speed unit of the display
* @param v The speed unit of the display, effective range 0-1, 0-metric 1-imperial
* @return Error code
* @else
* @brief 设置显示屏的速度单位
* @param v 显示屏的速度单位,有效范围0-1,0-公制 1-英制
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setDisplayScreenSpeedUnit(int v);
/**
* @if english
* @brief Set the temperature unit of the display
* @param v Temperature unit of the display, effective range 0-1, 0-degrees Celsius, 1-degrees Fahrenheit
* @return Error code
* @else
* @brief 设置显示屏的温度单位
* @param v 显示屏的温度单位,有效范围0-1,0-摄氏度 1-华氏度
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setDisplayScreenTemperatureUnit(int v);
/**
* @if english
* @brief Set the screen brightness of the display
* @param v Display screen brightness, effective range 0-100
* @return Error code
* @else
* @brief 设置显示屏的屏幕亮度
* @param v 显示屏的屏幕亮度,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setDisplayScreenScreenBrightness(int v);
/**
* @if english
* @brief Set the current UI of the display
* @param v UI id
* @return Error code
* @else
* @brief 设置显示屏当前UI
* @param v UI id
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setDisplayScreenScreenCurrentUI(int v);
//踏板
/**
* @if english
* @brief Get the clutch output direction of the pedal
* @param err Error code
* @return Pedal clutch output direction, effective range 0-1, 0-forward 1-reverse
* @else
* @brief 获取踏板的离合输出方向
* @param err 错误码
* @return 踏板的离合输出方向,有效范围0-1,0-正向 1-反向
* @endif
*/
WIN_API int getPedalClutchOutDir(ERRORCODE& err);
/**
* @if english
* @brief Get the brake output direction of the pedal
* @param err Error code
* @return Pedal brake output direction, effective range 0-1, 0-forward 1-reverse
* @else
* @brief 获取踏板的刹车输出方向
* @param err 错误码
* @return 踏板的刹车输出方向,有效范围0-1,0-正向 1-反向
* @endif
*/
WIN_API int getPedalBrakeOutDir(ERRORCODE& err);
/**
* @if english
* @brief Get the throttle output direction of the pedal
* @param err Error code
* @return Pedal throttle output direction, effective range 0-1, 0-forward 1-reverse
* @else
* @brief 获取踏板的油门输出方向
* @param err 错误码
* @return 踏板的油门输出方向,有效范围0-1,0-正向 1-反向
* @endif
*/
WIN_API int getPedalAccOutDir(ERRORCODE& err);
/**
* @if english
* @brief Get the percentage of pressure binding points of the pedal
* @param err Error code
* @return Pedal pressure binding percentage, effective range 0-100
* @else
* @brief 获取踏板的压力结合点百分比
* @param err 错误码
* @return 踏板的压力结合点百分比,有效范围0-100
* @endif
*/
WIN_API int getPedalBrakePressCombine(ERRORCODE& err);
/**
* @if english
* @brief Get the pedal clutch output nonlinear adjustment
* @param err Error code
* @return Pedal clutch output nonlinear adjustment
* @else
* @brief
* @param err 错误码
* @return 踏板离合输出非线性调整
* @endif
*/
WIN_API const std::vector<int>* getPedalClutchNonLinear(ERRORCODE& err);
/**
* @if english
* @brief Get the pedal throttle output nonlinear adjustment
* @param err Error code
* @return Pedal throttle output nonlinear adjustment
* @else
* @brief 获取踏板油门输出非线性调整
* @param err 错误码
* @return 踏板油门输出非线性调整
* @endif
*/
WIN_API const std::vector<int>* getPedalAccNonLinear(ERRORCODE& err);
/**
* @if english
* @brief Get the pedal brake output nonlinear adjustment
* @param err Error code
* @return Pedal brake output nonlinear adjustment
* @else
* @brief 获取踏板刹车输出非线性调整
* @param err 错误码
* @return 踏板刹车输出非线性调整
* @endif
*/
WIN_API const std::vector<int>* getPedalBrakeNonLinear(ERRORCODE& err);
/**
* @if english
* @brief Pedal clutch calibration begins
* @return Error code
* @else
* @brief 踏板离合标定开始
* @return 错误码
* @endif
*/
WIN_API ERRORCODE ClutchCalibrateStrat();
/**
* @if english
* @brief Pedal clutch calibration is complete
* @return Error code
* @else
* @brief 踏板离合标定结束
* @return 错误码
* @endif
*/
WIN_API ERRORCODE ClutchCalibrateFinish();
/**
* @if english
* @brief Pedal throttle calibration begins
* @return Error code
* @else
* @brief 踏板油门标定开始
* @return 错误码
* @endif
*/
WIN_API ERRORCODE AccCalibrateStrat();
/**
* @if english
* @brief Pedal throttle calibration is complete
* @return Error code
* @else
* @brief 踏板油门标定结束
* @return 错误码
* @endif
*/
WIN_API ERRORCODE AccCalibrateFinish();
/**
* @if english
* @brief Pedal brake calibration begins
* @return Error code
* @else
* @brief 踏板刹车标定开始
* @return 错误码
* @endif
*/
WIN_API ERRORCODE BrakeCalibrateStrat();
/**
* @if english
* @brief Pedal brake calibration complete
* @return Error code
* @else
* @brief 踏板刹车标定结束
* @return 错误码
* @endif
*/
WIN_API ERRORCODE BrakeCalibrateFinish();
/**
* @if english
* @brief Set the clutch output direction of the pedal
* @param v Pedal clutch output direction, effective range 0-1, 0-forward 1-reverse
* @return Error code
* @else
* @brief 设置踏板的离合输出方向
* @param v 踏板的离合输出方向,有效范围0-1,0-正向 1-反向
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalClutchOutDir(int v);
/**
* @if english
* @brief Set the brake output direction of the pedal
* @param v Pedal brake output direction, effective range 0-1, 0-forward 1-reverse
* @return Error code
* @else
* @brief 设置踏板的刹车输出方向
* @param v 踏板的刹车输出方向,有效范围0-1,0-正向 1-反向
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalBrakeOutDir(int v);
/**
* @if english
* @brief Set the throttle output direction of the pedal
* @param v Pedal throttle output direction, effective range 0-1, 0-forward 1-reverse
* @return Error code
* @else
* @brief 设置踏板的油门输出方向
* @param v 踏板的油门输出方向,有效范围0-1,0-正向 1-反向
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalAccOutDir(int v);
/**
* @if english
* @brief Set the percentage of pressure binding points for the pedal
* @param v Pedal pressure binding percentage, effective range 0-100
* @return Error code
* @else
* @brief 设置踏板的压力结合点百分比
* @param v 踏板的压力结合点百分比,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalBrakePressCombine(int v);
/**
* @if english
* @brief Set pedal clutch output nonlinear adjustment
* @param v Pedal clutch output nonlinear adjustment, effective range 0-100
* @return Error code
* @else
* @brief 设置踏板离合输出非线性调整
* @param v 踏板离合输出非线性调整,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalClutchNonLinear(const std::vector<int>& v);
/**
* @if english
* @brief Set pedal throttle output nonlinear adjustment
* @param v Pedal throttle output nonlinear adjustment, effective range 0-100
* @return Error code
* @else
* @brief 设置踏板油门输出非线性调整
* @param v 踏板油门输出非线性调整,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalAccNonLinear(const std::vector<int>& v);
/**
* @if english
* @brief Set pedal brake output nonlinear adjustment
* @param v Pedal brake output nonlinear adjustment
* @return Error code
* @else
* @brief 设置踏板刹车输出非线性调整
* @param v 踏板刹车输出非线性调整
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setPedalBrakeNonLinear(const std::vector<int>& v);
//手刹
/**
* @if english
* @brief Get the output direction of the handbrake
* @param err Error code
* @return Hand brake output direction, effective range 0-1
* @else
* @brief 获取手刹的输出方向
* @param err 错误码
* @return 手刹的输出方向,有效范围0-1
* @endif
*/
WIN_API int getHandbrakeOutDir(ERRORCODE& err);
/**
* @if english
* @brief Get the application mode of the handbrake
* @param err Error code
* @return Handbrake application mode, effective range 0-1
* @else
* @brief 获取手刹的应用模式
* @param err 错误码
* @return 手刹的应用模式,有效范围0-1
* @endif
*/
WIN_API int getHandbrakeApplicationMode(ERRORCODE& err);
/**
* @if english
* @brief Get the nonlinear adjustment of handbrake output
* @param err Error code
* @return Handbrake output nonlinear adjustment
* @else
* @brief 获取手刹输出非线性调整
* @param err 错误码
* @return 手刹输出非线性调整
* @endif
*/
WIN_API const std::vector<int>* getHandbrakeNonLinear(ERRORCODE& err);
/**
* @if english
* @brief Handbrake calibration Start
* @return Error code
* @else
* @brief 手刹标定开始
* @return 错误码
* @endif
*/
WIN_API ERRORCODE HandbrakeCalibrateStart();
/**
* @if english
* @brief Handbrake calibration complete
* @return Error code
* @else
* @brief 手刹标定结束
* @return 错误码
* @endif
*/
WIN_API ERRORCODE HandbrakeCalibrateFinish();
/**
* @if english
* @brief Set the output direction of the handbrake
* @param v Hand brake output direction, effective range 0-1
* @return Error code
* @else
* @brief 设置手刹的输出方向
* @param v 手刹的输出方向,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setHandbrakeOutDir(int v);
/**
* @if english
* @brief Set the application mode of the handbrake
* @param v Handbrake application mode, effective range 0-1
* @return Error code
* @else
* @brief 设置手刹的应用模式
* @param v 手刹的应用模式,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setHandbrakeApplicationMode(int v);
/**
* @if english
* @brief Set the handbrake output nonlinear adjustment
* @param v Handbrake output nonlinear adjustment
* @return Error code
* @else
* @brief 设置手刹输出非线性调整
* @param v 手刹输出非线性调整
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setHandbrakeNonLinear(const std::vector<int>& v);
//换挡器
/**
* @if english
* @brief Get the downshift refill output percentage of the shifter
* @param err Error code
* @return Downshift oil output percentage of the stopper, effective range 0-100
* @else
* @brief 获取换挡器的降档补油输出百分比
* @param err 错误码
* @return 挡器的降档补油输出百分比,有效范围0-100
* @endif
*/
WIN_API int getHandingShifterAutoBlipOutput(ERRORCODE& err);
/**
* @if english
* @brief Get the downshift refill duration of the shifter
* @param err Error code
* @return Downshift replenishment duration of gear shifter, effective range 0-1000
* @else
* @brief 获取换挡器的降档补油持续时间
* @param err 错误码
* @return 换挡器的降档补油持续时间,有效范围0-1000
* @endif
*/
WIN_API int getHandingShifterAutoBlipDuration(ERRORCODE& err);
/**
* @if english
* @brief Get the downshift refill switch of the gear shifter
* @param err Error code
* @return Downshift oil refill switch of gear shifter, effective range 0-1
* @else
* @brief 获取换挡器的降档补油开关
* @param err 错误码
* @return 换挡器的降档补油开关,有效范围0-1
* @endif
*/
WIN_API int getHandingShifterAutoBlipSwitch(ERRORCODE& err);
/**
* @if english
* @brief Gear shifter start calibration
* @return Error code
* @else
* @brief 换挡器开始标定
* @return 错误码
* @endif
*/
WIN_API ERRORCODE ShifterCalibrateStart();
/**
* @if english
* @brief Shift end calibration
* @return Error code
* @else
* @brief 换挡器结束标定
* @return 错误码
* @endif
*/
WIN_API ERRORCODE ShifterCalibrateFinish();
/**
* @if english
* @brief Get the downshift refill output percentage of the shifter
* @param v Downshift oil output percentage of the stopper, effective range 0-100
* @return Error code
* @else
* @brief 获取换挡器的降档补油输出百分比
* @param v 挡器的降档补油输出百分比,有效范围0-100
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setHandingShifterAutoBlipOutput(int v);
/**
* @if english
* @brief Get the downshift refill duration of the shifter
* @param v Downshift replenishment duration of gear shifter, effective range 0-1000
* @return Error code
* @else
* @brief 获取换挡器的降档补油持续时间
* @param v 换挡器的降档补油持续时间,有效范围0-1000
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setHandingShifterAutoBlipDuration(int v);
/**
* @if english
* @brief Get the downshift refill switch of the gear shifter
* @param v Downshift oil refill switch of gear shifter, effective range 0-1
* @return Error code
* @else
* @brief 获取换挡器的降档补油开关
* @param v 换挡器的降档补油开关,有效范围0-1
* @return 错误码
* @endif
*/
WIN_API ERRORCODE setHandingShifterAutoBlipSwitch(int v);
/**
* @if english
* @brief Enumerates all MOZA Switches devices
* @param err Error code
* @return A list of device objects
* @else
* @brief 枚举出所有MOZA Switches设备(多功能组合开关)
* @param err 错误码
* @return 设备对象列表
* @endif
*/
WIN_API std::vector<moza::SwitchesDevice> enumSwitchesDevices(ERRORCODE& err);
/**
* @if english
* @brief Enumerates all MOZA Shifter devices
* @param err Error code
* @return A list of device objects
* @else
* @brief 枚举出所有MOZA Shifter设备(换挡器)
* @param err 错误码
* @return 设备对象列表
* @endif
*/
WIN_API std::vector<moza::ShifterDevice> enumShifterDevices(ERRORCODE& err);
}
#pragma once
#include "./hid_device.h"
namespace moza {
class WIN_API ShifterDevice : public HidDevice
{
public:
using HidDevice::HidDevice;
/**
* @if english
* @brief Get the current gear of the shifter
* @return The current gear
* @retval -1 for reverse gear, 0 for neutral gear, and 1-7 for forward gears.
* During gear shifting, since the neutral position is passed through, a value of 0 may appear during this process.
* @warning This function waits for the HID report while reading data, until valid data is received or an error occurs.
This means the execution time of this function may be relatively long, and it is not recommended to call it in the main thread.
* @else
* @brief 获取换挡器的当前档位
* @return 当前档位
* @retval -1为倒档,0为空档,1-7为前进档。在切换档位时,因为中途会经过空档,所以在这个过程中会出现0的值
* @warning 该函数在读取数据时会等待HID报文,直到读取到有效数据或者发生错误。这意味着该函数的执行时间可能会比较长,不适合在主线程中调用
* @endif
*/
int getCurrentGear() const;
};
}
#pragma once
#include "./hid_device.h"
enum ERRORCODE;
namespace moza {
/**
* @if english
* @brief Enumeration of switch indices for MOZA Switches devices
* @note The enumeration values can be directly used as indices for the switch state array
* @note Toggle Switch is a latching switch (it remains triggered after being pressed);
* Rotary Switch is a position switch (it stays at different positions or settings).
* @else
* @brief MOZA Switches(多功能组合开关)设备的开关索引枚举
* @note 枚举值可直接用作开关状态数组的下标
* @note Toggle Switch是保持型开关(按下触发后一直保持);Rotary Switch是拨动型开关(保持在不同挡位/位置)
* @endif
*/
enum SwitchesIndex
{
HeadlightOff = 0, /* Rotary Switch 1 */
HeadlightPark, /* Rotary Switch 1 */
HeadlightHigh, /* Rotary Switch 1 */
HighBeam, /* Rotary Switch 2 special */
FlasherOff, /* Rotary Switch 2 special */
Flasher, /* Rotary Switch 2 special */
FogLight, /* Toggle Switch */
TurnRight, /* Rotary Switch 3 */
TurnSignalOff, /* Rotary Switch 3 */
TurnLeft, /* Rotary Switch 3 */
RearWiperOff, /* Rotary Switch 4 */
RearWiperSpray, /* Rotary Switch 4 */
RearWiperWash, /* Rotary Switch 4 toggle */
WiperSensitivity1, /* Rotary Switch 5 */
WiperSensitivity2, /* Rotary Switch 5 */
WiperSensitivity3, /* Rotary Switch 5 */
WiperSensitivity4, /* Rotary Switch 5 */
WiperSensitivity5, /* Rotary Switch 5 */
FrontWiperWash, /* Toggle Switch */
FrontWiperSingle, /* Rotary Switch 6 toggle */
FrontWiperOff, /* Rotary Switch 6 */
FrontWiperInterval, /* Rotary Switch 6 */
FrontWiperLow, /* Rotary Switch 6 */
FrontWiperHigh, /* Rotary Switch 6 */
CruiseOnOff, /* Toggle Switch */
CruiseDecrease, /* Toggle Switch */
CruiseIncrease, /* Toggle Switch */
CruiseCancel, /* Toggle Switch */
MAX_SWITCHES_INDEX
};
/**
* @if english
* @brief Group of switches, specifically for Rotary Switches. Each group corresponds to the different positions of a single Rotary Switch
* @else
* @brief 开关组,仅针对Rotary Switch旋转型开关,每组就是一个Rotary Switch对应在不同位置
* @endif
*/
const static std::vector<SwitchesIndex> SWITCHES_GROUPS[] = {
{HeadlightOff, HeadlightPark, HeadlightHigh}, /* Rotary Switch Group 1 */
{HighBeam, FlasherOff, Flasher}, /* Rotary Switch Group 2 */
{TurnRight, TurnSignalOff, TurnLeft}, /* Rotary Switch Group 3 */
{RearWiperOff, RearWiperSpray, RearWiperWash}, /* Rotary Switch Group 4 */
{WiperSensitivity1, WiperSensitivity2, WiperSensitivity3, WiperSensitivity4, WiperSensitivity5}, /* Rotary Switch Group 5 */
{FrontWiperSingle, FrontWiperOff, FrontWiperInterval, FrontWiperLow, FrontWiperHigh}, /* Rotary Switch Group 6 */
};
/**
* @if english
* @brief MOZA Switches device class
* @else
* @brief MOZA Switches(多功能组合开关)设备类
* @endif
*/
class WIN_API SwitchesDevice : public HidDevice
{
friend class SwitchesDevicePrivate;
public:
/**
* @if english
* @brief Default constructor
* @else
* @brief 无参构造
* @endif
*/
SwitchesDevice();
/**
* @if english
* @brief Constructs with a device instance path
* @param path device instance path
* @else
* @brief 从一个设备实例路径构造
* @param path 设备实例路径
* @endif
*/
explicit SwitchesDevice(const std::string& path);
~SwitchesDevice() override;
SwitchesDevice(const SwitchesDevice&) = delete;
SwitchesDevice& operator=(const SwitchesDevice&) = delete;
SwitchesDevice(SwitchesDevice&& other) noexcept;
SwitchesDevice& operator=(SwitchesDevice&& other) noexcept;
/**
* @if english
* @brief Open the device
* @return True if the device is successfully opened; false otherwise
* @else
* @brief 打开设备
* @return 设备是否成功打开
* @endif
*/
bool open() override;
/**
* @if english
* @brief Close the device
* @else
* @brief 关闭设备
* @endif
*/
void close() override;
/**
* @if english
* @brief Check if the rotary switch states are ready
* @return Returns true if the states are ready; otherwise, returns false
* @note This function is non-blocking when reading data
* @else
* @brief 检查旋转型开关的状态是否准备完毕
* @return 如果准备完毕则返回true;否则返回false
* @note 该函数在读取数据是非阻塞的
* @endif
*/
bool isRotarySwitchStateReady() const;
/**
* @if english
* @brief Get the current switches state of the device
* @param err Error code
* @return A vector of device switches state
* @retval Each element in the vector represents the state of a switch.
* The index starts from 0 and corresponds to the switch numbers in MOZA Pit House minus 1.
* Alternatively, refer to the moza::SwitchesIndex enum values.
* @note Some switch state data needs to be retrieved from Pit House. Establishing communication between the SDK and Pit House takes time to complete.
* Therefore, the switch states obtained by this function may be inaccurate before the communication is fully established.
* You can check whether the preparation is complete by using the return value of the `isRotarySwitchStateReady` function or the error code `err`.
* This function is non-blocking when reading data
* @else
* @brief 获取设备当前的开关状态
* @param err 错误码
* @return 设备的开关状态数组
* @retval 数组的每一项都表示一个开关的状态。下标从0开始,对应MOZA Pit House中的开关编号-1,也可以参考moza::SwitchesIndex枚举值
* @note 开关状态部分数据需要从PitHouse获取,而SDK与PitHouse的通信建立需要一定的时间才能完成,所以在通信未完成时该函数获取到的开关状态不准确;
* 可以通过`isRotarySwitchStateReady`函数返回值或者错误码`err`判断是否准备完毕;
* 该函数在读取数据是非阻塞的。
* @endif
*/
std::vector<uint8_t> getStateInfo(ERRORCODE& err) const;
/**
* @if english
* @brief Get the current switches state of the device (retrieved solely from the HID reports sent by the device)
* @return A vector of device switches state
* @retval Each element in the vector represents the state of a switch.
* The index starts from 0 and corresponds to the switch numbers in MOZA Pit House minus 1.
* Alternatively, refer to the moza::SwitchesIndex enum values.
* @note It is generally recommended to use the `getStateInfo` function to obtain the current switch state of the device.
* This function retrieves the switch state solely by reading the HID report, which does not include the device's initial state.
* It can be used when the device firmware is not supported or when PitHouse cannot be connected.
* This function is non-blocking when reading data.
* @else
* @brief 获取设备当前的开关状态(仅通过设备发送的HID报告来获取)
* @return 设备的开关状态数组
* @retval 数组的每一项都表示一个开关的状态。下标从0开始,对应MOZA Pit House中的开关编号-1,也可以参考moza::SwitchesIndex枚举值
* @note 通常情况下建议使用`getStateInfo`函数来获取当前设备的开关状态。该函数仅通过读取HID报告来获取开关状态,这将无法获取到设备的初始状态。可以在设备固件不支持时或无法连接PitHouse时使用该函数。
* 该函数在读取数据是非阻塞的。
* @endif
*/
std::vector<uint8_t> getStateInfoByHid() const;
private:
SwitchesDevicePrivate* m_impl;
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment