Compare commits
2 Commits
fa4f80ebdf
...
Canary-1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3541e282ea | ||
|
|
1ce37ec317 |
@@ -2,14 +2,24 @@
|
||||
{
|
||||
public class LedConfigController
|
||||
{
|
||||
/// <summary>
|
||||
/// Packed RGB int of the color
|
||||
/// </summary>
|
||||
public uint LedColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enable LED color changing by the emulator
|
||||
/// </summary>
|
||||
public bool EnableLed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the color and disables the LED entirely.
|
||||
/// </summary>
|
||||
public bool TurnOffLed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the color and uses the rainbow color functionality for the LED.
|
||||
/// </summary>
|
||||
public bool UseRainbow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Packed RGB int of the color
|
||||
/// </summary>
|
||||
public uint LedColor { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
88
src/Ryujinx.Common/Utilities/Rainbow.cs
Normal file
88
src/Ryujinx.Common/Utilities/Rainbow.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Ryujinx.Common.Utilities
|
||||
{
|
||||
public class Rainbow
|
||||
{
|
||||
public static float Speed { get; set; } = 1;
|
||||
|
||||
public static Color Color { get; private set; } = Color.Blue;
|
||||
|
||||
private static float _lastHue;
|
||||
|
||||
public static void Tick()
|
||||
{
|
||||
float currentHue = Color.GetHue();
|
||||
float nextHue = currentHue;
|
||||
|
||||
if (currentHue >= 360)
|
||||
nextHue = 0;
|
||||
else
|
||||
nextHue += Speed;
|
||||
|
||||
Color = HsbToRgb(
|
||||
nextHue / 360,
|
||||
1,
|
||||
1
|
||||
);
|
||||
|
||||
_lastHue = currentHue;
|
||||
|
||||
RainbowColorUpdated?.Invoke(Color.ToArgb());
|
||||
}
|
||||
|
||||
public static event Action<int> RainbowColorUpdated;
|
||||
|
||||
private static Color HsbToRgb(float hue, float saturation, float brightness)
|
||||
{
|
||||
int r = 0, g = 0, b = 0;
|
||||
if (saturation == 0)
|
||||
{
|
||||
r = g = b = (int)(brightness * 255.0f + 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
float h = (hue - (float)Math.Floor(hue)) * 6.0f;
|
||||
float f = h - (float)Math.Floor(h);
|
||||
float p = brightness * (1.0f - saturation);
|
||||
float q = brightness * (1.0f - saturation * f);
|
||||
float t = brightness * (1.0f - (saturation * (1.0f - f)));
|
||||
switch ((int)h)
|
||||
{
|
||||
case 0:
|
||||
r = (int)(brightness * 255.0f + 0.5f);
|
||||
g = (int)(t * 255.0f + 0.5f);
|
||||
b = (int)(p * 255.0f + 0.5f);
|
||||
break;
|
||||
case 1:
|
||||
r = (int)(q * 255.0f + 0.5f);
|
||||
g = (int)(brightness * 255.0f + 0.5f);
|
||||
b = (int)(p * 255.0f + 0.5f);
|
||||
break;
|
||||
case 2:
|
||||
r = (int)(p * 255.0f + 0.5f);
|
||||
g = (int)(brightness * 255.0f + 0.5f);
|
||||
b = (int)(t * 255.0f + 0.5f);
|
||||
break;
|
||||
case 3:
|
||||
r = (int)(p * 255.0f + 0.5f);
|
||||
g = (int)(q * 255.0f + 0.5f);
|
||||
b = (int)(brightness * 255.0f + 0.5f);
|
||||
break;
|
||||
case 4:
|
||||
r = (int)(t * 255.0f + 0.5f);
|
||||
g = (int)(p * 255.0f + 0.5f);
|
||||
b = (int)(brightness * 255.0f + 0.5f);
|
||||
break;
|
||||
case 5:
|
||||
r = (int)(brightness * 255.0f + 0.5f);
|
||||
g = (int)(p * 255.0f + 0.5f);
|
||||
b = (int)(q * 255.0f + 0.5f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.HOS.Services.Hid;
|
||||
using SDL2;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -86,7 +88,7 @@ namespace Ryujinx.Input.SDL2
|
||||
Id = driverId;
|
||||
Features = GetFeaturesFlag();
|
||||
_triggerThreshold = 0.0f;
|
||||
|
||||
|
||||
// Enable motion tracking
|
||||
if (Features.HasFlag(GamepadFeaturesFlag.Motion))
|
||||
{
|
||||
@@ -102,6 +104,18 @@ namespace Ryujinx.Input.SDL2
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLed(uint packedRgb)
|
||||
{
|
||||
if (!Features.HasFlag(GamepadFeaturesFlag.Led)) return;
|
||||
|
||||
byte red = packedRgb > 0 ? (byte)(packedRgb >> 16) : (byte)0;
|
||||
byte green = packedRgb > 0 ? (byte)(packedRgb >> 8) : (byte)0;
|
||||
byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0;
|
||||
|
||||
if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0)
|
||||
Logger.Error?.Print(LogClass.Hid, "LED is not supported on this game controller.");
|
||||
}
|
||||
|
||||
private GamepadFeaturesFlag GetFeaturesFlag()
|
||||
{
|
||||
GamepadFeaturesFlag result = GamepadFeaturesFlag.None;
|
||||
@@ -112,9 +126,7 @@ namespace Ryujinx.Input.SDL2
|
||||
result |= GamepadFeaturesFlag.Motion;
|
||||
}
|
||||
|
||||
int error = SDL_GameControllerRumble(_gamepadHandle, 0, 0, 100);
|
||||
|
||||
if (error == 0)
|
||||
if (SDL_GameControllerHasRumble(_gamepadHandle) == SDL_bool.SDL_TRUE)
|
||||
{
|
||||
result |= GamepadFeaturesFlag.Rumble;
|
||||
}
|
||||
@@ -214,12 +226,32 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY;
|
||||
|
||||
private void RainbowColorChanged(int packedRgb)
|
||||
{
|
||||
if (!_configuration.Led.UseRainbow) return;
|
||||
|
||||
SetLed((uint)packedRgb);
|
||||
}
|
||||
|
||||
public void SetConfiguration(InputConfig configuration)
|
||||
{
|
||||
lock (_userMappingLock)
|
||||
{
|
||||
_configuration = (StandardControllerInputConfig)configuration;
|
||||
|
||||
if (Features.HasFlag(GamepadFeaturesFlag.Led) && _configuration.Led.EnableLed)
|
||||
{
|
||||
if (_configuration.Led.TurnOffLed)
|
||||
(this as IGamepad).ClearLed();
|
||||
else if (_configuration.Led.UseRainbow)
|
||||
Rainbow.RainbowColorUpdated += RainbowColorChanged;
|
||||
else
|
||||
SetLed(_configuration.Led.LedColor);
|
||||
|
||||
if (!_configuration.Led.UseRainbow)
|
||||
Rainbow.RainbowColorUpdated -= RainbowColorChanged;
|
||||
}
|
||||
|
||||
_buttonsUserMapping.Clear();
|
||||
|
||||
// First update sticks
|
||||
|
||||
@@ -173,5 +173,16 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
return new SDL2Gamepad(gamepadHandle, id);
|
||||
}
|
||||
|
||||
public IEnumerable<IGamepad> GetGamepads()
|
||||
{
|
||||
lock (_gamepadsIds)
|
||||
{
|
||||
foreach (string gamepadId in _gamepadsIds)
|
||||
{
|
||||
yield return GetGamepad(gamepadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
@@ -385,6 +386,11 @@ namespace Ryujinx.Input.SDL2
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLed(uint packedRgb)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.UI, "SetLed called on an SDL2Keyboard");
|
||||
}
|
||||
|
||||
public void SetTriggerThreshold(float triggerThreshold)
|
||||
{
|
||||
// No operations
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
@@ -76,6 +77,11 @@ namespace Ryujinx.Input.SDL2
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetLed(uint packedRgb)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.UI, "SetLed called on an SDL2Mouse");
|
||||
}
|
||||
|
||||
public void SetTriggerThreshold(float triggerThreshold)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
@@ -164,6 +165,8 @@ namespace Ryujinx.Input.SDL2
|
||||
return new SDL2Mouse(this);
|
||||
}
|
||||
|
||||
public IEnumerable<IGamepad> GetGamepads() => [GetGamepad("0")];
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_isDisposed)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
@@ -51,5 +52,13 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
return new SDL2Keyboard(this, _keyboardIdentifers[0], "All keyboards");
|
||||
}
|
||||
|
||||
public IEnumerable<IGamepad> GetGamepads()
|
||||
{
|
||||
foreach (var keyboardId in _keyboardIdentifers)
|
||||
{
|
||||
yield return GetGamepad(keyboardId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,15 @@ namespace Ryujinx.Input
|
||||
/// <param name="configuration">The configuration of the gamepad</param>
|
||||
void SetConfiguration(InputConfig configuration);
|
||||
|
||||
/// <summary>
|
||||
/// Set the LED on the gamepad to a given color.
|
||||
/// </summary>
|
||||
/// <remarks>Does nothing on a controller without LED functionality.</remarks>
|
||||
/// <param name="packedRgb">The packed RGB integer.</param>
|
||||
void SetLed(uint packedRgb);
|
||||
|
||||
public void ClearLed() => SetLed(0);
|
||||
|
||||
/// <summary>
|
||||
/// Starts a rumble effect on the gamepad.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Input
|
||||
{
|
||||
@@ -33,6 +34,11 @@ namespace Ryujinx.Input
|
||||
/// <param name="id">The unique id of the gamepad</param>
|
||||
/// <returns>An instance of <see cref="IGamepad"/> associated to the gamepad id given or null if not found</returns>
|
||||
IGamepad GetGamepad(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an <see cref="IEnumerable{T}"/> of the connected gamepads.
|
||||
/// </summary>
|
||||
IEnumerable<IGamepad> GetGamepads();
|
||||
|
||||
/// <summary>
|
||||
/// Clear the internal state of the driver.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -167,6 +168,8 @@ namespace Ryujinx.SDL2.Common
|
||||
HandleSDLEvent(ref evnt);
|
||||
}
|
||||
});
|
||||
|
||||
Rainbow.Tick();
|
||||
|
||||
waitHandle.Wait(WaitTimeMs);
|
||||
}
|
||||
|
||||
@@ -587,6 +587,11 @@ namespace Ryujinx.Ava
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
|
||||
{
|
||||
gamepad?.ClearLed();
|
||||
}
|
||||
|
||||
_isStopped = true;
|
||||
Stop();
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@
|
||||
"th_TH": "โหลด DLC จากโฟลเดอร์",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Завантажити DLC з теки",
|
||||
"zh_CN": "从文件夹加载 DLC",
|
||||
"zh_CN": "从文件夹加载DLC",
|
||||
"zh_TW": "從資料夾中載入 DLC"
|
||||
}
|
||||
},
|
||||
@@ -768,7 +768,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Сканувати Amiibo (з теки Bin)",
|
||||
"zh_CN": "扫描 Amiibo (从 bin 文件)",
|
||||
"zh_CN": "从bin文件扫描 Amiibo",
|
||||
"zh_TW": "掃瞄 Amiibo (從 Bin 檔案)"
|
||||
}
|
||||
},
|
||||
@@ -818,7 +818,7 @@
|
||||
"th_TH": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP",
|
||||
"tr_TR": "XCI veya ZIP'ten Yazılım Yükle",
|
||||
"uk_UA": "Встановити прошивку з XCI або ZIP",
|
||||
"zh_CN": "从 XCI 或 ZIP 文件安装系统固件",
|
||||
"zh_CN": "从 XCI 或 ZIP 文件中安装系统固件",
|
||||
"zh_TW": "從 XCI 或 ZIP 安裝韌體"
|
||||
}
|
||||
},
|
||||
@@ -843,7 +843,7 @@
|
||||
"th_TH": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี",
|
||||
"tr_TR": "Bir Dizin Üzerinden Yazılım Yükle",
|
||||
"uk_UA": "Встановити прошивку з теки",
|
||||
"zh_CN": "从文件夹安装系统固件",
|
||||
"zh_CN": "从文件夹中安装系统固件",
|
||||
"zh_TW": "從資料夾安裝韌體"
|
||||
}
|
||||
},
|
||||
@@ -893,7 +893,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Встановити ключі з файлу .KEYS або .ZIP",
|
||||
"zh_CN": "从 .KEYS 文件或 .ZIP 压缩包安装密匙",
|
||||
"zh_CN": "从.KEYS文件或ZIP压缩包安装密匙",
|
||||
"zh_TW": "從 .KEYS 或 .ZIP 安裝金鑰"
|
||||
}
|
||||
},
|
||||
@@ -1018,7 +1018,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Обрізати XCI файли",
|
||||
"zh_CN": "瘦身 XCI 文件",
|
||||
"zh_CN": "XCI文件瘦身",
|
||||
"zh_TW": "修剪 XCI 檔案"
|
||||
}
|
||||
},
|
||||
@@ -1293,7 +1293,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Відкриває сторінку з Посібником по усуненню помилок та несправностей на офіційній вікі-сторінці Ryujinx (англійською)",
|
||||
"zh_CN": "打开 Ryujinx 官方 Wiki 的常见问题和问题排除页面",
|
||||
"zh_CN": "打开Ryujinx官方wiki的常见问题和问题排除页面",
|
||||
"zh_TW": "開啟官方 Ryujinx Wiki 常見問題 (FAQ) 和疑難排解頁面"
|
||||
}
|
||||
},
|
||||
@@ -1343,7 +1343,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Відкриває посібник з Налаштування та конфігурації на офіційній вікі-сторінці Ryujinx (англійською)",
|
||||
"zh_CN": "打开 Ryujinx 官方 Wiki 的安装与配置指南",
|
||||
"zh_CN": "打开Ryujinx官方wiki的安装与配置指南",
|
||||
"zh_TW": "開啟官方 Ryujinx Wiki 設定和配置指南"
|
||||
}
|
||||
},
|
||||
@@ -1393,7 +1393,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Відкриває посібник з налаштування Мультиплеєру на офіційній вікі-сторінці Ryujinx (англійською)",
|
||||
"zh_CN": "打开 Ryujinx 官方 Wiki 的多人游戏指南",
|
||||
"zh_CN": "打开Ryujinx官方wiki的多人游戏指南",
|
||||
"zh_TW": "開啟官方 Ryujinx Wiki 多人遊戲 (LDN/LAN) 指南"
|
||||
}
|
||||
},
|
||||
@@ -1443,7 +1443,7 @@
|
||||
"th_TH": "กำลังค้นหา...",
|
||||
"tr_TR": "Ara...",
|
||||
"uk_UA": "Пошук...",
|
||||
"zh_CN": "搜索...",
|
||||
"zh_CN": "搜索…",
|
||||
"zh_TW": "搜尋..."
|
||||
}
|
||||
},
|
||||
@@ -2593,7 +2593,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Перевірка та нарізка XCI Файлу",
|
||||
"zh_CN": "检查并瘦身 XCI 文件",
|
||||
"zh_CN": "检查并瘦身XCI文件",
|
||||
"zh_TW": "檢查及修剪 XCI 檔案"
|
||||
}
|
||||
},
|
||||
@@ -2618,7 +2618,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Перевірити та обрізати XCI Файл задля збереження місця на диску",
|
||||
"zh_CN": "检查并瘦身 XCI 文件以节约磁盘空间",
|
||||
"zh_CN": "检查并瘦身XCI文件以节约磁盘空间",
|
||||
"zh_TW": "檢查及修剪 XCI 檔案以節省儲存空間"
|
||||
}
|
||||
},
|
||||
@@ -2693,7 +2693,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Обрізається XCI Файлів '{0}'",
|
||||
"zh_CN": "正在瘦身 XCI 文件 '{0}'",
|
||||
"zh_CN": "XCI文件瘦身中'{0}'",
|
||||
"zh_TW": "正在修剪 XCI 檔案 '{0}'"
|
||||
}
|
||||
},
|
||||
@@ -3218,7 +3218,7 @@
|
||||
"th_TH": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Автозавантаження теки DLC/Оновлень",
|
||||
"zh_CN": "自动加载 DLC 及 游戏更新 的目录",
|
||||
"zh_CN": "自动加载DLC/游戏更新目录",
|
||||
"zh_TW": "自動載入 DLC/遊戲更新資料夾"
|
||||
}
|
||||
},
|
||||
@@ -3243,7 +3243,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "DLC та Оновлення, які посилаються на відсутні файли, будуть автоматично вимкнуті.",
|
||||
"zh_CN": "DLC 及 游戏更新 可自动加载和卸载",
|
||||
"zh_CN": "DLC/游戏更新可自动加载和卸载",
|
||||
"zh_TW": "遺失的 DLC 及遊戲更新檔案將會在自動載入中移除"
|
||||
}
|
||||
},
|
||||
@@ -7628,7 +7628,57 @@
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Custom LED",
|
||||
"en_US": "LED",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "ControllerSettingsLedColorDisable",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Disable",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "ControllerSettingsLedColorRainbow",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Rainbow",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
@@ -11293,7 +11343,7 @@
|
||||
"th_TH": "ไม่มีข้อมูลบันทึกไว้สำหรับ {0} [{1:x16}]",
|
||||
"tr_TR": "{0} [{1:x16}] için kayıt verisi bulunamadı",
|
||||
"uk_UA": "Немає збережених даних для {0} [{1:x16}]",
|
||||
"zh_CN": "没有 {0} [{1:x16}] 的游戏存档",
|
||||
"zh_CN": "没有{0} [{1:x16}]的游戏存档",
|
||||
"zh_TW": "沒有 {0} [{1:x16}] 的存檔"
|
||||
}
|
||||
},
|
||||
@@ -12443,7 +12493,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Вікно XCI Тримера",
|
||||
"zh_CN": "XCI 文件瘦身窗口",
|
||||
"zh_CN": "XCI文件瘦身窗口",
|
||||
"zh_TW": "XCI 修剪器視窗"
|
||||
}
|
||||
},
|
||||
@@ -13168,7 +13218,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "在 {0} 发现了一个无效的密匙文件",
|
||||
"zh_CN": "在{0}发现了一个无效的密匙文件",
|
||||
"zh_TW": "找到無效的金鑰檔案 {0}"
|
||||
}
|
||||
},
|
||||
@@ -14518,7 +14568,7 @@
|
||||
"th_TH": "แฮ็ค: สุ่มแท็ก Uuid",
|
||||
"tr_TR": "Hack: Rastgele bir Uuid kullan",
|
||||
"uk_UA": "Хитрість: Використовувати випадковий тег Uuid",
|
||||
"zh_CN": "修改:使用随机生成的 Amiibo ID",
|
||||
"zh_CN": "修改:使用随机生成的Amiibo ID",
|
||||
"zh_TW": "補釘修正:使用隨機標記的 Uuid"
|
||||
}
|
||||
},
|
||||
@@ -15468,7 +15518,7 @@
|
||||
"th_TH": "โหลด PPTC โดยใช้หนึ่งในสามของจำนวนคอร์",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Завантажувати PPTC використовуючи третину від кількості ядер.",
|
||||
"zh_CN": "使用三分之一的核心数加载 PPTC.",
|
||||
"zh_CN": "使用三分之一的核心数加载PPTC.",
|
||||
"zh_TW": "使用 CPU 核心數量的三分之一載入 PPTC。"
|
||||
}
|
||||
},
|
||||
@@ -16293,7 +16343,7 @@
|
||||
"th_TH": "เปิดตัวสำรวจไฟล์เพื่อเลือกหนึ่งโฟลเดอร์ขึ้นไปเพื่อโหลด DLC จำนวนมาก",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Відкриває Файловий провідник для обрання однієї або декількох тек для масового завантаження DLC",
|
||||
"zh_CN": "打开文件资源管理器以选择一个或多个文件夹来批量加载 DLC。",
|
||||
"zh_CN": "打开文件资源管理器以选择一个或多个文件夹来批量加载DLC。",
|
||||
"zh_TW": "開啟檔案總管,選擇一個或多個資料夾來大量載入 DLC"
|
||||
}
|
||||
},
|
||||
@@ -19118,7 +19168,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Перевірити та Обрізати XCI файл",
|
||||
"zh_CN": "检查并瘦身 XCI 文件",
|
||||
"zh_CN": "检查并瘦身XCI文件",
|
||||
"zh_TW": "檢查及修剪 XCI 檔案"
|
||||
}
|
||||
},
|
||||
@@ -19143,7 +19193,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Ця функція спочатку перевірить наявність порожнього місця, після чого обріже файл XCI для економії місця на диску.",
|
||||
"zh_CN": "这个功能将会先检查 XCI 文件,再对其执行瘦身操作以节约磁盘空间。",
|
||||
"zh_CN": "这个功能将会先检查XCI文件,再对其执行瘦身操作以节约磁盘空间。",
|
||||
"zh_TW": "此功能首先檢查 XCI 檔案是否有可修剪的字元,然後修剪檔案以節省儲存空間。"
|
||||
}
|
||||
},
|
||||
@@ -19193,7 +19243,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "XCI файл не потребує обрізання. Перевірте журнали (logs) для отримання додаткової інформації",
|
||||
"zh_CN": "XCI 文件不需要被瘦身。查看日志以获得更多细节。",
|
||||
"zh_CN": "XCI文件不需要被瘦身。查看日志以获得更多细节。",
|
||||
"zh_TW": "XCI 檔案不需要修剪。檢查日誌以取得更多資訊"
|
||||
}
|
||||
},
|
||||
@@ -19218,7 +19268,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "XCI файл не може бути обрізаний. Перевірте журнали (logs) для отримання додаткової інформації",
|
||||
"zh_CN": "XCI 文件不能被瘦身。查看日志以获得更多细节。",
|
||||
"zh_CN": "XCI文件不能被瘦身。查看日志以获得更多细节。",
|
||||
"zh_TW": "XCI 檔案不能被修剪。檢查日誌以取得更多資訊"
|
||||
}
|
||||
},
|
||||
@@ -19243,7 +19293,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "XCI файл Тільки для Читання і не може бути прочитаним. Перевірте журнали (logs) для отримання додаткової інформації",
|
||||
"zh_CN": "XCI 文件是只读的,且不可以被标记为可读取的。查看日志以获得更多细节。",
|
||||
"zh_CN": "XCI文件是只读的,且不可以被标记为可读取的。查看日志以获得更多细节。",
|
||||
"zh_TW": "XCI 檔案是唯讀,並且無法改成可寫入。檢查日誌以取得更多資訊"
|
||||
}
|
||||
},
|
||||
@@ -19268,7 +19318,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Розмір файлу XCI змінився з моменту сканування. Перевірте, чи не записується файл, та спробуйте знову",
|
||||
"zh_CN": "XCI 文件在扫描后大小发生了变化。请检查文件是否未被写入,然后重试。",
|
||||
"zh_CN": "XCI文件在扫描后大小发生了变化。请检查文件是否未被写入,然后重试。",
|
||||
"zh_TW": "XCI 檔案大小比較上次的掃瞄已經改變。請檢查檔案是否未被寫入,然後再嘗試。"
|
||||
}
|
||||
},
|
||||
@@ -19293,7 +19343,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Файл XCI містить дані в зоні вільного простору, тому обрізка небезпечна",
|
||||
"zh_CN": "XCI 文件的空闲区域内有数据,不能安全瘦身。",
|
||||
"zh_CN": "XCI文件的空闲区域内有数据,不能安全瘦身。",
|
||||
"zh_TW": "XCI 檔案有數據儲存於可節省儲存空間的區域,所以試圖修剪並不安全"
|
||||
}
|
||||
},
|
||||
@@ -19318,7 +19368,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "XCI Файл містить недійсні дані. Перевірте журнали (logs) для отримання додаткової інформації",
|
||||
"zh_CN": "XCI 文件含有无效数据。查看日志以获得更多细节。",
|
||||
"zh_CN": "XCI文件含有无效数据。查看日志以获得更多细节。",
|
||||
"zh_TW": "XCI 檔案帶有無效的數據。檢查日誌以取得更多資訊"
|
||||
}
|
||||
},
|
||||
@@ -19343,7 +19393,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "XCI Файл файл не вдалося відкрити для запису. Перевірте журнали для додаткової інформації",
|
||||
"zh_CN": "XCI 文件不能被读写。查看日志以获得更多细节。",
|
||||
"zh_CN": "XCI文件不能被读写。查看日志以获得更多细节。",
|
||||
"zh_TW": "XCI 檔案不能被寫入。檢查日誌以取得更多資訊"
|
||||
}
|
||||
},
|
||||
@@ -19368,7 +19418,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Не вдалося обрізати файл XCI",
|
||||
"zh_CN": "XCI 文件瘦身失败",
|
||||
"zh_CN": "XCI文件瘦身失败",
|
||||
"zh_TW": "修剪 XCI 檔案失敗"
|
||||
}
|
||||
},
|
||||
@@ -19568,7 +19618,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Обрізка XCI Файлів",
|
||||
"zh_CN": "XCI 文件瘦身器",
|
||||
"zh_CN": "XCI文件瘦身器",
|
||||
"zh_TW": "XCI 檔案修剪器"
|
||||
}
|
||||
},
|
||||
@@ -20043,7 +20093,7 @@
|
||||
"th_TH": "แพ็ค DLC ไม่สามารถลบทิ้งได้ สามารถปิดใช้งานได้เท่านั้น",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Комплектні DLC (бандли) не можуть бути видаленими, лише вимкненими.",
|
||||
"zh_CN": "游戏整合的 DLC 无法移除,可尝试禁用。",
|
||||
"zh_CN": "游戏整合的DLC无法移除,可尝试禁用。",
|
||||
"zh_TW": "附帶的 DLC 只能被停用而無法被刪除。"
|
||||
}
|
||||
},
|
||||
@@ -20093,7 +20143,7 @@
|
||||
"th_TH": "{0} DLC ใหม่ที่เพิ่มเข้ามา",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "{0} нового завантажувального вмісту додано",
|
||||
"zh_CN": "{0} 个 DLC 被添加",
|
||||
"zh_CN": "{0} 个DLC被添加",
|
||||
"zh_TW": "已加入 {0} 個 DLC"
|
||||
}
|
||||
},
|
||||
@@ -20118,7 +20168,7 @@
|
||||
"th_TH": "{0} ใหม่ที่เพิ่มเข้ามา",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "{0} нового завантажувального вмісту додано",
|
||||
"zh_CN": "{0} 个 DLC 被添加",
|
||||
"zh_CN": "{0} 个DLC被添加",
|
||||
"zh_TW": "已加入 {0} 個 DLC"
|
||||
}
|
||||
},
|
||||
@@ -20143,7 +20193,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "{0} відсутнього завантажувального вмісту видалено",
|
||||
"zh_CN": "{0} 个失效的 DLC 已移除",
|
||||
"zh_CN": "{0} 个失效的DLC已移除",
|
||||
"zh_TW": "已刪除 {0} 個遺失的 DLC"
|
||||
}
|
||||
},
|
||||
@@ -20668,7 +20718,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "使用 Vulkan。\n在 ARM Mac 上,当玩在其下运行良好的游戏时,使用 Metal 后端。",
|
||||
"zh_CN": "使用Vulkan。\n在ARM Mac上,当玩在其下运行良好的游戏时,使用Metal后端。",
|
||||
"zh_TW": "使用Vulkan。\n在 ARM Mac 上,如果遊戲執行性能良好時,則將使用 Metal 後端。"
|
||||
}
|
||||
},
|
||||
@@ -22068,7 +22118,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Вимкнути хостинг P2P мережі (може збільшити затримку)",
|
||||
"zh_CN": "禁用 P2P 网络连接 (也许会增加延迟)",
|
||||
"zh_CN": "禁用P2P网络连接 (也许会增加延迟)",
|
||||
"zh_TW": "停用對等網路代管 (P2P Network Hosting) (可能增加網路延遲)"
|
||||
}
|
||||
},
|
||||
@@ -22093,7 +22143,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Вимкнути хостинг P2P мережі, піри будуть підключатися через майстер-сервер замість прямого з'єднання з вами.",
|
||||
"zh_CN": "禁用 P2P 网络连接,对方将通过主服务器进行连接,而不是直接连接到您。",
|
||||
"zh_CN": "禁用P2P网络连接,对方将通过主服务器进行连接,而不是直接连接到您。",
|
||||
"zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理何服器而非直接連線至你的主機。"
|
||||
}
|
||||
},
|
||||
@@ -22168,7 +22218,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Введіть пароль у форматі Ryujinx-<8 символів>. Ви зможете бачити лише ті ігри, які мають такий самий пароль, як і у вас.",
|
||||
"zh_CN": "以 Ryujinx-<8个十六进制字符> 的格式输入密码。您只能看到与您使用相同密码的游戏房间。",
|
||||
"zh_CN": "以Ryujinx-<8个十六进制字符>的格式输入密码。您只能看到与您使用相同密码的游戏房间。",
|
||||
"zh_TW": "以「Ryujinx-<8 個十六進制數字>」的格式輸入密碼片語 (passphrase)。你只會看到與你的密碼片語 (passphrase) 相同的遊戲房間。"
|
||||
}
|
||||
},
|
||||
@@ -22468,7 +22518,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Емульована вертикальна синхронізація кадрів. 'Switch' емулює частоту оновлення консолі Nintendo Switch (60 Гц). 'Необмежена' — частота оновлення не матиме обмежень.",
|
||||
"zh_CN": "模拟垂直同步。“Switch”模拟了 Switch 的 60Hz 刷新率。“无限制”没有刷新率限制。",
|
||||
"zh_CN": "模拟垂直同步。“Switch”模拟了Switch的60Hz刷新率。“无限制”没有刷新率限制。",
|
||||
"zh_TW": "模擬垂直同步。「Switch」 模擬 Nintendo Switch 的 60Hz 重新整理頻率。「沒有限制」是沒有限制的重新整理頻率。"
|
||||
}
|
||||
},
|
||||
@@ -22493,7 +22543,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Емульована вертикальна синхронізація кадрів. 'Switch' емулює частоту оновлення консолі Nintendo Switch (60 Гц). 'Необмежена' — частота оновлення не матиме обмежень. 'Користувацька' емулює вказану користувацьку частоту оновлення.",
|
||||
"zh_CN": "模拟垂直同步。“Switch”模拟了 Switch 的 60Hz 刷新率。“无限制”没有刷新率限制。“自定义刷新率”模拟指定的自定义刷新率。",
|
||||
"zh_CN": "模拟垂直同步。“Switch”模拟了Switch的60Hz刷新率。“无限制”没有刷新率限制。“自定义刷新率”模拟指定的自定义刷新率。",
|
||||
"zh_TW": "模擬垂直同步。「Switch」 模擬 Nintendo Switch 的 60Hz 重新整理頻率。「沒有限制」是沒有限制的重新整理頻率。「自訂的重新整理頻率」模擬所自訂的重新整理頻率。"
|
||||
}
|
||||
},
|
||||
@@ -22518,7 +22568,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Дозволяє користувачу вказати емульовану частоту оновлення. У деяких іграх це може прискорити або сповільнити логіку гри. Натомість в інших іграх ця функція може дозволити обмежити FPS на певні кратні частоти оновлення або призвести до непередбачуваної поведінки. Це експериментальна функція, без гарантій того, як вона вплине на ігровий процес. \n\nЗалиште ВИМКНЕНИМ, якщо не впевнені.",
|
||||
"zh_CN": "允许用户指定模拟刷新率。在某些游戏中,这可能会加快或减慢游戏逻辑的速度。在其他游戏中,它可能允许将 FPS 限制在刷新率的某个倍数,或者导致不可预测的行为。这是一个实验性功能,无法保证游戏会受到怎样的影响。\n\n如果不确定,请关闭。",
|
||||
"zh_CN": "允许用户指定模拟刷新率。在某些游戏中,这可能会加快或减慢游戏逻辑的速度。在其他游戏中,它可能允许将FPS限制在刷新率的某个倍数,或者导致不可预测的行为。这是一个实验性功能,无法保证游戏会受到怎样的影响。\n\n如果不确定,请关闭。",
|
||||
"zh_TW": "容許使用者自訂模擬的重新整理頻率。你可能會在某些遊戲裡感受到加快或減慢的遊戲速度;其他遊戲裡則可能會容許限制最高的 FPS 至重新整理頻率的倍數,或引起未知遊戲行為。這是實驗性功能,且沒有保證遊戲會穩定執行。\n\n如果不確定,請保持關閉狀態。"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -143,6 +144,11 @@ namespace Ryujinx.Ava.Input
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLed(uint packedRgb)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.UI, "SetLed called on an AvaloniaKeyboard");
|
||||
}
|
||||
|
||||
public void SetTriggerThreshold(float triggerThreshold) { }
|
||||
|
||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs) { }
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace Ryujinx.Ava.Input
|
||||
return new AvaloniaKeyboard(this, _keyboardIdentifers[0], LocaleManager.Instance[LocaleKeys.AllKeyboards]);
|
||||
}
|
||||
|
||||
public IEnumerable<IGamepad> GetGamepads() => [GetGamepad("0")];
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
@@ -74,6 +75,11 @@ namespace Ryujinx.Ava.Input
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetLed(uint packedRgb)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.UI, "SetLed called on an AvaloniaMouse");
|
||||
}
|
||||
|
||||
public void SetTriggerThreshold(float triggerThreshold)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -3,6 +3,7 @@ using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using MouseButton = Ryujinx.Input.MouseButton;
|
||||
using Size = System.Drawing.Size;
|
||||
@@ -134,6 +135,8 @@ namespace Ryujinx.Ava.Input
|
||||
return new AvaloniaMouse(this);
|
||||
}
|
||||
|
||||
public IEnumerable<IGamepad> GetGamepads() => [GetGamepad("0")];
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_isDisposed)
|
||||
|
||||
@@ -388,30 +388,6 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableLedChanging;
|
||||
|
||||
public bool EnableLedChanging
|
||||
{
|
||||
get => _enableLedChanging;
|
||||
set
|
||||
{
|
||||
_enableLedChanging = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _ledColor;
|
||||
|
||||
public Color LedColor
|
||||
{
|
||||
get => _ledColor;
|
||||
set
|
||||
{
|
||||
_ledColor = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableMotion;
|
||||
public bool EnableMotion
|
||||
{
|
||||
@@ -433,6 +409,58 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableLedChanging;
|
||||
|
||||
public bool EnableLedChanging
|
||||
{
|
||||
get => _enableLedChanging;
|
||||
set
|
||||
{
|
||||
_enableLedChanging = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
private bool _turnOffLed;
|
||||
|
||||
public bool TurnOffLed
|
||||
{
|
||||
get => _turnOffLed;
|
||||
set
|
||||
{
|
||||
_turnOffLed = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
private bool _useRainbowLed;
|
||||
|
||||
public bool UseRainbowLed
|
||||
{
|
||||
get => _useRainbowLed;
|
||||
set
|
||||
{
|
||||
_useRainbowLed = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
private Color _ledColor;
|
||||
|
||||
public Color LedColor
|
||||
{
|
||||
get => _ledColor;
|
||||
set
|
||||
{
|
||||
_ledColor = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public GamepadInputConfig(InputConfig config)
|
||||
{
|
||||
@@ -512,6 +540,8 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
if (controllerInput.Led != null)
|
||||
{
|
||||
EnableLedChanging = controllerInput.Led.EnableLed;
|
||||
TurnOffLed = controllerInput.Led.TurnOffLed;
|
||||
UseRainbowLed = controllerInput.Led.UseRainbow;
|
||||
uint rawColor = controllerInput.Led.LedColor;
|
||||
byte alpha = (byte)(rawColor >> 24);
|
||||
byte red = (byte)(rawColor >> 16);
|
||||
@@ -579,6 +609,8 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
Led = new LedConfigController
|
||||
{
|
||||
EnableLed = EnableLedChanging,
|
||||
TurnOffLed = this.TurnOffLed,
|
||||
UseRainbow = UseRainbowLed,
|
||||
LedColor = LedColor.ToUInt32()
|
||||
},
|
||||
Version = InputConfig.CurrentVersion,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Avalonia.Svg.Skia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
|
||||
@@ -57,6 +60,16 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
await RumbleInputView.Show(this);
|
||||
}
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
{
|
||||
if (!Config.EnableLedChanging) return;
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32());
|
||||
});
|
||||
|
||||
public void OnParentModelChanged()
|
||||
{
|
||||
IsLeft = ParentModel.IsLeft;
|
||||
|
||||
@@ -3,6 +3,7 @@ using Avalonia.Controls;
|
||||
using Avalonia.Svg.Skia;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
@@ -54,7 +55,18 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
public IGamepadDriver AvaloniaKeyboardDriver { get; }
|
||||
public IGamepad SelectedGamepad { get; private set; }
|
||||
|
||||
private IGamepad _selectedGamepad;
|
||||
|
||||
public IGamepad SelectedGamepad
|
||||
{
|
||||
get => _selectedGamepad;
|
||||
private set
|
||||
{
|
||||
_selectedGamepad = value;
|
||||
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
|
||||
public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
|
||||
@@ -69,8 +81,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
public bool IsRight { get; set; }
|
||||
public bool IsLeft { get; set; }
|
||||
|
||||
public bool HasLed => false; //temporary
|
||||
//SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led);
|
||||
public bool HasLed => SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led);
|
||||
public bool CanClearLed => SelectedGamepad.Name.ContainsIgnoreCase("DualSense");
|
||||
|
||||
public bool IsModified { get; set; }
|
||||
public event Action NotifyChangesEvent;
|
||||
|
||||
@@ -429,7 +429,7 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<!-- Motion + Rumble -->
|
||||
<!-- Motion, Rumble, LED -->
|
||||
<StackPanel
|
||||
Margin="0,10,0,0"
|
||||
Spacing="5"
|
||||
@@ -495,25 +495,47 @@
|
||||
Margin="0,-1,0,0">
|
||||
<Grid IsVisible="{Binding ParentModel.HasLed}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox
|
||||
Margin="10"
|
||||
Margin="10, 10, 5, 10"
|
||||
MinWidth="0"
|
||||
Grid.Column="0"
|
||||
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLedColor}" />
|
||||
</CheckBox>
|
||||
<ui:ColorPickerButton
|
||||
<CheckBox
|
||||
Margin="5, 10, 5, 10"
|
||||
MinWidth="0"
|
||||
Grid.Column="1"
|
||||
Margin="10"
|
||||
IsVisible="{Binding ParentModel.CanClearLed}"
|
||||
IsChecked="{Binding Config.TurnOffLed, Mode=TwoWay}"
|
||||
Command="{Binding LedDisabledChanged}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLedColorDisable}" />
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
Margin="5, 10 5,10"
|
||||
MinWidth="0"
|
||||
Grid.Column="2"
|
||||
IsEnabled="{Binding !Config.TurnOffLed}"
|
||||
IsChecked="{Binding Config.UseRainbowLed, Mode=TwoWay}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLedColorRainbow}" />
|
||||
</CheckBox>
|
||||
<ui:ColorPickerButton
|
||||
Grid.Column="3"
|
||||
IsEnabled="{Binding Config.ShowLedColorPicker}"
|
||||
Margin="5, 10, 10, 10"
|
||||
IsMoreButtonVisible="False"
|
||||
UseColorPalette="False"
|
||||
UseColorTriangle="False"
|
||||
UseColorWheel="False"
|
||||
ShowAcceptDismissButtons="False"
|
||||
IsAlphaEnabled="False"
|
||||
AttachedToVisualTree="ColorPickerButton_OnAttachedToVisualTree"
|
||||
ColorChanged="ColorPickerButton_OnColorChanged"
|
||||
Color="{Binding Config.LedColor, Mode=TwoWay}">
|
||||
</ui:ColorPickerButton>
|
||||
</Grid>
|
||||
|
||||
@@ -4,11 +4,14 @@ using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System.Linq;
|
||||
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
@@ -82,7 +85,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton button)
|
||||
if (sender is ToggleButton button)
|
||||
{
|
||||
if (button.IsChecked is true)
|
||||
{
|
||||
@@ -103,7 +106,9 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
var viewModel = (DataContext as ControllerInputViewModel);
|
||||
|
||||
IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IKeyboard keyboard =
|
||||
(IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver
|
||||
.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IButtonAssigner assigner = CreateButtonAssigner(isStick);
|
||||
|
||||
_currentAssigner.ButtonAssigned += (sender, e) =>
|
||||
@@ -231,8 +236,31 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
|
||||
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
|
||||
{
|
||||
gamepad?.ClearLed();
|
||||
}
|
||||
|
||||
_currentAssigner?.Cancel();
|
||||
_currentAssigner = null;
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
|
||||
{
|
||||
if (!args.NewColor.HasValue) return;
|
||||
if (DataContext is not ControllerInputViewModel cVm) return;
|
||||
if (!cVm.Config.EnableLedChanging) return;
|
||||
|
||||
cVm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (DataContext is not ControllerInputViewModel cVm) return;
|
||||
if (!cVm.Config.EnableLedChanging) return;
|
||||
|
||||
cVm.ParentModel.SelectedGamepad.SetLed(cVm.Config.LedColor.ToUInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,14 @@ using Avalonia.Input;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Key = Avalonia.Input.Key;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
@@ -106,6 +111,12 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
HotkeysPage.Dispose();
|
||||
|
||||
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
|
||||
{
|
||||
gamepad?.ClearLed();
|
||||
}
|
||||
|
||||
InputPage.Dispose();
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Avalonia.Media;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||
@@ -421,7 +422,9 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
config.Led = new LedConfigController
|
||||
{
|
||||
EnableLed = false,
|
||||
LedColor = 328189
|
||||
TurnOffLed = false,
|
||||
UseRainbow = false,
|
||||
LedColor = new Color(255, 5, 1, 253).ToUInt32()
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user