Compare commits
34 Commits
Canary-1.2
...
0bf19aeb06
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bf19aeb06 | ||
|
|
91f73a4891 | ||
|
|
883d4d863a | ||
|
|
ca5de909a1 | ||
|
|
5172567b08 | ||
|
|
6fe4cee7c0 | ||
|
|
8623452abc | ||
|
|
17e8ae1d9a | ||
|
|
7591b07fce | ||
|
|
89b4389ed2 | ||
|
|
d9ee729199 | ||
|
|
ba0cd13cff | ||
|
|
501b199e24 | ||
|
|
8aecccadb8 | ||
|
|
e23d610f49 | ||
|
|
f6822f7358 | ||
|
|
d3f84a1305 | ||
|
|
06d34a5992 | ||
|
|
e8e1dc6619 | ||
|
|
c5603d4c36 | ||
|
|
05b56730d6 | ||
|
|
43f7b000ca | ||
|
|
ad89cf39b6 | ||
|
|
96c33a0b92 | ||
|
|
e0db55df46 | ||
|
|
30fef8e96e | ||
|
|
9cb5f5689b | ||
|
|
a205ec374b | ||
|
|
aab9b58542 | ||
|
|
daa648dc40 | ||
|
|
1024aa8757 | ||
|
|
13388e972a | ||
|
|
1eb78872d8 | ||
|
|
6d78e71fc7 |
4
.github/workflows/canary.yml
vendored
4
.github/workflows/canary.yml
vendored
@@ -29,7 +29,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
name: Create tag
|
name: Create tag
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
@@ -202,7 +202,7 @@ jobs:
|
|||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -18,7 +18,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
name: Create tag
|
name: Create tag
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
@@ -183,7 +183,7 @@ jobs:
|
|||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageVersion Include="Alimer.Bindings.SDL" Version="3.7.1" />
|
||||||
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
||||||
|
|||||||
@@ -39,12 +39,12 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
Click below to join the Discord:
|
Click below to join the Discord:
|
||||||
<br>
|
<br>
|
||||||
<a href="https://discord.gg/dHPrkBkkyA">
|
<a href="https://discord.gg/PEuzjrFXUA">
|
||||||
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/docs/shell.png">
|
<img src="https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/docs/shell.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{3BF24278-547D-42C2-9D43-182B978F54DD}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
|
||||||
@@ -259,6 +261,10 @@ Global
|
|||||||
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3BF24278-547D-42C2-9D43-182B978F54DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3BF24278-547D-42C2-9D43-182B978F54DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3BF24278-547D-42C2-9D43-182B978F54DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3BF24278-547D-42C2-9D43-182B978F54DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -1249,7 +1249,7 @@
|
|||||||
0100A6B00D4EC000,"Furwind",,playable,2021-02-19 19:44:08
|
0100A6B00D4EC000,"Furwind",,playable,2021-02-19 19:44:08
|
||||||
0100ECE00C0C4000,"Fury Unleashed",crash;services,ingame,2020-10-18 11:52:40
|
0100ECE00C0C4000,"Fury Unleashed",crash;services,ingame,2020-10-18 11:52:40
|
||||||
010070000ED9E000,"Fury Unleashed Demo",,playable,2020-10-08 20:09:21
|
010070000ED9E000,"Fury Unleashed Demo",,playable,2020-10-08 20:09:21
|
||||||
0100E1F013674000,"FUSER™",nvdec;UE4,playable,2022-10-17 20:58:32
|
0100E1F013674000,"FUSER™",nvdec;UE4;slow;gpu,ingame,2025-02-12 16:03:00
|
||||||
0100A7A015E4C000,"Fushigi no Gensokyo Lotus Labyrinth",Needs Update;audio;gpu;nvdec,ingame,2021-01-20 15:30:02
|
0100A7A015E4C000,"Fushigi no Gensokyo Lotus Labyrinth",Needs Update;audio;gpu;nvdec,ingame,2021-01-20 15:30:02
|
||||||
01003C300B274000,"Futari de! Nyanko Daisensou",,playable,2024-01-05 22:26:52
|
01003C300B274000,"Futari de! Nyanko Daisensou",,playable,2024-01-05 22:26:52
|
||||||
010055801134E000,"FUZE Player",online-broken;vulkan-backend-bug,ingame,2022-10-18 12:23:53
|
010055801134E000,"FUZE Player",online-broken;vulkan-backend-bug,ingame,2022-10-18 12:23:53
|
||||||
@@ -2063,7 +2063,7 @@
|
|||||||
010002700C34C000,"Numbala",,playable,2020-05-11 12:01:07
|
010002700C34C000,"Numbala",,playable,2020-05-11 12:01:07
|
||||||
010020500C8C8000,"Number Place 10000",gpu,menus,2021-11-24 09:14:23
|
010020500C8C8000,"Number Place 10000",gpu,menus,2021-11-24 09:14:23
|
||||||
010003701002C000,"Nurse Love Syndrome",,playable,2022-10-13 10:05:22
|
010003701002C000,"Nurse Love Syndrome",,playable,2022-10-13 10:05:22
|
||||||
0000000000000000,"nx-hbmenu",Needs Update;homebrew,boots,2024-04-06 22:05:32
|
,"nx-hbmenu",Needs Update;homebrew,boots,2024-04-06 22:05:32
|
||||||
,"nxquake2",services;crash;homebrew,nothing,2022-08-04 23:14:04
|
,"nxquake2",services;crash;homebrew,nothing,2022-08-04 23:14:04
|
||||||
010049F00EC30000,"Nyan Cat: Lost in Space",online,playable,2021-06-12 13:22:03
|
010049F00EC30000,"Nyan Cat: Lost in Space",online,playable,2021-06-12 13:22:03
|
||||||
01002E6014FC4000,"O---O",,playable,2022-10-29 12:12:14
|
01002E6014FC4000,"O---O",,playable,2022-10-29 12:12:14
|
||||||
@@ -2471,7 +2471,7 @@
|
|||||||
0100AFE00DDAC000,"Royal Roads",,playable,2020-11-17 12:54:38
|
0100AFE00DDAC000,"Royal Roads",,playable,2020-11-17 12:54:38
|
||||||
0100E2C00B414000,"RPG Maker MV",nvdec,playable,2021-01-05 20:12:01
|
0100E2C00B414000,"RPG Maker MV",nvdec,playable,2021-01-05 20:12:01
|
||||||
01005CD015986000,"rRootage Reloaded",,playable,2022-08-05 23:20:18
|
01005CD015986000,"rRootage Reloaded",,playable,2022-08-05 23:20:18
|
||||||
0000000000000000,"RSDKv5u",homebrew,ingame,2024-04-01 16:25:34
|
,"RSDKv5u",homebrew,ingame,2024-04-01 16:25:34
|
||||||
010009B00D33C000,"Rugby Challenge 4",slow;online-broken;UE4,playable,2022-10-06 12:45:53
|
010009B00D33C000,"Rugby Challenge 4",slow;online-broken;UE4,playable,2022-10-06 12:45:53
|
||||||
01006EC00F2CC000,"RUINER",UE4,playable,2022-10-03 14:11:33
|
01006EC00F2CC000,"RUINER",UE4,playable,2022-10-03 14:11:33
|
||||||
010074F00DE4A000,"Run the Fan",,playable,2021-02-27 13:36:28
|
010074F00DE4A000,"Run the Fan",,playable,2021-02-27 13:36:28
|
||||||
@@ -2480,6 +2480,7 @@
|
|||||||
010081C0191D8000,"Rune Factory 3 Special",,playable,2023-10-15 08:32:49
|
010081C0191D8000,"Rune Factory 3 Special",,playable,2023-10-15 08:32:49
|
||||||
010051D00E3A4000,"Rune Factory 4 Special",32-bit;crash;nvdec,ingame,2023-05-06 08:49:17
|
010051D00E3A4000,"Rune Factory 4 Special",32-bit;crash;nvdec,ingame,2023-05-06 08:49:17
|
||||||
010014D01216E000,"Rune Factory 5 (JP)",gpu,ingame,2021-06-01 12:00:36
|
010014D01216E000,"Rune Factory 5 (JP)",gpu,ingame,2021-06-01 12:00:36
|
||||||
|
010071E0145F8000,"Rustler",,playable,2025-02-10 20:17:12
|
||||||
0100E21013908000,"RWBY: Grimm Eclipse - Definitive Edition",online-broken,playable,2022-11-03 10:44:01
|
0100E21013908000,"RWBY: Grimm Eclipse - Definitive Edition",online-broken,playable,2022-11-03 10:44:01
|
||||||
010012C0060F0000,"RXN -Raijin-",nvdec,playable,2021-01-10 16:05:43
|
010012C0060F0000,"RXN -Raijin-",nvdec,playable,2021-01-10 16:05:43
|
||||||
0100B8B012ECA000,"S.N.I.P.E.R. - Hunter Scope",,playable,2021-04-19 15:58:09
|
0100B8B012ECA000,"S.N.I.P.E.R. - Hunter Scope",,playable,2021-04-19 15:58:09
|
||||||
@@ -2673,10 +2674,10 @@
|
|||||||
01004F401BEBE000,"Song of Nunu: A League of Legends Story",,ingame,2024-07-12 18:53:44
|
01004F401BEBE000,"Song of Nunu: A League of Legends Story",,ingame,2024-07-12 18:53:44
|
||||||
0100E5400BF94000,"Songbird Symphony",,playable,2021-02-27 02:44:04
|
0100E5400BF94000,"Songbird Symphony",,playable,2021-02-27 02:44:04
|
||||||
010031D00A604000,"Songbringer",,playable,2020-06-22 10:42:02
|
010031D00A604000,"Songbringer",,playable,2020-06-22 10:42:02
|
||||||
0000000000000000,"Sonic 1 (2013)",crash;homebrew,ingame,2024-04-06 18:31:20
|
,"Sonic 1 (2013)",crash;homebrew,ingame,2024-04-06 18:31:20
|
||||||
0000000000000000,"Sonic 2 (2013)",crash;homebrew,ingame,2024-04-01 16:25:30
|
,"Sonic 2 (2013)",crash;homebrew,ingame,2024-04-01 16:25:30
|
||||||
0000000000000000,"Sonic A.I.R",homebrew,ingame,2024-04-01 16:25:32
|
,"Sonic A.I.R",homebrew,ingame,2024-04-01 16:25:32
|
||||||
0000000000000000,"Sonic CD",crash;homebrew,ingame,2024-04-01 16:25:31
|
,"Sonic CD",crash;homebrew,ingame,2024-04-01 16:25:31
|
||||||
010040E0116B8000,"Sonic Colors: Ultimate",,playable,2022-11-12 21:24:26
|
010040E0116B8000,"Sonic Colors: Ultimate",,playable,2022-11-12 21:24:26
|
||||||
01001270012B6000,"SONIC FORCES™",,playable,2024-07-28 13:11:21
|
01001270012B6000,"SONIC FORCES™",,playable,2024-07-28 13:11:21
|
||||||
01004AD014BF0000,"Sonic Frontiers",gpu;deadlock;amd-vendor-bug;intel-vendor-bug,ingame,2024-09-05 09:18:53
|
01004AD014BF0000,"Sonic Frontiers",gpu;deadlock;amd-vendor-bug;intel-vendor-bug,ingame,2024-09-05 09:18:53
|
||||||
@@ -2693,7 +2694,7 @@
|
|||||||
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
|
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
|
||||||
010047B010260000,"Space Pioneer",,playable,2022-10-20 12:24:37
|
010047B010260000,"Space Pioneer",,playable,2022-10-20 12:24:37
|
||||||
010010A009830000,"Space Ribbon",,playable,2022-08-15 17:17:10
|
010010A009830000,"Space Ribbon",,playable,2022-08-15 17:17:10
|
||||||
0000000000000000,"SpaceCadetPinball",homebrew,ingame,2024-04-18 19:30:04
|
,"SpaceCadetPinball",homebrew,ingame,2024-04-18 19:30:04
|
||||||
0100D9B0041CE000,"Spacecats with Lasers",,playable,2022-08-15 17:22:44
|
0100D9B0041CE000,"Spacecats with Lasers",,playable,2022-08-15 17:22:44
|
||||||
010034800FB60000,"Spaceland",,playable,2020-11-01 14:31:56
|
010034800FB60000,"Spaceland",,playable,2020-11-01 14:31:56
|
||||||
010028D0045CE000,"Sparkle 2",,playable,2020-10-19 11:51:39
|
010028D0045CE000,"Sparkle 2",,playable,2020-10-19 11:51:39
|
||||||
@@ -2838,7 +2839,7 @@
|
|||||||
0100000000010000,"Super Mario Odyssey™",nvdec;intel-vendor-bug;mac-bug,playable,2024-08-25 01:32:34
|
0100000000010000,"Super Mario Odyssey™",nvdec;intel-vendor-bug;mac-bug,playable,2024-08-25 01:32:34
|
||||||
010036B0034E4000,"Super Mario Party™",gpu;Needs Update;ldn-works,ingame,2024-06-21 05:10:16
|
010036B0034E4000,"Super Mario Party™",gpu;Needs Update;ldn-works,ingame,2024-06-21 05:10:16
|
||||||
0100BC0018138000,"Super Mario RPG™",gpu;audio;nvdec,ingame,2024-06-19 17:43:42
|
0100BC0018138000,"Super Mario RPG™",gpu;audio;nvdec,ingame,2024-06-19 17:43:42
|
||||||
0000000000000000,"Super Mario World",homebrew,boots,2024-06-13 01:40:31
|
,"Super Mario World",homebrew,boots,2024-06-13 01:40:31
|
||||||
010049900F546000,"Super Mario™ 3D All-Stars",services-horizon;slow;vulkan;amd-vendor-bug,ingame,2024-05-07 02:38:16
|
010049900F546000,"Super Mario™ 3D All-Stars",services-horizon;slow;vulkan;amd-vendor-bug,ingame,2024-05-07 02:38:16
|
||||||
010028600EBDA000,"Super Mario™ 3D World + Bowser’s Fury",ldn-works,playable,2024-07-31 10:45:37
|
010028600EBDA000,"Super Mario™ 3D World + Bowser’s Fury",ldn-works,playable,2024-07-31 10:45:37
|
||||||
01004F8006A78000,"Super Meat Boy",services,playable,2020-04-02 23:10:07
|
01004F8006A78000,"Super Meat Boy",services,playable,2020-04-02 23:10:07
|
||||||
|
|||||||
|
@@ -56,6 +56,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
|||||||
return motionBackendType switch
|
return motionBackendType switch
|
||||||
{
|
{
|
||||||
MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
|
MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
|
||||||
|
MotionInputBackendType.Handheld => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
|
||||||
MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, _serializerContext.CemuHookMotionConfigController),
|
MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, _serializerContext.CemuHookMotionConfigController),
|
||||||
_ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"),
|
_ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"),
|
||||||
};
|
};
|
||||||
@@ -66,6 +67,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
|||||||
switch (value.MotionBackend)
|
switch (value.MotionBackend)
|
||||||
{
|
{
|
||||||
case MotionInputBackendType.GamepadDriver:
|
case MotionInputBackendType.GamepadDriver:
|
||||||
|
case MotionInputBackendType.Handheld:
|
||||||
JsonSerializer.Serialize(writer, value as StandardMotionConfigController, _serializerContext.StandardMotionConfigController);
|
JsonSerializer.Serialize(writer, value as StandardMotionConfigController, _serializerContext.StandardMotionConfigController);
|
||||||
break;
|
break;
|
||||||
case MotionInputBackendType.CemuHook:
|
case MotionInputBackendType.CemuHook:
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
|||||||
Invalid,
|
Invalid,
|
||||||
GamepadDriver,
|
GamepadDriver,
|
||||||
CemuHook,
|
CemuHook,
|
||||||
|
Handheld,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ namespace Ryujinx.Common
|
|||||||
//Misc Games
|
//Misc Games
|
||||||
"010056e00853a000", // A Hat in Time
|
"010056e00853a000", // A Hat in Time
|
||||||
"0100fd1014726000", // Baldurs Gate: Dark Alliance
|
"0100fd1014726000", // Baldurs Gate: Dark Alliance
|
||||||
|
"01008c2019598000", // Bluey: The Video Game
|
||||||
"0100c6800b934000", // Brawlhalla
|
"0100c6800b934000", // Brawlhalla
|
||||||
"0100dbf01000a000", // Burnout Paradise Remastered
|
"0100dbf01000a000", // Burnout Paradise Remastered
|
||||||
"0100744001588000", // Cars 3: Driven to Win
|
"0100744001588000", // Cars 3: Driven to Win
|
||||||
|
|||||||
@@ -158,13 +158,15 @@ namespace Ryujinx.HLE.HOS.Applets.Error
|
|||||||
|
|
||||||
string[] buttons = GetButtonsText(module, description, "DlgBtn");
|
string[] buttons = GetButtonsText(module, description, "DlgBtn");
|
||||||
|
|
||||||
bool showDetails = _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Code: {module}-{description:0000}", "\n" + message, buttons);
|
(uint Module, uint Description) errorCodeTuple = (module, uint.Parse(description.ToString("0000")));
|
||||||
|
|
||||||
|
bool showDetails = _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Code: {module}-{description:0000}", "\n" + message, buttons, errorCodeTuple);
|
||||||
if (showDetails)
|
if (showDetails)
|
||||||
{
|
{
|
||||||
message = GetMessageText(module, description, "FlvMsg");
|
message = GetMessageText(module, description, "FlvMsg");
|
||||||
buttons = GetButtonsText(module, description, "FlvBtn");
|
buttons = GetButtonsText(module, description, "FlvBtn");
|
||||||
|
|
||||||
_horizon.Device.UIHandler.DisplayErrorAppletDialog($"Details: {module}-{description:0000}", "\n" + message, buttons);
|
_horizon.Device.UIHandler.DisplayErrorAppletDialog($"Details: {module}-{description:0000}", "\n" + message, buttons, errorCodeTuple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,10 +45,12 @@ namespace Ryujinx.HLE.UI
|
|||||||
/// <param name="value">The value associated to the <paramref name="kind"/>.</param>
|
/// <param name="value">The value associated to the <paramref name="kind"/>.</param>
|
||||||
void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value);
|
void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// Displays a Message Dialog box specific to Error Applet and blocks until it is closed.
|
/// Displays a Message Dialog box specific to Error Applet and blocks until it is closed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>False when OK is pressed, True when another button (Details) is pressed.</returns>
|
/// <returns>False when OK is pressed, True when another button (Details) is pressed.</returns>
|
||||||
bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText);
|
// ReSharper disable once UnusedParameter.Global
|
||||||
|
bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText, (uint Module, uint Description)? errorCode = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a handler to process keyboard inputs into text strings.
|
/// Creates a handler to process keyboard inputs into text strings.
|
||||||
|
|||||||
13
src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj
Normal file
13
src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
|
||||||
|
<PackageReference Include="Alimer.Bindings.SDL" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
85
src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs
Normal file
85
src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using SDL3;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using static SDL3.SDL3;
|
||||||
|
|
||||||
|
namespace Ryujinx.Input.SDL3
|
||||||
|
{
|
||||||
|
public unsafe class SDL3MotionDriver : IHandheld, IDisposable
|
||||||
|
{
|
||||||
|
private readonly Dictionary<SDL_SensorType, SDL_Sensor> sensors;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public SDL3MotionDriver()
|
||||||
|
{
|
||||||
|
int result = SDL_Init(SDL_InitFlags.Sensor);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"SDL sensor initialization failed: {SDL_GetError()}");
|
||||||
|
}
|
||||||
|
sensors = SDL_GetSensors().ToArray().ToDictionary(SDL_GetSensorTypeForID, SDL_OpenSensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
~SDL3MotionDriver()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disposing && sensors != null)
|
||||||
|
{
|
||||||
|
foreach (var sensor in sensors.Values)
|
||||||
|
{
|
||||||
|
if (sensor != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
SDL_CloseSensor(sensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 GetMotionData(MotionInputId inputType)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
return inputType switch
|
||||||
|
{
|
||||||
|
MotionInputId.Gyroscope => GetSensorVector(SDL_SensorType.Gyro) * 180 / MathF.PI,
|
||||||
|
MotionInputId.Accelerometer => GetSensorVector(SDL_SensorType.Accel) / SDL_STANDARD_GRAVITY,
|
||||||
|
_ => Vector3.Zero
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 GetSensorVector(SDL_SensorType sensorType)
|
||||||
|
{
|
||||||
|
if (!sensors.TryGetValue(sensorType, out SDL_Sensor sensor))
|
||||||
|
{
|
||||||
|
return Vector3.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = stackalloc float[3];
|
||||||
|
if (SDL_GetSensorData(sensor, data, 3) < 0)
|
||||||
|
{
|
||||||
|
return Vector3.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Vector3(data[0], data[1], data[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,13 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Input.HLE
|
namespace Ryujinx.Input.HLE
|
||||||
{
|
{
|
||||||
public class InputManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver)
|
public class InputManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IHandheld handheld)
|
||||||
: IDisposable
|
: IDisposable
|
||||||
{
|
{
|
||||||
public IGamepadDriver KeyboardDriver { get; } = keyboardDriver;
|
public IGamepadDriver KeyboardDriver { get; } = keyboardDriver;
|
||||||
public IGamepadDriver GamepadDriver { get; } = gamepadDriver;
|
public IGamepadDriver GamepadDriver { get; } = gamepadDriver;
|
||||||
public IGamepadDriver MouseDriver { get; private set; }
|
public IGamepadDriver MouseDriver { get; private set; }
|
||||||
|
public IHandheld Handheld { get; } = handheld;
|
||||||
|
|
||||||
public void SetMouseDriver(IGamepadDriver mouseDriver)
|
public void SetMouseDriver(IGamepadDriver mouseDriver)
|
||||||
{
|
{
|
||||||
@@ -18,7 +19,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
public NpadManager CreateNpadManager()
|
public NpadManager CreateNpadManager()
|
||||||
{
|
{
|
||||||
return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver);
|
return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver, Handheld);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TouchScreenManager CreateTouchScreenManager()
|
public TouchScreenManager CreateTouchScreenManager()
|
||||||
@@ -38,6 +39,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
KeyboardDriver?.Dispose();
|
KeyboardDriver?.Dispose();
|
||||||
GamepadDriver?.Dispose();
|
GamepadDriver?.Dispose();
|
||||||
MouseDriver?.Dispose();
|
MouseDriver?.Dispose();
|
||||||
|
Handheld?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,12 +218,14 @@ namespace Ryujinx.Input.HLE
|
|||||||
public string Id { get; private set; }
|
public string Id { get; private set; }
|
||||||
|
|
||||||
private readonly CemuHookClient _cemuHookClient;
|
private readonly CemuHookClient _cemuHookClient;
|
||||||
|
private readonly IHandheld _handheld;
|
||||||
|
|
||||||
public NpadController(CemuHookClient cemuHookClient)
|
public NpadController(CemuHookClient cemuHookClient, IHandheld handheld)
|
||||||
{
|
{
|
||||||
State = default;
|
State = default;
|
||||||
Id = null;
|
Id = null;
|
||||||
_cemuHookClient = cemuHookClient;
|
_cemuHookClient = cemuHookClient;
|
||||||
|
_handheld = handheld;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UpdateDriverConfiguration(IGamepadDriver gamepadDriver, InputConfig config)
|
public bool UpdateDriverConfiguration(IGamepadDriver gamepadDriver, InputConfig config)
|
||||||
@@ -287,6 +289,18 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion)
|
if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion)
|
||||||
{
|
{
|
||||||
|
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.Handheld)
|
||||||
|
{
|
||||||
|
Vector3 accelerometer = _handheld.GetMotionData(MotionInputId.Accelerometer);
|
||||||
|
Vector3 gyroscope = _handheld.GetMotionData(MotionInputId.Gyroscope);
|
||||||
|
|
||||||
|
accelerometer = new Vector3(accelerometer.X, -accelerometer.Z, accelerometer.Y);
|
||||||
|
gyroscope = new Vector3(gyroscope.X, -gyroscope.Z, gyroscope.Y);
|
||||||
|
|
||||||
|
_leftMotionInput.Update(accelerometer, gyroscope, (ulong)PerformanceCounter.ElapsedNanoseconds / 1000, controllerConfig.Motion.Sensitivity, (float)controllerConfig.Motion.GyroDeadzone);
|
||||||
|
_rightMotionInput = _leftMotionInput;
|
||||||
|
}
|
||||||
|
|
||||||
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver)
|
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver)
|
||||||
{
|
{
|
||||||
if (gamepad.Features.HasFlag(GamepadFeaturesFlag.Motion))
|
if (gamepad.Features.HasFlag(GamepadFeaturesFlag.Motion))
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
private readonly IGamepadDriver _keyboardDriver;
|
private readonly IGamepadDriver _keyboardDriver;
|
||||||
private readonly IGamepadDriver _gamepadDriver;
|
private readonly IGamepadDriver _gamepadDriver;
|
||||||
private readonly IGamepadDriver _mouseDriver;
|
private readonly IGamepadDriver _mouseDriver;
|
||||||
|
private readonly IHandheld _handheld;
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
private List<InputConfig> _inputConfig;
|
private List<InputConfig> _inputConfig;
|
||||||
@@ -38,7 +39,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
private bool _enableMouse;
|
private bool _enableMouse;
|
||||||
private Switch _device;
|
private Switch _device;
|
||||||
|
|
||||||
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
|
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver, IHandheld handheld)
|
||||||
{
|
{
|
||||||
_controllers = new NpadController[MaxControllers];
|
_controllers = new NpadController[MaxControllers];
|
||||||
_cemuHookClient = new CemuHookClient(this);
|
_cemuHookClient = new CemuHookClient(this);
|
||||||
@@ -47,6 +48,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
_gamepadDriver = gamepadDriver;
|
_gamepadDriver = gamepadDriver;
|
||||||
_mouseDriver = mouseDriver;
|
_mouseDriver = mouseDriver;
|
||||||
_inputConfig = [];
|
_inputConfig = [];
|
||||||
|
_handheld = handheld;
|
||||||
|
|
||||||
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
@@ -139,7 +141,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
controller = new(_cemuHookClient);
|
controller = new(_cemuHookClient, _handheld);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
|
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
|
||||||
@@ -185,6 +187,15 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool InputUpdatesBlocked
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
return _blockInputUpdates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void BlockInputUpdates()
|
public void BlockInputUpdates()
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
|
|||||||
10
src/Ryujinx.Input/IHandheld.cs
Normal file
10
src/Ryujinx.Input/IHandheld.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Input
|
||||||
|
{
|
||||||
|
public interface IHandheld : IDisposable
|
||||||
|
{
|
||||||
|
Vector3 GetMotionData(MotionInputId gyroscope);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -517,7 +517,7 @@ namespace Ryujinx.Ava
|
|||||||
Device?.System.ChangeDockedModeState(e.NewValue);
|
Device?.System.ChangeDockedModeState(e.NewValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
|
public void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
|
||||||
{
|
{
|
||||||
Device?.SetVolume(e.NewValue);
|
Device?.SetVolume(e.NewValue);
|
||||||
|
|
||||||
@@ -1041,6 +1041,7 @@ namespace Ryujinx.Ava
|
|||||||
if (_viewModel.StartGamesInFullscreen)
|
if (_viewModel.StartGamesInFullscreen)
|
||||||
{
|
{
|
||||||
_viewModel.WindowState = WindowState.FullScreen;
|
_viewModel.WindowState = WindowState.FullScreen;
|
||||||
|
_viewModel.Window.TitleBar.ExtendsContentIntoTitleBar = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_viewModel.WindowState is WindowState.FullScreen || _viewModel.StartGamesWithoutUI)
|
if (_viewModel.WindowState is WindowState.FullScreen || _viewModel.StartGamesWithoutUI)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Common
|
|
||||||
{
|
|
||||||
public static class ThemeManager
|
|
||||||
{
|
|
||||||
public static event Action ThemeChanged;
|
|
||||||
|
|
||||||
public static void OnThemeChanged()
|
|
||||||
{
|
|
||||||
ThemeChanged?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,6 +23,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.SDL2;
|
using Ryujinx.Input.SDL2;
|
||||||
|
using Ryujinx.Input.SDL3;
|
||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -182,7 +183,7 @@ namespace Ryujinx.Headless
|
|||||||
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile);
|
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile);
|
||||||
_userChannelPersistence = new UserChannelPersistence();
|
_userChannelPersistence = new UserChannelPersistence();
|
||||||
|
|
||||||
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver(), new SDL3MotionDriver());
|
||||||
|
|
||||||
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
|
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
|
||||||
|
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ namespace Ryujinx.Headless
|
|||||||
Exit();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText)
|
public bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText, (uint Module, uint Description)? errorCode = null)
|
||||||
{
|
{
|
||||||
SDL_MessageBoxData data = new()
|
SDL_MessageBoxData data = new()
|
||||||
{
|
{
|
||||||
@@ -521,7 +521,7 @@ namespace Ryujinx.Headless
|
|||||||
message = message,
|
message = message,
|
||||||
buttons = new SDL_MessageBoxButtonData[buttonsText.Length],
|
buttons = new SDL_MessageBoxButtonData[buttonsText.Length],
|
||||||
numbuttons = buttonsText.Length,
|
numbuttons = buttonsText.Length,
|
||||||
window = WindowHandle,
|
window = WindowHandle
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < buttonsText.Length; i++)
|
for (int i = 0; i < buttonsText.Length; i++)
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
<ProjectReference Include="..\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
|
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
|
<ProjectReference Include="..\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
|
||||||
|
<ProjectReference Include="..\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj" />
|
<ProjectReference Include="..\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj" />
|
<ProjectReference Include="..\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ namespace Ryujinx.Ava
|
|||||||
{
|
{
|
||||||
public class RyujinxApp : Application
|
public class RyujinxApp : Application
|
||||||
{
|
{
|
||||||
|
public static event Action ThemeChanged;
|
||||||
|
|
||||||
internal static string FormatTitle(LocaleKeys? windowTitleKey = null, bool includeVersion = true)
|
internal static string FormatTitle(LocaleKeys? windowTitleKey = null, bool includeVersion = true)
|
||||||
=> windowTitleKey is null
|
=> windowTitleKey is null
|
||||||
? $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)}"
|
? $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)}"
|
||||||
@@ -112,7 +114,7 @@ namespace Ryujinx.Ava
|
|||||||
baseStyle = ConfigurationState.Instance.UI.BaseStyle;
|
baseStyle = ConfigurationState.Instance.UI.BaseStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeManager.OnThemeChanged();
|
ThemeChanged?.Invoke();
|
||||||
|
|
||||||
RequestedThemeVariant = baseStyle switch
|
RequestedThemeVariant = baseStyle switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,31 +75,32 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
bool opened = false;
|
bool opened = false;
|
||||||
|
|
||||||
UserResult response = await ContentDialogHelper.ShowDeferredContentDialog(_parent,
|
UserResult response = await ContentDialogHelper.ShowDeferredContentDialog(_parent,
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
string.Empty,
|
string.Empty,
|
||||||
LocaleManager.Instance[LocaleKeys.DialogOpenSettingsWindowLabel],
|
LocaleManager.Instance[LocaleKeys.DialogOpenSettingsWindowLabel],
|
||||||
string.Empty,
|
string.Empty,
|
||||||
LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
||||||
(int)Symbol.Important,
|
(int)Symbol.Important,
|
||||||
deferEvent,
|
deferEvent,
|
||||||
async window =>
|
async window =>
|
||||||
{
|
{
|
||||||
if (opened)
|
if (opened)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
opened = true;
|
opened = true;
|
||||||
|
|
||||||
_parent.SettingsWindow = new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
_parent.SettingsWindow =
|
||||||
|
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
||||||
|
|
||||||
await _parent.SettingsWindow.ShowDialog(window);
|
await _parent.SettingsWindow.ShowDialog(window);
|
||||||
|
|
||||||
_parent.SettingsWindow = null;
|
_parent.SettingsWindow = null;
|
||||||
|
|
||||||
opened = false;
|
opened = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response == UserResult.Ok)
|
if (response == UserResult.Ok)
|
||||||
{
|
{
|
||||||
@@ -110,7 +111,9 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageDialogErrorExceptionMessage, ex));
|
await ContentDialogHelper.CreateErrorDialog(
|
||||||
|
LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||||
|
LocaleKeys.DialogMessageDialogErrorExceptionMessage, ex));
|
||||||
|
|
||||||
dialogCloseEvent.Set();
|
dialogCloseEvent.Set();
|
||||||
}
|
}
|
||||||
@@ -134,7 +137,9 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||||
(UserResult result, string userInput) = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
|
(UserResult result, string userInput) =
|
||||||
|
await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard],
|
||||||
|
args);
|
||||||
|
|
||||||
if (result == UserResult.Ok)
|
if (result == UserResult.Ok)
|
||||||
{
|
{
|
||||||
@@ -146,7 +151,9 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
|
|
||||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage, ex));
|
await ContentDialogHelper.CreateErrorDialog(
|
||||||
|
LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||||
|
LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage, ex));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -177,7 +184,8 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
args.InitialText = "Ryujinx";
|
args.InitialText = "Ryujinx";
|
||||||
args.StringLengthMin = 1;
|
args.StringLengthMin = 1;
|
||||||
args.StringLengthMax = 25;
|
args.StringLengthMax = 25;
|
||||||
(UserResult result, string userInput) = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args);
|
(UserResult result, string userInput) =
|
||||||
|
await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args);
|
||||||
if (result == UserResult.Ok)
|
if (result == UserResult.Ok)
|
||||||
{
|
{
|
||||||
inputText = userInput;
|
inputText = userInput;
|
||||||
@@ -201,11 +209,13 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
{
|
{
|
||||||
dialogCloseEvent.Set();
|
dialogCloseEvent.Set();
|
||||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.CabinetScanDialog],
|
await ContentDialogHelper.CreateInfoDialog(
|
||||||
string.Empty,
|
LocaleManager.Instance[LocaleKeys.CabinetScanDialog],
|
||||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
string.Empty,
|
||||||
string.Empty,
|
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||||
LocaleManager.Instance[LocaleKeys.CabinetTitle]);
|
string.Empty,
|
||||||
|
LocaleManager.Instance[LocaleKeys.CabinetTitle]
|
||||||
|
);
|
||||||
});
|
});
|
||||||
dialogCloseEvent.WaitOne();
|
dialogCloseEvent.WaitOne();
|
||||||
}
|
}
|
||||||
@@ -217,7 +227,8 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
_parent.ViewModel.AppHost?.Stop();
|
_parent.ViewModel.AppHost?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
|
public bool DisplayErrorAppletDialog(string title, string message, string[] buttons,
|
||||||
|
(uint Module, uint Description)? errorCode = null)
|
||||||
{
|
{
|
||||||
ManualResetEvent dialogCloseEvent = new(false);
|
ManualResetEvent dialogCloseEvent = new(false);
|
||||||
|
|
||||||
@@ -229,9 +240,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
{
|
{
|
||||||
ErrorAppletWindow msgDialog = new(_parent, buttons, message)
|
ErrorAppletWindow msgDialog = new(_parent, buttons, message)
|
||||||
{
|
{
|
||||||
Title = title,
|
Title = title, WindowStartupLocation = WindowStartupLocation.CenterScreen, Width = 400
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
|
||||||
Width = 400
|
|
||||||
};
|
};
|
||||||
|
|
||||||
object response = await msgDialog.Run();
|
object response = await msgDialog.Run();
|
||||||
@@ -249,7 +258,9 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
{
|
{
|
||||||
dialogCloseEvent.Set();
|
dialogCloseEvent.Set();
|
||||||
|
|
||||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogErrorAppletErrorExceptionMessage, ex));
|
await ContentDialogHelper.CreateErrorDialog(
|
||||||
|
LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||||
|
LocaleKeys.DialogErrorAppletErrorExceptionMessage, ex));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -259,38 +270,36 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IDynamicTextInputHandler CreateDynamicTextInputHandler() => new AvaloniaDynamicTextInputHandler(_parent);
|
public IDynamicTextInputHandler CreateDynamicTextInputHandler() => new AvaloniaDynamicTextInputHandler(_parent);
|
||||||
|
|
||||||
public UserProfile ShowPlayerSelectDialog()
|
public UserProfile ShowPlayerSelectDialog()
|
||||||
{
|
{
|
||||||
UserId selected = UserId.Null;
|
UserId selected = UserId.Null;
|
||||||
byte[] defaultGuestImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/GuestUserImage.jpg");
|
byte[] defaultGuestImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/GuestUserImage.jpg");
|
||||||
UserProfile guest = new(new UserId("00000000000000000000000000000080"), "Guest", defaultGuestImage);
|
UserProfile guest = new(new UserId("00000000000000000000000000000080"), "Guest", defaultGuestImage);
|
||||||
|
|
||||||
ManualResetEvent dialogCloseEvent = new(false);
|
ManualResetEvent dialogCloseEvent = new(false);
|
||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
{
|
{
|
||||||
ObservableCollection<BaseModel> profiles = [];
|
ObservableCollection<BaseModel> profiles = [];
|
||||||
NavigationDialogHost nav = new();
|
NavigationDialogHost nav = new();
|
||||||
|
|
||||||
_parent.AccountManager.GetAllUsers()
|
_parent.AccountManager.GetAllUsers()
|
||||||
.OrderBy(x => x.Name)
|
.OrderBy(x => x.Name)
|
||||||
.ForEach(profile => profiles.Add(new Models.UserProfile(profile, nav)));
|
.ForEach(profile => profiles.Add(new Models.UserProfile(profile, nav)));
|
||||||
|
|
||||||
profiles.Add(new Models.UserProfile(guest, nav));
|
profiles.Add(new Models.UserProfile(guest, nav));
|
||||||
UserSelectorDialogViewModel viewModel = new()
|
ProfileSelectorDialogViewModel viewModel = new()
|
||||||
{
|
{
|
||||||
Profiles = profiles,
|
Profiles = profiles, SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
|
||||||
SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
|
|
||||||
};
|
};
|
||||||
UserSelectorDialog content = new(viewModel);
|
(selected, _) = await ProfileSelectorDialog.ShowInputDialog(viewModel);
|
||||||
(selected, _) = await UserSelectorDialog.ShowInputDialog(content);
|
|
||||||
|
|
||||||
dialogCloseEvent.Set();
|
dialogCloseEvent.Set();
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogCloseEvent.WaitOne();
|
dialogCloseEvent.WaitOne();
|
||||||
|
|
||||||
UserProfile profile = _parent.AccountManager.LastOpenedUser;
|
UserProfile profile = _parent.AccountManager.LastOpenedUser;
|
||||||
if (selected == guest.UserId)
|
if (selected == guest.UserId)
|
||||||
{
|
{
|
||||||
@@ -311,6 +320,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
x:Class="Ryujinx.Ava.UI.Applet.UserSelectorDialog"
|
x:Class="Ryujinx.Ava.UI.Applet.ProfileSelectorDialog"
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Focusable="True"
|
Focusable="True"
|
||||||
x:DataType="viewModels:UserSelectorDialogViewModel">
|
x:DataType="viewModels:ProfileSelectorDialogViewModel">
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
<viewModels:UserSelectorDialogViewModel />
|
<viewModels:ProfileSelectorDialogViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
@@ -16,15 +16,15 @@ using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
|||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Applet
|
namespace Ryujinx.Ava.UI.Applet
|
||||||
{
|
{
|
||||||
public partial class UserSelectorDialog : UserControl, INotifyPropertyChanged
|
public partial class ProfileSelectorDialog : UserControl
|
||||||
{
|
{
|
||||||
public UserSelectorDialogViewModel ViewModel { get; set; }
|
public ProfileSelectorDialogViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
public UserSelectorDialog(UserSelectorDialogViewModel viewModel)
|
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
|
||||||
{
|
{
|
||||||
|
DataContext = ViewModel = viewModel;
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ViewModel = viewModel;
|
|
||||||
DataContext = ViewModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Grid_PointerEntered(object sender, PointerEventArgs e)
|
private void Grid_PointerEntered(object sender, PointerEventArgs e)
|
||||||
@@ -54,7 +54,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
if (ViewModel.Profiles[selectedIndex] is UserProfile userProfile)
|
if (ViewModel.Profiles[selectedIndex] is UserProfile userProfile)
|
||||||
{
|
{
|
||||||
ViewModel.SelectedUserId = userProfile.UserId;
|
ViewModel.SelectedUserId = userProfile.UserId;
|
||||||
Logger.Info?.Print(LogClass.UI, $"Selected user: {userProfile.UserId}");
|
Logger.Info?.Print(LogClass.UI, $"Selected: {userProfile.UserId}", "ProfileSelector");
|
||||||
|
|
||||||
ObservableCollection<BaseModel> newProfiles = [];
|
ObservableCollection<BaseModel> newProfiles = [];
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<(UserId Id, bool Result)> ShowInputDialog(UserSelectorDialog content)
|
public static async Task<(UserId Id, bool Result)> ShowInputDialog(ProfileSelectorDialogViewModel viewModel)
|
||||||
{
|
{
|
||||||
ContentDialog contentDialog = new()
|
ContentDialog contentDialog = new()
|
||||||
{
|
{
|
||||||
@@ -87,22 +87,25 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.Continue],
|
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.Continue],
|
||||||
SecondaryButtonText = string.Empty,
|
SecondaryButtonText = string.Empty,
|
||||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.Cancel],
|
CloseButtonText = LocaleManager.Instance[LocaleKeys.Cancel],
|
||||||
Content = content,
|
Content = new ProfileSelectorDialog(viewModel),
|
||||||
Padding = new Thickness(0)
|
Padding = new Thickness(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
UserId result = UserId.Null;
|
UserId result = UserId.Null;
|
||||||
bool input = false;
|
bool input = false;
|
||||||
|
|
||||||
|
contentDialog.Closed += Handler;
|
||||||
|
|
||||||
|
await ContentDialogHelper.ShowAsync(contentDialog);
|
||||||
|
|
||||||
|
return (result, input);
|
||||||
|
|
||||||
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
|
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (eventArgs.Result == ContentDialogResult.Primary)
|
if (eventArgs.Result == ContentDialogResult.Primary)
|
||||||
{
|
{
|
||||||
if (contentDialog.Content is UserSelectorDialog view)
|
result = viewModel.SelectedUserId;
|
||||||
{
|
input = true;
|
||||||
result = view.ViewModel.SelectedUserId;
|
|
||||||
input = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -110,12 +113,6 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
input = false;
|
input = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentDialog.Closed += Handler;
|
|
||||||
|
|
||||||
await ContentDialogHelper.ShowAsync(contentDialog);
|
|
||||||
|
|
||||||
return (result, input);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
public partial class GamepadInputConfig : BaseModel
|
public partial class GamepadInputConfig : BaseModel
|
||||||
{
|
{
|
||||||
public bool EnableCemuHookMotion { get; set; }
|
public bool EnableCemuHookMotion { get; set; }
|
||||||
|
public bool EnableHandheldMotion { get; set; }
|
||||||
public string DsuServerHost { get; set; }
|
public string DsuServerHost { get; set; }
|
||||||
public int DsuServerPort { get; set; }
|
public int DsuServerPort { get; set; }
|
||||||
public int Slot { get; set; }
|
public int Slot { get; set; }
|
||||||
@@ -162,7 +163,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
EnableMotion = controllerInput.Motion.EnableMotion;
|
EnableMotion = controllerInput.Motion.EnableMotion;
|
||||||
GyroDeadzone = controllerInput.Motion.GyroDeadzone;
|
GyroDeadzone = controllerInput.Motion.GyroDeadzone;
|
||||||
Sensitivity = controllerInput.Motion.Sensitivity;
|
Sensitivity = controllerInput.Motion.Sensitivity;
|
||||||
|
EnableHandheldMotion = controllerInput.Motion.MotionBackend == MotionInputBackendType.Handheld;
|
||||||
if (controllerInput.Motion is CemuHookMotionConfigController cemuHook)
|
if (controllerInput.Motion is CemuHookMotionConfigController cemuHook)
|
||||||
{
|
{
|
||||||
EnableCemuHookMotion = true;
|
EnableCemuHookMotion = true;
|
||||||
@@ -285,7 +286,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
config.Motion = new StandardMotionConfigController
|
config.Motion = new StandardMotionConfigController
|
||||||
{
|
{
|
||||||
EnableMotion = EnableMotion,
|
EnableMotion = EnableMotion,
|
||||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
MotionBackend = EnableHandheldMotion ? MotionInputBackendType.Handheld : MotionInputBackendType.GamepadDriver,
|
||||||
GyroDeadzone = GyroDeadzone,
|
GyroDeadzone = GyroDeadzone,
|
||||||
Sensitivity = Sensitivity,
|
Sensitivity = Sensitivity,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Avalonia.Media.Imaging;
|
|||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common;
|
using Ryujinx.Ava.Common;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
@@ -24,30 +25,35 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
Version = RyujinxApp.FullAppName + "\n" + Program.Version;
|
Version = RyujinxApp.FullAppName + "\n" + Program.Version;
|
||||||
UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
|
UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
|
||||||
|
|
||||||
ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
|
RyujinxApp.ThemeChanged += Ryujinx_ThemeChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThemeManager_ThemeChanged()
|
private void Ryujinx_ThemeChanged()
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() => UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value));
|
Dispatcher.UIThread.Post(() => UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string LogoPathFormat = "resm:Ryujinx.Assets.UIImages.Logo_{0}_{1}.png?assembly=Ryujinx";
|
||||||
|
|
||||||
private void UpdateLogoTheme(string theme)
|
private void UpdateLogoTheme(string theme)
|
||||||
{
|
{
|
||||||
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
|
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
|
||||||
|
|
||||||
|
string themeName = isDarkTheme ? "Dark" : "Light";
|
||||||
|
|
||||||
string basePath = "resm:Ryujinx.Assets.UIImages.";
|
GithubLogo = LoadBitmap(LogoPathFormat.Format("GitHub", themeName));
|
||||||
string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
|
DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName));
|
||||||
|
|
||||||
GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx");
|
|
||||||
DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));
|
private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
ThemeManager.ThemeChanged -= ThemeManager_ThemeChanged;
|
RyujinxApp.ThemeChanged -= Ryujinx_ThemeChanged;
|
||||||
|
|
||||||
|
GithubLogo.Dispose();
|
||||||
|
DiscordLogo.Dispose();
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
|
Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
|
||||||
|
|
||||||
// Neither local or remote files are valid JSON, close window.
|
// Neither local or remote files are valid JSON, close window.
|
||||||
ShowInfoDialog();
|
await ShowInfoDialog();
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
else if (!remoteIsValid)
|
else if (!remoteIsValid)
|
||||||
@@ -273,7 +273,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
// Only the local file is valid, the local one should be used
|
// Only the local file is valid, the local one should be used
|
||||||
// but the user should be warned.
|
// but the user should be warned.
|
||||||
ShowInfoDialog();
|
await ShowInfoDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +525,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
AmiiboImage = bitmap;
|
AmiiboImage = bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async void ShowInfoDialog()
|
private static async Task ShowInfoDialog()
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
|
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
|
||||||
LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage],
|
LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage],
|
||||||
|
|||||||
@@ -18,6 +18,34 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
[ObservableProperty] private double _gyroDeadzone;
|
[ObservableProperty] private double _gyroDeadzone;
|
||||||
|
|
||||||
[ObservableProperty] private bool _enableCemuHookMotion;
|
private bool _enableCemuHookMotion;
|
||||||
|
public bool EnableCemuHookMotion
|
||||||
|
{
|
||||||
|
get => _enableCemuHookMotion;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
EnableHandheldMotion = false;
|
||||||
|
}
|
||||||
|
_enableCemuHookMotion = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _enableHandheldMotion;
|
||||||
|
public bool EnableHandheldMotion
|
||||||
|
{
|
||||||
|
get => _enableHandheldMotion;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
EnableCemuHookMotion = false;
|
||||||
|
}
|
||||||
|
_enableHandheldMotion = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Avalonia.Media.Imaging;
|
|||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Binding;
|
using DynamicData.Binding;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
@@ -104,6 +105,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
[ObservableProperty] private bool _isSubMenuOpen;
|
[ObservableProperty] private bool _isSubMenuOpen;
|
||||||
[ObservableProperty] private ApplicationContextMenu _listAppContextMenu;
|
[ObservableProperty] private ApplicationContextMenu _listAppContextMenu;
|
||||||
[ObservableProperty] private ApplicationContextMenu _gridAppContextMenu;
|
[ObservableProperty] private ApplicationContextMenu _gridAppContextMenu;
|
||||||
|
[ObservableProperty] private bool _updateAvailable;
|
||||||
|
|
||||||
|
public static AsyncRelayCommand UpdateCommand { get; } = Commands.Create(async () =>
|
||||||
|
{
|
||||||
|
if (Updater.CanUpdate(true))
|
||||||
|
await Updater.BeginUpdateAsync(true);
|
||||||
|
});
|
||||||
|
|
||||||
private bool _showLoadProgress;
|
private bool _showLoadProgress;
|
||||||
private bool _isGameRunning;
|
private bool _isGameRunning;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
|
|||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
public partial class UserSelectorDialogViewModel : BaseModel
|
public partial class ProfileSelectorDialogViewModel : BaseModel
|
||||||
{
|
{
|
||||||
|
|
||||||
[ObservableProperty] private UserId _selectedUserId;
|
[ObservableProperty] private UserId _selectedUserId;
|
||||||
@@ -126,6 +126,10 @@ 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 DisableInputWhenOutOfFocus { get; set; }
|
||||||
|
|
||||||
|
public int FocusLostActionType { get; set; }
|
||||||
|
|
||||||
public VSyncMode VSyncMode
|
public VSyncMode VSyncMode
|
||||||
{
|
{
|
||||||
get => _vSyncMode;
|
get => _vSyncMode;
|
||||||
@@ -479,6 +483,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
ShowTitleBar = config.ShowTitleBar;
|
ShowTitleBar = config.ShowTitleBar;
|
||||||
HideCursor = (int)config.HideCursor.Value;
|
HideCursor = (int)config.HideCursor.Value;
|
||||||
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
||||||
|
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
||||||
|
|
||||||
GameDirectories.Clear();
|
GameDirectories.Clear();
|
||||||
GameDirectories.AddRange(config.UI.GameDirs.Value);
|
GameDirectories.AddRange(config.UI.GameDirs.Value);
|
||||||
@@ -498,6 +503,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;
|
||||||
|
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
||||||
|
|
||||||
// Keyboard Hotkeys
|
// Keyboard Hotkeys
|
||||||
KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value);
|
KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value);
|
||||||
@@ -586,6 +592,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.ShowTitleBar.Value = ShowTitleBar;
|
config.ShowTitleBar.Value = ShowTitleBar;
|
||||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||||
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
||||||
|
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
||||||
|
|
||||||
if (GameDirectoryChanged)
|
if (GameDirectoryChanged)
|
||||||
{
|
{
|
||||||
@@ -609,6 +616,7 @@ 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;
|
||||||
|
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
||||||
|
|
||||||
// Keyboard Hotkeys
|
// Keyboard Hotkeys
|
||||||
config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig();
|
config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig();
|
||||||
|
|||||||
@@ -61,6 +61,17 @@
|
|||||||
Margin="5, 0"
|
Margin="5, 0"
|
||||||
Text="{Binding GyroDeadzone, StringFormat=\{0:0.00\}}" />
|
Text="{Binding GyroDeadzone, StringFormat=\{0:0.00\}}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<Separator
|
||||||
|
Height="1"
|
||||||
|
Margin="0,5" />
|
||||||
|
<CheckBox
|
||||||
|
Margin="5"
|
||||||
|
IsChecked="{Binding EnableHandheldMotion}">
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,3,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{ext:Locale ControllerSettingsMotionUseHandheldCompatibleMotion}" />
|
||||||
|
</CheckBox>
|
||||||
<Separator
|
<Separator
|
||||||
Height="1"
|
Height="1"
|
||||||
Margin="0,5" />
|
Margin="0,5" />
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||||||
Sensitivity = config.Sensitivity,
|
Sensitivity = config.Sensitivity,
|
||||||
GyroDeadzone = config.GyroDeadzone,
|
GyroDeadzone = config.GyroDeadzone,
|
||||||
EnableCemuHookMotion = config.EnableCemuHookMotion,
|
EnableCemuHookMotion = config.EnableCemuHookMotion,
|
||||||
|
EnableHandheldMotion = config.EnableHandheldMotion,
|
||||||
};
|
};
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -58,6 +59,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||||||
config.DsuServerHost = content._viewModel.DsuServerHost;
|
config.DsuServerHost = content._viewModel.DsuServerHost;
|
||||||
config.DsuServerPort = content._viewModel.DsuServerPort;
|
config.DsuServerPort = content._viewModel.DsuServerPort;
|
||||||
config.EnableCemuHookMotion = content._viewModel.EnableCemuHookMotion;
|
config.EnableCemuHookMotion = content._viewModel.EnableCemuHookMotion;
|
||||||
|
config.EnableHandheldMotion = content._viewModel.EnableHandheldMotion;
|
||||||
config.MirrorInput = content._viewModel.MirrorInput;
|
config.MirrorInput = content._viewModel.MirrorInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,12 +51,8 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
XciTrimmerMenuItem.Command = Commands.Create(XCITrimmerWindow.Show);
|
XciTrimmerMenuItem.Command = Commands.Create(XCITrimmerWindow.Show);
|
||||||
AboutWindowMenuItem.Command = Commands.Create(AboutWindow.Show);
|
AboutWindowMenuItem.Command = Commands.Create(AboutWindow.Show);
|
||||||
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityList.Show());
|
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityList.Show());
|
||||||
|
|
||||||
UpdateMenuItem.Command = Commands.Create(async () =>
|
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;
|
||||||
{
|
|
||||||
if (Updater.CanUpdate(true))
|
|
||||||
await Updater.BeginUpdateAsync(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
FaqMenuItem.Command =
|
FaqMenuItem.Command =
|
||||||
SetupGuideMenuItem.Command =
|
SetupGuideMenuItem.Command =
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
Background="{DynamicResource ThemeContentBackgroundColor}"
|
Background="{DynamicResource ThemeContentBackgroundColor}"
|
||||||
DockPanel.Dock="Bottom"
|
DockPanel.Dock="Bottom"
|
||||||
IsVisible="{Binding ShowMenuAndStatusBar}"
|
IsVisible="{Binding ShowMenuAndStatusBar}"
|
||||||
ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
ColumnDefinitions="Auto,Auto,*,Auto,Auto,Auto">
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="5"
|
Margin="5"
|
||||||
@@ -280,9 +280,31 @@
|
|||||||
Text="{Binding GpuNameText}"
|
Text="{Binding GpuNameText}"
|
||||||
TextAlignment="Start" />
|
TextAlignment="Start" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="4"
|
Grid.Column="4"
|
||||||
Margin="0,0,5,0"
|
Margin="0,0,5,0"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<StackPanel.IsVisible>
|
||||||
|
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||||
|
<Binding Path="EnableNonGameRunningControls" />
|
||||||
|
<Binding Path="UpdateAvailable" />
|
||||||
|
</MultiBinding>
|
||||||
|
</StackPanel.IsVisible>
|
||||||
|
<Button Margin="0, 0, 5, -2"
|
||||||
|
Command="{Binding UpdateCommand}"
|
||||||
|
Background="{DynamicResource SystemAccentColor}">
|
||||||
|
<TextBlock
|
||||||
|
Margin="-5"
|
||||||
|
Foreground="{StaticResource SystemColorButtonTextColor}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{ext:Locale UpdaterBackgroundStatusBarButtonText}" />
|
||||||
|
</Button>
|
||||||
|
<controls:MiniVerticalSeparator Margin="5,0,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel
|
||||||
|
Grid.Column="5"
|
||||||
|
Margin="0,0,5,0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
IsVisible="{Binding ShowFirmwareStatus}"
|
IsVisible="{Binding ShowFirmwareStatus}"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
|
|||||||
@@ -40,6 +40,30 @@
|
|||||||
<CheckBox IsChecked="{Binding ShowTitleBar}" IsVisible="{x:Static helper:RunningPlatform.IsWindows}">
|
<CheckBox IsChecked="{Binding ShowTitleBar}" IsVisible="{x:Static helper:RunningPlatform.IsWindows}">
|
||||||
<TextBlock Text="{ext:Locale SettingsTabGeneralShowTitleBar}" />
|
<TextBlock Text="{ext:Locale SettingsTabGeneralShowTitleBar}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
|
||||||
|
<TextBlock VerticalAlignment="Center"
|
||||||
|
Text="{ext:Locale SettingsTabGeneralFocusLossType}"
|
||||||
|
Width="150" />
|
||||||
|
<ComboBox SelectedIndex="{Binding FocusLostActionType}"
|
||||||
|
HorizontalContentAlignment="Left"
|
||||||
|
MinWidth="100">
|
||||||
|
<ComboBoxItem>
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeDoNothing}" />
|
||||||
|
</ComboBoxItem>
|
||||||
|
<ComboBoxItem>
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeBlockInput}" />
|
||||||
|
</ComboBoxItem>
|
||||||
|
<ComboBoxItem>
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeMuteAudio}" />
|
||||||
|
</ComboBoxItem>
|
||||||
|
<ComboBoxItem>
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeBlockInputAndMuteAudio}" />
|
||||||
|
</ComboBoxItem>
|
||||||
|
<ComboBoxItem>
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypePauseEmulation}" />
|
||||||
|
</ComboBoxItem>
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
<StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
|
<StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
|
||||||
<TextBlock VerticalAlignment="Center"
|
<TextBlock VerticalAlignment="Center"
|
||||||
Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunch}"
|
Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunch}"
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
Click="Button_OnClick"
|
Click="Button_OnClick"
|
||||||
CornerRadius="15"
|
CornerRadius="15"
|
||||||
Tag="https://discord.gg/dHPrkBkkyA"
|
Tag="https://discord.gg/PEuzjrFXUA"
|
||||||
ToolTip.Tip="{ext:Locale AboutDiscordUrlTooltipMessage}">
|
ToolTip.Tip="{ext:Locale AboutDiscordUrlTooltipMessage}">
|
||||||
<Image Source="{Binding DiscordLogo}" />
|
<Image Source="{Binding DiscordLogo}" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -142,42 +142,40 @@
|
|||||||
<Grid
|
<Grid
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch" RowDefinitions="Auto,Auto">
|
VerticalAlignment="Stretch" RowDefinitions="Auto,Auto,Auto">
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Margin="0,10,0,0"
|
|
||||||
Spacing="2">
|
Spacing="2">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
FontSize="15"
|
Classes="h1"
|
||||||
FontWeight="Bold"
|
FontWeight="Bold"
|
||||||
Text="{ext:Locale AboutRyujinxAboutTitle}" />
|
Text="{ext:Locale AboutRyujinxAboutTitle}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
FontSize="10"
|
|
||||||
Text="{ext:Locale AboutRyujinxAboutContent}"
|
Text="{ext:Locale AboutRyujinxAboutContent}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<Separator Grid.Row="1" Margin="0,20" />
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="1"
|
Grid.Row="2"
|
||||||
Margin="0,10,0,0"
|
|
||||||
Spacing="2">
|
Spacing="2">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
FontSize="15"
|
Classes="h1"
|
||||||
FontWeight="Bold"
|
FontWeight="Bold"
|
||||||
Text="{ext:Locale AboutRyujinxMaintainersTitle}" />
|
Text="{ext:Locale AboutRyujinxMaintainersTitle}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
FontSize="10"
|
|
||||||
Margin="0, 0, 0, 5"
|
Margin="0, 0, 0, 5"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
Text="{Binding Developers}"/>
|
Text="{Binding Developers}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
FontSize="15"
|
Classes="h1"
|
||||||
FontWeight="Bold"
|
FontWeight="Bold"
|
||||||
Text="{ext:Locale AboutRyujinxFormerMaintainersTitle}" />
|
Text="{ext:Locale AboutRyujinxFormerMaintainersTitle}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
FontSize="10"
|
FontSize="11"
|
||||||
Text="{Binding FormerDevelopers}"
|
Text="{Binding FormerDevelopers}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
<Button
|
<Button
|
||||||
|
Margin="0, 5, 0, 0"
|
||||||
Padding="5"
|
Padding="5"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
{
|
{
|
||||||
public AboutWindow()
|
public AboutWindow()
|
||||||
{
|
{
|
||||||
DataContext = new AboutWindowViewModel();
|
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
GitHubRepoButton.Tag =
|
GitHubRepoButton.Tag =
|
||||||
@@ -28,12 +26,14 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
public static async Task Show()
|
public static async Task Show()
|
||||||
{
|
{
|
||||||
|
using AboutWindowViewModel viewModel = new();
|
||||||
|
|
||||||
ContentDialog contentDialog = new()
|
ContentDialog contentDialog = new()
|
||||||
{
|
{
|
||||||
PrimaryButtonText = string.Empty,
|
PrimaryButtonText = string.Empty,
|
||||||
SecondaryButtonText = string.Empty,
|
SecondaryButtonText = string.Empty,
|
||||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
|
CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
|
||||||
Content = new AboutWindow()
|
Content = new AboutWindow { DataContext = viewModel }
|
||||||
};
|
};
|
||||||
|
|
||||||
Style closeButton = new(x => x.Name("CloseButton"));
|
Style closeButton = new(x => x.Name("CloseButton"));
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
x:DataType="viewModels:MainWindowViewModel"
|
x:DataType="viewModels:MainWindowViewModel"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
WindowStartupLocation="Manual"
|
WindowStartupLocation="Manual"
|
||||||
Focusable="True">
|
Focusable="True"
|
||||||
|
GotFocus="InputElement_OnGotFocus"
|
||||||
|
LostFocus="InputElement_OnLostFocus">
|
||||||
<Window.Styles>
|
<Window.Styles>
|
||||||
<Style Selector="TitleBar:fullscreen">
|
<Style Selector="TitleBar:fullscreen">
|
||||||
<Setter Property="Background" Value="#000000" />
|
<Setter Property="Background" Value="#000000" />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
@@ -30,6 +31,7 @@ using Ryujinx.HLE.HOS;
|
|||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.SDL2;
|
using Ryujinx.Input.SDL2;
|
||||||
|
using Ryujinx.Input.SDL3;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -108,7 +110,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(), new SDL3MotionDriver());
|
||||||
|
|
||||||
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
||||||
this.ScalingChanged += OnScalingChanged;
|
this.ScalingChanged += OnScalingChanged;
|
||||||
@@ -413,15 +415,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
case UpdaterType.CheckInBackground:
|
case UpdaterType.CheckInBackground:
|
||||||
if ((await Updater.CheckVersionAsync()).TryGet(out (Version Current, Version Incoming) versions))
|
if ((await Updater.CheckVersionAsync()).TryGet(out (Version Current, Version Incoming) versions))
|
||||||
{
|
{
|
||||||
string newVersionString = ReleaseInformation.IsCanaryBuild
|
Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.ViewModel.UpdateAvailable = versions.Current < versions.Incoming);
|
||||||
? $"Canary {versions.Current} -> Canary {versions.Incoming}"
|
|
||||||
: $"{versions.Current} -> {versions.Incoming}";
|
|
||||||
|
|
||||||
if (versions.Current < versions.Incoming)
|
|
||||||
NotificationHelper.ShowInformation(
|
|
||||||
title: "Update Available",
|
|
||||||
text: newVersionString,
|
|
||||||
onClick: () => _ = Updater.BeginUpdateAsync());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -769,5 +763,119 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
_intelMacWarningShown = true;
|
_intelMacWarningShown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InputElement_OnGotFocus(object sender, GotFocusEventArgs e)
|
||||||
|
{
|
||||||
|
if (ViewModel.AppHost is null) return;
|
||||||
|
|
||||||
|
if (!_focusLoss.Active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (_focusLoss.Type)
|
||||||
|
{
|
||||||
|
case FocusLostType.BlockInput:
|
||||||
|
{
|
||||||
|
if (!ViewModel.AppHost.NpadManager.InputUpdatesBlocked)
|
||||||
|
{
|
||||||
|
_focusLoss = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModel.AppHost.NpadManager.UnblockInputUpdates();
|
||||||
|
_focusLoss = default;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FocusLostType.MuteAudio:
|
||||||
|
{
|
||||||
|
if (!ViewModel.AppHost.Device.IsAudioMuted())
|
||||||
|
{
|
||||||
|
_focusLoss = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute);
|
||||||
|
|
||||||
|
_focusLoss = default;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FocusLostType.BlockInputAndMuteAudio:
|
||||||
|
{
|
||||||
|
if (!ViewModel.AppHost.Device.IsAudioMuted())
|
||||||
|
goto case FocusLostType.BlockInput;
|
||||||
|
|
||||||
|
ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute);
|
||||||
|
ViewModel.AppHost.NpadManager.UnblockInputUpdates();
|
||||||
|
|
||||||
|
_focusLoss = default;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FocusLostType.PauseEmulation:
|
||||||
|
{
|
||||||
|
if (!ViewModel.AppHost.Device.System.IsPaused)
|
||||||
|
{
|
||||||
|
_focusLoss = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModel.AppHost.Resume();
|
||||||
|
|
||||||
|
_focusLoss = default;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (FocusLostType Type, bool Active) _focusLoss;
|
||||||
|
|
||||||
|
private void InputElement_OnLostFocus(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (ConfigurationState.Instance.FocusLostActionType.Value is FocusLostType.DoNothing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ViewModel.AppHost is null) return;
|
||||||
|
|
||||||
|
switch (ConfigurationState.Instance.FocusLostActionType.Value)
|
||||||
|
{
|
||||||
|
case FocusLostType.BlockInput:
|
||||||
|
{
|
||||||
|
if (ViewModel.AppHost.NpadManager.InputUpdatesBlocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||||
|
_focusLoss = (FocusLostType.BlockInput, ViewModel.AppHost.NpadManager.InputUpdatesBlocked);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FocusLostType.MuteAudio:
|
||||||
|
{
|
||||||
|
if (ViewModel.AppHost.Device.GetVolume() is 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ViewModel.VolumeBeforeMute = ViewModel.AppHost.Device.GetVolume();
|
||||||
|
ViewModel.AppHost.Device.SetVolume(0);
|
||||||
|
_focusLoss = (FocusLostType.MuteAudio, ViewModel.AppHost.Device.GetVolume() is 0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FocusLostType.BlockInputAndMuteAudio:
|
||||||
|
{
|
||||||
|
if (ViewModel.AppHost.Device.GetVolume() is 0)
|
||||||
|
goto case FocusLostType.BlockInput;
|
||||||
|
|
||||||
|
ViewModel.VolumeBeforeMute = ViewModel.AppHost.Device.GetVolume();
|
||||||
|
ViewModel.AppHost.Device.SetVolume(0);
|
||||||
|
ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||||
|
_focusLoss = (FocusLostType.BlockInputAndMuteAudio, ViewModel.AppHost.Device.GetVolume() is 0f && ViewModel.AppHost.NpadManager.InputUpdatesBlocked);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FocusLostType.PauseEmulation:
|
||||||
|
{
|
||||||
|
if (ViewModel.AppHost.Device.System.IsPaused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ViewModel.AppHost.Pause();
|
||||||
|
_focusLoss = (FocusLostType.PauseEmulation, ViewModel.AppHost.Device.System.IsPaused);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
_running = false;
|
_running = false;
|
||||||
|
|
||||||
return (currentVersion, null);
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (currentVersion, newVersion);
|
return (currentVersion, newVersion);
|
||||||
@@ -178,7 +178,11 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
_running = true;
|
_running = true;
|
||||||
|
|
||||||
(Version currentVersion, Version newVersion) = (await CheckVersionAsync(showVersionUpToDate)).OrDefault();
|
Optional<(Version, Version)> versionTuple = await CheckVersionAsync(showVersionUpToDate);
|
||||||
|
|
||||||
|
if (_running is false || !versionTuple.HasValue) return;
|
||||||
|
|
||||||
|
(Version currentVersion, Version newVersion) = versionTuple.Value;
|
||||||
|
|
||||||
if (newVersion <= currentVersion)
|
if (newVersion <= currentVersion)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
|
|
||||||
public string LocalizedStatusTooltip =>
|
public string LocalizedStatusTooltip =>
|
||||||
Compatibility.Convert(x =>
|
Compatibility.Convert(x =>
|
||||||
#pragma warning disable CS8509 It is exhaustive for all possible values this can contain.
|
#pragma warning disable CS8509 // It is exhaustive for all possible values this can contain.
|
||||||
LocaleManager.Instance[x.Status switch
|
LocaleManager.Instance[x.Status switch
|
||||||
#pragma warning restore CS8509
|
#pragma warning restore CS8509
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace Ryujinx.Ava.Utilities
|
|||||||
if (string.IsNullOrEmpty(contentPath))
|
if (string.IsNullOrEmpty(contentPath))
|
||||||
goto BadData;
|
goto BadData;
|
||||||
|
|
||||||
appData = new() { Name = Name, Id = ProgramId, Path = GetContentPath(contentManager) };
|
appData = new() { Name = Name, Id = ProgramId, Path = contentPath };
|
||||||
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
|
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 65;
|
public const int CurrentVersion = 67;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
@@ -171,6 +171,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UpdaterType UpdateCheckerType { get; set; }
|
public UpdaterType UpdateCheckerType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How the emulator should behave when you click off/on the window.
|
||||||
|
/// </summary>
|
||||||
|
public FocusLostType FocusLostActionType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show "Confirm Exit" Dialog
|
/// Show "Confirm Exit" Dialog
|
||||||
@@ -383,6 +388,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// Enable or disable mouse support (Independent from controllers binding)
|
/// Enable or disable mouse support (Independent from controllers binding)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hotkey Keyboard Bindings
|
/// Hotkey Keyboard Bindings
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
||||||
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
||||||
UpdateCheckerType.Value = cff.UpdateCheckerType;
|
UpdateCheckerType.Value = cff.UpdateCheckerType;
|
||||||
|
FocusLostActionType.Value = cff.FocusLostActionType;
|
||||||
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
||||||
RememberWindowState.Value = cff.RememberWindowState;
|
RememberWindowState.Value = cff.RememberWindowState;
|
||||||
ShowTitleBar.Value = cff.ShowTitleBar;
|
ShowTitleBar.Value = cff.ShowTitleBar;
|
||||||
@@ -139,6 +140,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.DisableInputWhenOutOfFocus.Value = cff.DisableInputWhenOutOfFocus;
|
||||||
Hid.Hotkeys.Value = cff.Hotkeys;
|
Hid.Hotkeys.Value = cff.Hotkeys;
|
||||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||||
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
|
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
|
||||||
@@ -433,7 +435,9 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
(62, static cff => cff.RainbowSpeed = 1f),
|
(62, static cff => cff.RainbowSpeed = 1f),
|
||||||
(63, static cff => cff.MatchSystemTime = false),
|
(63, static cff => cff.MatchSystemTime = false),
|
||||||
(64, static cff => cff.LoggingEnableAvalonia = false),
|
(64, static cff => cff.LoggingEnableAvalonia = false),
|
||||||
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off)
|
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off),
|
||||||
|
(66, static cff => cff.DisableInputWhenOutOfFocus = false),
|
||||||
|
(67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -447,6 +447,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// Enable or disable mouse support (Independent from controllers binding)
|
/// Enable or disable mouse support (Independent from controllers binding)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableMouse { get; private set; }
|
public ReactiveObject<bool> EnableMouse { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> DisableInputWhenOutOfFocus { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hotkey Keyboard Bindings
|
/// Hotkey Keyboard Bindings
|
||||||
@@ -469,6 +474,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
{
|
{
|
||||||
EnableKeyboard = new ReactiveObject<bool>();
|
EnableKeyboard = new ReactiveObject<bool>();
|
||||||
EnableMouse = new ReactiveObject<bool>();
|
EnableMouse = 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>>();
|
||||||
RainbowSpeed = new ReactiveObject<float>();
|
RainbowSpeed = new ReactiveObject<float>();
|
||||||
@@ -773,6 +779,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<UpdaterType> UpdateCheckerType { get; private set; }
|
public ReactiveObject<UpdaterType> UpdateCheckerType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How the emulator should behave when you click off/on the window.
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<FocusLostType> FocusLostActionType { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show "Confirm Exit" Dialog
|
/// Show "Confirm Exit" Dialog
|
||||||
@@ -811,6 +822,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
EnableDiscordIntegration = new ReactiveObject<bool>();
|
EnableDiscordIntegration = new ReactiveObject<bool>();
|
||||||
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
||||||
UpdateCheckerType = new ReactiveObject<UpdaterType>();
|
UpdateCheckerType = new ReactiveObject<UpdaterType>();
|
||||||
|
FocusLostActionType = new ReactiveObject<FocusLostType>();
|
||||||
ShowConfirmExit = new ReactiveObject<bool>();
|
ShowConfirmExit = new ReactiveObject<bool>();
|
||||||
RememberWindowState = new ReactiveObject<bool>();
|
RememberWindowState = new ReactiveObject<bool>();
|
||||||
ShowTitleBar = new ReactiveObject<bool>();
|
ShowTitleBar = new ReactiveObject<bool>();
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
DockedMode = System.EnableDockedMode,
|
DockedMode = System.EnableDockedMode,
|
||||||
EnableDiscordIntegration = EnableDiscordIntegration,
|
EnableDiscordIntegration = EnableDiscordIntegration,
|
||||||
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
||||||
|
UpdateCheckerType = UpdateCheckerType,
|
||||||
|
FocusLostActionType = FocusLostActionType,
|
||||||
ShowConfirmExit = ShowConfirmExit,
|
ShowConfirmExit = ShowConfirmExit,
|
||||||
RememberWindowState = RememberWindowState,
|
RememberWindowState = RememberWindowState,
|
||||||
ShowTitleBar = ShowTitleBar,
|
ShowTitleBar = ShowTitleBar,
|
||||||
@@ -130,6 +132,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
ShowConsole = UI.ShowConsole,
|
ShowConsole = UI.ShowConsole,
|
||||||
EnableKeyboard = Hid.EnableKeyboard,
|
EnableKeyboard = Hid.EnableKeyboard,
|
||||||
EnableMouse = Hid.EnableMouse,
|
EnableMouse = Hid.EnableMouse,
|
||||||
|
DisableInputWhenOutOfFocus = Hid.DisableInputWhenOutOfFocus,
|
||||||
Hotkeys = Hid.Hotkeys,
|
Hotkeys = Hid.Hotkeys,
|
||||||
InputConfig = Hid.InputConfig,
|
InputConfig = Hid.InputConfig,
|
||||||
RainbowSpeed = Hid.RainbowSpeed,
|
RainbowSpeed = Hid.RainbowSpeed,
|
||||||
@@ -176,6 +179,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.EnableDockedMode.Value = true;
|
System.EnableDockedMode.Value = true;
|
||||||
EnableDiscordIntegration.Value = true;
|
EnableDiscordIntegration.Value = true;
|
||||||
UpdateCheckerType.Value = UpdaterType.PromptAtStartup;
|
UpdateCheckerType.Value = UpdaterType.PromptAtStartup;
|
||||||
|
FocusLostActionType.Value = FocusLostType.DoNothing;
|
||||||
ShowConfirmExit.Value = true;
|
ShowConfirmExit.Value = true;
|
||||||
RememberWindowState.Value = true;
|
RememberWindowState.Value = true;
|
||||||
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
||||||
@@ -244,6 +248,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.DisableInputWhenOutOfFocus.Value = false;
|
||||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||||
{
|
{
|
||||||
ToggleVSyncMode = Key.F1,
|
ToggleVSyncMode = Key.F1,
|
||||||
|
|||||||
15
src/Ryujinx/Utilities/Configuration/UI/FocusLostType.cs
Normal file
15
src/Ryujinx/Utilities/Configuration/UI/FocusLostType.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Ryujinx.Common.Utilities;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
||||||
|
{
|
||||||
|
[JsonConverter(typeof(TypedStringEnumConverter<FocusLostType>))]
|
||||||
|
public enum FocusLostType
|
||||||
|
{
|
||||||
|
DoNothing,
|
||||||
|
BlockInput,
|
||||||
|
MuteAudio,
|
||||||
|
BlockInputAndMuteAudio,
|
||||||
|
PauseEmulation
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user