From e49945004fb08bdd35b900fe37af7f9ebe19efed Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sun, 18 Oct 2015 17:12:53 +0200 Subject: [PATCH] Refactored effects into AbstractCueDevice --- Devices/Generic/AbstractCueDevice.cs | 99 +++++++++++++++++++++++++++- Devices/Headset/CorsairHeadset.cs | 9 +++ Devices/Keyboard/CorsairKeyboard.cs | 92 ++------------------------ Devices/Mouse/CorsairMouse.cs | 10 +++ Effects/EffectTimeContainer.cs | 10 +-- 5 files changed, 129 insertions(+), 91 deletions(-) diff --git a/Devices/Generic/AbstractCueDevice.cs b/Devices/Generic/AbstractCueDevice.cs index 6a9fbc3..f58b846 100644 --- a/Devices/Generic/AbstractCueDevice.cs +++ b/Devices/Generic/AbstractCueDevice.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using CUE.NET.Devices.Generic.Enums; +using CUE.NET.Effects; using CUE.NET.Native; namespace CUE.NET.Devices.Generic @@ -51,6 +52,11 @@ namespace CUE.NET.Devices.Generic /// protected abstract bool HasEffect { get; } + /// + /// + /// + protected LinkedList Effects { get; } = new LinkedList(); + private CancellationTokenSource _updateTokenSource; private CancellationToken _updateToken; private Task _updateTask; @@ -146,11 +152,13 @@ namespace CUE.NET.Devices.Generic } /// - /// Perform an update for all dirty keys, or all keys if flushLeds is set to true. + /// Performs an update for all dirty keys, or all keys if flushLeds is set to true. /// /// Specifies whether all keys (including clean ones) should be updated. public virtual void Update(bool flushLeds = false) { + UpdateEffects(); + IList> ledsToUpdate = (flushLeds ? Leds : Leds.Where(x => x.Value.IsDirty)).ToList(); foreach (CorsairLed led in Leds.Values) @@ -159,6 +167,48 @@ namespace CUE.NET.Devices.Generic UpdateLeds(ledsToUpdate); } + private void UpdateEffects() + { + List effectsToRemove = new List(); + lock (Effects) + { + long currentTicks = DateTime.Now.Ticks; + foreach (EffectTimeContainer effect in Effects.OrderBy(x => x.ZIndex)) + { + try + { + float deltaTime; + if (effect.TicksAtLastUpdate < 0) + { + effect.TicksAtLastUpdate = currentTicks; + deltaTime = 0f; + } + else + deltaTime = (currentTicks - effect.TicksAtLastUpdate) / 10000000f; + + effect.TicksAtLastUpdate = currentTicks; + effect.Effect.Update(deltaTime); + + ApplyEffect(effect.Effect); + + if (effect.Effect.IsDone) + effectsToRemove.Add(effect.Effect); + } + // ReSharper disable once CatchAllClause + catch (Exception ex) { ManageException(ex); } + } + } + + foreach (IEffect effect in effectsToRemove) + DetachEffect(effect); + } + + /// + /// Applies the given effect to the device LEDs. + /// + /// The effect to apply. + protected abstract void ApplyEffect(IEffect effect); + private static void UpdateLeds(ICollection> ledsToUpdate) { ledsToUpdate = ledsToUpdate.Where(x => x.Value.Color != Color.Transparent).ToList(); @@ -186,6 +236,53 @@ namespace CUE.NET.Devices.Generic Marshal.FreeHGlobal(ptr); } + /// + /// Attaches the given effect. + /// + /// The effect to attach. + /// true if the effect could be attached; otherwise, false. + 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; + } + + /// + /// Detaches the given effect. + /// + /// The effect to detached. + /// true if the effect could be detached; otherwise, false. + 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; + } + /// /// Handles the needed event-calls for an exception. /// diff --git a/Devices/Headset/CorsairHeadset.cs b/Devices/Headset/CorsairHeadset.cs index 9e4f826..5e3eac0 100644 --- a/Devices/Headset/CorsairHeadset.cs +++ b/Devices/Headset/CorsairHeadset.cs @@ -4,9 +4,11 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Drawing; using System.Linq; using CUE.NET.Devices.Generic; using CUE.NET.Devices.Headset.Enums; +using CUE.NET.Effects; namespace CUE.NET.Devices.Headset { @@ -69,6 +71,13 @@ namespace CUE.NET.Devices.Headset #region Methods + protected override void ApplyEffect(IEffect effect) + { + //TODO DarthAffe 18.10.2015: How should brushes be applied to headsets? + foreach (CorsairLed led in effect.LedList) + led.Color = effect.EffectBrush.GetColorAtPoint(new RectangleF(0, 0, 2, 2), new PointF(1, 1)); + } + private void InitializeLeds() { GetLed((int)CorsairHeadsetLedId.LeftLogo); diff --git a/Devices/Keyboard/CorsairKeyboard.cs b/Devices/Keyboard/CorsairKeyboard.cs index 3b9a860..7387038 100644 --- a/Devices/Keyboard/CorsairKeyboard.cs +++ b/Devices/Keyboard/CorsairKeyboard.cs @@ -76,7 +76,6 @@ namespace CUE.NET.Devices.Keyboard #endregion private readonly LinkedList _keyGroups = new LinkedList(); - private readonly LinkedList _effects = new LinkedList(); private Dictionary _keys = new Dictionary(); @@ -113,8 +112,8 @@ namespace CUE.NET.Devices.Keyboard { get { - lock (_effects) - return _effects.Any(); + lock (Effects) + return Effects.Any(); } } @@ -148,7 +147,6 @@ namespace CUE.NET.Devices.Keyboard public override void Update(bool flushLeds = false) { UpdateKeyGroups(); - UpdateEffects(); // Perform 'real' update base.Update(flushLeds); @@ -166,42 +164,13 @@ namespace CUE.NET.Devices.Keyboard } } - private void UpdateEffects() + protected override void ApplyEffect(IEffect effect) { - List effectsToRemove = new List(); - lock (_effects) - { - long currentTicks = DateTime.Now.Ticks; - foreach (EffectTimeContainer effect in _effects.OrderBy(x => x.ZIndex)) - { - try - { - float deltaTime; - if (effect.TicksAtLastUpdate < 0) - { - effect.TicksAtLastUpdate = currentTicks; - deltaTime = 0f; - } - else - deltaTime = (currentTicks - effect.TicksAtLastUpdate) / 10000000f; + if (effect == null) return; - effect.TicksAtLastUpdate = currentTicks; - effect.Effect.Update(deltaTime); - - //TODO DarthAffe 18.10.2015: This is really dirty and might have a really negative performance impact - find a better solution. - IEnumerable keys = effect.Effect?.LedList?.Select(x => this.FirstOrDefault(y => y.Led == x)); - ApplyBrush((keys ?? this).ToList(), effect.Effect.EffectBrush); - - if (effect.Effect.IsDone) - effectsToRemove.Add(effect.Effect); - } - // ReSharper disable once CatchAllClause - catch (Exception ex) { ManageException(ex); } - } - } - - foreach (IEffect effect in effectsToRemove) - DetachEffect(effect); + //TODO DarthAffe 18.10.2015: This is really dirty and might have a really negative performance impact - find a better solution. + IEnumerable keys = effect.LedList?.Select(x => this.FirstOrDefault(y => y.Led == x)); + ApplyBrush((keys ?? this).ToList(), effect.EffectBrush); } // ReSharper disable once MemberCanBeMadeStatic.Local - idc @@ -259,53 +228,6 @@ namespace CUE.NET.Devices.Keyboard } } - /// - /// Attaches the given effect. - /// - /// The effect to attach. - /// true if the effect could be attached; otherwise, false. - 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; - } - - /// - /// Detaches the given effect. - /// - /// The effect to detached. - /// true if the effect could be detached; otherwise, false. - 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() { _CorsairLedPositions nativeLedPositions = (_CorsairLedPositions)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositions(), typeof(_CorsairLedPositions)); diff --git a/Devices/Mouse/CorsairMouse.cs b/Devices/Mouse/CorsairMouse.cs index 944b769..8ff3888 100644 --- a/Devices/Mouse/CorsairMouse.cs +++ b/Devices/Mouse/CorsairMouse.cs @@ -2,12 +2,15 @@ // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedMember.Global +using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Drawing; using System.Linq; using CUE.NET.Devices.Generic; using CUE.NET.Devices.Mouse.Enums; +using CUE.NET.Effects; using CUE.NET.Exceptions; namespace CUE.NET.Devices.Mouse @@ -72,6 +75,13 @@ namespace CUE.NET.Devices.Mouse #region Methods + protected override void ApplyEffect(IEffect effect) + { + //TODO DarthAffe 18.10.2015: How should brushes be applied to mice? + foreach (CorsairLed led in effect.LedList) + led.Color = effect.EffectBrush.GetColorAtPoint(new RectangleF(0, 0, 2, 2), new PointF(1, 1)); + } + private void InitializeLeds() { switch (MouseDeviceInfo.PhysicalLayout) diff --git a/Effects/EffectTimeContainer.cs b/Effects/EffectTimeContainer.cs index 3cb70b0..a1c5c8a 100644 --- a/Effects/EffectTimeContainer.cs +++ b/Effects/EffectTimeContainer.cs @@ -6,24 +6,24 @@ namespace CUE.NET.Effects /// /// Represents a wrapped effect with additional time information. /// - internal class EffectTimeContainer + public class EffectTimeContainer { #region Properties & Fields /// /// Gets or sets the wrapped effect. /// - internal IEffect Effect { get; set; } + public IEffect Effect { get; set; } /// /// Gets or sets the tick-count from the last time the effect was updated. /// - internal long TicksAtLastUpdate { get; set; } + public long TicksAtLastUpdate { get; set; } /// /// Gets the z-index of the effect. /// - internal int ZIndex => Effect?.ZIndex ?? 0; + public int ZIndex => Effect?.ZIndex ?? 0; #endregion @@ -34,7 +34,7 @@ namespace CUE.NET.Effects /// /// The wrapped effect. /// The tick-count from the last time the effect was updated. - internal EffectTimeContainer(IEffect effect, long ticksAtLastUpdate) + public EffectTimeContainer(IEffect effect, long ticksAtLastUpdate) { this.Effect = effect; this.TicksAtLastUpdate = ticksAtLastUpdate;