bug fixes + missing feats from !125 (#149)

addresses two crashes (https://github.com/Ryubing/Issues/issues/455 and another one pointed out over on discord),
code cleanup,
various fixes and improvements :
- fix assigned devices menu player display section being too large when under 4 players were selected
- fix 'profile : ...' shifting around in the UI when enabling / disabling the checkbox
- update the Dynamic Input Swap warning message to show which device is assigned to which player
- make players that have Dynamic Input Swap disabled show up in the Device assignement menu.

Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/149
This commit is contained in:
Babib3l
2026-06-29 04:00:30 +00:00
committed by sh0inx
parent 45c66eaf66
commit 8b7d27a071
5 changed files with 69 additions and 47 deletions

View File

@@ -6206,9 +6206,9 @@
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "You can assign devices to specific players by clicking the gear icon next to each input device.",
"es_ES": "Puedes asignar dispositivos a jugadores específicos haciendo clic en el icono de engranaje junto a cada dispositivo de entrada.",
"fr_FR": "Vous pouvez assigner des périphériques à des joueurs spécifiques en cliquant sur l'icône d'engrenage à côté de chaque périphérique d'entrée.",
"en_US": "All currently connected input devices have been assigned to the following Players:\n\n{0}\n\nYou can assign devices to specific players by clicking the gear icon next to each input device.",
"es_ES": "Todos los dispositivos de entrada conectados actualmente se han asignado a los siguientes jugadores:\n\n{0}\n\nPuedes asignar dispositivos a jugadores específicos haciendo clic en el icono de engranaje junto a cada dispositivo de entrada.",
"fr_FR": "Tous les périphériques d'entrée actuellement connectés ont été assignés aux joueurs suivants :\n\n{0}\n\nVous pouvez assigner des périphériques à des joueurs spécifiques en cliquant sur l'icône d'engrenage à côté de chaque périphérique d'entrée.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",

View File

@@ -417,8 +417,8 @@ namespace Ryujinx.Input.HLE
bool motionWasDisabled = oldConfig?.Motion == null;
bool leftMotionMissing = _leftMotionInput == null;
bool isJoyconPairNeedingRightMotion = newConfig.ControllerType == ConfigControllerType.JoyconPair && _rightMotionInput == null;
bool motionEnabledChanged = oldConfig.Motion.EnableMotion != newConfig.Motion.EnableMotion;
bool motionBackendChanged = oldConfig.Motion.MotionBackend != newConfig.Motion.MotionBackend;
bool motionEnabledChanged = !motionWasDisabled && oldConfig?.Motion?.EnableMotion != newConfig.Motion.EnableMotion;
bool motionBackendChanged = !motionWasDisabled && oldConfig?.Motion?.MotionBackend != newConfig.Motion.MotionBackend;
return motionWasDisabled ||
leftMotionMissing ||
@@ -769,7 +769,7 @@ namespace Ryujinx.Input.HLE
{
foreach (string gamepadId in gamepadDriver.GamepadsIds)
{
if (gamepadId == assignedController.Id)
if (string.Equals(gamepadId, assignedController.Id, StringComparison.Ordinal))
{
yield return assignedController;
break;
@@ -784,7 +784,7 @@ namespace Ryujinx.Input.HLE
{
foreach (string gamepadId in gamepadDriver.GamepadsIds)
{
if (gamepadId == config.Id)
if (string.Equals(gamepadId, config.Id, StringComparison.Ordinal))
{
yield return new AssignedInputDevice
{

View File

@@ -109,6 +109,11 @@ namespace Ryujinx.Input.HLE
private void HandleOnGamepadConnected(string id)
{
List<InputConfig> requestedInputConfig;
List<PlayerInputAssignment> playerInputAssignments;
bool enableKeyboard;
bool enableMouse;
lock (_lock)
{
for (int i = 0; i < _controllers.Length; i++)
@@ -119,10 +124,15 @@ namespace Ryujinx.Input.HLE
_controllers[i] = null;
}
}
requestedInputConfig = _requestedInputConfig;
playerInputAssignments = _playerInputAssignments;
enableKeyboard = _enableKeyboard;
enableMouse = _enableMouse;
}
// Force input reload
ReloadConfiguration(_requestedInputConfig, _playerInputAssignments, _enableKeyboard, _enableMouse);
ReloadConfiguration(requestedInputConfig, playerInputAssignments, enableKeyboard, enableMouse);
}
private bool PlayerHasAssignedControllerId(PlayerIndex playerIndex, string id)

View File

@@ -207,7 +207,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private async void ShowDynamicInputSwapFirstUseWarning()
{
string message = LocaleManager.Instance[LocaleKeys.DialogDynamicInputSwapDeviceAssignmentsHint];
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.DialogDynamicInputSwapDeviceAssignmentsHint,
BuildDynamicInputSwapFirstUseAssignmentSummary());
CheckBoxDialogResult result = await ContentDialogHelper.CreateCheckBoxDialog(
LocaleManager.Instance[LocaleKeys.ControllerSettingsAssignedInputDevices],
@@ -221,6 +223,15 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
}
private string BuildDynamicInputSwapFirstUseAssignmentSummary()
{
return string.Join(
Environment.NewLine,
PlayerInputDevices
.Where(device => device.HasAssignedToPlayers)
.Select(device => $"{device.Name} - {device.AssignedToPlayers}"));
}
public bool AllowDuplicateDeviceAssignment
{
get => _allowDuplicateDeviceAssignment ?? GetSavedAllowDuplicateDeviceAssignment();
@@ -853,15 +864,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
PlayerInputAssignment normalizedOtherAssignment = GetWorkingPlayerInputAssignment(otherPlayer);
// Only include players who participate in dynamic input swap.
// Players with dynamic swap disabled manage their device through
// the traditional InputConfig and should not appear in the
// Assigned Devices menu for other players.
if (!normalizedOtherAssignment.EnableDynamicInputSwap)
{
continue;
}
string playerName = GetPlayerDisplayName(otherPlayer);
foreach (AssignedInputDevice device in normalizedOtherAssignment.Devices)
@@ -940,11 +942,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
string currentPlayerName = GetPlayerDisplayName(_playerId);
if (!AllowDuplicateDeviceAssignment)
{
return currentPlayerName;
}
return assignedOtherPlayers != null && assignedOtherPlayers.Count > 0
? $"{currentPlayerName}, {string.Join(", ", assignedOtherPlayers.OrderBy(name => ExtractPlayerNumber(name)))}"
: currentPlayerName;

View File

@@ -19,59 +19,74 @@
BorderThickness="1"
CornerRadius="5"
HorizontalAlignment="Stretch">
<ItemsControl
ItemsSource="{Binding PlayerInputDevices}">
<ItemsControl ItemsSource="{Binding PlayerInputDevices}">
<ItemsControl.Styles>
<Style Selector="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ItemsControl.Styles>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="models:PlayerInputDeviceAssignmentItem">
<Border
Margin="0,3"
Padding="10,8"
CornerRadius="4"
HorizontalAlignment="Stretch"
Background="{DynamicResource ControlFillColorTertiary}"
BorderBrush="{DynamicResource ThemeControlBorderColor}"
BorderThickness="1"
PointerPressed="DeviceRow_OnPointerPressed"
Cursor="Hand"
IsEnabled="{Binding !IsDisabledByOtherPlayer}">
<Grid ColumnDefinitions="Auto,*,200">
<DockPanel
HorizontalAlignment="Stretch"
LastChildFill="True">
<CheckBox
Grid.Column="0"
DockPanel.Dock="Left"
Margin="0,0,8,0"
Padding="0"
VerticalAlignment="Center"
ClipToBounds="False"
IsChecked="{Binding IsAssigned}"
Checked="AssignedDeviceCheckBox_OnCheckedChanged"
Unchecked="AssignedDeviceCheckBox_OnCheckedChanged"
Unchecked="AssignedDeviceCheckBox_OnCheckedChanged" />
<TextBlock
DockPanel.Dock="Right"
Margin="10,0,0,0"
Opacity="0.6"
FontSize="12"
MaxWidth="200"
VerticalAlignment="Center"
Margin="0"
Padding="0" />
HorizontalAlignment="Right"
TextWrapping="Wrap"
Text="{Binding AssignedToPlayers}"
IsVisible="{Binding HasAssignedToPlayers}" />
<StackPanel
Grid.Column="1"
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" />
<TextBlock
HorizontalAlignment="Left"
Text="{Binding Name}" />
<TextBlock
HorizontalAlignment="Left"
Opacity="0.6"
FontSize="12"
MaxWidth="160"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"
MaxLines="1"
IsVisible="{Binding HasBoundProfileName}">
<Run Text="{ext:Locale ControllerSettingsProfile}" />
<Run Text=":" />
<Run Text=": " />
<Run Text="{Binding BoundProfileName}" />
</TextBlock>
</StackPanel>
<TextBlock
Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="10,0,0,0"
Opacity="0.6"
FontSize="12"
Text="{Binding AssignedToPlayers}"
TextWrapping="Wrap"
MaxWidth="200"
IsVisible="{Binding HasAssignedToPlayers}" />
</Grid>
</DockPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>