1
0
mirror of https://github.com/DarthAffe/CUE.NET.git synced 2025-12-13 00:58:31 +00:00

Merge pull request #21 from DarthAffe/Development

Merge effect engine to resolve #11
This commit is contained in:
DarthAffe 2015-10-09 21:38:09 +02:00
commit e3c885b664
21 changed files with 486 additions and 54 deletions

View File

@ -55,10 +55,15 @@
<Compile Include="Devices\Keyboard\Brushes\RadialGradientBrush.cs" /> <Compile Include="Devices\Keyboard\Brushes\RadialGradientBrush.cs" />
<Compile Include="Devices\Keyboard\Brushes\RandomColorBrush.cs" /> <Compile Include="Devices\Keyboard\Brushes\RandomColorBrush.cs" />
<Compile Include="Devices\Keyboard\Brushes\SolidColorBrush.cs" /> <Compile Include="Devices\Keyboard\Brushes\SolidColorBrush.cs" />
<Compile Include="Devices\Keyboard\Effects\AbstractEffect.cs" />
<Compile Include="Devices\Keyboard\Effects\FlashEffect.cs" />
<Compile Include="Devices\Keyboard\Effects\IEffect.cs" />
<Compile Include="Devices\Keyboard\Effects\EffectTimeContainer.cs" />
<Compile Include="Devices\Keyboard\Enums\CorsairLogicalKeyboardLayout.cs" /> <Compile Include="Devices\Keyboard\Enums\CorsairLogicalKeyboardLayout.cs" />
<Compile Include="Devices\Headset\Enums\CorsairHeadsetLedId.cs" /> <Compile Include="Devices\Headset\Enums\CorsairHeadsetLedId.cs" />
<Compile Include="Devices\Keyboard\Enums\CorsairKeyboardKeyId.cs" /> <Compile Include="Devices\Keyboard\Enums\CorsairKeyboardKeyId.cs" />
<Compile Include="Devices\Keyboard\Enums\CorsairPhysicalKeyboardLayout.cs" /> <Compile Include="Devices\Keyboard\Enums\CorsairPhysicalKeyboardLayout.cs" />
<Compile Include="Devices\Generic\Enums\UpdateMode.cs" />
<Compile Include="Devices\Keyboard\Keys\BaseKeyGroup.cs" /> <Compile Include="Devices\Keyboard\Keys\BaseKeyGroup.cs" />
<Compile Include="Devices\Keyboard\Keys\IKeyGroup.cs" /> <Compile Include="Devices\Keyboard\Keys\IKeyGroup.cs" />
<Compile Include="Devices\Keyboard\Keys\RectangleKeyGroup.cs" /> <Compile Include="Devices\Keyboard\Keys\RectangleKeyGroup.cs" />

View File

