Compare commits

...

8 Commits

Author SHA1 Message Date
Evan Husted
359852b5c0 UI: Change order of VSync mode changing
VSync -> VSync Off -> Custom
is now
VSync -> Custom -> VSync Off

Note that Custom only appears if it's enabled in settings. This has no change if you aren't using custom VSync.
2025-01-30 16:47:40 -06:00
Evan Husted
796674d9cf UI: Allow more freedom changing the Speed value & clamp the visible number to a sane amount of trailing digits 2025-01-30 03:30:50 -06:00
Evan Husted
4efe24a3bc misc: chore: [ci skip] forgot to make that a locale entry 2025-01-30 03:21:42 -06:00
Evan Husted
1a42d1396c UI: Rainbow cycling speed settings
Note: this setting is global, even though it appears in the settings for the individual gamepad. This is simply for consistency; you access all the rainbow stuff in one place.
2025-01-30 03:18:34 -06:00
Evan Husted
11f29361eb misc: chore: [ci skip] Log errors from TaskScheduler.UnobservedTaskException 2025-01-29 21:07:43 -06:00
Evan Husted
71d8cfd232 misc: chore: Pass rainbow color by reference in the event instead of passing around a packed int. 2025-01-29 20:51:55 -06:00
Evan Husted
023bd5f00f UI: Enable Rainbow cycling in the Settings window 2025-01-29 20:27:01 -06:00
Evan Husted
0ed7fd14ba misc: chore: [ci skip] Collapse CheckboxMenuItemStyle into the main Styles.xaml. 2025-01-29 18:59:17 -06:00
21 changed files with 197 additions and 66 deletions

View File

@@ -0,0 +1,58 @@
using Gommon;
using System.Collections.Generic;
using System.Threading;
namespace Ryujinx.Common.Helper
{
public class RefEvent<T>
{
public delegate void Handler(ref T arg);
private readonly Lock _subLock = new();
private readonly List<Handler> _subscriptions = [];
public bool HasSubscribers
{
get
{
lock (_subLock)
return _subscriptions.Count != 0;
}
}
public IReadOnlyList<Handler> Subscriptions
{
get
{
lock (_subLock)
return _subscriptions;
}
}
public void Add(Handler subscriber)
{
Guard.Require(subscriber, nameof(subscriber));
lock (_subLock)
_subscriptions.Add(subscriber);
}
public void Remove(Handler subscriber)
{
Guard.Require(subscriber, nameof(subscriber));
lock (_subLock)
_subscriptions.Remove(subscriber);
}
public void Clear()
{
lock (_subLock)
_subscriptions.Clear();
}
public void Call(ref T arg)
{
foreach (Handler subscription in Subscriptions)
subscription(ref arg);
}
}
}

View File

