diff --git a/RGB.NET.Core/Effects/AbstractBrushEffect.cs b/RGB.NET.Core/Effects/AbstractBrushEffect.cs new file mode 100644 index 0000000..12ef4e8 --- /dev/null +++ b/RGB.NET.Core/Effects/AbstractBrushEffect.cs @@ -0,0 +1,54 @@ +// ReSharper disable MemberCanBePrivate.Global + +namespace RGB.NET.Core +{ + /// + /// Represents a basic effect targeting an . + /// + public abstract class AbstractBrushEffect : IEffect + where T : IBrush + { + #region Properties & Fields + + /// + public bool IsDone { get; protected set; } + + /// + /// Gets the this effect is targeting. + /// + protected T Brush { get; set; } + + #endregion + + #region Methods + + /// + public abstract void Update(double deltaTime); + + /// + public virtual bool CanBeAppliedTo(IBrush target) + { + return target is T; + } + + /// + public virtual void OnAttach(IBrush target) + { + Brush = (T)target; + } + + /// + public virtual void OnDetach(IBrush target) + { + Brush = default(T); + } + + #endregion + } + + /// + /// Represents a basic effect targeting an . + /// + public abstract class AbstractBrushEffect : AbstractBrushEffect + { } +} diff --git a/RGB.NET.Core/Effects/AbstractLedGroupEffect.cs b/RGB.NET.Core/Effects/AbstractLedGroupEffect.cs new file mode 100644 index 0000000..2e2dcfe --- /dev/null +++ b/RGB.NET.Core/Effects/AbstractLedGroupEffect.cs @@ -0,0 +1,56 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable UnusedMember.Global + +namespace RGB.NET.Core +{ + /// + /// Represents a basic effect targeting an . + /// + public abstract class AbstractLedGroupEffect : IEffect + where T : ILedGroup + { + #region Properties & Fields + + /// + public bool IsDone { get; protected set; } + + /// + /// Gets the this effect is targeting. + /// + protected T LedGroup { get; set; } + + #endregion + + #region Methods + + /// + public abstract void Update(double deltaTime); + + /// + public virtual bool CanBeAppliedTo(ILedGroup target) + { + return target is T; + } + + /// + public virtual void OnAttach(ILedGroup target) + { + LedGroup = (T)target; + } + + /// + public virtual void OnDetach(ILedGroup target) + { + LedGroup = default(T); + } + + #endregion + } + + /// + /// Represents a basic effect targeting an . + /// + public abstract class AbstractLedGroupEffect : AbstractLedGroupEffect + { } +} diff --git a/RGB.NET.Core/RGB.NET.Core.csproj b/RGB.NET.Core/RGB.NET.Core.csproj index 297a8d3..f219385 100644 --- a/RGB.NET.Core/RGB.NET.Core.csproj +++ b/RGB.NET.Core/RGB.NET.Core.csproj @@ -51,7 +51,9 @@ + + diff --git a/RGB.NET.Effects/Effects/FlashEffect.cs b/RGB.NET.Effects/Effects/FlashEffect.cs new file mode 100644 index 0000000..daab23a --- /dev/null +++ b/RGB.NET.Effects/Effects/FlashEffect.cs @@ -0,0 +1,153 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +// ReSharper disable UnusedMember.Global + +using System; +using RGB.NET.Core; + +namespace RGB.NET.Effects +{ + /// + /// Represents an effect which allows to flash an brush by modifying his opacity. + /// + public class FlashEffect : AbstractBrushEffect + { + #region Properties & Fields + + /// + /// Gets or sets the attack-time (in seconds) of the effect. (default: 0.2)
+ /// This is close to a synthesizer envelope. (See as reference) + ///
+ public double Attack { get; set; } = 0.2; + + /// + /// Gets or sets the decay-time (in seconds) of the effect. (default: 0)
+ /// This is close to a synthesizer envelope. (See as reference) + ///
+ public double Decay { get; set; } = 0; + + /// + /// Gets or sets the sustain-time (in seconds) of the effect. (default: 0.3)
+ /// This is close to a synthesizer envelope. (See as reference)
+ /// Note that this value for naming reasons represents the time NOT the level. + ///
+ public double Sustain { get; set; } = 0.3; + + /// + /// Gets or sets the release-time (in seconds) of the effect. (default: 0.2)
+ /// This is close to a synthesizer envelope. (See as reference) + ///
+ public double Release { get; set; } = 0.2; + + /// + /// Gets or sets the level to which the oppacity (percentage) should raise in the attack-cycle. (default: 1); + /// + public double AttackValue { get; set; } = 1; + + /// + /// Gets or sets the level at which the oppacity (percentage) should stay in the sustain-cycle. (default: 1); + /// + public double SustainValue { get; set; } = 1; + + /// + /// Gets or sets the interval (in seconds) in which the effect should repeat (if repetition is enabled). (default: 1) + /// + public double Interval { get; set; } = 1; + + /// + /// Gets or sets the amount of repetitions the effect should do until it's finished. Zero means infinite. (default: 0) + /// + public int Repetitions { get; set; } = 0; + + private ADSRPhase _currentPhase; + private double _currentPhaseValue; + private int _repetitionCount; + + #endregion + + #region Methods + + /// + public override void Update(double deltaTime) + { + _currentPhaseValue -= deltaTime; + + // Using ifs instead of a switch allows to skip phases with time 0. + // ReSharper disable InvertIf + + if (_currentPhase == ADSRPhase.Attack) + if (_currentPhaseValue > 0) + Brush.Opacity = Math.Min(1, (Attack - _currentPhaseValue) / Attack) * AttackValue; + else + { + _currentPhaseValue = Decay; + _currentPhase = ADSRPhase.Decay; + } + + if (_currentPhase == ADSRPhase.Decay) + if (_currentPhaseValue > 0) + Brush.Opacity = SustainValue + (Math.Min(1, _currentPhaseValue / Decay) * (AttackValue - SustainValue)); + else + { + _currentPhaseValue = Sustain; + _currentPhase = ADSRPhase.Sustain; + } + + if (_currentPhase == ADSRPhase.Sustain) + if (_currentPhaseValue > 0) + Brush.Opacity = SustainValue; + else + { + _currentPhaseValue = Release; + _currentPhase = ADSRPhase.Release; + } + + if (_currentPhase == ADSRPhase.Release) + if (_currentPhaseValue > 0) + Brush.Opacity = Math.Min(1, _currentPhaseValue / Release) * SustainValue; + else + { + _currentPhaseValue = Interval; + _currentPhase = ADSRPhase.Pause; + } + + if (_currentPhase == ADSRPhase.Pause) + if (_currentPhaseValue > 0) + Brush.Opacity = 0; + else + { + if ((++_repetitionCount >= Repetitions) && (Repetitions > 0)) + IsDone = true; + _currentPhaseValue = Attack; + _currentPhase = ADSRPhase.Attack; + } + + // ReSharper restore InvertIf + } + + /// + /// Resets the effect. + /// + public override void OnAttach(IBrush brush) + { + base.OnAttach(brush); + + _currentPhase = ADSRPhase.Attack; + _currentPhaseValue = Attack; + _repetitionCount = 0; + brush.Opacity = 0; + } + + #endregion + + // ReSharper disable once InconsistentNaming + private enum ADSRPhase + { + Attack, + Decay, + Sustain, + Release, + Pause + } + } +} diff --git a/RGB.NET.Effects/Effects/MoveGradientEffect.cs b/RGB.NET.Effects/Effects/MoveGradientEffect.cs new file mode 100644 index 0000000..92452e8 --- /dev/null +++ b/RGB.NET.Effects/Effects/MoveGradientEffect.cs @@ -0,0 +1,101 @@ +using RGB.NET.Brushes; +using RGB.NET.Brushes.Gradients; +using RGB.NET.Core; + +namespace RGB.NET.Effects +{ + /// + /// Represents an effect which allows to move an by modifying his offset. + /// + public class MoveGradientEffect : AbstractBrushEffect + { + #region Properties & Fields + // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + // ReSharper disable MemberCanBePrivate.Global + + /// + /// Gets or sets the direction the is moved. + /// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left). + /// + public bool Direction { get; set; } + + /// + /// Gets or sets the speed of the movement in units per second. + /// The meaning of units differs for the different , but 360 units will always be one complete cycle: + /// : 360 unit = 1 offset. + /// : 1 unit = 1 degree. + /// + public double Speed { get; set; } + + // ReSharper restore MemberCanBePrivate.Global + // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global + #endregion + + #region Constructors + + /// + /// + /// + /// + /// + public MoveGradientEffect(double speed = 180.0, bool direction = true) + { + this.Speed = speed; + this.Direction = direction; + } + + #endregion + + #region Methods + + /// + public override void Update(double deltaTime) + { + double movement = Speed * deltaTime; + + if (!Direction) + movement = -movement; + + // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull + if (Brush.Gradient is LinearGradient) + { + LinearGradient linearGradient = (LinearGradient)Brush.Gradient; + + movement /= 360.0; + + foreach (GradientStop gradientStop in linearGradient.GradientStops) + { + gradientStop.Offset = gradientStop.Offset + movement; + + if (gradientStop.Offset > 1) + gradientStop.Offset -= 1; + else if (gradientStop.Offset < 0) + gradientStop.Offset += 1; + } + } + else if (Brush.Gradient is RainbowGradient) + { + RainbowGradient rainbowGradient = (RainbowGradient)Brush.Gradient; + + // RainbowGradient is calculated inverse but the movement should be the same for all. + movement *= -1; + + rainbowGradient.StartHue += movement; + rainbowGradient.EndHue += movement; + + if ((rainbowGradient.StartHue > 360) && (rainbowGradient.EndHue > 360)) + { + rainbowGradient.StartHue -= 360; + rainbowGradient.EndHue -= 360; + } + else if ((rainbowGradient.StartHue < -360) && (rainbowGradient.EndHue < -360)) + { + rainbowGradient.StartHue += 360; + rainbowGradient.EndHue += 360; + } + } + } + + #endregion + } +} diff --git a/RGB.NET.Effects/RGB.NET.Effects.csproj b/RGB.NET.Effects/RGB.NET.Effects.csproj index 4a65052..78143b9 100644 --- a/RGB.NET.Effects/RGB.NET.Effects.csproj +++ b/RGB.NET.Effects/RGB.NET.Effects.csproj @@ -31,6 +31,14 @@ 4 + + ..\packages\RGB.NET.Brushes.1.0.0\lib\net45\RGB.NET.Brushes.dll + True + + + ..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.dll + True + @@ -41,8 +49,13 @@ + + + + +