Compare commits

...

5 Commits

Author SHA1 Message Date
Barış Hamil
6d78e71fc7 Handheld Gyro 2025-02-01 22:26:05 +03:00
Evan Husted
707c9ef748 misc: chore: slightly improve PTC init log line 2025-01-28 22:25:01 -06:00
Evan Husted
2acc43e968 misc: chore: Use string.Empty in more places where it's snuck back 2025-01-28 22:17:11 -06:00
Evan Husted
191e158289 misc: chore: Use static instances of converters instead of using control resources 2025-01-28 22:11:48 -06:00
Evan Husted
a469f3d710 UI: Remove empty StackPanel in UserSelectorDialog 2025-01-28 21:47:29 -06:00
49 changed files with 329 additions and 183 deletions

View File

@@ -3,6 +3,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Alimer.Bindings.SDL" Version="3.7.1" />
<PackageVersion Include="Avalonia" Version="11.0.13" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />

View File

@@ -75,6 +75,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{3BF24278-547D-42C2-9D43-182B978F54DD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
@@ -259,6 +261,10 @@ Global
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU
{3BF24278-547D-42C2-9D43-182B978F54DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BF24278-547D-42C2-9D43-182B978F54DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BF24278-547D-42C2-9D43-182B978F54DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BF24278-547D-42C2-9D43-182B978F54DD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -4,6 +4,7 @@ using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Common;
using ARMeilleure.Memory;
using ARMeilleure.State;
using Humanizer;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
@@ -923,15 +924,11 @@ namespace ARMeilleure.Translation.PTC
sw.Stop();
PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount);
if (_translateCount == _translateTotalCount)
{
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s");
}
else
{
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | {_translateTotalCount - _translateCount} function{(_translateTotalCount - _translateCount != 1 ? "s" : "")} blacklisted | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s");
}
Logger.Info?.Print(LogClass.Ptc,
$"{_translateCount} of {_translateTotalCount} functions translated in {sw.Elapsed.TotalSeconds} seconds " +
$"| {"function".ToQuantity(_translateTotalCount - _translateCount)} blacklisted " +
$"| Thread count: {degreeOfParallelism}");
Thread preSaveThread = new(PreSave)
{

View File

@@ -56,6 +56,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
return motionBackendType switch
{
MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
MotionInputBackendType.Handheld => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, _serializerContext.CemuHookMotionConfigController),
_ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"),
};
@@ -66,6 +67,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
switch (value.MotionBackend)
{
case MotionInputBackendType.GamepadDriver:
case MotionInputBackendType.Handheld:
JsonSerializer.Serialize(writer, value as StandardMotionConfigController, _serializerContext.StandardMotionConfigController);
break;
case MotionInputBackendType.CemuHook:

View File

@@ -9,5 +9,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
Invalid,
GamepadDriver,
CemuHook,
Handheld,
}
}

View File

@@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Metal
return model;
}
return "";
return string.Empty;
}
}
}

View File