@@ -1,4 +1,5 @@
using Gommon; using Gommon;
using Ryujinx.Common.Helper;
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading; using System.Threading;
@@ -55,7 +56,7 @@ namespace Ryujinx.Common.Utilities
{ {
_color = HsbToRgb((_color.GetHue() + Speed) / 360); _color = HsbToRgb((_color.GetHue() + Speed) / 360);
_updatedHandler.Call(_color.ToArgb()); _updatedHandler.Call(ref _color);
} }
} }
@@ -67,13 +68,13 @@ namespace Ryujinx.Common.Utilities
_color = Color.Blue; _color = Color.Blue;
} }
public static event Action<int> Updated public static event RefEvent<Color>.Handler Updated
{ {
add => _updatedHandler.Add(value); add => _updatedHandler.Add(value);
remove => _updatedHandler.Remove(value); remove => _updatedHandler.Remove(value);
} }
private static readonly Event<int> _updatedHandler = new(); private static readonly RefEvent<Color> _updatedHandler = new();
private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1) private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1)
{ {

View File

@@ -2,8 +2,6 @@ using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS.Services.Hid;
using SDL2;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
@@ -12,7 +10,7 @@ using static SDL2.SDL;
namespace Ryujinx.Input.SDL2 namespace Ryujinx.Input.SDL2
{ {
class SDL2Gamepad : IGamepad public class SDL2Gamepad : IGamepad
{ {
private bool HasConfiguration => _configuration != null; private bool HasConfiguration => _configuration != null;
@@ -113,7 +111,7 @@ namespace Ryujinx.Input.SDL2
byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0; byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0;
if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0) if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0)
Logger.Error?.Print(LogClass.Hid, "LED is not supported on this game controller."); Logger.Error?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
} }
private GamepadFeaturesFlag GetFeaturesFlag() private GamepadFeaturesFlag GetFeaturesFlag()

View File

@@ -325,21 +325,15 @@ namespace Ryujinx.Ava
switch (oldVSyncMode) switch (oldVSyncMode)
{ {
case VSyncMode.Switch: case VSyncMode.Switch:
newVSyncMode = VSyncMode.Unbounded; newVSyncMode = customVSyncIntervalEnabled
? VSyncMode.Custom
: VSyncMode.Unbounded;
break; break;
case VSyncMode.Unbounded: case VSyncMode.Unbounded:
if (customVSyncIntervalEnabled)
{
newVSyncMode = VSyncMode.Custom;
}
else
{
newVSyncMode = VSyncMode.Switch; newVSyncMode = VSyncMode.Switch;
}
break; break;
case VSyncMode.Custom: case VSyncMode.Custom:
newVSyncMode = VSyncMode.Switch; newVSyncMode = VSyncMode.Unbounded;
break; break;
} }

View File

@@ -1,13 +0,0 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style Selector="MenuItem.withCheckbox Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="MenuItem.withCheckbox ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</Styles>

View File

@@ -218,6 +218,15 @@
<Setter Property="BorderBrush" <Setter Property="BorderBrush"
Value="{DynamicResource ThemeControlBorderColor}" /> Value="{DynamicResource ThemeControlBorderColor}" />
</Style> </Style>
<Style Selector="MenuItem.withCheckbox Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="MenuItem.withCheckbox ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
<Style Selector="TabItem > ScrollViewer"> <Style Selector="TabItem > ScrollViewer">
<Setter Property="Background" <Setter Property="Background"
Value="{DynamicResource ThemeBackgroundColor}" /> Value="{DynamicResource ThemeBackgroundColor}" />

View File

@@ -7747,6 +7747,31 @@
"zh_TW": "" "zh_TW": ""
} }
}, },
{
"ID": "ControllerSettingsLedColorRainbowSpeed",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Rainbow Speed",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{ {
"ID": "ControllerSettingsLedColor", "ID": "ControllerSettingsLedColor",
"Translations": { "Translations": {

View File

@@ -112,7 +112,11 @@ namespace Ryujinx.Ava
// Hook unhandled exception and process exit events. // Hook unhandled exception and process exit events.
AppDomain.CurrentDomain.UnhandledException += (sender, e) AppDomain.CurrentDomain.UnhandledException += (sender, e)
=> ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating); => ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
TaskScheduler.UnobservedTaskException += (sender, e)
=> ProcessUnhandledException(sender, e.Exception, false);
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit(); AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
// Setup base data directory. // Setup base data directory.
AppDataManager.Initialize(CommandLineState.BaseDirPathArg); AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
@@ -282,9 +286,7 @@ namespace Ryujinx.Ava
log.PrintMsg(LogClass.Application, message); log.PrintMsg(LogClass.Application, message);
} }
if (isTerminating) if (isTerminating)
Exit(); Exit();
} }

View File

