diff --git a/CUE.NET.csproj b/CUE.NET.csproj index b7c90ac..3932d0e 100644 --- a/CUE.NET.csproj +++ b/CUE.NET.csproj @@ -55,10 +55,15 @@ + + + + + diff --git a/Devices/Generic/AbstractCueDevice.cs b/Devices/Generic/AbstractCueDevice.cs index 138cb3f..40e522a 100644 --- a/Devices/Generic/AbstractCueDevice.cs +++ b/Devices/Generic/AbstractCueDevice.cs @@ -3,18 +3,40 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using CUE.NET.Devices.Generic.Enums; using CUE.NET.Native; namespace CUE.NET.Devices.Generic { public abstract class AbstractCueDevice : ICueDevice { + private UpdateMode _updateMode = UpdateMode.AutoOnEffect; + #region Properties & Fields public IDeviceInfo DeviceInfo { get; } + public UpdateMode UpdateMode + { + get { return _updateMode; } + set + { + _updateMode = value; + CheckUpdateLoop(); + } + } + public float UpdateFrequency { get; set; } = 1f / 30f; + private Dictionary Leds { get; } = new Dictionary(); + protected abstract bool HasEffect { get; } + + private CancellationTokenSource _updateTokenSource; + private CancellationToken _updateToken; + private Task _updateTask; + #endregion #region Constructors @@ -22,6 +44,8 @@ namespace CUE.NET.Devices.Generic protected AbstractCueDevice(IDeviceInfo info) { this.DeviceInfo = info; + + CheckUpdateLoop(); } #endregion @@ -36,16 +60,61 @@ namespace CUE.NET.Devices.Generic return Leds[ledId]; } - public virtual void UpdateLeds(bool forceUpdate = false) + protected async void CheckUpdateLoop() { - IList> ledsToUpdate = (forceUpdate ? Leds : Leds.Where(x => x.Value.IsDirty)).ToList(); + bool shouldRun; + switch (UpdateMode) + { + case UpdateMode.Manual: + shouldRun = false; + break; + case UpdateMode.AutoOnEffect: + shouldRun = HasEffect; + break; + case UpdateMode.Continuous: + shouldRun = true; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + if (shouldRun && _updateTask == null) // Start task + { + _updateTokenSource?.Dispose(); + _updateTokenSource = new CancellationTokenSource(); + _updateTask = Task.Factory.StartNew(UpdateLoop, (_updateToken = _updateTokenSource.Token)); + } + else if (!shouldRun && _updateTask != null) // Stop task + { + _updateTokenSource.Cancel(); + await _updateTask; + _updateTask.Dispose(); + _updateTask = null; + } + } + + private void UpdateLoop() + { + while (!_updateToken.IsCancellationRequested) + { + long preUpdateTicks = DateTime.Now.Ticks; + Update(); + int sleep = (int)((UpdateFrequency * 1000f) - ((DateTime.Now.Ticks - preUpdateTicks) / 10000f)); + if (sleep > 0) + Thread.Sleep(sleep); + } + } + + public virtual void Update(bool flushLeds = false) + { + IList> ledsToUpdate = (flushLeds ? Leds : Leds.Where(x => x.Value.IsDirty)).ToList(); foreach (CorsairLed led in Leds.Values) led.Update(); UpdateLeds(ledsToUpdate); } - + private static void UpdateLeds(ICollection> ledsToUpdate) { ledsToUpdate = ledsToUpdate.Where(x => x.Value.Color != Color.Transparent).ToList(); diff --git a/Devices/Generic/CorsairLed.cs b/Devices/Generic/CorsairLed.cs index 930862d..c07dc18 100644 --- a/Devices/Generic/CorsairLed.cs +++ b/Devices/Generic/CorsairLed.cs @@ -1,4 +1,8 @@ -using System.Drawing; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + +using System.Drawing; using CUE.NET.Helper; namespace CUE.NET.Devices.Generic @@ -28,8 +32,6 @@ namespace CUE.NET.Devices.Generic public bool IsLocked { get; set; } = false; - //TODO DarthAffe 19.09.2015: Add effects and stuff - #endregion #region Constructors diff --git a/Devices/Generic/Enums/UpdateMode.cs b/Devices/Generic/Enums/UpdateMode.cs new file mode 100644 index 0000000..8ce44ab --- /dev/null +++ b/Devices/Generic/Enums/UpdateMode.cs @@ -0,0 +1,9 @@ +namespace CUE.NET.Devices.Generic.Enums +{ + public enum UpdateMode + { + Manual, + AutoOnEffect, + Continuous + } +} diff --git a/Devices/Headset/CorsairHeadset.cs b/Devices/Headset/CorsairHeadset.cs index c754b24..a976a64 100644 --- a/Devices/Headset/CorsairHeadset.cs +++ b/Devices/Headset/CorsairHeadset.cs @@ -7,6 +7,8 @@ namespace CUE.NET.Devices.Headset { #region Properties & Fields + protected override bool HasEffect => false; + #endregion #region Constructors diff --git a/Devices/ICueDevice.cs b/Devices/ICueDevice.cs index c1bab11..4a6d654 100644 --- a/Devices/ICueDevice.cs +++ b/Devices/ICueDevice.cs @@ -1,9 +1,15 @@ -namespace CUE.NET.Devices +using CUE.NET.Devices.Generic.Enums; + +namespace CUE.NET.Devices { public interface ICueDevice { IDeviceInfo DeviceInfo { get; } - void UpdateLeds(bool forceUpdate = false); + UpdateMode UpdateMode { get; set; } + + float UpdateFrequency { get; set; } + + void Update(bool flushLeds = false); } } diff --git a/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs b/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs index dfe056b..cb1bd64 100644 --- a/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs +++ b/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +// ReSharper disable MemberCanBeProtected.Global + +using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -14,10 +16,10 @@ namespace CUE.NET.Devices.Keyboard.Brushes.Gradient #region Constructors - public AbstractGradient() + protected AbstractGradient() { } - public AbstractGradient(params GradientStop[] gradientStops) + protected AbstractGradient(params GradientStop[] gradientStops) { foreach (GradientStop gradientStop in gradientStops) GradientStops.Add(gradientStop); diff --git a/Devices/Keyboard/Brushes/Gradient/GradientStop.cs b/Devices/Keyboard/Brushes/Gradient/GradientStop.cs index 89bd03a..8ddd9db 100644 --- a/Devices/Keyboard/Brushes/Gradient/GradientStop.cs +++ b/Devices/Keyboard/Brushes/Gradient/GradientStop.cs @@ -1,4 +1,7 @@ -using System.Drawing; +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +// ReSharper disable MemberCanBePrivate.Global + +using System.Drawing; namespace CUE.NET.Devices.Keyboard.Brushes.Gradient { diff --git a/Devices/Keyboard/Brushes/LinearGradientBrush.cs b/Devices/Keyboard/Brushes/LinearGradientBrush.cs index 729d969..741d4e6 100644 --- a/Devices/Keyboard/Brushes/LinearGradientBrush.cs +++ b/Devices/Keyboard/Brushes/LinearGradientBrush.cs @@ -1,6 +1,7 @@ // ReSharper disable CollectionNeverUpdated.Global // ReSharper disable MemberCanBePrivate.Global // ReSharper disable ReturnTypeCanBeEnumerable.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global using System.Drawing; using CUE.NET.Devices.Keyboard.Brushes.Gradient; diff --git a/Devices/Keyboard/Brushes/RadialGradientBrush.cs b/Devices/Keyboard/Brushes/RadialGradientBrush.cs index 57cca44..c284d0a 100644 --- a/Devices/Keyboard/Brushes/RadialGradientBrush.cs +++ b/Devices/Keyboard/Brushes/RadialGradientBrush.cs @@ -1,4 +1,7 @@ -using System; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + +using System; using System.Drawing; using CUE.NET.Devices.Keyboard.Brushes.Gradient; using CUE.NET.Helper; @@ -39,6 +42,7 @@ namespace CUE.NET.Devices.Keyboard.Brushes PointF centerPoint = new PointF(rectangle.X + rectangle.Width * Center.X, rectangle.Y + rectangle.Height * Center.Y); // Calculate the distance to the farthest point from the center as reference (this has to be a corner) + // ReSharper disable once RedundantCast - never trust this ... float refDistance = (float)Math.Max(Math.Max(Math.Max(GradientHelper.CalculateDistance(rectangle.Location, centerPoint), GradientHelper.CalculateDistance(new PointF(rectangle.X + rectangle.Width, rectangle.Y), centerPoint)), GradientHelper.CalculateDistance(new PointF(rectangle.X, rectangle.Y + rectangle.Height), centerPoint)), diff --git a/Devices/Keyboard/CorsairKeyboard.cs b/Devices/Keyboard/CorsairKeyboard.cs index 27fa6a0..806b88d 100644 --- a/Devices/Keyboard/CorsairKeyboard.cs +++ b/Devices/Keyboard/CorsairKeyboard.cs @@ -1,4 +1,8 @@ -using System; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable UnusedMember.Global + +using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -7,6 +11,7 @@ using System.Linq; using System.Runtime.InteropServices; using CUE.NET.Devices.Generic; using CUE.NET.Devices.Keyboard.Brushes; +using CUE.NET.Devices.Keyboard.Effects; using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Keyboard.Keys; using CUE.NET.Helper; @@ -18,11 +23,8 @@ namespace CUE.NET.Devices.Keyboard { #region Properties & Fields - public CorsairKeyboardDeviceInfo KeyboardDeviceInfo { get; } + #region Indexer - public RectangleF KeyboardRectangle { get; private set; } - - private Dictionary _keys = new Dictionary(); public CorsairKey this[CorsairKeyboardKeyId keyId] { get @@ -30,32 +32,34 @@ namespace CUE.NET.Devices.Keyboard CorsairKey key; return _keys.TryGetValue(keyId, out key) ? key : null; } - private set { throw new NotSupportedException(); } } - public CorsairKey this[char key] - { - get { return this[_CUESDK.CorsairGetLedIdForKeyName(key)]; } - private set { throw new NotSupportedException(); } - } + public CorsairKey this[char key] => this[_CUESDK.CorsairGetLedIdForKeyName(key)]; - public CorsairKey this[PointF location] - { - get { return _keys.Values.FirstOrDefault(x => x.KeyRectangle.Contains(location)); } - private set { throw new NotSupportedException(); } - } + public CorsairKey this[PointF location] => _keys.Values.FirstOrDefault(x => x.KeyRectangle.Contains(location)); - public IEnumerable this[RectangleF referenceRect, float minOverlayPercentage = 0.5f] - { - get { return _keys.Values.Where(x => RectangleHelper.CalculateIntersectPercentage(x.KeyRectangle, referenceRect) >= minOverlayPercentage); } - private set { throw new NotSupportedException(); } - } + public IEnumerable this[RectangleF referenceRect, float minOverlayPercentage = 0.5f] => _keys.Values.Where(x => RectangleHelper.CalculateIntersectPercentage(x.KeyRectangle, referenceRect) >= minOverlayPercentage); + #endregion + + private readonly LinkedList _keyGroups = new LinkedList(); + private readonly LinkedList _effects = new LinkedList(); + + private Dictionary _keys = new Dictionary(); public IEnumerable Keys => new ReadOnlyCollection(_keys.Values.ToList()); + public CorsairKeyboardDeviceInfo KeyboardDeviceInfo { get; } + public RectangleF KeyboardRectangle { get; private set; } public IBrush Brush { get; set; } - private readonly IList _keyGroups = new List(); + protected override bool HasEffect + { + get + { + lock (_effects) + return _effects.Any(); + } + } #endregion @@ -74,21 +78,62 @@ namespace CUE.NET.Devices.Keyboard #region Methods - public override void UpdateLeds(bool forceUpdate = false) - { - // Apply all KeyGroups + #region Update + public override void Update(bool flushLeds = false) + { + UpdateKeyGroups(); + UpdateEffects(); + + // Perform 'real' update + base.Update(flushLeds); + } + + private void UpdateEffects() + { + List effectsToRemove = new List(); + lock (_effects) + { + long currentTicks = DateTime.Now.Ticks; + foreach (EffectTimeContainer effect in _effects) + { + float deltaTime; + if (effect.TicksAtLastUpdate < 0) + { + effect.TicksAtLastUpdate = currentTicks; + deltaTime = 0f; + } + else + deltaTime = (currentTicks - effect.TicksAtLastUpdate) / 10000000f; + + effect.TicksAtLastUpdate = currentTicks; + effect.Effect.Update(deltaTime); + + ApplyBrush((effect.Effect.KeyList ?? this).ToList(), effect.Effect.EffectBrush); + + if (effect.Effect.IsDone) + effectsToRemove.Add(effect.Effect); + } + } + + foreach (IEffect effect in effectsToRemove) + DetachEffect(effect); + } + + private void UpdateKeyGroups() + { if (Brush != null) ApplyBrush(this.ToList(), Brush); - //TODO DarthAffe 20.09.2015: Add some sort of priority - foreach (IKeyGroup keyGroup in _keyGroups) - ApplyBrush(keyGroup.Keys.ToList(), keyGroup.Brush); - - // Perform 'real' update - base.UpdateLeds(forceUpdate); + lock (_keyGroups) + { + //TODO DarthAffe 20.09.2015: Add some sort of priority + foreach (IKeyGroup keyGroup in _keyGroups) + ApplyBrush(keyGroup.Keys.ToList(), keyGroup.Brush); + } } + // ReSharper disable once MemberCanBeMadeStatic.Local - idc private void ApplyBrush(ICollection keys, IBrush brush) { RectangleF brushRectangle = RectangleHelper.CreateRectangleFromRectangles(keys.Select(x => x.KeyRectangle)); @@ -96,20 +141,68 @@ namespace CUE.NET.Devices.Keyboard key.Led.Color = brush.GetColorAtPoint(brushRectangle, key.KeyRectangle.GetCenter()); } + #endregion + public bool AttachKeyGroup(IKeyGroup keyGroup) { - if (keyGroup == null || _keyGroups.Contains(keyGroup)) return false; + lock (_keyGroups) + { + if (keyGroup == null || _keyGroups.Contains(keyGroup)) return false; - _keyGroups.Add(keyGroup); - return true; + _keyGroups.AddLast(keyGroup); + return true; + } } public bool DetachKeyGroup(IKeyGroup keyGroup) { - if (keyGroup == null || !_keyGroups.Contains(keyGroup)) return false; + lock (_keyGroups) + { + if (keyGroup == null) return false; - _keyGroups.Remove(keyGroup); - return true; + LinkedListNode node = _keyGroups.Find(keyGroup); + if (node == null) return false; + + _keyGroups.Remove(node); + return true; + } + } + + public bool AttachEffect(IEffect effect) + { + bool retVal = false; + lock (_effects) + { + if (effect != null && _effects.All(x => x.Effect != effect)) + { + effect.OnAttach(); + _effects.AddLast(new EffectTimeContainer(effect, -1)); + retVal = true; + } + } + + CheckUpdateLoop(); + return retVal; + } + + public bool DetachEffect(IEffect effect) + { + bool retVal = false; + lock (_effects) + { + if (effect != null) + { + EffectTimeContainer val = _effects.FirstOrDefault(x => x.Effect == effect); + if (val != null) + { + effect.OnDetach(); + _effects.Remove(val); + retVal = true; + } + } + } + CheckUpdateLoop(); + return retVal; } private void InitializeKeys() diff --git a/Devices/Keyboard/Effects/AbstractEffect.cs b/Devices/Keyboard/Effects/AbstractEffect.cs new file mode 100644 index 0000000..25268b0 --- /dev/null +++ b/Devices/Keyboard/Effects/AbstractEffect.cs @@ -0,0 +1,39 @@ +// ReSharper disable MemberCanBePrivate.Global + +using System.Collections.Generic; +using System.Linq; +using CUE.NET.Devices.Keyboard.Brushes; +using CUE.NET.Devices.Keyboard.Keys; + +namespace CUE.NET.Devices.Keyboard.Effects +{ + public abstract class AbstractEffect : IEffect + { + #region Properties & Fields + + public abstract IBrush EffectBrush { get; } + + public IEnumerable KeyList { get; protected set; } + + public bool IsDone { get; protected set; } + + #endregion + + #region Methods + + public void SetTarget(IKeyGroup keyGroup) + { + KeyList = keyGroup.Keys.ToList(); + } + + public abstract void Update(float deltaTime); + + public virtual void OnAttach() + { } + + public virtual void OnDetach() + { } + + #endregion + } +} diff --git a/Devices/Keyboard/Effects/EffectTimeContainer.cs b/Devices/Keyboard/Effects/EffectTimeContainer.cs new file mode 100644 index 0000000..ea32de4 --- /dev/null +++ b/Devices/Keyboard/Effects/EffectTimeContainer.cs @@ -0,0 +1,26 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + +namespace CUE.NET.Devices.Keyboard.Effects +{ + internal class EffectTimeContainer + { + #region Properties & Fields + + internal IEffect Effect { get; set; } + + internal long TicksAtLastUpdate { get; set; } + + #endregion + + #region Constructors + + internal EffectTimeContainer(IEffect effect, long ticksAtLastUpdate) + { + this.Effect = effect; + this.TicksAtLastUpdate = ticksAtLastUpdate; + } + + #endregion + } +} diff --git a/Devices/Keyboard/Effects/FlashEffect.cs b/Devices/Keyboard/Effects/FlashEffect.cs new file mode 100644 index 0000000..3a538db --- /dev/null +++ b/Devices/Keyboard/Effects/FlashEffect.cs @@ -0,0 +1,126 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + +using System; +using System.Drawing; +using CUE.NET.Devices.Keyboard.Brushes; + +namespace CUE.NET.Devices.Keyboard.Effects +{ + public class FlashEffect : AbstractEffect + { + #region Properties & Fields + + public override IBrush EffectBrush { get; } + + // Settings are close to a synthesizer envelope (sustain is different for consequent naming): https://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope + public float Attack { get; set; } = 0.2f; + public float Decay { get; set; } = 0f; + public float Sustain { get; set; } = 0.3f; + public float Release { get; set; } = 0.2f; + + public float SustainValue { get; set; } = 1f; + public float AttackValue { get; set; } = 1f; + + public float Interval { get; set; } = 1f; + + public int Repetitions { get; set; } = 0; + + private ADSRPhase _currentPhase; + private float _currentPhaseValue; + private int _repetitionCount; + + #endregion + + #region Constructors + + public FlashEffect(Color flashColor) + : this(new SolidColorBrush(flashColor)) + { } + + public FlashEffect(IBrush effectBrush) + { + this.EffectBrush = effectBrush; + } + + #endregion + + #region Methods + + public override void Update(float deltaTime) + { + _currentPhaseValue -= deltaTime; + + // Using ifs instead of a switch allows to skip phases with time 0. + + if (_currentPhase == ADSRPhase.Attack) + if (_currentPhaseValue > 0f) + EffectBrush.Opacity = Math.Min(1f, (Attack - _currentPhaseValue) / Attack) * AttackValue; + else + { + _currentPhaseValue = Decay; + _currentPhase = ADSRPhase.Decay; + } + + if (_currentPhase == ADSRPhase.Decay) + if (_currentPhaseValue > 0f) + EffectBrush.Opacity = SustainValue + (Math.Min(1f, _currentPhaseValue / Decay) * (AttackValue - SustainValue)); + else + { + _currentPhaseValue = Sustain; + _currentPhase = ADSRPhase.Sustain; + } + + if (_currentPhase == ADSRPhase.Sustain) + if (_currentPhaseValue > 0f) + EffectBrush.Opacity = SustainValue; + else + { + _currentPhaseValue = Release; + _currentPhase = ADSRPhase.Release; + } + + if (_currentPhase == ADSRPhase.Release) + if (_currentPhaseValue > 0f) + EffectBrush.Opacity = Math.Min(1f, _currentPhaseValue / Release) * SustainValue; + else + { + _currentPhaseValue = Interval; + _currentPhase = ADSRPhase.Pause; + } + + if (_currentPhase == ADSRPhase.Pause) + if (_currentPhaseValue > 0f) + EffectBrush.Opacity = 0f; + else + { + if (++_repetitionCount >= Repetitions && Repetitions > 0) + IsDone = true; + _currentPhaseValue = Attack; + _currentPhase = ADSRPhase.Attack; + } + } + + public override void OnAttach() + { + base.OnAttach(); + + _currentPhase = ADSRPhase.Attack; + _currentPhaseValue = Attack; + _repetitionCount = 0; + EffectBrush.Opacity = 0f; + } + + #endregion + + // ReSharper disable once InconsistentNaming + private enum ADSRPhase + { + Attack, + Decay, + Sustain, + Release, + Pause + } + } +} diff --git a/Devices/Keyboard/Effects/IEffect.cs b/Devices/Keyboard/Effects/IEffect.cs new file mode 100644 index 0000000..9f166aa --- /dev/null +++ b/Devices/Keyboard/Effects/IEffect.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using CUE.NET.Devices.Keyboard.Brushes; +using CUE.NET.Devices.Keyboard.Keys; + +namespace CUE.NET.Devices.Keyboard.Effects +{ + public interface IEffect + { + #region Properties & Fields + + IBrush EffectBrush { get; } + + IEnumerable KeyList { get; } + + bool IsDone { get; } + + #endregion + + #region Methods + + void Update(float deltaTime); + + void OnAttach(); + + void OnDetach(); + + #endregion + } +} diff --git a/Devices/Keyboard/Extensions/KeyGroupExtension.cs b/Devices/Keyboard/Extensions/KeyGroupExtension.cs index b68cc7d..73abff3 100644 --- a/Devices/Keyboard/Extensions/KeyGroupExtension.cs +++ b/Devices/Keyboard/Extensions/KeyGroupExtension.cs @@ -1,4 +1,6 @@ -using System.Linq; +// ReSharper disable MemberCanBePrivate.Global + +using System.Linq; using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Keyboard.Keys; @@ -33,6 +35,7 @@ namespace CUE.NET.Devices.Keyboard.Extensions return simpleKeyGroup; } + // ReSharper disable once UnusedMethodReturnValue.Global public static bool Attach(this BaseKeyGroup keyGroup) { return keyGroup.Keyboard?.AttachKeyGroup(keyGroup) ?? false; diff --git a/Devices/Keyboard/Keys/CorsairKey.cs b/Devices/Keyboard/Keys/CorsairKey.cs index 7a05530..aaa6705 100644 --- a/Devices/Keyboard/Keys/CorsairKey.cs +++ b/Devices/Keyboard/Keys/CorsairKey.cs @@ -1,4 +1,7 @@ -using System.Drawing; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +using System.Drawing; using CUE.NET.Devices.Generic; using CUE.NET.Devices.Keyboard.Enums; diff --git a/Devices/Keyboard/Keys/ListKeyGroup.cs b/Devices/Keyboard/Keys/ListKeyGroup.cs index bf158a6..5d95aae 100644 --- a/Devices/Keyboard/Keys/ListKeyGroup.cs +++ b/Devices/Keyboard/Keys/ListKeyGroup.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +// ReSharper disable MemberCanBePrivate.Global + +using System.Collections.Generic; using CUE.NET.Devices.Keyboard.Enums; namespace CUE.NET.Devices.Keyboard.Keys diff --git a/Devices/Keyboard/Keys/RectangleKeyGroup.cs b/Devices/Keyboard/Keys/RectangleKeyGroup.cs index 77db408..f29708f 100644 --- a/Devices/Keyboard/Keys/RectangleKeyGroup.cs +++ b/Devices/Keyboard/Keys/RectangleKeyGroup.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + +using System.Collections.Generic; using System.Drawing; using System.Linq; using CUE.NET.Devices.Keyboard.Enums; diff --git a/Devices/Mouse/CorsairMouse.cs b/Devices/Mouse/CorsairMouse.cs index e61cb05..e770e91 100644 --- a/Devices/Mouse/CorsairMouse.cs +++ b/Devices/Mouse/CorsairMouse.cs @@ -9,6 +9,8 @@ namespace CUE.NET.Devices.Mouse public CorsairMouseDeviceInfo MouseDeviceInfo { get; } + protected override bool HasEffect => false; + #endregion #region Constructors diff --git a/Helper/ColorHelper.cs b/Helper/ColorHelper.cs index 8f3df61..b4cbc7e 100644 --- a/Helper/ColorHelper.cs +++ b/Helper/ColorHelper.cs @@ -36,6 +36,7 @@ namespace CUE.NET.Helper private static byte GetIntColorFromFloat(float f) { + // ReSharper disable once RedundantCast - never trust this ... float calcF = (float)Math.Max(0f, Math.Min(1f, f)); return (byte)(calcF.Equals(1f) ? 255 : calcF * 256f); } @@ -69,7 +70,9 @@ namespace CUE.NET.Helper int max = Math.Max(color.R, Math.Max(color.G, color.B)); int min = Math.Min(color.R, Math.Min(color.G, color.B)); + // ReSharper disable RedundantCast - never trust this ... return (max == 0) ? 0 : 1f - ((float)min / (float)max); + // ReSharper restore RedundantCast } public static float GetHSVValue(this Color color)