mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-30 01:29:48 -06:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
4ee1dff497 | |||
b2a35ecf6c | |||
5f6d9eef6b | |||
40a488799e | |||
f9f037a951 |
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@ -7,6 +7,7 @@ on:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
- 'docs/**'
|
||||
- '*.yml'
|
||||
- '*.json'
|
||||
- '*.config'
|
||||
|
57
README.md
57
README.md
@ -1,6 +1,6 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://ryujinx.org/"><img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx/master/distribution/misc/Logo.svg" alt="Ryujinx" width="150"></a>
|
||||
<img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/master/distribution/misc/Logo.svg" alt="Ryujinx" width="150"></a>
|
||||
<br>
|
||||
<b>Ryujinx</b>
|
||||
<br>
|
||||
@ -9,29 +9,34 @@
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
|
||||
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017.
|
||||
Ryujinx is available on Github under the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
Ryujinx is available on Github under the <a href="https://github.com/GreemDev/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
<br />
|
||||
</p>
|
||||
<p align="center">
|
||||
On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
|
||||
This fork is intended to be a direct continuation for existing Ryujinx users.
|
||||
Guides and documentation will not be provided at this time, though you can find the old ones on the Internet Archive.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml">
|
||||
<img src="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml/badge.svg"
|
||||
<a href="https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml">
|
||||
<img src="https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml/badge.svg"
|
||||
alt="">
|
||||
</a>
|
||||
<a href="https://crwd.in/ryujinx">
|
||||
<img src="https://badges.crowdin.net/ryujinx/localized.svg"
|
||||
alt="">
|
||||
</a>
|
||||
<a href="https://discord.com/invite/VkQYXAZ">
|
||||
<img src="https://img.shields.io/discord/410208534861447168?color=5865F2&label=Ryujinx&logo=discord&logoColor=white"
|
||||
<a href="https://discord.gg/dHPrkBkkyA">
|
||||
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryujinx&logo=discord&logoColor=white"
|
||||
alt="Discord">
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/public/assets/images/shell.png">
|
||||
<img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/docs/shell.png">
|
||||
</p>
|
||||
|
||||
## Compatibility
|
||||
@ -39,8 +44,6 @@
|
||||
As of May 2024, Ryujinx has been tested on approximately 4,300 titles;
|
||||
over 4,100 boot past menus and into gameplay, with roughly 3,550 of those being considered playable.
|
||||
|
||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
||||
|
||||
Anyone is free to submit a new game test or update an existing game test entry;
|
||||
simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue.
|
||||
Use the search function to see if a game has been tested already!
|
||||
@ -50,22 +53,11 @@ Use the search function to see if a game has been tested already!
|
||||
To run this emulator, your PC must be equipped with at least 8GiB of RAM;
|
||||
failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||
|
||||
See our [Setup & Configuration Guide](https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide) on how to set up the emulator.
|
||||
|
||||
For our Local Wireless (LDN) builds, see our [Multiplayer: Local Play/Local Wireless Guide
|
||||
](https://github.com/Ryujinx/Ryujinx/wiki/Multiplayer-(LDN-Local-Wireless)-Guide).
|
||||
|
||||
Avalonia UI comes with translations for various languages. See [Crowdin](https://crwd.in/ryujinx) for more information.
|
||||
|
||||
## Latest build
|
||||
|
||||
These builds are compiled automatically for each commit on the master branch.
|
||||
While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken**.
|
||||
|
||||
If you want to see details on updates to the emulator, you can visit our [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog).
|
||||
|
||||
The latest automatic build for Windows, macOS, and Linux can be found on the [Official Website](https://ryujinx.org/download).
|
||||
|
||||
## Documentation
|
||||
|
||||
If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md).
|
||||
@ -81,7 +73,7 @@ Make sure your SDK version is higher or equal to the required version specified
|
||||
|
||||
### Step 2
|
||||
|
||||
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
Either use `git clone https://github.com/GreemDev/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
|
||||
### Step 3
|
||||
|
||||
@ -135,27 +127,6 @@ This folder is located in the user folder, which can be accessed by clicking `Op
|
||||
The emulator has settings for enabling or disabling some logging, remapping controllers, and more.
|
||||
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
## Contact
|
||||
|
||||
If you have contributions, suggestions, need emulator support or just want to get in touch with the team, join our [Discord server](https://discord.com/invite/Ryujinx).
|
||||
You may also review our [FAQ](https://github.com/Ryujinx/Ryujinx/wiki/Frequently-Asked-Questions).
|
||||
|
||||
## Donations
|
||||
|
||||
If you'd like to support the project financially, Ryujinx has an active Patreon campaign.
|
||||
|
||||
<a href="https://www.patreon.com/ryujinx">
|
||||
<img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150">
|
||||
</a>
|
||||
|
||||
All developers working on the project do so in their free time, but the project has several expenses:
|
||||
* Hackable Nintendo Switch consoles to reverse-engineer the hardware
|
||||
* Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.)
|
||||
* Licenses for various software development tools (e.g. Jetbrains, IDA)
|
||||
* Web hosting and infrastructure maintenance (e.g. LDN servers)
|
||||
|
||||
All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews.
|
||||
|
||||
## License
|
||||
|
||||
This software is licensed under the terms of the [MIT license](LICENSE.txt).
|
||||
|
BIN
docs/shell.png
Normal file
BIN
docs/shell.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 905 KiB |
@ -492,7 +492,7 @@ namespace Ryujinx.Common.Collections
|
||||
Start = start;
|
||||
End = end;
|
||||
Max = end;
|
||||
Values = new List<RangeNode<TKey, TValue>> { new RangeNode<TKey, TValue>(start, end, value) };
|
||||
Values = [ new RangeNode<TKey, TValue>(start, end, value) ];
|
||||
Parent = parent;
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,8 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
public bool TextProcessingEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return Volatile.Read(ref _canProcessInput);
|
||||
}
|
||||
|
||||
get => Volatile.Read(ref _canProcessInput);
|
||||
|
||||
set
|
||||
{
|
||||
Volatile.Write(ref _canProcessInput, value);
|
||||
|
@ -10,6 +10,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationPr
|
||||
using Ryujinx.HLE.UI;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.Input.SDL2;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
@ -12,7 +12,10 @@ namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
private bool HasConfiguration => _configuration != null;
|
||||
|
||||
private record struct ButtonMappingEntry(GamepadButtonInputId To, GamepadButtonInputId From);
|
||||
private readonly record struct ButtonMappingEntry(GamepadButtonInputId To, GamepadButtonInputId From)
|
||||
{
|
||||
public bool IsValid => To is not GamepadButtonInputId.Unbound && From is not GamepadButtonInputId.Unbound;
|
||||
}
|
||||
|
||||
private StandardControllerInputConfig _configuration;
|
||||
|
||||
@ -144,86 +147,64 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||
{
|
||||
if (Features.HasFlag(GamepadFeaturesFlag.Rumble))
|
||||
{
|
||||
ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue);
|
||||
ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue);
|
||||
if (!Features.HasFlag(GamepadFeaturesFlag.Rumble)) return;
|
||||
|
||||
if (durationMs == uint.MaxValue)
|
||||
{
|
||||
if (SDL_GameControllerRumble(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, SDL_HAPTIC_INFINITY) != 0)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
||||
}
|
||||
}
|
||||
else if (durationMs > SDL_HAPTIC_INFINITY)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Hid, $"Unsupported rumble duration {durationMs}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SDL_GameControllerRumble(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs) != 0)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
||||
}
|
||||
}
|
||||
ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue);
|
||||
ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue);
|
||||
|
||||
if (durationMs == uint.MaxValue)
|
||||
{
|
||||
if (SDL_GameControllerRumble(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, SDL_HAPTIC_INFINITY) != 0)
|
||||
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
||||
}
|
||||
else if (durationMs > SDL_HAPTIC_INFINITY)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Hid, $"Unsupported rumble duration {durationMs}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SDL_GameControllerRumble(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs) != 0)
|
||||
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 GetMotionData(MotionInputId inputId)
|
||||
{
|
||||
SDL_SensorType sensorType = SDL_SensorType.SDL_SENSOR_INVALID;
|
||||
|
||||
if (inputId == MotionInputId.Accelerometer)
|
||||
SDL_SensorType sensorType = inputId switch
|
||||
{
|
||||
sensorType = SDL_SensorType.SDL_SENSOR_ACCEL;
|
||||
}
|
||||
else if (inputId == MotionInputId.Gyroscope)
|
||||
{
|
||||
sensorType = SDL_SensorType.SDL_SENSOR_GYRO;
|
||||
}
|
||||
MotionInputId.Accelerometer => SDL_SensorType.SDL_SENSOR_ACCEL,
|
||||
MotionInputId.Gyroscope => SDL_SensorType.SDL_SENSOR_GYRO,
|
||||
_ => SDL_SensorType.SDL_SENSOR_INVALID
|
||||
};
|
||||
|
||||
if (Features.HasFlag(GamepadFeaturesFlag.Motion) && sensorType != SDL_SensorType.SDL_SENSOR_INVALID)
|
||||
{
|
||||
const int ElementCount = 3;
|
||||
if (!Features.HasFlag(GamepadFeaturesFlag.Motion) || sensorType is SDL_SensorType.SDL_SENSOR_INVALID)
|
||||
return Vector3.Zero;
|
||||
|
||||
unsafe
|
||||
const int ElementCount = 3;
|
||||
|
||||
unsafe
|
||||
{
|
||||
float* values = stackalloc float[ElementCount];
|
||||
|
||||
int result = SDL_GameControllerGetSensorData(_gamepadHandle, sensorType, (IntPtr)values, ElementCount);
|
||||
|
||||
if (result != 0)
|
||||
return Vector3.Zero;
|
||||
|
||||
Vector3 value = new(values[0], values[1], values[2]);
|
||||
|
||||
return inputId switch
|
||||
{
|
||||
float* values = stackalloc float[ElementCount];
|
||||
|
||||
int result = SDL_GameControllerGetSensorData(_gamepadHandle, sensorType, (IntPtr)values, ElementCount);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
Vector3 value = new(values[0], values[1], values[2]);
|
||||
|
||||
if (inputId == MotionInputId.Gyroscope)
|
||||
{
|
||||
return RadToDegree(value);
|
||||
}
|
||||
|
||||
if (inputId == MotionInputId.Accelerometer)
|
||||
{
|
||||
return GsToMs2(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
MotionInputId.Gyroscope => RadToDegree(value),
|
||||
MotionInputId.Accelerometer => GsToMs2(value),
|
||||
_ => value
|
||||
};
|
||||
}
|
||||
|
||||
return Vector3.Zero;
|
||||
}
|
||||
|
||||
private static Vector3 RadToDegree(Vector3 rad)
|
||||
{
|
||||
return rad * (180 / MathF.PI);
|
||||
}
|
||||
private static Vector3 RadToDegree(Vector3 rad) => rad * (180 / MathF.PI);
|
||||
|
||||
private static Vector3 GsToMs2(Vector3 gs)
|
||||
{
|
||||
return gs / SDL_STANDARD_GRAVITY;
|
||||
}
|
||||
private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY;
|
||||
|
||||
public void SetConfiguration(InputConfig configuration)
|
||||
{
|
||||
@ -278,16 +259,13 @@ namespace Ryujinx.Input.SDL2
|
||||
lock (_userMappingLock)
|
||||
{
|
||||
if (_buttonsUserMapping.Count == 0)
|
||||
{
|
||||
return rawState;
|
||||
}
|
||||
|
||||
|
||||
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
||||
foreach (ButtonMappingEntry entry in _buttonsUserMapping)
|
||||
{
|
||||
if (entry.From == GamepadButtonInputId.Unbound || entry.To == GamepadButtonInputId.Unbound)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!entry.IsValid) continue;
|
||||
|
||||
// Do not touch state of button already pressed
|
||||
if (!result.IsPressed(entry.To))
|
||||
@ -316,9 +294,8 @@ namespace Ryujinx.Input.SDL2
|
||||
public (float, float) GetStick(StickInputId inputId)
|
||||
{
|
||||
if (inputId == StickInputId.Unbound)
|
||||
{
|
||||
return (0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
(short stickX, short stickY) = GetStickXY(inputId);
|
||||
|
||||
@ -351,6 +328,7 @@ namespace Ryujinx.Input.SDL2
|
||||
return (resultX, resultY);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private (short, short) GetStickXY(StickInputId inputId) =>
|
||||
inputId switch
|
||||
{
|
||||
@ -365,14 +343,12 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
public bool IsPressed(GamepadButtonInputId inputId)
|
||||
{
|
||||
if (inputId == GamepadButtonInputId.LeftTrigger)
|
||||
switch (inputId)
|
||||
{
|
||||
return ConvertRawStickValue(SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT)) > _triggerThreshold;
|
||||
}
|
||||
|
||||
if (inputId == GamepadButtonInputId.RightTrigger)
|
||||
{
|
||||
return ConvertRawStickValue(SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) > _triggerThreshold;
|
||||
case GamepadButtonInputId.LeftTrigger:
|
||||
return ConvertRawStickValue(SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT)) > _triggerThreshold;
|
||||
case GamepadButtonInputId.RightTrigger:
|
||||
return ConvertRawStickValue(SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) > _triggerThreshold;
|
||||
}
|
||||
|
||||
if (_buttonsDriverMapping[(int)inputId] == SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_INVALID)
|
||||
|
@ -1,12 +1,11 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
class SDL2Mouse : IMouse
|
||||
public class SDL2Mouse : IMouse
|
||||
{
|
||||
private SDL2MouseDriver _driver;
|
||||
|
@ -1,6 +1,5 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
@ -8,9 +7,9 @@ using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static SDL2.SDL;
|
||||
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
class SDL2MouseDriver : IGamepadDriver
|
||||
public class SDL2MouseDriver : IGamepadDriver
|
||||
{
|
||||
private const int CursorHideIdleTime = 5; // seconds
|
||||
|
||||
@ -44,7 +43,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static MouseButton DriverButtonToMouseButton(uint rawButton)
|
||||
{
|
||||
Debug.Assert(rawButton > 0 && rawButton <= (int)MouseButton.Count);
|
||||
Debug.Assert(rawButton is > 0 and <= (int)MouseButton.Count);
|
||||
|
||||
return (MouseButton)(rawButton - 1);
|
||||
}
|
@ -143,7 +143,7 @@ namespace Ryujinx.SDL2.Common
|
||||
|
||||
OnJoystickDisconnected?.Invoke(evnt.cbutton.which);
|
||||
}
|
||||
else if (evnt.type == SDL_EventType.SDL_WINDOWEVENT || evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN || evnt.type == SDL_EventType.SDL_MOUSEBUTTONUP)
|
||||
else if (evnt.type is SDL_EventType.SDL_WINDOWEVENT or SDL_EventType.SDL_MOUSEBUTTONDOWN or SDL_EventType.SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
if (_registeredWindowHandlers.TryGetValue(evnt.window.windowID, out Action<SDL_Event> handler))
|
||||
{
|
||||
|
@ -8,10 +8,8 @@ namespace Ryujinx.UI.Common.Helper
|
||||
public static string ActiveApplicationTitle(ProcessResult activeProcess, string applicationVersion, string pauseString = "")
|
||||
{
|
||||
if (activeProcess == null)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}";
|
||||
string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
@ -19,12 +17,9 @@ namespace Ryujinx.UI.Common.Helper
|
||||
|
||||
string appTitle = $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
|
||||
if (!string.IsNullOrEmpty(pauseString))
|
||||
{
|
||||
appTitle += $" ({pauseString})";
|
||||
}
|
||||
|
||||
return appTitle;
|
||||
return !string.IsNullOrEmpty(pauseString)
|
||||
? appTitle + $" ({pauseString})"
|
||||
: appTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,14 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
internal static string FormatTitle(LocaleKeys? windowTitleKey = null)
|
||||
=> windowTitleKey is null
|
||||
? $"Ryujinx {Program.Version}"
|
||||
: $"Ryujinx {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
Name = $"Ryujinx {Program.Version}";
|
||||
Name = FormatTitle();
|
||||
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
|
@ -1705,7 +1705,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
Title = $"Ryujinx {Program.Version}";
|
||||
Title = App.FormatTitle();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.Amiibo];
|
||||
Title = App.FormatTitle(LocaleKeys.Amiibo);
|
||||
}
|
||||
|
||||
public AmiiboWindow()
|
||||
@ -31,7 +31,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.Amiibo];
|
||||
Title = App.FormatTitle(LocaleKeys.Amiibo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle];
|
||||
Title = App.FormatTitle(LocaleKeys.CheatWindowTitle);
|
||||
}
|
||||
|
||||
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
||||
@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
DataContext = this;
|
||||
|
||||
Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle];
|
||||
Title = App.FormatTitle(LocaleKeys.CheatWindowTitle);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
|
@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
UiHandler = new AvaHostUIHandler(this);
|
||||
|
||||
ViewModel.Title = $"Ryujinx {Program.Version}";
|
||||
ViewModel.Title = App.FormatTitle();
|
||||
|
||||
// NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point.
|
||||
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
|
||||
|
@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager)
|
||||
{
|
||||
Title = $"Ryujinx {Program.Version} - {LocaleManager.Instance[LocaleKeys.Settings]}";
|
||||
Title = App.FormatTitle(LocaleKeys.Settings);
|
||||
|
||||
ViewModel = new SettingsViewModel(virtualFileSystem, contentManager);
|
||||
DataContext = ViewModel;
|
||||
|
@ -1,6 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Styling;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
@ -64,21 +62,14 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
private void OpenLocation(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
if (button.DataContext is TitleUpdateModel model)
|
||||
{
|
||||
OpenHelper.LocateFile(model.Path);
|
||||
}
|
||||
}
|
||||
if (sender is Button { DataContext: TitleUpdateModel model })
|
||||
OpenHelper.LocateFile(model.Path);
|
||||
}
|
||||
|
||||
private void RemoveUpdate(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
ViewModel.RemoveUpdate((TitleUpdateModel)button.DataContext);
|
||||
}
|
||||
if (sender is Button { DataContext: TitleUpdateModel model })
|
||||
ViewModel.RemoveUpdate(model);
|
||||
}
|
||||
|
||||
private void RemoveAll(object sender, RoutedEventArgs e)
|
||||
|
Reference in New Issue
Block a user