@@ -123,13 +123,11 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</AvaloniaResource> </AvaloniaResource>
<AvaloniaResource Include="Assets\Styles\Styles.xaml" /> <AvaloniaResource Include="Assets\Styles\Styles.xaml" />
<AvaloniaResource Include="Assets\Styles\CheckboxMenuItemStyle.axaml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Assets\locales.json" /> <None Remove="Assets\locales.json" />
<None Remove="Assets\Styles\Themes.xaml" /> <None Remove="Assets\Styles\Themes.xaml" />
<None Remove="Assets\Styles\CheckboxMenuItemStyle.xaml" />
<None Remove="Assets\Icons\Controller_JoyConLeft.svg" /> <None Remove="Assets\Icons\Controller_JoyConLeft.svg" />
<None Remove="Assets\Icons\Controller_JoyConPair.svg" /> <None Remove="Assets\Icons\Controller_JoyConPair.svg" />
<None Remove="Assets\Icons\Controller_JoyConRight.svg" /> <None Remove="Assets\Icons\Controller_JoyConRight.svg" />
@@ -151,7 +149,6 @@
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Assets\locales.json" /> <EmbeddedResource Include="Assets\locales.json" />
<EmbeddedResource Include="Assets\Styles\Styles.xaml" /> <EmbeddedResource Include="Assets\Styles\Styles.xaml" />
<EmbeddedResource Include="Assets\Styles\CheckboxMenuItemStyle.axaml" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />

View File

@@ -16,6 +16,5 @@
<Application.Styles> <Application.Styles>
<sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" /> <sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
<StyleInclude Source="/Assets/Styles/Styles.xaml" /> <StyleInclude Source="/Assets/Styles/Styles.xaml" />
<StyleInclude Source="/Assets/Styles/CheckboxMenuItemStyle.axaml"/>
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -1,11 +1,10 @@
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Views.Input; using Ryujinx.Ava.UI.Views.Input;
using Ryujinx.Common.Utilities;
using Ryujinx.UI.Views.Input; using Ryujinx.UI.Views.Input;
using System.Drawing;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
@@ -48,6 +47,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
ParentModel = model; ParentModel = model;
model.NotifyChangesEvent += OnParentModelChanged; model.NotifyChangesEvent += OnParentModelChanged;
OnParentModelChanged(); OnParentModelChanged();
config.PropertyChanged += (_, args) =>
{
if (args.PropertyName is nameof(Config.UseRainbowLed))
{
if (Config is { UseRainbowLed: true, TurnOffLed: false, EnableLedChanging: true })
Rainbow.Updated += (ref Color color) => ParentModel.SelectedGamepad.SetLed((uint)color.ToArgb());
else
{
Rainbow.Reset();
if (Config.TurnOffLed)
ParentModel.SelectedGamepad.ClearLed();
else
ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32());
}
}
};
Config = config; Config = config;
} }

View File

@@ -23,6 +23,7 @@ using Ryujinx.Input;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
@@ -63,7 +64,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
get => _selectedGamepad; get => _selectedGamepad;
private set private set
{ {
Rainbow.Reset();
_selectedGamepad = value; _selectedGamepad = value;
if (ConfigViewModel is ControllerInputViewModel { Config.UseRainbowLed: true })
Rainbow.Updated += (ref Color color) => _selectedGamepad.SetLed((uint)color.ToArgb());
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed)); OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
} }
} }

View File

@@ -1,7 +1,13 @@
using Avalonia.Media; using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Gommon;
using Humanizer;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.Configuration;
using System;
using System.Globalization;
using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
@@ -21,6 +27,19 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
[ObservableProperty] private bool _enableLedChanging; [ObservableProperty] private bool _enableLedChanging;
[ObservableProperty] private Color _ledColor; [ObservableProperty] private Color _ledColor;
public string RainbowSpeedText => RainbowSpeed.ToString(CultureInfo.CurrentCulture).Truncate(4, string.Empty);
public float RainbowSpeed
{
get => ConfigurationState.Instance.Hid.RainbowSpeed;
set
{
ConfigurationState.Instance.Hid.RainbowSpeed.Value = value;
OnPropertyChanged();
OnPropertyChanged(nameof(RainbowSpeedText));
}
}
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed; public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;