@ -3,18 +3,40 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Native; using CUE.NET.Native;
namespace CUE.NET.Devices.Generic namespace CUE.NET.Devices.Generic
{ {
public abstract class AbstractCueDevice : ICueDevice public abstract class AbstractCueDevice : ICueDevice
{ {
private UpdateMode _updateMode = UpdateMode.AutoOnEffect;
#region Properties & Fields #region Properties & Fields
public IDeviceInfo DeviceInfo { get; } public IDeviceInfo DeviceInfo { get; }
public UpdateMode UpdateMode
{
get { return _updateMode; }
set
{
_updateMode = value;
CheckUpdateLoop();
}
}
public float UpdateFrequency { get; set; } = 1f / 30f;
private Dictionary<int, CorsairLed> Leds { get; } = new Dictionary<int, CorsairLed>(); private Dictionary<int, CorsairLed> Leds { get; } = new Dictionary<int, CorsairLed>();
protected abstract bool HasEffect { get; }
private CancellationTokenSource _updateTokenSource;
private CancellationToken _updateToken;
private Task _updateTask;
#endregion #endregion
#region Constructors #region Constructors
@ -22,6 +44,8 @@ namespace CUE.NET.Devices.Generic
protected AbstractCueDevice(IDeviceInfo info) protected AbstractCueDevice(IDeviceInfo info)
{ {
this.DeviceInfo = info; this.DeviceInfo = info;
CheckUpdateLoop();
} }
#endregion #endregion
@ -36,16 +60,61 @@ namespace CUE.NET.Devices.Generic
return Leds[ledId]; return Leds[ledId];
} }
public virtual void UpdateLeds(bool forceUpdate = false) protected async void CheckUpdateLoop()
{ {
IList<KeyValuePair<int, CorsairLed>> 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<KeyValuePair<int, CorsairLed>> ledsToUpdate = (flushLeds ? Leds : Leds.Where(x => x.Value.IsDirty)).ToList();
foreach (CorsairLed led in Leds.Values) foreach (CorsairLed led in Leds.Values)
led.Update(); led.Update();
UpdateLeds(ledsToUpdate); UpdateLeds(ledsToUpdate);
} }
private static void UpdateLeds(ICollection<KeyValuePair<int, CorsairLed>> ledsToUpdate) private static void UpdateLeds(ICollection<KeyValuePair<int, CorsairLed>> ledsToUpdate)
{ {
ledsToUpdate = ledsToUpdate.Where(x => x.Value.Color != Color.Transparent).ToList(); ledsToUpdate = ledsToUpdate.Where(x => x.Value.Color != Color.Transparent).ToList();

View File

@ -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; using CUE.NET.Helper;
namespace CUE.NET.Devices.Generic namespace CUE.NET.Devices.Generic
@ -28,8 +32,6 @@ namespace CUE.NET.Devices.Generic
public bool IsLocked { get; set; } = false; public bool IsLocked { get; set; } = false;
//TODO DarthAffe 19.09.2015: Add effects and stuff
#endregion #endregion
#region Constructors #region Constructors

View File

@ -0,0 +1,9 @@
namespace CUE.NET.Devices.Generic.Enums
{
public enum UpdateMode
{
Manual,
AutoOnEffect,
Continuous
}
}

View File

@ -7,6 +7,8 @@ namespace CUE.NET.Devices.Headset
{ {
#region Properties & Fields #region Properties & Fields
protected override bool HasEffect => false;
#endregion #endregion
#region Constructors #region Constructors

View File

@ -1,9 +1,15 @@
namespace CUE.NET.Devices using CUE.NET.Devices.Generic.Enums;
namespace CUE.NET.Devices
{ {
public interface ICueDevice public interface ICueDevice
{ {
IDeviceInfo DeviceInfo { get; } IDeviceInfo DeviceInfo { get; }
void UpdateLeds(bool forceUpdate = false); UpdateMode UpdateMode { get; set; }
float UpdateFrequency { get; set; }
void Update(bool flushLeds = false);
} }
} }

View File

@ -1,4 +1,6 @@
using System.Collections.Generic; // ReSharper disable MemberCanBeProtected.Global
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
@ -14,10 +16,10 @@ namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
#region Constructors #region Constructors
public AbstractGradient() protected AbstractGradient()
{ } { }
public AbstractGradient(params GradientStop[] gradientStops) protected AbstractGradient(params GradientStop[] gradientStops)
{ {
foreach (GradientStop gradientStop in gradientStops) foreach (GradientStop gradientStop in gradientStops)
GradientStops.Add(gradientStop); GradientStops.Add(gradientStop);

View File

@ -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 namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
{ {

View File

@ -1,6 +1,7 @@
// ReSharper disable CollectionNeverUpdated.Global // ReSharper disable CollectionNeverUpdated.Global
// ReSharper disable MemberCanBePrivate.Global // ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ReturnTypeCanBeEnumerable.Global // ReSharper disable ReturnTypeCanBeEnumerable.Global
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
using System.Drawing; using System.Drawing;
using CUE.NET.Devices.Keyboard.Brushes.Gradient; using CUE.NET.Devices.Keyboard.Brushes.Gradient;

View File

@ -1,4 +1,7 @@
using System; // ReSharper disable MemberCanBePrivate.Global
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
using System;
using System.Drawing; using System.Drawing;
using CUE.NET.Devices.Keyboard.Brushes.Gradient; using CUE.NET.Devices.Keyboard.Brushes.Gradient;
using CUE.NET.Helper; 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); 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) // 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), 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.Width, rectangle.Y), centerPoint)),
GradientHelper.CalculateDistance(new PointF(rectangle.X, rectangle.Y + rectangle.Height), centerPoint)), GradientHelper.CalculateDistance(new PointF(rectangle.X, rectangle.Y + rectangle.Height), centerPoint)),

View File

@ -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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -7,6 +11,7 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CUE.NET.Devices.Generic; using CUE.NET.Devices.Generic;
using CUE.NET.Devices.Keyboard.Brushes; using CUE.NET.Devices.Keyboard.Brushes;
using CUE.NET.Devices.Keyboard.Effects;
using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Keyboard.Enums;
using CUE.NET.Devices.Keyboard.Keys; using CUE.NET.Devices.Keyboard.Keys;
using CUE.NET.Helper; using CUE.NET.Helper;
@ -18,11 +23,8 @@ namespace CUE.NET.Devices.Keyboard
{ {
#region Properties & Fields #region Properties & Fields
public CorsairKeyboardDeviceInfo KeyboardDeviceInfo { get; } #region Indexer
public RectangleF KeyboardRectangle { get; private set; }
private Dictionary<CorsairKeyboardKeyId, CorsairKey> _keys = new Dictionary<CorsairKeyboardKeyId, CorsairKey>();
public CorsairKey this[CorsairKeyboardKeyId keyId] public CorsairKey this[CorsairKeyboardKeyId keyId]
{ {
get get
@ -30,32 +32,34 @@ namespace CUE.NET.Devices.Keyboard
CorsairKey key; CorsairKey key;
return _keys.TryGetValue(keyId, out key) ? key : null; return _keys.TryGetValue(keyId, out key) ? key : null;
} }
private set { throw new NotSupportedException(); }
} }
public CorsairKey this[char key] public CorsairKey this[char key] => this[_CUESDK.CorsairGetLedIdForKeyName(key)];
{
get { return this[_CUESDK.CorsairGetLedIdForKeyName(key)]; }
private set { throw new NotSupportedException(); }
}
public CorsairKey this[PointF location] public CorsairKey this[PointF location] => _keys.Values.FirstOrDefault(x => x.KeyRectangle.Contains(location));
{
get { return _keys.Values.FirstOrDefault(x => x.KeyRectangle.Contains(location)); }
private set { throw new NotSupportedException(); }
}
public IEnumerable<CorsairKey> this[RectangleF referenceRect, float minOverlayPercentage = 0.5f] public IEnumerable<CorsairKey> this[RectangleF referenceRect, float minOverlayPercentage = 0.5f] => _keys.Values.Where(x => RectangleHelper.CalculateIntersectPercentage(x.KeyRectangle, referenceRect) >= minOverlayPercentage);
{
get { return _keys.Values.Where(x => RectangleHelper.CalculateIntersectPercentage(x.KeyRectangle, referenceRect) >= minOverlayPercentage); }
private set { throw new NotSupportedException(); }
}
#endregion
private readonly LinkedList<IKeyGroup> _keyGroups = new LinkedList<IKeyGroup>();
private readonly LinkedList<EffectTimeContainer> _effects = new LinkedList<EffectTimeContainer>();
private Dictionary<CorsairKeyboardKeyId, CorsairKey> _keys = new Dictionary<CorsairKeyboardKeyId, CorsairKey>();
public IEnumerable<CorsairKey> Keys => new ReadOnlyCollection<CorsairKey>(_keys.Values.ToList()); public IEnumerable<CorsairKey> Keys => new ReadOnlyCollection<CorsairKey>(_keys.Values.ToList());
public CorsairKeyboardDeviceInfo KeyboardDeviceInfo { get; }
public RectangleF KeyboardRectangle { get; private set; }
public IBrush Brush { get; set; } public IBrush Brush { get; set; }
private readonly IList<IKeyGroup> _keyGroups = new List<IKeyGroup>(); protected override bool HasEffect
{
get
{
lock (_effects)
return _effects.Any();
}
}
#endregion #endregion
@ -74,21 +78,62 @@ namespace CUE.NET.Devices.Keyboard
#region Methods #region Methods
public override void UpdateLeds(bool forceUpdate = false) #region Update
{
// Apply all KeyGroups
public override void Update(bool flushLeds = false)
{
UpdateKeyGroups();
UpdateEffects();
// Perform 'real' update
base.Update(flushLeds);
}
private void UpdateEffects()
{
List<IEffect> effectsToRemove = new List<IEffect>();
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) if (Brush != null)
ApplyBrush(this.ToList(), Brush); ApplyBrush(this.ToList(), Brush);
//TODO DarthAffe 20.09.2015: Add some sort of priority lock (_keyGroups)
foreach (IKeyGroup keyGroup in _keyGroups) {
ApplyBrush(keyGroup.Keys.ToList(), keyGroup.Brush); //TODO DarthAffe 20.09.2015: Add some sort of priority
foreach (IKeyGroup keyGroup in _keyGroups)
// Perform 'real' update ApplyBrush(keyGroup.Keys.ToList(), keyGroup.Brush);
base.UpdateLeds(forceUpdate); }
} }
// ReSharper disable once MemberCanBeMadeStatic.Local - idc
private void ApplyBrush(ICollection<CorsairKey> keys, IBrush brush) private void ApplyBrush(ICollection<CorsairKey> keys, IBrush brush)
{ {
RectangleF brushRectangle = RectangleHelper.CreateRectangleFromRectangles(keys.Select(x => x.KeyRectangle)); 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()); key.Led.Color = brush.GetColorAtPoint(brushRectangle, key.KeyRectangle.GetCenter());
} }
#endregion
public bool AttachKeyGroup(IKeyGroup keyGroup) 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); _keyGroups.AddLast(keyGroup);
return true; return true;
}
} }
public bool DetachKeyGroup(IKeyGroup keyGroup) public bool DetachKeyGroup(IKeyGroup keyGroup)
{ {
if (keyGroup == null || !_keyGroups.Contains(keyGroup)) return false; lock (_keyGroups)
{
if (keyGroup == null) return false;
_keyGroups.Remove(keyGroup); LinkedListNode<IKeyGroup> node = _keyGroups.Find(keyGroup);
return true; 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() private void InitializeKeys()

View File

@ -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<CorsairKey> 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
}
}

View File

@ -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
}
}

