diff --git a/Brushes/AbstractBrush.cs b/Brushes/AbstractBrush.cs
index 649caba..8e3c085 100644
--- a/Brushes/AbstractBrush.cs
+++ b/Brushes/AbstractBrush.cs
@@ -2,6 +2,7 @@
using System.Drawing;
using CUE.NET.Devices.Keyboard.Enums;
+using CUE.NET.Effects;
using CUE.NET.Helper;
namespace CUE.NET.Brushes
@@ -9,7 +10,7 @@ namespace CUE.NET.Brushes
///
/// Represents a basic brush.
///
- public abstract class AbstractBrush : IBrush
+ public abstract class AbstractBrush : AbstractEffectTarget, IBrush
{
#region Properties & Fields
diff --git a/Brushes/IBrush.cs b/Brushes/IBrush.cs
index bcb1099..094f7ff 100644
--- a/Brushes/IBrush.cs
+++ b/Brushes/IBrush.cs
@@ -2,13 +2,14 @@
using System.Drawing;
using CUE.NET.Devices.Keyboard.Enums;
+using CUE.NET.Effects;
namespace CUE.NET.Brushes
{
///
/// Represents a basic brush.
///
- public interface IBrush
+ public interface IBrush : IEffectTarget
{
///
/// Gets or sets the calculation mode used for the rectangle/points used for color-selection in brushes.
diff --git a/Brushes/ImageBrush.cs b/Brushes/ImageBrush.cs
index 7319389..2f458fb 100644
--- a/Brushes/ImageBrush.cs
+++ b/Brushes/ImageBrush.cs
@@ -39,6 +39,8 @@ namespace CUE.NET.Brushes
#region Properties & Fields
+ protected override IBrush EffectTarget => this;
+
///
/// Gets or sets the image drawn by the brush. If null it will default to full transparent.
///
diff --git a/Brushes/LinearGradientBrush.cs b/Brushes/LinearGradientBrush.cs
index 25c7121..55264c0 100644
--- a/Brushes/LinearGradientBrush.cs
+++ b/Brushes/LinearGradientBrush.cs
@@ -18,6 +18,8 @@ namespace CUE.NET.Brushes
{
#region Properties & Fields
+ protected override IBrush EffectTarget => this;
+
///
/// Gets or sets the start point (as percentage in the range [0..1]) of the gradient drawn by the brush. (default: 0f, 0.5f)
///
diff --git a/Brushes/ProfileBrush.cs b/Brushes/ProfileBrush.cs
index 815672b..b3cdb4d 100644
--- a/Brushes/ProfileBrush.cs
+++ b/Brushes/ProfileBrush.cs
@@ -11,7 +11,9 @@ namespace CUE.NET.Brushes
public class ProfileBrush : AbstractBrush
{
#region Properties & Fields
-
+
+ protected override IBrush EffectTarget => this;
+
private Dictionary _keyLights;
#endregion
diff --git a/Brushes/RadialGradientBrush.cs b/Brushes/RadialGradientBrush.cs
index 0b97af3..8a87c54 100644
--- a/Brushes/RadialGradientBrush.cs
+++ b/Brushes/RadialGradientBrush.cs
@@ -16,6 +16,8 @@ namespace CUE.NET.Brushes
{
#region Properties & Fields
+ protected override IBrush EffectTarget => this;
+
///
/// Gets or sets the center point (as percentage in the range [0..1]) around which the brush should be drawn.
///
diff --git a/Brushes/RandomColorBrush.cs b/Brushes/RandomColorBrush.cs
index 5037854..dd427eb 100644
--- a/Brushes/RandomColorBrush.cs
+++ b/Brushes/RandomColorBrush.cs
@@ -15,6 +15,8 @@ namespace CUE.NET.Brushes
{
#region Properties & Fields
+ protected override IBrush EffectTarget => this;
+
private Random _random = new Random();
#endregion
diff --git a/Brushes/SolidColorBrush.cs b/Brushes/SolidColorBrush.cs
index 1ad65bd..d315199 100644
--- a/Brushes/SolidColorBrush.cs
+++ b/Brushes/SolidColorBrush.cs
@@ -12,6 +12,8 @@ namespace CUE.NET.Brushes
{
#region Properties & Fields
+ protected override IBrush EffectTarget => this;
+
///
/// Gets or sets the color drawn by the brush.
///
diff --git a/CUE.NET.csproj b/CUE.NET.csproj
index a378353..cf69886 100644
--- a/CUE.NET.csproj
+++ b/CUE.NET.csproj
@@ -58,6 +58,10 @@
+
+
+
+
@@ -67,7 +71,6 @@
-
@@ -76,7 +79,7 @@
-
+
diff --git a/Devices/Generic/AbstractCueDevice.cs b/Devices/Generic/AbstractCueDevice.cs
index 499b591..66d2d66 100644
--- a/Devices/Generic/AbstractCueDevice.cs
+++ b/Devices/Generic/AbstractCueDevice.cs
@@ -10,7 +10,6 @@ using System.Threading;
using System.Threading.Tasks;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Generic.EventArgs;
-using CUE.NET.Effects;
using CUE.NET.Native;
namespace CUE.NET.Devices.Generic
@@ -27,7 +26,7 @@ namespace CUE.NET.Devices.Generic
///
public IDeviceInfo DeviceInfo { get; }
- private UpdateMode _updateMode = UpdateMode.AutoOnEffect;
+ private UpdateMode _updateMode = UpdateMode.Manual;
///
/// Gets or sets the update-mode for the device.
///
@@ -51,16 +50,6 @@ namespace CUE.NET.Devices.Generic
///
protected Dictionary Leds { get; } = new Dictionary();
- ///
- /// Indicates if the device has an active effect to deal with.
- ///
- protected abstract bool HasEffect { get; }
-
- ///
- ///
- ///
- protected LinkedList Effects { get; } = new LinkedList();
-
private CancellationTokenSource _updateTokenSource;
private CancellationToken _updateToken;
private Task _updateTask;
@@ -139,9 +128,6 @@ namespace CUE.NET.Devices.Generic
case UpdateMode.Manual:
shouldRun = false;
break;
- case UpdateMode.AutoOnEffect:
- shouldRun = HasEffect;
- break;
case UpdateMode.Continuous:
shouldRun = true;
break;
@@ -184,8 +170,8 @@ namespace CUE.NET.Devices.Generic
{
OnUpdating();
+ DeviceUpdateEffects();
DeviceUpdate();
- UpdateEffects();
ICollection ledsToUpdate = (flushLeds ? Leds : Leds.Where(x => x.Value.IsDirty)).Select(x => new LedUpateRequest(x.Key, x.Value.RequestedColor)).ToList();
@@ -198,53 +184,15 @@ namespace CUE.NET.Devices.Generic
}
///
- /// Empty method which can be overwritten to perform device specific updates.
+ /// Performs device specific updates.
///
- protected virtual void DeviceUpdate()
- { }
-
- 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) { OnException(ex); }
- }
- }
-
- foreach (IEffect effect in effectsToRemove)
- DetachEffect(effect);
- }
+ protected abstract void DeviceUpdate();
///
- /// Applies the given effect to the device LEDs.
+ /// Performs device specific updates effect-updates.
///
- /// The effect to apply.
- protected abstract void ApplyEffect(IEffect effect);
-
+ protected abstract void DeviceUpdateEffects();
+
private void UpdateLeds(ICollection updateRequests)
{
updateRequests = updateRequests.Where(x => x.Color != Color.Transparent).ToList();
@@ -276,53 +224,6 @@ namespace CUE.NET.Devices.Generic
OnLedsUpdated(updateRequests);
}
- ///
- /// 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;
- }
-
///
/// Resets all loaded LEDs back to default.
///
diff --git a/Devices/Generic/Enums/UpdateMode.cs b/Devices/Generic/Enums/UpdateMode.cs
index 6dc10a1..24be91d 100644
--- a/Devices/Generic/Enums/UpdateMode.cs
+++ b/Devices/Generic/Enums/UpdateMode.cs
@@ -12,12 +12,6 @@ namespace CUE.NET.Devices.Generic.Enums
///
Manual,
- ///
- /// The device will perform automatic updates at the rate set in
- /// as long as an is attached.
- ///
- AutoOnEffect,
-
///
/// The device will perform automatic updates at the rate set in .
///
diff --git a/Devices/Headset/CorsairHeadset.cs b/Devices/Headset/CorsairHeadset.cs
index b674634..37590b9 100644
--- a/Devices/Headset/CorsairHeadset.cs
+++ b/Devices/Headset/CorsairHeadset.cs
@@ -5,11 +5,9 @@
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
{
@@ -43,11 +41,6 @@ namespace CUE.NET.Devices.Headset
///
public CorsairHeadsetDeviceInfo HeadsetDeviceInfo { get; }
- ///
- /// Gets a value indicating if the headset has an active effect to deal with or not.
- ///
- protected override bool HasEffect => false;
-
///
/// Gets a read-only collection containing all LEDs of the headset.
///
@@ -72,19 +65,22 @@ 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);
GetLed((int)CorsairHeadsetLedId.RightLogo);
}
+ protected override void DeviceUpdate()
+ {
+ //TODO DarthAffe 21.08.2016: Create something fancy for headsets
+ }
+
+ protected override void DeviceUpdateEffects()
+ {
+ //TODO DarthAffe 21.08.2016: Create something fancy for headsets
+ }
+
#region IEnumerable
///
diff --git a/Devices/Keyboard/CorsairKeyboard.cs b/Devices/Keyboard/CorsairKeyboard.cs
index d0cc226..edb9342 100644
--- a/Devices/Keyboard/CorsairKeyboard.cs
+++ b/Devices/Keyboard/CorsairKeyboard.cs
@@ -106,18 +106,6 @@ namespace CUE.NET.Devices.Keyboard
///
public int ZIndex { get; set; } = 0;
- ///
- /// Gets a value indicating if the keyboard has an active effect to deal with or not.
- ///
- protected override bool HasEffect
- {
- get
- {
- lock (Effects)
- return Effects.Any();
- }
- }
-
#endregion
#region Constructors
@@ -156,13 +144,9 @@ namespace CUE.NET.Devices.Keyboard
}
}
- protected override void ApplyEffect(IEffect effect)
+ protected override void DeviceUpdateEffects()
{
- if (effect == null) return;
-
- //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);
+ UpdateEffects();
}
// ReSharper disable once MemberCanBeMadeStatic.Local - idc
@@ -200,6 +184,30 @@ namespace CUE.NET.Devices.Keyboard
#endregion
+ public void UpdateEffects()
+ {
+ lock (_keyGroups)
+ {
+ foreach (IKeyGroup keyGroup in _keyGroups)
+ {
+ keyGroup.UpdateEffects();
+ keyGroup.Brush.UpdateEffects();
+ }
+ }
+
+ Brush.UpdateEffects();
+ }
+
+ public void AddEffect(IEffect effect)
+ {
+ throw new NotSupportedException("Effects can't be applied directly to the keyboard. Add it to the Brush or create a keygroup instead.");
+ }
+
+ public void RemoveEffect(IEffect effect)
+ {
+ throw new NotSupportedException("Effects can't be applied directly to the keyboard. Add it to the Brush or create a keygroup instead.");
+ }
+
///
/// Attaches the given keygroup.
///
diff --git a/Devices/Keyboard/Extensions/KeyGroupExtension.cs b/Devices/Keyboard/Extensions/KeyGroupExtension.cs
index 629974b..3114a5a 100644
--- a/Devices/Keyboard/Extensions/KeyGroupExtension.cs
+++ b/Devices/Keyboard/Extensions/KeyGroupExtension.cs
@@ -13,11 +13,11 @@ namespace CUE.NET.Devices.Keyboard.Extensions
public static class KeyGroupExtension
{
///
- /// Converts the given to a .
+ /// Converts the given to a .
///
- /// The to convert.
+ /// The to convert.
/// The converted .
- public static ListKeyGroup ToSimpleKeyGroup(this BaseKeyGroup keyGroup)
+ public static ListKeyGroup ToSimpleKeyGroup(this AbstractKeyGroup keyGroup)
{
ListKeyGroup simpleKeyGroup = keyGroup as ListKeyGroup;
if (simpleKeyGroup == null)
@@ -34,7 +34,7 @@ namespace CUE.NET.Devices.Keyboard.Extensions
/// The base keygroup.
/// The ids of the keys to exclude.
/// The new .
- public static ListKeyGroup Exclude(this BaseKeyGroup keyGroup, params CorsairKeyboardKeyId[] keyIds)
+ public static ListKeyGroup Exclude(this AbstractKeyGroup keyGroup, params CorsairKeyboardKeyId[] keyIds)
{
ListKeyGroup simpleKeyGroup = keyGroup.ToSimpleKeyGroup();
foreach (CorsairKeyboardKeyId keyId in keyIds)
@@ -48,7 +48,7 @@ namespace CUE.NET.Devices.Keyboard.Extensions
/// The base keygroup.
/// The keys to exclude.
/// The new .
- public static ListKeyGroup Exclude(this BaseKeyGroup keyGroup, params CorsairKey[] keyIds)
+ public static ListKeyGroup Exclude(this AbstractKeyGroup keyGroup, params CorsairKey[] keyIds)
{
ListKeyGroup simpleKeyGroup = keyGroup.ToSimpleKeyGroup();
foreach (CorsairKey key in keyIds)
@@ -62,7 +62,7 @@ namespace CUE.NET.Devices.Keyboard.Extensions
///
/// The keygroup to attach.
/// true if the keygroup could be attached; otherwise, false.
- public static bool Attach(this BaseKeyGroup keyGroup)
+ public static bool Attach(this AbstractKeyGroup keyGroup)
{
return keyGroup.Keyboard?.AttachKeyGroup(keyGroup) ?? false;
}
@@ -72,7 +72,7 @@ namespace CUE.NET.Devices.Keyboard.Extensions
///
/// The keygroup to attach.
/// true if the keygroup could be detached; otherwise, false.
- public static bool Detach(this BaseKeyGroup keyGroup)
+ public static bool Detach(this AbstractKeyGroup keyGroup)
{
return keyGroup.Keyboard?.DetachKeyGroup(keyGroup) ?? false;
}
diff --git a/Devices/Keyboard/Keys/BaseKeyGroup.cs b/Devices/Keyboard/Keys/AbstractKeyGroup.cs
similarity index 87%
rename from Devices/Keyboard/Keys/BaseKeyGroup.cs
rename to Devices/Keyboard/Keys/AbstractKeyGroup.cs
index fa8874c..51927ca 100644
--- a/Devices/Keyboard/Keys/BaseKeyGroup.cs
+++ b/Devices/Keyboard/Keys/AbstractKeyGroup.cs
@@ -4,13 +4,14 @@ using System.Linq;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic;
using CUE.NET.Devices.Keyboard.Extensions;
+using CUE.NET.Effects;
namespace CUE.NET.Devices.Keyboard.Keys
{
///
/// Represents a basic keygroup.
///
- public abstract class BaseKeyGroup : IKeyGroup
+ public abstract class AbstractKeyGroup : AbstractEffectTarget, IKeyGroup
{
#region Properties & Fields
@@ -39,11 +40,11 @@ namespace CUE.NET.Devices.Keyboard.Keys
#region Constructors
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The keyboard this keygroup belongs to.
/// Specifies whether this group should be automatically attached or not.
- protected BaseKeyGroup(CorsairKeyboard keyboard, bool autoAttach = true)
+ protected AbstractKeyGroup(CorsairKeyboard keyboard, bool autoAttach = true)
{
this.Keyboard = keyboard;
diff --git a/Devices/Keyboard/Keys/IKeyGroup.cs b/Devices/Keyboard/Keys/IKeyGroup.cs
index 58891b2..0f60529 100644
--- a/Devices/Keyboard/Keys/IKeyGroup.cs
+++ b/Devices/Keyboard/Keys/IKeyGroup.cs
@@ -4,10 +4,11 @@
using System.Collections.Generic;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic;
+using CUE.NET.Effects;
namespace CUE.NET.Devices.Keyboard.Keys
{
- public interface IKeyGroup
+ public interface IKeyGroup : IEffectTarget
{
///
/// Gets a read-only collection containing the keys from this group.
diff --git a/Devices/Keyboard/Keys/ListKeyGroup.cs b/Devices/Keyboard/Keys/ListKeyGroup.cs
index 009d0bf..b5bb241 100644
--- a/Devices/Keyboard/Keys/ListKeyGroup.cs
+++ b/Devices/Keyboard/Keys/ListKeyGroup.cs
@@ -9,10 +9,12 @@ namespace CUE.NET.Devices.Keyboard.Keys
///
/// Represents a keygroup containing arbitrary keys.
///
- public class ListKeyGroup : BaseKeyGroup
+ public class ListKeyGroup : AbstractKeyGroup
{
#region Properties & Fields
+ protected override IKeyGroup EffectTarget => this;
+
///
/// Gets the list containing the keys of this keygroup.
///
diff --git a/Devices/Keyboard/Keys/RectangleKeyGroup.cs b/Devices/Keyboard/Keys/RectangleKeyGroup.cs
index e02caba..c2a175c 100644
--- a/Devices/Keyboard/Keys/RectangleKeyGroup.cs
+++ b/Devices/Keyboard/Keys/RectangleKeyGroup.cs
@@ -13,10 +13,12 @@ namespace CUE.NET.Devices.Keyboard.Keys
///
/// Represents a keygroup containing keys which physically lay inside a rectangle.
///
- public class RectangleKeyGroup : BaseKeyGroup
+ public class RectangleKeyGroup : AbstractKeyGroup
{
#region Properties & Fields
+ protected override IKeyGroup EffectTarget => this;
+
private IList _keyCache;
private RectangleF _rectangle;
diff --git a/Devices/Mouse/CorsairMouse.cs b/Devices/Mouse/CorsairMouse.cs
index 1b181c3..59d51e7 100644
--- a/Devices/Mouse/CorsairMouse.cs
+++ b/Devices/Mouse/CorsairMouse.cs
@@ -5,11 +5,9 @@
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
@@ -44,11 +42,6 @@ namespace CUE.NET.Devices.Mouse
///
public CorsairMouseDeviceInfo MouseDeviceInfo { get; }
- ///
- /// Gets a value indicating if the mouse has an active effect to deal with or not.
- ///
- protected override bool HasEffect => false;
-
///
/// Gets a read-only collection containing all LEDs of the mouse.
///
@@ -74,13 +67,6 @@ 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)
@@ -108,6 +94,16 @@ namespace CUE.NET.Devices.Mouse
}
}
+ protected override void DeviceUpdate()
+ {
+ //TODO DarthAffe 21.08.2016: Create something fancy for mice
+ }
+
+ protected override void DeviceUpdateEffects()
+ {
+ //TODO DarthAffe 21.08.2016: Create something fancy for mice
+ }
+
#region IEnumerable
///
diff --git a/Effects/AbstractEffect.cs b/Effects/AbstractBrushEffect.cs
similarity index 55%
rename from Effects/AbstractEffect.cs
rename to Effects/AbstractBrushEffect.cs
index c3ea829..3290c34 100644
--- a/Effects/AbstractEffect.cs
+++ b/Effects/AbstractBrushEffect.cs
@@ -1,38 +1,26 @@
// ReSharper disable MemberCanBePrivate.Global
-using System.Collections.Generic;
using CUE.NET.Brushes;
-using CUE.NET.Devices.Generic;
namespace CUE.NET.Effects
{
///
- /// Represents a basic effect.
+ /// Represents a basic effect targeting an .
///
- public abstract class AbstractEffect : IEffect
+ public abstract class AbstractBrushEffect : IEffect
{
#region Properties & Fields
- ///
- /// Gets or sets the list of LEDSs to which the effect applies.
- ///
- public IEnumerable LedList { get; set; }
-
- ///
- /// Gets the brush which is drawn by the effect.
- ///
- public abstract IBrush EffectBrush { get; }
-
- ///
- /// Gets or sets the z-index of the brush to allow ordering them before drawing. (lowest first) (default: 0)
- ///
- public int ZIndex { get; set; } = 0;
-
///
/// Gets or sets if this effect has finished all of his work.
///
public bool IsDone { get; protected set; }
+ ///
+ /// Gets the this effect is targeting.
+ ///
+ protected IBrush Brush { get; private set; }
+
#endregion
#region Methods
@@ -46,14 +34,20 @@ namespace CUE.NET.Effects
///
/// Hook which is called when the effect is attached to a device.
///
- public virtual void OnAttach()
- { }
+ /// The this effect is attached to.
+ public virtual void OnAttach(IBrush target)
+ {
+ Brush = target;
+ }
///
/// Hook which is called when the effect is detached from a device.
///
- public virtual void OnDetach()
- { }
+ /// The this effect is detached from.
+ public virtual void OnDetach(IBrush target)
+ {
+ Brush = null;
+ }
#endregion
}
diff --git a/Effects/AbstractEffectTarget.cs b/Effects/AbstractEffectTarget.cs
new file mode 100644
index 0000000..5ba8315
--- /dev/null
+++ b/Effects/AbstractEffectTarget.cs
@@ -0,0 +1,71 @@
+// ReSharper disable MemberCanBePrivate.Global
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace CUE.NET.Effects
+{
+ public abstract class AbstractEffectTarget : IEffectTarget
+ where T : IEffectTarget
+ {
+ #region Properties & Fields
+
+ private IList _effectTimes = new List();
+ protected IList> Effects => _effectTimes.Select(x => x.Effect).Cast>().ToList();
+ protected abstract T EffectTarget { get; }
+
+ #endregion
+
+ #region Methods
+
+ public void UpdateEffects()
+ {
+ lock (Effects)
+ {
+ for (int i = _effectTimes.Count - 1; i >= 0; i--)
+ {
+ EffectTimeContainer effectTime = _effectTimes[i];
+ long currentTicks = DateTime.Now.Ticks;
+
+ float deltaTime;
+ if (effectTime.TicksAtLastUpdate < 0)
+ {
+ effectTime.TicksAtLastUpdate = currentTicks;
+ deltaTime = 0f;
+ }
+ else
+ deltaTime = (currentTicks - effectTime.TicksAtLastUpdate) / 10000000f;
+
+ effectTime.TicksAtLastUpdate = currentTicks;
+ effectTime.Effect.Update(deltaTime);
+
+
+ if (effectTime.Effect.IsDone)
+ _effectTimes.RemoveAt(i);
+ }
+ }
+ }
+
+ public void AddEffect(IEffect effect)
+ {
+ if (_effectTimes.All(x => x.Effect != effect))
+ {
+ effect.OnAttach(EffectTarget);
+ _effectTimes.Add(new EffectTimeContainer(effect, -1));
+ }
+ }
+
+ public void RemoveEffect(IEffect effect)
+ {
+ EffectTimeContainer effectTimeToRemove = _effectTimes.FirstOrDefault(x => x.Effect == effect);
+ if (effectTimeToRemove != null)
+ {
+ effect.OnDetach(EffectTarget);
+ _effectTimes.Remove(effectTimeToRemove);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Effects/AbstractKeyGroupEffect.cs b/Effects/AbstractKeyGroupEffect.cs
new file mode 100644
index 0000000..71a67ba
--- /dev/null
+++ b/Effects/AbstractKeyGroupEffect.cs
@@ -0,0 +1,54 @@
+// ReSharper disable MemberCanBePrivate.Global
+
+using CUE.NET.Devices.Keyboard.Keys;
+
+namespace CUE.NET.Effects
+{
+ ///
+ /// Represents a basic effect targeting an .
+ ///
+ public abstract class AbstractKeyGroupEffect : IEffect
+ {
+ #region Properties & Fields
+
+ ///
+ /// Gets or sets if this effect has finished all of his work.
+ ///
+ public bool IsDone { get; protected set; }
+
+ ///
+ /// Gets the this effect is targeting.
+ ///
+ protected IKeyGroup KeyGroup { get; private set; }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Updates the effect.
+ ///
+ /// The elapsed time (in seconds) since the last update.
+ public abstract void Update(float deltaTime);
+
+ ///
+ /// Hook which is called when the effect is attached to a device.
+ ///
+ /// The this effect is attached to.
+ public virtual void OnAttach(IKeyGroup target)
+ {
+ KeyGroup = target;
+ }
+
+ ///
+ /// Hook which is called when the effect is detached from a device.
+ ///
+ /// The this effect is detached from.
+ public virtual void OnDetach(IKeyGroup target)
+ {
+ KeyGroup = null;
+ }
+
+ #endregion
+ }
+}
diff --git a/Effects/EffectTimeContainer.cs b/Effects/EffectTimeContainer.cs
index a1c5c8a..25450fa 100644
--- a/Effects/EffectTimeContainer.cs
+++ b/Effects/EffectTimeContainer.cs
@@ -13,18 +13,13 @@ namespace CUE.NET.Effects
///
/// Gets or sets the wrapped effect.
///
- public IEffect Effect { get; set; }
+ public IEffect Effect { get; }
///
/// Gets or sets the tick-count from the last time the effect was updated.
///
public long TicksAtLastUpdate { get; set; }
- ///
- /// Gets the z-index of the effect.
- ///
- public int ZIndex => Effect?.ZIndex ?? 0;
-
#endregion
#region Constructors
diff --git a/Effects/FlashEffect.cs b/Effects/FlashEffect.cs
index 64ee818..da21172 100644
--- a/Effects/FlashEffect.cs
+++ b/Effects/FlashEffect.cs
@@ -3,7 +3,6 @@
// ReSharper disable UnusedMember.Global
using System;
-using System.Drawing;
using CUE.NET.Brushes;
namespace CUE.NET.Effects
@@ -11,15 +10,10 @@ namespace CUE.NET.Effects
///
/// Represents an effect which allows to flash an brush by modifying his opacity.
///
- public class FlashEffect : AbstractEffect
+ public class FlashEffect : AbstractBrushEffect
{
#region Properties & Fields
- ///
- /// Gets the brush which is drawn by the effect.
- ///
- public override IBrush EffectBrush { get; }
-
///
/// Gets or sets the attack-time (in seconds) of the effect. (default: 0.2f)
/// This is close to a synthesizer envelope. (See as reference)
@@ -71,27 +65,6 @@ namespace CUE.NET.Effects
#endregion
- #region Constructors
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The color from which a should be created and used by this effect.
- public FlashEffect(Color flashColor)
- : this(new SolidColorBrush(flashColor))
- { }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The brush which should be used by this effect,
- public FlashEffect(IBrush effectBrush)
- {
- this.EffectBrush = effectBrush;
- }
-
- #endregion
-
#region Methods
///
@@ -106,7 +79,7 @@ namespace CUE.NET.Effects
if (_currentPhase == ADSRPhase.Attack)
if (_currentPhaseValue > 0f)
- EffectBrush.Opacity = Math.Min(1f, (Attack - _currentPhaseValue) / Attack) * AttackValue;
+ Brush.Opacity = Math.Min(1f, (Attack - _currentPhaseValue) / Attack) * AttackValue;
else
{
_currentPhaseValue = Decay;
@@ -115,7 +88,7 @@ namespace CUE.NET.Effects
if (_currentPhase == ADSRPhase.Decay)
if (_currentPhaseValue > 0f)
- EffectBrush.Opacity = SustainValue + (Math.Min(1f, _currentPhaseValue / Decay) * (AttackValue - SustainValue));
+ Brush.Opacity = SustainValue + (Math.Min(1f, _currentPhaseValue / Decay) * (AttackValue - SustainValue));
else
{
_currentPhaseValue = Sustain;
@@ -124,7 +97,7 @@ namespace CUE.NET.Effects
if (_currentPhase == ADSRPhase.Sustain)
if (_currentPhaseValue > 0f)
- EffectBrush.Opacity = SustainValue;
+ Brush.Opacity = SustainValue;
else
{
_currentPhaseValue = Release;
@@ -133,7 +106,7 @@ namespace CUE.NET.Effects
if (_currentPhase == ADSRPhase.Release)
if (_currentPhaseValue > 0f)
- EffectBrush.Opacity = Math.Min(1f, _currentPhaseValue / Release) * SustainValue;
+ Brush.Opacity = Math.Min(1f, _currentPhaseValue / Release) * SustainValue;
else
{
_currentPhaseValue = Interval;
@@ -142,7 +115,7 @@ namespace CUE.NET.Effects
if (_currentPhase == ADSRPhase.Pause)
if (_currentPhaseValue > 0f)
- EffectBrush.Opacity = 0f;
+ Brush.Opacity = 0f;
else
{
if (++_repetitionCount >= Repetitions && Repetitions > 0)
@@ -155,14 +128,14 @@ namespace CUE.NET.Effects
///
/// Resets the effect.
///
- public override void OnAttach()
+ public override void OnAttach(IBrush brush)
{
- base.OnAttach();
+ base.OnAttach(brush);
_currentPhase = ADSRPhase.Attack;
_currentPhaseValue = Attack;
_repetitionCount = 0;
- EffectBrush.Opacity = 0f;
+ brush.Opacity = 0f;
}
#endregion
diff --git a/Effects/IEffect.cs b/Effects/IEffect.cs
index 4cce82c..eb4a663 100644
--- a/Effects/IEffect.cs
+++ b/Effects/IEffect.cs
@@ -1,10 +1,6 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedMemberInSuper.Global
-using System.Collections.Generic;
-using CUE.NET.Brushes;
-using CUE.NET.Devices.Generic;
-
namespace CUE.NET.Effects
{
///
@@ -15,22 +11,7 @@ namespace CUE.NET.Effects
#region Properties & Fields
///
- /// Gets or sets the list of LEDs to which the effect applies.
- ///
- IEnumerable LedList { get; set; }
-
- ///
- /// Gets the brush which is drawn by the effect.
- ///
- IBrush EffectBrush { get; }
-
- ///
- /// Gets or sets the z-index of the effect to allow ordering them before drawing. (lowest first) (default: 0)
- ///
- int ZIndex { get; set; }
-
- ///
- /// Gets or sets if this effect has finished all of his work.
+ /// Gets if this effect has finished all of his work.
///
bool IsDone { get; }
@@ -44,15 +25,29 @@ namespace CUE.NET.Effects
/// The elapsed time (in seconds) since the last update.
void Update(float deltaTime);
+ #endregion
+ }
+
+ ///
+ /// Represents a basic effect.
+ ///
+ /// The type of this effect can be attached to.
+ public interface IEffect : IEffect
+ where T : IEffectTarget
+ {
+ #region Methods
+
///
/// Hook which is called when the effect is attached to a device.
///
- void OnAttach();
+ /// The this effect is attached to.
+ void OnAttach(T target);
///
/// Hook which is called when the effect is detached from a device.
///
- void OnDetach();
+ /// The this effect is detached from.
+ void OnDetach(T target);
#endregion
}
diff --git a/Effects/IEffectTarget.cs b/Effects/IEffectTarget.cs
new file mode 100644
index 0000000..ba08ae2
--- /dev/null
+++ b/Effects/IEffectTarget.cs
@@ -0,0 +1,31 @@
+namespace CUE.NET.Effects
+{
+ ///
+ /// Represents a basic effect-target.
+ ///
+ /// The type this target represents.
+ public interface IEffectTarget
+ where T : IEffectTarget
+ {
+ #region Methods
+
+ ///
+ /// Updates all effects added to this target.
+ ///
+ void UpdateEffects();
+
+ ///
+ /// Adds an affect.
+ ///
+ /// The effect to add.
+ void AddEffect(IEffect effect);
+
+ ///
+ /// Removes an effect
+ ///
+ /// The effect to remove.
+ void RemoveEffect(IEffect effect);
+
+ #endregion
+ }
+}
diff --git a/Effects/RippleEffect.cs b/Effects/RippleEffect.cs
new file mode 100644
index 0000000..721c4bd
--- /dev/null
+++ b/Effects/RippleEffect.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Drawing;
+using CUE.NET.Brushes;
+
+namespace CUE.NET.Effects
+{
+ public class RippleEffect : AbstractEffect
+ {
+ #region Properties & Fields
+
+ private RippleBrush _brush = new RippleBrush();
+ public override IBrush EffectBrush => _brush;
+
+ #endregion
+
+ #region Constructors
+
+ #endregion
+
+ #region Methods
+
+ public override void Update(float deltaTime)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ private class RippleBrush : AbstractBrush
+ {
+ public override Color GetColorAtPoint(RectangleF rectangle, PointF point)
+ {
+ return FinalizeColor(Color.Black);
+ }
+ }
+ }
+}
diff --git a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioAnalyzerExample.cs b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioAnalyzerExample.cs
index ae559e3..2c4ca16 100644
--- a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioAnalyzerExample.cs
+++ b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioAnalyzerExample.cs
@@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.Drawing;
using CUE.NET;
using CUE.NET.Brushes;
+using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard;
+using CUE.NET.Devices.Keyboard.Keys;
using CUE.NET.Exceptions;
using CUE.NET.Gradients;
using Example_AudioAnalyzer_full.TakeAsIs;
@@ -60,18 +62,22 @@ namespace Example_AudioAnalyzer_full
public void Run()
{
- // Add a lack background. We want this to be semi-transparent to add some sort of fade-effect - this will smooth everything out a bit
+ _keyboard.UpdateMode = UpdateMode.Continuous;
+ // Add a black background. We want this to be semi-transparent to add some sort of fade-effect - this will smooth everything out a bit
// Note that this isn't a 'real effect' since it's update-rate dependent. A real effect would do always the same thing not mather how fast the keyboard updates.
_keyboard.Brush = new SolidColorBrush(Color.FromArgb(96, 0, 0, 0));
// Add our song-beat-effect. Remember to uncomment the update in the spectrum effect if you want to remove this.
- _keyboard.AttachEffect(new SongBeatEffect(_soundDataProcessor, Color.FromArgb(127, 164, 164, 164)));
+ ListKeyGroup songBeatGroup = new ListKeyGroup(_keyboard, _keyboard);
+ songBeatGroup.Brush = new SolidColorBrush(Color.FromArgb(127, 164, 164, 164));
+ songBeatGroup.Brush.AddEffect(new SongBeatEffect(_soundDataProcessor));
// Add our spectrum-effect using the soundDataProcessor and a rainbow from purple to red as gradient
- _keyboard.AttachEffect(new AudioSpectrumEffect(_soundDataProcessor, new RainbowGradient(300, -14)));
+ ListKeyGroup spectrumGroup = new ListKeyGroup(_keyboard, _keyboard);
+ spectrumGroup.Brush = new AudioSpectrumBrush(_soundDataProcessor, new RainbowGradient(300, -14));
// Hook onto the keyboard update and process data
_keyboard.Updating += (sender, args) => _soundDataProcessor.Process();
-
+
// If you don't like rainbows replace the gradient with anything you like. For example:
//_keyboard.AttachEffect(new AudioSpectrumEffect(_soundDataProcessor, new LinearGradient(new GradientStop(0f, Color.Blue), new GradientStop(1f, Color.Red))));
diff --git a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumBrush.cs b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumBrush.cs
index 933d2f5..2149bc2 100644
--- a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumBrush.cs
+++ b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumBrush.cs
@@ -11,16 +11,18 @@ namespace Example_AudioAnalyzer_full
{
#region Properties & Fields
- public float[] BarData { get; set; }
+ private SoundDataProcessor _soundDataProcessor;
#endregion
#region Constructors
// default values for start/end are fine
- public AudioSpectrumBrush(IGradient gradient)
+ public AudioSpectrumBrush(SoundDataProcessor soundDataProcessor, IGradient gradient)
: base(gradient)
- { }
+ {
+ this._soundDataProcessor = soundDataProcessor;
+ }
#endregion
@@ -28,11 +30,11 @@ namespace Example_AudioAnalyzer_full
public override Color GetColorAtPoint(RectangleF rectangle, PointF point)
{
- if (BarData == null) return Color.Transparent;
+ if (_soundDataProcessor?.BarValues == null) return Color.Transparent;
// This logic is also stolen from AterialDawn
- int barSampleIndex = (int)Math.Floor(BarData.Length * (point.X / (rectangle.X + rectangle.Width))); // Calculate bar sampling index
- float curBarHeight = 1f - Utility.Clamp(BarData[barSampleIndex], 0f, 1f); // Invert this value since the keyboard is laid out with topleft being point 0,0
+ int barSampleIndex = (int)Math.Floor(_soundDataProcessor.BarValues.Length * (point.X / (rectangle.X + rectangle.Width))); // Calculate bar sampling index
+ float curBarHeight = 1f - Utility.Clamp(_soundDataProcessor.BarValues[barSampleIndex], 0f, 1f); // Invert this value since the keyboard is laid out with topleft being point 0,0
float verticalPos = (point.Y / rectangle.Height);
// If the barHeight is lower than the vertical pos currently calculated return the brush value. Otherwise do nothing by returning transparent.
diff --git a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumEffect.cs b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumEffect.cs
deleted file mode 100644
index 022641c..0000000
--- a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/AudioSpectrumEffect.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using CUE.NET.Brushes;
-using CUE.NET.Effects;
-using CUE.NET.Gradients;
-using Example_AudioAnalyzer_full.TakeAsIs;
-
-namespace Example_AudioAnalyzer_full
-{
- public class AudioSpectrumEffect : AbstractEffect
- {
- #region Properties & Fields
-
- private SoundDataProcessor _dataProcessor;
-
- private AudioSpectrumBrush _audioSpectrumBrush;
- public override IBrush EffectBrush => _audioSpectrumBrush;
-
- #endregion
-
- #region Constructors
-
- public AudioSpectrumEffect(SoundDataProcessor dataProcessor, IGradient gradient)
- {
- this._dataProcessor = dataProcessor;
- _audioSpectrumBrush = new AudioSpectrumBrush(gradient);
-
- // Give this effect a high Z-Index to keep it in the foreground
- ZIndex = 10;
- }
-
- #endregion
-
- #region Methods
-
- public override void Update(float deltaTime)
- {
- _audioSpectrumBrush.BarData = _dataProcessor.BarValues;
- }
-
- #endregion
- }
-}
diff --git a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/Example_AudioAnalyzer_full.csproj b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/Example_AudioAnalyzer_full.csproj
index 6ba9d6d..8bdfa2e 100644
--- a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/Example_AudioAnalyzer_full.csproj
+++ b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/Example_AudioAnalyzer_full.csproj
@@ -62,7 +62,6 @@
-
diff --git a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/SongBeatEffect.cs b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/SongBeatEffect.cs
index 42b54bf..9dfeb96 100644
--- a/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/SongBeatEffect.cs
+++ b/Examples/AudioAnalyzer/Example_AudioAnalyzer_full/SongBeatEffect.cs
@@ -1,11 +1,9 @@
-using System.Drawing;
-using CUE.NET.Brushes;
-using CUE.NET.Effects;
+using CUE.NET.Effects;
using Example_AudioAnalyzer_full.TakeAsIs;
namespace Example_AudioAnalyzer_full
{
- public class SongBeatEffect : AbstractEffect
+ public class SongBeatEffect : AbstractBrushEffect
{
#region Constants
@@ -22,17 +20,13 @@ namespace Example_AudioAnalyzer_full
private float _currentEffect = -1f;
- private SolidColorBrush _brush;
- public override IBrush EffectBrush => _brush;
-
#endregion
#region Constructors
- public SongBeatEffect(SoundDataProcessor dataProcessor, Color color)
+ public SongBeatEffect(SoundDataProcessor dataProcessor)
{
this._dataProcessor = dataProcessor;
- _brush = new SolidColorBrush(color);
}
#endregion
@@ -48,7 +42,7 @@ namespace Example_AudioAnalyzer_full
_currentEffect -= deltaTime;
// and set the current brush-opacity
- _brush.Opacity = _currentEffect > 0f ? (_currentEffect / FLASH_DURATION) : 0f;
+ Brush.Opacity = _currentEffect > 0f ? (_currentEffect / FLASH_DURATION) : 0f;
}
#endregion