@@ -218,7 +218,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
foreach (MemoryDefinition memory in memories)
{
string arraySize = "";
string arraySize = string.Empty;
if ((memory.Type & AggregateType.Array) != 0)
{
arraySize = $"[{memory.ArrayLength}]";
@@ -240,7 +240,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
BufferDefinition buffer = buffers[i];
bool needsPadding = buffer.Layout == BufferLayout.Std140;
string fsiSuffix = !constant && fsi ? " [[raster_order_group(0)]]" : "";
string fsiSuffix = !constant && fsi ? " [[raster_order_group(0)]]" : string.Empty;
bufferDec[i] = $"{addressSpace} {Defaults.StructPrefix}_{buffer.Name}* {buffer.Name}{fsiSuffix};";
@@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
type &= ~AggregateType.Array;
string typeName = GetVarTypeName(type);
string arraySuffix = "";
string arraySuffix = string.Empty;
if (field.Type.HasFlag(AggregateType.Array))
{
@@ -353,7 +353,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
imageTypeName = $"array<{imageTypeName}, {image.ArrayLength}>";
}
string fsiSuffix = fsi ? " [[raster_order_group(0)]]" : "";
string fsiSuffix = fsi ? " [[raster_order_group(0)]]" : string.Empty;
imageDec[i] = $"{imageTypeName} {image.Name}{fsiSuffix};";
}
@@ -454,7 +454,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
IoVariable.VertexIndex => "[[vertex_id]]",
// IoVariable.PointCoord => "[[point_coord]]",
IoVariable.UserDefined => context.Definitions.Stage == ShaderStage.Fragment ? $"[[user(loc{ioDefinition.Location})]]" : $"[[attribute({ioDefinition.Location})]]",
_ => ""
_ => string.Empty
};
context.AppendLine($"{type} {name} {iq}{suffix};");
@@ -545,7 +545,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
IoVariable.FragmentOutputColor => $"[[color({ioDefinition.Location})]]",
IoVariable.FragmentOutputDepth => "[[depth(any)]]",
IoVariable.ClipDistance => $"[[clip_distance]][{Defaults.TotalClipDistances}]",
_ => ""
_ => string.Empty
};
context.AppendLine($"{type} {name} {suffix};");

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
inputsCount--;
}
string fieldName = "";
string fieldName = string.Empty;
switch (storageKind)
{
case StorageKind.ConstantBuffer:
@@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
}
}
varName += fieldName;
varName += fieldHasPadding ? ".x" : "";
varName += fieldHasPadding ? ".x" : string.Empty;
if (isStore)
{
@@ -434,7 +434,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
string prefix = intCoords ? "uint" : "float";
return prefix + (count > 1 ? count : "") + "(" + coords + ")";
return prefix + (count > 1 ? count : string.Empty) + "(" + coords + ")";
}
Append(AssemblePVector(pCount));
@@ -504,7 +504,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
}
texCallBuilder.Append(')');
texCallBuilder.Append(colorIsVector ? GetMaskMultiDest(texOp.Index) : "");
texCallBuilder.Append(colorIsVector ? GetMaskMultiDest(texOp.Index) : string.Empty);
return texCallBuilder.ToString();
}
@@ -558,7 +558,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
{
if (mask == 0x0)
{
return "";
return string.Empty;
}
string swizzle = ".";

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
if (parameters.Definitions.Stage is not (ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute))
{
Logger.Warning?.Print(LogClass.Gpu, $"Attempted to generate unsupported shader type {parameters.Definitions.Stage}!");
return "";
return string.Empty;
}
CodeGenContext context = new(info, parameters);

View File

@@ -199,7 +199,7 @@ namespace Ryujinx.Graphics.Shader
_ => "float"
};
return $"{typeName}<{format}{(image ? ", access::read_write" : "")}>";
return $"{typeName}<{format}{(image ? ", access::read_write" : string.Empty)}>";
}
}
}

View File

@@ -679,7 +679,7 @@ namespace Ryujinx.HLE.HOS
{
using (MD5 md5 = MD5.Create())
{
modLoadResult.Hash += BitConverter.ToString(md5.ComputeHash(tempHash.ToBytes())).Replace("-", "").ToLowerInvariant();
modLoadResult.Hash += BitConverter.ToString(md5.ComputeHash(tempHash.ToBytes())).Replace("-", string.Empty).ToLowerInvariant();
}
}

View File

@@ -121,7 +121,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu
private void UpdatePassphraseIfNeeded()
{
string passphrase = _config.MultiplayerLdnPassphrase ?? "";
string passphrase = _config.MultiplayerLdnPassphrase ?? string.Empty;
if (passphrase != _passphrase)
{
_passphrase = passphrase;

View File

@@ -88,7 +88,7 @@ namespace Ryujinx.HLE.Loaders.Processes
bool isFirmwareApplication = ProgramId <= 0x0100000000007FFF;
string name = !isFirmware
? (isFirmwareApplication ? "Firmware Application " : "") + (!string.IsNullOrWhiteSpace(Name) ? Name : "<Unknown Name>")
? (isFirmwareApplication ? "Firmware Application " : string.Empty) + (!string.IsNullOrWhiteSpace(Name) ? Name : "<Unknown Name>")
: "Firmware";
// TODO: LibHac npdm currently doesn't support version field.

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
<PackageReference Include="Alimer.Bindings.SDL" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,85 @@
using SDL3;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using static SDL3.SDL3;
namespace Ryujinx.Input.SDL3
{
public unsafe class SDL3MotionDriver : IHandheld, IDisposable
{
private readonly Dictionary<SDL_SensorType, SDL_Sensor> sensors;
private bool _disposed;
public SDL3MotionDriver()
{
int result = SDL_Init(SDL_InitFlags.Sensor);
if (result < 0)
{
throw new InvalidOperationException($"SDL sensor initialization failed: {SDL_GetError()}");
}
sensors = SDL_GetSensors().ToArray().ToDictionary(SDL_GetSensorTypeForID, SDL_OpenSensor);
}
~SDL3MotionDriver()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing && sensors != null)
{
foreach (var sensor in sensors.Values)
{
if (sensor != IntPtr.Zero)
{
SDL_CloseSensor(sensor);
}
}
}
_disposed = true;
}
public Vector3 GetMotionData(MotionInputId inputType)
{
ObjectDisposedException.ThrowIf(_disposed, this);
return inputType switch
{
MotionInputId.Gyroscope => GetSensorVector(SDL_SensorType.Gyro) * 180 / MathF.PI,
MotionInputId.Accelerometer => GetSensorVector(SDL_SensorType.Accel) / SDL_STANDARD_GRAVITY,
_ => Vector3.Zero
};
}
private Vector3 GetSensorVector(SDL_SensorType sensorType)
{
if (!sensors.TryGetValue(sensorType, out SDL_Sensor sensor))
{
return Vector3.Zero;
}
var data = stackalloc float[3];
if (SDL_GetSensorData(sensor, data, 3) < 0)
{
return Vector3.Zero;
}
return new Vector3(data[0], data[1], data[2]);
}
}
}

