From b19ff742b66af77b17d57daade5fc32f686e90b6 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 22 Jun 2019 12:14:48 +0200 Subject: [PATCH 01/16] Added refresh logic to prevent the SDK from timing out --- .../Generic/SteelSeriesDeviceUpdateQueue.cs | 13 ++ .../Generic/SteelSeriesDeviceUpdateTrigger.cs | 161 ++++++++++++++++++ .../SteelSeriesDeviceProvider.cs | 6 +- 3 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs index 9b43d5c..fe3d576 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs @@ -15,6 +15,7 @@ namespace RGB.NET.Devices.SteelSeries #region Properties & Fields private string _deviceType; + private Dictionary _lastDataSet; #endregion @@ -35,9 +36,21 @@ namespace RGB.NET.Devices.SteelSeries #region Methods + protected override void OnUpdate(object sender, CustomUpdateData customData) + { + if ((customData != null) && (customData["refresh"] as bool? ?? false)) + { + if ((_lastDataSet != null) && (_lastDataSet.Count != 0)) + Update(_lastDataSet); + } + else + base.OnUpdate(sender, customData); + } + /// protected override void Update(Dictionary dataSet) { + _lastDataSet = dataSet; SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.ToDictionary(x => ((SteelSeriesLedId)x.Key).GetAPIName(), x => x.Value.ToIntArray())); } diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs new file mode 100644 index 0000000..2d5ac46 --- /dev/null +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs @@ -0,0 +1,161 @@ +// ReSharper disable MemberCanBePrivate.Global + +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using RGB.NET.Core; + +namespace RGB.NET.Devices.SteelSeries +{ + /// + /// Represents an update-trigger used to update devices with a maximum update-rate. + /// + public class SteelSeriesDeviceUpdateTrigger : AbstractUpdateTrigger, IDeviceUpdateTrigger + { + #region Constants + + private const long FLUSH_TIMER = 5 * 1000 * TimeSpan.TicksPerMillisecond; // every 5 seconds flush the device to prevent timeouts + + #endregion + + #region Properties & Fields + + /// + /// Gets or sets the timeout used by the blocking wait for data availability. + /// + public int Timeout { get; set; } = 100; + + /// + /// Gets the update frequency used by the trigger if not limited by data shortage. + /// + public double UpdateFrequency { get; private set; } + + private double _maxUpdateRate; + /// + /// Gets or sets the maximum update rate of this trigger (is overwriten if the is smaller). + /// <= 0 removes the limit. + /// + public double MaxUpdateRate + { + get => _maxUpdateRate; + set + { + _maxUpdateRate = value; + UpdateUpdateFrequency(); + } + } + + private double _updateRateHardLimit; + /// + /// Gets the hard limit of the update rate of this trigger. Updates will never perform faster then then this value if it's set. + /// <= 0 removes the limit. + /// + public double UpdateRateHardLimit + { + get => _updateRateHardLimit; + protected set + { + _updateRateHardLimit = value; + UpdateUpdateFrequency(); + } + } + + private AutoResetEvent _hasDataEvent = new AutoResetEvent(false); + + private long _lastUpdateTimestamp; + private bool _isRunning; + private Task _updateTask; + private CancellationTokenSource _updateTokenSource; + private CancellationToken _updateToken; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public SteelSeriesDeviceUpdateTrigger() + { } + + /// + /// Initializes a new instance of the class. + /// + /// The hard limit of the update rate of this trigger. + public SteelSeriesDeviceUpdateTrigger(double updateRateHardLimit) + { + this.UpdateRateHardLimit = updateRateHardLimit; + } + + #endregion + + #region Methods + + /// + /// Starts the trigger. + /// + public void Start() + { + if (_isRunning) return; + + _isRunning = true; + + _updateTokenSource?.Dispose(); + _updateTokenSource = new CancellationTokenSource(); + _updateTask = Task.Factory.StartNew(UpdateLoop, (_updateToken = _updateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + + /// + /// Stops the trigger. + /// + public async void Stop() + { + if (!_isRunning) return; + + _isRunning = false; + + _updateTokenSource.Cancel(); + await _updateTask; + _updateTask.Dispose(); + _updateTask = null; + } + + private void UpdateLoop() + { + OnStartup(); + while (!_updateToken.IsCancellationRequested) + { + if (_hasDataEvent.WaitOne(Timeout)) + { + long preUpdateTicks = Stopwatch.GetTimestamp(); + + OnUpdate(); + + if (UpdateFrequency > 0) + { + _lastUpdateTimestamp = Stopwatch.GetTimestamp(); + double lastUpdateTime = ((_lastUpdateTimestamp - preUpdateTicks) / (double)TimeSpan.TicksPerMillisecond); + int sleep = (int)((UpdateFrequency * 1000.0) - lastUpdateTime); + if (sleep > 0) + Thread.Sleep(sleep); + } + } + else if (((Stopwatch.GetTimestamp() - _lastUpdateTimestamp) > FLUSH_TIMER)) + OnUpdate(new CustomUpdateData(("refresh", true))); + } + } + + /// + public void TriggerHasData() => _hasDataEvent.Set(); + + private void UpdateUpdateFrequency() + { + UpdateFrequency = MaxUpdateRate; + if ((UpdateFrequency <= 0) || ((UpdateRateHardLimit > 0) && (UpdateRateHardLimit < UpdateFrequency))) + UpdateFrequency = UpdateRateHardLimit; + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs index 432c51b..9f59d7d 100644 --- a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs +++ b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs @@ -37,9 +37,9 @@ namespace RGB.NET.Devices.SteelSeries public IEnumerable Devices { get; private set; } /// - /// The used to trigger the updates for SteelSeries devices. + /// The used to trigger the updates for SteelSeries devices. /// - public DeviceUpdateTrigger UpdateTrigger { get; } + public SteelSeriesDeviceUpdateTrigger UpdateTrigger { get; } #endregion @@ -54,7 +54,7 @@ namespace RGB.NET.Devices.SteelSeries if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}"); _instance = this; - UpdateTrigger = new DeviceUpdateTrigger(); + UpdateTrigger = new SteelSeriesDeviceUpdateTrigger(); } #endregion From 5f203859ca00dadcef5efb870e8d42f97c1e7305 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 22 Jun 2019 12:21:48 +0200 Subject: [PATCH 02/16] Changed SteelSeriesDeviceUpdateTrigger to inherit DeviceUpdateTrigger --- .../Update/Devices/DeviceUpdateTrigger.cs | 40 +++---- .../Generic/SteelSeriesDeviceUpdateTrigger.cs | 104 ++---------------- 2 files changed, 29 insertions(+), 115 deletions(-) diff --git a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs index 03410fb..04cfb92 100644 --- a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs +++ b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs @@ -53,12 +53,12 @@ namespace RGB.NET.Core } } - private AutoResetEvent _hasDataEvent = new AutoResetEvent(false); + protected AutoResetEvent HasDataEvent = new AutoResetEvent(false); - private bool _isRunning; - private Task _updateTask; - private CancellationTokenSource _updateTokenSource; - private CancellationToken _updateToken; + protected bool IsRunning; + protected Task UpdateTask; + protected CancellationTokenSource UpdateTokenSource; + protected CancellationToken UpdateToken; #endregion @@ -88,13 +88,13 @@ namespace RGB.NET.Core /// public void Start() { - if (_isRunning) return; + if (IsRunning) return; - _isRunning = true; + IsRunning = true; - _updateTokenSource?.Dispose(); - _updateTokenSource = new CancellationTokenSource(); - _updateTask = Task.Factory.StartNew(UpdateLoop, (_updateToken = _updateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default); + UpdateTokenSource?.Dispose(); + UpdateTokenSource = new CancellationTokenSource(); + UpdateTask = Task.Factory.StartNew(UpdateLoop, (UpdateToken = UpdateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default); } /// @@ -102,22 +102,22 @@ namespace RGB.NET.Core /// public async void Stop() { - if (!_isRunning) return; + if (!IsRunning) return; - _isRunning = false; + IsRunning = false; - _updateTokenSource.Cancel(); - await _updateTask; - _updateTask.Dispose(); - _updateTask = null; + UpdateTokenSource.Cancel(); + await UpdateTask; + UpdateTask.Dispose(); + UpdateTask = null; } - private void UpdateLoop() + protected virtual void UpdateLoop() { OnStartup(); - while (!_updateToken.IsCancellationRequested) + while (!UpdateToken.IsCancellationRequested) { - if (_hasDataEvent.WaitOne(Timeout)) + if (HasDataEvent.WaitOne(Timeout)) { long preUpdateTicks = Stopwatch.GetTimestamp(); @@ -135,7 +135,7 @@ namespace RGB.NET.Core } /// - public void TriggerHasData() => _hasDataEvent.Set(); + public void TriggerHasData() => HasDataEvent.Set(); private void UpdateUpdateFrequency() { diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs index 2d5ac46..88c04ac 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs @@ -3,71 +3,24 @@ using System; using System.Diagnostics; using System.Threading; -using System.Threading.Tasks; using RGB.NET.Core; namespace RGB.NET.Devices.SteelSeries { /// - /// Represents an update-trigger used to update devices with a maximum update-rate. + /// Represents an update-trigger used to update SteelSeries devices /// - public class SteelSeriesDeviceUpdateTrigger : AbstractUpdateTrigger, IDeviceUpdateTrigger + public class SteelSeriesDeviceUpdateTrigger : DeviceUpdateTrigger { #region Constants - private const long FLUSH_TIMER = 5 * 1000 * TimeSpan.TicksPerMillisecond; // every 5 seconds flush the device to prevent timeouts + private const long FLUSH_TIMER = 5 * 1000 * TimeSpan.TicksPerMillisecond; // flush the device every 5 seconds to prevent timeouts #endregion #region Properties & Fields - /// - /// Gets or sets the timeout used by the blocking wait for data availability. - /// - public int Timeout { get; set; } = 100; - - /// - /// Gets the update frequency used by the trigger if not limited by data shortage. - /// - public double UpdateFrequency { get; private set; } - - private double _maxUpdateRate; - /// - /// Gets or sets the maximum update rate of this trigger (is overwriten if the is smaller). - /// <= 0 removes the limit. - /// - public double MaxUpdateRate - { - get => _maxUpdateRate; - set - { - _maxUpdateRate = value; - UpdateUpdateFrequency(); - } - } - - private double _updateRateHardLimit; - /// - /// Gets the hard limit of the update rate of this trigger. Updates will never perform faster then then this value if it's set. - /// <= 0 removes the limit. - /// - public double UpdateRateHardLimit - { - get => _updateRateHardLimit; - protected set - { - _updateRateHardLimit = value; - UpdateUpdateFrequency(); - } - } - - private AutoResetEvent _hasDataEvent = new AutoResetEvent(false); - private long _lastUpdateTimestamp; - private bool _isRunning; - private Task _updateTask; - private CancellationTokenSource _updateTokenSource; - private CancellationToken _updateToken; #endregion @@ -76,6 +29,7 @@ namespace RGB.NET.Devices.SteelSeries /// /// Initializes a new instance of the class. /// + /// The hard limit of the update rate of this trigger. public SteelSeriesDeviceUpdateTrigger() { } @@ -84,49 +38,19 @@ namespace RGB.NET.Devices.SteelSeries /// /// The hard limit of the update rate of this trigger. public SteelSeriesDeviceUpdateTrigger(double updateRateHardLimit) - { - this.UpdateRateHardLimit = updateRateHardLimit; - } + : base(updateRateHardLimit) + { } #endregion #region Methods - /// - /// Starts the trigger. - /// - public void Start() - { - if (_isRunning) return; - - _isRunning = true; - - _updateTokenSource?.Dispose(); - _updateTokenSource = new CancellationTokenSource(); - _updateTask = Task.Factory.StartNew(UpdateLoop, (_updateToken = _updateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default); - } - - /// - /// Stops the trigger. - /// - public async void Stop() - { - if (!_isRunning) return; - - _isRunning = false; - - _updateTokenSource.Cancel(); - await _updateTask; - _updateTask.Dispose(); - _updateTask = null; - } - - private void UpdateLoop() + protected override void UpdateLoop() { OnStartup(); - while (!_updateToken.IsCancellationRequested) + while (!UpdateToken.IsCancellationRequested) { - if (_hasDataEvent.WaitOne(Timeout)) + if (HasDataEvent.WaitOne(Timeout)) { long preUpdateTicks = Stopwatch.GetTimestamp(); @@ -146,16 +70,6 @@ namespace RGB.NET.Devices.SteelSeries } } - /// - public void TriggerHasData() => _hasDataEvent.Set(); - - private void UpdateUpdateFrequency() - { - UpdateFrequency = MaxUpdateRate; - if ((UpdateFrequency <= 0) || ((UpdateRateHardLimit > 0) && (UpdateRateHardLimit < UpdateFrequency))) - UpdateFrequency = UpdateRateHardLimit; - } - #endregion } } From fe8adbd849f23ad53c14b773954ce628c15c22d3 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sun, 18 Aug 2019 17:58:03 +0200 Subject: [PATCH 03/16] Added event to intercept the creation of absolute paths --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 2 +- RGB.NET.Core/Events/ResolvePathEventArgs.cs | 64 +++++++++++++++++++ RGB.NET.Core/Helper/PathHelper.cs | 60 ++++++++++++++++- .../Dram/AsusDramRGBDevice.cs | 2 +- .../GraphicsCard/AsusGraphicsCardRGBDevice.cs | 2 +- .../Headset/AsusHeadsetRGBDevice.cs | 2 +- .../Keyboard/AsusKeyboardRGBDevice.cs | 4 +- .../Mainboard/AsusMainboardRGBDevice.cs | 2 +- .../Mouse/AsusMouseRGBDevice.cs | 2 +- .../GraphicsCard/AsusGraphicsCardRGBDevice.cs | 2 +- .../Keyboard/AsusKeyboardRGBDevice.cs | 4 +- .../Mainboard/AsusMainboardRGBDevice.cs | 2 +- .../Mouse/AsusMouseRGBDevice.cs | 2 +- .../Keyboard/CoolerMasterKeyboardRGBDevice.cs | 4 +- .../Mouse/CoolerMasterMouseRGBDevice.cs | 4 +- .../Custom/CorsairCustomRGBDevice.cs | 2 +- .../Headset/CorsairHeadsetRGBDevice.cs | 2 +- .../CorsairHeadsetStandRGBDevice.cs | 4 +- .../Keyboard/CorsairKeyboardRGBDevice.cs | 4 +- .../Memory/CorsairMemoryRGBDevice.cs | 2 +- .../Mouse/CorsairMouseRGBDevice.cs | 2 +- .../Mousepad/CorsairMousepadRGBDevice.cs | 2 +- .../Generic/LogitechRGBDevice.cs | 2 +- .../Launchpad/NovationLaunchpadRGBDevice.cs | 2 +- .../ChromaLink/RazerChromaLinkRGBDevice.cs | 2 +- .../Headset/RazerHeadsetRGBDevice.cs | 2 +- .../Keypad/RazerKeypadRGBDevice.cs | 2 +- .../Mouse/RazerMouseRGBDevice.cs | 2 +- .../Mousepad/RazerMousepadRGBDevice.cs | 2 +- .../Generic/SteelSeriesRGBDevice.cs | 2 +- 30 files changed, 155 insertions(+), 37 deletions(-) create mode 100644 RGB.NET.Core/Events/ResolvePathEventArgs.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 0575ca3..90c97e1 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -157,7 +157,7 @@ namespace RGB.NET.Core DeviceLayout layout = DeviceLayout.Load(layoutPath); if (layout != null) { - string imageBasePath = string.IsNullOrWhiteSpace(layout.ImageBasePath) ? null : PathHelper.GetAbsolutePath(layout.ImageBasePath); + string imageBasePath = string.IsNullOrWhiteSpace(layout.ImageBasePath) ? null : PathHelper.GetAbsolutePath(this, layout.ImageBasePath); if ((imageBasePath != null) && !string.IsNullOrWhiteSpace(layout.DeviceImage) && (DeviceInfo != null)) DeviceInfo.Image = new Uri(Path.Combine(imageBasePath, layout.DeviceImage), UriKind.Absolute); diff --git a/RGB.NET.Core/Events/ResolvePathEventArgs.cs b/RGB.NET.Core/Events/ResolvePathEventArgs.cs new file mode 100644 index 0000000..2b73a2e --- /dev/null +++ b/RGB.NET.Core/Events/ResolvePathEventArgs.cs @@ -0,0 +1,64 @@ +using System; + +namespace RGB.NET.Core +{ + public class ResolvePathEventArgs : EventArgs + { + #region Properties & Fields + + /// + /// Gets the filename used to resolve the path. + /// This has to be checked for null since it'S possible that only is used. + /// Also check before use. + /// + public string RelativePart { get; } + + /// + /// Gets the filename used to resolve the path. + /// This has to be checked for null since it'S possible that only is used. + /// Also check before use. + /// + public string FileName { get; } + + /// + /// Gets the relative path used to resolve the path. + /// If this is set and are unused. + /// + public string RelativePath { get; } + + /// + /// Gets or sets the resolved path. + /// + public string FinalPath { get; set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The filename used to resolve the path. + /// The filename used to resolve the path. + /// The relative part used to resolve the path. + public ResolvePathEventArgs(string relativePart, string fileName, string finalPath) + { + this.RelativePart = relativePart; + this.FileName = fileName; + this.FinalPath = finalPath; + } + + /// + /// Initializes a new instance of the class. + /// + /// The relative path used to resolve the path. + /// The relative part used to resolve the path. + public ResolvePathEventArgs(string relativePath, string finalPath) + { + this.RelativePath = relativePath; + this.FinalPath = finalPath; + } + + #endregion + } +} diff --git a/RGB.NET.Core/Helper/PathHelper.cs b/RGB.NET.Core/Helper/PathHelper.cs index dc43f25..d67e5b7 100644 --- a/RGB.NET.Core/Helper/PathHelper.cs +++ b/RGB.NET.Core/Helper/PathHelper.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Reflection; namespace RGB.NET.Core @@ -8,20 +9,73 @@ namespace RGB.NET.Core /// public static class PathHelper { + #region Events + + /// + /// Occurs when a path is resolving. + /// + public static event EventHandler ResolvingAbsolutePath; + + #endregion + #region Methods /// /// Returns an absolute path created from an relative path relatvie to the location of the executung assembly. /// + /// The relative part of the path to convert. + /// The absolute path. + public static string GetAbsolutePath(string relativePath) => GetAbsolutePath((object)null, relativePath); + + /// + /// Returns an absolute path created from an relative path relatvie to the location of the executung assembly. + /// + /// The relative part of the path to convert. + /// The file name of the path to convert. + /// The absolute path. + public static string GetAbsolutePath(string relativePath, string fileName) => GetAbsolutePath(null, relativePath, fileName); + + /// + /// Returns an absolute path created from an relative path relatvie to the location of the executung assembly. + /// + /// The requester of this path. (Used for better control when using the event to override this behavior.) + /// The relative path to convert. + /// The file name of the path to convert. + /// The absolute path. + public static string GetAbsolutePath(object sender, string relativePath, string fileName) + { + string relativePart = Path.Combine(relativePath, fileName); + + string assemblyLocation = Assembly.GetEntryAssembly()?.Location; + if (assemblyLocation == null) return relativePart; + + string directoryName = Path.GetDirectoryName(assemblyLocation); + string path = directoryName == null ? null : Path.Combine(directoryName, relativePart); + + ResolvePathEventArgs args = new ResolvePathEventArgs(relativePath, fileName, path); + ResolvingAbsolutePath?.Invoke(sender, args); + + return args.FinalPath; + } + + /// + /// Returns an absolute path created from an relative path relatvie to the location of the executung assembly. + /// + /// The requester of this path. (Used for better control when using the event to override this behavior.) /// The relative path to convert. /// The absolute path. - public static string GetAbsolutePath(string relativePath) + public static string GetAbsolutePath(object sender, string relativePath) { string assemblyLocation = Assembly.GetEntryAssembly()?.Location; if (assemblyLocation == null) return relativePath; string directoryName = Path.GetDirectoryName(assemblyLocation); - return directoryName == null ? null : Path.Combine(directoryName, relativePath); + string path = directoryName == null ? null : Path.Combine(directoryName, relativePath); + + ResolvePathEventArgs args = new ResolvePathEventArgs(relativePath, path); + ResolvingAbsolutePath?.Invoke(sender, args); + + return args.FinalPath; } #endregion diff --git a/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs b/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs index 7e74550..315b1ed 100644 --- a/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs @@ -33,7 +33,7 @@ namespace RGB.NET.Devices.Asus //TODO DarthAffe 21.10.2017: We don't know the model, how to save layouts and images? //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images? - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Drams\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\Drams", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs index 679dd4a..de925fb 100644 --- a/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs +++ b/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs @@ -32,7 +32,7 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.GraphicsCard1 + i, new Rectangle(i * 10, 0, 10, 10)); //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images? - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\GraphicsCards\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\GraphicsCards", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs b/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs index c221e1e..e762d97 100644 --- a/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs @@ -32,7 +32,7 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.Headset1 + i, new Rectangle(i * 40, 0, 40, 8)); //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images? - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Headsets\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\Headsets", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs index 320f39a..f16acf4 100644 --- a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs @@ -32,12 +32,12 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.Keyboard_Escape + i, new Rectangle(i * 19, 0, 19, 19)); string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Keyboards\{model}\{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), DeviceInfo.LogicalLayout.ToString()); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, $@"Layouts\Asus\Keyboards\{model}", $"{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), DeviceInfo.LogicalLayout.ToString()); } /// protected override object CreateLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keyboard_Escape; - + #endregion } } diff --git a/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs b/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs index 907b704..df7d419 100644 --- a/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs @@ -32,7 +32,7 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.Mainboard1 + i, new Rectangle(i * 40, 0, 40, 8)); //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images? - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Mainboards\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\Mainboards", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs b/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs index bc9df80..a6a7ea3 100644 --- a/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs @@ -31,7 +31,7 @@ namespace RGB.NET.Devices.Asus for (int i = 0; i < ledCount; i++) InitializeLed(LedId.Mouse1 + i, new Rectangle(i * 10, 0, 10, 10)); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Mouses\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\Mouses", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus_Legacy/GraphicsCard/AsusGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Asus_Legacy/GraphicsCard/AsusGraphicsCardRGBDevice.cs index 360fa38..be0c0b2 100644 --- a/RGB.NET.Devices.Asus_Legacy/GraphicsCard/AsusGraphicsCardRGBDevice.cs +++ b/RGB.NET.Devices.Asus_Legacy/GraphicsCard/AsusGraphicsCardRGBDevice.cs @@ -34,7 +34,7 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.GraphicsCard1 + i, new Rectangle(i * 10, 0, 10, 10)); //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images? - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\GraphicsCards\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\GraphicsCards", $"{ DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus_Legacy/Keyboard/AsusKeyboardRGBDevice.cs b/RGB.NET.Devices.Asus_Legacy/Keyboard/AsusKeyboardRGBDevice.cs index 6ced56e..d92d4d7 100644 --- a/RGB.NET.Devices.Asus_Legacy/Keyboard/AsusKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Asus_Legacy/Keyboard/AsusKeyboardRGBDevice.cs @@ -34,12 +34,12 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.Keyboard_Escape + i, new Rectangle(i * 19, 0, 19, 19)); string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Keyboards\{model}\{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), DeviceInfo.LogicalLayout.ToString()); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, $@"Layouts\Asus\Keyboards\{model}", $"{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), DeviceInfo.LogicalLayout.ToString()); } /// protected override object CreateLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keyboard_Escape; - + /// protected override Action GetUpdateColorAction() => _AsusSDK.SetClaymoreKeyboardColor; diff --git a/RGB.NET.Devices.Asus_Legacy/Mainboard/AsusMainboardRGBDevice.cs b/RGB.NET.Devices.Asus_Legacy/Mainboard/AsusMainboardRGBDevice.cs index 26fecdb..4ea1c60 100644 --- a/RGB.NET.Devices.Asus_Legacy/Mainboard/AsusMainboardRGBDevice.cs +++ b/RGB.NET.Devices.Asus_Legacy/Mainboard/AsusMainboardRGBDevice.cs @@ -34,7 +34,7 @@ namespace RGB.NET.Devices.Asus InitializeLed(LedId.Mainboard1 + i, new Rectangle(i * 40, 0, 40, 8)); //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images? - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Mainboards\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\Mainboards", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Asus_Legacy/Mouse/AsusMouseRGBDevice.cs b/RGB.NET.Devices.Asus_Legacy/Mouse/AsusMouseRGBDevice.cs index 03db09c..d318cae 100644 --- a/RGB.NET.Devices.Asus_Legacy/Mouse/AsusMouseRGBDevice.cs +++ b/RGB.NET.Devices.Asus_Legacy/Mouse/AsusMouseRGBDevice.cs @@ -33,7 +33,7 @@ namespace RGB.NET.Devices.Asus for (int i = 0; i < ledCount; i++) InitializeLed(LedId.Mouse1 + i, new Rectangle(i * 10, 0, 10, 10)); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Mouses\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Asus\Mouses", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs index 3a30cc2..e8906e3 100644 --- a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs @@ -33,8 +33,8 @@ namespace RGB.NET.Devices.CoolerMaster InitializeLed(led.Key, new Rectangle(led.Value.column * 19, led.Value.row * 19, 19, 19)); string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath( - $@"Layouts\CoolerMaster\Keyboards\{model}\{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), DeviceInfo.LogicalLayout.ToString()); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, $@"Layouts\CoolerMaster\Keyboards\{model}", $"{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), + DeviceInfo.LogicalLayout.ToString()); } /// diff --git a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs index 3cbee5b..4281706 100644 --- a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs @@ -23,7 +23,7 @@ namespace RGB.NET.Devices.CoolerMaster #endregion #region Methods - + /// protected override void InitializeLayout() { @@ -33,7 +33,7 @@ namespace RGB.NET.Devices.CoolerMaster InitializeLed(led.Key, new Rectangle(led.Value.column * 19, led.Value.row * 19, 19, 19)); string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\CoolerMaster\Mice\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\CoolerMaster\Mice", $"{model}.xml"), null); } /// diff --git a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs b/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs index 3386a7a..711d97c 100644 --- a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs @@ -46,7 +46,7 @@ namespace RGB.NET.Devices.Corsair } string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Corsair\Customs\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Corsair\Customs", $"{model}.xml"), null); } /// diff --git a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs index 1f5f951..1ecbe9b 100644 --- a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs @@ -32,7 +32,7 @@ namespace RGB.NET.Devices.Corsair InitializeLed(LedId.Headset1, new Rectangle(0, 0, 10, 10)); InitializeLed(LedId.Headset2, new Rectangle(10, 0, 10, 10)); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Corsair\Headsets\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Corsair\Headsets", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs index ad855cb..ed25ad7 100644 --- a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs @@ -51,9 +51,9 @@ namespace RGB.NET.Devices.Corsair foreach (_CorsairLedPosition ledPosition in positions.OrderBy(p => p.LedId)) InitializeLed(mapping.TryGetValue(ledPosition.LedId, out LedId ledId) ? ledId : LedId.Invalid, ledPosition.ToRectangle()); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Corsair\HeadsetStands\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Corsair\HeadsetStands", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } - + /// protected override object CreateLedCustomData(LedId ledId) => HeadsetStandIdMapping.DEFAULT.TryGetValue(ledId, out CorsairLedId id) ? id : CorsairLedId.Invalid; diff --git a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs index 8752ee5..4fdd829 100644 --- a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs @@ -48,8 +48,8 @@ namespace RGB.NET.Devices.Corsair } string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath( - $@"Layouts\Corsair\Keyboards\{model}\{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), DeviceInfo.LogicalLayout.ToString()); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, $@"Layouts\Corsair\Keyboards\{model}", $"{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"), + DeviceInfo.LogicalLayout.ToString()); } /// diff --git a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs index d9bb202..ed2c2fb 100644 --- a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs @@ -48,7 +48,7 @@ namespace RGB.NET.Devices.Corsair } string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Corsair\Memory\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Corsair\Memory", $"{model}.xml"), null); } /// diff --git a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs index afa275d..6fcbffb 100644 --- a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs @@ -54,7 +54,7 @@ namespace RGB.NET.Devices.Corsair throw new RGBDeviceException($"Can't initialize mouse with layout '{DeviceInfo.PhysicalLayout}'"); } - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Corsair\Mice\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Corsair\Mice", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs index b83a0ca..e918b58 100644 --- a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs @@ -51,7 +51,7 @@ namespace RGB.NET.Devices.Corsair foreach (_CorsairLedPosition ledPosition in positions.OrderBy(p => p.LedId)) InitializeLed(mapping.TryGetValue(ledPosition.LedId, out LedId ledId) ? ledId : LedId.Invalid, ledPosition.ToRectangle()); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Corsair\Mousepads\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Corsair\Mousepads", $"{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null); } /// diff --git a/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs b/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs index b8f6eab..02a8373 100644 --- a/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs @@ -67,7 +67,7 @@ namespace RGB.NET.Devices.Logitech string layout = info.ImageLayout; string layoutPath = info.LayoutPath; - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Logitech\{layoutPath}.xml"), layout, true); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Logitech", $"{layoutPath}.xml"), layout, true); } #endregion diff --git a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs index c0abd7f..6f58e93 100644 --- a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs @@ -47,7 +47,7 @@ namespace RGB.NET.Devices.Novation } string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Novation\Launchpads\{model.ToUpper()}.xml"), "Default"); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Novation\Launchpads", $"{model.ToUpper()}.xml"), "Default"); } /// diff --git a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs index 069aab8..79745d4 100644 --- a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs +++ b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs @@ -31,7 +31,7 @@ namespace RGB.NET.Devices.Razer protected override void InitializeLayout() { string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Razer\ChromaLink\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Razer\ChromaLink", $"{model}.xml"), null); if (LedMapping.Count == 0) for (int i = 0; i < _Defines.CHROMALINK_MAX_LEDS; i++) diff --git a/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs index a5ef0ab..fb332dc 100644 --- a/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs @@ -31,7 +31,7 @@ namespace RGB.NET.Devices.Razer protected override void InitializeLayout() { string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Razer\Headset\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Razer\Headset", $"{model}.xml"), null); if (LedMapping.Count == 0) for (int i = 0; i < _Defines.HEADSET_MAX_LEDS; i++) diff --git a/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs index 589faae..01f1820 100644 --- a/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs @@ -31,7 +31,7 @@ namespace RGB.NET.Devices.Razer protected override void InitializeLayout() { string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Razer\Keypad\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Razer\Keypad", $"{model}.xml"), null); if (LedMapping.Count == 0) { diff --git a/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs index 2eeba61..4516f15 100644 --- a/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs @@ -31,7 +31,7 @@ namespace RGB.NET.Devices.Razer protected override void InitializeLayout() { string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Razer\Mice\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Razer\Mice", $"{model}.xml"), null); if (LedMapping.Count == 0) { diff --git a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs index d0d8e1c..869c67b 100644 --- a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs @@ -31,7 +31,7 @@ namespace RGB.NET.Devices.Razer protected override void InitializeLayout() { string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Razer\Mousepad\{model}.xml"), null); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\Razer\Mousepad", $"{model}.xml"), null); if (LedMapping.Count == 0) for (int i = 0; i < _Defines.MOUSEPAD_MAX_LEDS; i++) diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs index b30d85b..f13d918 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs @@ -80,7 +80,7 @@ namespace RGB.NET.Devices.SteelSeries string layout = info.ImageLayout; string layoutPath = info.LayoutPath; - ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\SteelSeries\{layoutPath}.xml"), layout, true); + ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, @"Layouts\SteelSeries", $"{layoutPath}.xml"), layout, true); } #endregion From 86e9bb293bf8235529ba6461b9b96126bb61b3d1 Mon Sep 17 00:00:00 2001 From: Robert Beekman Date: Sun, 10 Nov 2019 12:55:49 +0100 Subject: [PATCH 04/16] Fix per key device loading --- RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs index a9d08f1..991fc01 100644 --- a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs +++ b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs @@ -114,7 +114,7 @@ namespace RGB.NET.Devices.Logitech try { - if (DeviceChecker.IsPerDeviceDeviceConnected) + if (DeviceChecker.IsPerKeyDeviceConnected) { (string model, RGBDeviceType deviceType, int _, int _, string imageLayout, string layoutPath) = DeviceChecker.PerKeyDeviceData; if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter From 65abc896056a1914d2034198e6583879b18cc374 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 18 Nov 2019 19:36:46 +0100 Subject: [PATCH 05/16] Changed rectangle to be immutable --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 4 +- .../Extensions/RectangleExtensions.cs | 115 ++++++++++ RGB.NET.Core/Leds/Led.cs | 19 +- RGB.NET.Core/Positioning/Rectangle.cs | 213 ++---------------- RGB.NET.Core/RGBSurface.cs | 13 +- RGB.NET.Groups/Groups/RectangleLedGroup.cs | 14 +- 6 files changed, 162 insertions(+), 216 deletions(-) create mode 100644 RGB.NET.Core/Extensions/RectangleExtensions.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 90c97e1..59d0eae 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -175,9 +175,7 @@ namespace RGB.NET.Core if (led != null) { - led.LedRectangle.Location = new Point(layoutLed.X, layoutLed.Y); - led.LedRectangle.Size = new Size(layoutLed.Width, layoutLed.Height); - + led.LedRectangle = new Rectangle(new Point(layoutLed.X, layoutLed.Y), new Size(layoutLed.Width, layoutLed.Height)); led.Shape = layoutLed.Shape; led.ShapeData = layoutLed.ShapeData; diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs new file mode 100644 index 0000000..7d2f85a --- /dev/null +++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs @@ -0,0 +1,115 @@ +using System; + +namespace RGB.NET.Core +{ + public static class RectangleExtensions + { + #region Methods + + /// + /// Sets the of the given rectangle. + /// + /// The rectangle to modify. + /// The new location of the rectangle. + /// The modified . + public static Rectangle SetLocation(this Rectangle rect, Point location) => new Rectangle(location, rect.Size); + + /// + /// Sets the of the of the given rectangle. + /// + /// The rectangle to modify. + /// The new x-location of the rectangle. + /// The modified . + public static Rectangle SetX(this Rectangle rect, double x) => new Rectangle(new Point(x, rect.Location.Y), rect.Size); + + /// + /// Sets the of the of the given rectangle. + /// + /// The rectangle to modify. + /// The new y-location of the rectangle. + /// The modified . + public static Rectangle SetY(this Rectangle rect, double y) => new Rectangle(new Point(rect.Location.X, y), rect.Size); + + /// + /// Sets the of the given rectangle. + /// + /// The rectangle to modify. + /// The new size of the rectangle. + /// The modified . + public static Rectangle SetSize(this Rectangle rect, Size size) => new Rectangle(rect.Location, size); + + /// + /// Sets the of the of the given rectangle. + /// + /// The rectangle to modify. + /// The new width of the rectangle. + /// The modified . + public static Rectangle SetWidth(this Rectangle rect, double width) => new Rectangle(rect.Location, new Size(width, rect.Size.Height)); + + /// + /// Sets the of the of the given rectangle. + /// + /// The rectangle to modify. + /// The new height of the rectangle. + /// The modified . + public static Rectangle SetHeight(this Rectangle rect, double height) => new Rectangle(rect.Location, new Size(rect.Size.Width, height)); + + /// + /// Calculates the percentage of intersection of a rectangle. + /// + /// The intersecting rectangle. + /// The percentage of intersection. + public static double CalculateIntersectPercentage(this Rectangle rect, Rectangle intersectingRect) + { + if (rect.IsEmpty || intersectingRect.IsEmpty) return 0; + + Rectangle intersection = rect.CalculateIntersection(intersectingRect); + return (intersection.Size.Width * intersection.Size.Height) / (rect.Size.Width * rect.Size.Height); + } + + /// + /// Calculates the representing the intersection of this and the one provided as parameter. + /// + /// The intersecting + /// A new representing the intersection this and the one provided as parameter. + public static Rectangle CalculateIntersection(this Rectangle rect, Rectangle intersectingRectangle) + { + double x1 = Math.Max(rect.Location.X, intersectingRectangle.Location.X); + double x2 = Math.Min(rect.Location.X + rect.Size.Width, intersectingRectangle.Location.X + intersectingRectangle.Size.Width); + + double y1 = Math.Max(rect.Location.Y, intersectingRectangle.Location.Y); + double y2 = Math.Min(rect.Location.Y + rect.Size.Height, intersectingRectangle.Location.Y + intersectingRectangle.Size.Height); + + if ((x2 >= x1) && (y2 >= y1)) + return new Rectangle(x1, y1, x2 - x1, y2 - y1); + + return new Rectangle(); + } + + /// + /// Determines if the specified is contained within this . + /// + /// The to test. + /// + public static bool Contains(this Rectangle rect, Point point) => rect.Contains(point.X, point.Y); + + /// + /// Determines if the specified location is contained within this . + /// + /// The X-location to test. + /// The Y-location to test. + /// + public static bool Contains(this Rectangle rect, double x, double y) => (rect.Location.X <= x) && (x < (rect.Location.X + rect.Size.Width)) + && (rect.Location.Y <= y) && (y < (rect.Location.Y + rect.Size.Height)); + + /// + /// Determines if the specified is contained within this . + /// + /// The to test. + /// + public static bool Contains(this Rectangle rect, Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) + && (rect.Location.Y <= rect2.Location.Y) && ((rect2.Location.Y + rect2.Size.Height) <= (rect.Location.Y + rect.Size.Height)); + + #endregion + } +} diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index b300065..27bf4ed 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -44,10 +44,19 @@ namespace RGB.NET.Core set => SetProperty(ref _shapeData, value); } + private Rectangle _ledRectangle; /// /// Gets a rectangle representing the physical location of the relative to the . /// - public Rectangle LedRectangle { get; } + public Rectangle LedRectangle + { + get => _ledRectangle; + set + { + if (SetProperty(ref _ledRectangle, value)) + OnPropertyChanged(nameof(AbsoluteLedRectangle)); + } + } /// /// Gets a rectangle representing the physical location of the on the . @@ -142,6 +151,12 @@ namespace RGB.NET.Core this.Id = id; this.LedRectangle = ledRectangle; this.CustomData = customData; + + device.PropertyChanged += (sender, args) => + { + OnPropertyChanged(nameof(LedRectangle)); + OnPropertyChanged(nameof(AbsoluteLedRectangle)); + }; } #endregion @@ -195,7 +210,7 @@ namespace RGB.NET.Core /// Converts a to a . /// /// The to convert. - public static implicit operator Rectangle(Led led) => led?.LedRectangle; + public static implicit operator Rectangle(Led led) => led?.LedRectangle ?? new Rectangle(); #endregion } diff --git a/RGB.NET.Core/Positioning/Rectangle.cs b/RGB.NET.Core/Positioning/Rectangle.cs index ede55c3..7bf5330 100644 --- a/RGB.NET.Core/Positioning/Rectangle.cs +++ b/RGB.NET.Core/Positioning/Rectangle.cs @@ -8,155 +8,47 @@ using System.Linq; namespace RGB.NET.Core { - /// /// /// Represents a rectangle defined by it's position and it's size. /// [DebuggerDisplay("[Location: {Location}, Size: {Size}]")] - public class Rectangle : AbstractBindable + public struct Rectangle { #region Properties & Fields - private double _x; /// - /// Gets or sets the X-position of this . + /// Gets the representing the top-left corner of the . /// - public double X - { - get => _x; - set - { - if (SetProperty(ref _x, value)) - { - OnPropertyChanged(nameof(Location)); - OnPropertyChanged(nameof(Center)); - } - } - } - - private double _y; - /// - /// Gets or sets the Y-position of this . - /// - public double Y - { - get => _y; - set - { - if (SetProperty(ref _y, value)) - { - OnPropertyChanged(nameof(Location)); - OnPropertyChanged(nameof(Center)); - } - } - } - - private double _width; - /// - /// Gets or sets the width of this . - /// - public double Width - { - get => _width; - set - { - if (SetProperty(ref _width, Math.Max(0, value))) - { - OnPropertyChanged(nameof(Size)); - OnPropertyChanged(nameof(Center)); - OnPropertyChanged(nameof(IsEmpty)); - } - } - } - - private double _height; - /// - /// Gets or sets the height of this . - /// - public double Height - { - get => _height; - set - { - if (SetProperty(ref _height, Math.Max(0, value))) - { - OnPropertyChanged(nameof(Size)); - OnPropertyChanged(nameof(Center)); - OnPropertyChanged(nameof(IsEmpty)); - } - } - } + public Point Location { get; } /// - /// Gets or sets the representing the top-left corner of the . + /// Gets the of the . /// - public Point Location - { - get => new Point(X, Y); - set - { - if (Location != value) - { - _x = value.X; - _y = value.Y; - - OnPropertyChanged(nameof(Location)); - OnPropertyChanged(nameof(Center)); - } - } - } - - /// - /// Gets or sets the of the . - /// - public Size Size - { - get => new Size(Width, Height); - set - { - if (Size != value) - { - _width = value.Width; - _height = value.Height; - - OnPropertyChanged(nameof(Size)); - OnPropertyChanged(nameof(Center)); - OnPropertyChanged(nameof(IsEmpty)); - } - } - } + public Size Size { get; } /// /// Gets a new representing the center-point of the . /// - public Point Center => new Point(X + (Width / 2.0), Y + (Height / 2.0)); + public Point Center { get; } /// /// Gets a bool indicating if both, the width and the height of the rectangle is greater than zero. /// True if the rectangle has a width or a height of zero; otherwise, false. /// - public bool IsEmpty => (Width <= DoubleExtensions.TOLERANCE) || (Height <= DoubleExtensions.TOLERANCE); + public bool IsEmpty => (Size.Width <= DoubleExtensions.TOLERANCE) || (Size.Height <= DoubleExtensions.TOLERANCE); #endregion #region Constructors - /// - /// - /// Initializes a new instance of the class. - /// - public Rectangle() - : this(new Point(), new Size()) - { } - /// /// /// Initializes a new instance of the class using the provided values for ans . /// - /// The -position of this . - /// The -position of this . - /// The of this . - /// The of this . + /// The x-value of the of this . + /// The y-value of the -position of this . + /// The width of the of this . + /// The height of the of this . public Rectangle(double x, double y, double width, double height) : this(new Point(x, y), new Size(width, height)) { } @@ -170,6 +62,7 @@ namespace RGB.NET.Core { this.Location = location; this.Size = size; + Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); } /// @@ -205,10 +98,10 @@ namespace RGB.NET.Core posY2 = Math.Max(posY2, rectangle.Location.Y + rectangle.Size.Height); } - if (hasPoint) - InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)); - else - InitializeFromPoints(new Point(0, 0), new Point(0, 0)); + (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0)); + Location = location; + Size = size; + Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); } /// @@ -246,82 +139,27 @@ namespace RGB.NET.Core posY2 = Math.Max(posY2, point.Y); } - if (hasPoint) - InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)); - else - InitializeFromPoints(new Point(0, 0), new Point(0, 0)); + (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0)); + + Location = location; + Size = size; + Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); } #endregion #region Methods - private void InitializeFromPoints(Point point1, Point point2) + private static (Point location, Size size) InitializeFromPoints(Point point1, Point point2) { double posX = Math.Min(point1.X, point2.X); double posY = Math.Min(point1.Y, point2.Y); double width = Math.Max(point1.X, point2.X) - posX; double height = Math.Max(point1.Y, point2.Y) - posY; - Location = new Point(posX, posY); - Size = new Size(width, height); + return (new Point(posX, posY), new Size(width, height)); } - /// - /// Calculates the percentage of intersection of a rectangle. - /// - /// The intersecting rectangle. - /// The percentage of intersection. - public double CalculateIntersectPercentage(Rectangle intersectingRect) - { - if (IsEmpty || intersectingRect.IsEmpty) return 0; - - Rectangle intersection = CalculateIntersection(intersectingRect); - return (intersection.Size.Width * intersection.Size.Height) / (Size.Width * Size.Height); - } - - /// - /// Calculates the representing the intersection of this and the one provided as parameter. - /// - /// The intersecting - /// A new representing the intersection this and the one provided as parameter. - public Rectangle CalculateIntersection(Rectangle intersectingRectangle) - { - double x1 = Math.Max(Location.X, intersectingRectangle.Location.X); - double x2 = Math.Min(Location.X + Size.Width, intersectingRectangle.Location.X + intersectingRectangle.Size.Width); - - double y1 = Math.Max(Location.Y, intersectingRectangle.Location.Y); - double y2 = Math.Min(Location.Y + Size.Height, intersectingRectangle.Location.Y + intersectingRectangle.Size.Height); - - if ((x2 >= x1) && (y2 >= y1)) - return new Rectangle(x1, y1, x2 - x1, y2 - y1); - - return new Rectangle(); - } - - /// - /// Determines if the specified is contained within this . - /// - /// The to test. - /// - public bool Contains(Point point) => Contains(point.X, point.Y); - - /// - /// Determines if the specified location is contained within this . - /// - /// The X-location to test. - /// The Y-location to test. - /// - public bool Contains(double x, double y) => (Location.X <= x) && (x < (Location.X + Size.Width)) && (Location.Y <= y) && (y < (Location.Y + Size.Height)); - - /// - /// Determines if the specified is contained within this . - /// - /// The to test. - /// - public bool Contains(Rectangle rect) => (Location.X <= rect.Location.X) && ((rect.Location.X + rect.Size.Width) <= (Location.X + Size.Width)) - && (Location.Y <= rect.Location.Y) && ((rect.Location.Y + rect.Size.Height) <= (Location.Y + Size.Height)); - /// /// Converts the - and -position of this to a human-readable string. /// @@ -338,9 +176,6 @@ namespace RGB.NET.Core if (!(obj is Rectangle compareRect)) return false; - if (ReferenceEquals(this, compareRect)) - return true; - if (GetType() != compareRect.GetType()) return false; @@ -371,7 +206,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. - public static bool operator ==(Rectangle rectangle1, Rectangle rectangle2) => rectangle1?.Equals(rectangle2) ?? ReferenceEquals(rectangle2, null); + public static bool operator ==(Rectangle rectangle1, Rectangle rectangle2) => rectangle1.Equals(rectangle2); /// /// Returns a value that indicates whether two specified are equal. diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index d2933c7..1db3b08 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -33,8 +33,6 @@ namespace RGB.NET.Core private readonly LinkedList _ledGroups = new LinkedList(); - private readonly Rectangle _surfaceRectangle = new Rectangle(); - // ReSharper restore InconsistentNaming /// @@ -50,7 +48,7 @@ namespace RGB.NET.Core /// /// Gets a copy of the representing this . /// - public Rectangle SurfaceRectangle => new Rectangle(_surfaceRectangle); + public Rectangle SurfaceRectangle { get; private set; } /// /// Gets a list of all on this . @@ -162,9 +160,8 @@ namespace RGB.NET.Core case BrushCalculationMode.Relative: Rectangle brushRectangle = new Rectangle(leds.Select(led => led.AbsoluteLedRectangle)); Point offset = new Point(-brushRectangle.Location.X, -brushRectangle.Location.Y); - brushRectangle.Location = new Point(0, 0); - brush.PerformRender(brushRectangle, - leds.Select(x => new BrushRenderTarget(x, GetDeviceLedLocation(x, offset)))); + brushRectangle = brushRectangle.SetLocation(new Point(0, 0)); + brush.PerformRender(brushRectangle, leds.Select(x => new BrushRenderTarget(x, GetDeviceLedLocation(x, offset)))); break; case BrushCalculationMode.Absolute: brush.PerformRender(SurfaceRectangle, leds.Select(x => new BrushRenderTarget(x, x.AbsoluteLedRectangle))); @@ -230,9 +227,7 @@ namespace RGB.NET.Core private void UpdateSurfaceRectangle() { Rectangle devicesRectangle = new Rectangle(_devices.Select(d => new Rectangle(d.Location, d.Size))); - - _surfaceRectangle.Width = devicesRectangle.Location.X + devicesRectangle.Size.Width; - _surfaceRectangle.Height = devicesRectangle.Location.Y + devicesRectangle.Size.Height; + SurfaceRectangle = SurfaceRectangle.SetSize(new Size(devicesRectangle.Location.X + devicesRectangle.Size.Width, devicesRectangle.Location.Y + devicesRectangle.Size.Height)); } /// diff --git a/RGB.NET.Groups/Groups/RectangleLedGroup.cs b/RGB.NET.Groups/Groups/RectangleLedGroup.cs index 63b5616..18ffb8c 100644 --- a/RGB.NET.Groups/Groups/RectangleLedGroup.cs +++ b/RGB.NET.Groups/Groups/RectangleLedGroup.cs @@ -2,7 +2,6 @@ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global // ReSharper disable UnusedMember.Global -using System; using System.Collections.Generic; using System.Linq; using RGB.NET.Core; @@ -28,17 +27,8 @@ namespace RGB.NET.Groups get => _rectangle; set { - Rectangle oldValue = _rectangle; if (SetProperty(ref _rectangle, value)) - { - if (oldValue != null) - oldValue.PropertyChanged -= RectangleChanged; - - if (_rectangle != null) - _rectangle.PropertyChanged += RectangleChanged; - InvalidateCache(); - } } } @@ -110,14 +100,12 @@ namespace RGB.NET.Groups private void RGBSurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args) => InvalidateCache(); - private void RectangleChanged(object sender, EventArgs eventArgs) => InvalidateCache(); - /// /// /// Gets a list containing all of this . /// /// The list containing all of this . - public override IEnumerable GetLeds() => _ledCache ?? (_ledCache = RGBSurface.Instance.Leds.Where(x => x.AbsoluteLedRectangle.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList()); + public override IEnumerable GetLeds() => _ledCache ??= RGBSurface.Instance.Leds.Where(x => x.AbsoluteLedRectangle.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList(); private void InvalidateCache() => _ledCache = null; From 2cf8609173bc0ce380bfa19fa2837bc7de300c37 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 18 Nov 2019 19:59:28 +0100 Subject: [PATCH 06/16] Added Device-Scaling --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 20 ++++++++-- RGB.NET.Core/Devices/IRGBDevice.cs | 2 + RGB.NET.Core/Leds/Led.cs | 29 ++++++++++---- RGB.NET.Core/Positioning/Point.cs | 2 + RGB.NET.Core/Positioning/Scale.cs | 46 ++++++++++++++++++++++ RGB.NET.Core/Positioning/Size.cs | 8 ++++ RGB.NET.Groups/Groups/RectangleLedGroup.cs | 2 +- 7 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 RGB.NET.Core/Positioning/Scale.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 59d0eae..3a418f3 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -31,8 +31,8 @@ namespace RGB.NET.Core /// public Size Size { - get => _size; - set => SetProperty(ref _size, value); + get => _size * Scale; + protected set => SetProperty(ref _size, value); } private Point _location = new Point(0, 0); @@ -43,6 +43,18 @@ namespace RGB.NET.Core set => SetProperty(ref _location, value); } + private Scale _scale = new Scale(1); + /// + public Scale Scale + { + get => _scale; + set + { + if (SetProperty(ref _scale, value)) + OnPropertyChanged(nameof(Size)); + } + } + /// /// Gets or sets if the device needs to be flushed on every update. /// @@ -67,11 +79,11 @@ namespace RGB.NET.Core Led IRGBDevice.this[LedId ledId] => LedMapping.TryGetValue(ledId, out Led led) ? led : null; /// - Led IRGBDevice.this[Point location] => LedMapping.Values.FirstOrDefault(x => x.LedRectangle.Contains(location)); + Led IRGBDevice.this[Point location] => LedMapping.Values.FirstOrDefault(x => x.ActualLedRectangle.Contains(location)); /// IEnumerable IRGBDevice.this[Rectangle referenceRect, double minOverlayPercentage] - => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.LedRectangle) >= minOverlayPercentage); + => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.ActualLedRectangle) >= minOverlayPercentage); #endregion diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index 9ba17c4..9321850 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -27,6 +27,8 @@ namespace RGB.NET.Core /// Gets a copy of the of the whole . /// Size Size { get; } + + Scale Scale { get; set; } /// /// Gets or sets the of the . diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index 27bf4ed..a52cc6d 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -1,6 +1,7 @@ // ReSharper disable MemberCanBePrivate.Global using System; +using System.ComponentModel; using System.Diagnostics; namespace RGB.NET.Core @@ -54,14 +55,19 @@ namespace RGB.NET.Core set { if (SetProperty(ref _ledRectangle, value)) + { + OnPropertyChanged(nameof(ActualLedRectangle)); OnPropertyChanged(nameof(AbsoluteLedRectangle)); + } } } + public Rectangle ActualLedRectangle => new Rectangle(LedRectangle.Location * Device.Scale, LedRectangle.Size * Device.Scale); + /// /// Gets a rectangle representing the physical location of the on the . /// - public Rectangle AbsoluteLedRectangle => (LedRectangle.Location + Device.Location) + new Size(LedRectangle.Size.Width, LedRectangle.Size.Height); + public Rectangle AbsoluteLedRectangle => new Rectangle(ActualLedRectangle.Location + Device.Location, ActualLedRectangle.Size); /// /// Indicates whether the is about to change it's color. @@ -152,17 +158,26 @@ namespace RGB.NET.Core this.LedRectangle = ledRectangle; this.CustomData = customData; - device.PropertyChanged += (sender, args) => - { - OnPropertyChanged(nameof(LedRectangle)); - OnPropertyChanged(nameof(AbsoluteLedRectangle)); - }; + device.PropertyChanged += DevicePropertyChanged; } #endregion #region Methods + private void DevicePropertyChanged(object sender, PropertyChangedEventArgs e) + { + if ((e.PropertyName == nameof(IRGBDevice.Location))) + { + OnPropertyChanged(nameof(AbsoluteLedRectangle)); + } + else if ((e.PropertyName == nameof(IRGBDevice.Scale))) + { + OnPropertyChanged(nameof(ActualLedRectangle)); + OnPropertyChanged(nameof(AbsoluteLedRectangle)); + } + } + /// /// Converts the and the of this to a human-readable string. /// @@ -210,7 +225,7 @@ namespace RGB.NET.Core /// Converts a to a . /// /// The to convert. - public static implicit operator Rectangle(Led led) => led?.LedRectangle ?? new Rectangle(); + public static implicit operator Rectangle(Led led) => led?.ActualLedRectangle ?? new Rectangle(); #endregion } diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs index 58eb2d9..38be165 100644 --- a/RGB.NET.Core/Positioning/Point.cs +++ b/RGB.NET.Core/Positioning/Point.cs @@ -149,6 +149,8 @@ namespace RGB.NET.Core return new Point(point1.X / point2.X, point1.Y / point2.Y); } + public static Point operator *(Point point, Scale scale) => new Point(point.X * scale.Horizontal, point.Y * scale.Vertical); + #endregion } } diff --git a/RGB.NET.Core/Positioning/Scale.cs b/RGB.NET.Core/Positioning/Scale.cs new file mode 100644 index 0000000..42558e5 --- /dev/null +++ b/RGB.NET.Core/Positioning/Scale.cs @@ -0,0 +1,46 @@ +namespace RGB.NET.Core +{ + public struct Scale + { + #region Properties & Fields + + public double Horizontal { get; } + public double Vertical { get; } + + #endregion + + #region Constructors + + public Scale(double scale = 1.0) : this(scale, scale) + { } + + public Scale(double horizontal, double vertical) + { + this.Horizontal = horizontal; + this.Vertical = vertical; + } + + #endregion + + #region Methods + + public bool Equals(Scale other) => Horizontal.EqualsInTolerance(other.Horizontal) && Vertical.EqualsInTolerance(other.Vertical); + public override bool Equals(object obj) => obj is Scale other && Equals(other); + public override int GetHashCode() { unchecked { return (Horizontal.GetHashCode() * 397) ^ Vertical.GetHashCode(); } } + + public void Deconstruct(out double horizontalScale, out double verticalScale) + { + horizontalScale = Horizontal; + verticalScale = Vertical; + } + + #endregion + + #region Operators + + public static implicit operator Scale(double scale) => new Scale(scale); + public static implicit operator Scale((double horizontal, double vertical) scale) => new Scale(scale.horizontal, scale.vertical); + + #endregion + } +} diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs index d6b7c6f..8342c4f 100644 --- a/RGB.NET.Core/Positioning/Size.cs +++ b/RGB.NET.Core/Positioning/Size.cs @@ -94,6 +94,12 @@ namespace RGB.NET.Core } } + public void Deconstruct(out double width, out double height) + { + width = Width; + height = Height; + } + #endregion #region Operators @@ -172,6 +178,8 @@ namespace RGB.NET.Core /// A new representing the division of the and the provided factor. public static Size operator /(Size size, double factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); + public static Size operator *(Size size, Scale scale) => new Size(size.Width * scale.Horizontal, size.Height * scale.Vertical); + #endregion } } diff --git a/RGB.NET.Groups/Groups/RectangleLedGroup.cs b/RGB.NET.Groups/Groups/RectangleLedGroup.cs index 18ffb8c..9958a0d 100644 --- a/RGB.NET.Groups/Groups/RectangleLedGroup.cs +++ b/RGB.NET.Groups/Groups/RectangleLedGroup.cs @@ -59,7 +59,7 @@ namespace RGB.NET.Groups /// (optional) The minimal percentage overlay a must have with the to be taken into the . (default: 0.5) /// (optional) Specifies whether this should be automatically attached or not. (default: true) public RectangleLedGroup(Led fromLed, Led toLed, double minOverlayPercentage = 0.5, bool autoAttach = true) - : this(new Rectangle(fromLed.LedRectangle, toLed.LedRectangle), minOverlayPercentage, autoAttach) + : this(new Rectangle(fromLed.ActualLedRectangle, toLed.ActualLedRectangle), minOverlayPercentage, autoAttach) { } /// From 59d203657e083c9596d8c50cfdd9cb8fde09a7bf Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Tue, 19 Nov 2019 15:34:47 +0100 Subject: [PATCH 07/16] Added ActualSize for devices --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 13 ++++++++++--- RGB.NET.Core/Devices/IRGBDevice.cs | 12 ++++++++++-- RGB.NET.Core/RGBSurface.cs | 2 +- RGB.NET.Core/RGBSurfaceDeviceLoader.cs | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 3a418f3..c12c931 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -31,10 +31,17 @@ namespace RGB.NET.Core /// public Size Size { - get => _size * Scale; - protected set => SetProperty(ref _size, value); + get => _size; + protected set + { + if (SetProperty(ref _size, value)) + OnPropertyChanged(nameof(ActualSize)); + } } + /// + public Size ActualSize => Size * Scale; + private Point _location = new Point(0, 0); /// public Point Location @@ -51,7 +58,7 @@ namespace RGB.NET.Core set { if (SetProperty(ref _scale, value)) - OnPropertyChanged(nameof(Size)); + OnPropertyChanged(nameof(ActualSize)); } } diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index 9321850..07d28ee 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -24,10 +24,18 @@ namespace RGB.NET.Core Point Location { get; set; } /// - /// Gets a copy of the of the whole . + /// Gets the of the . /// Size Size { get; } - + + /// + /// Gets the actual (scaled and rotated) of the . + /// + Size ActualSize { get; } + + /// + /// Gets or sets the scale of the . + /// Scale Scale { get; set; } /// diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index 1db3b08..058eda5 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -226,7 +226,7 @@ namespace RGB.NET.Core private void UpdateSurfaceRectangle() { - Rectangle devicesRectangle = new Rectangle(_devices.Select(d => new Rectangle(d.Location, d.Size))); + Rectangle devicesRectangle = new Rectangle(_devices.Select(d => new Rectangle(d.Location, d.ActualSize))); SurfaceRectangle = SurfaceRectangle.SetSize(new Size(devicesRectangle.Location.X + devicesRectangle.Size.Width, devicesRectangle.Location.Y + devicesRectangle.Size.Height)); } diff --git a/RGB.NET.Core/RGBSurfaceDeviceLoader.cs b/RGB.NET.Core/RGBSurfaceDeviceLoader.cs index b3fe9e6..f233282 100644 --- a/RGB.NET.Core/RGBSurfaceDeviceLoader.cs +++ b/RGB.NET.Core/RGBSurfaceDeviceLoader.cs @@ -63,7 +63,7 @@ namespace RGB.NET.Core foreach (IRGBDevice device in Devices) { device.Location += new Point(posX, 0); - posX += device.Size.Width + 1; + posX += device.ActualSize.Width + 1; } } From fab502e0e4af8e3d30ec643be329f79a883fe906 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 20 Nov 2019 17:05:55 +0100 Subject: [PATCH 08/16] Added device-rotation --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 61 +++++++++++++--- RGB.NET.Core/Devices/IRGBDevice.cs | 7 ++ .../Extensions/RectangleExtensions.cs | 38 ++++++++++ RGB.NET.Core/Leds/Led.cs | 70 +++++++++++++------ RGB.NET.Core/Positioning/Rectangle.cs | 11 ++- RGB.NET.Core/Positioning/Rotation.cs | 54 ++++++++++++++ RGB.NET.Core/RGBSurface.cs | 12 +--- RGB.NET.Groups/Groups/RectangleLedGroup.cs | 4 +- 8 files changed, 212 insertions(+), 45 deletions(-) create mode 100644 RGB.NET.Core/Positioning/Rotation.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index c12c931..8a50ae9 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -27,6 +27,14 @@ namespace RGB.NET.Core /// IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo; + private Point _location = new Point(0, 0); + /// + public Point Location + { + get => _location; + set => SetProperty(ref _location, value); + } + private Size _size = Size.Invalid; /// public Size Size @@ -35,19 +43,22 @@ namespace RGB.NET.Core protected set { if (SetProperty(ref _size, value)) + { OnPropertyChanged(nameof(ActualSize)); + OnPropertyChanged(nameof(DeviceRectangle)); + } } } /// public Size ActualSize => Size * Scale; - private Point _location = new Point(0, 0); - /// - public Point Location + public Rectangle DeviceRectangle { - get => _location; - set => SetProperty(ref _location, value); + get + { + return new Rectangle(Location, new Rectangle(new Rectangle(Location, ActualSize).Rotate(Rotation)).Size); + } } private Scale _scale = new Scale(1); @@ -58,7 +69,24 @@ namespace RGB.NET.Core set { if (SetProperty(ref _scale, value)) + { OnPropertyChanged(nameof(ActualSize)); + OnPropertyChanged(nameof(DeviceRectangle)); + } + } + } + + private Rotation _rotation = new Rotation(0); + /// + public Rotation Rotation + { + get => _rotation; + set + { + if (SetProperty(ref _rotation, value)) + { + OnPropertyChanged(nameof(DeviceRectangle)); + } } } @@ -86,11 +114,11 @@ namespace RGB.NET.Core Led IRGBDevice.this[LedId ledId] => LedMapping.TryGetValue(ledId, out Led led) ? led : null; /// - Led IRGBDevice.this[Point location] => LedMapping.Values.FirstOrDefault(x => x.ActualLedRectangle.Contains(location)); + Led IRGBDevice.this[Point location] => LedMapping.Values.FirstOrDefault(x => x.LedRectangle.Contains(location)); /// IEnumerable IRGBDevice.this[Rectangle referenceRect, double minOverlayPercentage] - => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.ActualLedRectangle) >= minOverlayPercentage); + => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.LedRectangle) >= minOverlayPercentage); #endregion @@ -143,11 +171,21 @@ namespace RGB.NET.Core /// The to initialize. /// The representing the position of the to initialize. /// - protected virtual Led InitializeLed(LedId ledId, Rectangle ledRectangle) + [Obsolete("Use InitializeLed(LedId ledId, Point location, Size size) instead.")] + protected virtual Led InitializeLed(LedId ledId, Rectangle rectangle) => InitializeLed(ledId, rectangle.Location, rectangle.Size); + + /// + /// Initializes the with the specified id. + /// + /// The to initialize. + /// The location of the to initialize. + /// The size of the to initialize. + /// The initialized led. + protected virtual Led InitializeLed(LedId ledId, Point location, Size size) { if ((ledId == LedId.Invalid) || LedMapping.ContainsKey(ledId)) return null; - Led led = new Led(this, ledId, ledRectangle, CreateLedCustomData(ledId)); + Led led = new Led(this, ledId, location, size, CreateLedCustomData(ledId)); LedMapping.Add(ledId, led); return led; } @@ -190,11 +228,12 @@ namespace RGB.NET.Core if (Enum.TryParse(layoutLed.Id, true, out LedId ledId)) { if (!LedMapping.TryGetValue(ledId, out Led led) && createMissingLeds) - led = InitializeLed(ledId, new Rectangle()); + led = InitializeLed(ledId, new Point(), new Size()); if (led != null) { - led.LedRectangle = new Rectangle(new Point(layoutLed.X, layoutLed.Y), new Size(layoutLed.Width, layoutLed.Height)); + led.Location = new Point(layoutLed.X, layoutLed.Y); + led.Size = new Size(layoutLed.Width, layoutLed.Height); led.Shape = layoutLed.Shape; led.ShapeData = layoutLed.ShapeData; diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index 07d28ee..c64f2ef 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -32,12 +32,19 @@ namespace RGB.NET.Core /// Gets the actual (scaled and rotated) of the . /// Size ActualSize { get; } + + Rectangle DeviceRectangle { get; } /// /// Gets or sets the scale of the . /// Scale Scale { get; set; } + /// + /// Gets or sets the rotation of the . + /// + Rotation Rotation { get; set; } + /// /// Gets or sets the of the . /// diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs index 7d2f85a..f16842e 100644 --- a/RGB.NET.Core/Extensions/RectangleExtensions.cs +++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs @@ -110,6 +110,44 @@ namespace RGB.NET.Core public static bool Contains(this Rectangle rect, Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) && (rect.Location.Y <= rect2.Location.Y) && ((rect2.Location.Y + rect2.Size.Height) <= (rect.Location.Y + rect.Size.Height)); + public static Point Translate(this Point point, double x = 0, double y = 0) => new Point(point.X + x, point.Y + y); + + public static Point Rotate(this Point point, Rotation rotation, Point origin = new Point()) + { + double sin = Math.Sin(rotation.Radians); + double cos = Math.Cos(rotation.Radians); + + point = new Point(point.X - origin.X, point.Y - origin.Y); + point = new Point((point.X * cos) - (point.Y * sin), (point.X * sin) + (point.Y * cos)); + return new Point(point.X + origin.X, point.Y + origin.Y); ; + } + + public static Rectangle Translate(this Rectangle rect, Point point) => rect.Translate(point.X, point.Y); + public static Rectangle Translate(this Rectangle rect, double x = 0, double y = 0) => new Rectangle(rect.Location.Translate(x, y), rect.Size); + + public static Point[] Rotate(this Rectangle rect, Rotation rotation, Point origin = new Point()) + { + Point[] points = { + rect.Location, // top left + new Point(rect.Location.X + rect.Size.Width, rect.Location.Y), // top right + new Point(rect.Location.X + rect.Size.Width, rect.Location.Y + rect.Size.Height), // bottom right + new Point(rect.Location.X, rect.Location.Y + rect.Size.Height), // bottom right + }; + + double sin = Math.Sin(rotation.Radians); + double cos = Math.Cos(rotation.Radians); + + for (int i = 0; i < points.Length; i++) + { + Point point = points[i]; + point = new Point(point.X - origin.X, point.Y - origin.Y); + point = new Point((point.X * cos) - (point.Y * sin), (point.X * sin) + (point.Y * cos)); + points[i] = new Point(point.X + origin.X, point.Y + origin.Y); + } + + return points; + } + #endregion } } diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index a52cc6d..d172269 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -45,29 +45,53 @@ namespace RGB.NET.Core set => SetProperty(ref _shapeData, value); } - private Rectangle _ledRectangle; - /// - /// Gets a rectangle representing the physical location of the relative to the . - /// - public Rectangle LedRectangle + public Point Location { get; set; } + + public Size Size { get; set; } + + public Point ActualLocation { - get => _ledRectangle; - set + get { - if (SetProperty(ref _ledRectangle, value)) + Point point = (Location * Device.Scale); + if (!Device.Rotation.Radians.EqualsInTolerance(0)) { - OnPropertyChanged(nameof(ActualLedRectangle)); - OnPropertyChanged(nameof(AbsoluteLedRectangle)); + Point deviceCenter = new Rectangle(Device.ActualSize).Center; + Point actualDeviceCenter = Device.DeviceRectangle.Center; + Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); + point = point.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center) + centerOffset; } + + return point; } } - public Rectangle ActualLedRectangle => new Rectangle(LedRectangle.Location * Device.Scale, LedRectangle.Size * Device.Scale); + public Size ActualSize => Size * Device.Scale; /// - /// Gets a rectangle representing the physical location of the on the . + /// Gets a rectangle representing the logical location of the relative to the . /// - public Rectangle AbsoluteLedRectangle => new Rectangle(ActualLedRectangle.Location + Device.Location, ActualLedRectangle.Size); + public Rectangle LedRectangle + { + get + { + Rectangle rect = new Rectangle(Location * Device.Scale, Size * Device.Scale); + if (!Device.Rotation.Radians.EqualsInTolerance(0)) + { + Point deviceCenter = new Rectangle(Device.ActualSize).Center; + Point actualDeviceCenter = Device.DeviceRectangle.Center; + Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); + rect = new Rectangle(rect.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center)).Translate(centerOffset); + } + + return rect; + } + } + + /// + /// Gets a rectangle representing the logical location of the on the . + /// + public Rectangle AbsoluteLedRectangle => LedRectangle.Translate(Device.Location); /// /// Indicates whether the is about to change it's color. @@ -149,13 +173,15 @@ namespace RGB.NET.Core /// /// The the is associated with. /// The of the . - /// The representing the physical location of the relative to the . + /// The physical location of the relative to the . + /// The size of the . /// The provider-specific data associated with this led. - internal Led(IRGBDevice device, LedId id, Rectangle ledRectangle, object customData = null) + internal Led(IRGBDevice device, LedId id, Point location, Size size, object customData = null) { this.Device = device; this.Id = id; - this.LedRectangle = ledRectangle; + this.Location = location; + this.Size = size; this.CustomData = customData; device.PropertyChanged += DevicePropertyChanged; @@ -171,10 +197,12 @@ namespace RGB.NET.Core { OnPropertyChanged(nameof(AbsoluteLedRectangle)); } - else if ((e.PropertyName == nameof(IRGBDevice.Scale))) + else if ((e.PropertyName == nameof(IRGBDevice.Scale)) || (e.PropertyName == nameof(IRGBDevice.Rotation))) { - OnPropertyChanged(nameof(ActualLedRectangle)); + OnPropertyChanged(nameof(LedRectangle)); OnPropertyChanged(nameof(AbsoluteLedRectangle)); + OnPropertyChanged(nameof(ActualLocation)); + OnPropertyChanged(nameof(ActualSize)); } } @@ -185,7 +213,7 @@ namespace RGB.NET.Core public override string ToString() => $"{Id} {Color}"; /// - /// Updates the to the requested . + /// Updates the to the requested . /// internal void Update() { @@ -199,7 +227,7 @@ namespace RGB.NET.Core } /// - /// Resets the back to default. + /// Resets the back to default. /// internal void Reset() { @@ -225,7 +253,7 @@ namespace RGB.NET.Core /// Converts a to a . /// /// The to convert. - public static implicit operator Rectangle(Led led) => led?.ActualLedRectangle ?? new Rectangle(); + public static implicit operator Rectangle(Led led) => led?.LedRectangle ?? new Rectangle(); #endregion } diff --git a/RGB.NET.Core/Positioning/Rectangle.cs b/RGB.NET.Core/Positioning/Rectangle.cs index 7bf5330..d3b1618 100644 --- a/RGB.NET.Core/Positioning/Rectangle.cs +++ b/RGB.NET.Core/Positioning/Rectangle.cs @@ -53,11 +53,18 @@ namespace RGB.NET.Core : this(new Point(x, y), new Size(width, height)) { } + /// + /// Initializes a new instance of the class using the (0,0) and the given . + /// + /// The size of of this . + public Rectangle(Size size) : this(new Point(), size) + { } + /// /// Initializes a new instance of the class using the given and . /// - /// - /// + /// The location of this of this . + /// The size of of this . public Rectangle(Point location, Size size) { this.Location = location; diff --git a/RGB.NET.Core/Positioning/Rotation.cs b/RGB.NET.Core/Positioning/Rotation.cs new file mode 100644 index 0000000..92e6c5b --- /dev/null +++ b/RGB.NET.Core/Positioning/Rotation.cs @@ -0,0 +1,54 @@ +using System; + +namespace RGB.NET.Core +{ + public struct Rotation + { + #region Constants + + private const double TWO_PI = Math.PI * 2.0; + private const double RADIANS_DEGREES_CONVERSION = 180.0 / Math.PI; + private const double DEGREES_RADIANS_CONVERSION = Math.PI / 180.0; + + #endregion + + #region Properties & Fields + + public double Degrees { get; } + public double Radians { get; } + + #endregion + + #region Constructors + + public Rotation(double degrees) + : this(degrees, degrees * DEGREES_RADIANS_CONVERSION) + { } + + private Rotation(double degrees, double radians) + { + this.Degrees = degrees % 360.0; + this.Radians = radians % TWO_PI; + } + + #endregion + + #region Methods + + public static Rotation FromDegrees(double degrees) => new Rotation(degrees); + public static Rotation FromRadians(double radians) => new Rotation(radians * RADIANS_DEGREES_CONVERSION, radians); + + public bool Equals(Rotation other) => Degrees.EqualsInTolerance(other.Degrees); + public override bool Equals(object obj) => obj is Rotation other && Equals(other); + public override int GetHashCode() => Degrees.GetHashCode(); + + #endregion + + #region Operators + + public static implicit operator Rotation(double rotation) => new Rotation(rotation); + public static implicit operator double(Rotation rotation) => rotation.Degrees; + + #endregion + } +} diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index 058eda5..7ba3183 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -161,10 +161,10 @@ namespace RGB.NET.Core Rectangle brushRectangle = new Rectangle(leds.Select(led => led.AbsoluteLedRectangle)); Point offset = new Point(-brushRectangle.Location.X, -brushRectangle.Location.Y); brushRectangle = brushRectangle.SetLocation(new Point(0, 0)); - brush.PerformRender(brushRectangle, leds.Select(x => new BrushRenderTarget(x, GetDeviceLedLocation(x, offset)))); + brush.PerformRender(brushRectangle, leds.Select(led => new BrushRenderTarget(led, led.AbsoluteLedRectangle.Translate(offset)))); break; case BrushCalculationMode.Absolute: - brush.PerformRender(SurfaceRectangle, leds.Select(x => new BrushRenderTarget(x, x.AbsoluteLedRectangle))); + brush.PerformRender(SurfaceRectangle, leds.Select(led => new BrushRenderTarget(led, led.AbsoluteLedRectangle))); break; default: throw new ArgumentException(); @@ -177,12 +177,6 @@ namespace RGB.NET.Core renders.Key.Led.Color = renders.Value; } - private Rectangle GetDeviceLedLocation(Led led, Point extraOffset) - { - Rectangle absoluteRectangle = led.AbsoluteLedRectangle; - return (absoluteRectangle.Location + extraOffset) + absoluteRectangle.Size; - } - /// /// Attaches the given . /// @@ -226,7 +220,7 @@ namespace RGB.NET.Core private void UpdateSurfaceRectangle() { - Rectangle devicesRectangle = new Rectangle(_devices.Select(d => new Rectangle(d.Location, d.ActualSize))); + Rectangle devicesRectangle = new Rectangle(_devices.Select(d => d.DeviceRectangle)); SurfaceRectangle = SurfaceRectangle.SetSize(new Size(devicesRectangle.Location.X + devicesRectangle.Size.Width, devicesRectangle.Location.Y + devicesRectangle.Size.Height)); } diff --git a/RGB.NET.Groups/Groups/RectangleLedGroup.cs b/RGB.NET.Groups/Groups/RectangleLedGroup.cs index 9958a0d..1b23c26 100644 --- a/RGB.NET.Groups/Groups/RectangleLedGroup.cs +++ b/RGB.NET.Groups/Groups/RectangleLedGroup.cs @@ -59,7 +59,7 @@ namespace RGB.NET.Groups /// (optional) The minimal percentage overlay a must have with the to be taken into the . (default: 0.5) /// (optional) Specifies whether this should be automatically attached or not. (default: true) public RectangleLedGroup(Led fromLed, Led toLed, double minOverlayPercentage = 0.5, bool autoAttach = true) - : this(new Rectangle(fromLed.ActualLedRectangle, toLed.ActualLedRectangle), minOverlayPercentage, autoAttach) + : this(new Rectangle(fromLed.LedRectangle, toLed.LedRectangle), minOverlayPercentage, autoAttach) { } /// @@ -105,7 +105,7 @@ namespace RGB.NET.Groups /// Gets a list containing all of this . /// /// The list containing all of this . - public override IEnumerable GetLeds() => _ledCache ??= RGBSurface.Instance.Leds.Where(x => x.AbsoluteLedRectangle.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList(); + public override IEnumerable GetLeds() => _ledCache ??= RGBSurface.Instance.Leds.Where(led => led.AbsoluteLedRectangle.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList(); private void InvalidateCache() => _ledCache = null; From 1126408069377af0a426eac126cac1e8b3c26ef9 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 20 Nov 2019 17:33:07 +0100 Subject: [PATCH 09/16] Added caching for actual layout data --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 34 +++---- RGB.NET.Core/Leds/Led.cs | 108 ++++++++++++++-------- RGB.NET.Core/Positioning/Rotation.cs | 2 + 3 files changed, 92 insertions(+), 52 deletions(-) diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 8a50ae9..e1f9e10 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -43,22 +43,23 @@ namespace RGB.NET.Core protected set { if (SetProperty(ref _size, value)) - { - OnPropertyChanged(nameof(ActualSize)); - OnPropertyChanged(nameof(DeviceRectangle)); - } + UpdateActualData(); } } + private Size _actualSize; /// - public Size ActualSize => Size * Scale; + public Size ActualSize + { + get => _actualSize; + private set => SetProperty(ref _actualSize, value); + } + private Rectangle _deviceRectangle; public Rectangle DeviceRectangle { - get - { - return new Rectangle(Location, new Rectangle(new Rectangle(Location, ActualSize).Rotate(Rotation)).Size); - } + get => _deviceRectangle; + private set => SetProperty(ref _deviceRectangle, value); } private Scale _scale = new Scale(1); @@ -69,10 +70,7 @@ namespace RGB.NET.Core set { if (SetProperty(ref _scale, value)) - { - OnPropertyChanged(nameof(ActualSize)); - OnPropertyChanged(nameof(DeviceRectangle)); - } + UpdateActualData(); } } @@ -84,9 +82,7 @@ namespace RGB.NET.Core set { if (SetProperty(ref _rotation, value)) - { - OnPropertyChanged(nameof(DeviceRectangle)); - } + UpdateActualData(); } } @@ -126,6 +122,12 @@ namespace RGB.NET.Core #region Methods + private void UpdateActualData() + { + ActualSize = Size * Scale; + DeviceRectangle = new Rectangle(Location, new Rectangle(new Rectangle(Location, ActualSize).Rotate(Rotation)).Size); + } + /// public virtual void Update(bool flushLeds = false) { diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index d172269..a514d80 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -45,53 +45,67 @@ namespace RGB.NET.Core set => SetProperty(ref _shapeData, value); } - public Point Location { get; set; } - - public Size Size { get; set; } - - public Point ActualLocation + private Point _location; + public Point Location { - get + get => _location; + set { - Point point = (Location * Device.Scale); - if (!Device.Rotation.Radians.EqualsInTolerance(0)) + if (SetProperty(ref _location, value)) { - Point deviceCenter = new Rectangle(Device.ActualSize).Center; - Point actualDeviceCenter = Device.DeviceRectangle.Center; - Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); - point = point.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center) + centerOffset; + UpdateActualData(); + UpdateAbsoluteData(); } - - return point; } } - public Size ActualSize => Size * Device.Scale; + private Size _size; + public Size Size + { + get => _size; + set + { + if (SetProperty(ref _size, value)) + { + UpdateActualData(); + UpdateAbsoluteData(); + } + } + } + private Point _actualLocation; + public Point ActualLocation + { + get => _actualLocation; + private set => SetProperty(ref _actualLocation, value); + } + + private Size _actualSize; + public Size ActualSize + { + get => _actualSize; + private set => SetProperty(ref _actualSize, value); + } + + private Rectangle _ledRectangle; /// /// Gets a rectangle representing the logical location of the relative to the . /// public Rectangle LedRectangle { - get - { - Rectangle rect = new Rectangle(Location * Device.Scale, Size * Device.Scale); - if (!Device.Rotation.Radians.EqualsInTolerance(0)) - { - Point deviceCenter = new Rectangle(Device.ActualSize).Center; - Point actualDeviceCenter = Device.DeviceRectangle.Center; - Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); - rect = new Rectangle(rect.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center)).Translate(centerOffset); - } - - return rect; - } + get => _ledRectangle; + private set => SetProperty(ref _ledRectangle, value); } + private Rectangle _absoluteLedRectangle; /// /// Gets a rectangle representing the logical location of the on the . /// - public Rectangle AbsoluteLedRectangle => LedRectangle.Translate(Device.Location); + public Rectangle AbsoluteLedRectangle + { + get => _absoluteLedRectangle; + private set => SetProperty(ref _absoluteLedRectangle, value); + } /// /// Indicates whether the is about to change it's color. @@ -194,18 +208,40 @@ namespace RGB.NET.Core private void DevicePropertyChanged(object sender, PropertyChangedEventArgs e) { if ((e.PropertyName == nameof(IRGBDevice.Location))) - { - OnPropertyChanged(nameof(AbsoluteLedRectangle)); - } + UpdateAbsoluteData(); else if ((e.PropertyName == nameof(IRGBDevice.Scale)) || (e.PropertyName == nameof(IRGBDevice.Rotation))) { - OnPropertyChanged(nameof(LedRectangle)); - OnPropertyChanged(nameof(AbsoluteLedRectangle)); - OnPropertyChanged(nameof(ActualLocation)); - OnPropertyChanged(nameof(ActualSize)); + UpdateActualData(); + UpdateAbsoluteData(); } } + private void UpdateActualData() + { + ActualSize = Size * Device.Scale; + + Point actualLocation = (Location * Device.Scale); + Rectangle ledRectangle = new Rectangle(Location * Device.Scale, Size * Device.Scale); + + if (Device.Rotation.IsRotated) + { + Point deviceCenter = new Rectangle(Device.ActualSize).Center; + Point actualDeviceCenter = Device.DeviceRectangle.Center; + Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); + + actualLocation = actualLocation.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center) + centerOffset; + ledRectangle = new Rectangle(ledRectangle.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center)).Translate(centerOffset); + } + + ActualLocation = actualLocation; + LedRectangle = ledRectangle; + } + + private void UpdateAbsoluteData() + { + AbsoluteLedRectangle = LedRectangle.Translate(Device.Location); + } + /// /// Converts the and the of this to a human-readable string. /// diff --git a/RGB.NET.Core/Positioning/Rotation.cs b/RGB.NET.Core/Positioning/Rotation.cs index 92e6c5b..aca7f87 100644 --- a/RGB.NET.Core/Positioning/Rotation.cs +++ b/RGB.NET.Core/Positioning/Rotation.cs @@ -17,6 +17,8 @@ namespace RGB.NET.Core public double Degrees { get; } public double Radians { get; } + public bool IsRotated => !Degrees.EqualsInTolerance(0); + #endregion #region Constructors From 1d727e16b09d8216aa6fdae54854aeca48430e1a Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 20 Nov 2019 17:44:14 +0100 Subject: [PATCH 10/16] Fixed led actual-data update --- RGB.NET.Core/Leds/Led.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index a514d80..07ed513 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -209,7 +209,7 @@ namespace RGB.NET.Core { if ((e.PropertyName == nameof(IRGBDevice.Location))) UpdateAbsoluteData(); - else if ((e.PropertyName == nameof(IRGBDevice.Scale)) || (e.PropertyName == nameof(IRGBDevice.Rotation))) + else if (e.PropertyName == nameof(IRGBDevice.DeviceRectangle)) { UpdateActualData(); UpdateAbsoluteData(); From ac8ec602dd55964860070c6c1d6e9ef94cbb2254 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 20 Nov 2019 20:44:12 +0100 Subject: [PATCH 11/16] Added missing operators and documentation --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 1 + RGB.NET.Core/Devices/IRGBDevice.cs | 8 +- RGB.NET.Core/Extensions/PointExtensions.cs | 37 ++++++ .../Extensions/RectangleExtensions.cs | 50 +++++--- RGB.NET.Core/Leds/Led.cs | 14 +++ RGB.NET.Core/Positioning/Point.cs | 6 + RGB.NET.Core/Positioning/Rotation.cs | 108 +++++++++++++++++- RGB.NET.Core/Positioning/Scale.cs | 102 ++++++++++++++++- RGB.NET.Core/Positioning/Size.cs | 11 ++ 9 files changed, 315 insertions(+), 22 deletions(-) create mode 100644 RGB.NET.Core/Extensions/PointExtensions.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index e1f9e10..cd76493 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -56,6 +56,7 @@ namespace RGB.NET.Core } private Rectangle _deviceRectangle; + /// public Rectangle DeviceRectangle { get => _deviceRectangle; diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index c64f2ef..23278ba 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -29,10 +29,14 @@ namespace RGB.NET.Core Size Size { get; } /// - /// Gets the actual (scaled and rotated) of the . + /// Gets the actual of the . + /// This includes the . /// Size ActualSize { get; } - + + /// + /// Gets a representing the logical location of the relative to the . + /// Rectangle DeviceRectangle { get; } /// diff --git a/RGB.NET.Core/Extensions/PointExtensions.cs b/RGB.NET.Core/Extensions/PointExtensions.cs new file mode 100644 index 0000000..7c413e9 --- /dev/null +++ b/RGB.NET.Core/Extensions/PointExtensions.cs @@ -0,0 +1,37 @@ +using System; + +namespace RGB.NET.Core +{ + public static class PointExtensions + { + #region Methods + + /// + /// Moves the specified by the given amount. + /// + /// The to move. + /// The x-ammount to move. + /// The y-ammount to move. + /// The new location of the point. + public static Point Translate(this Point point, double x = 0, double y = 0) => new Point(point.X + x, point.Y + y); + + /// + /// Rotates the specified by the given amuont around the given origin. + /// + /// The to rotate. + /// The rotation. + /// The origin to rotate around. [0,0] if not set. + /// The new location of the point. + public static Point Rotate(this Point point, Rotation rotation, Point origin = new Point()) + { + double sin = Math.Sin(rotation.Radians); + double cos = Math.Cos(rotation.Radians); + + point = new Point(point.X - origin.X, point.Y - origin.Y); + point = new Point((point.X * cos) - (point.Y * sin), (point.X * sin) + (point.Y * cos)); + return new Point(point.X + origin.X, point.Y + origin.Y); ; + } + + #endregion + } +} diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs index f16842e..aae9b04 100644 --- a/RGB.NET.Core/Extensions/RectangleExtensions.cs +++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs @@ -90,7 +90,7 @@ namespace RGB.NET.Core /// Determines if the specified is contained within this . /// /// The to test. - /// + /// true if the rectangle contains the given point; otherwise false. public static bool Contains(this Rectangle rect, Point point) => rect.Contains(point.X, point.Y); /// @@ -98,33 +98,49 @@ namespace RGB.NET.Core /// /// The X-location to test. /// The Y-location to test. - /// + /// true if the rectangle contains the given coordinates; otherwise false. public static bool Contains(this Rectangle rect, double x, double y) => (rect.Location.X <= x) && (x < (rect.Location.X + rect.Size.Width)) - && (rect.Location.Y <= y) && (y < (rect.Location.Y + rect.Size.Height)); + && (rect.Location.Y <= y) && (y < (rect.Location.Y + rect.Size.Height)); /// /// Determines if the specified is contained within this . /// /// The to test. - /// + /// true if the rectangle contains the given rect; otherwise false. public static bool Contains(this Rectangle rect, Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) - && (rect.Location.Y <= rect2.Location.Y) && ((rect2.Location.Y + rect2.Size.Height) <= (rect.Location.Y + rect.Size.Height)); - - public static Point Translate(this Point point, double x = 0, double y = 0) => new Point(point.X + x, point.Y + y); - - public static Point Rotate(this Point point, Rotation rotation, Point origin = new Point()) - { - double sin = Math.Sin(rotation.Radians); - double cos = Math.Cos(rotation.Radians); - - point = new Point(point.X - origin.X, point.Y - origin.Y); - point = new Point((point.X * cos) - (point.Y * sin), (point.X * sin) + (point.Y * cos)); - return new Point(point.X + origin.X, point.Y + origin.Y); ; - } + && (rect.Location.Y <= rect2.Location.Y) && ((rect2.Location.Y + rect2.Size.Height) <= (rect.Location.Y + rect.Size.Height)); + /// + /// Moves the specified by the given amount. + /// + /// The to move. + /// The amount to move. + /// The moved rectangle. public static Rectangle Translate(this Rectangle rect, Point point) => rect.Translate(point.X, point.Y); + + /// + /// Moves the specified by the given amount. + /// + /// The to move. + /// The x-ammount to move. + /// The y-ammount to move. + /// The moved rectangle. public static Rectangle Translate(this Rectangle rect, double x = 0, double y = 0) => new Rectangle(rect.Location.Translate(x, y), rect.Size); + /// + /// Rotates the specified by the given amuont around the given origin. + /// + /// + /// The returned array of is filled with the new locations of the rectangle clockwise starting from the top left: + /// [0] = top left + /// [1] = top right + /// [2] = bottom right + /// [3] = bottom left + /// + /// The to rotate. + /// The rotation. + /// The origin to rotate around. [0,0] if not set. + /// A array of containing the new locations of the corners of the original rectangle. public static Point[] Rotate(this Rectangle rect, Rotation rotation, Point origin = new Point()) { Point[] points = { diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index 07ed513..8b6b310 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -46,6 +46,9 @@ namespace RGB.NET.Core } private Point _location; + /// + /// Gets or sets the relative location of the . + /// public Point Location { get => _location; @@ -60,6 +63,9 @@ namespace RGB.NET.Core } private Size _size; + /// + /// Gets or sets the size of the . + /// public Size Size { get => _size; @@ -74,6 +80,10 @@ namespace RGB.NET.Core } private Point _actualLocation; + /// + /// Gets the actual location of the . + /// This includes device-scaling and rotation. + /// public Point ActualLocation { get => _actualLocation; @@ -81,6 +91,10 @@ namespace RGB.NET.Core } private Size _actualSize; + /// + /// Gets the actual location of the . + /// This includes device-scaling. + /// public Size ActualSize { get => _actualSize; diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs index 38be165..9583863 100644 --- a/RGB.NET.Core/Positioning/Point.cs +++ b/RGB.NET.Core/Positioning/Point.cs @@ -149,6 +149,12 @@ namespace RGB.NET.Core return new Point(point1.X / point2.X, point1.Y / point2.Y); } + /// + /// Returns a new representing the multiplication of the and the provided . + /// + /// The . + /// The . + /// A new representing the multiplication of the and the provided . public static Point operator *(Point point, Scale scale) => new Point(point.X * scale.Horizontal, point.Y * scale.Vertical); #endregion diff --git a/RGB.NET.Core/Positioning/Rotation.cs b/RGB.NET.Core/Positioning/Rotation.cs index aca7f87..0f638ec 100644 --- a/RGB.NET.Core/Positioning/Rotation.cs +++ b/RGB.NET.Core/Positioning/Rotation.cs @@ -1,7 +1,15 @@ -using System; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global + +using System; +using System.Diagnostics; namespace RGB.NET.Core { + /// + /// Represents an angular rotation. + /// + [DebuggerDisplay("[{Degrees}°]")] public struct Rotation { #region Constants @@ -14,15 +22,29 @@ namespace RGB.NET.Core #region Properties & Fields + /// + /// Gets the angle in degrees. + /// public double Degrees { get; } + + /// + /// Gets the angle in radians. + /// public double Radians { get; } + /// + /// Gets a bool indicating if the rotation is > 0. + /// public bool IsRotated => !Degrees.EqualsInTolerance(0); #endregion #region Constructors + /// + /// Initializes a new instance of the class using the provided values. + /// + /// The rotation in degrees. public Rotation(double degrees) : this(degrees, degrees * DEGREES_RADIANS_CONVERSION) { } @@ -37,18 +59,102 @@ namespace RGB.NET.Core #region Methods + /// + /// Creates a new Rotation out of the given degree-angle. + /// + /// The angle in degrees. + /// The new rotation. public static Rotation FromDegrees(double degrees) => new Rotation(degrees); + + /// + /// Creates a new Rotation out of the given radian-angle. + /// + /// The angle in radians. + /// The new rotation. public static Rotation FromRadians(double radians) => new Rotation(radians * RADIANS_DEGREES_CONVERSION, radians); + /// + /// Tests whether the specified is equivalent to this . + /// + /// The rotation to test. + /// true if is equivalent to this ; otherwise, false. public bool Equals(Rotation other) => Degrees.EqualsInTolerance(other.Degrees); + + /// + /// Tests whether the specified object is a and is equivalent to this . + /// + /// The object to test. + /// true if is a equivalent to this ; otherwise, false. public override bool Equals(object obj) => obj is Rotation other && Equals(other); + + /// + /// Returns a hash code for this . + /// + /// An integer value that specifies the hash code for this . public override int GetHashCode() => Degrees.GetHashCode(); #endregion #region Operators + /// + /// Returns a value that indicates whether two specified are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool operator ==(Rotation rotation1, Rotation rotation2) => rotation1.Equals(rotation2); + + /// + /// Returns a value that indicates whether two specified are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are not equal; otherwise, false. + public static bool operator !=(Rotation rotation1, Rotation rotation2) => !(rotation1 == rotation2); + + /// + /// Returns a new representing the addition of the and the provided value. + /// + /// The . + /// The value to add. + /// A new representing the addition of the and the provided value. + public static Rotation operator +(Rotation rotation, double value) => new Rotation(rotation.Degrees + value); + + /// + /// Returns a new representing the subtraction of the and the provided value. + /// + /// The . + /// The value to substract. + /// A new representing the subtraction of the and the provided value. + public static Rotation operator -(Rotation rotation, double value) => new Rotation(rotation.Degrees - value); + + /// + /// Returns a new representing the multiplication of the and the provided value. + /// + /// The . + /// The value to multiply with. + /// A new representing the multiplication of the and the provided value. + public static Rotation operator *(Rotation rotation, double value) => new Rotation(rotation.Degrees * value); + + /// + /// Returns a new representing the division of the and the provided value. + /// + /// The . + /// The value to device with. + /// A new representing the division of the and the provided value. + public static Rotation operator /(Rotation rotation, double value) => value.EqualsInTolerance(0) ? new Rotation(0) : new Rotation(rotation.Degrees / value); + + /// + /// Converts a double to a . + /// + /// The rotation in degrees to convert. public static implicit operator Rotation(double rotation) => new Rotation(rotation); + + /// + /// Converts to a double representing the rotation in degrees. + /// + /// The rotatio to convert. public static implicit operator double(Rotation rotation) => rotation.Degrees; #endregion diff --git a/RGB.NET.Core/Positioning/Scale.cs b/RGB.NET.Core/Positioning/Scale.cs index 42558e5..04b8f09 100644 --- a/RGB.NET.Core/Positioning/Scale.cs +++ b/RGB.NET.Core/Positioning/Scale.cs @@ -1,19 +1,44 @@ -namespace RGB.NET.Core +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global + +using System.Diagnostics; + +namespace RGB.NET.Core { + /// + /// Represents a scaling. + /// + [DebuggerDisplay("[Horizontal: {Horizontal}, Vertical: {Vertical}]")] public struct Scale { #region Properties & Fields + /// + /// Gets the horizontal scaling value. + /// public double Horizontal { get; } + + /// + /// Gets the vertical scaling value. + /// public double Vertical { get; } #endregion #region Constructors + /// + /// Initializes a new instance of the class using the provided values. + /// + /// The value used for horizontal and vertical scaling. 0 if not set. public Scale(double scale = 1.0) : this(scale, scale) { } + /// + /// Initializes a new instance of the class using the provided values. + /// + /// The value used for horizontal scaling. + /// The value used for vertical scaling. public Scale(double horizontal, double vertical) { this.Horizontal = horizontal; @@ -24,10 +49,31 @@ #region Methods + /// + /// Tests whether the specified is equivalent to this . + /// + /// The scale to test. + /// true if is equivalent to this ; otherwise, false. public bool Equals(Scale other) => Horizontal.EqualsInTolerance(other.Horizontal) && Vertical.EqualsInTolerance(other.Vertical); + + /// + /// Tests whether the specified object is a and is equivalent to this . + /// + /// The object to test. + /// true if is a equivalent to this ; otherwise, false. public override bool Equals(object obj) => obj is Scale other && Equals(other); + + /// + /// Returns a hash code for this . + /// + /// An integer value that specifies the hash code for this . public override int GetHashCode() { unchecked { return (Horizontal.GetHashCode() * 397) ^ Vertical.GetHashCode(); } } + /// + /// Deconstructs the scale into the horizontal and vertical value. + /// + /// The horizontal scaling value. + /// The vertical scaling value. public void Deconstruct(out double horizontalScale, out double verticalScale) { horizontalScale = Horizontal; @@ -38,8 +84,60 @@ #region Operators + /// + /// Returns a value that indicates whether two specified are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool operator ==(Scale scale1, Scale scale2) => scale1.Equals(scale2); + + /// + /// Returns a value that indicates whether two specified are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are not equal; otherwise, false. + public static bool operator !=(Scale scale1, Scale scale2) => !(scale1 == scale2); + + /// + /// Returns a new representing the addition of the and the provided value. + /// + /// The . + /// The value to add. + /// A new representing the addition of the and the provided value. + public static Scale operator +(Scale scale, double value) => new Scale(scale.Horizontal + value, scale.Vertical + value); + + /// + /// Returns a new representing the subtraction of the and the provided value. + /// + /// The . + /// The value to substract. + /// A new representing the subtraction of the and the provided value. + public static Scale operator -(Scale scale, double value) => new Scale(scale.Horizontal - value, scale.Vertical - value); + + /// + /// Returns a new representing the multiplication of the and the provided value. + /// + /// The . + /// The value to multiply with. + /// A new representing the multiplication of the and the provided value. + public static Scale operator *(Scale scale, double value) => new Scale(scale.Horizontal * value, scale.Vertical * value); + + /// + /// Returns a new representing the division of the and the provided value. + /// + /// The . + /// The value to device with. + /// A new representing the division of the and the provided value. + public static Scale operator /(Scale scale, double value) => value.EqualsInTolerance(0) ? new Scale(0) : new Scale(scale.Horizontal / value, scale.Vertical / value); + + + /// + /// Converts a double to a . + /// + /// The scale value to convert. public static implicit operator Scale(double scale) => new Scale(scale); - public static implicit operator Scale((double horizontal, double vertical) scale) => new Scale(scale.horizontal, scale.vertical); #endregion } diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs index 8342c4f..74f9153 100644 --- a/RGB.NET.Core/Positioning/Size.cs +++ b/RGB.NET.Core/Positioning/Size.cs @@ -94,6 +94,11 @@ namespace RGB.NET.Core } } + /// + /// Deconstructs the size into the width and height value. + /// + /// The width. + /// The height. public void Deconstruct(out double width, out double height) { width = Width; @@ -178,6 +183,12 @@ namespace RGB.NET.Core /// A new representing the division of the and the provided factor. public static Size operator /(Size size, double factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); + /// + /// Returns a new representing the multiplication of the and the given . + /// + /// The to scale. + /// The scaling factor. + /// A new representing the multiplication of the and the given . public static Size operator *(Size size, Scale scale) => new Size(size.Width * scale.Horizontal, size.Height * scale.Vertical); #endregion From a3d9c6d16d71b96ed0e54f5098ddd9b63ed63def Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 21 Nov 2019 00:09:21 +0100 Subject: [PATCH 12/16] Fixed translation issue of devices not aligned to the surface origin --- RGB.NET.Core/Leds/Led.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index 8b6b310..c296633 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -240,7 +240,7 @@ namespace RGB.NET.Core if (Device.Rotation.IsRotated) { Point deviceCenter = new Rectangle(Device.ActualSize).Center; - Point actualDeviceCenter = Device.DeviceRectangle.Center; + Point actualDeviceCenter = new Rectangle(Device.DeviceRectangle.Size).Center; Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); actualLocation = actualLocation.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center) + centerOffset; From 09e514c813de7f935857af844f130263eb13f4b4 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 21 Nov 2019 20:38:38 +0100 Subject: [PATCH 13/16] Prevented concurrent list operations when modifying decorators --- RGB.NET.Core/Brushes/AbstractBrush.cs | 7 +++-- .../Decorators/AbstractDecorateable.cs | 30 +++++++++++++++---- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/RGB.NET.Core/Brushes/AbstractBrush.cs b/RGB.NET.Core/Brushes/AbstractBrush.cs index 0c6591a..7e36afc 100644 --- a/RGB.NET.Core/Brushes/AbstractBrush.cs +++ b/RGB.NET.Core/Brushes/AbstractBrush.cs @@ -78,9 +78,10 @@ namespace RGB.NET.Core /// The to be modified. protected virtual Color ApplyDecorators(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) { - foreach (IBrushDecorator decorator in Decorators) - if (decorator.IsEnabled) - color = decorator.ManipulateColor(rectangle, renderTarget, color); + lock (Decorators) + foreach (IBrushDecorator decorator in Decorators) + if (decorator.IsEnabled) + color = decorator.ManipulateColor(rectangle, renderTarget, color); return color; } diff --git a/RGB.NET.Core/Decorators/AbstractDecorateable.cs b/RGB.NET.Core/Decorators/AbstractDecorateable.cs index a9c5560..94b8f05 100644 --- a/RGB.NET.Core/Decorators/AbstractDecorateable.cs +++ b/RGB.NET.Core/Decorators/AbstractDecorateable.cs @@ -11,11 +11,20 @@ namespace RGB.NET.Core { #region Properties & Fields - private List _decorators = new List(); + private readonly List _decorators = new List(); /// /// Gets a readonly-list of all attached to this . /// - protected IReadOnlyCollection Decorators => new ReadOnlyCollection(_decorators); + protected IReadOnlyCollection Decorators { get; } + + #endregion + + #region Constructors + + protected AbstractDecoratable() + { + Decorators = new ReadOnlyCollection(_decorators); + } #endregion @@ -24,8 +33,11 @@ namespace RGB.NET.Core /// public void AddDecorator(T decorator) { - _decorators.Add(decorator); - _decorators = _decorators.OrderByDescending(x => x.Order).ToList(); + lock (Decorators) + { + _decorators.Add(decorator); + _decorators.Sort((d1, d2) => d1.Order.CompareTo(d2.Order)); + } decorator.OnAttached(this); } @@ -33,7 +45,8 @@ namespace RGB.NET.Core /// public void RemoveDecorator(T decorator) { - _decorators.Remove(decorator); + lock (Decorators) + _decorators.Remove(decorator); decorator.OnDetached(this); } @@ -41,7 +54,12 @@ namespace RGB.NET.Core /// public void RemoveAllDecorators() { - foreach (T decorator in Decorators.ToList()) + IEnumerable decorators; + + lock (Decorators) + decorators = Decorators.ToList(); + + foreach (T decorator in decorators) RemoveDecorator(decorator); } From 9258e9286e8251bc64da1b387452bfa21a87ab97 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 21 Nov 2019 20:49:56 +0100 Subject: [PATCH 14/16] Added HID for G502 Hero Fixes #84 --- RGB.NET.Devices.Logitech/HID/DeviceChecker.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/RGB.NET.Devices.Logitech/HID/DeviceChecker.cs b/RGB.NET.Devices.Logitech/HID/DeviceChecker.cs index 5455ec3..db8209d 100644 --- a/RGB.NET.Devices.Logitech/HID/DeviceChecker.cs +++ b/RGB.NET.Devices.Logitech/HID/DeviceChecker.cs @@ -30,6 +30,7 @@ namespace RGB.NET.Devices.Logitech.HID ("G19", RGBDeviceType.Keyboard, 0xC228, 0, "DE", @"Keyboards\G19\UK"), ("G19s", RGBDeviceType.Keyboard, 0xC229, 0, "DE", @"Keyboards\G19s\UK"), ("G502", RGBDeviceType.Mouse, 0xC332, 0, "default", @"Mice\G502"), + ("G502 HERO", RGBDeviceType.Mouse, 0xC08B, 0, "default", @"Mice\G502"), ("G600", RGBDeviceType.Mouse, 0xC24A, 0, "default", @"Mice\G600"), ("G300s", RGBDeviceType.Mouse, 0xC246, 0, "default", @"Mice\G300s"), ("G510", RGBDeviceType.Keyboard, 0xC22D, 0, "DE", @"Keyboards\G510\UK"), From 638a833e1d4ede11a3f6480293fe0e01652fe9fd Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 22 Nov 2019 20:42:58 +0100 Subject: [PATCH 15/16] Fixed typo --- RGB.NET.Core/Leds/Led.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index c296633..67cea33 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -92,7 +92,7 @@ namespace RGB.NET.Core private Size _actualSize; /// - /// Gets the actual location of the . + /// Gets the actual size of the . /// This includes device-scaling. /// public Size ActualSize From 50532637ab123ca7ae7c1d13fd39666b6efc318d Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sun, 24 Nov 2019 16:30:38 +0100 Subject: [PATCH 16/16] Added new steelseries device-zones; prevent update-spam in steelseries updatetrigger --- .../Enum/SteelSeriesDeviceType.cs | 14 +- .../Enum/SteelSeriesLedId.cs | 186 ++++++++++++++++++ .../Generic/SteelSeriesDeviceUpdateTrigger.cs | 13 +- 3 files changed, 209 insertions(+), 4 deletions(-) diff --git a/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs b/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs index 83152c0..65ee724 100644 --- a/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs +++ b/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs @@ -27,6 +27,18 @@ SevenZone, [APIName("rgb-8-zone")] - EightZone + EightZone, + + [APIName("rgb-12-zone")] + TwelveZone, + + [APIName("rgb-17-zone")] + SeventeenZone, + + [APIName("rgb-24-zone")] + TwentyfourZone, + + [APIName("rgb-103-zone")] + OneHundredAndThreeZone } } diff --git a/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs b/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs index a7636aa..4c3baa1 100644 --- a/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs +++ b/RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs @@ -22,6 +22,192 @@ ZoneNine, [APIName("ten")] ZoneTen, + [APIName("eleven")] + ZoneEleven, + [APIName("twelve")] + ZoneTwelve, + [APIName("thirteen")] + ZoneThirteen, + [APIName("fourteen")] + ZoneFourteen, + [APIName("fifteen")] + ZoneFifteen, + [APIName("sixteen")] + ZoneSixteen, + [APIName("seventeen")] + ZoneSeventeen, + [APIName("eighteen")] + ZoneEighteen, + [APIName("nineteen")] + ZoneNineteen, + [APIName("twenty")] + ZoneTwenty, + [APIName("twenty-one")] + ZoneTwentyOne, + [APIName("twenty-two")] + ZoneTwentyTwo, + [APIName("twenty-three")] + ZoneTwentyThree, + [APIName("twenty-four")] + ZoneTwentyFour, + [APIName("twenty-five")] + ZoneTwentyFive, + [APIName("twenty-six")] + ZoneTwentySix, + [APIName("twenty-seven")] + ZoneTwentySeven, + [APIName("twenty-eight")] + ZoneTwentyEight, + [APIName("twenty-nine")] + ZoneTwentyNine, + [APIName("thirty")] + ZoneThirty, + [APIName("thirty-one")] + ZoneThirtyOne, + [APIName("thirty-two")] + ZoneThirtyTwo, + [APIName("thirty-three")] + ZoneThirtyThree, + [APIName("thirty-four")] + ZoneThirtyFour, + [APIName("thirty-five")] + ZoneThirtyFive, + [APIName("thirty-six")] + ZoneThirtySix, + [APIName("thirty-seven")] + ZoneThirtySeven, + [APIName("thirty-eight")] + ZoneThirtyEight, + [APIName("thirty-nine")] + ZoneThirtyNine, + [APIName("forty")] + ZoneForty, + [APIName("forty-one")] + ZoneFortyOne, + [APIName("forty-two")] + ZoneFortyTwo, + [APIName("forty-three")] + ZoneFortyThree, + [APIName("forty-four")] + ZoneFortyFour, + [APIName("forty-five")] + ZoneFortyFive, + [APIName("forty-six")] + ZoneFortySix, + [APIName("forty-seven")] + ZoneFortySeven, + [APIName("forty-eight")] + ZoneFortyEight, + [APIName("forty-nine")] + ZoneFortyNine, + [APIName("fifty")] + ZoneFifty, + [APIName("fifty-one")] + ZoneFiftyOne, + [APIName("fifty-two")] + ZoneFiftyTwo, + [APIName("fifty-three")] + ZoneFiftyThree, + [APIName("fifty-four")] + ZoneFiftyFour, + [APIName("fifty-five")] + ZoneFiftyFive, + [APIName("fifty-six")] + ZoneFiftySix, + [APIName("fifty-seven")] + ZoneFiftySeven, + [APIName("fifty-eight")] + ZoneFiftyEight, + [APIName("fifty-nine")] + ZoneFiftyNine, + [APIName("sixty")] + ZoneSixty, + [APIName("sixty-one")] + ZoneSixtyOne, + [APIName("sixty-two")] + ZoneSixtyTwo, + [APIName("sixty-three")] + ZoneSixtyThree, + [APIName("sixty-four")] + ZoneSixtyFour, + [APIName("sixty-five")] + ZoneSixtyFive, + [APIName("sixty-six")] + ZoneSixtySix, + [APIName("sixty-seven")] + ZoneSixtySeven, + [APIName("sixty-eight")] + ZoneSixtyEight, + [APIName("sixty-nine")] + ZoneSixtyNine, + [APIName("seventy")] + ZoneSeventy, + [APIName("seventy-one")] + ZoneSeventyOne, + [APIName("seventy-two")] + ZoneSeventyTwo, + [APIName("seventy-three")] + ZoneSeventyThree, + [APIName("seventy-four")] + ZoneSeventyFour, + [APIName("seventy-five")] + ZoneSeventyFive, + [APIName("seventy-six")] + ZoneSeventySix, + [APIName("seventy-seven")] + ZoneSeventySeven, + [APIName("seventy-eight")] + ZoneSeventyEight, + [APIName("seventy-nine")] + ZoneSeventyNine, + [APIName("eighty")] + ZoneEighty, + [APIName("eighty-one")] + ZoneEightyOne, + [APIName("eighty-two")] + ZoneEightyTwo, + [APIName("eighty-three")] + ZoneEightyThree, + [APIName("eighty-four")] + ZoneEightyFour, + [APIName("eighty-five")] + ZoneEightyFive, + [APIName("eighty-six")] + ZoneEightySix, + [APIName("eighty-seven")] + ZoneEightySeven, + [APIName("eighty-eight")] + ZoneEightyEight, + [APIName("eighty-nine")] + ZoneEightyNine, + [APIName("ninety")] + ZoneNinety, + [APIName("ninety-one")] + ZoneNinetyOne, + [APIName("ninety-two")] + ZoneNinetyTwo, + [APIName("ninety-three")] + ZoneNinetyThree, + [APIName("ninety-four")] + ZoneNinetyFour, + [APIName("ninety-five")] + ZoneNinetyFive, + [APIName("ninety-six")] + ZoneNinetySix, + [APIName("ninety-seven")] + ZoneNinetySeven, + [APIName("ninety-eight")] + ZoneNinetyEight, + [APIName("ninety-nine")] + ZoneNinetyNine, + [APIName("one-hundred")] + ZoneOneHundred, + [APIName("one-hundred-one")] + ZoneOneHundredOne, + [APIName("one-hundred-two")] + ZoneOneHundredTwo, + [APIName("one-hundred-three")] + ZoneOneHundredThree, [APIName("logo")] Logo, diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs index 88c04ac..c6a6823 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateTrigger.cs @@ -29,7 +29,6 @@ namespace RGB.NET.Devices.SteelSeries /// /// Initializes a new instance of the class. /// - /// The hard limit of the update rate of this trigger. public SteelSeriesDeviceUpdateTrigger() { } @@ -45,9 +44,11 @@ namespace RGB.NET.Devices.SteelSeries #region Methods + /// protected override void UpdateLoop() { OnStartup(); + while (!UpdateToken.IsCancellationRequested) { if (HasDataEvent.WaitOne(Timeout)) @@ -58,18 +59,24 @@ namespace RGB.NET.Devices.SteelSeries if (UpdateFrequency > 0) { - _lastUpdateTimestamp = Stopwatch.GetTimestamp(); double lastUpdateTime = ((_lastUpdateTimestamp - preUpdateTicks) / (double)TimeSpan.TicksPerMillisecond); int sleep = (int)((UpdateFrequency * 1000.0) - lastUpdateTime); if (sleep > 0) Thread.Sleep(sleep); } } - else if (((Stopwatch.GetTimestamp() - _lastUpdateTimestamp) > FLUSH_TIMER)) + else if ((_lastUpdateTimestamp > 0) && ((Stopwatch.GetTimestamp() - _lastUpdateTimestamp) > FLUSH_TIMER)) OnUpdate(new CustomUpdateData(("refresh", true))); } } + /// + protected override void OnUpdate(CustomUpdateData updateData = null) + { + base.OnUpdate(updateData); + _lastUpdateTimestamp = Stopwatch.GetTimestamp(); + } + #endregion } }