Compare commits
37 Commits
Canary-1.2
...
aa9a37bfea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa9a37bfea | ||
|
|
f024c8a695 | ||
|
|
e104ee6be3 | ||
|
|
e65d1ec6c9 | ||
|
|
534f92506b | ||
|
|
10d20c1ae3 | ||
|
|
e294a79975 | ||
|
|
ec06a86899 | ||
|
|
6ecdf690be | ||
|
|
c6e82046dd | ||
|
|
538a9c83bd | ||
|
|
c3bfa67393 | ||
|
|
72c3ca7769 | ||
|
|
da268ebbee | ||
|
|
55f3a4b7ff | ||
|
|
cc905280cd | ||
|
|
38ecb3d5bc | ||
|
|
fd9bce0f6b | ||
|
|
b8cb70ef32 | ||
|
|
e238ea85c9 | ||
|
|
8cc74dab08 | ||
|
|
62dfbb5dcb | ||
|
|
5b88a2dd89 | ||
|
|
5034ef18c9 | ||
|
|
287d68c2cc | ||
|
|
f07efb751e | ||
|
|
6c8a60db08 | ||
|
|
7999a973f3 | ||
|
|
5513de93e5 | ||
|
|
9cccaac9d3 | ||
|
|
9b7dc6f4ee | ||
|
|
3ff9d1e128 | ||
|
|
ab4bb0a885 | ||
|
|
97be01d473 | ||
|
|
24cef89b6c | ||
|
|
2fe157e2b2 | ||
|
|
186ed4f984 |
@@ -97,7 +97,7 @@ If you are planning to contribute or just want to learn more about this project
|
|||||||
|
|
||||||
- **Input**
|
- **Input**
|
||||||
|
|
||||||
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers.
|
We currently have support for keyboard, mouse, touch input, Joy-Con input support, and nearly all controllers.
|
||||||
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||||
In all scenarios, you can set up everything inside the input configuration menu.
|
In all scenarios, you can set up everything inside the input configuration menu.
|
||||||
|
|
||||||
|
|||||||
@@ -71,16 +71,24 @@ namespace Ryujinx.HLE.Loaders.Mods
|
|||||||
int patchOffset = (int)offset;
|
int patchOffset = (int)offset;
|
||||||
int patchSize = patch.Length;
|
int patchSize = patch.Length;
|
||||||
|
|
||||||
if (patchOffset < protectedOffset || patchOffset > memory.Length)
|
if (patchOffset < protectedOffset)
|
||||||
{
|
{
|
||||||
continue; // Add warning?
|
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch protected memory ({patchOffset:x} is within protected boundary of {protectedOffset:x}).");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patchOffset > memory.Length)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch out of bounds memory (offset {patchOffset} ({patchOffset:x}) exceeds memory buffer length {memory.Length}).");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
patchOffset -= protectedOffset;
|
patchOffset -= protectedOffset;
|
||||||
|
|
||||||
if (patchOffset + patchSize > memory.Length)
|
if (patchOffset + patchSize > memory.Length)
|
||||||
{
|
{
|
||||||
patchSize = memory.Length - patchOffset; // Add warning?
|
Logger.Warning?.Print(LogClass.ModLoader, $"Patch offset ({patchOffset:x}) + size ({patchSize}) is greater than the size of the memory buffer ({memory.Length}). Attempting to fix this...");
|
||||||
|
patchSize = memory.Length - patchOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
|
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace Ryujinx.Input.SDL2
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId)
|
private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId)
|
||||||
{
|
{
|
||||||
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
|
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
|
||||||
{
|
{
|
||||||
if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
|
if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using ControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
|
|||||||
using PlayerIndex = Ryujinx.HLE.HOS.Services.Hid.PlayerIndex;
|
using PlayerIndex = Ryujinx.HLE.HOS.Services.Hid.PlayerIndex;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
|
|
||||||
|
|
||||||
namespace Ryujinx.Input.HLE
|
namespace Ryujinx.Input.HLE
|
||||||
{
|
{
|
||||||
public class NpadManager : IDisposable
|
public class NpadManager : IDisposable
|
||||||
@@ -38,6 +39,8 @@ namespace Ryujinx.Input.HLE
|
|||||||
private bool _enableMouse;
|
private bool _enableMouse;
|
||||||
private Switch _device;
|
private Switch _device;
|
||||||
|
|
||||||
|
public bool AutoAssignEnabled { get; set; } = false;
|
||||||
|
|
||||||
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
|
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
|
||||||
{
|
{
|
||||||
_controllers = new NpadController[MaxControllers];
|
_controllers = new NpadController[MaxControllers];
|
||||||
@@ -84,12 +87,14 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AutoAssignEnabled) return;
|
||||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadConnected(string id)
|
private void HandleOnGamepadConnected(string id)
|
||||||
{
|
{
|
||||||
|
if (AutoAssignEnabled) return;
|
||||||
// Force input reload
|
// Force input reload
|
||||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
||||||
}
|
}
|
||||||
@@ -171,7 +176,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
_device.Hid.RefreshInputConfig(validInputs);
|
_device.Hid.RefreshInputConfig(validInputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnblockInputUpdates()
|
public void UnblockInputUpdates()
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
@@ -202,11 +207,13 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
|
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
|
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
|
||||||
|
|
||||||
|
AutoAssignEnabled = enableAutoAssign;
|
||||||
|
|
||||||
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
DisplaySleep.Prevent();
|
DisplaySleep.Prevent();
|
||||||
|
|
||||||
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
|
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse, ConfigurationState.Instance.Hid.EnableAutoAssign);
|
||||||
TouchScreenManager.Initialize(Device);
|
TouchScreenManager.Initialize(Device);
|
||||||
|
|
||||||
_viewModel.IsGameRunning = true;
|
_viewModel.IsGameRunning = true;
|
||||||
|
|||||||
@@ -147,6 +147,31 @@
|
|||||||
"zh_TW": "滑鼠直接存取"
|
"zh_TW": "滑鼠直接存取"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsTabInputAutoAssign",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Auto-assign controllers",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "Assegnamento controller automatico",
|
||||||
|
"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": "SettingsTabSystemMemoryManagerMode",
|
"ID": "SettingsTabSystemMemoryManagerMode",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -464,7 +489,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Abrir Pasta de Capturas de Tela",
|
"pt_BR": "Abrir Pasta de Capturas de Tela",
|
||||||
"ru_RU": "Открыть папку со скриншотами",
|
"ru_RU": "Открыть папку со скриншотами",
|
||||||
"sv_SE": "",
|
"sv_SE": "Öppna skärmbildsmappen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Відкрити теку скріншотів",
|
"uk_UA": "Відкрити теку скріншотів",
|
||||||
@@ -1564,7 +1589,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desenvolvido por {0}",
|
"pt_BR": "Desenvolvido por {0}",
|
||||||
"ru_RU": "Разработана {0}",
|
"ru_RU": "Разработана {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Utvecklat av {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Розроблено: {0}",
|
"uk_UA": "Розроблено: {0}",
|
||||||
@@ -1864,7 +1889,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Compatibilidade:",
|
"pt_BR": "Compatibilidade:",
|
||||||
"ru_RU": "Совместимость:",
|
"ru_RU": "Совместимость:",
|
||||||
"sv_SE": "",
|
"sv_SE": "Kompatibilitet:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Сумісність:",
|
"uk_UA": "Сумісність:",
|
||||||
@@ -1889,7 +1914,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "ID do Título:",
|
"pt_BR": "ID do Título:",
|
||||||
"ru_RU": "ID приложения",
|
"ru_RU": "ID приложения",
|
||||||
"sv_SE": "",
|
"sv_SE": "Titel-id:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "ID гри:",
|
"uk_UA": "ID гри:",
|
||||||
@@ -1914,7 +1939,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Jogos Hospedados: {0}",
|
"pt_BR": "Jogos Hospedados: {0}",
|
||||||
"ru_RU": "Запущенно игр: {0}",
|
"ru_RU": "Запущенно игр: {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Värdskap för spel: {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Розміщені ігри: {0}",
|
"uk_UA": "Розміщені ігри: {0}",
|
||||||
@@ -1939,7 +1964,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Jogadores Online: {0}",
|
"pt_BR": "Jogadores Online: {0}",
|
||||||
"ru_RU": "Игроков онлайн: {0}",
|
"ru_RU": "Игроков онлайн: {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Online-spelare: {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Гравців онлайн: {0}",
|
"uk_UA": "Гравців онлайн: {0}",
|
||||||
@@ -2289,7 +2314,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Limpar Cache PPTC",
|
"pt_BR": "Limpar Cache PPTC",
|
||||||
"ru_RU": "Очистить кэш PPTC",
|
"ru_RU": "Очистить кэш PPTC",
|
||||||
"sv_SE": "",
|
"sv_SE": "Rensa PPTC-cache",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Очистити кеш PPTC",
|
"uk_UA": "Очистити кеш PPTC",
|
||||||
@@ -2314,7 +2339,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
|
"pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
|
||||||
"ru_RU": "Удаляет все файлы кэша PPTC для приложения",
|
"ru_RU": "Удаляет все файлы кэша PPTC для приложения",
|
||||||
"sv_SE": "",
|
"sv_SE": "Tar bort alla PPTC-cachefiler för applikationen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
|
"uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
|
||||||
@@ -2763,7 +2788,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Создать пользовательскую конфигурацию",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -2788,7 +2813,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Изменить пользовательскую конфигурацию",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -2863,7 +2888,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Отредактировать существующую независимую конфигурацию для выбранной игры.",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -2889,7 +2914,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Dados de Compatibilidade",
|
"pt_BR": "Mostrar Dados de Compatibilidade",
|
||||||
"ru_RU": "Показать записи о совместимости",
|
"ru_RU": "Показать записи о совместимости",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa kompatibilitetspost",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Iнформація про сумісність",
|
"uk_UA": "Iнформація про сумісність",
|
||||||
@@ -2914,7 +2939,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
|
"pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
|
||||||
"ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
|
"ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa valt spel i kompatibilitetslistan som du normalt sett kan komma åt via hjälpmenyn.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
|
"uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
|
||||||
@@ -2939,7 +2964,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Informações do Jogo",
|
"pt_BR": "Mostrar Informações do Jogo",
|
||||||
"ru_RU": "Показать информацию об игре",
|
"ru_RU": "Показать информацию об игре",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa spelinformation",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Інформація про гру",
|
"uk_UA": "Інформація про гру",
|
||||||
@@ -2964,7 +2989,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Exibe estatísticas e detalhes sobre o jogo selecionado.",
|
"pt_BR": "Exibe estatísticas e detalhes sobre o jogo selecionado.",
|
||||||
"ru_RU": "Показывать статистику и подробную информацию о выбранной игре.",
|
"ru_RU": "Показывать статистику и подробную информацию о выбранной игре.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa statistik och detaljer om det aktuella spelet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показати статистику та деталі обраної гри.",
|
"uk_UA": "Показати статистику та деталі обраної гри.",
|
||||||
@@ -3514,7 +3539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Verificar Atualizações:",
|
"pt_BR": "Verificar Atualizações:",
|
||||||
"ru_RU": "Проверка наличия обновлений",
|
"ru_RU": "Проверка наличия обновлений",
|
||||||
"sv_SE": "",
|
"sv_SE": "Leta efter uppdateringar:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Перевірка оновлень:",
|
"uk_UA": "Перевірка оновлень:",
|
||||||
@@ -3539,7 +3564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desligado",
|
"pt_BR": "Desligado",
|
||||||
"ru_RU": "Отключить",
|
"ru_RU": "Отключить",
|
||||||
"sv_SE": "",
|
"sv_SE": "Av",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Вимкнути",
|
"uk_UA": "Вимкнути",
|
||||||
@@ -3564,7 +3589,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ao Abrir",
|
"pt_BR": "Ao Abrir",
|
||||||
"ru_RU": "При запуске",
|
"ru_RU": "При запуске",
|
||||||
"sv_SE": "",
|
"sv_SE": "Fråga",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запитувати щоразу",
|
"uk_UA": "Запитувати щоразу",
|
||||||
@@ -3589,7 +3614,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "2° Plano",
|
"pt_BR": "2° Plano",
|
||||||
"ru_RU": "В фоне",
|
"ru_RU": "В фоне",
|
||||||
"sv_SE": "",
|
"sv_SE": "Bakgrund",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Оновлювати в фоні",
|
"uk_UA": "Оновлювати в фоні",
|
||||||
@@ -3614,7 +3639,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ao Perder o Foco:",
|
"pt_BR": "Ao Perder o Foco:",
|
||||||
"ru_RU": "При выходе эмулятора из фокуса",
|
"ru_RU": "При выходе эмулятора из фокуса",
|
||||||
"sv_SE": "",
|
"sv_SE": "När emulatorn tappar fokus:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "При втраті фокуса емулятором:",
|
"uk_UA": "При втраті фокуса емулятором:",
|
||||||
@@ -3639,7 +3664,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Não Fazer Nada",
|
"pt_BR": "Não Fazer Nada",
|
||||||
"ru_RU": "Ничего не делать",
|
"ru_RU": "Ничего не делать",
|
||||||
"sv_SE": "",
|
"sv_SE": "Gör ingenting",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Нічого не робити",
|
"uk_UA": "Нічого не робити",
|
||||||
@@ -3664,7 +3689,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Bloquear Controles",
|
"pt_BR": "Bloquear Controles",
|
||||||
"ru_RU": "Блокировать управление",
|
"ru_RU": "Блокировать управление",
|
||||||
"sv_SE": "",
|
"sv_SE": "Blockera inmatning",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Блокувати введення",
|
"uk_UA": "Блокувати введення",
|
||||||
@@ -3689,7 +3714,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ficar Mudo",
|
"pt_BR": "Ficar Mudo",
|
||||||
"ru_RU": "Отключить звук",
|
"ru_RU": "Отключить звук",
|
||||||
"sv_SE": "",
|
"sv_SE": "Stäng av ljudet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Вимкнути звук",
|
"uk_UA": "Вимкнути звук",
|
||||||
@@ -3714,7 +3739,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Bloquear Controles & Ficar Mudo",
|
"pt_BR": "Bloquear Controles & Ficar Mudo",
|
||||||
"ru_RU": "Блокировать управление и отключить звук",
|
"ru_RU": "Блокировать управление и отключить звук",
|
||||||
"sv_SE": "",
|
"sv_SE": "Blockera inmatningar och stäng av ljudet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Блокувати введення та Вимкнути звук",
|
"uk_UA": "Блокувати введення та Вимкнути звук",
|
||||||
@@ -3739,7 +3764,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Pausar a Emulação",
|
"pt_BR": "Pausar a Emulação",
|
||||||
"ru_RU": "Поставить паузу",
|
"ru_RU": "Поставить паузу",
|
||||||
"sv_SE": "",
|
"sv_SE": "Pausa emuleringen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Поставити на паузу",
|
"uk_UA": "Поставити на паузу",
|
||||||
@@ -3814,7 +3839,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
|
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
|
||||||
"ru_RU": "Отключает управление при выходе из фокуса",
|
"ru_RU": "Отключает управление при выходе из фокуса",
|
||||||
"sv_SE": "",
|
"sv_SE": "Inaktivera inmatning när fokus tappas",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -4839,7 +4864,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Sincronizar com o Sistema PC",
|
"pt_BR": "Sincronizar com o Sistema PC",
|
||||||
"ru_RU": "Соответствовать времени в системе",
|
"ru_RU": "Соответствовать времени в системе",
|
||||||
"sv_SE": "",
|
"sv_SE": "Matcha systemtid",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -5013,7 +5038,7 @@
|
|||||||
"no_NO": "Lyd Inn/Ut",
|
"no_NO": "Lyd Inn/Ut",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Выход/Вход звука",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -5264,7 +5289,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ignorar Applet do Controlador",
|
"pt_BR": "Ignorar Applet do Controlador",
|
||||||
"ru_RU": "Игнорировать апплет контроллера",
|
"ru_RU": "Игнорировать апплет контроллера",
|
||||||
"sv_SE": "",
|
"sv_SE": "Ignorera kontroller-applet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ігнорувати Аплет Контролера",
|
"uk_UA": "Ігнорувати Аплет Контролера",
|
||||||
@@ -6114,7 +6139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Habilitar Logs da IU",
|
"pt_BR": "Habilitar Logs da IU",
|
||||||
"ru_RU": "Включить журнал интерфейса",
|
"ru_RU": "Включить журнал интерфейса",
|
||||||
"sv_SE": "",
|
"sv_SE": "Aktivera gränssnittsloggar",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Увімкнути журнали інтерфейсу",
|
"uk_UA": "Увімкнути журнали інтерфейсу",
|
||||||
@@ -6514,7 +6539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Redefinir Configurações",
|
"pt_BR": "Redefinir Configurações",
|
||||||
"ru_RU": "Сбросить настройки",
|
"ru_RU": "Сбросить настройки",
|
||||||
"sv_SE": "",
|
"sv_SE": "Nollställ inställningar",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Скинути налаштування",
|
"uk_UA": "Скинути налаштування",
|
||||||
@@ -6539,7 +6564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Quero redefinir minhas configurações.",
|
"pt_BR": "Quero redefinir minhas configurações.",
|
||||||
"ru_RU": "Я хочу сбросить свои настройки.",
|
"ru_RU": "Я хочу сбросить свои настройки.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Jag vill nollställa mina inställningar.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Я хочу скинути налаштування.",
|
"uk_UA": "Я хочу скинути налаштування.",
|
||||||
@@ -6563,7 +6588,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Ок",
|
||||||
"sv_SE": "Ok",
|
"sv_SE": "Ok",
|
||||||
"th_TH": "ตกลง",
|
"th_TH": "ตกลง",
|
||||||
"tr_TR": "Tamam",
|
"tr_TR": "Tamam",
|
||||||
@@ -7013,7 +7038,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "Pro Kontroler",
|
"pl_PL": "Pro Kontroler",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Pro контроллер",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "โปรคอนโทรลเลอร์",
|
"th_TH": "โปรคอนโทรลเลอร์",
|
||||||
"tr_TR": "Profesyonel Kumanda",
|
"tr_TR": "Profesyonel Kumanda",
|
||||||
@@ -8514,7 +8539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Velocidade do Arco-íris",
|
"pt_BR": "Velocidade do Arco-íris",
|
||||||
"ru_RU": "Скорость переливания",
|
"ru_RU": "Скорость переливания",
|
||||||
"sv_SE": "",
|
"sv_SE": "Regnbågshastighet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -13814,7 +13839,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
|
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
|
||||||
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
|
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
|
||||||
"sv_SE": "",
|
"sv_SE": "Du är på väg att ta bort allt PPTC-data från:\n\n{0}\n\nÄr du säker på att du vill fortsätta?",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
|
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
|
||||||
@@ -16222,6 +16247,31 @@
|
|||||||
"zh_TW": "支援滑鼠直接存取 (HID)。遊戲可將滑鼠作為指向裝置使用。\n\n僅適用於在 Switch 硬體上原生支援滑鼠控制的遊戲,這類遊戲很少。\n\n啟用後,觸控螢幕功能可能無法使用。\n\n如果不確定,請保持關閉狀態。"
|
"zh_TW": "支援滑鼠直接存取 (HID)。遊戲可將滑鼠作為指向裝置使用。\n\n僅適用於在 Switch 硬體上原生支援滑鼠控制的遊戲,這類遊戲很少。\n\n啟用後,觸控螢幕功能可能無法使用。\n\n如果不確定,請保持關閉狀態。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "AutoAssignTooltip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Automatic controllers assignment support.\n\nAutomatically assigns connected controllers to each player.\n\nManual configuration remains available, even when this option is activated.\n\nLeave OFF if you prefer to manually assign controllers.",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "Supporto per l'assegnazione automatica dei controller.\n\nAssegna automaticamente i controller connessi a ciascun giocatore.\n\nÈ possibile configurare manualmente i controller anche quando questa opzione è attivata.\n\nLascia disattivato se preferisci assegnare i controller manualmente.",
|
||||||
|
"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": "RegionTooltip",
|
"ID": "RegionTooltip",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -16664,7 +16714,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
|
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
|
||||||
"ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
|
"ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Handkontroller-appleten kommer inte att visas om gamepaden är frånkopplad under tiden en applikation körs.\n\nLämna AV om du är osäker.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
|
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
|
||||||
@@ -17139,7 +17189,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
|
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
|
||||||
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
|
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Skriver ut loggmeddelanden från Avalonia (användargränssnittet) i konsollen.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
|
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
|
||||||
@@ -17339,7 +17389,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Abre a pasta de capturas de tela do Ryujinx",
|
"pt_BR": "Abre a pasta de capturas de tela do Ryujinx",
|
||||||
"ru_RU": "Открывает папку скриншотов Ryujinx",
|
"ru_RU": "Открывает папку скриншотов Ryujinx",
|
||||||
"sv_SE": "",
|
"sv_SE": "Öppna Ryujinx skärmbildsmapp",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Відкрити теку куди зберігаються скріншоти Ryujinx",
|
"uk_UA": "Відкрити теку куди зберігаються скріншоти Ryujinx",
|
||||||
@@ -18089,7 +18139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Atualização Disponível!",
|
"pt_BR": "Atualização Disponível!",
|
||||||
"ru_RU": "Доступно обновление!",
|
"ru_RU": "Доступно обновление!",
|
||||||
"sv_SE": "",
|
"sv_SE": "Uppdatering finns tillgänglig!",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Доступне оновлення!",
|
"uk_UA": "Доступне оновлення!",
|
||||||
@@ -20013,7 +20063,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Амибо",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -24064,7 +24114,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
|
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
|
||||||
"ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
|
"ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp och spelas utan några krascher eller GPU-fel av några slag och med en hastighet som är snabb nog för bra upplevelse på en genomsnittlig PC.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
|
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
|
||||||
@@ -24089,7 +24139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
|
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
|
||||||
"ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
|
"ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar och går in i spelet men lider av ett eller flera av följande: kraschar, deadlocks, GPU-buggar, distraherande dåligt ljud eller är helt enkelt för långsamt. Spelet kan fortfarande spelas hela vägen igenom, men inte så som spelet är avsett att spelas.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.",
|
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.",
|
||||||
@@ -24114,7 +24164,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
|
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
|
||||||
"ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
|
"ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp och går förbi titelskärmen men tar sig inte in i huvudspelet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.",
|
"uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.",
|
||||||
@@ -24139,7 +24189,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inizializa, mas não passa da tela de título.",
|
"pt_BR": "Inizializa, mas não passa da tela de título.",
|
||||||
"ru_RU": "Загружается, но не проходит дальше титульного экрана.",
|
"ru_RU": "Загружается, но не проходит дальше титульного экрана.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp men tar sig inte förbi titelskärmen.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
|
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
|
||||||
@@ -24164,7 +24214,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
|
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
|
||||||
"ru_RU": "Не запускается или не подаёт признаков жизни.",
|
"ru_RU": "Не запускается или не подаёт признаков жизни.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar inte upp eller visar någon form av aktivitet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Взагалі не запускається.",
|
"uk_UA": "Взагалі не запускається.",
|
||||||
@@ -24264,7 +24314,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Imagem da Presença do Discord",
|
"pt_BR": "Imagem da Presença do Discord",
|
||||||
"ru_RU": "Изображение для статуса активности",
|
"ru_RU": "Изображение для статуса активности",
|
||||||
"sv_SE": "",
|
"sv_SE": "Bild för Rich Presence",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Зображення картки активності Discord",
|
"uk_UA": "Зображення картки активності Discord",
|
||||||
@@ -24289,7 +24339,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Presença Dinâmica do Discord",
|
"pt_BR": "Presença Dinâmica do Discord",
|
||||||
"ru_RU": "Динамический статус активности",
|
"ru_RU": "Динамический статус активности",
|
||||||
"sv_SE": "",
|
"sv_SE": "Dynamisk Rich Presence",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Динамічна картка активності Discord",
|
"uk_UA": "Динамічна картка активності Discord",
|
||||||
@@ -24298,4 +24348,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,7 @@ namespace Ryujinx.Headless
|
|||||||
private static List<InputConfig> _inputConfiguration = [];
|
private static List<InputConfig> _inputConfiguration = [];
|
||||||
private static bool _enableKeyboard;
|
private static bool _enableKeyboard;
|
||||||
private static bool _enableMouse;
|
private static bool _enableMouse;
|
||||||
|
private static bool _enableAutoAssign;
|
||||||
|
|
||||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
@@ -230,6 +231,7 @@ namespace Ryujinx.Headless
|
|||||||
_inputConfiguration ??= [];
|
_inputConfiguration ??= [];
|
||||||
_enableKeyboard = option.EnableKeyboard;
|
_enableKeyboard = option.EnableKeyboard;
|
||||||
_enableMouse = option.EnableMouse;
|
_enableMouse = option.EnableMouse;
|
||||||
|
_enableAutoAssign = option.EnableAutoAssign;
|
||||||
|
|
||||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||||
@@ -371,7 +373,7 @@ namespace Ryujinx.Headless
|
|||||||
|
|
||||||
DisplaySleep.Prevent();
|
DisplaySleep.Prevent();
|
||||||
|
|
||||||
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse);
|
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse, _enableAutoAssign);
|
||||||
|
|
||||||
_window.Execute();
|
_window.Execute();
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace Ryujinx.Headless
|
|||||||
|
|
||||||
if (NeedsOverride(nameof(EnableMouse)))
|
if (NeedsOverride(nameof(EnableMouse)))
|
||||||
EnableMouse = configurationState.Hid.EnableMouse;
|
EnableMouse = configurationState.Hid.EnableMouse;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(EnableAutoAssign)))
|
||||||
|
EnableAutoAssign = configurationState.Hid.EnableAutoAssign;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(HideCursorMode)))
|
if (NeedsOverride(nameof(HideCursorMode)))
|
||||||
HideCursorMode = configurationState.HideCursor;
|
HideCursorMode = configurationState.HideCursor;
|
||||||
@@ -272,6 +275,9 @@ namespace Ryujinx.Headless
|
|||||||
|
|
||||||
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
|
||||||
|
[Option("enable-auto-assign", Required = false, Default = false, HelpText = "Enable or disable auto-assigning controllers to players.")]
|
||||||
|
public bool EnableAutoAssign { get; set; }
|
||||||
|
|
||||||
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
||||||
public HideCursorMode HideCursorMode { get; set; }
|
public HideCursorMode HideCursorMode { get; set; }
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Headless
|
|||||||
SDL2Driver.Instance.Initialize();
|
SDL2Driver.Instance.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(Switch device, List<InputConfig> inputConfigs, bool enableKeyboard, bool enableMouse)
|
public void Initialize(Switch device, List<InputConfig> inputConfigs, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
|
||||||
{
|
{
|
||||||
Device = device;
|
Device = device;
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Headless
|
|||||||
|
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
|
|
||||||
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse);
|
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse, enableAutoAssign);
|
||||||
TouchScreenManager.Initialize(device);
|
TouchScreenManager.Initialize(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
75
src/Ryujinx/Input/AutoAssignController.cs
Normal file
75
src/Ryujinx/Input/AutoAssignController.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using Ryujinx.Input.HLE;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Input
|
||||||
|
{
|
||||||
|
public class AutoAssignController
|
||||||
|
{
|
||||||
|
private readonly InputManager _inputManager;
|
||||||
|
private readonly MainWindowViewModel _viewModel;
|
||||||
|
private readonly ConfigurationState _configurationState;
|
||||||
|
|
||||||
|
public event Action ConfigurationUpdated;
|
||||||
|
|
||||||
|
public AutoAssignController(InputManager inputManager, MainWindowViewModel mainWindowViewModel)
|
||||||
|
{
|
||||||
|
_inputManager = inputManager;
|
||||||
|
_viewModel = mainWindowViewModel;
|
||||||
|
_configurationState = ConfigurationState.Instance;
|
||||||
|
|
||||||
|
_inputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
|
_inputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
|
|
||||||
|
RefreshControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOnGamepadConnected(string id)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Gamepad connected: {id}");
|
||||||
|
RefreshControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOnGamepadDisconnected(string id)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Gamepad disconnected: {id}");
|
||||||
|
RefreshControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshControllers()
|
||||||
|
{
|
||||||
|
if (!_configurationState.Hid.EnableAutoAssign) return;
|
||||||
|
|
||||||
|
List<IGamepad> controllers = _inputManager.GamepadDriver.GetGamepads().ToList();
|
||||||
|
List<InputConfig> oldConfig = _configurationState.Hid.InputConfig.Value.Where(x => x != null).ToList();
|
||||||
|
|
||||||
|
List<InputConfig> newConfig = ControllerAssignmentManager.GetConfiguredControllers(
|
||||||
|
controllers, oldConfig, out bool hasNewControllersConnected);
|
||||||
|
|
||||||
|
_viewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, _configurationState.Hid.EnableKeyboard, _configurationState.Hid.EnableMouse);
|
||||||
|
|
||||||
|
if (!hasNewControllersConnected)
|
||||||
|
{
|
||||||
|
// there is no *new* controller, we must switch the order of the controllers in
|
||||||
|
// oldConfig to match the new order since probably a controller was disconnected
|
||||||
|
// or an old controller was reconnected
|
||||||
|
newConfig = ControllerAssignmentManager.ReorderControllers(newConfig, oldConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
_configurationState.Hid.InputConfig.Value = newConfig;
|
||||||
|
|
||||||
|
// we want to save the configuration only if a *new* controller was connected
|
||||||
|
if(hasNewControllersConnected)
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||||
|
}
|
||||||
|
ConfigurationUpdated?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
274
src/Ryujinx/Input/ControllerAssignmentManager.cs
Normal file
274
src/Ryujinx/Input/ControllerAssignmentManager.cs
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Input
|
||||||
|
{
|
||||||
|
public static class ControllerAssignmentManager
|
||||||
|
{
|
||||||
|
private static readonly uint[] _playerColors =
|
||||||
|
[
|
||||||
|
0xFF0000FF, // Player 1 - Blue
|
||||||
|
0xFFFF0000, // Player 2 - Red
|
||||||
|
0xFF00FF00, // Player 3 - Green
|
||||||
|
0xFFFFFF00, // Player 4 - Yellow
|
||||||
|
0xFFFF00FF, // Player 5 - Magenta
|
||||||
|
0xFFFFA500, // Player 6 - Orange
|
||||||
|
0xFF00FFFF, // Player 7 - Cyan
|
||||||
|
0xFF800080 // Player 8 - Purple
|
||||||
|
];
|
||||||
|
|
||||||
|
private const int MaxControllers = 9;
|
||||||
|
|
||||||
|
public static List<InputConfig> ReorderControllers(List<InputConfig> newConfig, List<InputConfig> oldConfig)
|
||||||
|
{
|
||||||
|
if(newConfig == null || oldConfig == null || newConfig.Count == 0 || oldConfig.Count == 0) return [];
|
||||||
|
|
||||||
|
List<InputConfig> reorderedConfig = oldConfig.Select(config => new GamepadInputConfig(config).GetConfig()).ToList();
|
||||||
|
|
||||||
|
foreach (var config in newConfig)
|
||||||
|
{
|
||||||
|
InputConfig substitute = reorderedConfig.FirstOrDefault(x => x.Id == config.Id);
|
||||||
|
InputConfig toBeReplaced = reorderedConfig.FirstOrDefault(x => x.PlayerIndex == config.PlayerIndex);
|
||||||
|
|
||||||
|
if (substitute == null || toBeReplaced == null || substitute.PlayerIndex == toBeReplaced.PlayerIndex) continue;
|
||||||
|
|
||||||
|
(substitute.PlayerIndex, toBeReplaced.PlayerIndex) = (toBeReplaced.PlayerIndex, substitute.PlayerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reorderedConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<InputConfig> GetConfiguredControllers(
|
||||||
|
List<IGamepad> controllers,
|
||||||
|
List<InputConfig> oldConfig,
|
||||||
|
out bool hasNewControllersConnected)
|
||||||
|
{
|
||||||
|
if(controllers == null || controllers.Count == 0)
|
||||||
|
{
|
||||||
|
hasNewControllersConnected = false;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, InputConfig> oldConfigMap = oldConfig
|
||||||
|
.Where(c => c?.Id != null)
|
||||||
|
.ToDictionary(x => x.Id);
|
||||||
|
|
||||||
|
Dictionary<int, InputConfig> playerIndexMap = new();
|
||||||
|
HashSet<int> usedIndices = [];
|
||||||
|
int recognizedControllersCount = 0;
|
||||||
|
|
||||||
|
List<IGamepad> remainingControllers = controllers.Where(c => c?.Id != null).ToList();
|
||||||
|
|
||||||
|
// Add controllers with existing configurations
|
||||||
|
AddExistingControllers(remainingControllers, oldConfigMap, playerIndexMap, usedIndices, ref recognizedControllersCount);
|
||||||
|
|
||||||
|
// Add new controllers
|
||||||
|
AddNewControllers(remainingControllers, playerIndexMap, usedIndices);
|
||||||
|
|
||||||
|
List<InputConfig> orderedConfigs = playerIndexMap
|
||||||
|
.OrderBy(x => x.Key)
|
||||||
|
.Select(x => x.Value)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Update player indices and LED colors
|
||||||
|
UpdatePlayerIndicesAndLEDs(orderedConfigs);
|
||||||
|
|
||||||
|
hasNewControllersConnected = controllers.Count > recognizedControllersCount;
|
||||||
|
return orderedConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddExistingControllers(
|
||||||
|
List<IGamepad> controllers,
|
||||||
|
Dictionary<string, InputConfig> oldConfigMap,
|
||||||
|
Dictionary<int, InputConfig> playerIndexMap,
|
||||||
|
HashSet<int> usedIndices,
|
||||||
|
ref int recognizedControllersCount)
|
||||||
|
{
|
||||||
|
foreach (var controller in controllers.ToList())
|
||||||
|
{
|
||||||
|
if (!oldConfigMap.TryGetValue(controller.Id, out InputConfig existingConfig))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int desiredIndex = (int)existingConfig.PlayerIndex;
|
||||||
|
|
||||||
|
// Ensure the index is valid and available
|
||||||
|
if (desiredIndex < 0 || desiredIndex >= MaxControllers || usedIndices.Contains(desiredIndex))
|
||||||
|
{
|
||||||
|
desiredIndex = GetFirstAvailableIndex(usedIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(desiredIndex == -1) continue;
|
||||||
|
|
||||||
|
InputConfig config = new GamepadInputConfig(existingConfig).GetConfig();
|
||||||
|
config.PlayerIndex = (PlayerIndex)desiredIndex;
|
||||||
|
usedIndices.Add(desiredIndex);
|
||||||
|
playerIndexMap[desiredIndex] = config;
|
||||||
|
recognizedControllersCount++;
|
||||||
|
|
||||||
|
controllers.Remove(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddNewControllers(
|
||||||
|
List<IGamepad> controllers,
|
||||||
|
Dictionary<int, InputConfig> playerIndexMap,
|
||||||
|
HashSet<int> usedIndices)
|
||||||
|
{
|
||||||
|
foreach (var controller in controllers)
|
||||||
|
{
|
||||||
|
InputConfig config = CreateConfigFromController(controller);
|
||||||
|
int freeIndex = GetFirstAvailableIndex(usedIndices);
|
||||||
|
config.PlayerIndex = (PlayerIndex)freeIndex;
|
||||||
|
usedIndices.Add(freeIndex);
|
||||||
|
playerIndexMap[freeIndex] = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetFirstAvailableIndex(HashSet<int> usedIndices)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MaxControllers; i++)
|
||||||
|
{
|
||||||
|
if (!usedIndices.Contains(i)) return i;
|
||||||
|
}
|
||||||
|
return -1; // Should not happen unless MaxControllers is exceeded
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdatePlayerIndicesAndLEDs(List<InputConfig> orderedConfigs)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < orderedConfigs.Count; index++)
|
||||||
|
{
|
||||||
|
orderedConfigs[index].PlayerIndex = (PlayerIndex)index;
|
||||||
|
|
||||||
|
if (orderedConfigs[index] is not StandardControllerInputConfig standardConfig ||
|
||||||
|
standardConfig.Led.UseRainbow)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Setting color for Player{index + 1}");
|
||||||
|
standardConfig.Led = new LedConfigController
|
||||||
|
{
|
||||||
|
EnableLed = true,
|
||||||
|
LedColor = _playerColors[index]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputConfig CreateConfigFromController(IGamepad controller)
|
||||||
|
{
|
||||||
|
if (controller == null) return null;
|
||||||
|
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Creating config for controller: {controller.Id}");
|
||||||
|
|
||||||
|
string id = controller.Id.Split(" ")[0];
|
||||||
|
bool isNintendoStyle = controller.Name.Contains("Nintendo");
|
||||||
|
ControllerType controllerType;
|
||||||
|
|
||||||
|
if (isNintendoStyle && !controller.Name.Contains("(L/R)"))
|
||||||
|
{
|
||||||
|
if (controller.Name.Contains("(L)"))
|
||||||
|
{
|
||||||
|
controllerType = ControllerType.JoyconLeft;
|
||||||
|
}
|
||||||
|
else if (controller.Name.Contains("(R)"))
|
||||||
|
{
|
||||||
|
controllerType = ControllerType.JoyconRight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllerType = ControllerType.ProController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if it's not a nintendo controller, we assume it's a pro controller or a joy-con pair
|
||||||
|
controllerType = ControllerType.ProController;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputConfig config = new StandardControllerInputConfig
|
||||||
|
{
|
||||||
|
Version = InputConfig.CurrentVersion,
|
||||||
|
Backend = InputBackendType.GamepadSDL2,
|
||||||
|
Id = id,
|
||||||
|
ControllerType = controllerType,
|
||||||
|
DeadzoneLeft = 0.1f,
|
||||||
|
DeadzoneRight = 0.1f,
|
||||||
|
RangeLeft = 1.0f,
|
||||||
|
RangeRight = 1.0f,
|
||||||
|
TriggerThreshold = 0.5f,
|
||||||
|
LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
|
||||||
|
{
|
||||||
|
DpadUp = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.Y : GamepadInputId.DpadUp,
|
||||||
|
DpadDown = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.A : GamepadInputId.DpadDown,
|
||||||
|
DpadLeft = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.B : GamepadInputId.DpadLeft,
|
||||||
|
DpadRight = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.X : GamepadInputId.DpadRight,
|
||||||
|
ButtonMinus = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.Plus : GamepadInputId.Minus,
|
||||||
|
ButtonL = GamepadInputId.LeftShoulder,
|
||||||
|
ButtonZl = GamepadInputId.LeftTrigger,
|
||||||
|
ButtonSl = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.LeftShoulder : GamepadInputId.Unbound,
|
||||||
|
ButtonSr = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.RightShoulder : GamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||||
|
{
|
||||||
|
Joystick = StickInputId.Left,
|
||||||
|
StickButton = GamepadInputId.LeftStick,
|
||||||
|
InvertStickX = false,
|
||||||
|
InvertStickY = false,
|
||||||
|
Rotate90CW = (controllerType == ControllerType.JoyconLeft),
|
||||||
|
},
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
|
||||||
|
{
|
||||||
|
ButtonA = GamepadInputId.B,
|
||||||
|
ButtonB = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.Y : GamepadInputId.A,
|
||||||
|
ButtonX = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.A : GamepadInputId.Y,
|
||||||
|
ButtonY = GamepadInputId.X,
|
||||||
|
ButtonPlus = GamepadInputId.Plus,
|
||||||
|
ButtonR = GamepadInputId.RightShoulder,
|
||||||
|
ButtonZr = GamepadInputId.RightTrigger,
|
||||||
|
ButtonSl = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.LeftShoulder : GamepadInputId.Unbound,
|
||||||
|
ButtonSr = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.RightShoulder : GamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||||
|
{
|
||||||
|
Joystick = (controllerType == ControllerType.JoyconRight) ? StickInputId.Left : StickInputId.Right,
|
||||||
|
StickButton = GamepadInputId.RightStick,
|
||||||
|
InvertStickX = (controllerType == ControllerType.JoyconRight),
|
||||||
|
InvertStickY = (controllerType == ControllerType.JoyconRight),
|
||||||
|
Rotate90CW = (controllerType == ControllerType.JoyconRight),
|
||||||
|
},
|
||||||
|
Motion = new StandardMotionConfigController
|
||||||
|
{
|
||||||
|
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||||
|
EnableMotion = true,
|
||||||
|
Sensitivity = 100,
|
||||||
|
GyroDeadzone = 1,
|
||||||
|
},
|
||||||
|
Rumble = new RumbleConfigController
|
||||||
|
{
|
||||||
|
StrongRumble = 1f,
|
||||||
|
WeakRumble = 1f,
|
||||||
|
EnableRumble = false,
|
||||||
|
},
|
||||||
|
Led = new LedConfigController
|
||||||
|
{
|
||||||
|
EnableLed = true,
|
||||||
|
TurnOffLed = false,
|
||||||
|
UseRainbow = false,
|
||||||
|
LedColor = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -134,7 +134,7 @@ namespace Ryujinx.Ava
|
|||||||
SDL2Driver.MainThreadDispatcher = action => Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Input);
|
SDL2Driver.MainThreadDispatcher = action => Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Input);
|
||||||
|
|
||||||
ReloadConfig();
|
ReloadConfig();
|
||||||
|
|
||||||
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
|
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
|
||||||
|
|
||||||
// Logging system information.
|
// Logging system information.
|
||||||
@@ -158,16 +158,6 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool FindGameConfig(string gameDir)
|
|
||||||
{
|
|
||||||
if (File.Exists(gameDir))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(gameId))
|
if (string.IsNullOrEmpty(gameId))
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
_parent.SettingsWindow =
|
_parent.SettingsWindow =
|
||||||
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
||||||
|
|
||||||
await _parent.SettingsWindow.ShowDialog(window);
|
await StyleableAppWindow.ShowAsync(_parent.SettingsWindow, window);
|
||||||
|
|
||||||
_parent.SettingsWindow = null;
|
_parent.SettingsWindow = null;
|
||||||
|
|
||||||
|
|||||||
@@ -91,11 +91,14 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await new CheatWindow(
|
await StyleableAppWindow.ShowAsync(
|
||||||
viewModel.VirtualFileSystem,
|
new CheatWindow(
|
||||||
viewModel.SelectedApplication.IdString,
|
viewModel.VirtualFileSystem,
|
||||||
viewModel.SelectedApplication.Name,
|
viewModel.SelectedApplication.IdString,
|
||||||
viewModel.SelectedApplication.Path).ShowDialog((Window)viewModel.TopLevel);
|
viewModel.SelectedApplication.Name,
|
||||||
|
viewModel.SelectedApplication.Path
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
||||||
@@ -391,9 +394,9 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
{
|
{
|
||||||
await new GameSpecificSettingsWindow(viewModel).ShowDialog((Window)viewModel.TopLevel);
|
await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel));
|
||||||
|
|
||||||
//just checking for file presence
|
// just checking for file presence
|
||||||
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
||||||
|
|
||||||
viewModel.RefreshView();
|
viewModel.RefreshView();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
@@ -384,6 +385,10 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||||||
Position = parent.PointToScreen(new Point()),
|
Position = parent.PointToScreen(new Point()),
|
||||||
ShowInTaskbar = false,
|
ShowInTaskbar = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
_contentDialogOverlayWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||||
|
#endif
|
||||||
|
|
||||||
parent.PositionChanged += OverlayOnPositionChanged;
|
parent.PositionChanged += OverlayOnPositionChanged;
|
||||||
|
|
||||||
|
|||||||
@@ -252,6 +252,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
|
|
||||||
|
_mainWindow.AutoAssignController.ConfigurationUpdated += OnConfigurationUpdated;
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
|
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
|
||||||
|
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
@@ -365,14 +367,47 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
private void HandleOnGamepadDisconnected(string id)
|
private void HandleOnGamepadDisconnected(string id)
|
||||||
{
|
{
|
||||||
|
if(ConfigurationState.Instance.Hid.EnableAutoAssign) return;
|
||||||
Dispatcher.UIThread.Post(LoadDevices);
|
Dispatcher.UIThread.Post(LoadDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadConnected(string id)
|
private void HandleOnGamepadConnected(string id)
|
||||||
{
|
{
|
||||||
|
if(ConfigurationState.Instance.Hid.EnableAutoAssign) return;
|
||||||
Dispatcher.UIThread.Post(LoadDevices);
|
Dispatcher.UIThread.Post(LoadDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnConfigurationUpdated()
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(() => {
|
||||||
|
LoadDevices();
|
||||||
|
_isLoaded = false;
|
||||||
|
LoadConfiguration();
|
||||||
|
LoadDevice();
|
||||||
|
_isLoaded = true;
|
||||||
|
|
||||||
|
UpdateGamepadLed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateGamepadLed()
|
||||||
|
{
|
||||||
|
if (ConfigViewModel is not ControllerInputViewModel controllerInputViewModel) return;
|
||||||
|
GamepadInputConfig inputConfig = controllerInputViewModel.Config;
|
||||||
|
|
||||||
|
if (inputConfig is not { EnableLedChanging: true }) return;
|
||||||
|
|
||||||
|
if (inputConfig.TurnOffLed)
|
||||||
|
{
|
||||||
|
SelectedGamepad.ClearLed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inputConfig.TurnOffLed && !inputConfig.UseRainbowLed)
|
||||||
|
{
|
||||||
|
SelectedGamepad.SetLed(inputConfig.LedColor.ToUInt32());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GetCurrentGamepadId()
|
private string GetCurrentGamepadId()
|
||||||
{
|
{
|
||||||
if (_device < 0)
|
if (_device < 0)
|
||||||
@@ -859,6 +894,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_mainWindow.ViewModel.AppHost != null)
|
||||||
|
{
|
||||||
|
_mainWindow.ViewModel.AppHost.NpadManager.AutoAssignEnabled =
|
||||||
|
ConfigurationState.Instance.Hid.EnableAutoAssign;
|
||||||
|
}
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
|
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
|
||||||
|
|
||||||
// Atomically replace and signal input change.
|
// Atomically replace and signal input change.
|
||||||
@@ -890,6 +931,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
|
||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
|
||||||
|
_mainWindow.AutoAssignController.ConfigurationUpdated -= OnConfigurationUpdated;
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
||||||
|
|
||||||
|
|||||||
@@ -1747,7 +1747,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
|
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
|
||||||
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
|
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
|
||||||
|
|
||||||
await window.ShowDialog(Window);
|
await StyleableAppWindow.ShowAsync(window);
|
||||||
|
|
||||||
if (window.IsScanned)
|
if (window.IsScanned)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
public bool EnableDockedMode { get; set; }
|
public bool EnableDockedMode { get; set; }
|
||||||
public bool EnableKeyboard { get; set; }
|
public bool EnableKeyboard { get; set; }
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
public bool EnableAutoAssign { get; set; }
|
||||||
public bool DisableInputWhenOutOfFocus { get; set; }
|
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||||
|
|
||||||
public int FocusLostActionType { get; set; }
|
public int FocusLostActionType { get; set; }
|
||||||
@@ -563,6 +564,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
EnableDockedMode = config.System.EnableDockedMode;
|
EnableDockedMode = config.System.EnableDockedMode;
|
||||||
EnableKeyboard = config.Hid.EnableKeyboard;
|
EnableKeyboard = config.Hid.EnableKeyboard;
|
||||||
EnableMouse = config.Hid.EnableMouse;
|
EnableMouse = config.Hid.EnableMouse;
|
||||||
|
EnableAutoAssign = config.Hid.EnableAutoAssign;
|
||||||
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
||||||
|
|
||||||
// Keyboard Hotkeys
|
// Keyboard Hotkeys
|
||||||
@@ -668,6 +670,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||||
config.Hid.EnableMouse.Value = EnableMouse;
|
config.Hid.EnableMouse.Value = EnableMouse;
|
||||||
|
bool activatingAutoAssign = EnableAutoAssign && !config.Hid.EnableAutoAssign;
|
||||||
|
config.Hid.EnableAutoAssign.Value = EnableAutoAssign;
|
||||||
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
||||||
|
|
||||||
// Keyboard Hotkeys
|
// Keyboard Hotkeys
|
||||||
@@ -690,7 +694,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
||||||
config.System.DramSize.Value = DramSize;
|
config.System.DramSize.Value = DramSize;
|
||||||
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
||||||
config.System.IgnoreControllerApplet.Value = IgnoreApplet;
|
config.System.IgnoreControllerApplet.Value = (EnableAutoAssign) || IgnoreApplet;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
config.System.EnablePtc.Value = EnablePptc;
|
config.System.EnablePtc.Value = EnablePptc;
|
||||||
@@ -766,7 +770,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
MainWindow.UpdateGraphicsConfig();
|
MainWindow.UpdateGraphicsConfig();
|
||||||
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
||||||
|
|
||||||
SaveSettingsEvent?.Invoke();
|
if(activatingAutoAssign)
|
||||||
|
{
|
||||||
|
RyujinxApp.MainWindow.AutoAssignController.RefreshControllers();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SaveSettingsEvent?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
GameListNeedsRefresh = false;
|
GameListNeedsRefresh = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using Ryujinx.Common.Utilities;
|
|||||||
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
|
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -133,20 +134,20 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
|
|
||||||
if (ViewModel.SelectedApplication is null) // Checks if game data exists
|
if (ViewModel.SelectedApplication is null) // Checks if game data exists
|
||||||
{
|
{
|
||||||
await Window.SettingsWindow.ShowDialog(Window);
|
await StyleableAppWindow.ShowAsync(Window.SettingsWindow);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool userConfigExist = Program.FindGameConfig(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString, false, false));
|
bool customConfigExists = File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString));
|
||||||
|
|
||||||
if (!ViewModel.IsGameRunning || !userConfigExist)
|
if (!ViewModel.IsGameRunning || !customConfigExists)
|
||||||
{
|
{
|
||||||
await Window.SettingsWindow.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
await Window.SettingsWindow.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If there is a custom configuration in the folder
|
// If there is a custom configuration in the folder
|
||||||
await new GameSpecificSettingsWindow(ViewModel, userConfigExist).ShowDialog((Window)ViewModel.TopLevel);
|
await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(ViewModel, customConfigExists));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,11 +176,13 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
|
|
||||||
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
|
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
|
||||||
|
|
||||||
await new CheatWindow(
|
await StyleableAppWindow.ShowAsync(
|
||||||
Window.VirtualFileSystem,
|
new CheatWindow(
|
||||||
ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
|
Window.VirtualFileSystem,
|
||||||
name,
|
ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
|
||||||
ViewModel.SelectedApplication.Path).ShowDialog(Window);
|
name,
|
||||||
|
ViewModel.SelectedApplication.Path)
|
||||||
|
);
|
||||||
|
|
||||||
ViewModel.AppHost.Device.EnableCheats();
|
ViewModel.AppHost.Device.EnableCheats();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,12 @@
|
|||||||
<TextBlock
|
<TextBlock
|
||||||
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<CheckBox
|
||||||
|
ToolTip.Tip="{ext:Locale AutoAssignTooltip}"
|
||||||
|
IsChecked="{Binding EnableAutoAssign}">
|
||||||
|
<TextBlock
|
||||||
|
Text="{ext:Locale SettingsTabInputAutoAssign}" />
|
||||||
|
</CheckBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -319,6 +319,7 @@
|
|||||||
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreMissingServices}" />
|
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreMissingServices}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
|
IsEnabled="{Binding !EnableAutoAssign}"
|
||||||
IsChecked="{Binding IgnoreApplet}"
|
IsChecked="{Binding IgnoreApplet}"
|
||||||
ToolTip.Tip="{ext:Locale IgnoreControllerAppletTooltip}">
|
ToolTip.Tip="{ext:Locale IgnoreControllerAppletTooltip}">
|
||||||
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreControllerApplet}" />
|
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreControllerApplet}" />
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||||
Width="1100"
|
Width="1100"
|
||||||
Height="768"
|
Height="910"
|
||||||
MinWidth="800"
|
MinWidth="800"
|
||||||
MinHeight="480"
|
MinHeight="480"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
|
|||||||
@@ -47,11 +47,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Load();
|
Load();
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveSettings()
|
public void SaveSettings()
|
||||||
@@ -65,7 +60,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
Pages.Children.Clear();
|
Pages.Children.Clear();
|
||||||
NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
|
NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
|
||||||
NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
|
NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
|
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
public LibHacHorizonManager LibHacHorizonManager { get; private set; }
|
public LibHacHorizonManager LibHacHorizonManager { get; private set; }
|
||||||
|
|
||||||
public InputManager InputManager { get; private set; }
|
public InputManager InputManager { get; private set; }
|
||||||
|
public AutoAssignController AutoAssignController { get; private set; }
|
||||||
|
|
||||||
public SettingsWindow SettingsWindow { get; set; }
|
public SettingsWindow SettingsWindow { get; set; }
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
if (Program.PreviewerDetached)
|
if (Program.PreviewerDetached)
|
||||||
{
|
{
|
||||||
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
|
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
|
||||||
|
AutoAssignController = new AutoAssignController(InputManager, ViewModel);
|
||||||
|
|
||||||
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
||||||
this.ScalingChanged += OnScalingChanged;
|
this.ScalingChanged += OnScalingChanged;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||||
Width="1100"
|
Width="1100"
|
||||||
Height="768"
|
Height="918"
|
||||||
MinWidth="800"
|
MinWidth="800"
|
||||||
MinHeight="480"
|
MinHeight="480"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
@@ -8,7 +6,6 @@ using Ryujinx.HLE.FileSystem;
|
|||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Key = Avalonia.Input.Key;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Windows
|
||||||
{
|
{
|
||||||
@@ -27,10 +24,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Load();
|
Load();
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsWindow()
|
public SettingsWindow()
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Windows
|
||||||
{
|
{
|
||||||
public abstract class StyleableAppWindow : AppWindow
|
public abstract class StyleableAppWindow : AppWindow
|
||||||
{
|
{
|
||||||
|
public static async Task ShowAsync(StyleableAppWindow appWindow, Window owner = null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
appWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||||
|
#endif
|
||||||
|
await appWindow.ShowDialog(owner ?? RyujinxApp.MainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
protected StyleableAppWindow()
|
protected StyleableAppWindow()
|
||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||||
@@ -36,6 +47,14 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
public abstract class StyleableWindow : Window
|
public abstract class StyleableWindow : Window
|
||||||
{
|
{
|
||||||
|
public static async Task ShowAsync(StyleableWindow window, Window owner = null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
window.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||||
|
#endif
|
||||||
|
await window.ShowDialog(owner ?? RyujinxApp.MainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
protected StyleableWindow()
|
protected StyleableWindow()
|
||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||||
|
|||||||
@@ -389,6 +389,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable or disable automatic controller assignment for players
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableAutoAssign { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
|
|
||||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||||
|
Hid.EnableAutoAssign.Value = cff.EnableAutoAssign;
|
||||||
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
||||||
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
||||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||||
|
|||||||
@@ -449,6 +449,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableMouse { get; private set; }
|
public ReactiveObject<bool> EnableMouse { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable or disable auto-assigning controllers to players
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> EnableAutoAssign { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -475,6 +480,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
{
|
{
|
||||||
EnableKeyboard = new ReactiveObject<bool>();
|
EnableKeyboard = new ReactiveObject<bool>();
|
||||||
EnableMouse = new ReactiveObject<bool>();
|
EnableMouse = new ReactiveObject<bool>();
|
||||||
|
EnableAutoAssign = new ReactiveObject<bool>();
|
||||||
DisableInputWhenOutOfFocus = new ReactiveObject<bool>();
|
DisableInputWhenOutOfFocus = new ReactiveObject<bool>();
|
||||||
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
||||||
InputConfig = new ReactiveObject<List<InputConfig>>();
|
InputConfig = new ReactiveObject<List<InputConfig>>();
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
ShowConsole = UI.ShowConsole,
|
ShowConsole = UI.ShowConsole,
|
||||||
EnableKeyboard = Hid.EnableKeyboard,
|
EnableKeyboard = Hid.EnableKeyboard,
|
||||||
EnableMouse = Hid.EnableMouse,
|
EnableMouse = Hid.EnableMouse,
|
||||||
|
EnableAutoAssign = Hid.EnableAutoAssign,
|
||||||
DisableInputWhenOutOfFocus = Hid.DisableInputWhenOutOfFocus,
|
DisableInputWhenOutOfFocus = Hid.DisableInputWhenOutOfFocus,
|
||||||
Hotkeys = Hid.Hotkeys,
|
Hotkeys = Hid.Hotkeys,
|
||||||
InputConfig = Hid.InputConfig,
|
InputConfig = Hid.InputConfig,
|
||||||
@@ -249,6 +250,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
UI.WindowStartup.WindowMaximized.Value = false;
|
UI.WindowStartup.WindowMaximized.Value = false;
|
||||||
Hid.EnableKeyboard.Value = false;
|
Hid.EnableKeyboard.Value = false;
|
||||||
Hid.EnableMouse.Value = false;
|
Hid.EnableMouse.Value = false;
|
||||||
|
Hid.EnableAutoAssign.Value = false;
|
||||||
Hid.DisableInputWhenOutOfFocus.Value = false;
|
Hid.DisableInputWhenOutOfFocus.Value = false;
|
||||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user