View File

@@ -11,7 +11,7 @@
x:Class="Ryujinx.UI.Views.Input.LedInputView"> x:Class="Ryujinx.UI.Views.Input.LedInputView">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center"> <StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" IsVisible="{Binding ParentModel.CanClearLed}"> <StackPanel Orientation="Horizontal" IsVisible="{Binding ParentModel.CanClearLed}">
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColorDisable}" /> <TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColorDisable}" />
<CheckBox <CheckBox
Margin="5" Margin="5"
MinWidth="0" MinWidth="0"
@@ -20,15 +20,33 @@
</CheckBox> </CheckBox>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" IsEnabled="{Binding !TurnOffLed}"> <StackPanel Orientation="Horizontal" IsEnabled="{Binding !TurnOffLed}">
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColorRainbow}" /> <TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColorRainbow}" />
<CheckBox <CheckBox
Margin="5" Margin="5"
MinWidth="0" MinWidth="0"
IsChecked="{Binding UseRainbowLed, Mode=TwoWay}"> IsChecked="{Binding UseRainbowLed, Mode=TwoWay}">
</CheckBox> </CheckBox>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" IsEnabled="{Binding !TurnOffLed}">
<TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColorRainbowSpeed}" />
<Slider HorizontalAlignment="Center"
Value="{Binding RainbowSpeed}"
Width="175"
Margin="0,-3,0,0"
Height="32"
Padding="0,-5"
TickFrequency="0.25"
LargeChange="1"
SmallChange="0.25"
VerticalAlignment="Center"
Minimum="1"
Maximum="10" />
<TextBlock Margin="5,0"
MinWidth="75"
Text="{Binding RainbowSpeedText}" />
</StackPanel>
<StackPanel Orientation="Horizontal" IsEnabled="{Binding ShowLedColorPicker}"> <StackPanel Orientation="Horizontal" IsEnabled="{Binding ShowLedColorPicker}">
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColor}" /> <TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColor}" />
<ui:ColorPickerButton <ui:ColorPickerButton
Margin="5" Margin="5"
IsMoreButtonVisible="False" IsMoreButtonVisible="False"

View File

@@ -1,11 +1,9 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.ViewModels.Input; using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Ava.UI.Views.Input;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.UI.Views.Input namespace Ryujinx.UI.Views.Input

View File

@@ -134,7 +134,12 @@ namespace Ryujinx.Ava.UI.Views.Main
{ {
Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager); Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager);
Rainbow.Enable();
await Window.SettingsWindow.ShowDialog(Window); await Window.SettingsWindow.ShowDialog(Window);
Rainbow.Disable();
Rainbow.Reset();
Window.SettingsWindow = null; Window.SettingsWindow = null;

View File

@@ -34,7 +34,6 @@ namespace Ryujinx.Ava.UI.Windows
#if DEBUG #if DEBUG
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt)); this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
#endif #endif
} }
public SettingsWindow() public SettingsWindow()

View File

