diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7812be5..924250a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,7 +115,24 @@ jobs: Write-Error "InputWeave.GameInput 套件 SHA256 不符。Expected=$expected Actual=$actual" } + $expectedCommit = "72697db594b8f1863bd3fbf5db75ff69b40e3364" + $inspectDir = Join-Path $env:RUNNER_TEMP "inputweave-gameinput-package" + if (Test-Path $inspectDir) { + Remove-Item -LiteralPath $inspectDir -Recurse -Force + } + New-Item -ItemType Directory -Path $inspectDir | Out-Null + Expand-Archive -Path $packagePath -DestinationPath $inspectDir -Force + $nuspecPath = Get-ChildItem -LiteralPath $inspectDir -Filter "*.nuspec" -File | Select-Object -First 1 + if ($null -eq $nuspecPath) { + Write-Error "InputWeave.GameInput 套件缺少 nuspec。" + } + $nuspecText = Get-Content -LiteralPath $nuspecPath.FullName -Raw + if ($nuspecText -notmatch "commit=`"$expectedCommit`"") { + Write-Error "InputWeave.GameInput 套件封裝來源 commit 不符;必須為 $expectedCommit。" + } + Write-Host "InputWeave.GameInput 套件 SHA256 驗證通過:$actual" + Write-Host "InputWeave.GameInput 套件封裝來源 commit 驗證通過:$expectedCommit" - name: 還原主專案 NuGet 套件 run: dotnet restore ./src/InputBox/InputBox.csproj --force-evaluate diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad6318b..0b95a22 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -92,7 +92,24 @@ jobs: Write-Error "InputWeave.GameInput 套件 SHA256 不符。Expected=$expected Actual=$actual" } + $expectedCommit = "72697db594b8f1863bd3fbf5db75ff69b40e3364" + $inspectDir = Join-Path $env:RUNNER_TEMP "inputweave-gameinput-package" + if (Test-Path $inspectDir) { + Remove-Item -LiteralPath $inspectDir -Recurse -Force + } + New-Item -ItemType Directory -Path $inspectDir | Out-Null + Expand-Archive -Path $packagePath -DestinationPath $inspectDir -Force + $nuspecPath = Get-ChildItem -LiteralPath $inspectDir -Filter "*.nuspec" -File | Select-Object -First 1 + if ($null -eq $nuspecPath) { + Write-Error "InputWeave.GameInput 套件缺少 nuspec。" + } + $nuspecText = Get-Content -LiteralPath $nuspecPath.FullName -Raw + if ($nuspecText -notmatch "commit=`"$expectedCommit`"") { + Write-Error "InputWeave.GameInput 套件封裝來源 commit 不符;必須為 $expectedCommit。" + } + Write-Host "InputWeave.GameInput 套件 SHA256 驗證通過:$actual" + Write-Host "InputWeave.GameInput 套件封裝來源 commit 驗證通過:$expectedCommit" - name: 還原 NuGet 套件 run: dotnet restore ./src/InputBox/InputBox.csproj --force-evaluate @@ -237,13 +254,13 @@ jobs: Add-Content -Path $noticePath -Encoding utf8 -Value '## InputWeave.GameInput' Add-Content -Path $noticePath -Encoding utf8 -Value '' Add-Content -Path $noticePath -Encoding utf8 -Value '- 套件:InputWeave.GameInput 0.0.1' - Add-Content -Path $noticePath -Encoding utf8 -Value '- 來源:https://github.com/rubujo/InputWeave.GameInput/tree/664a9d3e96458a49688ff2255a36f6e073977065' + Add-Content -Path $noticePath -Encoding utf8 -Value '- 來源:https://github.com/rubujo/InputWeave.GameInput/tree/72697db594b8f1863bd3fbf5db75ff69b40e3364' Add-Content -Path $noticePath -Encoding utf8 -Value '- 作者:https://github.com/rubujo' Add-Content -Path $noticePath -Encoding utf8 -Value '- 貢獻者:https://github.com/rubujo/InputWeave.GameInput/graphs/contributors' - Add-Content -Path $noticePath -Encoding utf8 -Value '- 封裝來源:https://github.com/rubujo/InputWeave.GameInput/commit/664a9d3e96458a49688ff2255a36f6e073977065' + Add-Content -Path $noticePath -Encoding utf8 -Value '- 封裝來源:https://github.com/rubujo/InputWeave.GameInput/commit/72697db594b8f1863bd3fbf5db75ff69b40e3364' Add-Content -Path $noticePath -Encoding utf8 -Value '- 套件檔案:eng/nuget/InputWeave.GameInput.0.0.1.nupkg' - Add-Content -Path $noticePath -Encoding utf8 -Value '- SHA256: 64d9ef502853130d4af8df7cc1c2777a67808ef668e41c22fc6b526b83ed2805' - Add-Content -Path $noticePath -Encoding utf8 -Value '- 授權:Creative Commons CC0 1.0 Universal(SPDX:CC0-1.0);詳見本 Licenses 目錄中的 InputWeave.GameInput_LICENSE.txt 與 https://github.com/rubujo/InputWeave.GameInput/blob/664a9d3e96458a49688ff2255a36f6e073977065/LICENSE。' + Add-Content -Path $noticePath -Encoding utf8 -Value '- SHA256: 451b9d65143eafea130ec3492f12a991b29c62d53509e74b856894848f329f5e' + Add-Content -Path $noticePath -Encoding utf8 -Value '- 授權:Creative Commons CC0 1.0 Universal(SPDX:CC0-1.0);詳見本 Licenses 目錄中的 InputWeave.GameInput_LICENSE.txt 與 https://github.com/rubujo/InputWeave.GameInput/blob/72697db594b8f1863bd3fbf5db75ff69b40e3364/LICENSE。' - name: 產生執行檔的雜湊值(SHA256) shell: pwsh diff --git a/README.md b/README.md index 55cdf3d..95aa536 100644 --- a/README.md +++ b/README.md @@ -592,7 +592,7 @@ Remove-Item Env:INPUTBOX_RUN_UI_TESTS -ErrorAction SilentlyContinue - [.NET Runtime](https://github.com/dotnet/runtime):由 [Microsoft](https://github.com/microsoft) 及其 [貢獻者](https://github.com/dotnet/runtime/graphs/contributors) 開發並採用 [**MIT License**](https://github.com/dotnet/runtime/blob/main/LICENSE.TXT) 授權,作為本應用程式之底層執行環境,相關第三方聲明請參閱 [**THIRD-PARTY-NOTICES**](https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT)。 - [Windows Forms(WinForms)](https://github.com/dotnet/winforms):由 [Microsoft](https://github.com/microsoft) 及其 [貢獻者](https://github.com/dotnet/winforms/graphs/contributors) 開發並採用 [**MIT License**](https://github.com/dotnet/winforms/blob/main/LICENSE.TXT) 授權,提供桌面視窗圖形介面基礎架構,相關第三方聲明請參閱 [**THIRD-PARTY-NOTICES**](https://github.com/dotnet/winforms/blob/main/THIRD-PARTY-NOTICES.TXT)。 -- [InputWeave.GameInput 0.0.1](https://github.com/rubujo/InputWeave.GameInput/tree/664a9d3e96458a49688ff2255a36f6e073977065):由 [rubujo](https://github.com/rubujo) 及其 [貢獻者](https://github.com/rubujo/InputWeave.GameInput/graphs/contributors) 開發並採用 [**CC0 1.0 Universal**](https://github.com/rubujo/InputWeave.GameInput/blob/664a9d3e96458a49688ff2255a36f6e073977065/LICENSE) 授權,提供 GameInput 執行階段、用戶端、裝置、讀取狀態與震動控制介面。套件固定於本儲存庫的 NuGet 來源 `eng/nuget/InputWeave.GameInput.0.0.1.nupkg`,封裝來源為 [`664a9d3e96458a49688ff2255a36f6e073977065`](https://github.com/rubujo/InputWeave.GameInput/commit/664a9d3e96458a49688ff2255a36f6e073977065),套件 SHA256 為 `64d9ef502853130d4af8df7cc1c2777a67808ef668e41c22fc6b526b83ed2805`。 +- [InputWeave.GameInput 0.0.1](https://github.com/rubujo/InputWeave.GameInput/tree/72697db594b8f1863bd3fbf5db75ff69b40e3364):由 [rubujo](https://github.com/rubujo) 及其 [貢獻者](https://github.com/rubujo/InputWeave.GameInput/graphs/contributors) 開發並採用 [**CC0 1.0 Universal**](https://github.com/rubujo/InputWeave.GameInput/blob/72697db594b8f1863bd3fbf5db75ff69b40e3364/LICENSE) 授權,提供 GameInput 執行階段、用戶端、裝置、讀取狀態與震動控制介面。套件固定於本儲存庫的 NuGet 來源 `eng/nuget/InputWeave.GameInput.0.0.1.nupkg`,封裝來源為 [`72697db594b8f1863bd3fbf5db75ff69b40e3364`](https://github.com/rubujo/InputWeave.GameInput/commit/72697db594b8f1863bd3fbf5db75ff69b40e3364),套件 SHA256 為 `451b9d65143eafea130ec3492f12a991b29c62d53509e74b856894848f329f5e`。 - [Microsoft GameInput Redistributable](https://www.nuget.org/packages/Microsoft.GameInput):由 Microsoft 提供,作為選用的 GameInput 執行階段可轉散發套件。正式發佈 ZIP 檔會隨附 `redist/GameInputRedist.msi` 供使用者手動安裝;本應用程式不會自動安裝。手動安裝 `redist/GameInputRedist.msi` 即表示使用者需遵守 [Microsoft.GameInput 授權條款](https://www.nuget.org/packages/Microsoft.GameInput/3.4.218/License);相關授權與 NOTICE 檔案位於 `Licenses/Microsoft.GameInput_LICENSE.txt` 與 `Licenses/Microsoft.GameInput_NOTICE.txt`,且該可轉散發安裝程式不屬於本專案 CC0 授權範圍。 本專案的詳細條款與免責聲明,請參閱隨附之 [**LICENSE**](LICENSE) 文件;發佈檔 `Licenses/` 資料夾內含 `ThirdPartyNotices.txt`(NuGet 套件授權聲明清單)、`InputWeave.GameInput_LICENSE.txt`、`Microsoft.GameInput_LICENSE.txt`、`Microsoft.GameInput_NOTICE.txt`,以及各元件完整授權文字;[Microsoft.GameInput 3.4.218 線上授權頁](https://www.nuget.org/packages/Microsoft.GameInput/3.4.218/License) 另可於 NuGet 查閱。 diff --git a/docs/engineering/gamepad-api.md b/docs/engineering/gamepad-api.md index 15932eb..96b8538 100644 --- a/docs/engineering/gamepad-api.md +++ b/docs/engineering/gamepad-api.md @@ -28,6 +28,7 @@ - **GameInput 同步**:InputBox 仍必須在背景 MTA polling thread 建立、存取與釋放 InputWeave `GameInputClient` / `GameInputDevice` / callback registration;callback 只能設定喚醒或重新整理訊號,不得直接觸發 managed UI 命令。 - **GameInput 診斷 metadata 邊界**:runtime probe、timestamp stale counters、missing reading counters、device unavailable refresh counters 只能進入 log、測試或未來診斷快照,不可直接改變 edge detection、Pause/Resume neutral gate 或任何 UI 命令。 - **GameInput subset 範圍**:目前只實作 InputBox 需要的 Gamepad subset:裝置資訊、VID/PID、timestamp、gamepad button state、rumble、device/reading callbacks,以及 gamepad capabilities / extra control metadata。不得在未重新評估安全與產品需求前擴張到 keyboard、mouse、sensors、raw report、force feedback、aggregate device 或 1:1 GameInput wrapper。 +- **InputWeave callback 互通性**:repo-local `InputWeave.GameInput` 套件的 `IGameInput.Register*Callback` callback 參數必須以 `MarshalAs(UnmanagedType.FunctionPtr)` 宣告。不得以 InputBox 端 aggregate polling fallback 遮蔽 callback marshaling 錯誤;若列舉或 callback 仍失敗,應走既有 GameInput 初始化失敗與 XInput 退避路徑。 - **Callback 使用邊界**:GameInput 的 `RegisterDeviceCallback` / `RegisterReadingCallback` 僅可用於要求背景 MTA polling thread 重新整理或喚醒診斷路徑;正式輸入命令仍必須由 60 FPS polling 消費,callback 不得直接觸發 UI、剪貼簿、返回前景或任何輸入動作。 - **GameInput runtime/redist 政策**:`Microsoft.GameInput` NuGet 僅作為官方 SDK、header 與 redist 來源。發佈 ZIP 可隨附 `redist/GameInputRedist.msi` 供使用者手動安裝,但應用程式不得自動執行安裝程式,也不得要求一般啟動流程取得系統管理員權限。 - **Auto 模式解析優先序**:當使用者選擇 Face 鍵 `Auto` 模式且目前提供者為 **GameInput** 時,必須先使用較穩定的硬體識別資訊(例如 VID/PID、產品家族名稱)判斷裝置類型,再退回裝置名稱關鍵字比對;像 `Wireless`、`Bluetooth`、`Adapter`、`Receiver` 等連線詞應視為雜訊而忽略。 diff --git a/eng/nuget/InputWeave.GameInput.0.0.1.nupkg b/eng/nuget/InputWeave.GameInput.0.0.1.nupkg index da3d81e..cc95516 100644 Binary files a/eng/nuget/InputWeave.GameInput.0.0.1.nupkg and b/eng/nuget/InputWeave.GameInput.0.0.1.nupkg differ diff --git a/eng/nuget/InputWeave.GameInput.0.0.1.nupkg.sha256 b/eng/nuget/InputWeave.GameInput.0.0.1.nupkg.sha256 index ee5c8d7..14d0220 100644 --- a/eng/nuget/InputWeave.GameInput.0.0.1.nupkg.sha256 +++ b/eng/nuget/InputWeave.GameInput.0.0.1.nupkg.sha256 @@ -1 +1 @@ -64d9ef502853130d4af8df7cc1c2777a67808ef668e41c22fc6b526b83ed2805 InputWeave.GameInput.0.0.1.nupkg +451b9d65143eafea130ec3492f12a991b29c62d53509e74b856894848f329f5e InputWeave.GameInput.0.0.1.nupkg diff --git a/eng/nuget/InputWeave.GameInput_LICENSE.txt b/eng/nuget/InputWeave.GameInput_LICENSE.txt index 66fddfe..d300119 100644 --- a/eng/nuget/InputWeave.GameInput_LICENSE.txt +++ b/eng/nuget/InputWeave.GameInput_LICENSE.txt @@ -1,15 +1,15 @@ InputWeave.GameInput 0.0.1 =========================== -來源: https://github.com/rubujo/InputWeave.GameInput/tree/664a9d3e96458a49688ff2255a36f6e073977065 +來源: https://github.com/rubujo/InputWeave.GameInput/tree/72697db594b8f1863bd3fbf5db75ff69b40e3364 作者: https://github.com/rubujo 貢獻者: https://github.com/rubujo/InputWeave.GameInput/graphs/contributors -封裝來源: https://github.com/rubujo/InputWeave.GameInput/commit/664a9d3e96458a49688ff2255a36f6e073977065 +封裝來源: https://github.com/rubujo/InputWeave.GameInput/commit/72697db594b8f1863bd3fbf5db75ff69b40e3364 套件檔案: eng/nuget/InputWeave.GameInput.0.0.1.nupkg -套件 SHA256: 64d9ef502853130d4af8df7cc1c2777a67808ef668e41c22fc6b526b83ed2805 +套件 SHA256: 451b9d65143eafea130ec3492f12a991b29c62d53509e74b856894848f329f5e 授權名稱: Creative Commons CC0 1.0 Universal 授權識別碼 (SPDX): CC0-1.0 -授權檔案: https://github.com/rubujo/InputWeave.GameInput/blob/664a9d3e96458a49688ff2255a36f6e073977065/LICENSE +授權檔案: https://github.com/rubujo/InputWeave.GameInput/blob/72697db594b8f1863bd3fbf5db75ff69b40e3364/LICENSE InputWeave.GameInput 採用 Creative Commons CC0 1.0 Universal 公眾領域貢獻宣告。 在法律允許的最大範圍內,作者已將此套件的著作權與相關權利貢獻至全球公眾領域。 diff --git a/tests/InputBox.Tests/GameInputDirectUsageTests.cs b/tests/InputBox.Tests/GameInputDirectUsageTests.cs index 68f6c49..77330a2 100644 --- a/tests/InputBox.Tests/GameInputDirectUsageTests.cs +++ b/tests/InputBox.Tests/GameInputDirectUsageTests.cs @@ -2,6 +2,7 @@ using InputWeave.GameInput; using InputWeave.GameInput.Interop; using System.Reflection; +using System.Runtime.InteropServices; using Xunit; namespace InputBox.Tests; @@ -30,6 +31,18 @@ public void RequiredInputWeaveGamepadApi_Surface_IsAvailable() Assert.NotNull(typeof(GameInputDevice).GetMethod(nameof(GameInputDevice.SetRumbleState), [typeof(GameInputRumbleParams).MakeByRefType()])); } + /// + /// InputWeave 的 GameInput callback 參數必須以 unmanaged function pointer 傳遞,避免退回 _Delegate COM marshaling。 + /// + [Fact] + public void GameInputCallbackParameters_AreFunctionPointers() + { + AssertCallbackParameterIsFunctionPointer(nameof(IGameInput.RegisterReadingCallback), typeof(GameInputReadingCallback)); + AssertCallbackParameterIsFunctionPointer(nameof(IGameInput.RegisterDeviceCallback), typeof(GameInputDeviceCallback)); + AssertCallbackParameterIsFunctionPointer(nameof(IGameInput.RegisterSystemButtonCallback), typeof(GameInputSystemButtonCallback)); + AssertCallbackParameterIsFunctionPointer(nameof(IGameInput.RegisterKeyboardLayoutCallback), typeof(GameInputKeyboardLayoutCallback)); + } + /// /// GameInput v3 的 gamepad button 位元必須維持 Microsoft 定義值,避免 face key、D-Pad、背鍵與搖桿方向判斷錯位。 /// @@ -166,6 +179,17 @@ public void GameInputRumbleParams_MotorFields_PreserveAssignedValues() Assert.Equal(0.4f, rumble.RightTrigger); } + private static void AssertCallbackParameterIsFunctionPointer(string methodName, Type callbackType) + { + MethodInfo method = typeof(IGameInput).GetMethod(methodName) + ?? throw new InvalidOperationException($"找不到 IGameInput.{methodName}。"); + ParameterInfo callbackParameter = method.GetParameters().Single(parameter => parameter.ParameterType == callbackType); + MarshalAsAttribute? marshalAs = callbackParameter.GetCustomAttribute(); + + Assert.NotNull(marshalAs); + Assert.Equal(UnmanagedType.FunctionPtr, marshalAs.Value); + } + private static GameInputDeviceInfoSnapshot CreateDeviceInfoSnapshot( ushort vendorId, ushort productId, diff --git a/tests/InputBox.Tests/README.md b/tests/InputBox.Tests/README.md index 4e396ff..dfae4a2 100644 --- a/tests/InputBox.Tests/README.md +++ b/tests/InputBox.Tests/README.md @@ -22,7 +22,7 @@ | `GamepadDeadzoneHysteresisTests` | `GamepadDeadzoneHysteresis.ResolveDirection`(int / float 多載),含正負方向對稱性守門(硬體平等原則) | 14 | | `GamepadControllerFactoryTests` | 控制器後端建立策略,驗證 XInput 預設路徑、GameInput 成功路徑,以及 GameInput 執行階段不可用時退避至 XInput | 3 | | `GamepadControllerPauseTests` | 控制器在 `Pause()` / `Resume()`、連線可用性語意、GameInput 讀取缺失斷線重列舉、裝置狀態過濾、震動停止安全性、`ClearAllEvents` 肩鍵釋放訂閱清除與原生對話框切換時的殘留輸入回歸保護 | 10 | -| `GameInputDirectUsageTests` | `GameInputGamepadController` 直接使用 `InputWeave.GameInput` 遊戲控制器介面的守門、官方 v3 按鍵位元、快照邊緣偵測、穩定裝置識別與震動參數保留 | 7 | +| `GameInputDirectUsageTests` | `GameInputGamepadController` 直接使用 `InputWeave.GameInput` 遊戲控制器介面的守門、callback function pointer marshaling、官方 v3 按鍵位元、快照邊緣偵測、穩定裝置識別與震動參數保留 | 8 | | `GamepadCalibrationVisualizerMapperTests` | `GamepadCalibrationVisualizerMapper` 對校準視覺化座標限制、死區半徑換算、D-Pad 導覽防誤觸,以及雙搖桿狀態/控制器連線文案格式化的回歸保護 | 14 | | `GamepadEventBinderTests` | `GamepadEventBinder` 的 LB / RB / LT / RT 與肩鍵放開事件綁定回歸保護 | 1 | | `GamepadFaceButtonProfileTests` | `GamepadFaceButtonProfile` 的 Auto 解析、手動覆寫優先權、GameInput 裝置識別保留 VID/PID 時的 Sony/Nintendo 判斷,以及 Xbox / PlayStation / Nintendo 模式的按鍵標示、助記詞同步、資源化字串、主畫面說明文字、目前生效配置顯示、標題列提示、選單勾選邏輯與 PlayStation ○/× 確認模式回歸保護 | 25 | @@ -45,7 +45,7 @@ | `TaskExtensionsTests` | `TaskExtensions` CTS 擴充方法與生命週期連結保護 | 12 | | `VibrationPatternsTests` | `VibrationPatterns` 與方向性震動設定、語意情境解析、能力感知的多段式微震動序列,以及歷程滾輪阻尼感、字數上限硬牆、震動強度預覽、右搖桿選取粒度、組合鍵進入提示與喚起握手回饋的回歸保護 | 37 | | `VibrationSafetyLimiterTests` | `VibrationSafetyLimiter` 熱保護、Duty Cycle 限制器與極端邊界保護 | 8 | -| **合計** | | **383** | +| **合計** | | **384** | ## 二、執行方式 🚀 @@ -121,7 +121,7 @@ xUnit v3 為每個 `[Fact]` 建立獨立的測試類別實例,`IDisposable.Dis - Microsoft.Testing.Extensions.CodeCoverage:原始碼儲存庫為 [microsoft/codecoverage](https://github.com/microsoft/codecoverage),由 [Microsoft](https://github.com/microsoft) 及其 [貢獻者](https://github.com/microsoft/codecoverage/graphs/contributors) 開發並採用 [MIT License](https://github.com/microsoft/codecoverage/blob/main/LICENSE) 授權,用於測試覆蓋率收集。 - FlaUI.Core:原始碼儲存庫為 [FlaUI/FlaUI](https://github.com/FlaUI/FlaUI),由 [Roman Baeriswyl](https://github.com/Roemer) 及其 [貢獻者](https://github.com/FlaUI/FlaUI/graphs/contributors) 開發並採用 [MIT License](https://github.com/FlaUI/FlaUI/blob/main/LICENSE.txt) 授權,作為 Windows UI 自動化核心函式庫。 - FlaUI.UIA3:原始碼儲存庫為 [FlaUI/FlaUI](https://github.com/FlaUI/FlaUI),由 [Roman Baeriswyl](https://github.com/Roemer) 及其 [貢獻者](https://github.com/FlaUI/FlaUI/graphs/contributors) 開發並採用 [MIT License](https://github.com/FlaUI/FlaUI/blob/main/LICENSE.txt) 授權,作為 UIA3 後端,用於 WinForms UI 冒煙測試。 -- InputWeave.GameInput 0.0.1:原始碼儲存庫固定於 [rubujo/InputWeave.GameInput 封裝來源](https://github.com/rubujo/InputWeave.GameInput/tree/664a9d3e96458a49688ff2255a36f6e073977065),由 [rubujo](https://github.com/rubujo) 及其 [貢獻者](https://github.com/rubujo/InputWeave.GameInput/graphs/contributors) 開發並採用 [CC0 1.0 Universal](https://github.com/rubujo/InputWeave.GameInput/blob/664a9d3e96458a49688ff2255a36f6e073977065/LICENSE) 授權,作為 GameInput 直接使用與震動型別守門測試依賴;套件固定於 [../../eng/nuget/InputWeave.GameInput.0.0.1.nupkg](../../eng/nuget/InputWeave.GameInput.0.0.1.nupkg),SHA256 為 `64d9ef502853130d4af8df7cc1c2777a67808ef668e41c22fc6b526b83ed2805`。 +- InputWeave.GameInput 0.0.1:原始碼儲存庫固定於 [rubujo/InputWeave.GameInput 封裝來源](https://github.com/rubujo/InputWeave.GameInput/tree/72697db594b8f1863bd3fbf5db75ff69b40e3364),由 [rubujo](https://github.com/rubujo) 及其 [貢獻者](https://github.com/rubujo/InputWeave.GameInput/graphs/contributors) 開發並採用 [CC0 1.0 Universal](https://github.com/rubujo/InputWeave.GameInput/blob/72697db594b8f1863bd3fbf5db75ff69b40e3364/LICENSE) 授權,作為 GameInput 直接使用與震動型別守門測試依賴;套件固定於 [../../eng/nuget/InputWeave.GameInput.0.0.1.nupkg](../../eng/nuget/InputWeave.GameInput.0.0.1.nupkg),SHA256 為 `451b9d65143eafea130ec3492f12a991b29c62d53509e74b856894848f329f5e`。 本測試專案的相關說明詳見本文件;主專案授權與完整聲明仍以 [../../README.md](../../README.md) 及 [../../LICENSE](../../LICENSE) 為準。