View File

@ -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
}
}
}

View File

@ -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<CorsairKey> KeyList { get; }
bool IsDone { get; }
#endregion
#region Methods
void Update(float deltaTime);
void OnAttach();
void OnDetach();
#endregion
}
}

View File

@ -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.Enums;
using CUE.NET.Devices.Keyboard.Keys; using CUE.NET.Devices.Keyboard.Keys;
@ -33,6 +35,7 @@ namespace CUE.NET.Devices.Keyboard.Extensions
return simpleKeyGroup; return simpleKeyGroup;
} }
// ReSharper disable once UnusedMethodReturnValue.Global
public static bool Attach(this BaseKeyGroup keyGroup) public static bool Attach(this BaseKeyGroup keyGroup)
{ {
return keyGroup.Keyboard?.AttachKeyGroup(keyGroup) ?? false; return keyGroup.Keyboard?.AttachKeyGroup(keyGroup) ?? false;

View File

@ -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.Generic;
using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Keyboard.Enums;

View File

@ -1,4 +1,6 @@
using System.Collections.Generic; // ReSharper disable MemberCanBePrivate.Global
using System.Collections.Generic;
using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Keyboard.Enums;
namespace CUE.NET.Devices.Keyboard.Keys namespace CUE.NET.Devices.Keyboard.Keys

View File

@ -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.Drawing;
using System.Linq; using System.Linq;
using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Keyboard.Enums;

View File

@ -9,6 +9,8 @@ namespace CUE.NET.Devices.Mouse
public CorsairMouseDeviceInfo MouseDeviceInfo { get; } public CorsairMouseDeviceInfo MouseDeviceInfo { get; }
protected override bool HasEffect => false;
#endregion #endregion
#region Constructors #region Constructors

View File

@ -36,6 +36,7 @@ namespace CUE.NET.Helper
private static byte GetIntColorFromFloat(float f) private static byte GetIntColorFromFloat(float f)
{ {
// ReSharper disable once RedundantCast - never trust this ...
float calcF = (float)Math.Max(0f, Math.Min(1f, f)); float calcF = (float)Math.Max(0f, Math.Min(1f, f));
return (byte)(calcF.Equals(1f) ? 255 : calcF * 256f); 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 max = Math.Max(color.R, Math.Max(color.G, color.B));
int min = Math.Min(color.R, Math.Min(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); return (max == 0) ? 0 : 1f - ((float)min / (float)max);
// ReSharper restore RedundantCast
} }
public static float GetHSVValue(this Color color) public static float GetHSVValue(this Color color)