@@ -1,6 +1,5 @@
using Ryujinx.Ava.Utilities.Configuration.System; using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI; using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
@@ -8,7 +7,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE; using Ryujinx.HLE;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Nodes;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.Ava.Utilities.Configuration
{ {
@@ -17,7 +15,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 61; public const int CurrentVersion = 62;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@@ -376,24 +374,15 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// </summary> /// </summary>
public KeyboardHotkeys Hotkeys { get; set; } public KeyboardHotkeys Hotkeys { get; set; }
/// <summary>
/// Legacy keyboard control bindings
/// </summary>
/// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
/// TODO: Remove this when those older versions aren't in use anymore.
public List<JsonObject> KeyboardConfig { get; set; }
/// <summary>
/// Legacy controller control bindings
/// </summary>
/// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
/// TODO: Remove this when those older versions aren't in use anymore.
public List<JsonObject> ControllerConfig { get; set; }
/// <summary> /// <summary>
/// Input configurations /// Input configurations
/// </summary> /// </summary>
public List<InputConfig> InputConfig { get; set; } public List<InputConfig> InputConfig { get; set; }
/// <summary>
/// The speed of spectrum cycling for the Rainbow LED feature.
/// </summary>
public float RainbowSpeed { get; set; }
/// <summary> /// <summary>
/// Graphics backend /// Graphics backend

View File

@@ -140,6 +140,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
Hid.EnableMouse.Value = cff.EnableMouse; Hid.EnableMouse.Value = cff.EnableMouse;
Hid.Hotkeys.Value = cff.Hotkeys; Hid.Hotkeys.Value = cff.Hotkeys;
Hid.InputConfig.Value = cff.InputConfig ?? []; Hid.InputConfig.Value = cff.InputConfig ?? [];
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
Multiplayer.LanInterfaceId.Value = cff.MultiplayerLanInterfaceId; Multiplayer.LanInterfaceId.Value = cff.MultiplayerLanInterfaceId;
Multiplayer.Mode.Value = cff.MultiplayerMode; Multiplayer.Mode.Value = cff.MultiplayerMode;
@@ -427,7 +428,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
LedColor = new Color(255, 5, 1, 253).ToUInt32() LedColor = new Color(255, 5, 1, 253).ToUInt32()
}; };
} }
}) }),
(62, static cff => cff.RainbowSpeed = 1f)
); );
} }
} }

View File

@@ -7,6 +7,7 @@ using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE; using Ryujinx.HLE;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -444,6 +445,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// TODO: Implement a ReactiveList class. /// TODO: Implement a ReactiveList class.
/// </summary> /// </summary>
public ReactiveObject<List<InputConfig>> InputConfig { get; private set; } public ReactiveObject<List<InputConfig>> InputConfig { get; private set; }
/// <summary>
/// The speed of spectrum cycling for the Rainbow LED feature.
/// </summary>
public ReactiveObject<float> RainbowSpeed { get; }
public HidSection() public HidSection()
{ {
@@ -451,6 +457,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
EnableMouse = new ReactiveObject<bool>(); EnableMouse = new ReactiveObject<bool>();
Hotkeys = new ReactiveObject<KeyboardHotkeys>(); Hotkeys = new ReactiveObject<KeyboardHotkeys>();
InputConfig = new ReactiveObject<List<InputConfig>>(); InputConfig = new ReactiveObject<List<InputConfig>>();
RainbowSpeed = new ReactiveObject<float>();
RainbowSpeed.Event += (_, args) => Rainbow.Speed = args.NewValue;
} }
} }

View File

@@ -130,9 +130,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
EnableKeyboard = Hid.EnableKeyboard, EnableKeyboard = Hid.EnableKeyboard,
EnableMouse = Hid.EnableMouse, EnableMouse = Hid.EnableMouse,
Hotkeys = Hid.Hotkeys, Hotkeys = Hid.Hotkeys,
KeyboardConfig = [],
ControllerConfig = [],
InputConfig = Hid.InputConfig, InputConfig = Hid.InputConfig,
RainbowSpeed = Hid.RainbowSpeed,
GraphicsBackend = Graphics.GraphicsBackend, GraphicsBackend = Graphics.GraphicsBackend,
PreferredGpu = Graphics.PreferredGpu, PreferredGpu = Graphics.PreferredGpu,
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId, MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
@@ -255,6 +254,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
VolumeUp = Key.Unbound, VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound, VolumeDown = Key.Unbound,
}; };
Hid.RainbowSpeed.Value = 1f;
Hid.InputConfig.Value = Hid.InputConfig.Value =
[ [
new StandardKeyboardInputConfig new StandardKeyboardInputConfig