Compare commits
49 Commits
Canary-1.2
...
44de9b378b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44de9b378b | ||
|
|
2ec032c48b | ||
|
|
f75efbea54 | ||
|
|
11f1922a82 | ||
|
|
f9e8f4bc29 | ||
|
|
de18c4927f | ||
|
|
7694c8c046 | ||
|
|
0dd789e8a5 | ||
|
|
4e0aafd005 | ||
|
|
c5091f499e | ||
|
|
41c8fd8194 | ||
|
|
d4a7ee25ea | ||
|
|
3141c560fb | ||
|
|
de341b285b | ||
|
|
78e7a3085a | ||
|
|
01e22f1c67 | ||
|
|
cc95e80ee9 | ||
|
|
d75ce52bd4 | ||
|
|
3352d70ea4 | ||
|
|
864cd57b51 | ||
|
|
4a4ea557de | ||
|
|
06cd53925c | ||
|
|
33fefb1323 | ||
|
|
0c503e10ae | ||
|
|
1c6390cbfb | ||
|
|
c20452be61 | ||
|
|
b6667a8352 | ||
|
|
37b4dd2133 | ||
|
|
007d3bc045 | ||
|
|
be2aa5ae8f | ||
|
|
7f5978155b | ||
|
|
cd43362042 | ||
|
|
39e8283fb8 | ||
|
|
3e3de18976 | ||
|
|
a158a93d0a | ||
|
|
ff90b68d09 | ||
|
|
d7bd165861 | ||
|
|
5bfa01b58a | ||
|
|
7c30426f89 | ||
|
|
267aaca87d | ||
|
|
b9012e291b | ||
|
|
7da4a917ba | ||
|
|
4bab858793 | ||
|
|
ca7c17186e | ||
|
|
ea061cf60c | ||
|
|
d83da7d2fb | ||
|
|
25499cbbf6 | ||
|
|
8074a4dd87 | ||
|
|
13d2498405 |
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -3,16 +3,6 @@ name: Release job
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
push:
|
||||
branches: [ release ]
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
- 'docs/**'
|
||||
- 'assets/**'
|
||||
- '*.yml'
|
||||
- '*.json'
|
||||
- '*.config'
|
||||
- '*.md'
|
||||
|
||||
concurrency: release
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.0.1" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.0.2" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -253,11 +253,23 @@ namespace Ryujinx.Input.SDL2
|
||||
return IGamepad.GetStateSnapshot(this);
|
||||
}
|
||||
|
||||
private static bool hotButtonMinus = false;
|
||||
private static bool hotExit = false;
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
if (hotButtonMinus)
|
||||
{
|
||||
hotButtonMinus = false;
|
||||
return hotExit;
|
||||
}
|
||||
return hotExit = false;
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetMappedStateSnapshot()
|
||||
{
|
||||
GamepadStateSnapshot rawState = GetStateSnapshot();
|
||||
GamepadStateSnapshot result = default;
|
||||
|
||||
lock (_userMappingLock)
|
||||
{
|
||||
if (_buttonsUserMapping.Count == 0)
|
||||
@@ -270,6 +282,28 @@ namespace Ryujinx.Input.SDL2
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
if (GamepadButtonInputId.Minus == entry.To)
|
||||
{
|
||||
if (rawState.IsPressed(entry.From) && !hotButtonMinus)
|
||||
{
|
||||
hotButtonMinus = true;
|
||||
}
|
||||
else if (!result.IsPressed(entry.From) && hotButtonMinus)
|
||||
{
|
||||
hotButtonMinus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (GamepadButtonInputId.Plus == entry.To)
|
||||
{
|
||||
if (rawState.IsPressed(entry.To) && hotButtonMinus)
|
||||
{
|
||||
|
||||
hotExit = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Do not touch state of button already pressed
|
||||
if (!result.IsPressed(entry.To))
|
||||
{
|
||||
@@ -376,5 +410,7 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
return SDL_GameControllerGetButton(_gamepadHandle, _buttonsDriverMapping[(int)inputId]) == 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +329,11 @@ namespace Ryujinx.Input.SDL2
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetStateSnapshot()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
|
||||
@@ -25,6 +25,10 @@ namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
_driver = driver;
|
||||
}
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Vector2 GetPosition()
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.HLE.HOS.Services.Hid;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -273,15 +274,21 @@ namespace Ryujinx.Input.HLE
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
public bool Update()
|
||||
{
|
||||
|
||||
// _gamepad may be altered by other threads
|
||||
var gamepad = _gamepad;
|
||||
|
||||
|
||||
if (gamepad != null && GamepadDriver != null)
|
||||
{
|
||||
State = gamepad.GetMappedStateSnapshot();
|
||||
|
||||
if (gamepad.SpecialExit())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion)
|
||||
{
|
||||
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver)
|
||||
@@ -334,6 +341,7 @@ namespace Ryujinx.Input.HLE
|
||||
State = default;
|
||||
_leftMotionInput = null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public GamepadInput GetHLEInputState()
|
||||
|
||||
@@ -200,8 +200,10 @@ namespace Ryujinx.Input.HLE
|
||||
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
||||
}
|
||||
|
||||
public void Update(float aspectRatio = 1)
|
||||
public bool Update(float aspectRatio = 1)
|
||||
{
|
||||
bool specialExit = false;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
List<GamepadInput> hleInputStates = new();
|
||||
@@ -225,9 +227,10 @@ namespace Ryujinx.Input.HLE
|
||||
DriverConfigurationUpdate(ref controller, inputConfig);
|
||||
|
||||
controller.UpdateUserConfiguration(inputConfig);
|
||||
controller.Update();
|
||||
controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex));
|
||||
|
||||
specialExit = controller.Update(); //hotkey press check
|
||||
controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex));
|
||||
|
||||
inputState = controller.GetHLEInputState();
|
||||
|
||||
inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick);
|
||||
@@ -315,6 +318,8 @@ namespace Ryujinx.Input.HLE
|
||||
|
||||
_device.TamperMachine.UpdateInput(hleInputStates);
|
||||
}
|
||||
|
||||
return specialExit;
|
||||
}
|
||||
|
||||
internal InputConfig GetPlayerInputConfigByIndex(int index)
|
||||
|
||||
@@ -79,6 +79,12 @@ namespace Ryujinx.Input
|
||||
/// <returns>A remapped snaphost of the state of the gamepad.</returns>
|
||||
GamepadStateSnapshot GetMappedStateSnapshot();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state if the minus and plus buttons were pressed on the gamepad.
|
||||
/// </summary>
|
||||
/// <returns>returns true if the buttons were pressed.</returns>
|
||||
bool SpecialExit();
|
||||
|
||||
/// <summary>
|
||||
/// Get a snaphost of the state of the gamepad.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,6 +18,7 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Renderer;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Views.Main;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
@@ -70,6 +71,7 @@ namespace Ryujinx.Ava
|
||||
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
||||
private const int TargetFps = 60;
|
||||
private const float VolumeDelta = 0.05f;
|
||||
static bool SpecialExit = false;
|
||||
|
||||
private static readonly Cursor _invisibleCursor = new(StandardCursorType.None);
|
||||
private readonly nint _invisibleCursorWin;
|
||||
@@ -96,6 +98,7 @@ namespace Ryujinx.Ava
|
||||
private bool _isCursorInRenderer = true;
|
||||
private bool _ignoreCursorState = false;
|
||||
|
||||
|
||||
private enum CursorStates
|
||||
{
|
||||
CursorIsHidden,
|
||||
@@ -503,10 +506,15 @@ namespace Ryujinx.Ava
|
||||
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
||||
|
||||
MainLoop();
|
||||
|
||||
|
||||
Exit();
|
||||
}
|
||||
|
||||
public bool IsSpecialExit()
|
||||
{
|
||||
return SpecialExit;
|
||||
}
|
||||
|
||||
private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args)
|
||||
{
|
||||
if (Device != null)
|
||||
@@ -589,6 +597,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
_isStopped = true;
|
||||
Stop();
|
||||
|
||||
}
|
||||
|
||||
public void DisposeContext()
|
||||
@@ -1135,6 +1144,7 @@ namespace Ryujinx.Ava
|
||||
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
|
||||
string vSyncMode = Device.VSyncMode.ToString();
|
||||
|
||||
|
||||
UpdateShaderCount();
|
||||
|
||||
if (GraphicsConfig.ResScale != 1)
|
||||
@@ -1200,7 +1210,17 @@ namespace Ryujinx.Ava
|
||||
return false;
|
||||
}
|
||||
|
||||
NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
|
||||
if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat()))
|
||||
{
|
||||
if (ConfigurationState.Instance.Hid.SpecialExitEmulator.Value == 1)
|
||||
{
|
||||
SpecialExit = true; // close App
|
||||
}
|
||||
if (ConfigurationState.Instance.Hid.SpecialExitEmulator.Value > 0)
|
||||
{
|
||||
_isActive = false; //close game
|
||||
}
|
||||
}
|
||||
|
||||
if (_viewModel.IsActive)
|
||||
{
|
||||
@@ -1335,6 +1355,8 @@ namespace Ryujinx.Ava
|
||||
|
||||
Device.Hid.DebugPad.Update();
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,31 @@
|
||||
"zh_TW": "滑鼠直接存取"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsExtraCloseApp",
|
||||
"Translations": {
|
||||
"ar_SA": "خروج سريع من التطبيق",
|
||||
"de_DE": "Schneller Ausstieg aus der Anwendung",
|
||||
"el_GR": "Γρήγορη έξοδος από την εφαρμογή",
|
||||
"en_US": "Quick Exit from Application",
|
||||
"es_ES": "Salida rápida de la aplicación",
|
||||
"fr_FR": "Sortie rapide de l'application",
|
||||
"he_IL": "יציאה מהירה מהאפליקציה",
|
||||
"it_IT": "Uscita rapida dall'applicazione",
|
||||
"ja_JP": "アプリケーションからの迅速な終了",
|
||||
"ko_KR": "애플리케이션에서 빠른 종료",
|
||||
"no_NO": "Rask avslutning av applikasjonen",
|
||||
"pl_PL": "Szybkie wyjście z aplikacji",
|
||||
"pt_BR": "Saída rápida do aplicativo",
|
||||
"ru_RU": "Быстрый выход из приложения",
|
||||
"sv_SE": "Snabb avslutning från applikationen",
|
||||
"th_TH": "ออกจากแอปพลิเคชันอย่างรวดเร็ว",
|
||||
"tr_TR": "Uygulamadan Hızlı Çıkış",
|
||||
"uk_UA": "Швидкий вихід з програми",
|
||||
"zh_CN": "快速退出应用程序",
|
||||
"zh_TW": "快速退出應用程式"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabSystemMemoryManagerMode",
|
||||
"Translations": {
|
||||
@@ -11047,6 +11072,81 @@
|
||||
"zh_TW": "淺色"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabInputDisableExitHotKey",
|
||||
"Translations": {
|
||||
"ar_SA": "الخروج السريع معطل",
|
||||
"de_DE": "Schneller Ausstieg deaktiviert",
|
||||
"el_GR": "Η γρήγορη έξοδος είναι απενεργοποιημένη",
|
||||
"en_US": "Quick exit disabled",
|
||||
"es_ES": "Salida rápida desactivada",
|
||||
"fr_FR": "Sortie rapide désactivée",
|
||||
"he_IL": "יציאה מהירה מושבתת",
|
||||
"it_IT": "Uscita rapida disabilitata",
|
||||
"ja_JP": "クイック終了が無効です",
|
||||
"ko_KR": "빠른 종료 비활성화됨",
|
||||
"no_NO": "Rask avslutning er deaktivert",
|
||||
"pl_PL": "Szybkie wyjście wyłączone",
|
||||
"pt_BR": "Saída rápida desativada",
|
||||
"ru_RU": "Быстрый выход выключен",
|
||||
"sv_SE": "Snabb avslutning inaktiverad",
|
||||
"th_TH": "ปิดใช้งานออกอย่างรวดเร็ว",
|
||||
"tr_TR": "Hızlı çıkış devre dışı bırakıldı",
|
||||
"uk_UA": "Швидкий вихід вимкнено",
|
||||
"zh_CN": "快速退出已禁用",
|
||||
"zh_TW": "快速退出已停用"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabInputHotkeyIsCloseApp",
|
||||
"Translations": {
|
||||
"ar_SA": "إغلاق التطبيق بالضغط على الزرين '+' و '-'.",
|
||||
"de_DE": "App schließen mit den '+' und '-' Tasten.",
|
||||
"el_GR": "Κλείσιμο της εφαρμογής με τα κουμπιά '+' και '-'.",
|
||||
"en_US": "Close app by '+' and '-' buttons.",
|
||||
"es_ES": "Cerrar la aplicación pulsando los botones '+' y '-'.",
|
||||
"fr_FR": "Fermer l'application avec les boutons '+' et '-'.",
|
||||
"he_IL": "סגור את האפליקציה בלחיצה על '+' ו-'-'.",
|
||||
"it_IT": "Chiudi l'app premendo i pulsanti '+' e '-'.",
|
||||
"ja_JP": "「+」と「-」ボタンを押してアプリを終了します。",
|
||||
"ko_KR": "'+' 및 '-' 버튼을 눌러 앱을 종료합니다.",
|
||||
"no_NO": "Lukk appen med '+' og '-' knappene.",
|
||||
"pl_PL": "Zamknij aplikację przyciskiem '+' i '-'.",
|
||||
"pt_BR": "Fechar o aplicativo pressionando os botões '+' e '-'.",
|
||||
"ru_RU": "Закрыть приложение нажатием '+' и '-'.",
|
||||
"sv_SE": "Stäng appen med '+' och '-' knapparna.",
|
||||
"th_TH": "ปิดแอปโดยกดปุ่ม '+' และ '-'.",
|
||||
"tr_TR": "'+' ve '-' düğmelerine basarak uygulamayı kapatın.",
|
||||
"uk_UA": "Закрити додаток натисканням '+' та '-'.",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabInputHotkeyIsCloseGame",
|
||||
"Translations": {
|
||||
"ar_SA": "الخروج من اللعبة بالضغط على الزرين '+' و '-'.",
|
||||
"de_DE": "Spiel beenden mit den '+' und '-' Tasten.",
|
||||
"el_GR": "Έξοδος από το παιχνίδι με τα κουμπιά '+' και '-'.",
|
||||
"en_US": "Exit game by '+' and '-' buttons.",
|
||||
"es_ES": "Salir del juego pulsando los botones '+' y '-'.",
|
||||
"fr_FR": "Quitter le jeu avec les boutons '+' et '-'.",
|
||||
"he_IL": "יציאה מהמשחק בלחיצה על '+' ו-'-'.",
|
||||
"it_IT": "Esci dal gioco premendo i pulsanti '+' e '-'.",
|
||||
"ja_JP": "「+」と「-」ボタンを押してゲームを終了します。",
|
||||
"ko_KR": "'+' 및 '-' 버튼을 눌러 게임을 종료합니다.",
|
||||
"no_NO": "Avslutt spillet med '+' og '-' knappene.",
|
||||
"pl_PL": "Wyjście z gry przyciskiem '+' i '-'.",
|
||||
"pt_BR": "Sair do jogo pressionando os botões '+' e '-'.",
|
||||
"ru_RU": "Выйти из игры нажатием '+' и '-'.",
|
||||
"sv_SE": "Avsluta spelet med '+' och '-' knapparna.",
|
||||
"th_TH": "ออกจากเกมโดยกดปุ่ม '+' และ '-'.",
|
||||
"tr_TR": "'+' ve '-' düğmelerine basarak oyundan çıkın.",
|
||||
"uk_UA": "Вийти з гри натисканням '+' та '-'.",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "ControllerSettingsConfigureGeneral",
|
||||
"Translations": {
|
||||
@@ -15147,6 +15247,31 @@
|
||||
"zh_TW": "支援滑鼠直接存取 (HID)。遊戲可將滑鼠作為指向裝置使用。\n\n僅適用於在 Switch 硬體上原生支援滑鼠控制的遊戲,這類遊戲很少。\n\n啟用後,觸控螢幕功能可能無法使用。\n\n如果不確定,請保持關閉狀態。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SpecialExitTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "يقوم بتفعيل مفاتيح الاختصار 'زائد' و 'ناقص'.\nاضغط على زرّي زائد وناقص في نفس الوقت لتنفيذ إحدى العمليات:\n\n1) إغلاق التطبيق باستخدام مفاتيح الاختصار.\n2) الخروج من اللعبة دون إغلاق التطبيق.\n\nيعمل فقط مع أذرع التحكم.",
|
||||
"de_DE": "Aktiviert die Hotkeys 'Plus' und 'Minus'.\nDrücken Sie gleichzeitig die Plus- und Minus-Tasten, um eine der folgenden Aktionen auszuführen:\n\n1) Schließt die Anwendung durch Drücken der Hotkeys.\n2) Beendet das Spiel, ohne die Anwendung zu schließen.\n\nFunktioniert nur mit Gamepads.",
|
||||
"el_GR": "Ενεργοποιεί τα πλήκτρα πρόσβασης 'συν' και 'πλην'.\nΠατήστε ταυτόχρονα τα κουμπιά συν και πλην για μία από τις ενέργειες:\n\n1) Κλείνει την εφαρμογή πατώντας τα πλήκτρα πρόσβασης.\n2) Εξέρχεται από το παιχνίδι χωρίς να κλείσει η εφαρμογή.\n\nΛειτουργεί μόνο με gamepads.",
|
||||
"en_US": "Activates the hot keys 'plus' and 'minus'.\nPress buttons plus and minus at the same time to get one of the actions:\n\n1) Closes the application by pressing the hot keys.\n2) Exits the game without closing the application.\n\nWorks only with gamepads.",
|
||||
"es_ES": "Activa las teclas rápidas 'más' y 'menos'.\nPresiona los botones más y menos al mismo tiempo para realizar una de las siguientes acciones:\n\n1) Cierra la aplicación presionando las teclas rápidas.\n2) Salir del juego sin cerrar la aplicación.\n\nFunciona solo con mandos.",
|
||||
"fr_FR": "Active les raccourcis 'plus' et 'moins'.\nAppuyez simultanément sur les boutons plus et moins pour effectuer l'une des actions suivantes :\n\n1) Ferme l'application en appuyant sur les raccourcis.\n2) Quitte le jeu sans fermer l'application.\n\nFonctionne uniquement avec les manettes.",
|
||||
"he_IL": "מפעיל את המקשים הקצרים 'פלוס' ו-'מינוס'.\nלחץ על הכפתורים פלוס ומינוס בו זמנית כדי לבצע אחת מהפעולות:\n\n1) סוגר את היישום באמצעות המקשים הקצרים.\n2) יוצא מהמשחק מבלי לסגור את היישום.\n\nפועל רק עם בקרי משחק.",
|
||||
"it_IT": "Attiva i tasti rapidi 'più' e 'meno'.\nPremere i pulsanti più e meno contemporaneamente per eseguire una delle seguenti azioni:\n\n1) Chiude l'applicazione premendo i tasti rapidi.\n2) Esce dal gioco senza chiudere l'applicazione.\n\nFunziona solo con i gamepad.",
|
||||
"ja_JP": "ホットキー「プラス」と「マイナス」を有効化します。\nプラスとマイナスのボタンを同時に押して、次のいずれかの操作を実行します:\n\n1) ホットキーを押すことでアプリを閉じます。\n2) アプリを閉じずにゲームを終了します。\n\nゲームパッドでのみ動作します。",
|
||||
"ko_KR": "'플러스' 및 '마이너스' 단축키를 활성화합니다.\n플러스 및 마이너스 버튼을 동시에 눌러 다음 작업 중 하나를 수행합니다:\n\n1) 단축키를 눌러 애플리케이션을 닫습니다.\n2) 애플리케이션을 닫지 않고 게임을 종료합니다.\n\n게임패드에서만 작동합니다.",
|
||||
"no_NO": "Aktiverer hurtigtastene 'pluss' og 'minus'.\nTrykk på knappene pluss og minus samtidig for å utføre en av følgende handlinger:\n\n1) Lukker applikasjonen ved å trykke på hurtigtastene.\n2) Avslutter spillet uten å lukke applikasjonen.\n\nFungerer kun med spillkontroller.",
|
||||
"pl_PL": "Aktywuje klawisze skrótu 'plus' i 'minus'.\nNaciśnij jednocześnie przyciski plus i minus, aby wykonać jedną z akcji:\n\n1) Zamknij aplikację, naciskając klawisze skrótu.\n2) Wyjdź z gry bez zamykania aplikacji.\n\nDziała tylko z gamepadami.",
|
||||
"pt_BR": "Ativa as teclas de atalho 'mais' e 'menos'.\nPressione os botões mais e menos ao mesmo tempo para realizar uma das ações:\n\n1) Fecha o aplicativo pressionando as teclas de atalho.\n2) Sai do jogo sem fechar o aplicativo.\n\nFunciona apenas com gamepads.",
|
||||
"ru_RU": "Активирует горячие клавиши 'плюс' и 'минус'.\nНажмите одновременно кнопки плюс и минус чтобы получить одно из действий:\n\n1) Закрывает приложение по нажатию горячих кнопок.\n2) Выходит из игры без закрытия приложения.\n\nРаботает только с геймпадами.",
|
||||
"sv_SE": "Aktiverar snabbtangenterna 'plus' och 'minus'.\nTryck samtidigt på plus- och minusknapparna för att utföra en av följande åtgärder:\n\n1) Stänger applikationen med snabbtangenterna.\n2) Avslutar spelet utan att stänga applikationen.\n\nFungerar bara med spelkontroller.",
|
||||
"th_TH": "เปิดใช้งานปุ่มลัด '+' และ '-'.\nกดปุ่ม '+' และ '-' พร้อมกันเพื่อทำการอย่างใดอย่างหนึ่ง:\n\n1) ปิดแอปพลิเคชันด้วยการกดปุ่มลัด\n2) ออกจากเกมโดยไม่ปิดแอปพลิเคชัน\n\nใช้งานได้เฉพาะกับจอยเกม",
|
||||
"tr_TR": "'Artı' ve 'eksi' kısayol tuşlarını etkinleştirir.\nArtı ve eksi tuşlarına aynı anda basarak aşağıdaki işlemlerden birini gerçekleştirin:\n\n1) Kısayol tuşlarına basarak uygulamayı kapatır.\n2) Uygulamayı kapatmadan oyundan çıkar.\n\nYalnızca gamepad'lerle çalışır.",
|
||||
"uk_UA": "Активує гарячі клавіші '+' та '-'.\nНатисніть одночасно кнопки плюс та мінус для виконання однієї з дій:\n\n1) Закриває додаток за допомогою гарячих клавіш.\n2) Виходить із гри без закриття додатка.\n\nПрацює лише з геймпадами.",
|
||||
"zh_CN": "激活快捷键“加号”和“减号”。\n同时按下加号和减号按钮以执行以下操作之一:\n\n1) 按快捷键关闭应用程序。\n2) 退出游戏而不关闭应用程序。\n\n仅适用于游戏手柄。",
|
||||
"zh_TW": "啟用快捷鍵「加號」和「減號」。\n同時按下加號和減號按鈕以執行以下其中一項操作:\n\n1) 按快捷鍵關閉應用程式。\n2) 離開遊戲而不關閉應用程式。\n\n僅適用於遊戲手柄。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "RegionTooltip",
|
||||
"Translations": {
|
||||
@@ -22597,6 +22722,31 @@
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "CompatibilityListLastUpdated",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Last updated: {0}",
|
||||
"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": "CompatibilityListWarning",
|
||||
"Translations": {
|
||||
|
||||
@@ -350,11 +350,11 @@ namespace Ryujinx.Headless
|
||||
{
|
||||
return options.GraphicsBackend switch
|
||||
{
|
||||
GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet),
|
||||
GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit),
|
||||
GraphicsBackend.Metal => OperatingSystem.IsMacOS() ?
|
||||
new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet) :
|
||||
new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit) :
|
||||
throw new Exception("Attempted to use Metal renderer on non-macOS platform!"),
|
||||
_ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet)
|
||||
_ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) { }
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator) { }
|
||||
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL;
|
||||
|
||||
|
||||
@@ -118,8 +118,9 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator)
|
||||
{
|
||||
_glLogLevel = glLogLevel;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,10 @@ namespace Ryujinx.Headless
|
||||
|
||||
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||
IgnoreControllerApplet = configurationState.IgnoreApplet;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(SpecialExit)))
|
||||
SpecialExit = configurationState.Hid.SpecialExitEmulator;
|
||||
|
||||
return;
|
||||
|
||||
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||
@@ -274,6 +277,9 @@ namespace Ryujinx.Headless
|
||||
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
||||
public bool EnableMouse { get; set; }
|
||||
|
||||
[Option("enable-press-hotkeys-to-exit", Required = false, Default = 0, HelpText = "press the minus and plus buttons to: 0 -disable, 1 - exit app, 2 - exit game.")]
|
||||
public int SpecialExit { get; set; }
|
||||
|
||||
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
||||
public HideCursorMode HideCursorMode { get; set; }
|
||||
|
||||
@@ -414,6 +420,7 @@ namespace Ryujinx.Headless
|
||||
[Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")]
|
||||
public bool IgnoreControllerApplet { get; set; }
|
||||
|
||||
|
||||
// Values
|
||||
|
||||
[Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]
|
||||
|
||||
@@ -18,8 +18,9 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator)
|
||||
{
|
||||
_glLogLevel = glLogLevel;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
private readonly AspectRatio _aspectRatio;
|
||||
private readonly bool _enableMouse;
|
||||
private readonly int _specialExitEmulator;
|
||||
private readonly bool _ignoreControllerApplet;
|
||||
|
||||
public WindowBase(
|
||||
@@ -96,7 +97,8 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
{
|
||||
MouseDriver = new SDL2MouseDriver(hideCursorMode);
|
||||
_inputManager = inputManager;
|
||||
@@ -112,6 +114,7 @@ namespace Ryujinx.Headless
|
||||
_gpuDoneEvent = new ManualResetEvent(false);
|
||||
_aspectRatio = aspectRatio;
|
||||
_enableMouse = enableMouse;
|
||||
_specialExitEmulator = specialExitEmulator;
|
||||
_ignoreControllerApplet = ignoreControllerApplet;
|
||||
HostUITheme = new HeadlessHostUiTheme();
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Ryujinx.Ava.Input
|
||||
public readonly Key From = from;
|
||||
}
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
|
||||
{
|
||||
_buttonsUserMapping = [];
|
||||
|
||||
@@ -13,6 +13,11 @@ namespace Ryujinx.Ava.Input
|
||||
public string Id => "0";
|
||||
public string Name => "AvaloniaMouse";
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsConnected => true;
|
||||
public GamepadFeaturesFlag Features => throw new NotImplementedException();
|
||||
public bool[] Buttons => _driver.PressedButtons;
|
||||
|
||||
@@ -133,12 +133,13 @@
|
||||
Spacing="5">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding TimePlayedString}"
|
||||
Text="{Binding LastPlayedString}"
|
||||
TextAlignment="End"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding LastPlayedString}"
|
||||
Text="{Binding TimePlayedString}"
|
||||
IsVisible="{Binding HasPlayedPreviously}"
|
||||
TextAlignment="End"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
|
||||
@@ -1,152 +1,53 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models.Input
|
||||
{
|
||||
public class HotkeyConfig : BaseModel
|
||||
public partial class HotkeyConfig : BaseModel
|
||||
{
|
||||
private Key _toggleVSyncMode;
|
||||
public Key ToggleVSyncMode
|
||||
{
|
||||
get => _toggleVSyncMode;
|
||||
set
|
||||
{
|
||||
_toggleVSyncMode = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _toggleVSyncMode;
|
||||
|
||||
private Key _screenshot;
|
||||
public Key Screenshot
|
||||
{
|
||||
get => _screenshot;
|
||||
set
|
||||
{
|
||||
_screenshot = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _screenshot;
|
||||
|
||||
private Key _showUI;
|
||||
public Key ShowUI
|
||||
{
|
||||
get => _showUI;
|
||||
set
|
||||
{
|
||||
_showUI = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _showUI;
|
||||
|
||||
private Key _pause;
|
||||
public Key Pause
|
||||
{
|
||||
get => _pause;
|
||||
set
|
||||
{
|
||||
_pause = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _pause;
|
||||
|
||||
private Key _toggleMute;
|
||||
public Key ToggleMute
|
||||
{
|
||||
get => _toggleMute;
|
||||
set
|
||||
{
|
||||
_toggleMute = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _toggleMute;
|
||||
|
||||
private Key _resScaleUp;
|
||||
public Key ResScaleUp
|
||||
{
|
||||
get => _resScaleUp;
|
||||
set
|
||||
{
|
||||
_resScaleUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _resScaleUp;
|
||||
|
||||
private Key _resScaleDown;
|
||||
public Key ResScaleDown
|
||||
{
|
||||
get => _resScaleDown;
|
||||
set
|
||||
{
|
||||
_resScaleDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _resScaleDown;
|
||||
|
||||
private Key _volumeUp;
|
||||
public Key VolumeUp
|
||||
{
|
||||
get => _volumeUp;
|
||||
set
|
||||
{
|
||||
_volumeUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _volumeUp;
|
||||
|
||||
private Key _volumeDown;
|
||||
public Key VolumeDown
|
||||
{
|
||||
get => _volumeDown;
|
||||
set
|
||||
{
|
||||
_volumeDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _volumeDown;
|
||||
|
||||
private Key _customVSyncIntervalIncrement;
|
||||
public Key CustomVSyncIntervalIncrement
|
||||
{
|
||||
get => _customVSyncIntervalIncrement;
|
||||
set
|
||||
{
|
||||
_customVSyncIntervalIncrement = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _customVSyncIntervalIncrement;
|
||||
|
||||
private Key _customVSyncIntervalDecrement;
|
||||
public Key CustomVSyncIntervalDecrement
|
||||
{
|
||||
get => _customVSyncIntervalDecrement;
|
||||
set
|
||||
{
|
||||
_customVSyncIntervalDecrement = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _customVSyncIntervalDecrement;
|
||||
|
||||
public HotkeyConfig(KeyboardHotkeys config)
|
||||
{
|
||||
if (config != null)
|
||||
{
|
||||
ToggleVSyncMode = config.ToggleVSyncMode;
|
||||
Screenshot = config.Screenshot;
|
||||
ShowUI = config.ShowUI;
|
||||
Pause = config.Pause;
|
||||
ToggleMute = config.ToggleMute;
|
||||
ResScaleUp = config.ResScaleUp;
|
||||
ResScaleDown = config.ResScaleDown;
|
||||
VolumeUp = config.VolumeUp;
|
||||
VolumeDown = config.VolumeDown;
|
||||
CustomVSyncIntervalIncrement = config.CustomVSyncIntervalIncrement;
|
||||
CustomVSyncIntervalDecrement = config.CustomVSyncIntervalDecrement;
|
||||
}
|
||||
if (config == null)
|
||||
return;
|
||||
|
||||
ToggleVSyncMode = config.ToggleVSyncMode;
|
||||
Screenshot = config.Screenshot;
|
||||
ShowUI = config.ShowUI;
|
||||
Pause = config.Pause;
|
||||
ToggleMute = config.ToggleMute;
|
||||
ResScaleUp = config.ResScaleUp;
|
||||
ResScaleDown = config.ResScaleDown;
|
||||
VolumeUp = config.VolumeUp;
|
||||
VolumeDown = config.VolumeDown;
|
||||
CustomVSyncIntervalIncrement = config.CustomVSyncIntervalIncrement;
|
||||
CustomVSyncIntervalDecrement = config.CustomVSyncIntervalDecrement;
|
||||
}
|
||||
|
||||
public KeyboardHotkeys GetConfig()
|
||||
{
|
||||
var config = new KeyboardHotkeys
|
||||
public KeyboardHotkeys GetConfig() =>
|
||||
new()
|
||||
{
|
||||
ToggleVSyncMode = ToggleVSyncMode,
|
||||
Screenshot = Screenshot,
|
||||
@@ -160,8 +61,5 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
CustomVSyncIntervalIncrement = CustomVSyncIntervalIncrement,
|
||||
CustomVSyncIntervalDecrement = CustomVSyncIntervalDecrement,
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
using Avalonia.Svg.Skia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class ControllerInputViewModel : BaseModel
|
||||
public partial class ControllerInputViewModel : BaseModel
|
||||
{
|
||||
private GamepadInputConfig _config;
|
||||
public GamepadInputConfig Config
|
||||
{
|
||||
get => _config;
|
||||
set
|
||||
{
|
||||
_config = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private GamepadInputConfig _config;
|
||||
|
||||
private bool _isLeft;
|
||||
public bool IsLeft
|
||||
@@ -43,16 +35,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
public bool HasSides => IsLeft ^ IsRight;
|
||||
|
||||
private SvgImage _image;
|
||||
public SvgImage Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private SvgImage _image;
|
||||
|
||||
public readonly InputViewModel ParentModel;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Svg.Skia;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
@@ -32,7 +31,7 @@ using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class InputViewModel : BaseModel, IDisposable
|
||||
public partial class InputViewModel : BaseModel, IDisposable
|
||||
{
|
||||
private const string Disabled = "disabled";
|
||||
private const string ProControllerResource = "Ryujinx/Assets/Icons/Controller_ProCon.svg";
|
||||
@@ -48,8 +47,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
private int _controller;
|
||||
private string _controllerImage;
|
||||
private int _device;
|
||||
private object _configViewModel;
|
||||
private string _profileName;
|
||||
[ObservableProperty] private object _configViewModel;
|
||||
[ObservableProperty] private string _profileName;
|
||||
private bool _isLoaded;
|
||||
|
||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
@@ -73,17 +72,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
public bool IsModified { get; set; }
|
||||
public event Action NotifyChangesEvent;
|
||||
|
||||
public object ConfigViewModel
|
||||
{
|
||||
get => _configViewModel;
|
||||
set
|
||||
{
|
||||
_configViewModel = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public PlayerIndex PlayerIdChoose
|
||||
{
|
||||
get => _playerIdChoose;
|
||||
@@ -200,16 +188,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
}
|
||||
}
|
||||
|
||||
public string ProfileName
|
||||
{
|
||||
get => _profileName; set
|
||||
{
|
||||
_profileName = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int Device
|
||||
{
|
||||
get => _device;
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
using Avalonia.Svg.Skia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class KeyboardInputViewModel : BaseModel
|
||||
public partial class KeyboardInputViewModel : BaseModel
|
||||
{
|
||||
private KeyboardInputConfig _config;
|
||||
public KeyboardInputConfig Config
|
||||
{
|
||||
get => _config;
|
||||
set
|
||||
{
|
||||
_config = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private KeyboardInputConfig _config;
|
||||
|
||||
private bool _isLeft;
|
||||
public bool IsLeft
|
||||
@@ -42,16 +34,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
public bool HasSides => IsLeft ^ IsRight;
|
||||
|
||||
private SvgImage _image;
|
||||
public SvgImage Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private SvgImage _image;
|
||||
|
||||
public readonly InputViewModel ParentModel;
|
||||
|
||||
|
||||
@@ -1,93 +1,23 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class MotionInputViewModel : BaseModel
|
||||
public partial class MotionInputViewModel : BaseModel
|
||||
{
|
||||
private int _slot;
|
||||
public int Slot
|
||||
{
|
||||
get => _slot;
|
||||
set
|
||||
{
|
||||
_slot = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private int _slot;
|
||||
|
||||
private int _altSlot;
|
||||
public int AltSlot
|
||||
{
|
||||
get => _altSlot;
|
||||
set
|
||||
{
|
||||
_altSlot = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private int _altSlot;
|
||||
|
||||
private string _dsuServerHost;
|
||||
public string DsuServerHost
|
||||
{
|
||||
get => _dsuServerHost;
|
||||
set
|
||||
{
|
||||
_dsuServerHost = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private string _dsuServerHost;
|
||||
|
||||
private int _dsuServerPort;
|
||||
public int DsuServerPort
|
||||
{
|
||||
get => _dsuServerPort;
|
||||
set
|
||||
{
|
||||
_dsuServerPort = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private int _dsuServerPort;
|
||||
|
||||
private bool _mirrorInput;
|
||||
public bool MirrorInput
|
||||
{
|
||||
get => _mirrorInput;
|
||||
set
|
||||
{
|
||||
_mirrorInput = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private bool _mirrorInput;
|
||||
|
||||
private int _sensitivity;
|
||||
public int Sensitivity
|
||||
{
|
||||
get => _sensitivity;
|
||||
set
|
||||
{
|
||||
_sensitivity = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private int _sensitivity;
|
||||
|
||||
private double _gryoDeadzone;
|
||||
public double GyroDeadzone
|
||||
{
|
||||
get => _gryoDeadzone;
|
||||
set
|
||||
{
|
||||
_gryoDeadzone = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private double _gyroDeadzone;
|
||||
|
||||
private bool _enableCemuHookMotion;
|
||||
public bool EnableCemuHookMotion
|
||||
{
|
||||
get => _enableCemuHookMotion;
|
||||
set
|
||||
{
|
||||
_enableCemuHookMotion = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private bool _enableCemuHookMotion;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,11 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class RumbleInputViewModel : BaseModel
|
||||
public partial class RumbleInputViewModel : BaseModel
|
||||
{
|
||||
private float _strongRumble;
|
||||
public float StrongRumble
|
||||
{
|
||||
get => _strongRumble;
|
||||
set
|
||||
{
|
||||
_strongRumble = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private float _strongRumble;
|
||||
|
||||
private float _weakRumble;
|
||||
public float WeakRumble
|
||||
{
|
||||
get => _weakRumble;
|
||||
set
|
||||
{
|
||||
_weakRumble = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private float _weakRumble;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1049,6 +1049,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void InitializeGame()
|
||||
{
|
||||
|
||||
RendererHostControl.WindowCreated += RendererHost_Created;
|
||||
|
||||
AppHost.StatusUpdatedEvent += Update_StatusBar;
|
||||
@@ -1058,7 +1059,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
AppHost?.Start();
|
||||
|
||||
if (AppHost?.IsSpecialExit() == true)
|
||||
{
|
||||
Window.ForceExit();
|
||||
}
|
||||
|
||||
AppHost?.DisposeContext();
|
||||
|
||||
}
|
||||
|
||||
private async Task HandleRelaunch()
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableDockedMode { get; set; }
|
||||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
public int EnableSpecialExit { get; set; }
|
||||
public VSyncMode VSyncMode
|
||||
{
|
||||
get => _vSyncMode;
|
||||
@@ -259,6 +260,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public int OpenglDebugLevel { get; set; }
|
||||
public int MemoryMode { get; set; }
|
||||
public int BaseStyleIndex { get; set; }
|
||||
|
||||
|
||||
public int GraphicsBackendIndex
|
||||
{
|
||||
get => _graphicsBackendIndex;
|
||||
@@ -511,6 +514,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
EnableDockedMode = config.System.EnableDockedMode;
|
||||
EnableKeyboard = config.Hid.EnableKeyboard;
|
||||
EnableMouse = config.Hid.EnableMouse;
|
||||
EnableSpecialExit = config.Hid.SpecialExitEmulator.Value switch
|
||||
{
|
||||
0 => 0, // "Hotkey 'Exit' is Disabled"
|
||||
1 => 1, // "Close app. by hotkey"
|
||||
2 => 2, // "Close game by hotkey"
|
||||
_ => 0
|
||||
};
|
||||
|
||||
// Keyboard Hotkeys
|
||||
KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value);
|
||||
@@ -618,6 +628,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||
config.Hid.EnableMouse.Value = EnableMouse;
|
||||
config.Hid.SpecialExitEmulator.Value = EnableSpecialExit switch
|
||||
{
|
||||
0 => 0, // "Hotkey 'Exit' is Disabled",
|
||||
1 => 1, // "Close app. by hotkey",
|
||||
2 => 2, // "Close game by hotkey",
|
||||
_ => 0
|
||||
};
|
||||
|
||||
// Keyboard Hotkeys
|
||||
config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsInputView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
@@ -58,6 +58,20 @@
|
||||
<TextBlock
|
||||
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
||||
</CheckBox>
|
||||
<ComboBox SelectedIndex="{Binding EnableSpecialExit}"
|
||||
ToolTip.Tip="{ext:Locale SpecialExitTooltip}"
|
||||
HorizontalContentAlignment="Left"
|
||||
MinWidth="160">
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabInputDisableExitHotKey}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabInputHotkeyIsCloseApp}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabInputHotkeyIsCloseGame}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
internal readonly AvaHostUIHandler UiHandler;
|
||||
|
||||
private bool _isLoading;
|
||||
private bool _isExitWithoutConfirm = false;
|
||||
private bool _applicationsLoadedOnce;
|
||||
|
||||
private UserChannelPersistence _userChannelPersistence;
|
||||
@@ -164,7 +165,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
});
|
||||
}
|
||||
|
||||
private void ApplicationLibrary_LdnGameDataReceived(object sender, LdnGameDataReceivedEventArgs e)
|
||||
private void ApplicationLibrary_LdnGameDataReceived(LdnGameDataReceivedEventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
@@ -408,13 +409,10 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
StatusBarView.VolumeStatus.Click += VolumeStatus_CheckedChanged;
|
||||
|
||||
ApplicationGrid.DataContext = ApplicationList.DataContext = ViewModel;
|
||||
|
||||
ApplicationGrid.ApplicationOpened += Application_Opened;
|
||||
|
||||
ApplicationGrid.DataContext = ViewModel;
|
||||
|
||||
ApplicationList.ApplicationOpened += Application_Opened;
|
||||
|
||||
ApplicationList.DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private void SetWindowSizePosition()
|
||||
@@ -574,11 +572,11 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit)
|
||||
if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit && !_isExitWithoutConfirm)
|
||||
{
|
||||
e.Cancel = true;
|
||||
|
||||
ConfirmExit();
|
||||
ConfirmExit();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -619,6 +617,12 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
||||
public void ForceExit()
|
||||
{
|
||||
_isExitWithoutConfirm = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ConfirmExit()
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
@@ -23,6 +25,11 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
InitializeComponent();
|
||||
Load();
|
||||
|
||||
#if DEBUG
|
||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
public SettingsWindow()
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
|
||||
public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
|
||||
|
||||
public bool HasPlayedPreviously => TimePlayedString != string.Empty;
|
||||
|
||||
public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n");
|
||||
|
||||
public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
public Language DesiredLanguage { get; set; }
|
||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||
public event Action<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||
|
||||
public readonly IObservableCache<ApplicationData, ulong> Applications;
|
||||
public readonly IObservableCache<(TitleUpdateModel TitleUpdate, bool IsSelected), TitleUpdateModel> TitleUpdates;
|
||||
@@ -779,7 +779,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
using HttpClient httpClient = new HttpClient();
|
||||
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
|
||||
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
||||
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = ldnGameDataArray
|
||||
});
|
||||
@@ -787,7 +787,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
|
||||
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = Array.Empty<LdnGameData>()
|
||||
});
|
||||
@@ -795,7 +795,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
}
|
||||
else
|
||||
{
|
||||
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = Array.Empty<LdnGameData>()
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Gommon;
|
||||
using Humanizer;
|
||||
using nietras.SeparatedValues;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Common.Logging;
|
||||
@@ -56,7 +57,7 @@ namespace Ryujinx.Ava.Utilities.Compat
|
||||
? titleIdRow
|
||||
: default(Optional<string>);
|
||||
|
||||
GameName = ColStr(row[indices.GameName]).Trim().Trim('"');
|
||||
GameName = ColStr(row[indices.GameName]);
|
||||
|
||||
Labels = ColStr(row[indices.Labels]).Split(';');
|
||||
Status = ColStr(row[indices.Status]).ToLower() switch
|
||||
@@ -83,12 +84,14 @@ namespace Ryujinx.Ava.Utilities.Compat
|
||||
public LocaleKeys? Status { get; }
|
||||
public DateTime LastUpdated { get; }
|
||||
|
||||
public string LocalizedLastUpdated =>
|
||||
LocaleManager.FormatDynamicValue(LocaleKeys.CompatibilityListLastUpdated, LastUpdated.Humanize());
|
||||
|
||||
public string LocalizedStatus => LocaleManager.Instance[Status!.Value];
|
||||
public string FormattedTitleId => TitleId
|
||||
.OrElse(new string(' ', 16));
|
||||
|
||||
public string FormattedIssueLabels => Labels
|
||||
.Where(it => !it.StartsWithIgnoreCase("status"))
|
||||
.Select(FormatLabelName)
|
||||
.JoinToString(", ");
|
||||
|
||||
@@ -97,7 +100,9 @@ namespace Ryujinx.Ava.Utilities.Compat
|
||||
StringBuilder sb = new("CompatibilityEntry: {");
|
||||
sb.Append($"{nameof(GameName)}=\"{GameName}\", ");
|
||||
sb.Append($"{nameof(TitleId)}={TitleId}, ");
|
||||
sb.Append($"{nameof(Labels)}=\"{Labels}\", ");
|
||||
sb.Append($"{nameof(Labels)}={
|
||||
Labels.FormatCollection(it => $"\"{it}\"", separator: ", ", prefix: "[", suffix: "]")
|
||||
}, ");
|
||||
sb.Append($"{nameof(Status)}=\"{Status}\", ");
|
||||
sb.Append($"{nameof(LastUpdated)}=\"{LastUpdated}\"");
|
||||
sb.Append('}');
|
||||
|
||||
@@ -44,8 +44,11 @@
|
||||
ItemsSource="{Binding CurrentEntries}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type local:CompatibilityEntry}">
|
||||
<Grid Width="750" ColumnDefinitions="Auto,Auto,Auto,*"
|
||||
Margin="5">
|
||||
<Grid Width="750"
|
||||
Margin="5"
|
||||
ColumnDefinitions="Auto,Auto,Auto,*"
|
||||
Background="Transparent"
|
||||
ToolTip.Tip="{Binding LocalizedLastUpdated}">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding GameName}"
|
||||
Width="320"
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// <summary>
|
||||
/// The current version of the file format
|
||||
/// </summary>
|
||||
public const int CurrentVersion = 59;
|
||||
public const int CurrentVersion = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Version of the configuration file format
|
||||
@@ -366,6 +366,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
public bool EnableMouse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to choose one of several behaviors when pressing hotkeys:
|
||||
/// 0 - Do nothing, 1 - Close the emulator application, 2 - Exit the game.
|
||||
/// </summary>
|
||||
public int SpecialExitEmulator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hotkey Keyboard Bindings
|
||||
/// </summary>
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
|
||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||
Hid.SpecialExitEmulator.Value = cff.SpecialExitEmulator;
|
||||
Hid.Hotkeys.Value = cff.Hotkeys;
|
||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||
|
||||
@@ -414,6 +415,10 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
// This was accidentally enabled by default when it was PRed. That is not what we want,
|
||||
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
||||
cff.IgnoreApplet = false;
|
||||
}),
|
||||
(60, static cff =>
|
||||
{
|
||||
cff.SpecialExitEmulator = 0;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -420,6 +420,13 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableMouse { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to choose one of several behaviors when pressing hotkeys:
|
||||
/// 0 - Do nothing, 1 - Close the emulator application, 2 - Exit the game.
|
||||
/// </summary>
|
||||
public ReactiveObject<int> SpecialExitEmulator { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Hotkey Keyboard Bindings
|
||||
/// </summary>
|
||||
@@ -436,6 +443,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
{
|
||||
EnableKeyboard = new ReactiveObject<bool>();
|
||||
EnableMouse = new ReactiveObject<bool>();
|
||||
SpecialExitEmulator = new ReactiveObject<int>();
|
||||
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
||||
InputConfig = new ReactiveObject<List<InputConfig>>();
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
ShowConsole = UI.ShowConsole,
|
||||
EnableKeyboard = Hid.EnableKeyboard,
|
||||
EnableMouse = Hid.EnableMouse,
|
||||
SpecialExitEmulator = Hid.SpecialExitEmulator,
|
||||
Hotkeys = Hid.Hotkeys,
|
||||
KeyboardConfig = [],
|
||||
ControllerConfig = [],
|
||||
@@ -241,6 +242,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
UI.WindowStartup.WindowMaximized.Value = false;
|
||||
Hid.EnableKeyboard.Value = false;
|
||||
Hid.EnableMouse.Value = false;
|
||||
Hid.SpecialExitEmulator.Value = 0;
|
||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVSyncMode = Key.F1,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Humanizer;
|
||||
using Humanizer.Localisation;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
@@ -31,7 +33,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
Gigabytes = 9,
|
||||
Terabytes = 10,
|
||||
Petabytes = 11,
|
||||
Exabytes = 12,
|
||||
Exabytes = 12
|
||||
}
|
||||
|
||||
private const double SizeBase10 = 1000;
|
||||
@@ -48,22 +50,24 @@ namespace Ryujinx.Ava.Utilities
|
||||
public static string FormatTimeSpan(TimeSpan? timeSpan)
|
||||
{
|
||||
if (!timeSpan.HasValue || timeSpan.Value.TotalSeconds < 1)
|
||||
{
|
||||
// Game was never played
|
||||
return TimeSpan.Zero.ToString("c", CultureInfo.InvariantCulture);
|
||||
}
|
||||
return string.Empty;
|
||||
|
||||
if (timeSpan.Value.TotalSeconds < 60)
|
||||
return timeSpan.Value.Humanize(1,
|
||||
countEmptyUnits: false,
|
||||
maxUnit: TimeUnit.Second,
|
||||
minUnit: TimeUnit.Second);
|
||||
|
||||
if (timeSpan.Value.TotalDays < 1)
|
||||
{
|
||||
// Game was played for less than a day
|
||||
return timeSpan.Value.ToString("c", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// Game was played for more than a day
|
||||
TimeSpan onlyTime = timeSpan.Value.Subtract(TimeSpan.FromDays(timeSpan.Value.Days));
|
||||
string onlyTimeString = onlyTime.ToString("c", CultureInfo.InvariantCulture);
|
||||
|
||||
return $"{timeSpan.Value.Days}d, {onlyTimeString}";
|
||||
if (timeSpan.Value.TotalMinutes < 60)
|
||||
return timeSpan.Value.Humanize(1,
|
||||
countEmptyUnits: false,
|
||||
maxUnit: TimeUnit.Minute,
|
||||
minUnit: TimeUnit.Minute);
|
||||
|
||||
return timeSpan.Value.Humanize(1,
|
||||
countEmptyUnits: false,
|
||||
maxUnit: TimeUnit.Hour,
|
||||
minUnit: TimeUnit.Hour);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user