View File

@@ -2,12 +2,13 @@ using System;
namespace Ryujinx.Input.HLE
{
public class InputManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver)
public class InputManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IHandheld handheld)
: IDisposable
{
public IGamepadDriver KeyboardDriver { get; } = keyboardDriver;
public IGamepadDriver GamepadDriver { get; } = gamepadDriver;
public IGamepadDriver MouseDriver { get; private set; }
public IHandheld Handheld { get; } = handheld;
public void SetMouseDriver(IGamepadDriver mouseDriver)
{
@@ -18,7 +19,7 @@ namespace Ryujinx.Input.HLE
public NpadManager CreateNpadManager()
{
return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver);
return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver, Handheld);
}
public TouchScreenManager CreateTouchScreenManager()
@@ -38,6 +39,7 @@ namespace Ryujinx.Input.HLE
KeyboardDriver?.Dispose();
GamepadDriver?.Dispose();
MouseDriver?.Dispose();
Handheld?.Dispose();
}
}

View File

@@ -218,12 +218,14 @@ namespace Ryujinx.Input.HLE
public string Id { get; private set; }
private readonly CemuHookClient _cemuHookClient;
private readonly IHandheld _handheld;
public NpadController(CemuHookClient cemuHookClient)
public NpadController(CemuHookClient cemuHookClient, IHandheld handheld)
{
State = default;
Id = null;
_cemuHookClient = cemuHookClient;
_handheld = handheld;
}
public bool UpdateDriverConfiguration(IGamepadDriver gamepadDriver, InputConfig config)
@@ -287,6 +289,18 @@ namespace Ryujinx.Input.HLE
if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion)
{
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.Handheld)
{
Vector3 accelerometer = _handheld.GetMotionData(MotionInputId.Accelerometer);
Vector3 gyroscope = _handheld.GetMotionData(MotionInputId.Gyroscope);
accelerometer = new Vector3(accelerometer.X, -accelerometer.Z, accelerometer.Y);
gyroscope = new Vector3(gyroscope.X, -gyroscope.Z, gyroscope.Y);
_leftMotionInput.Update(accelerometer, gyroscope, (ulong)PerformanceCounter.ElapsedNanoseconds / 1000, controllerConfig.Motion.Sensitivity, (float)controllerConfig.Motion.GyroDeadzone);
_rightMotionInput = _leftMotionInput;
}
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver)
{
if (gamepad.Features.HasFlag(GamepadFeaturesFlag.Motion))

View File

@@ -31,6 +31,7 @@ namespace Ryujinx.Input.HLE
private readonly IGamepadDriver _keyboardDriver;
private readonly IGamepadDriver _gamepadDriver;
private readonly IGamepadDriver _mouseDriver;
private readonly IHandheld _handheld;
private bool _isDisposed;
private List<InputConfig> _inputConfig;
@@ -38,7 +39,7 @@ namespace Ryujinx.Input.HLE
private bool _enableMouse;
private Switch _device;
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver, IHandheld handheld)
{
_controllers = new NpadController[MaxControllers];
_cemuHookClient = new CemuHookClient(this);
@@ -47,6 +48,7 @@ namespace Ryujinx.Input.HLE
_gamepadDriver = gamepadDriver;
_mouseDriver = mouseDriver;
_inputConfig = [];
_handheld = handheld;
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
@@ -139,7 +141,7 @@ namespace Ryujinx.Input.HLE
}
else
{
controller = new(_cemuHookClient);
controller = new(_cemuHookClient, _handheld);
}
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);

View File

@@ -0,0 +1,10 @@
using System;
using System.Numerics;
namespace Ryujinx.Input
{
public interface IHandheld : IDisposable
{
Vector3 GetMotionData(MotionInputId gyroscope);
}
}

View File

