mirror of
https://github.com/Ryubing/Ryujinx.git
synced 2025-03-15 09:04:48 +00:00
Compare commits
No commits in common. "master" and "Canary-1.2.413" have entirely different histories.
master
...
Canary-1.2
191 changed files with 1987 additions and 3412 deletions
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
|
@ -19,7 +19,6 @@ jobs:
|
||||||
configuration: [Debug, Release]
|
configuration: [Debug, Release]
|
||||||
platform:
|
platform:
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||||
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
|
||||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||||
- { name: osx-x64, os: macos-13, zip_os_name: osx_x64 }
|
- { name: osx-x64, os: macos-13, zip_os_name: osx_x64 }
|
||||||
|
|
2
.github/workflows/canary.yml
vendored
2
.github/workflows/canary.yml
vendored
|
@ -62,7 +62,6 @@ jobs:
|
||||||
| Platform | Artifact |
|
| Platform | Artifact |
|
||||||
|--|--|
|
|--|--|
|
||||||
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||||
| Windows ARM 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
|
|
||||||
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||||
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
@ -80,7 +79,6 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
platform:
|
platform:
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||||
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
|
||||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||||
steps:
|
steps:
|
||||||
|
|
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
|
@ -12,8 +12,7 @@ env:
|
||||||
RYUJINX_BASE_VERSION: "1.2"
|
RYUJINX_BASE_VERSION: "1.2"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
|
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Stable-Releases"
|
|
||||||
RELEASE: 1
|
RELEASE: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -34,7 +33,7 @@ jobs:
|
||||||
script: |
|
script: |
|
||||||
github.rest.git.createRef({
|
github.rest.git.createRef({
|
||||||
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}",
|
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}",
|
||||||
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}",
|
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}",
|
||||||
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
|
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
|
||||||
sha: context.sha
|
sha: context.sha
|
||||||
})
|
})
|
||||||
|
@ -53,7 +52,7 @@ jobs:
|
||||||
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||||
|
@ -66,7 +65,6 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
platform:
|
platform:
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||||
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
|
||||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||||
steps:
|
steps:
|
||||||
|
@ -94,7 +92,7 @@ jobs:
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
@ -118,7 +116,6 @@ jobs:
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
if: matrix.platform.os == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
pushd publish
|
pushd publish
|
||||||
rm libarmeilleure-jitsupport.dylib
|
|
||||||
chmod +x Ryujinx.sh Ryujinx
|
chmod +x Ryujinx.sh Ryujinx
|
||||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||||
popd
|
popd
|
||||||
|
@ -176,7 +173,7 @@ jobs:
|
||||||
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
|
@ -225,7 +222,7 @@ jobs:
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
||||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||||
|
@ -53,8 +53,8 @@
|
||||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" />
|
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
||||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
<PackageVersion Include="System.Management" Version="9.0.0" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<table align="center">
|
<table align="center">
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center" width="25%">
|
<td align="center" width="25%">
|
||||||
<img src="https://raw.githubusercontent.com/Ryubing/Assets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" >
|
<img src="https://raw.githubusercontent.com/GreemDev/ryuassets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" >
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="75%">
|
<td align="center" width="75%">
|
||||||
|
|
||||||
# Ryujinx
|
# Ryujinx
|
||||||
|
|
||||||
[](https://github.com/Ryubing/Ryujinx/actions/workflows/release.yml)
|
[](https://github.com/Ryubing/Ryujinx/actions/workflows/release.yml)
|
||||||
[](https://github.com/Ryubing/Ryujinx/releases/latest)
|
[](https://github.com/Ryubing/Ryujinx/releases/latest)
|
||||||
<br>
|
<br>
|
||||||
[](https://github.com/Ryubing/Ryujinx/actions/workflows/canary.yml)
|
[](https://github.com/Ryubing/Ryujinx/actions/workflows/canary.yml)
|
||||||
[](https://github.com/Ryubing/Canary-Releases/releases/latest)
|
[](https://github.com/Ryubing/Canary-Releases/releases/latest)
|
||||||
|
@ -97,7 +97,7 @@ If you are planning to contribute or just want to learn more about this project
|
||||||
|
|
||||||
- **Input**
|
- **Input**
|
||||||
|
|
||||||
We currently have support for keyboard, mouse, touch input, Joy-Con input support, and nearly all controllers.
|
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers.
|
||||||
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||||
In all scenarios, you can set up everything inside the input configuration menu.
|
In all scenarios, you can set up everything inside the input configuration menu.
|
||||||
|
|
||||||
|
|
|
@ -631,7 +631,6 @@
|
||||||
010030D012FF6000,"Bus Driver Simulator",,playable,2022-10-17 13:55:27
|
010030D012FF6000,"Bus Driver Simulator",,playable,2022-10-17 13:55:27
|
||||||
0100A9101418C000,"BUSTAFELLOWS",nvdec,playable,2020-10-17 20:04:41
|
0100A9101418C000,"BUSTAFELLOWS",nvdec,playable,2020-10-17 20:04:41
|
||||||
0100177005C8A000,"BUTCHER",,playable,2021-01-11 18:50:17
|
0100177005C8A000,"BUTCHER",,playable,2021-01-11 18:50:17
|
||||||
01008c2019598000,"Bluey: The Videogame",,playable,2025-02-11 04:38:00
|
|
||||||
01000B900D8B0000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda",slow;nvdec,playable,2024-04-01 22:43:40
|
01000B900D8B0000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda",slow;nvdec,playable,2024-04-01 22:43:40
|
||||||
010065700EE06000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda Demo",demo;gpu;nvdec,ingame,2021-02-14 21:48:15
|
010065700EE06000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda Demo",demo;gpu;nvdec,ingame,2021-02-14 21:48:15
|
||||||
01005C00117A8000,"Café Enchanté",,playable,2020-11-13 14:54:25
|
01005C00117A8000,"Café Enchanté",,playable,2020-11-13 14:54:25
|
||||||
|
@ -1383,9 +1382,6 @@
|
||||||
0100763015C2E000,"Gunvolt Chronicles: Luminous Avenger iX 2",crash;Needs Update,nothing,2022-04-29 15:34:34
|
0100763015C2E000,"Gunvolt Chronicles: Luminous Avenger iX 2",crash;Needs Update,nothing,2022-04-29 15:34:34
|
||||||
01002C8018554000,"Gurimugurimoa OnceMore Demo",,playable,2022-07-29 22:07:31
|
01002C8018554000,"Gurimugurimoa OnceMore Demo",,playable,2022-07-29 22:07:31
|
||||||
0100AC601DCA8000,"GYLT",crash,ingame,2024-03-18 20:16:51
|
0100AC601DCA8000,"GYLT",crash,ingame,2024-03-18 20:16:51
|
||||||
0100c3c012718000,"Grand Theft Auto: III – The Definitive Edition",gpu;UE4,ingame,2022-10-31 20:13:52
|
|
||||||
0100182014022000,"Grand Theft Auto: Vice City – The Definitive Edition",gpu;UE4,ingame,2022-10-31 20:13:52
|
|
||||||
010065a014024000,"Grand Theft Auto: San Andreas – The Definitive Edition",gpu;UE4,ingame,2022-10-31 20:13:52
|
|
||||||
0100822012D76000,"HAAK",gpu,ingame,2023-02-19 14:31:05
|
0100822012D76000,"HAAK",gpu,ingame,2023-02-19 14:31:05
|
||||||
01007E100EFA8000,"Habroxia",,playable,2020-06-16 23:04:42
|
01007E100EFA8000,"Habroxia",,playable,2020-06-16 23:04:42
|
||||||
0100535012974000,"Hades",vulkan,playable,2022-10-05 10:45:21
|
0100535012974000,"Hades",vulkan,playable,2022-10-05 10:45:21
|
||||||
|
@ -2733,7 +2729,7 @@
|
||||||
0100C2500FC20000,"Splatoon™ 3",ldn-works;opengl-backend-bug;LAN;amd-vendor-bug,playable,2024-08-04 23:49:11
|
0100C2500FC20000,"Splatoon™ 3",ldn-works;opengl-backend-bug;LAN;amd-vendor-bug,playable,2024-08-04 23:49:11
|
||||||
0100BA0018500000,"Splatoon™ 3: Splatfest World Premiere",gpu;online-broken;demo,ingame,2022-09-19 03:17:12
|
0100BA0018500000,"Splatoon™ 3: Splatfest World Premiere",gpu;online-broken;demo,ingame,2022-09-19 03:17:12
|
||||||
010062800D39C000,"SpongeBob SquarePants: Battle for Bikini Bottom - Rehydrated",online-broken;UE4;ldn-broken;vulkan-backend-bug,playable,2023-08-01 19:29:34
|
010062800D39C000,"SpongeBob SquarePants: Battle for Bikini Bottom - Rehydrated",online-broken;UE4;ldn-broken;vulkan-backend-bug,playable,2023-08-01 19:29:34
|
||||||
01009FB0172F4000,"SpongeBob SquarePants: The Cosmic Shake",gpu;UE4,ingame,2024-03-04 16:35:00
|
01009FB0172F4000,"SpongeBob SquarePants: The Cosmic Shake",gpu;UE4,ingame,2023-08-01 19:29:53
|
||||||
010097C01336A000,"Spooky Chase",,playable,2022-11-04 12:17:44
|
010097C01336A000,"Spooky Chase",,playable,2022-11-04 12:17:44
|
||||||
0100C6100D75E000,"Spooky Ghosts Dot Com",,playable,2021-06-15 15:16:11
|
0100C6100D75E000,"Spooky Ghosts Dot Com",,playable,2021-06-15 15:16:11
|
||||||
0100DE9005170000,"Sports Party",nvdec,playable,2021-03-05 13:40:42
|
0100DE9005170000,"Sports Party",nvdec,playable,2021-03-05 13:40:42
|
||||||
|
|
|
|
@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache
|
||||||
|
|
||||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||||
|
|
||||||
private static List<CacheMemoryAllocator> _cacheAllocators = [];
|
private static CacheMemoryAllocator _cacheAllocator;
|
||||||
|
|
||||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||||
|
|
||||||
|
@ -40,48 +40,37 @@ namespace ARMeilleure.Translation.Cache
|
||||||
|
|
||||||
public static void Initialize(IJitMemoryAllocator allocator)
|
public static void Initialize(IJitMemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
|
if (_initialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
if (_initialized)
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows())
|
return;
|
||||||
{
|
|
||||||
JitUnwindWindows.RemoveFunctionTableHandler(
|
|
||||||
_jitRegions[0].Pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < _jitRegions.Count; i++)
|
|
||||||
{
|
|
||||||
_jitRegions[i].Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_jitRegions.Clear();
|
|
||||||
_cacheAllocators.Clear();
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_activeRegionIndex = 0;
|
|
||||||
|
|
||||||
ReservedRegion firstRegion = new(allocator, CacheSize);
|
ReservedRegion firstRegion = new(allocator, CacheSize);
|
||||||
_jitRegions.Add(firstRegion);
|
_jitRegions.Add(firstRegion);
|
||||||
|
_activeRegionIndex = 0;
|
||||||
CacheMemoryAllocator firstCacheAllocator = new(CacheSize);
|
|
||||||
_cacheAllocators.Add(firstCacheAllocator);
|
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
JitUnwindWindows.InstallFunctionTableHandler(
|
JitUnwindWindows.InstallFunctionTableHandler(
|
||||||
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +136,7 @@ namespace ARMeilleure.Translation.Cache
|
||||||
|
|
||||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||||
{
|
{
|
||||||
_cacheAllocators[_activeRegionIndex].Free(funcOffset, AlignCodeSize(entry.Size));
|
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||||
_cacheEntries.RemoveAt(entryIndex);
|
_cacheEntries.RemoveAt(entryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,24 +167,30 @@ namespace ARMeilleure.Translation.Cache
|
||||||
{
|
{
|
||||||
codeSize = AlignCodeSize(codeSize);
|
codeSize = AlignCodeSize(codeSize);
|
||||||
|
|
||||||
int allocOffset = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++)
|
||||||
|
|
||||||
if (allocOffset >= 0)
|
|
||||||
{
|
{
|
||||||
_jitRegions[_activeRegionIndex].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||||
return allocOffset;
|
|
||||||
|
if (allocOffset >= 0)
|
||||||
|
{
|
||||||
|
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||||
|
_activeRegionIndex = i;
|
||||||
|
return allocOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int exhaustedRegion = _activeRegionIndex;
|
int exhaustedRegion = _activeRegionIndex;
|
||||||
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||||
_jitRegions.Add(newRegion);
|
_jitRegions.Add(newRegion);
|
||||||
_activeRegionIndex = _jitRegions.Count - 1;
|
_activeRegionIndex = _jitRegions.Count - 1;
|
||||||
|
|
||||||
|
int newRegionNumber = _activeRegionIndex;
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {_activeRegionIndex} ({((long)(_activeRegionIndex + 1) * CacheSize).Bytes()} Total Allocation).");
|
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||||
|
|
||||||
|
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||||
|
|
||||||
_cacheAllocators.Add(new CacheMemoryAllocator(CacheSize));
|
int allocOffsetNew = _cacheAllocator.Allocate(codeSize);
|
||||||
|
|
||||||
int allocOffsetNew = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
|
||||||
if (allocOffsetNew < 0)
|
if (allocOffsetNew < 0)
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||||
|
|
|
@ -52,11 +52,6 @@ namespace ARMeilleure.Translation.Cache
|
||||||
nint context,
|
nint context,
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
||||||
|
|
||||||
[LibraryImport("kernel32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
private static unsafe partial bool RtlDeleteFunctionTable(
|
|
||||||
ulong tableIdentifier);
|
|
||||||
|
|
||||||
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
||||||
|
|
||||||
private static int _sizeOfRuntimeFunction;
|
private static int _sizeOfRuntimeFunction;
|
||||||
|
@ -96,23 +91,6 @@ namespace ARMeilleure.Translation.Cache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RemoveFunctionTableHandler(nint codeCachePointer)
|
|
||||||
{
|
|
||||||
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
|
||||||
|
|
||||||
bool result;
|
|
||||||
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
result = RtlDeleteFunctionTable(codeCachePtr | 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Failure removing function table callback.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
||||||
{
|
{
|
||||||
int offset = (int)((long)controlPc - context.ToInt64());
|
int offset = (int)((long)controlPc - context.ToInt64());
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -11,15 +11,15 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'">
|
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>libsoundio.dll</TargetPath>
|
<TargetPath>libsoundio.dll</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'">
|
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>libsoundio.dylib</TargetPath>
|
<TargetPath>libsoundio.dylib</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64' AND '$(RuntimeIdentifier)' != 'linux-arm64'">
|
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64'">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>libsoundio.so</TargetPath>
|
<TargetPath>libsoundio.so</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
|
|
|
@ -9,8 +9,7 @@ namespace Ryujinx.Common.Configuration
|
||||||
public enum DirtyHack : byte
|
public enum DirtyHack : byte
|
||||||
{
|
{
|
||||||
Xc2MenuSoftlockFix = 1,
|
Xc2MenuSoftlockFix = 1,
|
||||||
// ShaderTranslationDelay = 2
|
ShaderTranslationDelay = 2
|
||||||
NifmServiceDisableIsAnyInternetRequestAccepted = 3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct EnabledDirtyHack(DirtyHack hack, int value)
|
public readonly struct EnabledDirtyHack(DirtyHack hack, int value)
|
||||||
|
|
|
@ -5,34 +5,15 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public enum OperatingSystemType
|
|
||||||
{
|
|
||||||
MacOS,
|
|
||||||
Linux,
|
|
||||||
Windows
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RunningPlatform
|
public static class RunningPlatform
|
||||||
{
|
{
|
||||||
public static readonly OperatingSystemType CurrentOS
|
|
||||||
= IsMacOS
|
|
||||||
? OperatingSystemType.MacOS
|
|
||||||
: IsWindows
|
|
||||||
? OperatingSystemType.Windows
|
|
||||||
: IsLinux
|
|
||||||
? OperatingSystemType.Linux
|
|
||||||
: throw new PlatformNotSupportedException();
|
|
||||||
|
|
||||||
public static Architecture Architecture => RuntimeInformation.OSArchitecture;
|
|
||||||
public static Architecture CurrentProcessArchitecture => RuntimeInformation.ProcessArchitecture;
|
|
||||||
|
|
||||||
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
||||||
public static bool IsWindows => OperatingSystem.IsWindows();
|
public static bool IsWindows => OperatingSystem.IsWindows();
|
||||||
public static bool IsLinux => OperatingSystem.IsLinux();
|
public static bool IsLinux => OperatingSystem.IsLinux();
|
||||||
|
|
||||||
public static bool IsArm => Architecture is Architecture.Arm64;
|
public static bool IsArm => RuntimeInformation.OSArchitecture is Architecture.Arm64;
|
||||||
|
|
||||||
public static bool IsX64 => Architecture is Architecture.X64;
|
public static bool IsX64 => RuntimeInformation.OSArchitecture is Architecture.X64;
|
||||||
|
|
||||||
public static bool IsIntelMac => IsMacOS && IsX64;
|
public static bool IsIntelMac => IsMacOS && IsX64;
|
||||||
public static bool IsArmMac => IsMacOS && IsArm;
|
public static bool IsArmMac => IsMacOS && IsArm;
|
||||||
|
|
|
@ -37,9 +37,9 @@ namespace Ryujinx.Common
|
||||||
public static string GetChangelogUrl(Version currentVersion, Version newVersion) =>
|
public static string GetChangelogUrl(Version currentVersion, Version newVersion) =>
|
||||||
IsCanaryBuild
|
IsCanaryBuild
|
||||||
? $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/compare/Canary-{currentVersion}...Canary-{newVersion}"
|
? $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/compare/Canary-{currentVersion}...Canary-{newVersion}"
|
||||||
: GetChangelogForVersion(newVersion);
|
: $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/releases/tag/{newVersion}";
|
||||||
|
|
||||||
public static string GetChangelogForVersion(Version version) =>
|
public static string GetChangelogForVersion(Version version) =>
|
||||||
$"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelRepo}/releases/{version}";
|
$"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelRepo}/releases/tag/{version}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
using Gommon;
|
using Gommon;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Helper;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -12,20 +10,6 @@ namespace Ryujinx.Graphics.GAL
|
||||||
|
|
||||||
bool PreferThreading { get; }
|
bool PreferThreading { get; }
|
||||||
|
|
||||||
public IRenderer TryMakeThreaded(BackendThreading backendThreading = BackendThreading.Auto)
|
|
||||||
{
|
|
||||||
if (backendThreading is BackendThreading.On ||
|
|
||||||
(backendThreading is BackendThreading.Auto && PreferThreading))
|
|
||||||
{
|
|
||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): True");
|
|
||||||
return new ThreadedRenderer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): False");
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPipeline Pipeline { get; }
|
IPipeline Pipeline { get; }
|
||||||
|
|
||||||
IWindow Window { get; }
|
IWindow Window { get; }
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
|
||||||
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new()
|
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new()
|
||||||
{
|
{
|
||||||
{ AvCodecLibraryName, (58, 61) },
|
{ AvCodecLibraryName, (58, 59) },
|
||||||
{ AvUtilLibraryName, (56, 59) },
|
{ AvUtilLibraryName, (56, 57) },
|
||||||
};
|
};
|
||||||
|
|
||||||
private static string FormatLibraryNameForCurrentOs(string libraryName, int version)
|
private static string FormatLibraryNameForCurrentOs(string libraryName, int version)
|
||||||
|
|
|
@ -15,55 +15,55 @@ namespace Ryujinx.HLE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HLE configuration.
|
/// HLE configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HleConfiguration
|
public class HLEConfiguration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The virtual file system used by the FS service.
|
/// The virtual file system used by the FS service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal VirtualFileSystem VirtualFileSystem { get; private set; }
|
internal readonly VirtualFileSystem VirtualFileSystem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The manager for handling a LibHac Horizon instance.
|
/// The manager for handling a LibHac Horizon instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal LibHacHorizonManager LibHacHorizonManager { get; private set; }
|
internal readonly LibHacHorizonManager LibHacHorizonManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The account manager used by the account service.
|
/// The account manager used by the account service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal AccountManager AccountManager { get; private set; }
|
internal readonly AccountManager AccountManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The content manager used by the NCM service.
|
/// The content manager used by the NCM service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal ContentManager ContentManager { get; private set; }
|
internal readonly ContentManager ContentManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The persistent information between run for multi-application capabilities.
|
/// The persistent information between run for multi-application capabilities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
public UserChannelPersistence UserChannelPersistence { get; private set; }
|
public readonly UserChannelPersistence UserChannelPersistence;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GPU renderer to use for all GPU operations.
|
/// The GPU renderer to use for all GPU operations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal IRenderer GpuRenderer { get; private set; }
|
internal readonly IRenderer GpuRenderer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The audio device driver to use for all audio operations.
|
/// The audio device driver to use for all audio operations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal IHardwareDeviceDriver AudioDeviceDriver { get; private set; }
|
internal readonly IHardwareDeviceDriver AudioDeviceDriver;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The handler for various UI related operations needed outside of HLE.
|
/// The handler for various UI related operations needed outside of HLE.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal IHostUIHandler HostUIHandler { get; private set; }
|
internal readonly IHostUIHandler HostUIHandler;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Control the memory configuration used by the emulation context.
|
/// Control the memory configuration used by the emulation context.
|
||||||
|
@ -195,7 +195,15 @@ namespace Ryujinx.HLE
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
public EnabledDirtyHack[] Hacks { internal get; set; }
|
public EnabledDirtyHack[] Hacks { internal get; set; }
|
||||||
|
|
||||||
public HleConfiguration(MemoryConfiguration memoryConfiguration,
|
public HLEConfiguration(VirtualFileSystem virtualFileSystem,
|
||||||
|
LibHacHorizonManager libHacHorizonManager,
|
||||||
|
ContentManager contentManager,
|
||||||
|
AccountManager accountManager,
|
||||||
|
UserChannelPersistence userChannelPersistence,
|
||||||
|
IRenderer gpuRenderer,
|
||||||
|
IHardwareDeviceDriver audioDeviceDriver,
|
||||||
|
MemoryConfiguration memoryConfiguration,
|
||||||
|
IHostUIHandler hostUIHandler,
|
||||||
SystemLanguage systemLanguage,
|
SystemLanguage systemLanguage,
|
||||||
RegionCode region,
|
RegionCode region,
|
||||||
VSyncMode vSyncMode,
|
VSyncMode vSyncMode,
|
||||||
|
@ -219,7 +227,15 @@ namespace Ryujinx.HLE
|
||||||
int customVSyncInterval,
|
int customVSyncInterval,
|
||||||
EnabledDirtyHack[] dirtyHacks = null)
|
EnabledDirtyHack[] dirtyHacks = null)
|
||||||
{
|
{
|
||||||
|
VirtualFileSystem = virtualFileSystem;
|
||||||
|
LibHacHorizonManager = libHacHorizonManager;
|
||||||
|
AccountManager = accountManager;
|
||||||
|
ContentManager = contentManager;
|
||||||
|
UserChannelPersistence = userChannelPersistence;
|
||||||
|
GpuRenderer = gpuRenderer;
|
||||||
|
AudioDeviceDriver = audioDeviceDriver;
|
||||||
MemoryConfiguration = memoryConfiguration;
|
MemoryConfiguration = memoryConfiguration;
|
||||||
|
HostUIHandler = hostUIHandler;
|
||||||
SystemLanguage = systemLanguage;
|
SystemLanguage = systemLanguage;
|
||||||
Region = region;
|
Region = region;
|
||||||
VSyncMode = vSyncMode;
|
VSyncMode = vSyncMode;
|
||||||
|
@ -243,30 +259,5 @@ namespace Ryujinx.HLE
|
||||||
MultiplayerLdnServer = multiplayerLdnServer;
|
MultiplayerLdnServer = multiplayerLdnServer;
|
||||||
Hacks = dirtyHacks ?? [];
|
Hacks = dirtyHacks ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the pre-configured services to use for this <see cref="HleConfiguration"/> instance.
|
|
||||||
/// </summary>
|
|
||||||
public HleConfiguration Configure(
|
|
||||||
VirtualFileSystem virtualFileSystem,
|
|
||||||
LibHacHorizonManager libHacHorizonManager,
|
|
||||||
ContentManager contentManager,
|
|
||||||
AccountManager accountManager,
|
|
||||||
UserChannelPersistence userChannelPersistence,
|
|
||||||
IRenderer gpuRenderer,
|
|
||||||
IHardwareDeviceDriver audioDeviceDriver,
|
|
||||||
IHostUIHandler hostUIHandler
|
|
||||||
)
|
|
||||||
{
|
|
||||||
VirtualFileSystem = virtualFileSystem;
|
|
||||||
LibHacHorizonManager = libHacHorizonManager;
|
|
||||||
AccountManager = accountManager;
|
|
||||||
ContentManager = contentManager;
|
|
||||||
UserChannelPersistence = userChannelPersistence;
|
|
||||||
GpuRenderer = gpuRenderer;
|
|
||||||
AudioDeviceDriver = audioDeviceDriver;
|
|
||||||
HostUIHandler = hostUIHandler;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
|
||||||
|
|
||||||
private readonly LanDiscovery _lanDiscovery;
|
private readonly LanDiscovery _lanDiscovery;
|
||||||
|
|
||||||
public LdnMitmClient(HleConfiguration config)
|
public LdnMitmClient(HLEConfiguration config)
|
||||||
{
|
{
|
||||||
UnicastIPAddressInformation localIpInterface = NetworkHelpers.GetLocalInterface(config.MultiplayerLanInterfaceId).Item2;
|
UnicastIPAddressInformation localIpInterface = NetworkHelpers.GetLocalInterface(config.MultiplayerLanInterfaceId).Item2;
|
||||||
|
|
||||||
|
|
|
@ -51,13 +51,13 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu
|
||||||
private string _passphrase;
|
private string _passphrase;
|
||||||
private byte[] _gameVersion = new byte[0x10];
|
private byte[] _gameVersion = new byte[0x10];
|
||||||
|
|
||||||
private readonly HleConfiguration _config;
|
private readonly HLEConfiguration _config;
|
||||||
|
|
||||||
public event EventHandler<NetworkChangeEventArgs> NetworkChange;
|
public event EventHandler<NetworkChangeEventArgs> NetworkChange;
|
||||||
|
|
||||||
public ProxyConfig Config { get; private set; }
|
public ProxyConfig Config { get; private set; }
|
||||||
|
|
||||||
public LdnMasterProxyClient(string address, int port, HleConfiguration config) : base(address, port)
|
public LdnMasterProxyClient(string address, int port, HLEConfiguration config) : base(address, port)
|
||||||
{
|
{
|
||||||
if (ProxyHelpers.SupportsNoDelay())
|
if (ProxyHelpers.SupportsNoDelay())
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
|
||||||
// CreateGeneralServiceOld() -> object<nn::nifm::detail::IGeneralService>
|
// CreateGeneralServiceOld() -> object<nn::nifm::detail::IGeneralService>
|
||||||
public ResultCode CreateGeneralServiceOld(ServiceCtx context)
|
public ResultCode CreateGeneralServiceOld(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new IGeneralService(context));
|
MakeObject(context, new IGeneralService());
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
|
||||||
// CreateGeneralService(u64, pid) -> object<nn::nifm::detail::IGeneralService>
|
// CreateGeneralService(u64, pid) -> object<nn::nifm::detail::IGeneralService>
|
||||||
public ResultCode CreateGeneralService(ServiceCtx context)
|
public ResultCode CreateGeneralService(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new IGeneralService(context));
|
MakeObject(context, new IGeneralService());
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
|
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
|
||||||
|
@ -18,12 +17,12 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
private UnicastIPAddressInformation _targetAddressInfoCache = null;
|
private UnicastIPAddressInformation _targetAddressInfoCache = null;
|
||||||
private string _cacheChosenInterface = null;
|
private string _cacheChosenInterface = null;
|
||||||
|
|
||||||
public IGeneralService(ServiceCtx context)
|
public IGeneralService()
|
||||||
{
|
{
|
||||||
_generalServiceDetail = new GeneralServiceDetail
|
_generalServiceDetail = new GeneralServiceDetail
|
||||||
{
|
{
|
||||||
ClientId = GeneralServiceManager.Count,
|
ClientId = GeneralServiceManager.Count,
|
||||||
IsAnyInternetRequestAccepted = !context.Device.DirtyHacks.IsEnabled(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted), // NOTE: Why not accept any internet request?
|
IsAnyInternetRequestAccepted = true, // NOTE: Why not accept any internet request?
|
||||||
};
|
};
|
||||||
|
|
||||||
NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler;
|
NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy;
|
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -71,24 +71,16 @@ namespace Ryujinx.HLE.Loaders.Mods
|
||||||
int patchOffset = (int)offset;
|
int patchOffset = (int)offset;
|
||||||
int patchSize = patch.Length;
|
int patchSize = patch.Length;
|
||||||
|
|
||||||
if (patchOffset < protectedOffset)
|
if (patchOffset < protectedOffset || patchOffset > memory.Length)
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch protected memory ({patchOffset:x} is within protected boundary of {protectedOffset:x}).");
|
continue; // Add warning?
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patchOffset > memory.Length)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch out of bounds memory (offset {patchOffset} ({patchOffset:x}) exceeds memory buffer length {memory.Length}).");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
patchOffset -= protectedOffset;
|
patchOffset -= protectedOffset;
|
||||||
|
|
||||||
if (patchOffset + patchSize > memory.Length)
|
if (patchOffset + patchSize > memory.Length)
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.ModLoader, $"Patch offset ({patchOffset:x}) + size ({patchSize}) is greater than the size of the memory buffer ({memory.Length}). Attempting to fix this...");
|
patchSize = memory.Length - patchOffset; // Add warning?
|
||||||
patchSize = memory.Length - patchOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
|
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ryujinx.HLE
|
||||||
{
|
{
|
||||||
public static Switch Shared { get; private set; }
|
public static Switch Shared { get; private set; }
|
||||||
|
|
||||||
public HleConfiguration Configuration { get; }
|
public HLEConfiguration Configuration { get; }
|
||||||
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
||||||
public MemoryBlock Memory { get; }
|
public MemoryBlock Memory { get; }
|
||||||
public GpuContext Gpu { get; }
|
public GpuContext Gpu { get; }
|
||||||
|
@ -44,7 +44,7 @@ namespace Ryujinx.HLE
|
||||||
|
|
||||||
public DirtyHacks DirtyHacks { get; }
|
public DirtyHacks DirtyHacks { get; }
|
||||||
|
|
||||||
public Switch(HleConfiguration configuration)
|
public Switch(HLEConfiguration configuration)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
||||||
ArgumentNullException.ThrowIfNull(configuration.AudioDeviceDriver);
|
ArgumentNullException.ThrowIfNull(configuration.AudioDeviceDriver);
|
||||||
|
@ -94,20 +94,16 @@ namespace Ryujinx.HLE
|
||||||
Gpu.GPFifo.DispatchCalls();
|
Gpu.GPFifo.DispatchCalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int IncrementCustomVSyncInterval()
|
public void IncrementCustomVSyncInterval()
|
||||||
{
|
{
|
||||||
CustomVSyncInterval += 1;
|
CustomVSyncInterval += 1;
|
||||||
UpdateVSyncInterval();
|
UpdateVSyncInterval();
|
||||||
|
|
||||||
return CustomVSyncInterval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int DecrementCustomVSyncInterval()
|
public void DecrementCustomVSyncInterval()
|
||||||
{
|
{
|
||||||
CustomVSyncInterval -= 1;
|
CustomVSyncInterval -= 1;
|
||||||
UpdateVSyncInterval();
|
UpdateVSyncInterval();
|
||||||
|
|
||||||
return CustomVSyncInterval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateVSyncInterval()
|
public void UpdateVSyncInterval()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Avalonia.Threading;
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
|
using LibHac.Tools.FsSystem;
|
||||||
using Ryujinx.Audio.Backends.Dummy;
|
using Ryujinx.Audio.Backends.Dummy;
|
||||||
using Ryujinx.Audio.Backends.OpenAL;
|
using Ryujinx.Audio.Backends.OpenAL;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
|
@ -20,8 +21,8 @@ using Ryujinx.Ava.UI.Renderer;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
|
@ -34,9 +35,11 @@ using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.Graphics.OpenGL;
|
using Ryujinx.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
@ -59,7 +62,7 @@ using Size = Avalonia.Size;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Systems
|
namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
internal class AppHost
|
internal class AppHost
|
||||||
{
|
{
|
||||||
|
@ -467,7 +470,7 @@ namespace Ryujinx.Ava.Systems
|
||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
|
||||||
});
|
});
|
||||||
|
|
||||||
_viewModel.SetUiProgressHandlers(Device);
|
_viewModel.SetUiProgressHandlers(Device);
|
||||||
|
@ -869,7 +872,7 @@ namespace Ryujinx.Ava.Systems
|
||||||
Device?.System.TogglePauseEmulation(false);
|
Device?.System.TogglePauseEmulation(false);
|
||||||
|
|
||||||
_viewModel.IsPaused = false;
|
_viewModel.IsPaused = false;
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
|
||||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,7 +881,7 @@ namespace Ryujinx.Ava.Systems
|
||||||
Device?.System.TogglePauseEmulation(true);
|
Device?.System.TogglePauseEmulation(true);
|
||||||
|
|
||||||
_viewModel.IsPaused = true;
|
_viewModel.IsPaused = true;
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar, LocaleManager.Instance[LocaleKeys.Paused]);
|
||||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,19 +902,53 @@ namespace Ryujinx.Ava.Systems
|
||||||
_ => new OpenGLRenderer()
|
_ => new OpenGLRenderer()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||||
|
|
||||||
|
bool isGALThreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||||
|
if (isGALThreaded)
|
||||||
|
{
|
||||||
|
renderer = new ThreadedRenderer(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALThreaded}");
|
||||||
|
|
||||||
// Initialize Configuration.
|
// Initialize Configuration.
|
||||||
Device = new Switch(ConfigurationState.Instance.CreateHleConfiguration()
|
MemoryConfiguration memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
|
||||||
.Configure(
|
|
||||||
VirtualFileSystem,
|
Device = new Switch(new HLEConfiguration(
|
||||||
_viewModel.LibHacHorizonManager,
|
VirtualFileSystem,
|
||||||
ContentManager,
|
_viewModel.LibHacHorizonManager,
|
||||||
_accountManager,
|
ContentManager,
|
||||||
_userChannelPersistence,
|
_accountManager,
|
||||||
renderer.TryMakeThreaded(ConfigurationState.Instance.Graphics.BackendThreading),
|
_userChannelPersistence,
|
||||||
InitializeAudio(),
|
renderer,
|
||||||
_viewModel.UiHandler
|
InitializeAudio(),
|
||||||
)
|
memoryConfiguration,
|
||||||
);
|
_viewModel.UiHandler,
|
||||||
|
(SystemLanguage)ConfigurationState.Instance.System.Language.Value,
|
||||||
|
(RegionCode)ConfigurationState.Instance.System.Region.Value,
|
||||||
|
ConfigurationState.Instance.Graphics.VSyncMode,
|
||||||
|
ConfigurationState.Instance.System.EnableDockedMode,
|
||||||
|
ConfigurationState.Instance.System.EnablePtc,
|
||||||
|
ConfigurationState.Instance.System.EnableInternetAccess,
|
||||||
|
ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||||
|
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
||||||
|
ConfigurationState.Instance.System.MatchSystemTime
|
||||||
|
? 0
|
||||||
|
: ConfigurationState.Instance.System.SystemTimeOffset,
|
||||||
|
ConfigurationState.Instance.System.TimeZone,
|
||||||
|
ConfigurationState.Instance.System.MemoryManagerMode,
|
||||||
|
ConfigurationState.Instance.System.IgnoreMissingServices,
|
||||||
|
ConfigurationState.Instance.Graphics.AspectRatio,
|
||||||
|
ConfigurationState.Instance.System.AudioVolume,
|
||||||
|
ConfigurationState.Instance.System.UseHypervisor,
|
||||||
|
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
|
||||||
|
ConfigurationState.Instance.Multiplayer.Mode,
|
||||||
|
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||||
|
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||||
|
ConfigurationState.Instance.Multiplayer.GetLdnServer(),
|
||||||
|
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
||||||
|
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IHardwareDeviceDriver InitializeAudio()
|
private static IHardwareDeviceDriver InitializeAudio()
|
||||||
|
@ -1076,13 +1113,6 @@ namespace Ryujinx.Ava.Systems
|
||||||
});
|
});
|
||||||
|
|
||||||
(RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
|
(RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
|
||||||
|
|
||||||
// Reload settings when the game is turned off
|
|
||||||
// (resets custom settings if there were any)
|
|
||||||
Program.ReloadConfig();
|
|
||||||
|
|
||||||
// Reload application list (changes the status of the user setting if it was added or removed during the game)
|
|
||||||
Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.LoadApplications());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitStatus()
|
public void InitStatus()
|
||||||
|
@ -1145,9 +1175,6 @@ namespace Ryujinx.Ava.Systems
|
||||||
|
|
||||||
private void UpdateShaderCount()
|
private void UpdateShaderCount()
|
||||||
{
|
{
|
||||||
if (_displayCount is 0 && _renderer.ProgramCount is 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If there is a mismatch between total program compile and previous count
|
// If there is a mismatch between total program compile and previous count
|
||||||
// this means new shaders have been compiled and should be displayed.
|
// this means new shaders have been compiled and should be displayed.
|
||||||
if (_renderer.ProgramCount != _previousCount)
|
if (_renderer.ProgramCount != _previousCount)
|
||||||
|
@ -1221,10 +1248,12 @@ namespace Ryujinx.Ava.Systems
|
||||||
VSyncModeToggle();
|
VSyncModeToggle();
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.CustomVSyncIntervalDecrement:
|
case KeyboardHotkeyState.CustomVSyncIntervalDecrement:
|
||||||
_viewModel.CustomVSyncInterval = Device.DecrementCustomVSyncInterval();
|
Device.DecrementCustomVSyncInterval();
|
||||||
|
_viewModel.CustomVSyncInterval -= 1;
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.CustomVSyncIntervalIncrement:
|
case KeyboardHotkeyState.CustomVSyncIntervalIncrement:
|
||||||
_viewModel.CustomVSyncInterval = Device.IncrementCustomVSyncInterval();
|
Device.IncrementCustomVSyncInterval();
|
||||||
|
_viewModel.CustomVSyncInterval += 1;
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.Screenshot:
|
case KeyboardHotkeyState.Screenshot:
|
||||||
ScreenshotRequested = true;
|
ScreenshotRequested = true;
|
|
@ -1,8 +1,7 @@
|
||||||
<Styles
|
<Styles
|
||||||
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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
|
||||||
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia">
|
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Height="2000"
|
<Border Height="2000"
|
||||||
|
@ -31,8 +30,7 @@
|
||||||
<Button
|
<Button
|
||||||
Name="btnRem"
|
Name="btnRem"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Content="Add"
|
Content="Add" />
|
||||||
Classes="red"/>
|
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="100"
|
Width="100"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
@ -43,13 +41,7 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<ui:NumberBox Value="1" />
|
<ui:NumberBox Value="1" />
|
||||||
<MenuItem
|
|
||||||
Header="123 0000"
|
|
||||||
ToolTip.Tip="What this"/>
|
|
||||||
<TextBlock
|
|
||||||
Classes="globalConfigMarker"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
</Border>
|
</Border>
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
<Style Selector="DropDownButton">
|
<Style Selector="DropDownButton">
|
||||||
|
@ -339,14 +331,6 @@
|
||||||
<Setter Property="Margin"
|
<Setter Property="Margin"
|
||||||
Value="0,5,0,0" />
|
Value="0,5,0,0" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="TextBlock.globalConfigMarker" >
|
|
||||||
<Setter Property="Foreground" Value="SeaGreen"/>
|
|
||||||
<Setter Property="Margin" Value="5,0,0,0"/>
|
|
||||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
|
||||||
<Setter Property="Text" Value="{ext:Locale GameSpecificConfigurationGlobal}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="StackPanel.globalConfigMarker">
|
|
||||||
</Style>
|
|
||||||
<Style Selector="ContextMenu">
|
<Style Selector="ContextMenu">
|
||||||
<Setter Property="BorderBrush"
|
<Setter Property="BorderBrush"
|
||||||
Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" />
|
Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" />
|
||||||
|
@ -389,19 +373,6 @@
|
||||||
<Setter Property="Background"
|
<Setter Property="Background"
|
||||||
Value="{DynamicResource AppListHoverBackgroundColor}" />
|
Value="{DynamicResource AppListHoverBackgroundColor}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="Button.red /template/ ContentPresenter">
|
|
||||||
<Setter Property="CornerRadius" Value="4"/>
|
|
||||||
<Setter Property="Background" Value="red"/>
|
|
||||||
<Setter Property="Foreground" Value="White"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Button.red:pointerover /template/ ContentPresenter">
|
|
||||||
<Setter Property="CornerRadius" Value="4"/>
|
|
||||||
<Setter Property="Background" Value="{DynamicResource WarningBackgroundColor}" />
|
|
||||||
<Setter Property="Foreground" Value="White"/>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Styles.Resources>
|
<Styles.Resources>
|
||||||
<SolidColorBrush x:Key="ThemeAccentColorBrush"
|
<SolidColorBrush x:Key="ThemeAccentColorBrush"
|
||||||
Color="{DynamicResource SystemAccentColor}" />
|
Color="{DynamicResource SystemAccentColor}" />
|
||||||
|
@ -440,7 +411,7 @@
|
||||||
<x:Double x:Key="ControlContentThemeFontSize">13</x:Double>
|
<x:Double x:Key="ControlContentThemeFontSize">13</x:Double>
|
||||||
<x:Double x:Key="MenuItemHeight">26</x:Double>
|
<x:Double x:Key="MenuItemHeight">26</x:Double>
|
||||||
<x:Double x:Key="TabItemMinHeight">28</x:Double>
|
<x:Double x:Key="TabItemMinHeight">28</x:Double>
|
||||||
<x:Double x:Key="ContentDialogMaxWidth">700</x:Double>
|
<x:Double x:Key="ContentDialogMaxWidth">900</x:Double>
|
||||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||||
</Styles.Resources>
|
</Styles.Resources>
|
||||||
</Styles>
|
</Styles>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<ResourceDictionary x:Key="Default">
|
<ResourceDictionary x:Key="Default">
|
||||||
|
@ -12,13 +12,11 @@
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
|
||||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
<Color x:Key="Warning">#800080</Color>
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="Light">
|
<ResourceDictionary x:Key="Light">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
|
@ -31,13 +29,11 @@
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
|
||||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
<Color x:Key="Switch">#13c3a4</Color>
|
<Color x:Key="Switch">#13c3a4</Color>
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
<Color x:Key="Warning">#800080</Color>
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
|
@ -50,13 +46,11 @@
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
|
||||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
<Color x:Key="Warning">#FFA500</Color>
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,10 +13,10 @@ using LibHac.Tools.Fs;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
using LibHac.Tools.FsSystem.NcaUtils;
|
using LibHac.Tools.FsSystem.NcaUtils;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
|
@ -216,7 +216,11 @@ namespace Ryujinx.Ava.Common
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(Nca updatePatchNca, _) = mainNca.GetUpdateData(_virtualFileSystem, ConfigurationState.Instance.System.IntegrityCheckLevel, programIndex, out _);
|
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
|
||||||
|
? IntegrityCheckLevel.ErrorOnInvalid
|
||||||
|
: IntegrityCheckLevel.None;
|
||||||
|
|
||||||
|
(Nca updatePatchNca, _) = mainNca.GetUpdateData(_virtualFileSystem, checkLevel, programIndex, out _);
|
||||||
if (updatePatchNca is not null)
|
if (updatePatchNca is not null)
|
||||||
{
|
{
|
||||||
patchNca = updatePatchNca;
|
patchNca = updatePatchNca;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Systems;
|
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System;
|
using System;
|
||||||
|
@ -26,21 +25,7 @@ namespace Ryujinx.Ava.Common.Locale
|
||||||
public LocaleManager()
|
public LocaleManager()
|
||||||
{
|
{
|
||||||
_localeStrings = new Dictionary<LocaleKeys, string>();
|
_localeStrings = new Dictionary<LocaleKeys, string>();
|
||||||
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>(new Dictionary<LocaleKeys, object[]>
|
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>();
|
||||||
{
|
|
||||||
{ LocaleKeys.DialogConfirmationTitle, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.DialogUpdaterTitle, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.DialogErrorTitle, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.DialogWarningTitle, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.DialogExitTitle, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.DialogStopEmulationTitle, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.RyujinxInfo, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.RyujinxConfirm, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.RyujinxUpdater, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.RyujinxRebooter, [RyujinxApp.FullAppName] },
|
|
||||||
{ LocaleKeys.CompatibilityListSearchBoxWatermarkWithCount, [CompatibilityDatabase.Entries.Length] },
|
|
||||||
{ LocaleKeys.CompatibilityListTitle, [CompatibilityDatabase.Entries.Length] }
|
|
||||||
});
|
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +44,16 @@ namespace Ryujinx.Ava.Common.Locale
|
||||||
|
|
||||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetDynamicValues(LocaleKeys.DialogConfirmationTitle, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.DialogUpdaterTitle, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.DialogErrorTitle, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.DialogWarningTitle, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.DialogExitTitle, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.DialogStopEmulationTitle, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.RyujinxInfo, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.RyujinxConfirm, RyujinxApp.FullAppName);
|
||||||
|
SetDynamicValues(LocaleKeys.RyujinxUpdater, RyujinxApp.FullAppName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string this[LocaleKeys key]
|
public string this[LocaleKeys key]
|
||||||
|
|
|
@ -24,17 +24,4 @@ namespace Ryujinx.Ava.Common.Markup
|
||||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||||
=> bindingExtension.Source = LocaleManager.Instance;
|
=> bindingExtension.Source = LocaleManager.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class WindowTitleExtension(LocaleKeys key, bool includeVersion) : BasicMarkupExtension<string>
|
|
||||||
{
|
|
||||||
public WindowTitleExtension(LocaleKeys key) : this(key, true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Name => "WindowTitleTranslation";
|
|
||||||
protected override string Value => RyujinxApp.FormatTitle(key, includeVersion);
|
|
||||||
|
|
||||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
|
||||||
=> bindingExtension.Source = LocaleManager.Instance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@ namespace Ryujinx.Ava.Common
|
||||||
|
|
||||||
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
||||||
{
|
{
|
||||||
private readonly XciTrimmerViewModel _viewModel;
|
private readonly XCITrimmerViewModel _viewModel;
|
||||||
|
|
||||||
public TrimmerWindow(XciTrimmerViewModel viewModel)
|
public TrimmerWindow(XCITrimmerViewModel viewModel)
|
||||||
{
|
{
|
||||||
_viewModel = viewModel;
|
_viewModel = viewModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Ava.Systems.PlayReport;
|
using Ryujinx.Ava.Utilities.PlayReport;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.Loaders.Processes;
|
using Ryujinx.HLE.Loaders.Processes;
|
||||||
using Ryujinx.Horizon;
|
using Ryujinx.Horizon;
|
||||||
|
using Ryujinx.Horizon.Prepo.Types;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Systems
|
namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
public static class DiscordIntegrationModule
|
public static class DiscordIntegrationModule
|
||||||
{
|
{
|
||||||
|
@ -123,7 +124,7 @@ namespace Ryujinx.Ava.Systems
|
||||||
_currentApp = null;
|
_currentApp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandlePlayReport(Horizon.Prepo.Types.PlayReport playReport)
|
private static void HandlePlayReport(PlayReport playReport)
|
||||||
{
|
{
|
||||||
if (_discordClient is null) return;
|
if (_discordClient is null) return;
|
||||||
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
|
@ -2,8 +2,7 @@ using DiscordRPC;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
using Ryujinx.Ava;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Ava.Systems;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
@ -12,6 +11,7 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
using Ryujinx.Graphics.OpenGL;
|
using Ryujinx.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
|
@ -312,42 +312,49 @@ namespace Ryujinx.Headless
|
||||||
return new OpenGLRenderer();
|
return new OpenGLRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options) =>
|
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
||||||
new(
|
{
|
||||||
new HleConfiguration(
|
BackendThreading threadingMode = options.BackendThreading;
|
||||||
options.DramSize,
|
|
||||||
options.SystemLanguage,
|
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||||
options.SystemRegion,
|
|
||||||
options.VSyncMode,
|
if (threadedGAL)
|
||||||
!options.DisableDockedMode,
|
{
|
||||||
!options.DisablePTC,
|
renderer = new ThreadedRenderer(renderer);
|
||||||
options.EnableInternetAccess,
|
}
|
||||||
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
|
||||||
options.FsGlobalAccessLogMode,
|
HLEConfiguration configuration = new(_virtualFileSystem,
|
||||||
options.SystemTimeOffset,
|
_libHacHorizonManager,
|
||||||
options.SystemTimeZone,
|
_contentManager,
|
||||||
options.MemoryManagerMode,
|
_accountManager,
|
||||||
options.IgnoreMissingServices,
|
_userChannelPersistence,
|
||||||
options.AspectRatio,
|
renderer,
|
||||||
options.AudioVolume,
|
new SDL2HardwareDeviceDriver(),
|
||||||
options.UseHypervisor ?? true,
|
options.DramSize,
|
||||||
options.MultiplayerLanInterfaceId,
|
window,
|
||||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
options.SystemLanguage,
|
||||||
false,
|
options.SystemRegion,
|
||||||
string.Empty,
|
options.VSyncMode,
|
||||||
string.Empty,
|
!options.DisableDockedMode,
|
||||||
options.CustomVSyncInterval
|
!options.DisablePTC,
|
||||||
)
|
options.EnableInternetAccess,
|
||||||
.Configure(
|
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||||
_virtualFileSystem,
|
options.FsGlobalAccessLogMode,
|
||||||
_libHacHorizonManager,
|
options.SystemTimeOffset,
|
||||||
_contentManager,
|
options.SystemTimeZone,
|
||||||
_accountManager,
|
options.MemoryManagerMode,
|
||||||
_userChannelPersistence,
|
options.IgnoreMissingServices,
|
||||||
renderer.TryMakeThreaded(options.BackendThreading),
|
options.AspectRatio,
|
||||||
new SDL2HardwareDeviceDriver(),
|
options.AudioVolume,
|
||||||
window
|
options.UseHypervisor ?? true,
|
||||||
)
|
options.MultiplayerLanInterfaceId,
|
||||||
);
|
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
||||||
|
false,
|
||||||
|
string.Empty,
|
||||||
|
string.Empty,
|
||||||
|
options.CustomVSyncInterval);
|
||||||
|
|
||||||
|
return new Switch(configuration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Ava.Systems.Configuration.System;
|
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
|
@ -38,7 +37,7 @@ namespace Ryujinx.Headless
|
||||||
EnableInternetAccess = configurationState.System.EnableInternetAccess;
|
EnableInternetAccess = configurationState.System.EnableInternetAccess;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
||||||
DisableFsIntegrityChecks = !configurationState.System.EnableFsIntegrityChecks;
|
DisableFsIntegrityChecks = configurationState.System.EnableFsIntegrityChecks;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
||||||
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
||||||
|
@ -59,10 +58,10 @@ namespace Ryujinx.Headless
|
||||||
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(SystemLanguage)))
|
if (NeedsOverride(nameof(SystemLanguage)))
|
||||||
SystemLanguage = configurationState.System.Language.Value.ToHLE();
|
SystemLanguage = (SystemLanguage)(int)configurationState.System.Language.Value;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(SystemRegion)))
|
if (NeedsOverride(nameof(SystemRegion)))
|
||||||
SystemRegion = configurationState.System.Region.Value.ToHLE();
|
SystemRegion = (RegionCode)(int)configurationState.System.Region.Value;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(SystemTimeZone)))
|
if (NeedsOverride(nameof(SystemTimeZone)))
|
||||||
SystemTimeZone = configurationState.System.TimeZone;
|
SystemTimeZone = configurationState.System.TimeZone;
|
||||||
|
|
|
@ -5,12 +5,10 @@ using Gommon;
|
||||||
using Projektanker.Icons.Avalonia;
|
using Projektanker.Icons.Avalonia;
|
||||||
using Projektanker.Icons.Avalonia.FontAwesome;
|
using Projektanker.Icons.Avalonia.FontAwesome;
|
||||||
using Projektanker.Icons.Avalonia.MaterialDesign;
|
using Projektanker.Icons.Avalonia.MaterialDesign;
|
||||||
using Ryujinx.Ava.Systems;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Ava.Systems.Configuration.System;
|
|
||||||
using Ryujinx.Ava.Utilities.SystemInfo;
|
using Ryujinx.Ava.Utilities.SystemInfo;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
|
@ -34,10 +32,8 @@ namespace Ryujinx.Ava
|
||||||
public static double DesktopScaleFactor { get; set; } = 1.0;
|
public static double DesktopScaleFactor { get; set; } = 1.0;
|
||||||
public static string Version { get; private set; }
|
public static string Version { get; private set; }
|
||||||
public static string ConfigurationPath { get; private set; }
|
public static string ConfigurationPath { get; private set; }
|
||||||
public static string GlobalConfigurationPath { get; private set; }
|
|
||||||
public static bool PreviewerDetached { get; private set; }
|
public static bool PreviewerDetached { get; private set; }
|
||||||
public static bool UseHardwareAcceleration { get; private set; }
|
public static bool UseHardwareAcceleration { get; private set; }
|
||||||
public static string BackendThreadingArg { get; private set; }
|
|
||||||
|
|
||||||
[LibraryImport("user32.dll", SetLastError = true)]
|
[LibraryImport("user32.dll", SetLastError = true)]
|
||||||
public static partial int MessageBoxA(nint hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
public static partial int MessageBoxA(nint hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
||||||
|
@ -160,38 +156,11 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(gameId))
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string gameDir = Path.Combine(AppDataManager.GamesDirPath, gameId, ReleaseInformation.ConfigName);
|
|
||||||
|
|
||||||
// Should load with the game if there is a custom setting for the game
|
|
||||||
if (rememberGlobalDir)
|
|
||||||
{
|
|
||||||
GlobalConfigurationPath = ConfigurationPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeFolderForGame)
|
|
||||||
{
|
|
||||||
ConfigurationPath = gameDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
return gameDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReloadConfig()
|
public static void ReloadConfig()
|
||||||
{
|
{
|
||||||
//It is necessary that when a user setting appears, the global setting remains available
|
|
||||||
GlobalConfigurationPath = null;
|
|
||||||
|
|
||||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||||
|
|
||||||
|
|
||||||
// Now load the configuration as the other subsystems are now registered
|
// Now load the configuration as the other subsystems are now registered
|
||||||
if (File.Exists(localConfigurationPath))
|
if (File.Exists(localConfigurationPath))
|
||||||
{
|
{
|
||||||
|
@ -248,11 +217,6 @@ namespace Ryujinx.Ava
|
||||||
_ => ConfigurationState.Instance.Graphics.BackendThreading
|
_ => ConfigurationState.Instance.Graphics.BackendThreading
|
||||||
};
|
};
|
||||||
|
|
||||||
if (CommandLineState.OverrideBackendThreadingAfterReboot is not null)
|
|
||||||
{
|
|
||||||
BackendThreadingArg = CommandLineState.OverrideBackendThreadingAfterReboot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if docked mode was overriden.
|
// Check if docked mode was overriden.
|
||||||
if (CommandLineState.OverrideDockedMode.HasValue)
|
if (CommandLineState.OverrideDockedMode.HasValue)
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
||||||
|
@ -268,33 +232,6 @@ namespace Ryujinx.Ava
|
||||||
_ => ConfigurationState.Instance.HideCursor,
|
_ => ConfigurationState.Instance.HideCursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if memoryManagerMode was overridden.
|
|
||||||
if (CommandLineState.OverrideMemoryManagerMode is not null)
|
|
||||||
if (Enum.TryParse(CommandLineState.OverrideMemoryManagerMode, true, out MemoryManagerMode result))
|
|
||||||
{
|
|
||||||
ConfigurationState.Instance.System.MemoryManagerMode.Value = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if PPTC was overridden.
|
|
||||||
if (CommandLineState.OverridePPTC is not null)
|
|
||||||
if (Enum.TryParse(CommandLineState.OverridePPTC, true, out bool result))
|
|
||||||
{
|
|
||||||
ConfigurationState.Instance.System.EnablePtc.Value = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if region was overridden.
|
|
||||||
if (CommandLineState.OverrideSystemRegion is not null)
|
|
||||||
if (Enum.TryParse(CommandLineState.OverrideSystemRegion, true, out HLE.HOS.SystemState.RegionCode result))
|
|
||||||
{
|
|
||||||
ConfigurationState.Instance.System.Region.Value = result.ToUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if language was overridden.
|
|
||||||
if (CommandLineState.OverrideSystemLanguage is not null)
|
|
||||||
if (Enum.TryParse(CommandLineState.OverrideSystemLanguage, true, out HLE.HOS.SystemState.SystemLanguage result))
|
|
||||||
{
|
|
||||||
ConfigurationState.Instance.System.Language.Value = result.ToUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if hardware-acceleration was overridden.
|
// Check if hardware-acceleration was overridden.
|
||||||
if (CommandLineState.OverrideHardwareAcceleration != null)
|
if (CommandLineState.OverrideHardwareAcceleration != null)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64;</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>1.0.0-dirty</Version>
|
<Version>1.0.0-dirty</Version>
|
||||||
|
@ -29,18 +29,12 @@
|
||||||
<TrimMode>partial</TrimMode>
|
<TrimMode>partial</TrimMode>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-arm64'">
|
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
|
||||||
<PublishTrimmed>false</PublishTrimmed>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json.
|
FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json.
|
||||||
See:
|
See:
|
||||||
https://github.com/amwx/FluentAvalonia/issues/481
|
https://github.com/amwx/FluentAvalonia/issues/481
|
||||||
https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-8/
|
https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-8/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
|
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -63,8 +57,8 @@
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" />
|
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" />
|
||||||
<PackageReference Include="OpenTK.Core" />
|
<PackageReference Include="OpenTK.Core" />
|
||||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" />
|
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" />
|
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
||||||
<PackageReference Include="securifybv.ShellLink" />
|
<PackageReference Include="securifybv.ShellLink" />
|
||||||
<PackageReference Include="Sep" />
|
<PackageReference Include="Sep" />
|
||||||
<PackageReference Include="Silk.NET.Vulkan" />
|
<PackageReference Include="Silk.NET.Vulkan" />
|
||||||
|
@ -73,7 +67,7 @@
|
||||||
<PackageReference Include="SPB" />
|
<PackageReference Include="SPB" />
|
||||||
<PackageReference Include="SharpZipLib" />
|
<PackageReference Include="SharpZipLib" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
|
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
|
||||||
|
@ -90,19 +84,17 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'">
|
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<TargetPath>alsoft.ini</TargetPath>
|
<TargetPath>alsoft.ini</TargetPath>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||||
<Visible>False</Visible>
|
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="..\..\LICENSE.txt">
|
<Content Include="..\..\LICENSE.txt">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<TargetPath>LICENSE.txt</TargetPath>
|
<TargetPath>LICENSE.txt</TargetPath>
|
||||||
<Visible>False</Visible>
|
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -120,10 +112,6 @@
|
||||||
<AvaloniaResource Include="UI\**\*.xaml">
|
<AvaloniaResource Include="UI\**\*.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AvaloniaResource>
|
</AvaloniaResource>
|
||||||
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-Bold.ttf" />
|
|
||||||
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-BoldItalic.ttf" />
|
|
||||||
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-Italic.ttf" />
|
|
||||||
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-Regular.ttf" />
|
|
||||||
<AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" />
|
<AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" />
|
||||||
<AvaloniaResource Include="Assets\Styles\Themes.xaml">
|
<AvaloniaResource Include="Assets\Styles\Themes.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|
|
@ -17,9 +17,4 @@
|
||||||
<sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
|
<sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
|
||||||
<StyleInclude Source="/Assets/Styles/Styles.xaml" />
|
<StyleInclude Source="/Assets/Styles/Styles.xaml" />
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
<NativeMenu.Menu>
|
|
||||||
<NativeMenu>
|
|
||||||
<NativeMenuItem Header="About Ryujinx" Click="AboutRyujinx_OnClick" />
|
|
||||||
</NativeMenu>
|
|
||||||
</NativeMenu.Menu>
|
|
||||||
</Application>
|
</Application>
|
|
@ -7,12 +7,12 @@ using Avalonia.Styling;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.Common;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Ava.UI.Views.Dialog;
|
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
@ -147,10 +147,5 @@ namespace Ryujinx.Ava
|
||||||
Current is RyujinxApp { PlatformSettings: not null } app
|
Current is RyujinxApp { PlatformSettings: not null } app
|
||||||
? ConvertThemeVariant(app.PlatformSettings.GetColorValues().ThemeVariant)
|
? ConvertThemeVariant(app.PlatformSettings.GetColorValues().ThemeVariant)
|
||||||
: ThemeVariant.Default;
|
: ThemeVariant.Default;
|
||||||
|
|
||||||
private async void AboutRyujinx_OnClick(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
await AboutView.Show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Systems.Configuration.System
|
|
||||||
{
|
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<Region>))]
|
|
||||||
public enum Region
|
|
||||||
{
|
|
||||||
Japan,
|
|
||||||
USA,
|
|
||||||
Europe,
|
|
||||||
Australia,
|
|
||||||
China,
|
|
||||||
Korea,
|
|
||||||
Taiwan,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RegionEnumHelper
|
|
||||||
{
|
|
||||||
public static Region ToUI(this HLE.HOS.SystemState.RegionCode hleRegion)
|
|
||||||
=> (Region)hleRegion;
|
|
||||||
|
|
||||||
public static HLE.HOS.SystemState.RegionCode ToHLE(this Region uiRegion)
|
|
||||||
=> (HLE.HOS.SystemState.RegionCode)uiRegion;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
using FluentAvalonia.UI.Controls;
|
|
||||||
using Ryujinx.Ava.Common.Locale;
|
|
||||||
using Ryujinx.Ava.Utilities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Systems
|
|
||||||
{
|
|
||||||
internal static class Rebooter
|
|
||||||
{
|
|
||||||
|
|
||||||
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
|
||||||
|
|
||||||
|
|
||||||
public static void RebootAppWithGame(string gamePath, List<string> args)
|
|
||||||
{
|
|
||||||
_ = Reboot(gamePath, args);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task Reboot(string gamePath, List<string> args)
|
|
||||||
{
|
|
||||||
|
|
||||||
bool shouldRestart = true;
|
|
||||||
|
|
||||||
TaskDialog taskDialog = new()
|
|
||||||
{
|
|
||||||
Header = LocaleManager.Instance[LocaleKeys.RyujinxRebooter],
|
|
||||||
SubHeader = LocaleManager.Instance[LocaleKeys.DialogRebooterMessage],
|
|
||||||
IconSource = new SymbolIconSource { Symbol = Symbol.Games },
|
|
||||||
XamlRoot = RyujinxApp.MainWindow,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (shouldRestart)
|
|
||||||
{
|
|
||||||
List<string> arguments = CommandLineState.Arguments.ToList();
|
|
||||||
string executableDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
|
||||||
|
|
||||||
var dialogTask = taskDialog.ShowAsync(true);
|
|
||||||
await Task.Delay(500);
|
|
||||||
|
|
||||||
// Find the process name.
|
|
||||||
string ryuName = Path.GetFileName(Environment.ProcessPath) ?? string.Empty;
|
|
||||||
|
|
||||||
// Fallback if the executable could not be found.
|
|
||||||
if (ryuName.Length == 0 || !Path.Exists(Path.Combine(executableDirectory, ryuName)))
|
|
||||||
{
|
|
||||||
ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx";
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessStartInfo processStart = new(ryuName)
|
|
||||||
{
|
|
||||||
UseShellExecute = true,
|
|
||||||
WorkingDirectory = executableDirectory,
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var arg in args)
|
|
||||||
{
|
|
||||||
processStart.ArgumentList.Add(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
processStart.ArgumentList.Add(gamePath);
|
|
||||||
|
|
||||||
Process.Start(processStart);
|
|
||||||
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.HOS.Applets;
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
|
@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Applet
|
||||||
_parent.SettingsWindow =
|
_parent.SettingsWindow =
|
||||||
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
||||||
|
|
||||||
await StyleableAppWindow.ShowAsync(_parent.SettingsWindow, window);
|
await _parent.SettingsWindow.ShowDialog(window);
|
||||||
|
|
||||||
_parent.SettingsWindow = null;
|
_parent.SettingsWindow = null;
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,12 @@
|
||||||
<viewModels:ProfileSelectorDialogViewModel />
|
<viewModels:ProfileSelectorDialogViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDefinitions="*,Auto">
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Border
|
<Border
|
||||||
CornerRadius="5"
|
CornerRadius="5"
|
||||||
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
|
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
|
||||||
|
|
|
@ -9,14 +9,17 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
||||||
using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Applet
|
namespace Ryujinx.Ava.UI.Applet
|
||||||
{
|
{
|
||||||
public partial class ProfileSelectorDialog : RyujinxControl<ProfileSelectorDialogViewModel>
|
public partial class ProfileSelectorDialog : UserControl
|
||||||
{
|
{
|
||||||
|
public ProfileSelectorDialogViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
|
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
|
||||||
{
|
{
|
||||||
DataContext = ViewModel = viewModel;
|
DataContext = ViewModel = viewModel;
|
||||||
|
|
|
@ -19,18 +19,6 @@
|
||||||
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
||||||
Icon="{ext:Icon fa-solid fa-bookmark}"
|
Icon="{ext:Icon fa-solid fa-bookmark}"
|
||||||
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||||
<MenuItem
|
|
||||||
Click="EditGameConfiguration_Click"
|
|
||||||
IsVisible="{Binding SelectedApplication.HasIndependentConfiguration}"
|
|
||||||
Header="{ext:Locale GameListContextMenuEditCustomConfiguration}"
|
|
||||||
Icon="{ext:Icon fa-solid fa-gear}"
|
|
||||||
ToolTip.Tip="{ext:Locale EditCustomConfigurationToolTip}" />
|
|
||||||
<MenuItem
|
|
||||||
Click="EditGameConfiguration_Click"
|
|
||||||
IsVisible="{Binding !SelectedApplication.HasIndependentConfiguration}"
|
|
||||||
Header="{ext:Locale GameListContextMenuCreateCustomConfiguration}"
|
|
||||||
Icon="{ext:Icon fa-solid fa-gear}"
|
|
||||||
ToolTip.Tip="{ext:Locale CreateCustomConfigurationToolTip}" />
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
IsVisible="{Binding HasCompatibilityEntry}"
|
IsVisible="{Binding HasCompatibilityEntry}"
|
||||||
Click="OpenApplicationCompatibility_Click"
|
Click="OpenApplicationCompatibility_Click"
|
||||||
|
|
|
@ -11,8 +11,8 @@ using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.UI.Views.Dialog;
|
using Ryujinx.Ava.Utilities.Compat;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
|
@ -26,7 +26,6 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public class ApplicationContextMenu : MenuFlyout
|
public class ApplicationContextMenu : MenuFlyout
|
||||||
{
|
{
|
||||||
|
|
||||||
public ApplicationContextMenu()
|
public ApplicationContextMenu()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -80,26 +79,23 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
await TitleUpdateWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
await DownloadableContentManagerWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await StyleableAppWindow.ShowAsync(
|
await new CheatWindow(
|
||||||
new CheatWindow(
|
viewModel.VirtualFileSystem,
|
||||||
viewModel.VirtualFileSystem,
|
viewModel.SelectedApplication.IdString,
|
||||||
viewModel.SelectedApplication.IdString,
|
viewModel.SelectedApplication.Name,
|
||||||
viewModel.SelectedApplication.Name,
|
viewModel.SelectedApplication.Path).ShowDialog((Window)viewModel.TopLevel);
|
||||||
viewModel.SelectedApplication.Path
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
||||||
|
@ -127,7 +123,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await ModManagerView.Show(
|
await ModManagerWindow.Show(
|
||||||
viewModel.SelectedApplication.Id,
|
viewModel.SelectedApplication.Id,
|
||||||
viewModel.SelectedApplication.IdBase,
|
viewModel.SelectedApplication.IdBase,
|
||||||
viewModel.ApplicationLibrary,
|
viewModel.ApplicationLibrary,
|
||||||
|
@ -204,7 +200,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
if (backupDir.Exists)
|
if (backupDir.Exists)
|
||||||
{
|
{
|
||||||
cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
|
cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
|
||||||
cacheFiles.AddRange(backupDir.EnumerateFiles("*.info"));
|
cacheFiles.AddRange(mainDir.EnumerateFiles("*.info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheFiles.Count > 0)
|
if (cacheFiles.Count > 0)
|
||||||
|
@ -390,26 +386,13 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
viewModel.SelectedApplication.Icon
|
viewModel.SelectedApplication.Icon
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void EditGameConfiguration_Click(object sender, RoutedEventArgs args)
|
|
||||||
{
|
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
|
||||||
{
|
|
||||||
await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel));
|
|
||||||
|
|
||||||
// just checking for file presence
|
|
||||||
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
|
||||||
|
|
||||||
viewModel.RefreshView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString);
|
await CompatibilityList.Show(viewModel.SelectedApplication.IdString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OpenApplicationData_Click(object sender, RoutedEventArgs args)
|
public async void OpenApplicationData_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Dialog.ApplicationDataView"
|
x:Class="Ryujinx.Ava.UI.Controls.ApplicationDataView"
|
||||||
x:DataType="viewModels:ApplicationDataViewModel">
|
x:DataType="viewModels:ApplicationDataViewModel">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<Image Margin="0"
|
<Image Margin="0"
|
|
@ -1,20 +1,20 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input.Platform;
|
using Avalonia.Input.Platform;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Styling;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
|
using Ryujinx.Ava.Utilities.Compat;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Dialog
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class ApplicationDataView : RyujinxControl<ApplicationDataViewModel>
|
public partial class ApplicationDataView : UserControl
|
||||||
{
|
{
|
||||||
public static async Task Show(ApplicationData appData)
|
public static async Task Show(ApplicationData appData)
|
||||||
{
|
{
|
||||||
|
@ -25,10 +25,20 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
||||||
SecondaryButtonText = string.Empty,
|
SecondaryButtonText = string.Empty,
|
||||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
CloseButtonText = LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
||||||
MinWidth = 256,
|
MinWidth = 256,
|
||||||
Content = new ApplicationDataView { ViewModel = new ApplicationDataViewModel(appData) }
|
Content = new ApplicationDataView { DataContext = new ApplicationDataViewModel(appData) }
|
||||||
};
|
};
|
||||||
|
|
||||||
await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles(160, HorizontalAlignment.Center));
|
Style closeButton = new(x => x.Name("CloseButton"));
|
||||||
|
closeButton.Setters.Add(new Setter(WidthProperty, 160d));
|
||||||
|
|
||||||
|
Style closeButtonParent = new(x => x.Name("CommandSpace"));
|
||||||
|
closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty,
|
||||||
|
Avalonia.Layout.HorizontalAlignment.Center));
|
||||||
|
|
||||||
|
contentDialog.Styles.Add(closeButton);
|
||||||
|
contentDialog.Styles.Add(closeButtonParent);
|
||||||
|
|
||||||
|
await ContentDialogHelper.ShowAsync(contentDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationDataView()
|
public ApplicationDataView()
|
||||||
|
@ -44,18 +54,21 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
||||||
if (RyujinxApp.AppLifetime.Windows.TryGetFirst(x => x is ContentDialogOverlayWindow, out Window window))
|
if (RyujinxApp.AppLifetime.Windows.TryGetFirst(x => x is ContentDialogOverlayWindow, out Window window))
|
||||||
window.Close(ContentDialogResult.None);
|
window.Close(ContentDialogResult.None);
|
||||||
|
|
||||||
await CompatibilityListWindow.Show((string)playabilityLabel.Tag);
|
await CompatibilityList.Show((string)playabilityLabel.Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (DataContext is not MainWindowViewModel mwvm)
|
||||||
|
return;
|
||||||
|
|
||||||
if (sender is not Button { Content: TextBlock idText })
|
if (sender is not Button { Content: TextBlock idText })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ApplicationData appData = RyujinxApp.MainWindow.ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
ApplicationData appData = mwvm.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
||||||
if (appData is null)
|
if (appData is null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<UserControl
|
<UserControl
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Misc.ApplicationGridView"
|
x:Class="Ryujinx.Ava.UI.Controls.ApplicationGridView"
|
||||||
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:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
|
@ -7,14 +7,16 @@
|
||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
Focusable="True"
|
Focusable="True"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
x:DataType="viewModels:MainWindowViewModel">
|
x:DataType="viewModels:MainWindowViewModel">
|
||||||
<Grid RowDefinitions="*">
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<ListBox
|
<ListBox
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Padding="8"
|
Padding="8"
|
||||||
|
@ -54,7 +56,11 @@
|
||||||
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
|
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
|
||||||
ClipToBounds="True"
|
ClipToBounds="True"
|
||||||
CornerRadius="4">
|
CornerRadius="4">
|
||||||
<Grid RowDefinitions="Auto,Auto">
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<Image
|
<Image
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
|
@ -67,18 +73,12 @@
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
<TextBlock
|
||||||
<TextBlock
|
HorizontalAlignment="Center"
|
||||||
Text="{Binding Name}"
|
VerticalAlignment="Center"
|
||||||
TextAlignment="Center"
|
Text="{Binding Name}"
|
||||||
TextWrapping="Wrap" />
|
TextAlignment="Center"
|
||||||
<TextBlock
|
TextWrapping="Wrap" />
|
||||||
IsVisible="{Binding HasIndependentConfiguration}"
|
|
||||||
Text="{ext:Locale GameSpecificConfigurationHeader}"
|
|
||||||
TextAlignment="Center"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
Foreground="{DynamicResource Warning}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Panel>
|
</Panel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
@ -86,28 +86,10 @@
|
||||||
Margin="5,5,0,0"
|
Margin="5,5,0,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
FontSize="18"
|
FontSize="16"
|
||||||
Foreground="{DynamicResource FavoriteApplicationIconColor}"
|
Foreground="{DynamicResource FavoriteApplicationIconColor}"
|
||||||
IsVisible="{Binding Favorite}"
|
IsVisible="{Binding Favorite}"
|
||||||
Symbol="StarFilled" />
|
Symbol="StarFilled" />
|
||||||
<Grid IsVisible="{Binding !$parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
|
||||||
<Border
|
|
||||||
Margin="15,35,5,15"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
VerticalAlignment="Bottom"
|
|
||||||
Width="90"
|
|
||||||
Height="20"
|
|
||||||
CornerRadius="4"
|
|
||||||
IsVisible="{Binding HasIndependentConfiguration}"
|
|
||||||
Background="{DynamicResource ThemeContentBackgroundColor}">
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Text="{ext:Locale GameSpecificConfigurationHeader}"
|
|
||||||
TextAlignment="Center"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
|
@ -1,15 +1,13 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Misc
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class ApplicationGridView : RyujinxControl<MainWindowViewModel>
|
public partial class ApplicationGridView : UserControl
|
||||||
{
|
{
|
||||||
public static readonly RoutedEvent<ApplicationOpenedEventArgs> ApplicationOpenedEvent =
|
public static readonly RoutedEvent<ApplicationOpenedEventArgs> ApplicationOpenedEvent =
|
||||||
RoutedEvent.Register<ApplicationGridView, ApplicationOpenedEventArgs>(nameof(ApplicationOpened), RoutingStrategies.Bubble);
|
RoutedEvent.Register<ApplicationGridView, ApplicationOpenedEventArgs>(nameof(ApplicationOpened), RoutingStrategies.Bubble);
|
|
@ -1,19 +1,21 @@
|
||||||
<UserControl
|
<UserControl
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Misc.ApplicationListView"
|
x:Class="Ryujinx.Ava.UI.Controls.ApplicationListView"
|
||||||
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"
|
||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
Focusable="True"
|
Focusable="True"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
x:DataType="viewModels:MainWindowViewModel">
|
x:DataType="viewModels:MainWindowViewModel">
|
||||||
<Grid RowDefinitions="*">
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<ListBox
|
<ListBox
|
||||||
Name="GameListBox"
|
Name="GameListBox"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
|
@ -154,13 +156,6 @@
|
||||||
Text="{Binding Converter={x:Static helpers:MultiplayerInfoConverter.Instance}}"
|
Text="{Binding Converter={x:Static helpers:MultiplayerInfoConverter.Instance}}"
|
||||||
TextAlignment="Start"
|
TextAlignment="Start"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
IsVisible="{Binding HasIndependentConfiguration}"
|
|
||||||
Text="{ext:Locale GameSpecificConfigurationHeader}"
|
|
||||||
TextAlignment="Start"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
Foreground="{DynamicResource Warning}" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="4"
|
Grid.Column="4"
|
|
@ -2,17 +2,16 @@ using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Input.Platform;
|
using Avalonia.Input.Platform;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.Utilities.Compat;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Misc
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class ApplicationListView : RyujinxControl<MainWindowViewModel>
|
public partial class ApplicationListView : UserControl
|
||||||
{
|
{
|
||||||
public static readonly RoutedEvent<ApplicationOpenedEventArgs> ApplicationOpenedEvent =
|
public static readonly RoutedEvent<ApplicationOpenedEventArgs> ApplicationOpenedEvent =
|
||||||
RoutedEvent.Register<ApplicationListView, ApplicationOpenedEventArgs>(nameof(ApplicationOpened), RoutingStrategies.Bubble);
|
RoutedEvent.Register<ApplicationListView, ApplicationOpenedEventArgs>(nameof(ApplicationOpened), RoutingStrategies.Bubble);
|
||||||
|
@ -33,21 +32,27 @@ namespace Ryujinx.Ava.UI.Views.Misc
|
||||||
|
|
||||||
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
|
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (DataContext is not MainWindowViewModel mwvm)
|
||||||
|
return;
|
||||||
|
|
||||||
if (sender is not Button { Content: TextBlock playabilityLabel })
|
if (sender is not Button { Content: TextBlock playabilityLabel })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await CompatibilityListWindow.Show((string)playabilityLabel.Tag);
|
await CompatibilityList.Show((string)playabilityLabel.Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (DataContext is not MainWindowViewModel mwvm)
|
||||||
|
return;
|
||||||
|
|
||||||
if (sender is not Button { Content: TextBlock idText })
|
if (sender is not Button { Content: TextBlock idText })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ApplicationData appData = ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
ApplicationData appData = mwvm.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
||||||
if (appData is null)
|
if (appData is null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
xmlns:models="using:Ryujinx.Ava.Common.Models"
|
xmlns:models="using:Ryujinx.Ava.Common.Models"
|
||||||
xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Dialog.DlcSelectView"
|
x:Class="Ryujinx.Ava.UI.Controls.DlcSelectView"
|
||||||
x:DataType="viewModels:DlcSelectViewModel">
|
x:DataType="viewModels:DlcSelectViewModel">
|
||||||
<Grid RowDefinitions="*,Auto,*">
|
<Grid RowDefinitions="*,Auto,*">
|
||||||
<TextBlock
|
<TextBlock
|
|
@ -1,15 +1,16 @@
|
||||||
using FluentAvalonia.UI.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Styling;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Dialog
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class DlcSelectView : RyujinxControl<DlcSelectViewModel>
|
public partial class DlcSelectView : UserControl
|
||||||
{
|
{
|
||||||
public DlcSelectView()
|
public DlcSelectView()
|
||||||
{
|
{
|
||||||
|
@ -27,10 +28,20 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
||||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.Continue],
|
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.Continue],
|
||||||
SecondaryButtonText = string.Empty,
|
SecondaryButtonText = string.Empty,
|
||||||
CloseButtonText = string.Empty,
|
CloseButtonText = string.Empty,
|
||||||
Content = new DlcSelectView { ViewModel = viewModel }
|
Content = new DlcSelectView { DataContext = viewModel }
|
||||||
};
|
};
|
||||||
|
|
||||||
await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles());
|
Style closeButton = new(x => x.Name("CloseButton"));
|
||||||
|
closeButton.Setters.Add(new Setter(WidthProperty, 80d));
|
||||||
|
|
||||||
|
Style closeButtonParent = new(x => x.Name("CommandSpace"));
|
||||||
|
closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty,
|
||||||
|
Avalonia.Layout.HorizontalAlignment.Right));
|
||||||
|
|
||||||
|
contentDialog.Styles.Add(closeButton);
|
||||||
|
contentDialog.Styles.Add(closeButtonParent);
|
||||||
|
|
||||||
|
await ContentDialogHelper.ShowAsync(contentDialog);
|
||||||
|
|
||||||
return viewModel.SelectedDlc;
|
return viewModel.SelectedDlc;
|
||||||
}
|
}
|
|
@ -23,12 +23,13 @@ using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class NavigationDialogHost : RyujinxControl<UserProfileViewModel>
|
public partial class NavigationDialogHost : UserControl
|
||||||
{
|
{
|
||||||
public AccountManager AccountManager { get; }
|
public AccountManager AccountManager { get; }
|
||||||
public ContentManager ContentManager { get; }
|
public ContentManager ContentManager { get; }
|
||||||
public VirtualFileSystem VirtualFileSystem { get; }
|
public VirtualFileSystem VirtualFileSystem { get; }
|
||||||
public HorizonClient HorizonClient { get; }
|
public HorizonClient HorizonClient { get; }
|
||||||
|
public UserProfileViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
public NavigationDialogHost()
|
public NavigationDialogHost()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
using Avalonia.Controls;
|
|
||||||
using Gommon;
|
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
|
||||||
{
|
|
||||||
public class RyujinxControl<TViewModel> : UserControl where TViewModel : BaseModel
|
|
||||||
{
|
|
||||||
public TViewModel ViewModel
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (DataContext is not TViewModel viewModel)
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
$"Underlying DataContext is not of type {typeof(TViewModel).AsPrettyString()}; " +
|
|
||||||
$"Actual type is {DataContext?.GetType().AsPrettyString()}");
|
|
||||||
|
|
||||||
return viewModel;
|
|
||||||
}
|
|
||||||
set => DataContext = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
|
||||||
{
|
|
||||||
public class RyujinxLogo : Image
|
|
||||||
{
|
|
||||||
// The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions.
|
|
||||||
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
|
||||||
// The border gets reduced to colored pixels in the 4 corners.
|
|
||||||
public static readonly Bitmap Bitmap =
|
|
||||||
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
|
|
||||||
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
|
|
||||||
|
|
||||||
public RyujinxLogo()
|
|
||||||
{
|
|
||||||
Margin = new Thickness(7, 7, 7, 0);
|
|
||||||
Height = 25;
|
|
||||||
Width = 25;
|
|
||||||
Source = Bitmap;
|
|
||||||
IsVisible = !ConfigurationState.Instance.ShowOldUI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
<Window
|
<Window
|
||||||
x:Class="Ryujinx.Ava.UI.Windows.UpdateWaitWindow"
|
x:Class="Ryujinx.Ava.UI.Controls.UpdateWaitWindow"
|
||||||
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"
|
||||||
|
@ -13,7 +13,15 @@
|
||||||
<Grid
|
<Grid
|
||||||
Margin="20"
|
Margin="20"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch" ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto">
|
VerticalAlignment="Stretch">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<Image
|
<Image
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Height="70"
|
Height="70"
|
|
@ -1,7 +1,8 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class UpdateWaitWindow : StyleableWindow
|
public partial class UpdateWaitWindow : StyleableWindow
|
||||||
{
|
{
|
|
@ -1,5 +1,5 @@
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Helpers
|
namespace Ryujinx.Ava.UI.Helpers
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input;
|
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Styling;
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using FluentAvalonia.Core;
|
using FluentAvalonia.Core;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
|
@ -22,23 +20,6 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||||
private static bool _isChoiceDialogOpen;
|
private static bool _isChoiceDialogOpen;
|
||||||
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
|
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
|
||||||
|
|
||||||
public static ContentDialog ApplyStyles(
|
|
||||||
this ContentDialog contentDialog,
|
|
||||||
double closeButtonWidth = 80,
|
|
||||||
HorizontalAlignment buttonSpaceAlignment = HorizontalAlignment.Right)
|
|
||||||
{
|
|
||||||
Style closeButton = new(x => x.Name("CloseButton"));
|
|
||||||
closeButton.Setters.Add(new Setter(Layoutable.WidthProperty, closeButtonWidth));
|
|
||||||
|
|
||||||
Style closeButtonParent = new(x => x.Name("CommandSpace"));
|
|
||||||
closeButtonParent.Setters.Add(new Setter(Layoutable.HorizontalAlignmentProperty, buttonSpaceAlignment));
|
|
||||||
|
|
||||||
contentDialog.Styles.Add(closeButton);
|
|
||||||
contentDialog.Styles.Add(closeButtonParent);
|
|
||||||
|
|
||||||
return contentDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async static Task<UserResult> ShowContentDialog(
|
private async static Task<UserResult> ShowContentDialog(
|
||||||
string title,
|
string title,
|
||||||
object content,
|
object content,
|
||||||
|
@ -58,19 +39,19 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||||
SecondaryButtonText = secondaryButton,
|
SecondaryButtonText = secondaryButton,
|
||||||
CloseButtonText = closeButton,
|
CloseButtonText = closeButton,
|
||||||
Content = content,
|
Content = content,
|
||||||
PrimaryButtonCommand = Commands.Create(() =>
|
PrimaryButtonCommand = MiniCommand.Create(() =>
|
||||||
{
|
{
|
||||||
result = primaryButtonResult;
|
result = primaryButtonResult;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
contentDialog.SecondaryButtonCommand = Commands.Create(() =>
|
contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
|
||||||
{
|
{
|
||||||
result = UserResult.No;
|
result = UserResult.No;
|
||||||
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
||||||
});
|
});
|
||||||
|
|
||||||
contentDialog.CloseButtonCommand = Commands.Create(() =>
|
contentDialog.CloseButtonCommand = MiniCommand.Create(() =>
|
||||||
{
|
{
|
||||||
result = UserResult.Cancel;
|
result = UserResult.Cancel;
|
||||||
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
||||||
|
@ -403,10 +384,6 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||||
Position = parent.PointToScreen(new Point()),
|
Position = parent.PointToScreen(new Point()),
|
||||||
ShowInTaskbar = false,
|
ShowInTaskbar = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
_contentDialogOverlayWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
parent.PositionChanged += OverlayOnPositionChanged;
|
parent.PositionChanged += OverlayOnPositionChanged;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ using Avalonia.Data.Converters;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Avalonia.Logging;
|
using Avalonia.Logging;
|
||||||
using Avalonia.Utilities;
|
using Avalonia.Utilities;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
72
src/Ryujinx/UI/Helpers/MiniCommand.cs
Normal file
72
src/Ryujinx/UI/Helpers/MiniCommand.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Helpers
|
||||||
|
{
|
||||||
|
public sealed class MiniCommand<T> : MiniCommand, ICommand
|
||||||
|
{
|
||||||
|
private readonly Action<T> _callback;
|
||||||
|
private bool _busy;
|
||||||
|
private readonly Func<T, Task> _asyncCallback;
|
||||||
|
|
||||||
|
public MiniCommand(Action<T> callback)
|
||||||
|
{
|
||||||
|
_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MiniCommand(Func<T, Task> callback)
|
||||||
|
{
|
||||||
|
_asyncCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Busy
|
||||||
|
{
|
||||||
|
get => _busy;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_busy = value;
|
||||||
|
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override event EventHandler CanExecuteChanged;
|
||||||
|
public override bool CanExecute(object parameter) => !_busy;
|
||||||
|
|
||||||
|
public override async void Execute(object parameter)
|
||||||
|
{
|
||||||
|
if (Busy)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Busy = true;
|
||||||
|
if (_callback != null)
|
||||||
|
{
|
||||||
|
_callback((T)parameter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _asyncCallback((T)parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Busy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class MiniCommand : ICommand
|
||||||
|
{
|
||||||
|
public static MiniCommand Create(Action callback) => new MiniCommand<object>(_ => callback());
|
||||||
|
public static MiniCommand Create<TArg>(Action<TArg> callback) => new MiniCommand<TArg>(callback);
|
||||||
|
public static MiniCommand CreateFromTask(Func<Task> callback) => new MiniCommand<object>(_ => callback());
|
||||||
|
public static MiniCommand CreateFromTask<TArg>(Func<TArg, Task> callback) => new MiniCommand<TArg>(callback);
|
||||||
|
|
||||||
|
public abstract bool CanExecute(object parameter);
|
||||||
|
public abstract void Execute(object parameter);
|
||||||
|
public abstract event EventHandler CanExecuteChanged;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
@ -1,260 +0,0 @@
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
|
||||||
using Ryujinx.Input;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Models.Input
|
|
||||||
{
|
|
||||||
public class StickVisualizer : BaseModel, IDisposable
|
|
||||||
{
|
|
||||||
public const int DrawStickPollRate = 50; // Milliseconds per poll.
|
|
||||||
public const int DrawStickCircumference = 5;
|
|
||||||
public const float DrawStickScaleFactor = DrawStickCanvasCenter;
|
|
||||||
public const int DrawStickCanvasSize = 100;
|
|
||||||
public const int DrawStickBorderSize = DrawStickCanvasSize + 5;
|
|
||||||
public const float DrawStickCanvasCenter = (DrawStickCanvasSize - DrawStickCircumference) / 2;
|
|
||||||
public const float MaxVectorLength = DrawStickCanvasSize / 2;
|
|
||||||
|
|
||||||
public CancellationTokenSource PollTokenSource;
|
|
||||||
public CancellationToken PollToken;
|
|
||||||
|
|
||||||
private static float _vectorLength;
|
|
||||||
private static float _vectorMultiplier;
|
|
||||||
|
|
||||||
private bool disposedValue;
|
|
||||||
|
|
||||||
private DeviceType _type;
|
|
||||||
public DeviceType Type
|
|
||||||
{
|
|
||||||
get => _type;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_type = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private GamepadInputConfig _gamepadConfig;
|
|
||||||
public GamepadInputConfig GamepadConfig
|
|
||||||
{
|
|
||||||
get => _gamepadConfig;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_gamepadConfig = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeyboardInputConfig _keyboardConfig;
|
|
||||||
public KeyboardInputConfig KeyboardConfig
|
|
||||||
{
|
|
||||||
get => _keyboardConfig;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_keyboardConfig = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private (float, float) _uiStickLeft;
|
|
||||||
public (float, float) UiStickLeft
|
|
||||||
{
|
|
||||||
get => (_uiStickLeft.Item1 * DrawStickScaleFactor, _uiStickLeft.Item2 * DrawStickScaleFactor);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_uiStickLeft = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
OnPropertyChanged(nameof(UiStickRightX));
|
|
||||||
OnPropertyChanged(nameof(UiStickRightY));
|
|
||||||
OnPropertyChanged(nameof(UiDeadzoneRight));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private (float, float) _uiStickRight;
|
|
||||||
public (float, float) UiStickRight
|
|
||||||
{
|
|
||||||
get => (_uiStickRight.Item1 * DrawStickScaleFactor, _uiStickRight.Item2 * DrawStickScaleFactor);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_uiStickRight = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
OnPropertyChanged(nameof(UiStickLeftX));
|
|
||||||
OnPropertyChanged(nameof(UiStickLeftY));
|
|
||||||
OnPropertyChanged(nameof(UiDeadzoneLeft));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public float UiStickLeftX => ClampVector(UiStickLeft).Item1;
|
|
||||||
public float UiStickLeftY => ClampVector(UiStickLeft).Item2;
|
|
||||||
public float UiStickRightX => ClampVector(UiStickRight).Item1;
|
|
||||||
public float UiStickRightY => ClampVector(UiStickRight).Item2;
|
|
||||||
|
|
||||||
public int UiStickCircumference => DrawStickCircumference;
|
|
||||||
public int UiCanvasSize => DrawStickCanvasSize;
|
|
||||||
public int UiStickBorderSize => DrawStickBorderSize;
|
|
||||||
|
|
||||||
public float? UiDeadzoneLeft => _gamepadConfig?.DeadzoneLeft * DrawStickCanvasSize - DrawStickCircumference;
|
|
||||||
public float? UiDeadzoneRight => _gamepadConfig?.DeadzoneRight * DrawStickCanvasSize - DrawStickCircumference;
|
|
||||||
|
|
||||||
private InputViewModel Parent;
|
|
||||||
|
|
||||||
public StickVisualizer(InputViewModel parent)
|
|
||||||
{
|
|
||||||
Parent = parent;
|
|
||||||
|
|
||||||
PollTokenSource = new CancellationTokenSource();
|
|
||||||
PollToken = PollTokenSource.Token;
|
|
||||||
|
|
||||||
Task.Run(Initialize, PollToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateConfig(object config)
|
|
||||||
{
|
|
||||||
if (config is ControllerInputViewModel padConfig)
|
|
||||||
{
|
|
||||||
GamepadConfig = padConfig.Config;
|
|
||||||
Type = DeviceType.Controller;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (config is KeyboardInputViewModel keyConfig)
|
|
||||||
{
|
|
||||||
KeyboardConfig = keyConfig.Config;
|
|
||||||
Type = DeviceType.Keyboard;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type = DeviceType.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Initialize()
|
|
||||||
{
|
|
||||||
(float, float) leftBuffer;
|
|
||||||
(float, float) rightBuffer;
|
|
||||||
|
|
||||||
while (!PollToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
leftBuffer = (0f, 0f);
|
|
||||||
rightBuffer = (0f, 0f);
|
|
||||||
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case DeviceType.Keyboard:
|
|
||||||
IKeyboard keyboard = (IKeyboard)Parent.AvaloniaKeyboardDriver.GetGamepad("0");
|
|
||||||
|
|
||||||
if (keyboard != null)
|
|
||||||
{
|
|
||||||
KeyboardStateSnapshot snapshot = keyboard.GetKeyboardStateSnapshot();
|
|
||||||
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickRight))
|
|
||||||
{
|
|
||||||
leftBuffer.Item1 += 1;
|
|
||||||
}
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickLeft))
|
|
||||||
{
|
|
||||||
leftBuffer.Item1 -= 1;
|
|
||||||
}
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickUp))
|
|
||||||
{
|
|
||||||
leftBuffer.Item2 += 1;
|
|
||||||
}
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickDown))
|
|
||||||
{
|
|
||||||
leftBuffer.Item2 -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickRight))
|
|
||||||
{
|
|
||||||
rightBuffer.Item1 += 1;
|
|
||||||
}
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickLeft))
|
|
||||||
{
|
|
||||||
rightBuffer.Item1 -= 1;
|
|
||||||
}
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickUp))
|
|
||||||
{
|
|
||||||
rightBuffer.Item2 += 1;
|
|
||||||
}
|
|
||||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickDown))
|
|
||||||
{
|
|
||||||
rightBuffer.Item2 -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
UiStickLeft = leftBuffer;
|
|
||||||
UiStickRight = rightBuffer;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType.Controller:
|
|
||||||
IGamepad controller = Parent.SelectedGamepad;
|
|
||||||
|
|
||||||
if (controller != null)
|
|
||||||
{
|
|
||||||
leftBuffer = controller.GetStick((StickInputId)GamepadConfig.LeftJoystick);
|
|
||||||
rightBuffer = controller.GetStick((StickInputId)GamepadConfig.RightJoystick);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType.None:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException($"Unable to poll device type \"{Type}\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
UiStickLeft = leftBuffer;
|
|
||||||
UiStickRight = rightBuffer;
|
|
||||||
|
|
||||||
await Task.Delay(DrawStickPollRate, PollToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
PollTokenSource.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (float, float) ClampVector((float, float) vect)
|
|
||||||
{
|
|
||||||
_vectorMultiplier = 1;
|
|
||||||
_vectorLength = MathF.Sqrt((vect.Item1 * vect.Item1) + (vect.Item2 * vect.Item2));
|
|
||||||
|
|
||||||
if (_vectorLength > MaxVectorLength)
|
|
||||||
{
|
|
||||||
_vectorMultiplier = MaxVectorLength / _vectorLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
vect.Item1 = vect.Item1 * _vectorMultiplier + DrawStickCanvasCenter;
|
|
||||||
vect.Item2 = vect.Item2 * _vectorMultiplier + DrawStickCanvasCenter;
|
|
||||||
|
|
||||||
return vect;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!disposedValue)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
PollTokenSource.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyboardConfig = null;
|
|
||||||
GamepadConfig = null;
|
|
||||||
Parent = null;
|
|
||||||
|
|
||||||
disposedValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ using LibHac.Fs;
|
||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using SPB.Graphics;
|
using SPB.Graphics;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Renderer
|
namespace Ryujinx.Ava.UI.Renderer
|
||||||
|
@ -36,6 +38,32 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||||
EmbeddedWindowOpenGL => GraphicsBackend.OpenGl,
|
EmbeddedWindowOpenGL => GraphicsBackend.OpenGl,
|
||||||
_ => throw new NotImplementedException()
|
_ => throw new NotImplementedException()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public RendererHost(string titleId)
|
||||||
|
{
|
||||||
|
Focusable = true;
|
||||||
|
FlowDirection = FlowDirection.LeftToRight;
|
||||||
|
|
||||||
|
EmbeddedWindow =
|
||||||
|
#pragma warning disable CS8524
|
||||||
|
ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
|
||||||
|
#pragma warning restore CS8524
|
||||||
|
{
|
||||||
|
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
||||||
|
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
|
||||||
|
};
|
||||||
|
|
||||||
|
string backendText = EmbeddedWindow switch
|
||||||
|
{
|
||||||
|
EmbeddedWindowVulkan => "Vulkan",
|
||||||
|
EmbeddedWindowOpenGL => "OpenGL",
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend ({ConfigurationState.Instance.Graphics.GraphicsBackend.Value}): {backendText}");
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
|
|
|
@ -3,8 +3,9 @@ using Avalonia.Styling;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.Common;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
|
@ -432,7 +432,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://raw.githubusercontent.com/Ryubing/Nfc/refs/heads/main/tags.json"));
|
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json"));
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
|
@ -451,7 +451,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await _httpClient.GetAsync("https://raw.githubusercontent.com/Ryubing/Nfc/refs/heads/main/tags.json");
|
HttpResponseMessage response = await _httpClient.GetAsync($"https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json");
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Systems.PlayReport;
|
using Ryujinx.Ava.Utilities.PlayReport;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
|
@ -7,7 +7,7 @@ using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -10,30 +10,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
{
|
{
|
||||||
public partial class ControllerInputViewModel : BaseModel
|
public partial class ControllerInputViewModel : BaseModel
|
||||||
{
|
{
|
||||||
private GamepadInputConfig _config;
|
[ObservableProperty] private GamepadInputConfig _config;
|
||||||
public GamepadInputConfig Config
|
|
||||||
{
|
|
||||||
get => _config;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_config = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private StickVisualizer _visualizer;
|
|
||||||
public StickVisualizer Visualizer
|
|
||||||
{
|
|
||||||
get => _visualizer;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_visualizer = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isLeft;
|
private bool _isLeft;
|
||||||
public bool IsLeft
|
public bool IsLeft
|
||||||
{
|
{
|
||||||
|
@ -59,15 +37,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasSides => IsLeft ^ IsRight;
|
public bool HasSides => IsLeft ^ IsRight;
|
||||||
|
|
||||||
[ObservableProperty] private SvgImage _image;
|
[ObservableProperty] private SvgImage _image;
|
||||||
|
|
||||||
public InputViewModel ParentModel { get; }
|
public InputViewModel ParentModel { get; }
|
||||||
|
|
||||||
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config, StickVisualizer visualizer)
|
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config)
|
||||||
{
|
{
|
||||||
ParentModel = model;
|
ParentModel = model;
|
||||||
Visualizer = visualizer;
|
|
||||||
model.NotifyChangesEvent += OnParentModelChanged;
|
model.NotifyChangesEvent += OnParentModelChanged;
|
||||||
OnParentModelChanged();
|
OnParentModelChanged();
|
||||||
config.PropertyChanged += (_, args) =>
|
config.PropertyChanged += (_, args) =>
|
||||||
|
|
|
@ -10,7 +10,7 @@ using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.UI.Models.Input;
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
@ -49,7 +49,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
private int _controller;
|
private int _controller;
|
||||||
private string _controllerImage;
|
private string _controllerImage;
|
||||||
private int _device;
|
private int _device;
|
||||||
private object _configViewModel;
|
[ObservableProperty] private object _configViewModel;
|
||||||
[ObservableProperty] private string _profileName;
|
[ObservableProperty] private string _profileName;
|
||||||
private bool _isLoaded;
|
private bool _isLoaded;
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public StickVisualizer VisualStick { get; private set; }
|
|
||||||
|
|
||||||
public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
|
public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
|
||||||
public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
|
public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
|
||||||
|
@ -95,19 +94,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
public bool IsModified { get; set; }
|
public bool IsModified { get; set; }
|
||||||
public event Action NotifyChangesEvent;
|
public event Action NotifyChangesEvent;
|
||||||
|
|
||||||
public object ConfigViewModel
|
|
||||||
{
|
|
||||||
get => _configViewModel;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_configViewModel = value;
|
|
||||||
|
|
||||||
VisualStick.UpdateConfig(value);
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayerIndex PlayerIdChoose
|
public PlayerIndex PlayerIdChoose
|
||||||
{
|
{
|
||||||
get => _playerIdChoose;
|
get => _playerIdChoose;
|
||||||
|
@ -283,7 +269,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
Devices = [];
|
Devices = [];
|
||||||
ProfilesList = [];
|
ProfilesList = [];
|
||||||
DeviceList = [];
|
DeviceList = [];
|
||||||
VisualStick = new StickVisualizer(this);
|
|
||||||
|
|
||||||
ControllerImage = ProControllerResource;
|
ControllerImage = ProControllerResource;
|
||||||
|
|
||||||
|
@ -304,12 +289,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
|
|
||||||
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
||||||
{
|
{
|
||||||
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig), VisualStick);
|
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config is StandardControllerInputConfig controllerInputConfig)
|
if (Config is StandardControllerInputConfig controllerInputConfig)
|
||||||
{
|
{
|
||||||
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick);
|
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,8 +893,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
||||||
|
|
||||||
VisualStick.Dispose();
|
|
||||||
|
|
||||||
SelectedGamepad?.Dispose();
|
SelectedGamepad?.Dispose();
|
||||||
|
|
||||||
AvaloniaKeyboardDriver.Dispose();
|
AvaloniaKeyboardDriver.Dispose();
|
||||||
|
|
|
@ -6,29 +6,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
{
|
{
|
||||||
public partial class KeyboardInputViewModel : BaseModel
|
public partial class KeyboardInputViewModel : BaseModel
|
||||||
{
|
{
|
||||||
private KeyboardInputConfig _config;
|
[ObservableProperty] private KeyboardInputConfig _config;
|
||||||
public KeyboardInputConfig Config
|
|
||||||
{
|
|
||||||
get => _config;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_config = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private StickVisualizer _visualizer;
|
|
||||||
public StickVisualizer Visualizer
|
|
||||||
{
|
|
||||||
get => _visualizer;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_visualizer = value;
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isLeft;
|
private bool _isLeft;
|
||||||
public bool IsLeft
|
public bool IsLeft
|
||||||
|
@ -60,10 +38,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
|
|
||||||
public readonly InputViewModel ParentModel;
|
public readonly InputViewModel ParentModel;
|
||||||
|
|
||||||
public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config, StickVisualizer visualizer)
|
public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config)
|
||||||
{
|
{
|
||||||
ParentModel = model;
|
ParentModel = model;
|
||||||
Visualizer = visualizer;
|
|
||||||
model.NotifyChangesEvent += OnParentModelChanged;
|
model.NotifyChangesEvent += OnParentModelChanged;
|
||||||
OnParentModelChanged();
|
OnParentModelChanged();
|
||||||
Config = config;
|
Config = config;
|
||||||
|
|
|
@ -3,7 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Avalonia.Controls;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
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;
|
||||||
|
@ -16,15 +17,14 @@ using LibHac.Ns;
|
||||||
using Ryujinx.Ava.Common;
|
using Ryujinx.Ava.Common;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Input;
|
using Ryujinx.Ava.Input;
|
||||||
using Ryujinx.Ava.Systems;
|
|
||||||
using Ryujinx.Ava.UI.Controls;
|
using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.UI.Models.Generic;
|
using Ryujinx.Ava.UI.Models.Generic;
|
||||||
using Ryujinx.Ava.UI.Renderer;
|
using Ryujinx.Ava.UI.Renderer;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
|
@ -46,6 +46,7 @@ using System.Collections.ObjectModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Key = Ryujinx.Input.Key;
|
using Key = Ryujinx.Input.Key;
|
||||||
|
@ -136,6 +137,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
// Key is Title ID
|
// Key is Title ID
|
||||||
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
|
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
|
||||||
|
|
||||||
|
// The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions.
|
||||||
|
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
||||||
|
// The border gets reduced to colored pixels in the 4 corners.
|
||||||
|
public static readonly Bitmap IconBitmap =
|
||||||
|
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
|
||||||
|
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
|
||||||
|
|
||||||
public MainWindow Window { get; init; }
|
public MainWindow Window { get; init; }
|
||||||
|
|
||||||
internal AppHost AppHost { get; set; }
|
internal AppHost AppHost { get; set; }
|
||||||
|
@ -348,11 +356,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
set
|
|
||||||
{
|
|
||||||
ListSelectedApplication = value;
|
|
||||||
GridSelectedApplication = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||||
|
@ -1082,7 +1085,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
_rendererWaitEvent.WaitOne();
|
_rendererWaitEvent.WaitOne();
|
||||||
|
|
||||||
AppHost?.Start();
|
AppHost?.Start();
|
||||||
|
|
||||||
AppHost?.DisposeContext();
|
AppHost?.DisposeContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,50 +1551,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool InitializeUserConfig(ApplicationData application)
|
|
||||||
{
|
|
||||||
// Code where conditions will be met before loading the user configuration (Global Config)
|
|
||||||
BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value;
|
|
||||||
string BackendThreadingInit = Program.BackendThreadingArg;
|
|
||||||
|
|
||||||
if (BackendThreadingInit is null)
|
|
||||||
{
|
|
||||||
BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
|
|
||||||
string idGame = application.IdBaseString;
|
|
||||||
if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat))
|
|
||||||
{
|
|
||||||
// Loads the user configuration, having previously changed the global configuration to the user configuration
|
|
||||||
ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true, true), idGame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code where conditions will be executed after loading user configuration
|
|
||||||
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
|
|
||||||
{
|
|
||||||
|
|
||||||
List<string> Arguments = new List<string>
|
|
||||||
{
|
|
||||||
"--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading
|
|
||||||
};
|
|
||||||
|
|
||||||
Rebooter.RebootAppWithGame(application.Path, Arguments);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (InitializeUserConfig(application))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AppHost != null)
|
if (AppHost != null)
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateInfoDialog(
|
await ContentDialogHelper.CreateInfoDialog(
|
||||||
|
@ -1607,7 +1568,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
#if RELEASE
|
#if RELEASE
|
||||||
await PerformanceCheck();
|
await PerformanceCheck();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Logger.RestartTime();
|
Logger.RestartTime();
|
||||||
|
|
||||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id);
|
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id);
|
||||||
|
@ -1652,7 +1613,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
||||||
gameThread.Start();
|
gameThread.Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SwitchToRenderer(bool startFullscreen) =>
|
public void SwitchToRenderer(bool startFullscreen) =>
|
||||||
|
@ -1739,7 +1699,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
|
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
|
||||||
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
|
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
|
||||||
|
|
||||||
await StyleableAppWindow.ShowAsync(window);
|
await window.ShowDialog(Window);
|
||||||
|
|
||||||
if (window.IsScanned)
|
if (window.IsScanned)
|
||||||
{
|
{
|
||||||
|
@ -1786,7 +1746,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
if (WindowState is not WindowState.Normal)
|
if (WindowState is not WindowState.Normal)
|
||||||
{
|
{
|
||||||
WindowState = WindowState.Normal;
|
WindowState = WindowState.Normal;
|
||||||
Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowOldUI;
|
Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowTitleBar;
|
||||||
|
|
||||||
if (IsGameRunning)
|
if (IsGameRunning)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
|
@ -16,12 +16,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
|
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
|
||||||
[ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted;
|
|
||||||
|
|
||||||
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
|
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
|
||||||
{
|
{
|
||||||
sb.AppendLine(
|
sb.AppendLine(
|
||||||
"This hack applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
|
"This fix applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
|
||||||
.AppendLine();
|
.AppendLine();
|
||||||
|
|
||||||
sb.AppendLine("From the issue on GitHub:").AppendLine();
|
sb.AppendLine("From the issue on GitHub:").AppendLine();
|
||||||
|
@ -30,14 +29,5 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
"there is a low chance that the game will softlock, " +
|
"there is a low chance that the game will softlock, " +
|
||||||
"the submenu won't show up, while background music is still there.");
|
"the submenu won't show up, while background music is still there.");
|
||||||
});
|
});
|
||||||
|
|
||||||
public static string NifmDisableIsAnyInternetRequestAcceptedTooltip { get; } = Lambda.String(sb =>
|
|
||||||
{
|
|
||||||
sb.AppendLine(
|
|
||||||
"This hack simply sets 'IsAnyInternetRequestAccepted' to 'false' when initializing the Nifm IGeneralService.")
|
|
||||||
.AppendLine();
|
|
||||||
|
|
||||||
sb.Append("Lets DOOM 2016 go in game.");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
@ -12,9 +11,9 @@ using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models.Input;
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Ava.Systems.Configuration.System;
|
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||||
using Ryujinx.Ava.Systems.Configuration.UI;
|
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
|
@ -28,7 +27,6 @@ using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -70,19 +68,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
public SettingsHacksViewModel DirtyHacks { get; }
|
public SettingsHacksViewModel DirtyHacks { get; }
|
||||||
|
|
||||||
private readonly bool _isGameRunning;
|
|
||||||
private Bitmap _gameIcon;
|
|
||||||
private string _gameTitle;
|
|
||||||
private string _gamePath;
|
|
||||||
private string _gameId;
|
|
||||||
public bool IsGameRunning => _isGameRunning;
|
|
||||||
public Bitmap GameIcon => _gameIcon;
|
|
||||||
public string GamePath => _gamePath;
|
|
||||||
public string GameTitle => _gameTitle;
|
|
||||||
public string GameId => _gameId;
|
|
||||||
public bool IsGameTitleNotNull => !string.IsNullOrEmpty(GameTitle);
|
|
||||||
public double PanelOpacity => IsGameTitleNotNull ? 0.5 : 1;
|
|
||||||
|
|
||||||
public int ResolutionScale
|
public int ResolutionScale
|
||||||
{
|
{
|
||||||
get => _resolutionScale;
|
get => _resolutionScale;
|
||||||
|
@ -130,10 +115,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
||||||
|
|
||||||
public bool EnableDiscordIntegration { get; set; }
|
public bool EnableDiscordIntegration { get; set; }
|
||||||
|
public bool CheckUpdatesOnStart { get; set; }
|
||||||
public bool ShowConfirmExit { get; set; }
|
public bool ShowConfirmExit { get; set; }
|
||||||
public bool IgnoreApplet { get; set; }
|
public bool IgnoreApplet { get; set; }
|
||||||
public bool RememberWindowState { get; set; }
|
public bool RememberWindowState { get; set; }
|
||||||
public bool ShowOldUI { get; set; }
|
public bool ShowTitleBar { get; set; }
|
||||||
public int HideCursor { get; set; }
|
public int HideCursor { get; set; }
|
||||||
public int UpdateCheckerType { get; set; }
|
public int UpdateCheckerType { get; set; }
|
||||||
public bool EnableDockedMode { get; set; }
|
public bool EnableDockedMode { get; set; }
|
||||||
|
@ -349,7 +335,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
||||||
|
|
||||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this(false)
|
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
||||||
{
|
{
|
||||||
_virtualFileSystem = virtualFileSystem;
|
_virtualFileSystem = virtualFileSystem;
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
|
@ -362,51 +348,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsViewModel(
|
public SettingsViewModel()
|
||||||
VirtualFileSystem virtualFileSystem,
|
|
||||||
ContentManager contentManager,
|
|
||||||
bool gameRunning,
|
|
||||||
string gamePath,
|
|
||||||
string gameName,
|
|
||||||
string gameId,
|
|
||||||
byte[] gameIconData,
|
|
||||||
bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig)
|
|
||||||
{
|
|
||||||
_virtualFileSystem = virtualFileSystem;
|
|
||||||
_contentManager = contentManager;
|
|
||||||
|
|
||||||
if (gameIconData != null && gameIconData.Length > 0)
|
|
||||||
{
|
|
||||||
using (var ms = new MemoryStream(gameIconData))
|
|
||||||
{
|
|
||||||
_gameIcon = new Bitmap(ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_isGameRunning = gameRunning;
|
|
||||||
_gamePath = gamePath;
|
|
||||||
_gameTitle = gameName;
|
|
||||||
_gameId = gameId;
|
|
||||||
|
|
||||||
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
|
|
||||||
{
|
|
||||||
string gameDir = Program.GetDirGameUserConfig(gameId, false, true);
|
|
||||||
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
|
||||||
{
|
|
||||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadCurrentConfiguration(); // Needed to load custom configuration
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Program.PreviewerDetached)
|
|
||||||
{
|
|
||||||
Task.Run(LoadTimeZones);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SettingsViewModel(bool noLoadGlobalConfig = false)
|
|
||||||
{
|
{
|
||||||
GameDirectories = [];
|
GameDirectories = [];
|
||||||
AutoloadDirectories = [];
|
AutoloadDirectories = [];
|
||||||
|
@ -421,9 +363,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
if (Program.PreviewerDetached)
|
if (Program.PreviewerDetached)
|
||||||
{
|
{
|
||||||
Task.Run(LoadAvailableGpus);
|
Task.Run(LoadAvailableGpus);
|
||||||
|
LoadCurrentConfiguration();
|
||||||
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
|
||||||
LoadCurrentConfiguration();
|
|
||||||
|
|
||||||
DirtyHacks = new SettingsHacksViewModel(this);
|
DirtyHacks = new SettingsHacksViewModel(this);
|
||||||
}
|
}
|
||||||
|
@ -536,9 +476,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
// User Interface
|
// User Interface
|
||||||
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
||||||
|
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
||||||
ShowConfirmExit = config.ShowConfirmExit;
|
ShowConfirmExit = config.ShowConfirmExit;
|
||||||
RememberWindowState = config.RememberWindowState;
|
RememberWindowState = config.RememberWindowState;
|
||||||
ShowOldUI = config.ShowOldUI;
|
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;
|
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
||||||
|
@ -644,14 +585,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
// User Interface
|
// User Interface
|
||||||
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
||||||
|
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
||||||
config.ShowConfirmExit.Value = ShowConfirmExit;
|
config.ShowConfirmExit.Value = ShowConfirmExit;
|
||||||
config.RememberWindowState.Value = RememberWindowState;
|
config.RememberWindowState.Value = RememberWindowState;
|
||||||
config.ShowOldUI.Value = ShowOldUI;
|
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;
|
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
||||||
config.UI.GameDirs.Value = [.. GameDirectories];
|
config.UI.GameDirs.Value = [..GameDirectories];
|
||||||
config.UI.AutoloadDirs.Value = [.. AutoloadDirectories];
|
config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
|
||||||
|
|
||||||
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
||||||
{
|
{
|
||||||
|
@ -672,10 +614,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
// System
|
// System
|
||||||
config.System.Region.Value = (Region)Region;
|
config.System.Region.Value = (Region)Region;
|
||||||
|
|
||||||
if (config.System.Language.Value != (Language)Language)
|
if (config.System.Language.Value != (Language)Language)
|
||||||
GameListNeedsRefresh = true;
|
GameListNeedsRefresh = true;
|
||||||
|
|
||||||
config.System.Language.Value = (Language)Language;
|
config.System.Language.Value = (Language)Language;
|
||||||
if (_validTzRegions.Contains(TimeZone))
|
if (_validTzRegions.Contains(TimeZone))
|
||||||
{
|
{
|
||||||
|
@ -754,11 +696,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
config.Multiplayer.DisableP2p.Value = DisableP2P;
|
config.Multiplayer.DisableP2p.Value = DisableP2P;
|
||||||
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
|
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
|
||||||
config.Multiplayer.LdnServer.Value = LdnServer;
|
config.Multiplayer.LdnServer.Value = LdnServer;
|
||||||
|
|
||||||
// Dirty Hacks
|
// Dirty Hacks
|
||||||
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
|
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
|
||||||
config.Hacks.DisableNifmIsAnyInternetRequestAccepted.Value =
|
|
||||||
DirtyHacks.NifmDisableIsAnyInternetRequestAccepted;
|
|
||||||
|
|
||||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||||
|
|
||||||
|
@ -772,11 +712,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
private static void RevertIfNotSaved()
|
private static void RevertIfNotSaved()
|
||||||
{
|
{
|
||||||
// maybe this is an unnecessary check(all options need to be tested)
|
Program.ReloadConfig();
|
||||||
if (string.IsNullOrEmpty(Program.GlobalConfigurationPath))
|
|
||||||
{
|
|
||||||
Program.ReloadConfig();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyButton()
|
public void ApplyButton()
|
||||||
|
@ -784,26 +720,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteConfigGame()
|
|
||||||
{
|
|
||||||
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
|
|
||||||
|
|
||||||
if (File.Exists(gameDir))
|
|
||||||
{
|
|
||||||
File.Delete(gameDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
RevertIfNotSaved();
|
|
||||||
CloseWindow?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveUserConfig()
|
|
||||||
{
|
|
||||||
SaveSettings();
|
|
||||||
RevertIfNotSaved(); // Revert global configuration after saving user configuration
|
|
||||||
CloseWindow?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OkButton()
|
public void OkButton()
|
||||||
{
|
{
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
|
|
|
@ -6,7 +6,7 @@ using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -21,7 +21,7 @@ using Image = SkiaSharp.SKImage;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
public partial class UserFirmwareAvatarSelectorViewModel : BaseModel
|
internal partial class UserFirmwareAvatarSelectorViewModel : BaseModel
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, byte[]> _avatarStore = new();
|
private static readonly Dictionary<string, byte[]> _avatarStore = new();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
public partial class UserProfileImageSelectorViewModel : BaseModel
|
internal partial class UserProfileImageSelectorViewModel : BaseModel
|
||||||
{
|
{
|
||||||
[ObservableProperty] private bool _firmwareFound;
|
[ObservableProperty] private bool _firmwareFound;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ using Ryujinx.Ava.Common;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Systems.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
@ -16,7 +16,7 @@ using static Ryujinx.Common.Utilities.XCIFileTrimmer;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
public class XciTrimmerViewModel : BaseModel
|
public class XCITrimmerViewModel : BaseModel
|
||||||
{
|
{
|
||||||
private const long _bytesPerMB = 1024 * 1024;
|
private const long _bytesPerMB = 1024 * 1024;
|
||||||
private enum ProcessingMode
|
private enum ProcessingMode
|
||||||
|
@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
private SortField _sortField = SortField.Name;
|
private SortField _sortField = SortField.Name;
|
||||||
private bool _sortAscending = true;
|
private bool _sortAscending = true;
|
||||||
|
|
||||||
public XciTrimmerViewModel(MainWindowViewModel mainWindowViewModel)
|
public XCITrimmerViewModel(MainWindowViewModel mainWindowViewModel)
|
||||||
{
|
{
|
||||||
_logger = new XCITrimmerLog.TrimmerWindow(this);
|
_logger = new XCITrimmerLog.TrimmerWindow(this);
|
||||||
_mainWindowViewModel = mainWindowViewModel;
|
_mainWindowViewModel = mainWindowViewModel;
|
||||||
|
@ -254,9 +254,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
|
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
|
||||||
{
|
{
|
||||||
private XciTrimmerViewModel _viewModel;
|
private XCITrimmerViewModel _viewModel;
|
||||||
|
|
||||||
public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel)
|
public CompareXCITrimmerFiles(XCITrimmerViewModel ViewModel)
|
||||||
{
|
{
|
||||||
_viewModel = ViewModel;
|
_viewModel = ViewModel;
|
||||||
}
|
}
|
|
@ -4,10 +4,10 @@
|
||||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:pt="using:Projektanker.Icons.Avalonia"
|
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
d:DesignHeight="800"
|
d:DesignHeight="800"
|
||||||
|
@ -34,7 +34,12 @@
|
||||||
<!-- Button / JoyStick Settings -->
|
<!-- Button / JoyStick Settings -->
|
||||||
<Grid
|
<Grid
|
||||||
Name="SettingButtons"
|
Name="SettingButtons"
|
||||||
MinHeight="450" ColumnDefinitions="Auto,*,Auto">
|
MinHeight="450">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<!-- Left Controls -->
|
<!-- Left Controls -->
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
|
@ -49,7 +54,15 @@
|
||||||
CornerRadius="5">
|
CornerRadius="5">
|
||||||
<Grid
|
<Grid
|
||||||
Margin="10"
|
Margin="10"
|
||||||
HorizontalAlignment="Stretch" ColumnDefinitions="*,*" RowDefinitions="*,*">
|
HorizontalAlignment="Stretch">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
|
@ -303,99 +316,17 @@
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<!-- Controller Picture -->
|
<!-- Controller Picture -->
|
||||||
|
<Image
|
||||||
|
Margin="0,10"
|
||||||
|
MaxHeight="300"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Source="{Binding Image}" />
|
||||||
<Border
|
<Border
|
||||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
CornerRadius="5"
|
CornerRadius="5"
|
||||||
Margin="0,0, 0, 5"
|
|
||||||
MinHeight="90">
|
MinHeight="90">
|
||||||
<StackPanel Orientation="Vertical">
|
|
||||||
<Image
|
|
||||||
Margin="5,10"
|
|
||||||
MaxHeight="300"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
Source="{Binding Image}" />
|
|
||||||
<StackPanel
|
|
||||||
Margin="10"
|
|
||||||
Orientation="Horizontal"
|
|
||||||
Spacing="20"
|
|
||||||
HorizontalAlignment="Center">
|
|
||||||
<Border
|
|
||||||
BorderBrush="Transparent"
|
|
||||||
Height="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
Width="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
IsVisible="{Binding IsLeft}">
|
|
||||||
<Canvas
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}">
|
|
||||||
<Grid
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}">
|
|
||||||
<Ellipse
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Stroke="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
StrokeThickness="1"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}" />
|
|
||||||
<Ellipse
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Fill="Black"
|
|
||||||
Opacity="100"
|
|
||||||
Height="{Binding Visualizer.UiDeadzoneLeft}"
|
|
||||||
Width="{Binding Visualizer.UiDeadzoneLeft}" />
|
|
||||||
</Grid>
|
|
||||||
<Ellipse
|
|
||||||
Fill="{DynamicResource Warning}"
|
|
||||||
Width="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Height="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Canvas.Bottom="{Binding Visualizer.UiStickLeftY}"
|
|
||||||
Canvas.Left="{Binding Visualizer.UiStickLeftX}" />
|
|
||||||
</Canvas>
|
|
||||||
</Border>
|
|
||||||
<Border
|
|
||||||
BorderBrush="Transparent"
|
|
||||||
Height="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
Width="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
IsVisible="{Binding IsRight}">
|
|
||||||
<Canvas
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}">
|
|
||||||
<Grid
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}">
|
|
||||||
<Ellipse
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Stroke="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
StrokeThickness="1"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}" />
|
|
||||||
<Ellipse
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Fill="Black"
|
|
||||||
Opacity="100"
|
|
||||||
Height="{Binding Visualizer.UiDeadzoneRight}"
|
|
||||||
Width="{Binding Visualizer.UiDeadzoneRight}" />
|
|
||||||
</Grid>
|
|
||||||
<Ellipse
|
|
||||||
Fill="{DynamicResource Warning}"
|
|
||||||
Width="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Height="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Canvas.Bottom="{Binding Visualizer.UiStickRightY}"
|
|
||||||
Canvas.Left="{Binding Visualizer.UiStickRightX}" />
|
|
||||||
</Canvas>
|
|
||||||
</Border>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
<Border
|
|
||||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
BorderThickness="1"
|
|
||||||
CornerRadius="5">
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Margin="8"
|
Margin="8"
|
||||||
Orientation="Vertical">
|
Orientation="Vertical">
|
||||||
|
@ -414,8 +345,8 @@
|
||||||
Minimum="0"
|
Minimum="0"
|
||||||
Value="{Binding Config.TriggerThreshold, Mode=TwoWay}" />
|
Value="{Binding Config.TriggerThreshold, Mode=TwoWay}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Width="25"
|
Width="25"
|
||||||
Text="{Binding Config.TriggerThreshold, StringFormat=\{0:0.00\}}" />
|
Text="{Binding Config.TriggerThreshold, StringFormat=\{0:0.00\}}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
|
@ -497,7 +428,7 @@
|
||||||
</Border>
|
</Border>
|
||||||
<!-- Motion, Rumble, LED -->
|
<!-- Motion, Rumble, LED -->
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Margin="0,5,0,0"
|
Margin="0,10,0,0"
|
||||||
Spacing="5"
|
Spacing="5"
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
VerticalAlignment="Bottom">
|
VerticalAlignment="Bottom">
|
||||||
|
@ -507,49 +438,77 @@
|
||||||
CornerRadius="5"
|
CornerRadius="5"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
HorizontalAlignment="Stretch">
|
HorizontalAlignment="Stretch">
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
<Grid>
|
||||||
<StackPanel Orientation="Vertical" Spacing="5">
|
<Grid.ColumnDefinitions>
|
||||||
<CheckBox
|
<ColumnDefinition Width="*" />
|
||||||
Margin="10, 10, 10, 0"
|
<ColumnDefinition Width="Auto" />
|
||||||
MinWidth="0"
|
</Grid.ColumnDefinitions>
|
||||||
IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}">
|
<CheckBox
|
||||||
<TextBlock Text="{ext:Locale ControllerSettingsMotion}" />
|
Margin="10"
|
||||||
</CheckBox>
|
MinWidth="0"
|
||||||
<Button
|
Grid.Column="0"
|
||||||
Margin="10, 0, 10, 10"
|
IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}">
|
||||||
Command="{Binding ShowMotionConfig}">
|
<TextBlock Text="{ext:Locale ControllerSettingsMotion}" />
|
||||||
<pt:Icon Value="fa-solid fa-gear" />
|
</CheckBox>
|
||||||
</Button>
|
<Button
|
||||||
</StackPanel>
|
Margin="10"
|
||||||
<controls:MiniVerticalSeparator Height="64"/>
|
Grid.Column="1"
|
||||||
<StackPanel Orientation="Vertical" Spacing="5">
|
Command="{Binding ShowMotionConfig}">
|
||||||
<CheckBox
|
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" />
|
||||||
Margin="10, 10, 10, 0"
|
</Button>
|
||||||
MinWidth="0"
|
</Grid>
|
||||||
IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}">
|
</Border>
|
||||||
<TextBlock Text="{ext:Locale ControllerSettingsRumble}" />
|
<Border
|
||||||
</CheckBox>
|
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||||
<Button
|
BorderThickness="1"
|
||||||
Margin="10, 0, 10, 10"
|
CornerRadius="5"
|
||||||
Command="{Binding ShowRumbleConfig}">
|
HorizontalAlignment="Stretch"
|
||||||
<pt:Icon Value="fa-solid fa-gear" />
|
Margin="0,-1,0,0">
|
||||||
</Button>
|
<Grid>
|
||||||
</StackPanel>
|
<Grid.ColumnDefinitions>
|
||||||
<controls:MiniVerticalSeparator Height="64" IsVisible="{Binding ParentModel.HasLed}"/>
|
<ColumnDefinition Width="*" />
|
||||||
<StackPanel Orientation="Vertical" Spacing="5">
|
<ColumnDefinition Width="Auto" />
|
||||||
<CheckBox
|
</Grid.ColumnDefinitions>
|
||||||
Margin="10, 10, 10, 0"
|
<CheckBox
|
||||||
MinWidth="0"
|
Margin="10"
|
||||||
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
|
MinWidth="0"
|
||||||
<TextBlock Text="{ext:Locale ControllerSettingsLed}" />
|
Grid.Column="0"
|
||||||
</CheckBox>
|
IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}">
|
||||||
<Button
|
<TextBlock Text="{ext:Locale ControllerSettingsRumble}" />
|
||||||
Margin="10, 0, 10, 10"
|
</CheckBox>
|
||||||
Command="{Binding ShowLedConfig}">
|
<Button
|
||||||
<pt:Icon Value="fa-solid fa-gear" />
|
Margin="10"
|
||||||
</Button>
|
Grid.Column="1"
|
||||||
</StackPanel>
|
Command="{Binding ShowRumbleConfig}">
|
||||||
</StackPanel>
|
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
<Border
|
||||||
|
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="5"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Margin="0,-1,0,0">
|
||||||
|
<Grid IsVisible="{Binding ParentModel.HasLed}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<CheckBox
|
||||||
|
Margin="10, 10, 5, 10"
|
||||||
|
MinWidth="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
|
||||||
|
<TextBlock Text="{ext:Locale ControllerSettingsLed}" />
|
||||||
|
</CheckBox>
|
||||||
|
<Button
|
||||||
|
Margin="10"
|
||||||
|
Grid.Column="1"
|
||||||
|
Command="{Binding ShowLedConfig}">
|
||||||
|
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
@ -567,7 +526,15 @@
|
||||||
CornerRadius="5">
|
CornerRadius="5">
|
||||||
<Grid
|
<Grid
|
||||||
Margin="10"
|
Margin="10"
|
||||||
HorizontalAlignment="Stretch" ColumnDefinitions="*,*" RowDefinitions="*,*">
|
HorizontalAlignment="Stretch">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
|
|
|
@ -4,7 +4,6 @@ using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
@ -15,7 +14,7 @@ using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Input
|
namespace Ryujinx.Ava.UI.Views.Input
|
||||||
{
|
{
|
||||||
public partial class ControllerInputView : RyujinxControl<ControllerInputViewModel>
|
public partial class ControllerInputView : UserControl
|
||||||
{
|
{
|
||||||
private ButtonKeyAssigner _currentAssigner;
|
private ButtonKeyAssigner _currentAssigner;
|
||||||
|
|
||||||
|
@ -218,12 +217,20 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||||
PointerPressed -= MouseClick;
|
PointerPressed -= MouseClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IButtonAssigner CreateButtonAssigner(bool forStick) =>
|
private IButtonAssigner CreateButtonAssigner(bool forStick)
|
||||||
new GamepadButtonAssigner(
|
{
|
||||||
ViewModel.ParentModel.SelectedGamepad,
|
IButtonAssigner assigner;
|
||||||
(ViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold,
|
|
||||||
|
ControllerInputViewModel controllerInputViewModel = DataContext as ControllerInputViewModel;
|
||||||
|
|
||||||
|
assigner = new GamepadButtonAssigner(
|
||||||
|
controllerInputViewModel.ParentModel.SelectedGamepad,
|
||||||
|
(controllerInputViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold,
|
||||||
forStick);
|
forStick);
|
||||||
|
|
||||||
|
return assigner;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnDetachedFromVisualTree(e);
|
base.OnDetachedFromVisualTree(e);
|
||||||
|
|
|
@ -35,13 +35,22 @@
|
||||||
Margin="0 0 0 5"
|
Margin="0 0 0 5"
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
Spacing="5">
|
Spacing="5">
|
||||||
<Grid ColumnDefinitions="*,10,*">
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<!-- Player Selection -->
|
<!-- Player Selection -->
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="2"
|
Margin="2"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center" ColumnDefinitions="Auto,*">
|
VerticalAlignment="Center">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,10,0"
|
Margin="5,0,10,0"
|
||||||
Width="90"
|
Width="90"
|
||||||
|
@ -68,7 +77,14 @@
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Margin="2"
|
Margin="2"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
|
VerticalAlignment="Center">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,10,0"
|
Margin="5,0,10,0"
|
||||||
Width="90"
|
Width="90"
|
||||||
|
@ -123,12 +139,22 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Separator />
|
<Separator />
|
||||||
<Grid ColumnDefinitions="*,10,*">
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<!-- Input Device -->
|
<!-- Input Device -->
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="2"
|
Margin="2"
|
||||||
HorizontalAlignment="Stretch" ColumnDefinitions="Auto,*,Auto">
|
HorizontalAlignment="Stretch">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="5,0,10,0"
|
Margin="5,0,10,0"
|
||||||
|
@ -160,7 +186,11 @@
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Margin="2"
|
Margin="2"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center" ColumnDefinitions="Auto,*">
|
VerticalAlignment="Center">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,10,0"
|
Margin="5,0,10,0"
|
||||||
Width="90"
|
Width="90"
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Input
|
namespace Ryujinx.Ava.UI.Views.Input
|
||||||
{
|
{
|
||||||
public partial class InputView : RyujinxControl<InputViewModel>
|
public partial class InputView : UserControl
|
||||||
{
|
{
|
||||||
private bool _dialogOpen;
|
private bool _dialogOpen;
|
||||||
|
private InputViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
public InputView()
|
public InputView()
|
||||||
{
|
{
|
||||||
ViewModel = new InputViewModel(this);
|
DataContext = ViewModel = new InputViewModel(this);
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,12 @@
|
||||||
<!-- Button / JoyStick Settings -->
|
<!-- Button / JoyStick Settings -->
|
||||||
<Grid
|
<Grid
|
||||||
Name="SettingButtons"
|
Name="SettingButtons"
|
||||||
MinHeight="450" ColumnDefinitions="Auto,*,Auto">
|
MinHeight="450">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<!-- Left Controls -->
|
<!-- Left Controls -->
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
|
@ -47,7 +52,15 @@
|
||||||
CornerRadius="5">
|
CornerRadius="5">
|
||||||
<Grid
|
<Grid
|
||||||
Margin="10"
|
Margin="10"
|
||||||
HorizontalAlignment="Stretch" ColumnDefinitions="*,*" RowDefinitions="*,*">
|
HorizontalAlignment="Stretch">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
|
@ -296,79 +309,12 @@
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<!-- Controller Picture -->
|
<!-- Controller Picture -->
|
||||||
<Border
|
<Image
|
||||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
BorderThickness="1"
|
|
||||||
CornerRadius="5"
|
|
||||||
Margin="0,10"
|
Margin="0,10"
|
||||||
MinHeight="90">
|
MaxHeight="300"
|
||||||
<StackPanel
|
HorizontalAlignment="Stretch"
|
||||||
Margin="10"
|
VerticalAlignment="Stretch"
|
||||||
Orientation="Horizontal"
|
Source="{Binding Image}" />
|
||||||
Spacing="20"
|
|
||||||
HorizontalAlignment="Center">
|
|
||||||
<Border
|
|
||||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
BorderThickness="1"
|
|
||||||
CornerRadius="5"
|
|
||||||
Height="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
Width="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
IsVisible="{Binding IsLeft}">
|
|
||||||
<Canvas
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}">
|
|
||||||
<Grid
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}">
|
|
||||||
<Ellipse
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Stroke="Black"
|
|
||||||
StrokeThickness="1"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"/>
|
|
||||||
</Grid>
|
|
||||||
<Ellipse
|
|
||||||
Fill="Red"
|
|
||||||
Width="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Height="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Canvas.Bottom="{Binding Visualizer.UiStickLeftY}"
|
|
||||||
Canvas.Left="{Binding Visualizer.UiStickLeftX}" />
|
|
||||||
</Canvas>
|
|
||||||
</Border>
|
|
||||||
<Border
|
|
||||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
BorderThickness="1"
|
|
||||||
CornerRadius="5"
|
|
||||||
Height="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
Width="{Binding Visualizer.UiStickBorderSize}"
|
|
||||||
IsVisible="{Binding IsRight}">
|
|
||||||
<Canvas
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}">
|
|
||||||
<Grid
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Background="{DynamicResource ThemeBackgroundColor}">
|
|
||||||
<Ellipse
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Stroke="Black"
|
|
||||||
StrokeThickness="1"
|
|
||||||
Width="{Binding Visualizer.UiCanvasSize}"
|
|
||||||
Height="{Binding Visualizer.UiCanvasSize}"/>
|
|
||||||
</Grid>
|
|
||||||
<Ellipse
|
|
||||||
Fill="Red"
|
|
||||||
Width="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Height="{Binding Visualizer.UiStickCircumference}"
|
|
||||||
Canvas.Bottom="{Binding Visualizer.UiStickRightY}"
|
|
||||||
Canvas.Left="{Binding Visualizer.UiStickRightX}" />
|
|
||||||
</Canvas>
|
|
||||||
</Border>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
<Border
|
<Border
|
||||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
|
@ -467,7 +413,15 @@
|
||||||
CornerRadius="5">
|
CornerRadius="5">
|
||||||
<Grid
|
<Grid
|
||||||
Margin="10"
|
Margin="10"
|
||||||
HorizontalAlignment="Stretch" ColumnDefinitions="*,*" RowDefinitions="*,*">
|
HorizontalAlignment="Stretch">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
|
|
|
@ -4,7 +4,6 @@ using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
|
@ -14,7 +13,7 @@ using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Input
|
namespace Ryujinx.Ava.UI.Views.Input
|
||||||
{
|
{
|
||||||
public partial class KeyboardInputView : RyujinxControl<KeyboardInputViewModel>
|
public partial class KeyboardInputView : UserControl
|
||||||
{
|
{
|
||||||
private ButtonKeyAssigner _currentAssigner;
|
private ButtonKeyAssigner _currentAssigner;
|
||||||
|
|
||||||
|
@ -61,103 +60,106 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||||
|
|
||||||
PointerPressed += MouseClick;
|
PointerPressed += MouseClick;
|
||||||
|
|
||||||
IKeyboard keyboard =
|
if (DataContext is not KeyboardInputViewModel viewModel)
|
||||||
(IKeyboard)ViewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
return;
|
||||||
IButtonAssigner assigner =
|
|
||||||
new KeyboardKeyAssigner((IKeyboard)ViewModel.ParentModel.SelectedGamepad);
|
|
||||||
|
|
||||||
_currentAssigner.ButtonAssigned += (_, be) =>
|
IKeyboard keyboard =
|
||||||
|
(IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||||
|
IButtonAssigner assigner =
|
||||||
|
new KeyboardKeyAssigner((IKeyboard)viewModel.ParentModel.SelectedGamepad);
|
||||||
|
|
||||||
|
_currentAssigner.ButtonAssigned += (_, e) =>
|
||||||
{
|
{
|
||||||
if (be.ButtonValue.HasValue)
|
if (e.ButtonValue.HasValue)
|
||||||
{
|
{
|
||||||
Button buttonValue = be.ButtonValue.Value;
|
Button buttonValue = e.ButtonValue.Value;
|
||||||
ViewModel.ParentModel.IsModified = true;
|
viewModel.ParentModel.IsModified = true;
|
||||||
|
|
||||||
switch (button.Name)
|
switch (button.Name)
|
||||||
{
|
{
|
||||||
case "ButtonZl":
|
case "ButtonZl":
|
||||||
ViewModel.Config.ButtonZl = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonZl = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonL":
|
case "ButtonL":
|
||||||
ViewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonMinus":
|
case "ButtonMinus":
|
||||||
ViewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftStickButton":
|
case "LeftStickButton":
|
||||||
ViewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftStickUp":
|
case "LeftStickUp":
|
||||||
ViewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftStickDown":
|
case "LeftStickDown":
|
||||||
ViewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftStickRight":
|
case "LeftStickRight":
|
||||||
ViewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftStickLeft":
|
case "LeftStickLeft":
|
||||||
ViewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "DpadUp":
|
case "DpadUp":
|
||||||
ViewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
|
viewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "DpadDown":
|
case "DpadDown":
|
||||||
ViewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
|
viewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "DpadLeft":
|
case "DpadLeft":
|
||||||
ViewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
|
viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "DpadRight":
|
case "DpadRight":
|
||||||
ViewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
|
viewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftButtonSr":
|
case "LeftButtonSr":
|
||||||
ViewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "LeftButtonSl":
|
case "LeftButtonSl":
|
||||||
ViewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
|
viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightButtonSr":
|
case "RightButtonSr":
|
||||||
ViewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightButtonSl":
|
case "RightButtonSl":
|
||||||
ViewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonZr":
|
case "ButtonZr":
|
||||||
ViewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonR":
|
case "ButtonR":
|
||||||
ViewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonPlus":
|
case "ButtonPlus":
|
||||||
ViewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonA":
|
case "ButtonA":
|
||||||
ViewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonB":
|
case "ButtonB":
|
||||||
ViewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonX":
|
case "ButtonX":
|
||||||
ViewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "ButtonY":
|
case "ButtonY":
|
||||||
ViewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
|
viewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightStickButton":
|
case "RightStickButton":
|
||||||
ViewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightStickUp":
|
case "RightStickUp":
|
||||||
ViewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightStickDown":
|
case "RightStickDown":
|
||||||
ViewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightStickRight":
|
case "RightStickRight":
|
||||||
ViewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
case "RightStickLeft":
|
case "RightStickLeft":
|
||||||
ViewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
|
viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Models.Input;
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Views.Input
|
namespace Ryujinx.UI.Views.Input
|
||||||
{
|
{
|
||||||
public partial class LedInputView : RyujinxControl<LedInputViewModel>
|
public partial class LedInputView : UserControl
|
||||||
{
|
{
|
||||||
|
private readonly LedInputViewModel _viewModel;
|
||||||
|
|
||||||
public LedInputView(ControllerInputViewModel viewModel)
|
public LedInputView(ControllerInputViewModel viewModel)
|
||||||
{
|
{
|
||||||
ViewModel = new LedInputViewModel
|
DataContext = _viewModel = new LedInputViewModel
|
||||||
{
|
{
|
||||||
ParentModel = viewModel.ParentModel,
|
ParentModel = viewModel.ParentModel,
|
||||||
TurnOffLed = viewModel.Config.TurnOffLed,
|
TurnOffLed = viewModel.Config.TurnOffLed,
|
||||||
|
@ -27,18 +29,20 @@ namespace Ryujinx.UI.Views.Input
|
||||||
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
|
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
|
||||||
{
|
{
|
||||||
if (!args.NewColor.HasValue) return;
|
if (!args.NewColor.HasValue) return;
|
||||||
if (!ViewModel.EnableLedChanging) return;
|
if (DataContext is not LedInputViewModel lvm) return;
|
||||||
if (ViewModel.TurnOffLed) return;
|
if (!lvm.EnableLedChanging) return;
|
||||||
|
if (lvm.TurnOffLed) return;
|
||||||
|
|
||||||
ViewModel.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
|
lvm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
if (!ViewModel.EnableLedChanging) return;
|
if (DataContext is not LedInputViewModel lvm) return;
|
||||||
if (ViewModel.TurnOffLed) return;
|
if (!lvm.EnableLedChanging) return;
|
||||||
|
if (lvm.TurnOffLed) return;
|
||||||
|
|
||||||
ViewModel.ParentModel.SelectedGamepad.SetLed(ViewModel.LedColor.ToUInt32());
|
lvm.ParentModel.SelectedGamepad.SetLed(lvm.LedColor.ToUInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Show(ControllerInputViewModel viewModel)
|
public static async Task Show(ControllerInputViewModel viewModel)
|
||||||
|
@ -53,13 +57,13 @@ namespace Ryujinx.UI.Views.Input
|
||||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
||||||
Content = content,
|
Content = content,
|
||||||
};
|
};
|
||||||
contentDialog.PrimaryButtonClick += (_, _) =>
|
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||||
{
|
{
|
||||||
GamepadInputConfig config = viewModel.Config;
|
GamepadInputConfig config = viewModel.Config;
|
||||||
config.EnableLedChanging = content.ViewModel.EnableLedChanging;
|
config.EnableLedChanging = content._viewModel.EnableLedChanging;
|
||||||
config.LedColor = content.ViewModel.LedColor;
|
config.LedColor = content._viewModel.LedColor;
|
||||||
config.UseRainbowLed = content.ViewModel.UseRainbowLed;
|
config.UseRainbowLed = content._viewModel.UseRainbowLed;
|
||||||
config.TurnOffLed = content.ViewModel.TurnOffLed;
|
config.TurnOffLed = content._viewModel.TurnOffLed;
|
||||||
};
|
};
|
||||||
|
|
||||||
await contentDialog.ShowAsync();
|
await contentDialog.ShowAsync();
|
||||||
|
|
|
@ -11,7 +11,11 @@
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView"
|
x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView"
|
||||||
x:DataType="viewModels:MotionInputViewModel"
|
x:DataType="viewModels:MotionInputViewModel"
|
||||||
Focusable="True">
|
Focusable="True">
|
||||||
<Grid Margin="10" RowDefinitions="Auto,*">
|
<Grid Margin="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Orientation="Horizontal"
|
Orientation="Horizontal"
|
||||||
|
@ -76,7 +80,11 @@
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
CornerRadius="5"
|
CornerRadius="5"
|
||||||
HorizontalAlignment="Stretch">
|
HorizontalAlignment="Stretch">
|
||||||
<Grid VerticalAlignment="Top" RowDefinitions="Auto,*">
|
<Grid VerticalAlignment="Top">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
|
@ -110,7 +118,15 @@
|
||||||
Text="{Binding DsuServerPort, Mode=TwoWay}" />
|
Text="{Binding DsuServerPort, Mode=TwoWay}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,10,0,0"
|
Margin="0,10,0,0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
using Avalonia.Controls;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Models.Input;
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Input
|
namespace Ryujinx.Ava.UI.Views.Input
|
||||||
{
|
{
|
||||||
public partial class MotionInputView : RyujinxControl<MotionInputViewModel>
|
public partial class MotionInputView : UserControl
|
||||||
{
|
{
|
||||||
|
private readonly MotionInputViewModel _viewModel;
|
||||||
|
|
||||||
public MotionInputView()
|
public MotionInputView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -18,7 +20,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||||
{
|
{
|
||||||
GamepadInputConfig config = viewModel.Config;
|
GamepadInputConfig config = viewModel.Config;
|
||||||
|
|
||||||
ViewModel = new MotionInputViewModel
|
_viewModel = new MotionInputViewModel
|
||||||
{
|
{
|
||||||
Slot = config.Slot,
|
Slot = config.Slot,
|
||||||
AltSlot = config.AltSlot,
|
AltSlot = config.AltSlot,
|
||||||
|
@ -31,6 +33,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||||
};
|
};
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
DataContext = _viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Show(ControllerInputViewModel viewModel)
|
public static async Task Show(ControllerInputViewModel viewModel)
|
||||||
|
@ -45,17 +48,17 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
||||||
Content = content,
|
Content = content,
|
||||||
};
|
};
|
||||||
contentDialog.PrimaryButtonClick += (_, _) =>
|
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||||
{
|
{
|
||||||
GamepadInputConfig config = viewModel.Config;
|
GamepadInputConfig config = viewModel.Config;
|
||||||
config.Slot = content.ViewModel.Slot;
|
config.Slot = content._viewModel.Slot;
|
||||||
config.Sensitivity = content.ViewModel.Sensitivity;
|
config.Sensitivity = content._viewModel.Sensitivity;
|
||||||
config.GyroDeadzone = content.ViewModel.GyroDeadzone;
|
config.GyroDeadzone = content._viewModel.GyroDeadzone;
|
||||||
config.AltSlot = content.ViewModel.AltSlot;
|
config.AltSlot = content._viewModel.AltSlot;
|
||||||
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.MirrorInput = content.ViewModel.MirrorInput;
|
config.MirrorInput = content._viewModel.MirrorInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
await contentDialog.ShowAsync();
|
await contentDialog.ShowAsync();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue