Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c46aa76fd | |||
| e104ee6be3 | |||
| e65d1ec6c9 | |||
| 534f92506b | |||
| 10d20c1ae3 | |||
| e294a79975 | |||
| ec06a86899 | |||
| 30e790ced4 | |||
| 5e8af26516 | |||
| 9356b68f26 | |||
| 14aafebaa6 | |||
| 4518666a04 | |||
| 4399edaa9f | |||
| 4e77bcb55a | |||
| 3cbd7dc1a1 | |||
| 536f792558 | |||
| 7a451ab160 | |||
| 99c7c3fb14 | |||
| 09e7b660f4 | |||
| 69dfd8c60e | |||
| 8e50dd9fa6 | |||
| 68c03051ad | |||
| a837294b11 | |||
| f1c0cc8076 | |||
| 6dec7ff8ba | |||
| 20fdbff964 | |||
| e426680cb0 | |||
| 7863e97cb0 | |||
| c4dea0ee28 | |||
| e0b6a01e9d | |||
| e509ffa716 | |||
| 714c68b548 | |||
| fec197d9ec | |||
| a4b2feef79 | |||
| ad7d9d1ce0 | |||
| 86f9544910 | |||
| e9ecbd44fc |
@@ -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, JoyCon input support, and nearly all controllers.
|
We currently have support for keyboard, mouse, touch input, Joy-Con 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.
|
||||||
|
|
||||||
|
|||||||
@@ -71,16 +71,24 @@ namespace Ryujinx.HLE.Loaders.Mods
|
|||||||
int patchOffset = (int)offset;
|
int patchOffset = (int)offset;
|
||||||
int patchSize = patch.Length;
|
int patchSize = patch.Length;
|
||||||
|
|
||||||
if (patchOffset < protectedOffset || patchOffset > memory.Length)
|
if (patchOffset < protectedOffset)
|
||||||
{
|
{
|
||||||
continue; // Add warning?
|
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch protected memory ({patchOffset:x} is within protected boundary of {protectedOffset:x}).");
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
patchSize = memory.Length - patchOffset; // Add warning?
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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}");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -36,6 +37,7 @@ namespace Ryujinx.Input.SDL2
|
|||||||
SDL2Driver.Instance.Initialize();
|
SDL2Driver.Instance.Initialize();
|
||||||
SDL2Driver.Instance.OnJoyStickConnected += HandleJoyStickConnected;
|
SDL2Driver.Instance.OnJoyStickConnected += HandleJoyStickConnected;
|
||||||
SDL2Driver.Instance.OnJoystickDisconnected += HandleJoyStickDisconnected;
|
SDL2Driver.Instance.OnJoystickDisconnected += HandleJoyStickDisconnected;
|
||||||
|
SDL2Driver.Instance.OnJoyBatteryUpdated += HandleJoyBatteryUpdated;
|
||||||
|
|
||||||
// Add already connected gamepads
|
// Add already connected gamepads
|
||||||
int numJoysticks = SDL_NumJoysticks();
|
int numJoysticks = SDL_NumJoysticks();
|
||||||
@@ -83,19 +85,30 @@ namespace Ryujinx.Input.SDL2
|
|||||||
|
|
||||||
private void HandleJoyStickDisconnected(int joystickInstanceId)
|
private void HandleJoyStickDisconnected(int joystickInstanceId)
|
||||||
{
|
{
|
||||||
|
bool joyConPairDisconnected = false;
|
||||||
if (!_gamepadsInstanceIdsMapping.Remove(joystickInstanceId, out string id))
|
if (!_gamepadsInstanceIdsMapping.Remove(joystickInstanceId, out string id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
_gamepadsIds.Remove(id);
|
_gamepadsIds.Remove(id);
|
||||||
|
if (!SDL2JoyConPair.IsCombinable(_gamepadsIds))
|
||||||
|
{
|
||||||
|
_gamepadsIds.Remove(SDL2JoyConPair.Id);
|
||||||
|
joyConPairDisconnected = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnGamepadDisconnected?.Invoke(id);
|
OnGamepadDisconnected?.Invoke(id);
|
||||||
|
if (joyConPairDisconnected)
|
||||||
|
{
|
||||||
|
OnGamepadDisconnected?.Invoke(SDL2JoyConPair.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId)
|
private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId)
|
||||||
{
|
{
|
||||||
|
bool joyConPairConnected = false;
|
||||||
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
|
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
|
||||||
{
|
{
|
||||||
if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
|
if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
|
||||||
@@ -120,13 +133,29 @@ namespace Ryujinx.Input.SDL2
|
|||||||
_gamepadsIds.Insert(joystickDeviceId, id);
|
_gamepadsIds.Insert(joystickDeviceId, id);
|
||||||
else
|
else
|
||||||
_gamepadsIds.Add(id);
|
_gamepadsIds.Add(id);
|
||||||
|
if (SDL2JoyConPair.IsCombinable(_gamepadsIds))
|
||||||
|
{
|
||||||
|
_gamepadsIds.Remove(SDL2JoyConPair.Id);
|
||||||
|
_gamepadsIds.Add(SDL2JoyConPair.Id);
|
||||||
|
joyConPairConnected = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnGamepadConnected?.Invoke(id);
|
OnGamepadConnected?.Invoke(id);
|
||||||
|
if (joyConPairConnected)
|
||||||
|
{
|
||||||
|
OnGamepadConnected?.Invoke(SDL2JoyConPair.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleJoyBatteryUpdated(int joystickDeviceId, SDL_JoystickPowerLevel powerLevel)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Hid,
|
||||||
|
$"{SDL_GameControllerNameForIndex(joystickDeviceId)} power level: {powerLevel}");
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
@@ -157,6 +186,14 @@ namespace Ryujinx.Input.SDL2
|
|||||||
|
|
||||||
public IGamepad GetGamepad(string id)
|
public IGamepad GetGamepad(string id)
|
||||||
{
|
{
|
||||||
|
if (id == SDL2JoyConPair.Id)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return SDL2JoyConPair.GetGamepad(_gamepadsIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int joystickIndex = GetJoystickIndexByGamepadId(id);
|
int joystickIndex = GetJoystickIndexByGamepadId(id);
|
||||||
|
|
||||||
if (joystickIndex == -1)
|
if (joystickIndex == -1)
|
||||||
@@ -165,12 +202,16 @@ namespace Ryujinx.Input.SDL2
|
|||||||
}
|
}
|
||||||
|
|
||||||
nint gamepadHandle = SDL_GameControllerOpen(joystickIndex);
|
nint gamepadHandle = SDL_GameControllerOpen(joystickIndex);
|
||||||
|
|
||||||
if (gamepadHandle == nint.Zero)
|
if (gamepadHandle == nint.Zero)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerName(gamepadHandle).StartsWith(SDL2JoyCon.Prefix))
|
||||||
|
{
|
||||||
|
return new SDL2JoyCon(gamepadHandle, id);
|
||||||
|
}
|
||||||
|
|
||||||
return new SDL2Gamepad(gamepadHandle, id);
|
return new SDL2Gamepad(gamepadHandle, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,409 @@
|
|||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Threading;
|
||||||
|
using static SDL2.SDL;
|
||||||
|
|
||||||
|
namespace Ryujinx.Input.SDL2
|
||||||
|
{
|
||||||
|
internal class SDL2JoyCon : IGamepad
|
||||||
|
{
|
||||||
|
private bool HasConfiguration => _configuration != null;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private readonly Dictionary<GamepadButtonInputId,SDL_GameControllerButton> _leftButtonsDriverMapping = new()
|
||||||
|
{
|
||||||
|
{ GamepadButtonInputId.LeftStick , SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK },
|
||||||
|
{GamepadButtonInputId.DpadUp ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y},
|
||||||
|
{GamepadButtonInputId.DpadDown ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A},
|
||||||
|
{GamepadButtonInputId.DpadLeft ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B},
|
||||||
|
{GamepadButtonInputId.DpadRight ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X},
|
||||||
|
{GamepadButtonInputId.Minus ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START},
|
||||||
|
{GamepadButtonInputId.LeftShoulder,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE2},
|
||||||
|
{GamepadButtonInputId.LeftTrigger,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE4},
|
||||||
|
{GamepadButtonInputId.SingleRightTrigger0,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||||
|
{GamepadButtonInputId.SingleLeftTrigger0,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||||
|
};
|
||||||
|
private readonly Dictionary<GamepadButtonInputId,SDL_GameControllerButton> _rightButtonsDriverMapping = new()
|
||||||
|
{
|
||||||
|
{GamepadButtonInputId.RightStick,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK},
|
||||||
|
{GamepadButtonInputId.A,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B},
|
||||||
|
{GamepadButtonInputId.B,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y},
|
||||||
|
{GamepadButtonInputId.X,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A},
|
||||||
|
{GamepadButtonInputId.Y,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X},
|
||||||
|
{GamepadButtonInputId.Plus,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START},
|
||||||
|
{GamepadButtonInputId.RightShoulder,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE1},
|
||||||
|
{GamepadButtonInputId.RightTrigger,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE3},
|
||||||
|
{GamepadButtonInputId.SingleRightTrigger1,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||||
|
{GamepadButtonInputId.SingleLeftTrigger1,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER}
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly Dictionary<GamepadButtonInputId, SDL_GameControllerButton> _buttonsDriverMapping;
|
||||||
|
private readonly Lock _userMappingLock = new();
|
||||||
|
|
||||||
|
private readonly List<ButtonMappingEntry> _buttonsUserMapping;
|
||||||
|
|
||||||
|
private readonly StickInputId[] _stickUserMapping = new StickInputId[(int)StickInputId.Count]
|
||||||
|
{
|
||||||
|
StickInputId.Unbound, StickInputId.Left, StickInputId.Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
public GamepadFeaturesFlag Features { get; }
|
||||||
|
|
||||||
|
private nint _gamepadHandle;
|
||||||
|
|
||||||
|
private enum JoyConType
|
||||||
|
{
|
||||||
|
Left, Right
|
||||||
|
}
|
||||||
|
|
||||||
|
public const string Prefix = "Nintendo Switch Joy-Con";
|
||||||
|
public const string LeftName = "Nintendo Switch Joy-Con (L)";
|
||||||
|
public const string RightName = "Nintendo Switch Joy-Con (R)";
|
||||||
|
|
||||||
|
private readonly JoyConType _joyConType;
|
||||||
|
|
||||||
|
public SDL2JoyCon(nint gamepadHandle, string driverId)
|
||||||
|
{
|
||||||
|
_gamepadHandle = gamepadHandle;
|
||||||
|
_buttonsUserMapping = new List<ButtonMappingEntry>(10);
|
||||||
|
|
||||||
|
Name = SDL_GameControllerName(_gamepadHandle);
|
||||||
|
Id = driverId;
|
||||||
|
Features = GetFeaturesFlag();
|
||||||
|
|
||||||
|
// Enable motion tracking
|
||||||
|
if (Features.HasFlag(GamepadFeaturesFlag.Motion))
|
||||||
|
{
|
||||||
|
if (SDL_GameControllerSetSensorEnabled(_gamepadHandle, SDL_SensorType.SDL_SENSOR_ACCEL,
|
||||||
|
SDL_bool.SDL_TRUE) != 0)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Hid,
|
||||||
|
$"Could not enable data reporting for SensorType {SDL_SensorType.SDL_SENSOR_ACCEL}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerSetSensorEnabled(_gamepadHandle, SDL_SensorType.SDL_SENSOR_GYRO,
|
||||||
|
SDL_bool.SDL_TRUE) != 0)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Hid,
|
||||||
|
$"Could not enable data reporting for SensorType {SDL_SensorType.SDL_SENSOR_GYRO}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Name)
|
||||||
|
{
|
||||||
|
case LeftName:
|
||||||
|
{
|
||||||
|
_buttonsDriverMapping = _leftButtonsDriverMapping;
|
||||||
|
_joyConType = JoyConType.Left;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RightName:
|
||||||
|
{
|
||||||
|
_buttonsDriverMapping = _rightButtonsDriverMapping;
|
||||||
|
_joyConType = JoyConType.Right;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GamepadFeaturesFlag GetFeaturesFlag()
|
||||||
|
{
|
||||||
|
GamepadFeaturesFlag result = GamepadFeaturesFlag.None;
|
||||||
|
|
||||||
|
if (SDL_GameControllerHasSensor(_gamepadHandle, SDL_SensorType.SDL_SENSOR_ACCEL) == SDL_bool.SDL_TRUE &&
|
||||||
|
SDL_GameControllerHasSensor(_gamepadHandle, SDL_SensorType.SDL_SENSOR_GYRO) == SDL_bool.SDL_TRUE)
|
||||||
|
{
|
||||||
|
result |= GamepadFeaturesFlag.Motion;
|
||||||
|
}
|
||||||
|
|
||||||
|
int error = SDL_GameControllerRumble(_gamepadHandle, 0, 0, 100);
|
||||||
|
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
result |= GamepadFeaturesFlag.Rumble;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id { get; }
|
||||||
|
public string Name { get; }
|
||||||
|
public bool IsConnected => SDL_GameControllerGetAttached(_gamepadHandle) == SDL_bool.SDL_TRUE;
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && _gamepadHandle != nint.Zero)
|
||||||
|
{
|
||||||
|
SDL_GameControllerClose(_gamepadHandle);
|
||||||
|
|
||||||
|
_gamepadHandle = nint.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SetTriggerThreshold(float triggerThreshold)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
|
{
|
||||||
|
if (!Features.HasFlag(GamepadFeaturesFlag.Rumble))
|
||||||
|
return;
|
||||||
|
|
||||||
|
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 = inputId switch
|
||||||
|
{
|
||||||
|
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 is SDL_SensorType.SDL_SENSOR_INVALID)
|
||||||
|
return Vector3.Zero;
|
||||||
|
|
||||||
|
const int ElementCount = 3;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
float* values = stackalloc float[ElementCount];
|
||||||
|
|
||||||
|
int result = SDL_GameControllerGetSensorData(_gamepadHandle, sensorType, (nint)values, ElementCount);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
return Vector3.Zero;
|
||||||
|
|
||||||
|
Vector3 value = _joyConType switch
|
||||||
|
{
|
||||||
|
JoyConType.Left => new Vector3(-values[2], values[1], values[0]),
|
||||||
|
JoyConType.Right => new Vector3(values[2], values[1], -values[0])
|
||||||
|
};
|
||||||
|
|
||||||
|
return inputId switch
|
||||||
|
{
|
||||||
|
MotionInputId.Gyroscope => RadToDegree(value),
|
||||||
|
MotionInputId.Accelerometer => GsToMs2(value),
|
||||||
|
_ => value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector3 RadToDegree(Vector3 rad) => rad * (180 / MathF.PI);
|
||||||
|
|
||||||
|
private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY;
|
||||||
|
|
||||||
|
public void SetConfiguration(InputConfig configuration)
|
||||||
|
{
|
||||||
|
lock (_userMappingLock)
|
||||||
|
{
|
||||||
|
_configuration = (StandardControllerInputConfig)configuration;
|
||||||
|
|
||||||
|
_buttonsUserMapping.Clear();
|
||||||
|
|
||||||
|
// First update sticks
|
||||||
|
_stickUserMapping[(int)StickInputId.Left] = (StickInputId)_configuration.LeftJoyconStick.Joystick;
|
||||||
|
_stickUserMapping[(int)StickInputId.Right] = (StickInputId)_configuration.RightJoyconStick.Joystick;
|
||||||
|
|
||||||
|
|
||||||
|
switch (_joyConType)
|
||||||
|
{
|
||||||
|
case JoyConType.Left:
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (GamepadButtonInputId)_configuration.LeftJoyconStick.StickButton));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (GamepadButtonInputId)_configuration.LeftJoycon.DpadUp));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (GamepadButtonInputId)_configuration.LeftJoycon.DpadDown));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (GamepadButtonInputId)_configuration.LeftJoycon.DpadLeft));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (GamepadButtonInputId)_configuration.LeftJoycon.DpadRight));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (GamepadButtonInputId)_configuration.LeftJoycon.ButtonMinus));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (GamepadButtonInputId)_configuration.LeftJoycon.ButtonL));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (GamepadButtonInputId)_configuration.LeftJoycon.ButtonZl));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (GamepadButtonInputId)_configuration.LeftJoycon.ButtonSr));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (GamepadButtonInputId)_configuration.LeftJoycon.ButtonSl));
|
||||||
|
break;
|
||||||
|
case JoyConType.Right:
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (GamepadButtonInputId)_configuration.RightJoyconStick.StickButton));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (GamepadButtonInputId)_configuration.RightJoycon.ButtonA));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (GamepadButtonInputId)_configuration.RightJoycon.ButtonB));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (GamepadButtonInputId)_configuration.RightJoycon.ButtonX));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (GamepadButtonInputId)_configuration.RightJoycon.ButtonY));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (GamepadButtonInputId)_configuration.RightJoycon.ButtonPlus));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (GamepadButtonInputId)_configuration.RightJoycon.ButtonR));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (GamepadButtonInputId)_configuration.RightJoycon.ButtonZr));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (GamepadButtonInputId)_configuration.RightJoycon.ButtonSr));
|
||||||
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (GamepadButtonInputId)_configuration.RightJoycon.ButtonSl));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTriggerThreshold(_configuration.TriggerThreshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GamepadStateSnapshot GetStateSnapshot()
|
||||||
|
{
|
||||||
|
return IGamepad.GetStateSnapshot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GamepadStateSnapshot GetMappedStateSnapshot()
|
||||||
|
{
|
||||||
|
GamepadStateSnapshot rawState = GetStateSnapshot();
|
||||||
|
GamepadStateSnapshot result = default;
|
||||||
|
|
||||||
|
lock (_userMappingLock)
|
||||||
|
{
|
||||||
|
if (_buttonsUserMapping.Count == 0)
|
||||||
|
return rawState;
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
||||||
|
foreach (ButtonMappingEntry entry in _buttonsUserMapping)
|
||||||
|
{
|
||||||
|
if (!entry.IsValid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Do not touch state of button already pressed
|
||||||
|
if (!result.IsPressed(entry.To))
|
||||||
|
{
|
||||||
|
result.SetPressed(entry.To, rawState.IsPressed(entry.From));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(float leftStickX, float leftStickY) = rawState.GetStick(_stickUserMapping[(int)StickInputId.Left]);
|
||||||
|
(float rightStickX, float rightStickY) = rawState.GetStick(_stickUserMapping[(int)StickInputId.Right]);
|
||||||
|
|
||||||
|
result.SetStick(StickInputId.Left, leftStickX, leftStickY);
|
||||||
|
result.SetStick(StickInputId.Right, rightStickX, rightStickY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static float ConvertRawStickValue(short value)
|
||||||
|
{
|
||||||
|
const float ConvertRate = 1.0f / (short.MaxValue + 0.5f);
|
||||||
|
|
||||||
|
return value * ConvertRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JoyconConfigControllerStick<GamepadInputId, Common.Configuration.Hid.Controller.StickInputId>
|
||||||
|
GetLogicalJoyStickConfig(StickInputId inputId)
|
||||||
|
{
|
||||||
|
switch (inputId)
|
||||||
|
{
|
||||||
|
case StickInputId.Left:
|
||||||
|
if (_configuration.RightJoyconStick.Joystick ==
|
||||||
|
Common.Configuration.Hid.Controller.StickInputId.Left)
|
||||||
|
return _configuration.RightJoyconStick;
|
||||||
|
else
|
||||||
|
return _configuration.LeftJoyconStick;
|
||||||
|
case StickInputId.Right:
|
||||||
|
if (_configuration.LeftJoyconStick.Joystick ==
|
||||||
|
Common.Configuration.Hid.Controller.StickInputId.Right)
|
||||||
|
return _configuration.LeftJoyconStick;
|
||||||
|
else
|
||||||
|
return _configuration.RightJoyconStick;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public (float, float) GetStick(StickInputId inputId)
|
||||||
|
{
|
||||||
|
if (inputId == StickInputId.Unbound)
|
||||||
|
return (0.0f, 0.0f);
|
||||||
|
|
||||||
|
if (inputId == StickInputId.Left && _joyConType == JoyConType.Right || inputId == StickInputId.Right && _joyConType == JoyConType.Left)
|
||||||
|
{
|
||||||
|
return (0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
(short stickX, short stickY) = GetStickXY();
|
||||||
|
|
||||||
|
float resultX = ConvertRawStickValue(stickX);
|
||||||
|
float resultY = -ConvertRawStickValue(stickY);
|
||||||
|
|
||||||
|
if (HasConfiguration)
|
||||||
|
{
|
||||||
|
var joyconStickConfig = GetLogicalJoyStickConfig(inputId);
|
||||||
|
|
||||||
|
if (joyconStickConfig != null)
|
||||||
|
{
|
||||||
|
if (joyconStickConfig.InvertStickX)
|
||||||
|
resultX = -resultX;
|
||||||
|
|
||||||
|
if (joyconStickConfig.InvertStickY)
|
||||||
|
resultY = -resultY;
|
||||||
|
|
||||||
|
if (joyconStickConfig.Rotate90CW)
|
||||||
|
{
|
||||||
|
float temp = resultX;
|
||||||
|
resultX = resultY;
|
||||||
|
resultY = -temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputId switch
|
||||||
|
{
|
||||||
|
StickInputId.Left when _joyConType == JoyConType.Left => (resultY, -resultX),
|
||||||
|
StickInputId.Right when _joyConType == JoyConType.Right => (-resultY, resultX),
|
||||||
|
_ => (0.0f, 0.0f)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private (short, short) GetStickXY()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX),
|
||||||
|
SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPressed(GamepadButtonInputId inputId)
|
||||||
|
{
|
||||||
|
if (!_buttonsDriverMapping.TryGetValue(inputId, out var button))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_GameControllerGetButton(_gamepadHandle, button) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using static SDL2.SDL;
|
||||||
|
|
||||||
|
namespace Ryujinx.Input.SDL2
|
||||||
|
{
|
||||||
|
internal class SDL2JoyConPair(IGamepad left, IGamepad right) : IGamepad
|
||||||
|
{
|
||||||
|
private StandardControllerInputConfig _configuration;
|
||||||
|
|
||||||
|
private readonly StickInputId[] _stickUserMapping =
|
||||||
|
[
|
||||||
|
StickInputId.Unbound,
|
||||||
|
StickInputId.Left,
|
||||||
|
StickInputId.Right
|
||||||
|
];
|
||||||
|
|
||||||
|
public GamepadFeaturesFlag Features => (left?.Features ?? GamepadFeaturesFlag.None) |
|
||||||
|
(right?.Features ?? GamepadFeaturesFlag.None);
|
||||||
|
|
||||||
|
public const string Id = "JoyConPair";
|
||||||
|
string IGamepad.Id => Id;
|
||||||
|
|
||||||
|
public string Name => "* Nintendo Switch Joy-Con (L/R)";
|
||||||
|
public bool IsConnected => left is { IsConnected: true } && right is { IsConnected: true };
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
left?.Dispose();
|
||||||
|
right?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GamepadStateSnapshot GetMappedStateSnapshot()
|
||||||
|
{
|
||||||
|
return GetStateSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 GetMotionData(MotionInputId inputId)
|
||||||
|
{
|
||||||
|
return inputId switch
|
||||||
|
{
|
||||||
|
MotionInputId.Accelerometer or
|
||||||
|
MotionInputId.Gyroscope => left.GetMotionData(inputId),
|
||||||
|
MotionInputId.SecondAccelerometer => right.GetMotionData(MotionInputId.Accelerometer),
|
||||||
|
MotionInputId.SecondGyroscope => right.GetMotionData(MotionInputId.Gyroscope),
|
||||||
|
_ => Vector3.Zero
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public GamepadStateSnapshot GetStateSnapshot()
|
||||||
|
{
|
||||||
|
return IGamepad.GetStateSnapshot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (float, float) GetStick(StickInputId inputId)
|
||||||
|
{
|
||||||
|
return inputId switch
|
||||||
|
{
|
||||||
|
StickInputId.Left => left.GetStick(StickInputId.Left),
|
||||||
|
StickInputId.Right => right.GetStick(StickInputId.Right),
|
||||||
|
_ => (0, 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPressed(GamepadButtonInputId inputId)
|
||||||
|
{
|
||||||
|
return left.IsPressed(inputId) || right.IsPressed(inputId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
|
{
|
||||||
|
if (lowFrequency != 0)
|
||||||
|
{
|
||||||
|
right.Rumble(lowFrequency, lowFrequency, durationMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highFrequency != 0)
|
||||||
|
{
|
||||||
|
left.Rumble(highFrequency, highFrequency, durationMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowFrequency == 0 && highFrequency == 0)
|
||||||
|
{
|
||||||
|
left.Rumble(0, 0, durationMs);
|
||||||
|
right.Rumble(0, 0, durationMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetConfiguration(InputConfig configuration)
|
||||||
|
{
|
||||||
|
left.SetConfiguration(configuration);
|
||||||
|
right.SetConfiguration(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTriggerThreshold(float triggerThreshold)
|
||||||
|
{
|
||||||
|
left.SetTriggerThreshold(triggerThreshold);
|
||||||
|
right.SetTriggerThreshold(triggerThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsCombinable(List<string> gamepadsIds)
|
||||||
|
{
|
||||||
|
(int leftIndex, int rightIndex) = DetectJoyConPair(gamepadsIds);
|
||||||
|
return leftIndex >= 0 && rightIndex >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (int leftIndex, int rightIndex) DetectJoyConPair(List<string> gamepadsIds)
|
||||||
|
{
|
||||||
|
var gamepadNames = gamepadsIds.Where(gamepadId => gamepadId != Id)
|
||||||
|
.Select((_, index) => SDL_GameControllerNameForIndex(index)).ToList();
|
||||||
|
int leftIndex = gamepadNames.IndexOf(SDL2JoyCon.LeftName);
|
||||||
|
int rightIndex = gamepadNames.IndexOf(SDL2JoyCon.RightName);
|
||||||
|
|
||||||
|
return (leftIndex, rightIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IGamepad GetGamepad(List<string> gamepadsIds)
|
||||||
|
{
|
||||||
|
(int leftIndex, int rightIndex) = DetectJoyConPair(gamepadsIds);
|
||||||
|
if (leftIndex == -1 || rightIndex == -1)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
nint leftGamepadHandle = SDL_GameControllerOpen(leftIndex);
|
||||||
|
nint rightGamepadHandle = SDL_GameControllerOpen(rightIndex);
|
||||||
|
|
||||||
|
if (leftGamepadHandle == nint.Zero || rightGamepadHandle == nint.Zero)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return new SDL2JoyConPair(new SDL2JoyCon(leftGamepadHandle, gamepadsIds[leftIndex]),
|
||||||
|
new SDL2JoyCon(rightGamepadHandle, gamepadsIds[rightIndex]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -269,6 +269,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
if (motionConfig.MotionBackend != MotionInputBackendType.CemuHook)
|
if (motionConfig.MotionBackend != MotionInputBackendType.CemuHook)
|
||||||
{
|
{
|
||||||
_leftMotionInput = new MotionInput();
|
_leftMotionInput = new MotionInput();
|
||||||
|
_rightMotionInput = new MotionInput();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -301,7 +302,20 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
if (controllerConfig.ControllerType == ConfigControllerType.JoyconPair)
|
if (controllerConfig.ControllerType == ConfigControllerType.JoyconPair)
|
||||||
{
|
{
|
||||||
_rightMotionInput = _leftMotionInput;
|
if (gamepad.Id== "JoyConPair")
|
||||||
|
{
|
||||||
|
Vector3 rightAccelerometer = gamepad.GetMotionData(MotionInputId.SecondAccelerometer);
|
||||||
|
Vector3 rightGyroscope = gamepad.GetMotionData(MotionInputId.SecondGyroscope);
|
||||||
|
|
||||||
|
rightAccelerometer = new Vector3(rightAccelerometer.X, -rightAccelerometer.Z, rightAccelerometer.Y);
|
||||||
|
rightGyroscope = new Vector3(rightGyroscope.X, -rightGyroscope.Z, rightGyroscope.Y);
|
||||||
|
|
||||||
|
_rightMotionInput.Update(rightAccelerometer, rightGyroscope, (ulong)PerformanceCounter.ElapsedNanoseconds / 1000, controllerConfig.Motion.Sensitivity, (float)controllerConfig.Motion.GyroDeadzone);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_rightMotionInput = _leftMotionInput;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,6 +350,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
// Reset states
|
// Reset states
|
||||||
State = default;
|
State = default;
|
||||||
_leftMotionInput = null;
|
_leftMotionInput = null;
|
||||||
|
_rightMotionInput = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,5 +21,17 @@ namespace Ryujinx.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>Values are in degrees</remarks>
|
/// <remarks>Values are in degrees</remarks>
|
||||||
Gyroscope,
|
Gyroscope,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Second accelerometer.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Values are in m/s^2</remarks>
|
||||||
|
SecondAccelerometer,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Second gyroscope.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Values are in degrees</remarks>
|
||||||
|
SecondGyroscope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,14 +25,17 @@ namespace Ryujinx.SDL2.Common
|
|||||||
|
|
||||||
public static Action<Action> MainThreadDispatcher { get; set; }
|
public static Action<Action> MainThreadDispatcher { get; set; }
|
||||||
|
|
||||||
private const uint SdlInitFlags = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_VIDEO;
|
private const uint SdlInitFlags = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK |
|
||||||
|
SDL_INIT_AUDIO | SDL_INIT_VIDEO;
|
||||||
|
|
||||||
private bool _isRunning;
|
private bool _isRunning;
|
||||||
private uint _refereceCount;
|
private uint _refereceCount;
|
||||||
private Thread _worker;
|
private Thread _worker;
|
||||||
|
|
||||||
|
private const uint SDL_JOYBATTERYUPDATED = 1543;
|
||||||
public event Action<int, int> OnJoyStickConnected;
|
public event Action<int, int> OnJoyStickConnected;
|
||||||
public event Action<int> OnJoystickDisconnected;
|
public event Action<int> OnJoystickDisconnected;
|
||||||
|
public event Action<int, SDL_JoystickPowerLevel> OnJoyBatteryUpdated;
|
||||||
|
|
||||||
private ConcurrentDictionary<uint, Action<SDL_Event>> _registeredWindowHandlers;
|
private ConcurrentDictionary<uint, Action<SDL_Event>> _registeredWindowHandlers;
|
||||||
|
|
||||||
@@ -78,12 +81,14 @@ namespace Ryujinx.SDL2.Common
|
|||||||
// First ensure that we only enable joystick events (for connected/disconnected).
|
// First ensure that we only enable joystick events (for connected/disconnected).
|
||||||
if (SDL_GameControllerEventState(SDL_IGNORE) != SDL_IGNORE)
|
if (SDL_GameControllerEventState(SDL_IGNORE) != SDL_IGNORE)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.Application, "Couldn't change the state of game controller events.");
|
Logger.Error?.PrintMsg(LogClass.Application,
|
||||||
|
"Couldn't change the state of game controller events.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_JoystickEventState(SDL_ENABLE) < 0)
|
if (SDL_JoystickEventState(SDL_ENABLE) < 0)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.Application, $"Failed to enable joystick event polling: {SDL_GetError()}");
|
Logger.Error?.PrintMsg(LogClass.Application,
|
||||||
|
$"Failed to enable joystick event polling: {SDL_GetError()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable all joysticks information, we don't need them no need to flood the event queue for that.
|
// Disable all joysticks information, we don't need them no need to flood the event queue for that.
|
||||||
@@ -143,7 +148,12 @@ namespace Ryujinx.SDL2.Common
|
|||||||
|
|
||||||
OnJoystickDisconnected?.Invoke(evnt.cbutton.which);
|
OnJoystickDisconnected?.Invoke(evnt.cbutton.which);
|
||||||
}
|
}
|
||||||
else if (evnt.type is SDL_EventType.SDL_WINDOWEVENT or SDL_EventType.SDL_MOUSEBUTTONDOWN or SDL_EventType.SDL_MOUSEBUTTONUP)
|
else if ((uint)evnt.type == SDL_JOYBATTERYUPDATED)
|
||||||
|
{
|
||||||
|
OnJoyBatteryUpdated?.Invoke(evnt.cbutton.which, (SDL_JoystickPowerLevel)evnt.user.code);
|
||||||
|
}
|
||||||
|
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))
|
if (_registeredWindowHandlers.TryGetValue(evnt.window.windowID, out Action<SDL_Event> handler))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -464,7 +464,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Abrir Pasta de Capturas de Tela",
|
"pt_BR": "Abrir Pasta de Capturas de Tela",
|
||||||
"ru_RU": "Открыть папку со скриншотами",
|
"ru_RU": "Открыть папку со скриншотами",
|
||||||
"sv_SE": "",
|
"sv_SE": "Öppna skärmbildsmappen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Відкрити теку скріншотів",
|
"uk_UA": "Відкрити теку скріншотів",
|
||||||
@@ -1564,7 +1564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desenvolvido por {0}",
|
"pt_BR": "Desenvolvido por {0}",
|
||||||
"ru_RU": "Разработана {0}",
|
"ru_RU": "Разработана {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Utvecklat av {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Розроблено: {0}",
|
"uk_UA": "Розроблено: {0}",
|
||||||
@@ -1864,7 +1864,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Compatibilidade:",
|
"pt_BR": "Compatibilidade:",
|
||||||
"ru_RU": "Совместимость:",
|
"ru_RU": "Совместимость:",
|
||||||
"sv_SE": "",
|
"sv_SE": "Kompatibilitet:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Сумісність:",
|
"uk_UA": "Сумісність:",
|
||||||
@@ -1889,7 +1889,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "ID do Título:",
|
"pt_BR": "ID do Título:",
|
||||||
"ru_RU": "ID приложения",
|
"ru_RU": "ID приложения",
|
||||||
"sv_SE": "",
|
"sv_SE": "Titel-id:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "ID гри:",
|
"uk_UA": "ID гри:",
|
||||||
@@ -1914,7 +1914,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Jogos Hospedados: {0}",
|
"pt_BR": "Jogos Hospedados: {0}",
|
||||||
"ru_RU": "Запущенно игр: {0}",
|
"ru_RU": "Запущенно игр: {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Värdskap för spel: {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Розміщені ігри: {0}",
|
"uk_UA": "Розміщені ігри: {0}",
|
||||||
@@ -1939,7 +1939,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Jogadores Online: {0}",
|
"pt_BR": "Jogadores Online: {0}",
|
||||||
"ru_RU": "Игроков онлайн: {0}",
|
"ru_RU": "Игроков онлайн: {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Online-spelare: {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Гравців онлайн: {0}",
|
"uk_UA": "Гравців онлайн: {0}",
|
||||||
@@ -2289,7 +2289,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Limpar Cache PPTC",
|
"pt_BR": "Limpar Cache PPTC",
|
||||||
"ru_RU": "Очистить кэш PPTC",
|
"ru_RU": "Очистить кэш PPTC",
|
||||||
"sv_SE": "",
|
"sv_SE": "Rensa PPTC-cache",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Очистити кеш PPTC",
|
"uk_UA": "Очистити кеш PPTC",
|
||||||
@@ -2314,7 +2314,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
|
"pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
|
||||||
"ru_RU": "Удаляет все файлы кэша PPTC для приложения",
|
"ru_RU": "Удаляет все файлы кэша PPTC для приложения",
|
||||||
"sv_SE": "",
|
"sv_SE": "Tar bort alla PPTC-cachefiler för applikationen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
|
"uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
|
||||||
@@ -2763,7 +2763,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Создать пользовательскую конфигурацию",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -2788,7 +2788,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Изменить пользовательскую конфигурацию",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -2863,7 +2863,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Отредактировать существующую независимую конфигурацию для выбранной игры.",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -2889,7 +2889,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Dados de Compatibilidade",
|
"pt_BR": "Mostrar Dados de Compatibilidade",
|
||||||
"ru_RU": "Показать записи о совместимости",
|
"ru_RU": "Показать записи о совместимости",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa kompatibilitetspost",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Iнформація про сумісність",
|
"uk_UA": "Iнформація про сумісність",
|
||||||
@@ -2914,7 +2914,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
|
"pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
|
||||||
"ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
|
"ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa valt spel i kompatibilitetslistan som du normalt sett kan komma åt via hjälpmenyn.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
|
"uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
|
||||||
@@ -2939,7 +2939,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Informações do Jogo",
|
"pt_BR": "Mostrar Informações do Jogo",
|
||||||
"ru_RU": "Показать информацию об игре",
|
"ru_RU": "Показать информацию об игре",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa spelinformation",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Інформація про гру",
|
"uk_UA": "Інформація про гру",
|
||||||
@@ -2964,7 +2964,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Exibe estatísticas e detalhes sobre o jogo selecionado.",
|
"pt_BR": "Exibe estatísticas e detalhes sobre o jogo selecionado.",
|
||||||
"ru_RU": "Показывать статистику и подробную информацию о выбранной игре.",
|
"ru_RU": "Показывать статистику и подробную информацию о выбранной игре.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa statistik och detaljer om det aktuella spelet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показати статистику та деталі обраної гри.",
|
"uk_UA": "Показати статистику та деталі обраної гри.",
|
||||||
@@ -3514,7 +3514,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Verificar Atualizações:",
|
"pt_BR": "Verificar Atualizações:",
|
||||||
"ru_RU": "Проверка наличия обновлений",
|
"ru_RU": "Проверка наличия обновлений",
|
||||||
"sv_SE": "",
|
"sv_SE": "Leta efter uppdateringar:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Перевірка оновлень:",
|
"uk_UA": "Перевірка оновлень:",
|
||||||
@@ -3539,7 +3539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desligado",
|
"pt_BR": "Desligado",
|
||||||
"ru_RU": "Отключить",
|
"ru_RU": "Отключить",
|
||||||
"sv_SE": "",
|
"sv_SE": "Av",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Вимкнути",
|
"uk_UA": "Вимкнути",
|
||||||
@@ -3564,7 +3564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ao Abrir",
|
"pt_BR": "Ao Abrir",
|
||||||
"ru_RU": "При запуске",
|
"ru_RU": "При запуске",
|
||||||
"sv_SE": "",
|
"sv_SE": "Fråga",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запитувати щоразу",
|
"uk_UA": "Запитувати щоразу",
|
||||||
@@ -3589,7 +3589,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "2° Plano",
|
"pt_BR": "2° Plano",
|
||||||
"ru_RU": "В фоне",
|
"ru_RU": "В фоне",
|
||||||
"sv_SE": "",
|
"sv_SE": "Bakgrund",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Оновлювати в фоні",
|
"uk_UA": "Оновлювати в фоні",
|
||||||
@@ -3614,7 +3614,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ao Perder o Foco:",
|
"pt_BR": "Ao Perder o Foco:",
|
||||||
"ru_RU": "При выходе эмулятора из фокуса",
|
"ru_RU": "При выходе эмулятора из фокуса",
|
||||||
"sv_SE": "",
|
"sv_SE": "När emulatorn tappar fokus:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "При втраті фокуса емулятором:",
|
"uk_UA": "При втраті фокуса емулятором:",
|
||||||
@@ -3639,7 +3639,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Não Fazer Nada",
|
"pt_BR": "Não Fazer Nada",
|
||||||
"ru_RU": "Ничего не делать",
|
"ru_RU": "Ничего не делать",
|
||||||
"sv_SE": "",
|
"sv_SE": "Gör ingenting",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Нічого не робити",
|
"uk_UA": "Нічого не робити",
|
||||||
@@ -3664,7 +3664,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Bloquear Controles",
|
"pt_BR": "Bloquear Controles",
|
||||||
"ru_RU": "Блокировать управление",
|
"ru_RU": "Блокировать управление",
|
||||||
"sv_SE": "",
|
"sv_SE": "Blockera inmatning",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Блокувати введення",
|
"uk_UA": "Блокувати введення",
|
||||||
@@ -3689,7 +3689,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ficar Mudo",
|
"pt_BR": "Ficar Mudo",
|
||||||
"ru_RU": "Отключить звук",
|
"ru_RU": "Отключить звук",
|
||||||
"sv_SE": "",
|
"sv_SE": "Stäng av ljudet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Вимкнути звук",
|
"uk_UA": "Вимкнути звук",
|
||||||
@@ -3714,7 +3714,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Bloquear Controles & Ficar Mudo",
|
"pt_BR": "Bloquear Controles & Ficar Mudo",
|
||||||
"ru_RU": "Блокировать управление и отключить звук",
|
"ru_RU": "Блокировать управление и отключить звук",
|
||||||
"sv_SE": "",
|
"sv_SE": "Blockera inmatningar och stäng av ljudet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Блокувати введення та Вимкнути звук",
|
"uk_UA": "Блокувати введення та Вимкнути звук",
|
||||||
@@ -3739,7 +3739,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Pausar a Emulação",
|
"pt_BR": "Pausar a Emulação",
|
||||||
"ru_RU": "Поставить паузу",
|
"ru_RU": "Поставить паузу",
|
||||||
"sv_SE": "",
|
"sv_SE": "Pausa emuleringen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Поставити на паузу",
|
"uk_UA": "Поставити на паузу",
|
||||||
@@ -3814,7 +3814,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
|
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
|
||||||
"ru_RU": "Отключает управление при выходе из фокуса",
|
"ru_RU": "Отключает управление при выходе из фокуса",
|
||||||
"sv_SE": "",
|
"sv_SE": "Inaktivera inmatning när fokus tappas",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -4839,7 +4839,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Sincronizar com o Sistema PC",
|
"pt_BR": "Sincronizar com o Sistema PC",
|
||||||
"ru_RU": "Соответствовать времени в системе",
|
"ru_RU": "Соответствовать времени в системе",
|
||||||
"sv_SE": "",
|
"sv_SE": "Matcha systemtid",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -5013,7 +5013,7 @@
|
|||||||
"no_NO": "Lyd Inn/Ut",
|
"no_NO": "Lyd Inn/Ut",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Выход/Вход звука",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -5264,7 +5264,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ignorar Applet do Controlador",
|
"pt_BR": "Ignorar Applet do Controlador",
|
||||||
"ru_RU": "Игнорировать апплет контроллера",
|
"ru_RU": "Игнорировать апплет контроллера",
|
||||||
"sv_SE": "",
|
"sv_SE": "Ignorera kontroller-applet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ігнорувати Аплет Контролера",
|
"uk_UA": "Ігнорувати Аплет Контролера",
|
||||||
@@ -6114,7 +6114,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Habilitar Logs da IU",
|
"pt_BR": "Habilitar Logs da IU",
|
||||||
"ru_RU": "Включить журнал интерфейса",
|
"ru_RU": "Включить журнал интерфейса",
|
||||||
"sv_SE": "",
|
"sv_SE": "Aktivera gränssnittsloggar",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Увімкнути журнали інтерфейсу",
|
"uk_UA": "Увімкнути журнали інтерфейсу",
|
||||||
@@ -6514,7 +6514,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Redefinir Configurações",
|
"pt_BR": "Redefinir Configurações",
|
||||||
"ru_RU": "Сбросить настройки",
|
"ru_RU": "Сбросить настройки",
|
||||||
"sv_SE": "",
|
"sv_SE": "Nollställ inställningar",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Скинути налаштування",
|
"uk_UA": "Скинути налаштування",
|
||||||
@@ -6539,7 +6539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Quero redefinir minhas configurações.",
|
"pt_BR": "Quero redefinir minhas configurações.",
|
||||||
"ru_RU": "Я хочу сбросить свои настройки.",
|
"ru_RU": "Я хочу сбросить свои настройки.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Jag vill nollställa mina inställningar.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Я хочу скинути налаштування.",
|
"uk_UA": "Я хочу скинути налаштування.",
|
||||||
@@ -6563,7 +6563,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Ок",
|
||||||
"sv_SE": "Ok",
|
"sv_SE": "Ok",
|
||||||
"th_TH": "ตกลง",
|
"th_TH": "ตกลง",
|
||||||
"tr_TR": "Tamam",
|
"tr_TR": "Tamam",
|
||||||
@@ -7013,7 +7013,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "Pro Kontroler",
|
"pl_PL": "Pro Kontroler",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Pro контроллер",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "โปรคอนโทรลเลอร์",
|
"th_TH": "โปรคอนโทรลเลอร์",
|
||||||
"tr_TR": "Profesyonel Kumanda",
|
"tr_TR": "Profesyonel Kumanda",
|
||||||
@@ -8514,7 +8514,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Velocidade do Arco-íris",
|
"pt_BR": "Velocidade do Arco-íris",
|
||||||
"ru_RU": "Скорость переливания",
|
"ru_RU": "Скорость переливания",
|
||||||
"sv_SE": "",
|
"sv_SE": "Regnbågshastighet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -13814,7 +13814,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
|
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
|
||||||
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
|
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
|
||||||
"sv_SE": "",
|
"sv_SE": "Du är på väg att ta bort allt PPTC-data från:\n\n{0}\n\nÄr du säker på att du vill fortsätta?",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
|
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
|
||||||
@@ -16664,7 +16664,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
|
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
|
||||||
"ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
|
"ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Handkontroller-appleten kommer inte att visas om gamepaden är frånkopplad under tiden en applikation körs.\n\nLämna AV om du är osäker.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
|
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
|
||||||
@@ -17139,7 +17139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
|
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
|
||||||
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
|
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Skriver ut loggmeddelanden från Avalonia (användargränssnittet) i konsollen.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
|
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
|
||||||
@@ -17339,7 +17339,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Abre a pasta de capturas de tela do Ryujinx",
|
"pt_BR": "Abre a pasta de capturas de tela do Ryujinx",
|
||||||
"ru_RU": "Открывает папку скриншотов Ryujinx",
|
"ru_RU": "Открывает папку скриншотов Ryujinx",
|
||||||
"sv_SE": "",
|
"sv_SE": "Öppna Ryujinx skärmbildsmapp",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Відкрити теку куди зберігаються скріншоти Ryujinx",
|
"uk_UA": "Відкрити теку куди зберігаються скріншоти Ryujinx",
|
||||||
@@ -18089,7 +18089,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Atualização Disponível!",
|
"pt_BR": "Atualização Disponível!",
|
||||||
"ru_RU": "Доступно обновление!",
|
"ru_RU": "Доступно обновление!",
|
||||||
"sv_SE": "",
|
"sv_SE": "Uppdatering finns tillgänglig!",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Доступне оновлення!",
|
"uk_UA": "Доступне оновлення!",
|
||||||
@@ -20013,7 +20013,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Амибо",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -24064,7 +24064,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
|
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
|
||||||
"ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
|
"ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp och spelas utan några krascher eller GPU-fel av några slag och med en hastighet som är snabb nog för bra upplevelse på en genomsnittlig PC.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
|
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
|
||||||
@@ -24089,7 +24089,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
|
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
|
||||||
"ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
|
"ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar och går in i spelet men lider av ett eller flera av följande: kraschar, deadlocks, GPU-buggar, distraherande dåligt ljud eller är helt enkelt för långsamt. Spelet kan fortfarande spelas hela vägen igenom, men inte så som spelet är avsett att spelas.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.",
|
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.",
|
||||||
@@ -24114,7 +24114,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
|
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
|
||||||
"ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
|
"ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp och går förbi titelskärmen men tar sig inte in i huvudspelet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.",
|
"uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.",
|
||||||
@@ -24139,7 +24139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inizializa, mas não passa da tela de título.",
|
"pt_BR": "Inizializa, mas não passa da tela de título.",
|
||||||
"ru_RU": "Загружается, но не проходит дальше титульного экрана.",
|
"ru_RU": "Загружается, но не проходит дальше титульного экрана.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp men tar sig inte förbi titelskärmen.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
|
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
|
||||||
@@ -24164,7 +24164,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
|
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
|
||||||
"ru_RU": "Не запускается или не подаёт признаков жизни.",
|
"ru_RU": "Не запускается или не подаёт признаков жизни.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar inte upp eller visar någon form av aktivitet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Взагалі не запускається.",
|
"uk_UA": "Взагалі не запускається.",
|
||||||
@@ -24264,7 +24264,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Imagem da Presença do Discord",
|
"pt_BR": "Imagem da Presença do Discord",
|
||||||
"ru_RU": "Изображение для статуса активности",
|
"ru_RU": "Изображение для статуса активности",
|
||||||
"sv_SE": "",
|
"sv_SE": "Bild för Rich Presence",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Зображення картки активності Discord",
|
"uk_UA": "Зображення картки активності Discord",
|
||||||
@@ -24289,7 +24289,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Presença Dinâmica do Discord",
|
"pt_BR": "Presença Dinâmica do Discord",
|
||||||
"ru_RU": "Динамический статус активности",
|
"ru_RU": "Динамический статус активности",
|
||||||
"sv_SE": "",
|
"sv_SE": "Dynamisk Rich Presence",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Динамічна картка активності Discord",
|
"uk_UA": "Динамічна картка активності Discord",
|
||||||
|
|||||||
@@ -158,16 +158,6 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool FindGameConfig(string gameDir)
|
|
||||||
{
|
|
||||||
if (File.Exists(gameDir))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(gameId))
|
if (string.IsNullOrEmpty(gameId))
|
||||||
|
|||||||
@@ -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 _parent.SettingsWindow.ShowDialog(window);
|
await StyleableAppWindow.ShowAsync(_parent.SettingsWindow, window);
|
||||||
|
|
||||||
_parent.SettingsWindow = null;
|
_parent.SettingsWindow = null;
|
||||||
|
|
||||||
|
|||||||
@@ -91,11 +91,14 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
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 new CheatWindow(
|
await StyleableAppWindow.ShowAsync(
|
||||||
viewModel.VirtualFileSystem,
|
new CheatWindow(
|
||||||
viewModel.SelectedApplication.IdString,
|
viewModel.VirtualFileSystem,
|
||||||
viewModel.SelectedApplication.Name,
|
viewModel.SelectedApplication.IdString,
|
||||||
viewModel.SelectedApplication.Path).ShowDialog((Window)viewModel.TopLevel);
|
viewModel.SelectedApplication.Name,
|
||||||
|
viewModel.SelectedApplication.Path
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
||||||
@@ -391,9 +394,9 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
{
|
{
|
||||||
await new GameSpecificSettingsWindow(viewModel).ShowDialog((Window)viewModel.TopLevel);
|
await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel));
|
||||||
|
|
||||||
//just checking for file presence
|
// just checking for file presence
|
||||||
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
||||||
|
|
||||||
viewModel.RefreshView();
|
viewModel.RefreshView();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
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.Threading;
|
using Avalonia.Threading;
|
||||||
@@ -384,6 +385,10 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -1747,7 +1747,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 window.ShowDialog(Window);
|
await StyleableAppWindow.ShowAsync(window);
|
||||||
|
|
||||||
if (window.IsScanned)
|
if (window.IsScanned)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using Ryujinx.Common.Utilities;
|
|||||||
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
|
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -133,20 +134,20 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
|
|
||||||
if (ViewModel.SelectedApplication is null) // Checks if game data exists
|
if (ViewModel.SelectedApplication is null) // Checks if game data exists
|
||||||
{
|
{
|
||||||
await Window.SettingsWindow.ShowDialog(Window);
|
await StyleableAppWindow.ShowAsync(Window.SettingsWindow);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool userConfigExist = Program.FindGameConfig(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString, false, false));
|
bool customConfigExists = File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString));
|
||||||
|
|
||||||
if (!ViewModel.IsGameRunning || !userConfigExist)
|
if (!ViewModel.IsGameRunning || !customConfigExists)
|
||||||
{
|
{
|
||||||
await Window.SettingsWindow.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
await Window.SettingsWindow.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If there is a custom configuration in the folder
|
// If there is a custom configuration in the folder
|
||||||
await new GameSpecificSettingsWindow(ViewModel, userConfigExist).ShowDialog((Window)ViewModel.TopLevel);
|
await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(ViewModel, customConfigExists));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,11 +176,13 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
|
|
||||||
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
|
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
|
||||||
|
|
||||||
await new CheatWindow(
|
await StyleableAppWindow.ShowAsync(
|
||||||
Window.VirtualFileSystem,
|
new CheatWindow(
|
||||||
ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
|
Window.VirtualFileSystem,
|
||||||
name,
|
ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
|
||||||
ViewModel.SelectedApplication.Path).ShowDialog(Window);
|
name,
|
||||||
|
ViewModel.SelectedApplication.Path)
|
||||||
|
);
|
||||||
|
|
||||||
ViewModel.AppHost.Device.EnableCheats();
|
ViewModel.AppHost.Device.EnableCheats();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||||
Width="1100"
|
Width="1100"
|
||||||
Height="768"
|
Height="910"
|
||||||
MinWidth="800"
|
MinWidth="800"
|
||||||
MinHeight="480"
|
MinHeight="480"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
|
|||||||
@@ -47,11 +47,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Load();
|
Load();
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveSettings()
|
public void SaveSettings()
|
||||||
@@ -65,7 +60,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
Pages.Children.Clear();
|
Pages.Children.Clear();
|
||||||
NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
|
NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
|
||||||
NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
|
NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
|
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||||
Width="1100"
|
Width="1100"
|
||||||
Height="768"
|
Height="918"
|
||||||
MinWidth="800"
|
MinWidth="800"
|
||||||
MinHeight="480"
|
MinHeight="480"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
@@ -8,7 +6,6 @@ using Ryujinx.HLE.FileSystem;
|
|||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Key = Avalonia.Input.Key;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Windows
|
||||||
{
|
{
|
||||||
@@ -27,10 +24,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Load();
|
Load();
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsWindow()
|
public SettingsWindow()
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Windows
|
||||||
{
|
{
|
||||||
public abstract class StyleableAppWindow : AppWindow
|
public abstract class StyleableAppWindow : AppWindow
|
||||||
{
|
{
|
||||||
|
public static async Task ShowAsync(StyleableAppWindow appWindow, Window owner = null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
appWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||||
|
#endif
|
||||||
|
await appWindow.ShowDialog(owner ?? RyujinxApp.MainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
protected StyleableAppWindow()
|
protected StyleableAppWindow()
|
||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||||
@@ -36,6 +47,14 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
public abstract class StyleableWindow : Window
|
public abstract class StyleableWindow : Window
|
||||||
{
|
{
|
||||||
|
public static async Task ShowAsync(StyleableWindow window, Window owner = null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
window.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||||
|
#endif
|
||||||
|
await window.ShowDialog(owner ?? RyujinxApp.MainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
protected StyleableWindow()
|
protected StyleableWindow()
|
||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||||
|
|||||||
Reference in New Issue
Block a user