@@ -7522,6 +7522,31 @@
"zh_TW": "使用與 CemuHook 相容的體感"
}
},
{
"ID": "ControllerSettingsMotionUseHandheldCompatibleMotion",
"Translations": {
"ar_SA": "استخدام الحركة المتوافقة مع Hendheld",
"de_DE": "Hendheld kompatible Bewegungssteuerung",
"el_GR": "Κίνηση συμβατή με Hendheld",
"en_US": "Use Hendheld compatible motion",
"es_ES": "Usar movimiento compatible con Hendheld",
"fr_FR": "Utiliser un capteur de mouvements Hendheld",
"he_IL": "השתמש בתנועת Hendheld תואמת ",
"it_IT": "Usa sensore compatibile con Hendheld",
"ja_JP": "Hendheld 互換モーションを使用",
"ko_KR": "Hendheld 호환 모션 사용",
"no_NO": "Bruk Hendheld kompatibel bevegelse",
"pl_PL": "Użyj ruchu zgodnego z Hendheld",
"pt_BR": "Usar sensor compatível com Hendheld",
"ru_RU": "Включить совместимость с Hendheld",
"sv_SE": "Använd Hendheld-kompatibel rörelse",
"th_TH": "ใช้การเคลื่อนไหวที่เข้ากันได้กับ Hendheld",
"tr_TR": "Hendheld uyumlu hareket kullan",
"uk_UA": "Використовувати рух, сумісний з Hendheld",
"zh_CN": "使用 Hendheld 兼容的体感协议",
"zh_TW": "使用與 Hendheld 相容的體感"
}
},
{
"ID": "ControllerSettingsMotionControllerSlot",
"Translations": {
@@ -23173,4 +23198,4 @@
}
}
]
}
}

View File

@@ -23,6 +23,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.Input;
using Ryujinx.Input.HLE;
using Ryujinx.Input.SDL2;
using Ryujinx.Input.SDL3;
using Ryujinx.SDL2.Common;
using System;
using System.Collections.Generic;
@@ -182,7 +183,7 @@ namespace Ryujinx.Headless
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile);
_userChannelPersistence = new UserChannelPersistence();
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver(), new SDL3MotionDriver());
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;

View File

@@ -76,6 +76,7 @@
<ProjectReference Include="..\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj" />
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
<ProjectReference Include="..\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
<ProjectReference Include="..\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj" />
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />

View File

@@ -13,11 +13,6 @@
mc:Ignorable="d"
Focusable="True"
x:DataType="viewModels:UserSelectorDialogViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Design.DataContext>
<viewModels:UserSelectorDialogViewModel />
</Design.DataContext>
@@ -80,7 +75,7 @@
Height="96"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Source="{Binding Image, Converter={StaticResource ByteImage}}" />
Source="{Binding Image, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
<TextBlock
HorizontalAlignment="Stretch"
MaxWidth="90"
@@ -110,12 +105,5 @@
</ListBox>
</Border>
<StackPanel
Grid.Row="1"
Margin="0 24 0 0"
HorizontalAlignment="Left"
Orientation="Horizontal"
Spacing="10">
</StackPanel>
</Grid>
</UserControl>

View File

@@ -13,9 +13,6 @@
mc:Ignorable="d"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
x:DataType="viewModels:MainWindowViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
@@ -68,7 +65,7 @@
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
Source="{Binding Icon, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
<Panel
Grid.Row="1"
Height="50"

View File

@@ -12,9 +12,6 @@
mc:Ignorable="d"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
x:DataType="viewModels:MainWindowViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
@@ -62,7 +59,7 @@
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
Source="{Binding Icon, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
<Border
Grid.Column="2"
Margin="0,0,5,0"

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
internal class BitmapArrayValueConverter : IValueConverter
{
public static BitmapArrayValueConverter Instance = new();
public static readonly BitmapArrayValueConverter Instance = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
internal class DownloadableContentLabelConverter : IMultiValueConverter
{
public static DownloadableContentLabelConverter Instance = new();
public static readonly DownloadableContentLabelConverter Instance = new();
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
{

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
internal class KeyValueConverter : IValueConverter
{
public static KeyValueConverter Instance = new();
public static readonly KeyValueConverter Instance = new();
private static readonly Dictionary<Key, LocaleKeys> _keysMap = new()
{

View File

@@ -1,6 +1,5 @@
using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities.AppLibrary;
using System;
using System.Globalization;
@@ -19,15 +18,10 @@ namespace Ryujinx.Ava.UI.Helpers
{
return $"Hosted Games: {applicationData.GameCount}\nOnline Players: {applicationData.PlayerCount}";
}
else
{
return "";
}
}
else
{
return "";
}
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
internal class TitleUpdateLabelConverter : IMultiValueConverter
{
public static TitleUpdateLabelConverter Instance = new();
public static readonly TitleUpdateLabelConverter Instance = new();
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
{

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Ava.UI.Helpers
internal class XCITrimmerFileSpaceSavingsConverter : IValueConverter
{
private const long _bytesPerMB = 1024 * 1024;
public static XCITrimmerFileSpaceSavingsConverter Instance = new();
public static readonly XCITrimmerFileSpaceSavingsConverter Instance = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{

View File

@@ -10,6 +10,7 @@ namespace Ryujinx.Ava.UI.Models.Input
public class GamepadInputConfig : BaseModel
{
public bool EnableCemuHookMotion { get; set; }
public bool EnableHandheldMotion { get; set; }
public string DsuServerHost { get; set; }
public int DsuServerPort { get; set; }
public int Slot { get; set; }
@@ -518,7 +519,7 @@ namespace Ryujinx.Ava.UI.Models.Input
EnableMotion = controllerInput.Motion.EnableMotion;
GyroDeadzone = controllerInput.Motion.GyroDeadzone;
Sensitivity = controllerInput.Motion.Sensitivity;
EnableHandheldMotion = controllerInput.Motion.MotionBackend == MotionInputBackendType.Handheld;
if (controllerInput.Motion is CemuHookMotionConfigController cemuHook)
{
EnableCemuHookMotion = true;
@@ -641,7 +642,7 @@ namespace Ryujinx.Ava.UI.Models.Input
config.Motion = new StandardMotionConfigController
{
EnableMotion = EnableMotion,
MotionBackend = MotionInputBackendType.GamepadDriver,
MotionBackend = EnableHandheldMotion ? MotionInputBackendType.Handheld : MotionInputBackendType.GamepadDriver,
GyroDeadzone = GyroDeadzone,
Sensitivity = Sensitivity,
};

View File

@@ -18,6 +18,34 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
[ObservableProperty] private double _gyroDeadzone;
[ObservableProperty] private bool _enableCemuHookMotion;
private bool _enableCemuHookMotion;
public bool EnableCemuHookMotion
{
get => _enableCemuHookMotion;
set
{
if (value)
{
EnableHandheldMotion = false;
}
_enableCemuHookMotion = value;
OnPropertyChanged();
}
}
private bool _enableHandheldMotion;
public bool EnableHandheldMotion
{
get => _enableHandheldMotion;
set
{
if (value)
{
EnableCemuHookMotion = false;
}
_enableHandheldMotion = value;
OnPropertyChanged();
}
}
}
}

View File

@@ -20,9 +20,6 @@
<Design.DataContext>
<viewModels:ControllerInputViewModel />
</Design.DataContext>
<UserControl.Resources>
<helpers:KeyValueConverter x:Key="Key" />
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="ToggleButton">
<Setter Property="Width" Value="90" />
@@ -78,7 +75,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonZl">
<TextBlock
Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonZl, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -94,7 +91,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonL">
<TextBlock
Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonL, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -110,7 +107,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonMinus">
<TextBlock
Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonMinus, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -144,7 +141,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftStickButton">
<TextBlock
Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
Text="{Binding Config.LeftStickButton, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -161,7 +158,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftJoystick" Tag="stick">
<TextBlock
Text="{Binding Config.LeftJoystick, Converter={StaticResource Key}}"
Text="{Binding Config.LeftJoystick, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -254,7 +251,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadUp">
<TextBlock
Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
Text="{Binding Config.DpadUp, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -271,7 +268,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadDown">
<TextBlock
Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
Text="{Binding Config.DpadDown, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -288,7 +285,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadLeft">
<TextBlock
Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
Text="{Binding Config.DpadLeft, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -305,7 +302,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadRight">
<TextBlock
Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
Text="{Binding Config.DpadRight, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -368,7 +365,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftButtonSr">
<TextBlock
Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
Text="{Binding Config.LeftButtonSr, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -386,7 +383,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftButtonSl">
<TextBlock
Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
Text="{Binding Config.LeftButtonSl, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -404,7 +401,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightButtonSr">
<TextBlock
Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
Text="{Binding Config.RightButtonSr, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -422,7 +419,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightButtonSl">
<TextBlock
Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
Text="{Binding Config.RightButtonSl, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -550,7 +547,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonZr">
<TextBlock
Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonZr, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -568,7 +565,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonR">
<TextBlock
Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonR, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -586,7 +583,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonPlus">
<TextBlock
Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonPlus, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -621,7 +618,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonA">
<TextBlock
Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonA, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -638,7 +635,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonB">
<TextBlock
Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonB, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -655,7 +652,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonX">
<TextBlock
Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonX, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -672,7 +669,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonY">
<TextBlock
Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonY, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -706,7 +703,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightStickButton">
<TextBlock
Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
Text="{Binding Config.RightStickButton, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -724,7 +721,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightJoystick" Tag="stick">
<TextBlock
Text="{Binding Config.RightJoystick, Converter={StaticResource Key}}"
Text="{Binding Config.RightJoystick, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>

View File

@@ -18,9 +18,6 @@
<Design.DataContext>
<viewModels:KeyboardInputViewModel />
</Design.DataContext>
<UserControl.Resources>
<helpers:KeyValueConverter x:Key="Key" />
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="ToggleButton">
<Setter Property="Width" Value="90" />
@@ -76,7 +73,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonZl">
<TextBlock
Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonZl, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -92,7 +89,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonL">
<TextBlock
Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonL, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -108,7 +105,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonMinus">
<TextBlock
Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonMinus, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -143,7 +140,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftStickButton">
<TextBlock
Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
Text="{Binding Config.LeftStickButton, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -160,7 +157,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftStickUp">
<TextBlock
Text="{Binding Config.LeftStickUp, Converter={StaticResource Key}}"
Text="{Binding Config.LeftStickUp, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -177,7 +174,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftStickDown">
<TextBlock
Text="{Binding Config.LeftStickDown, Converter={StaticResource Key}}"
Text="{Binding Config.LeftStickDown, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -194,7 +191,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftStickLeft">
<TextBlock
Text="{Binding Config.LeftStickLeft, Converter={StaticResource Key}}"
Text="{Binding Config.LeftStickLeft, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -211,7 +208,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftStickRight">
<TextBlock
Text="{Binding Config.LeftStickRight, Converter={StaticResource Key}}"
Text="{Binding Config.LeftStickRight, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -247,7 +244,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadUp">
<TextBlock
Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
Text="{Binding Config.DpadUp, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -264,7 +261,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadDown">
<TextBlock
Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
Text="{Binding Config.DpadDown, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -281,7 +278,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadLeft">
<TextBlock
Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
Text="{Binding Config.DpadLeft, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -298,7 +295,7 @@
TextAlignment="Center" />
<ToggleButton Name="DpadRight">
<TextBlock
Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
Text="{Binding Config.DpadRight, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -341,7 +338,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftButtonSr">
<TextBlock
Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
Text="{Binding Config.LeftButtonSr, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -359,7 +356,7 @@
TextAlignment="Center" />
<ToggleButton Name="LeftButtonSl">
<TextBlock
Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
Text="{Binding Config.LeftButtonSl, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -377,7 +374,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightButtonSr">
<TextBlock
Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
Text="{Binding Config.RightButtonSr, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -395,7 +392,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightButtonSl">
<TextBlock
Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
Text="{Binding Config.RightButtonSl, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -437,7 +434,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonZr">
<TextBlock
Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonZr, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -455,7 +452,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonR">
<TextBlock
Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonR, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -473,7 +470,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonPlus">
<TextBlock
Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonPlus, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -508,7 +505,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonA">
<TextBlock
Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonA, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -525,7 +522,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonB">
<TextBlock
Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonB, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -542,7 +539,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonX">
<TextBlock
Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonX, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -559,7 +556,7 @@
TextAlignment="Center" />
<ToggleButton Name="ButtonY">
<TextBlock
Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
Text="{Binding Config.ButtonY, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -594,7 +591,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightStickButton">
<TextBlock
Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
Text="{Binding Config.RightStickButton, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -611,7 +608,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightStickUp">
<TextBlock
Text="{Binding Config.RightStickUp, Converter={StaticResource Key}}"
Text="{Binding Config.RightStickUp, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -628,7 +625,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightStickDown">
<TextBlock
Text="{Binding Config.RightStickDown, Converter={StaticResource Key}}"
Text="{Binding Config.RightStickDown, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -645,7 +642,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightStickLeft">
<TextBlock
Text="{Binding Config.RightStickLeft, Converter={StaticResource Key}}"
Text="{Binding Config.RightStickLeft, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>
@@ -662,7 +659,7 @@
TextAlignment="Center" />
<ToggleButton Name="RightStickRight">
<TextBlock
Text="{Binding Config.RightStickRight, Converter={StaticResource Key}}"
Text="{Binding Config.RightStickRight, Converter={x:Static helpers:KeyValueConverter.Instance}}"
TextAlignment="Center" />
</ToggleButton>
</StackPanel>

View File

@@ -61,6 +61,17 @@
Margin="5, 0"
Text="{Binding GyroDeadzone, StringFormat=\{0:0.00\}}" />
</StackPanel>
<Separator
Height="1"
Margin="0,5" />
<CheckBox
Margin="5"
IsChecked="{Binding EnableHandheldMotion}">
<TextBlock
Margin="0,3,0,0"
VerticalAlignment="Center"
Text="{ext:Locale ControllerSettingsMotionUseHandheldCompatibleMotion}" />
</CheckBox>
<Separator
Height="1"
Margin="0,5" />

View File

@@ -30,6 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Input
Sensitivity = config.Sensitivity,
GyroDeadzone = config.GyroDeadzone,
EnableCemuHookMotion = config.EnableCemuHookMotion,
EnableHandheldMotion = config.EnableHandheldMotion,
};
InitializeComponent();
@@ -58,6 +59,7 @@ namespace Ryujinx.Ava.UI.Views.Input
config.DsuServerHost = content._viewModel.DsuServerHost;
config.DsuServerPort = content._viewModel.DsuServerPort;
config.EnableCemuHookMotion = content._viewModel.EnableCemuHookMotion;
config.EnableHandheldMotion = content._viewModel.EnableHandheldMotion;
config.MirrorInput = content._viewModel.MirrorInput;
};

View File

@@ -14,9 +14,6 @@
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
<UserControl.Resources>
<helpers:KeyValueConverter x:Key="Key" />
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="StackPanel > StackPanel">
<Setter Property="Margin" Value="10, 0, 0, 0" />
@@ -52,67 +49,67 @@
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysToggleVSyncModeHotkey}" />
<ToggleButton Name="ToggleVSyncMode">
<TextBlock Text="{Binding KeyboardHotkey.ToggleVSyncMode, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.ToggleVSyncMode, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysScreenshotHotkey}" />
<ToggleButton Name="Screenshot">
<TextBlock Text="{Binding KeyboardHotkey.Screenshot, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.Screenshot, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysShowUiHotkey}" />
<ToggleButton Name="ShowUI">
<TextBlock Text="{Binding KeyboardHotkey.ShowUI, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.ShowUI, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysPauseHotkey}" />
<ToggleButton Name="Pause">
<TextBlock Text="{Binding KeyboardHotkey.Pause, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.Pause, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysToggleMuteHotkey}" />
<ToggleButton Name="ToggleMute">
<TextBlock Text="{Binding KeyboardHotkey.ToggleMute, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.ToggleMute, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysResScaleUpHotkey}" />
<ToggleButton Name="ResScaleUp">
<TextBlock Text="{Binding KeyboardHotkey.ResScaleUp, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.ResScaleUp, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysResScaleDownHotkey}" />
<ToggleButton Name="ResScaleDown">
<TextBlock Text="{Binding KeyboardHotkey.ResScaleDown, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.ResScaleDown, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysVolumeUpHotkey}" />
<ToggleButton Name="VolumeUp">
<TextBlock Text="{Binding KeyboardHotkey.VolumeUp, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.VolumeUp, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysVolumeDownHotkey}" />
<ToggleButton Name="VolumeDown">
<TextBlock Text="{Binding KeyboardHotkey.VolumeDown, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.VolumeDown, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey}" />
<ToggleButton Name="CustomVSyncIntervalIncrement">
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalIncrement, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalIncrement, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey}" />
<ToggleButton Name="CustomVSyncIntervalDecrement">
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalDecrement, Converter={StaticResource Key}}" />
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalDecrement, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
</StackPanel>
</StackPanel>

View File

@@ -7,23 +7,26 @@ namespace Ryujinx.Ava.UI.Views.Settings
{
public partial class SettingsNetworkView : UserControl
{
private readonly Random _random;
public SettingsViewModel ViewModel;
public SettingsNetworkView()
{
_random = new Random();
InitializeComponent();
}
private void GenLdnPassButton_OnClick(object sender, RoutedEventArgs e)
{
byte[] code = new byte[4];
new Random().NextBytes(code);
_random.NextBytes(code);
ViewModel.LdnPassphrase = $"Ryujinx-{BitConverter.ToUInt32(code):x8}";
}
private void ClearLdnPassButton_OnClick(object sender, RoutedEventArgs e)
{
ViewModel.LdnPassphrase = "";
ViewModel.LdnPassphrase = string.Empty;
}
}
}

View File

@@ -10,9 +10,6 @@
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel">
<UserControl.Resources>
<helpers:TimeZoneConverter x:Key="TimeZone" />
</UserControl.Resources>
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
@@ -162,7 +159,7 @@
Text="{Binding Path=TimeZone, Mode=OneWay}"
TextChanged="TimeZoneBox_OnTextChanged"
ToolTip.Tip="{ext:Locale TimezoneTooltip}"
ValueMemberBinding="{Binding Mode=OneWay, Converter={StaticResource TimeZone}}" />
ValueMemberBinding="{Binding Mode=OneWay, Converter={x:Static helpers:TimeZoneConverter.Instance}}" />
</StackPanel>
<StackPanel
Margin="0,0,0,10"

View File

@@ -14,9 +14,6 @@
mc:Ignorable="d"
Focusable="True"
x:DataType="models:TempProfile">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Grid Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -74,7 +71,7 @@
Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Source="{Binding Image, Converter={StaticResource ByteImage}}" />
Source="{Binding Image, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
</Panel>
</Border>
</StackPanel>

View File

@@ -17,9 +17,6 @@
<Design.DataContext>
<viewModels:UserFirmwareAvatarSelectorViewModel />
</Design.DataContext>
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Grid
Margin="0"
HorizontalAlignment="Stretch"
@@ -62,7 +59,7 @@
<Panel
Background="{Binding BackgroundColor}"
Margin="5">
<Image Source="{Binding Data, Converter={StaticResource ByteImage}}" />
<Image Source="{Binding Data, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
</Panel>
</DataTemplate>
</ListBox.ItemTemplate>

View File

@@ -19,9 +19,6 @@
<Design.DataContext>
<viewModels:UserSaveManagerViewModel />
</Design.DataContext>
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@@ -147,7 +144,7 @@
IsVisible="{Binding InGameList}"
Width="42"
Height="42"
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
Source="{Binding Icon, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
<TextBlock
MaxLines="3"
Width="320"

View File

@@ -15,9 +15,6 @@
mc:Ignorable="d"
Focusable="True"
x:DataType="viewModels:UserProfileViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Design.DataContext>
<viewModels:UserProfileViewModel />
</Design.DataContext>
@@ -74,7 +71,7 @@
Height="96"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Source="{Binding Image, Converter={StaticResource ByteImage}}" />
Source="{Binding Image, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
<TextBlock
HorizontalAlignment="Stretch"
MaxWidth="90"

View File

@@ -30,9 +30,6 @@
<Design.DataContext>
<viewModels:MainWindowViewModel />
</Design.DataContext>
<Window.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</Window.Resources>
<Window.KeyBindings>
<KeyBinding Gesture="Alt+Return" Command="{Binding ToggleFullscreen}" />
<KeyBinding Gesture="F11" Command="{Binding ToggleFullscreen}" />
@@ -121,7 +118,7 @@
Width="256"
Height="256"
IsVisible="{Binding ShowLoadProgress}"
Source="{Binding SelectedIcon, Converter={StaticResource ByteImage}}" />
Source="{Binding SelectedIcon, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
</Border>
<Grid
Grid.Column="1"

View File

@@ -29,11 +29,11 @@ using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.Input.HLE;
using Ryujinx.Input.SDL2;
using Ryujinx.Input.SDL3;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
@@ -108,7 +108,7 @@ namespace Ryujinx.Ava.UI.Windows
if (Program.PreviewerDetached)
{
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver(), new SDL3MotionDriver());
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
this.ScalingChanged += OnScalingChanged;

View File

@@ -14,9 +14,6 @@
mc:Ignorable="d"
x:DataType="viewModels:TitleUpdateViewModel"
Focusable="True">
<UserControl.Resources>
<helpers:TitleUpdateLabelConverter x:Key="TitleUpdateLabel" />
</UserControl.Resources>
<Grid RowDefinitions="Auto,*,Auto">
<StackPanel
Grid.Row="0"
@@ -57,7 +54,7 @@
VerticalAlignment="Center"
TextWrapping="Wrap">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource TitleUpdateLabel}">
<MultiBinding Converter="{x:Static helpers:TitleUpdateLabelConverter.Instance}">
<Binding Path="DisplayVersion" />
<Binding Path="IsBundled" />
</MultiBinding>

View File

@@ -13,11 +13,6 @@
x:DataType="viewModels:XCITrimmerViewModel"
Focusable="True"
mc:Ignorable="d">
<UserControl.Resources>
<helpers:XCITrimmerFileStatusConverter x:Key="StatusLabel" />
<helpers:XCITrimmerFileStatusDetailConverter x:Key="StatusDetailLabel" />
<helpers:XCITrimmerFileSpaceSavingsConverter x:Key="SpaceSavingsLabel" />
</UserControl.Resources>
<Grid Margin="20 0 20 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@@ -186,7 +181,7 @@
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="1"
Text="{Binding ., Converter={StaticResource StatusLabel}}">
Text="{Binding ., Converter={x:Static helpers:XCITrimmerFileStatusConverter.Instance}}">
<ToolTip.Tip>
<StackPanel
IsVisible="{Binding IsFailed}">
@@ -194,7 +189,7 @@
Classes="h1"
Text="{ext:Locale XCITrimmerTitleStatusFailed}" />
<TextBlock
Text="{Binding ., Converter={StaticResource StatusDetailLabel}}"
Text="{Binding ., Converter={x:Static helpers:XCITrimmerFileStatusDetailConverter.Instance}}"
MaxLines="5"
MaxWidth="200"
MaxHeight="100"
@@ -209,7 +204,7 @@
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="1"
Text="{Binding ., Converter={StaticResource SpaceSavingsLabel}}">>
Text="{Binding ., Converter={x:Static helpers:XCITrimmerFileSpaceSavingsConverter.Instance}}">>
</TextBlock>
</Grid>
</Grid>

View File

@@ -204,8 +204,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
Multiplayer.LanInterfaceId.Value = "0";
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
Multiplayer.DisableP2p.Value = false;
Multiplayer.LdnPassphrase.Value = "";
Multiplayer.LdnServer.Value = "";
Multiplayer.LdnPassphrase.Value = string.Empty;
Multiplayer.LdnServer.Value = string.Empty;
UI.GuiColumns.FavColumn.Value = true;
UI.GuiColumns.IconColumn.Value = true;
UI.GuiColumns.AppColumn.Value = true;