mirror of
https://github.com/DarthAffe/RGB.NET.git
synced 2026-11-11 21:16:24 +00:00
Changed all namespaces to file-scope
This commit is contained in:
1 parent
a0c6ccebea
commit
30624035f1
353 files changed
+35775
-36129
No files matched your search
@@ -5,173 +5,172 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Decorators
|
||||
namespace RGB.NET.Presets.Decorators;
|
||||
|
||||
/// <inheritdoc cref="AbstractUpdateAwareDecorator" />
|
||||
/// <inheritdoc cref="IBrushDecorator" />
|
||||
/// <summary>
|
||||
/// Represents a decorator which allows to flash a brush by modifying his opacity.
|
||||
/// </summary>
|
||||
public class FlashDecorator : AbstractUpdateAwareDecorator, IBrushDecorator
|
||||
{
|
||||
/// <inheritdoc cref="AbstractUpdateAwareDecorator" />
|
||||
/// <inheritdoc cref="IBrushDecorator" />
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Represents a decorator which allows to flash a brush by modifying his opacity.
|
||||
/// Gets or sets the attack-time (in seconds) of the decorator. (default: 0.2)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)
|
||||
/// </summary>
|
||||
public class FlashDecorator : AbstractUpdateAwareDecorator, IBrushDecorator
|
||||
public float Attack { get; set; } = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the decay-time (in seconds) of the decorator. (default: 0)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)
|
||||
/// </summary>
|
||||
public float Decay { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sustain-time (in seconds) of the decorator. (default: 0.3)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)<br />
|
||||
/// Note that this value for naming reasons represents the time NOT the level.
|
||||
/// </summary>
|
||||
public float Sustain { get; set; } = 0.3f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the release-time (in seconds) of the decorator. (default: 0.2)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)
|
||||
/// </summary>
|
||||
public float Release { get; set; } = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level to which the oppacity (percentage) should raise in the attack-cycle. (default: 1);
|
||||
/// </summary>
|
||||
public float AttackValue { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level at which the oppacity (percentage) should stay in the sustain-cycle. (default: 1);
|
||||
/// </summary>
|
||||
public float SustainValue { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level at which the oppacity (percentage) should stay in the pause-cycle. (default: 0);
|
||||
/// </summary>
|
||||
public float PauseValue { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the interval (in seconds) in which the decorator should repeat (if repetition is enabled). (default: 1)
|
||||
/// </summary>
|
||||
public float Interval { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount of repetitions the decorator should do until it's finished. Zero means infinite. (default: 0)
|
||||
/// </summary>
|
||||
public int Repetitions { get; set; } = 0;
|
||||
|
||||
private ADSRPhase _currentPhase;
|
||||
private float _currentPhaseValue;
|
||||
private int _repetitionCount;
|
||||
|
||||
private float _currentValue;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="FlashDecorator"/> from the specified xml.
|
||||
/// </summary>
|
||||
/// <param name="surface">The surface this decorator belongs to.</param>
|
||||
/// <param name="updateIfDisabled">A value indicating if the decorator should be updated if it is disabled.</param>
|
||||
public FlashDecorator(RGBSurface surface, bool updateIfDisabled = false)
|
||||
: base(surface, updateIfDisabled)
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ManipulateColor(in Rectangle rectangle, in RenderTarget renderTarget, ref Color color) => color = color.SetA(_currentValue);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(double deltaTime)
|
||||
{
|
||||
#region Properties & Fields
|
||||
_currentPhaseValue -= (float)deltaTime;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the attack-time (in seconds) of the decorator. (default: 0.2)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)
|
||||
/// </summary>
|
||||
public float Attack { get; set; } = 0.2f;
|
||||
// Using ifs instead of a switch allows to skip phases with time 0.
|
||||
// ReSharper disable InvertIf
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the decay-time (in seconds) of the decorator. (default: 0)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)
|
||||
/// </summary>
|
||||
public float Decay { get; set; } = 0;
|
||||
if (_currentPhase == ADSRPhase.Attack)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = PauseValue + (MathF.Min(1, (Attack - _currentPhaseValue) / Attack) * (AttackValue - PauseValue));
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Decay;
|
||||
_currentPhase = ADSRPhase.Decay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sustain-time (in seconds) of the decorator. (default: 0.3)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)<br />
|
||||
/// Note that this value for naming reasons represents the time NOT the level.
|
||||
/// </summary>
|
||||
public float Sustain { get; set; } = 0.3f;
|
||||
if (_currentPhase == ADSRPhase.Decay)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = SustainValue + (MathF.Min(1, _currentPhaseValue / Decay) * (AttackValue - SustainValue));
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Sustain;
|
||||
_currentPhase = ADSRPhase.Sustain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the release-time (in seconds) of the decorator. (default: 0.2)<br />
|
||||
/// This is close to a synthesizer envelope. (See <see href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope" /> as reference)
|
||||
/// </summary>
|
||||
public float Release { get; set; } = 0.2f;
|
||||
if (_currentPhase == ADSRPhase.Sustain)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = SustainValue;
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Release;
|
||||
_currentPhase = ADSRPhase.Release;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level to which the oppacity (percentage) should raise in the attack-cycle. (default: 1);
|
||||
/// </summary>
|
||||
public float AttackValue { get; set; } = 1;
|
||||
if (_currentPhase == ADSRPhase.Release)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = PauseValue + (MathF.Min(1, _currentPhaseValue / Release) * (SustainValue - PauseValue));
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Interval;
|
||||
_currentPhase = ADSRPhase.Pause;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level at which the oppacity (percentage) should stay in the sustain-cycle. (default: 1);
|
||||
/// </summary>
|
||||
public float SustainValue { get; set; } = 1;
|
||||
if (_currentPhase == ADSRPhase.Pause)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = PauseValue;
|
||||
else
|
||||
{
|
||||
if ((++_repetitionCount >= Repetitions) && (Repetitions > 0))
|
||||
Detach();
|
||||
_currentPhaseValue = Attack;
|
||||
_currentPhase = ADSRPhase.Attack;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level at which the oppacity (percentage) should stay in the pause-cycle. (default: 0);
|
||||
/// </summary>
|
||||
public float PauseValue { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the interval (in seconds) in which the decorator should repeat (if repetition is enabled). (default: 1)
|
||||
/// </summary>
|
||||
public float Interval { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount of repetitions the decorator should do until it's finished. Zero means infinite. (default: 0)
|
||||
/// </summary>
|
||||
public int Repetitions { get; set; } = 0;
|
||||
|
||||
private ADSRPhase _currentPhase;
|
||||
private float _currentPhaseValue;
|
||||
private int _repetitionCount;
|
||||
|
||||
private float _currentValue;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="FlashDecorator"/> from the specified xml.
|
||||
/// </summary>
|
||||
/// <param name="surface">The surface this decorator belongs to.</param>
|
||||
/// <param name="updateIfDisabled">A value indicating if the decorator should be updated if it is disabled.</param>
|
||||
public FlashDecorator(RGBSurface surface, bool updateIfDisabled = false)
|
||||
: base(surface, updateIfDisabled)
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ManipulateColor(in Rectangle rectangle, in RenderTarget renderTarget, ref Color color) => color = color.SetA(_currentValue);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(double deltaTime)
|
||||
{
|
||||
_currentPhaseValue -= (float)deltaTime;
|
||||
|
||||
// Using ifs instead of a switch allows to skip phases with time 0.
|
||||
// ReSharper disable InvertIf
|
||||
|
||||
if (_currentPhase == ADSRPhase.Attack)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = PauseValue + (MathF.Min(1, (Attack - _currentPhaseValue) / Attack) * (AttackValue - PauseValue));
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Decay;
|
||||
_currentPhase = ADSRPhase.Decay;
|
||||
}
|
||||
|
||||
if (_currentPhase == ADSRPhase.Decay)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = SustainValue + (MathF.Min(1, _currentPhaseValue / Decay) * (AttackValue - SustainValue));
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Sustain;
|
||||
_currentPhase = ADSRPhase.Sustain;
|
||||
}
|
||||
|
||||
if (_currentPhase == ADSRPhase.Sustain)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = SustainValue;
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Release;
|
||||
_currentPhase = ADSRPhase.Release;
|
||||
}
|
||||
|
||||
if (_currentPhase == ADSRPhase.Release)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = PauseValue + (MathF.Min(1, _currentPhaseValue / Release) * (SustainValue - PauseValue));
|
||||
else
|
||||
{
|
||||
_currentPhaseValue = Interval;
|
||||
_currentPhase = ADSRPhase.Pause;
|
||||
}
|
||||
|
||||
if (_currentPhase == ADSRPhase.Pause)
|
||||
if (_currentPhaseValue > 0)
|
||||
_currentValue = PauseValue;
|
||||
else
|
||||
{
|
||||
if ((++_repetitionCount >= Repetitions) && (Repetitions > 0))
|
||||
Detach();
|
||||
_currentPhaseValue = Attack;
|
||||
_currentPhase = ADSRPhase.Attack;
|
||||
}
|
||||
|
||||
// ReSharper restore InvertIf
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="AbstractUpdateAwareDecorator.OnAttached" />
|
||||
/// <inheritdoc cref="IDecorator.OnAttached" />
|
||||
public override void OnAttached(IDecoratable decoratable)
|
||||
{
|
||||
base.OnAttached(decoratable);
|
||||
|
||||
_currentPhase = ADSRPhase.Attack;
|
||||
_currentPhaseValue = Attack;
|
||||
_repetitionCount = 0;
|
||||
_currentValue = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private enum ADSRPhase
|
||||
{
|
||||
Attack,
|
||||
Decay,
|
||||
Sustain,
|
||||
Release,
|
||||
Pause
|
||||
}
|
||||
// ReSharper restore InvertIf
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="AbstractUpdateAwareDecorator.OnAttached" />
|
||||
/// <inheritdoc cref="IDecorator.OnAttached" />
|
||||
public override void OnAttached(IDecoratable decoratable)
|
||||
{
|
||||
base.OnAttached(decoratable);
|
||||
|
||||
_currentPhase = ADSRPhase.Attack;
|
||||
_currentPhaseValue = Attack;
|
||||
_repetitionCount = 0;
|
||||
_currentValue = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private enum ADSRPhase
|
||||
{
|
||||
Attack,
|
||||
Decay,
|
||||
Sustain,
|
||||
Release,
|
||||
Pause
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Decorators
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a basic decorator decorating a <see cref="T:RGB.NET.Presets.Gradients.IGradient" />.
|
||||
/// </summary>
|
||||
public interface IGradientDecorator : IDecorator
|
||||
{ }
|
||||
}
|
||||
namespace RGB.NET.Presets.Decorators;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a basic decorator decorating a <see cref="T:RGB.NET.Presets.Gradients.IGradient" />.
|
||||
/// </summary>
|
||||
public interface IGradientDecorator : IDecorator
|
||||
{ }
|
||||
@@ -1,74 +1,73 @@
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
namespace RGB.NET.Presets.Decorators
|
||||
namespace RGB.NET.Presets.Decorators;
|
||||
|
||||
/// <inheritdoc cref="AbstractUpdateAwareDecorator" />
|
||||
/// <inheritdoc cref="IGradientDecorator" />
|
||||
/// <summary>
|
||||
/// Represents a decorator which allows to move an <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> by modifying his offset.
|
||||
/// </summary>
|
||||
public class MoveGradientDecorator : AbstractUpdateAwareDecorator, IGradientDecorator
|
||||
{
|
||||
/// <inheritdoc cref="AbstractUpdateAwareDecorator" />
|
||||
/// <inheritdoc cref="IGradientDecorator" />
|
||||
#region Properties & Fields
|
||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
/// <summary>
|
||||
/// Represents a decorator which allows to move an <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> by modifying his offset.
|
||||
/// Gets or sets the direction the <see cref="IGradient"/> is moved.
|
||||
/// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left).
|
||||
/// </summary>
|
||||
public class MoveGradientDecorator : AbstractUpdateAwareDecorator, IGradientDecorator
|
||||
public bool Direction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the speed of the movement in units per second.
|
||||
/// The meaning of units differs for the different <see cref="IGradient"/>, but 360 units will always be one complete cycle:
|
||||
/// <see cref="LinearGradient"/>: 360 unit = 1 offset.
|
||||
/// <see cref="RainbowGradient"/>: 1 unit = 1 degree.
|
||||
/// </summary>
|
||||
public float Speed { get; set; }
|
||||
|
||||
// ReSharper restore MemberCanBePrivate.Global
|
||||
// ReSharper restore AutoPropertyCanBeMadeGetOnly.Global
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Decorators.MoveGradientDecorator" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">The surface this decorator belongs to.</param>
|
||||
/// <param name="speed">The speed of the movement in units per second.
|
||||
/// The meaning of units differs for the different <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> but 360 units will always be one complete cycle:
|
||||
/// <see cref="T:RGB.NET.Presets.Gradients.LinearGradient" />: 360 unit = 1 offset.
|
||||
/// <see cref="T:RGB.NET.Presets.Gradients.RainbowGradient" />: 1 unit = 1 degree.</param>
|
||||
/// <param name="direction">The direction the <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> is moved.
|
||||
/// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left).</param>
|
||||
public MoveGradientDecorator(RGBSurface surface, float speed = 180.0f, bool direction = true)
|
||||
: base(surface)
|
||||
{
|
||||
#region Properties & Fields
|
||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the direction the <see cref="IGradient"/> is moved.
|
||||
/// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left).
|
||||
/// </summary>
|
||||
public bool Direction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the speed of the movement in units per second.
|
||||
/// The meaning of units differs for the different <see cref="IGradient"/>, but 360 units will always be one complete cycle:
|
||||
/// <see cref="LinearGradient"/>: 360 unit = 1 offset.
|
||||
/// <see cref="RainbowGradient"/>: 1 unit = 1 degree.
|
||||
/// </summary>
|
||||
public float Speed { get; set; }
|
||||
|
||||
// ReSharper restore MemberCanBePrivate.Global
|
||||
// ReSharper restore AutoPropertyCanBeMadeGetOnly.Global
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Decorators.MoveGradientDecorator" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">The surface this decorator belongs to.</param>
|
||||
/// <param name="speed">The speed of the movement in units per second.
|
||||
/// The meaning of units differs for the different <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> but 360 units will always be one complete cycle:
|
||||
/// <see cref="T:RGB.NET.Presets.Gradients.LinearGradient" />: 360 unit = 1 offset.
|
||||
/// <see cref="T:RGB.NET.Presets.Gradients.RainbowGradient" />: 1 unit = 1 degree.</param>
|
||||
/// <param name="direction">The direction the <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> is moved.
|
||||
/// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left).</param>
|
||||
public MoveGradientDecorator(RGBSurface surface, float speed = 180.0f, bool direction = true)
|
||||
: base(surface)
|
||||
{
|
||||
this.Speed = speed;
|
||||
this.Direction = direction;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(double deltaTime)
|
||||
{
|
||||
float movement = Speed * (float)deltaTime;
|
||||
|
||||
if (!Direction)
|
||||
movement = -movement;
|
||||
|
||||
foreach (IDecoratable decoratedObject in DecoratedObjects)
|
||||
if (decoratedObject is IGradient gradient)
|
||||
gradient.Move(movement);
|
||||
}
|
||||
|
||||
#endregion
|
||||
this.Speed = speed;
|
||||
this.Direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(double deltaTime)
|
||||
{
|
||||
float movement = Speed * (float)deltaTime;
|
||||
|
||||
if (!Direction)
|
||||
movement = -movement;
|
||||
|
||||
foreach (IDecoratable decoratedObject in DecoratedObjects)
|
||||
if (decoratedObject is IGradient gradient)
|
||||
gradient.Move(movement);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -6,118 +6,117 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Groups
|
||||
namespace RGB.NET.Presets.Groups;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a <see cref="T:RGB.NET.Presets.Groups.RectangleLedGroup" /> containing <see cref="T:RGB.NET.Core.Led" /> which physically lay inside a <see cref="T:RGB.NET.Core.Rectangle" />.
|
||||
/// </summary>
|
||||
public class RectangleLedGroup : AbstractLedGroup
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private IList<Led>? _ledCache;
|
||||
|
||||
private Rectangle _rectangle;
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Core.Rectangle"/> the <see cref="Led"/> should be taken from.
|
||||
/// </summary>
|
||||
public Rectangle Rectangle
|
||||
{
|
||||
get => _rectangle;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _rectangle, value))
|
||||
InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
private double _minOverlayPercentage;
|
||||
/// <summary>
|
||||
/// Gets or sets the minimal percentage overlay a <see cref="Led"/> must have with the <see cref="Core.Rectangle" /> to be taken into the <see cref="RectangleLedGroup"/>.
|
||||
/// </summary>
|
||||
public double MinOverlayPercentage
|
||||
{
|
||||
get => _minOverlayPercentage;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _minOverlayPercentage, value))
|
||||
InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a <see cref="T:RGB.NET.Presets.Groups.RectangleLedGroup" /> containing <see cref="T:RGB.NET.Core.Led" /> which physically lay inside a <see cref="T:RGB.NET.Core.Rectangle" />.
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> class.
|
||||
/// </summary>
|
||||
public class RectangleLedGroup : AbstractLedGroup
|
||||
/// <param name="surface">Specifies the surface to attach this group to or <c>null</c> if the group should not be attached on creation.</param>
|
||||
/// <param name="fromLed">They first <see cref="T:RGB.NET.Core.Led" /> to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="toLed">They second <see cref="T:RGB.NET.Core.Led" /> to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="minOverlayPercentage">(optional) The minimal percentage overlay a <see cref="T:RGB.NET.Core.Led" /> must have with the <see cref="P:RGB.NET.Groups.RectangleLedGroup.Rectangle" /> to be taken into the <see cref="T:RGB.NET.Groups.RectangleLedGroup" />. (default: 0.5)</param>
|
||||
public RectangleLedGroup(RGBSurface? surface, Led fromLed, Led toLed, double minOverlayPercentage = 0.5)
|
||||
: this(surface, new Rectangle(fromLed.Boundary, toLed.Boundary), minOverlayPercentage)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">Specifies the surface to attach this group to or <c>null</c> if the group should not be attached on creation.</param>
|
||||
/// <param name="fromPoint">They first point to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="toPoint">They second point to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="minOverlayPercentage">(optional) The minimal percentage overlay a <see cref="T:RGB.NET.Core.Led" /> must have with the <see cref="P:RGB.NET.Groups.RectangleLedGroup.Rectangle" /> to be taken into the <see cref="T:RGB.NET.Groups.RectangleLedGroup" />. (default: 0.5)</param>
|
||||
public RectangleLedGroup(RGBSurface? surface, Point fromPoint, Point toPoint, double minOverlayPercentage = 0.5)
|
||||
: this(surface, new Rectangle(fromPoint, toPoint), minOverlayPercentage)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">Specifies the surface to attach this group to or <c>null</c> if the group should not be attached on creation.</param>
|
||||
/// <param name="rectangle">The <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" />.</param>
|
||||
/// <param name="minOverlayPercentage">(optional) The minimal percentage overlay a <see cref="T:RGB.NET.Core.Led" /> must have with the <see cref="P:RGB.NET.Groups.RectangleLedGroup.Rectangle" /> to be taken into the <see cref="T:RGB.NET.Groups.RectangleLedGroup" />. (default: 0.5)</param>
|
||||
public RectangleLedGroup(RGBSurface? surface, Rectangle rectangle, double minOverlayPercentage = 0.5)
|
||||
: base(surface)
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private IList<Led>? _ledCache;
|
||||
|
||||
private Rectangle _rectangle;
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Core.Rectangle"/> the <see cref="Led"/> should be taken from.
|
||||
/// </summary>
|
||||
public Rectangle Rectangle
|
||||
{
|
||||
get => _rectangle;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _rectangle, value))
|
||||
InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
private double _minOverlayPercentage;
|
||||
/// <summary>
|
||||
/// Gets or sets the minimal percentage overlay a <see cref="Led"/> must have with the <see cref="Core.Rectangle" /> to be taken into the <see cref="RectangleLedGroup"/>.
|
||||
/// </summary>
|
||||
public double MinOverlayPercentage
|
||||
{
|
||||
get => _minOverlayPercentage;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _minOverlayPercentage, value))
|
||||
InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">Specifies the surface to attach this group to or <c>null</c> if the group should not be attached on creation.</param>
|
||||
/// <param name="fromLed">They first <see cref="T:RGB.NET.Core.Led" /> to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="toLed">They second <see cref="T:RGB.NET.Core.Led" /> to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="minOverlayPercentage">(optional) The minimal percentage overlay a <see cref="T:RGB.NET.Core.Led" /> must have with the <see cref="P:RGB.NET.Groups.RectangleLedGroup.Rectangle" /> to be taken into the <see cref="T:RGB.NET.Groups.RectangleLedGroup" />. (default: 0.5)</param>
|
||||
public RectangleLedGroup(RGBSurface? surface, Led fromLed, Led toLed, double minOverlayPercentage = 0.5)
|
||||
: this(surface, new Rectangle(fromLed.Boundary, toLed.Boundary), minOverlayPercentage)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">Specifies the surface to attach this group to or <c>null</c> if the group should not be attached on creation.</param>
|
||||
/// <param name="fromPoint">They first point to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="toPoint">They second point to calculate the <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> from.</param>
|
||||
/// <param name="minOverlayPercentage">(optional) The minimal percentage overlay a <see cref="T:RGB.NET.Core.Led" /> must have with the <see cref="P:RGB.NET.Groups.RectangleLedGroup.Rectangle" /> to be taken into the <see cref="T:RGB.NET.Groups.RectangleLedGroup" />. (default: 0.5)</param>
|
||||
public RectangleLedGroup(RGBSurface? surface, Point fromPoint, Point toPoint, double minOverlayPercentage = 0.5)
|
||||
: this(surface, new Rectangle(fromPoint, toPoint), minOverlayPercentage)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.RectangleLedGroup" /> class.
|
||||
/// </summary>
|
||||
/// <param name="surface">Specifies the surface to attach this group to or <c>null</c> if the group should not be attached on creation.</param>
|
||||
/// <param name="rectangle">The <see cref="T:RGB.NET.Core.Rectangle" /> of this <see cref="T:RGB.NET.Groups.RectangleLedGroup" />.</param>
|
||||
/// <param name="minOverlayPercentage">(optional) The minimal percentage overlay a <see cref="T:RGB.NET.Core.Led" /> must have with the <see cref="P:RGB.NET.Groups.RectangleLedGroup.Rectangle" /> to be taken into the <see cref="T:RGB.NET.Groups.RectangleLedGroup" />. (default: 0.5)</param>
|
||||
public RectangleLedGroup(RGBSurface? surface, Rectangle rectangle, double minOverlayPercentage = 0.5)
|
||||
: base(surface)
|
||||
{
|
||||
this.Rectangle = rectangle;
|
||||
this.MinOverlayPercentage = minOverlayPercentage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnAttach()
|
||||
{
|
||||
base.OnAttach();
|
||||
Surface!.SurfaceLayoutChanged += RGBSurfaceOnSurfaceLayoutChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDetach()
|
||||
{
|
||||
Surface!.SurfaceLayoutChanged -= RGBSurfaceOnSurfaceLayoutChanged;
|
||||
|
||||
base.OnDetach();
|
||||
}
|
||||
|
||||
private void RGBSurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args) => InvalidateCache();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets a list containing all <see cref="T:RGB.NET.Core.Led" /> of this <see cref="T:RGB.NET.Presets.Groups.RectangleLedGroup" />.
|
||||
/// </summary>
|
||||
/// <returns>The list containing all <see cref="T:RGB.NET.Core.Led" /> of this <see cref="T:RGB.NET.Presets.Groups.RectangleLedGroup" />.</returns>
|
||||
protected override IEnumerable<Led> GetLeds() => _ledCache ??= (Surface?.Leds.Where(led => led.AbsoluteBoundary.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList() ?? new List<Led>());
|
||||
|
||||
private void InvalidateCache() => _ledCache = null;
|
||||
|
||||
#endregion
|
||||
this.Rectangle = rectangle;
|
||||
this.MinOverlayPercentage = minOverlayPercentage;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnAttach()
|
||||
{
|
||||
base.OnAttach();
|
||||
Surface!.SurfaceLayoutChanged += RGBSurfaceOnSurfaceLayoutChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDetach()
|
||||
{
|
||||
Surface!.SurfaceLayoutChanged -= RGBSurfaceOnSurfaceLayoutChanged;
|
||||
|
||||
base.OnDetach();
|
||||
}
|
||||
|
||||
private void RGBSurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args) => InvalidateCache();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets a list containing all <see cref="T:RGB.NET.Core.Led" /> of this <see cref="T:RGB.NET.Presets.Groups.RectangleLedGroup" />.
|
||||
/// </summary>
|
||||
/// <returns>The list containing all <see cref="T:RGB.NET.Core.Led" /> of this <see cref="T:RGB.NET.Presets.Groups.RectangleLedGroup" />.</returns>
|
||||
protected override IEnumerable<Led> GetLeds() => _ledCache ??= (Surface?.Leds.Where(led => led.AbsoluteBoundary.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList() ?? new List<Led>());
|
||||
|
||||
private void InvalidateCache() => _ledCache = null;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -3,84 +3,83 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Helper
|
||||
namespace RGB.NET.Presets.Helper;
|
||||
|
||||
/// <summary>
|
||||
/// Offers some extensions and helper-methods for gradient related things.
|
||||
/// </summary>
|
||||
public static class GradientHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
// Based on https://web.archive.org/web/20170125201230/https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
|
||||
/// <summary>
|
||||
/// Offers some extensions and helper-methods for gradient related things.
|
||||
/// Calculates the offset of an specified <see cref="Point"/> on an gradient.
|
||||
/// </summary>
|
||||
public static class GradientHelper
|
||||
/// <param name="startPoint">The start <see cref="Point"/> of the gradient.</param>
|
||||
/// <param name="endPoint">The end <see cref="Point"/> of the gradient.</param>
|
||||
/// <param name="point">The <see cref="Point"/> on the gradient to which the offset is calculated.</param>
|
||||
/// <returns>The offset of the <see cref="Point"/> on the gradient.</returns>
|
||||
public static float CalculateLinearGradientOffset(in Point startPoint, in Point endPoint, in Point point)
|
||||
{
|
||||
#region Methods
|
||||
Point intersectingPoint;
|
||||
if (startPoint.Y.EqualsInTolerance(endPoint.Y)) // Horizontal case
|
||||
intersectingPoint = new Point(point.X, startPoint.Y);
|
||||
|
||||
// Based on https://web.archive.org/web/20170125201230/https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
|
||||
/// <summary>
|
||||
/// Calculates the offset of an specified <see cref="Point"/> on an gradient.
|
||||
/// </summary>
|
||||
/// <param name="startPoint">The start <see cref="Point"/> of the gradient.</param>
|
||||
/// <param name="endPoint">The end <see cref="Point"/> of the gradient.</param>
|
||||
/// <param name="point">The <see cref="Point"/> on the gradient to which the offset is calculated.</param>
|
||||
/// <returns>The offset of the <see cref="Point"/> on the gradient.</returns>
|
||||
public static float CalculateLinearGradientOffset(in Point startPoint, in Point endPoint, in Point point)
|
||||
else if (startPoint.X.EqualsInTolerance(endPoint.X)) // Vertical case
|
||||
intersectingPoint = new Point(startPoint.X, point.Y);
|
||||
|
||||
else // Diagonal case
|
||||
{
|
||||
Point intersectingPoint;
|
||||
if (startPoint.Y.EqualsInTolerance(endPoint.Y)) // Horizontal case
|
||||
intersectingPoint = new Point(point.X, startPoint.Y);
|
||||
float slope = (endPoint.Y - startPoint.Y) / (endPoint.X - startPoint.X);
|
||||
float orthogonalSlope = -1 / slope;
|
||||
|
||||
else if (startPoint.X.EqualsInTolerance(endPoint.X)) // Vertical case
|
||||
intersectingPoint = new Point(startPoint.X, point.Y);
|
||||
float startYIntercept = startPoint.Y - (slope * startPoint.X);
|
||||
float pointYIntercept = point.Y - (orthogonalSlope * point.X);
|
||||
|
||||
else // Diagonal case
|
||||
{
|
||||
float slope = (endPoint.Y - startPoint.Y) / (endPoint.X - startPoint.X);
|
||||
float orthogonalSlope = -1 / slope;
|
||||
|
||||
float startYIntercept = startPoint.Y - (slope * startPoint.X);
|
||||
float pointYIntercept = point.Y - (orthogonalSlope * point.X);
|
||||
|
||||
float intersectingPointX = (pointYIntercept - startYIntercept) / (slope - orthogonalSlope);
|
||||
float intersectingPointY = (slope * intersectingPointX) + startYIntercept;
|
||||
intersectingPoint = new Point(intersectingPointX, intersectingPointY);
|
||||
}
|
||||
|
||||
// Calculate distances relative to the vector start
|
||||
float intersectDistance = CalculateDistance(intersectingPoint, startPoint, endPoint);
|
||||
float gradientLength = CalculateDistance(endPoint, startPoint, endPoint);
|
||||
|
||||
return intersectDistance / gradientLength;
|
||||
float intersectingPointX = (pointYIntercept - startYIntercept) / (slope - orthogonalSlope);
|
||||
float intersectingPointY = (slope * intersectingPointX) + startYIntercept;
|
||||
intersectingPoint = new Point(intersectingPointX, intersectingPointY);
|
||||
}
|
||||
|
||||
// Based on https://web.archive.org/web/20170125201230/https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
|
||||
/// <summary>
|
||||
/// Returns the signed magnitude of a <see cref="Point"/> on a vector.
|
||||
/// </summary>
|
||||
/// <param name="point">The <see cref="Point"/> on the vector of which the magnitude should be calculated.</param>
|
||||
/// <param name="origin">The origin of the vector.</param>
|
||||
/// <param name="direction">The direction of the vector.</param>
|
||||
/// <returns>The signed magnitude of a <see cref="Point"/> on a vector.</returns>
|
||||
public static float CalculateDistance(in Point point, in Point origin, in Point direction)
|
||||
{
|
||||
float distance = CalculateDistance(point, origin);
|
||||
// Calculate distances relative to the vector start
|
||||
float intersectDistance = CalculateDistance(intersectingPoint, startPoint, endPoint);
|
||||
float gradientLength = CalculateDistance(endPoint, startPoint, endPoint);
|
||||
|
||||
return (((point.Y < origin.Y) && (direction.Y > origin.Y))
|
||||
|| ((point.Y > origin.Y) && (direction.Y < origin.Y))
|
||||
|| ((point.Y.EqualsInTolerance(origin.Y)) && (point.X < origin.X) && (direction.X > origin.X))
|
||||
|| ((point.Y.EqualsInTolerance(origin.Y)) && (point.X > origin.X) && (direction.X < origin.X)))
|
||||
? -distance : distance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculated the distance between two <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <param name="point1">The first <see cref="Point"/>.</param>
|
||||
/// <param name="point2">The second <see cref="Point"/>.</param>
|
||||
/// <returns>The distance between the two <see cref="Point"/>.</returns>
|
||||
public static float CalculateDistance(in Point point1, in Point point2)
|
||||
{
|
||||
float x = point1.X - point2.X;
|
||||
float y = point1.Y - point2.Y;
|
||||
return MathF.Sqrt((y * y) + (x * x));
|
||||
}
|
||||
|
||||
#endregion
|
||||
return intersectDistance / gradientLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Based on https://web.archive.org/web/20170125201230/https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
|
||||
/// <summary>
|
||||
/// Returns the signed magnitude of a <see cref="Point"/> on a vector.
|
||||
/// </summary>
|
||||
/// <param name="point">The <see cref="Point"/> on the vector of which the magnitude should be calculated.</param>
|
||||
/// <param name="origin">The origin of the vector.</param>
|
||||
/// <param name="direction">The direction of the vector.</param>
|
||||
/// <returns>The signed magnitude of a <see cref="Point"/> on a vector.</returns>
|
||||
public static float CalculateDistance(in Point point, in Point origin, in Point direction)
|
||||
{
|
||||
float distance = CalculateDistance(point, origin);
|
||||
|
||||
return (((point.Y < origin.Y) && (direction.Y > origin.Y))
|
||||
|| ((point.Y > origin.Y) && (direction.Y < origin.Y))
|
||||
|| ((point.Y.EqualsInTolerance(origin.Y)) && (point.X < origin.X) && (direction.X > origin.X))
|
||||
|| ((point.Y.EqualsInTolerance(origin.Y)) && (point.X > origin.X) && (direction.X < origin.X)))
|
||||
? -distance : distance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculated the distance between two <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <param name="point1">The first <see cref="Point"/>.</param>
|
||||
/// <param name="point2">The second <see cref="Point"/>.</param>
|
||||
/// <returns>The distance between the two <see cref="Point"/>.</returns>
|
||||
public static float CalculateDistance(in Point point1, in Point point2)
|
||||
{
|
||||
float x = point1.X - point2.X;
|
||||
float y = point1.Y - point2.Y;
|
||||
return MathF.Sqrt((y * y) + (x * x));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,57 +1,56 @@
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <inheritdoc cref="AbstractBindable" />
|
||||
/// <inheritdoc cref="ITexture" />
|
||||
/// <summary>
|
||||
/// Represents a abstract texture containing a color-gradient.
|
||||
/// </summary>
|
||||
public abstract class AbstractGradientTexture : AbstractBindable, ITexture
|
||||
{
|
||||
/// <inheritdoc cref="AbstractBindable" />
|
||||
/// <inheritdoc cref="ITexture" />
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Represents a abstract texture containing a color-gradient.
|
||||
/// Gets the gradient used to generate this texture.
|
||||
/// </summary>
|
||||
public abstract class AbstractGradientTexture : AbstractBindable, ITexture
|
||||
public IGradient Gradient { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Size Size { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Color this[in Point point] => GetColor(point);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Color this[in Rectangle rectangle] => GetColor(rectangle.Center);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The gradient used to generate this texture.</param>
|
||||
protected AbstractGradientTexture(Size size, IGradient gradient)
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gradient used to generate this texture.
|
||||
/// </summary>
|
||||
public IGradient Gradient { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Size Size { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Color this[in Point point] => GetColor(point);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Color this[in Rectangle rectangle] => GetColor(rectangle.Center);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The gradient used to generate this texture.</param>
|
||||
protected AbstractGradientTexture(Size size, IGradient gradient)
|
||||
{
|
||||
this.Size = size;
|
||||
this.Gradient = gradient;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color at the specified location of the texture.
|
||||
/// </summary>
|
||||
/// <param name="point">The location to get the color from.</param>
|
||||
/// <returns>The color at the specified location.</returns>
|
||||
protected abstract Color GetColor(in Point point);
|
||||
|
||||
#endregion
|
||||
this.Size = size;
|
||||
this.Gradient = gradient;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color at the specified location of the texture.
|
||||
/// </summary>
|
||||
/// <param name="point">The location to get the color from.</param>
|
||||
/// <returns>The color at the specified location.</returns>
|
||||
protected abstract Color GetColor(in Point point);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -2,73 +2,72 @@
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Textures.Sampler;
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a texture of byte-data pixels.
|
||||
/// </summary>
|
||||
public sealed class BytePixelTexture : PixelTexture<byte>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly byte[] _data;
|
||||
/// <inheritdoc />
|
||||
protected override ReadOnlySpan<byte> Data => _data;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a texture of byte-data pixels.
|
||||
/// Gets the color format the data is in.
|
||||
/// </summary>
|
||||
public sealed class BytePixelTexture : PixelTexture<byte>
|
||||
public ColorFormat ColorFormat { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BytePixelTexture" /> class.
|
||||
/// A <see cref="AverageColorSampler"/> is used.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public BytePixelTexture(int with, int height, byte[] data, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: this(with, height, data, new AverageByteSampler(), colorFormat)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BytePixelTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="sampler">The sampler used to get the color of a region.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public BytePixelTexture(int with, int height, byte[] data, ISampler<byte> sampler, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: base(with, height, 3, sampler)
|
||||
{
|
||||
#region Properties & Fields
|
||||
this._data = data;
|
||||
this.ColorFormat = colorFormat;
|
||||
|
||||
private readonly byte[] _data;
|
||||
/// <inheritdoc />
|
||||
protected override ReadOnlySpan<byte> Data => _data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color format the data is in.
|
||||
/// </summary>
|
||||
public ColorFormat ColorFormat { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BytePixelTexture" /> class.
|
||||
/// A <see cref="AverageColorSampler"/> is used.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public BytePixelTexture(int with, int height, byte[] data, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: this(with, height, data, new AverageByteSampler(), colorFormat)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BytePixelTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="sampler">The sampler used to get the color of a region.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public BytePixelTexture(int with, int height, byte[] data, ISampler<byte> sampler, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: base(with, height, 3, sampler)
|
||||
{
|
||||
this._data = data;
|
||||
this.ColorFormat = colorFormat;
|
||||
|
||||
if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the specified size {with}x{height} * 3 bytes ({with * height * 3}).");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in ReadOnlySpan<byte> pixel)
|
||||
{
|
||||
return ColorFormat switch
|
||||
{
|
||||
ColorFormat.RGB => new Color(pixel[0], pixel[1], pixel[2]),
|
||||
ColorFormat.BGR => new Color(pixel[2], pixel[1], pixel[0]),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the specified size {with}x{height} * 3 bytes ({with * height * 3}).");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in ReadOnlySpan<byte> pixel)
|
||||
{
|
||||
return ColorFormat switch
|
||||
{
|
||||
ColorFormat.RGB => new Color(pixel[0], pixel[1], pixel[2]),
|
||||
ColorFormat.BGR => new Color(pixel[2], pixel[1], pixel[0]),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -8,95 +8,94 @@ using System;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a texture drawing a conical gradient.
|
||||
/// </summary>
|
||||
public sealed class ConicalGradientTexture : AbstractGradientTexture
|
||||
{
|
||||
/// <inheritdoc />
|
||||
#region Constants
|
||||
|
||||
private const float PI2 = MathF.PI * 2.0f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
private float _origin = MathF.Atan2(-1, 0);
|
||||
/// <summary>
|
||||
/// Represents a texture drawing a conical gradient.
|
||||
/// Gets or sets the origin (radian-angle) this <see cref="ConicalGradientTexture"/> is drawn to. (default: -π/2)
|
||||
/// </summary>
|
||||
public sealed class ConicalGradientTexture : AbstractGradientTexture
|
||||
public float Origin
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const float PI2 = MathF.PI * 2.0f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
private float _origin = MathF.Atan2(-1, 0);
|
||||
/// <summary>
|
||||
/// Gets or sets the origin (radian-angle) this <see cref="ConicalGradientTexture"/> is drawn to. (default: -π/2)
|
||||
/// </summary>
|
||||
public float Origin
|
||||
{
|
||||
get => _origin;
|
||||
set => SetProperty(ref _origin, value);
|
||||
}
|
||||
|
||||
private Point _center = new(0.5f, 0.5f);
|
||||
/// <summary>
|
||||
/// Gets or sets the center <see cref="Point"/> (as percentage in the range [0..1]) of the <see cref="IGradient"/> drawn by this <see cref="ConicalGradientTexture"/>. (default: 0.5, 0.5)
|
||||
/// </summary>
|
||||
public Point Center
|
||||
{
|
||||
get => _center;
|
||||
set => SetProperty(ref _center, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" />.</param>
|
||||
public ConicalGradientTexture(Size size, IGradient gradient)
|
||||
: base(size, gradient)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" />.</param>
|
||||
/// <param name="center">The center <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
public ConicalGradientTexture(Size size, IGradient gradient, Point center)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.Center = center;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" />.</param>
|
||||
/// <param name="center">The center <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
/// <param name="origin">The origin (radian-angle) the gradient is drawn to.</param>
|
||||
public ConicalGradientTexture(Size size, IGradient gradient, Point center, float origin)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.Center = center;
|
||||
this.Origin = origin;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in Point point)
|
||||
{
|
||||
float angle = MathF.Atan2(point.Y - Center.Y, point.X - Center.X) - Origin;
|
||||
if (angle < 0) angle += PI2;
|
||||
float offset = angle / PI2;
|
||||
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
|
||||
#endregion
|
||||
get => _origin;
|
||||
set => SetProperty(ref _origin, value);
|
||||
}
|
||||
}
|
||||
|
||||
private Point _center = new(0.5f, 0.5f);
|
||||
/// <summary>
|
||||
/// Gets or sets the center <see cref="Point"/> (as percentage in the range [0..1]) of the <see cref="IGradient"/> drawn by this <see cref="ConicalGradientTexture"/>. (default: 0.5, 0.5)
|
||||
/// </summary>
|
||||
public Point Center
|
||||
{
|
||||
get => _center;
|
||||
set => SetProperty(ref _center, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" />.</param>
|
||||
public ConicalGradientTexture(Size size, IGradient gradient)
|
||||
: base(size, gradient)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" />.</param>
|
||||
/// <param name="center">The center <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
public ConicalGradientTexture(Size size, IGradient gradient, Point center)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.Center = center;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.ConicalGradientTexture" />.</param>
|
||||
/// <param name="center">The center <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
/// <param name="origin">The origin (radian-angle) the gradient is drawn to.</param>
|
||||
public ConicalGradientTexture(Size size, IGradient gradient, Point center, float origin)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.Center = center;
|
||||
this.Origin = origin;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in Point point)
|
||||
{
|
||||
float angle = MathF.Atan2(point.Y - Center.Y, point.X - Center.X) - Origin;
|
||||
if (angle < 0) angle += PI2;
|
||||
float offset = angle / PI2;
|
||||
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
#pragma warning disable 1591
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a list of possible color formats.
|
||||
/// </summary>
|
||||
public enum ColorFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a list of possible color formats.
|
||||
/// </summary>
|
||||
public enum ColorFormat
|
||||
{
|
||||
RGB,
|
||||
BGR
|
||||
}
|
||||
}
|
||||
RGB,
|
||||
BGR
|
||||
}
|
||||
@@ -2,73 +2,72 @@
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Textures.Sampler;
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a texture of float-data pixels.
|
||||
/// </summary>
|
||||
public sealed class FloatPixelTexture : PixelTexture<float>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly float[] _data;
|
||||
/// <inheritdoc />
|
||||
protected override ReadOnlySpan<float> Data => _data;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a texture of float-data pixels.
|
||||
/// Gets the color format the data is in.
|
||||
/// </summary>
|
||||
public sealed class FloatPixelTexture : PixelTexture<float>
|
||||
public ColorFormat ColorFormat { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FloatPixelTexture" /> class.
|
||||
/// A <see cref="AverageColorSampler"/> is used.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public FloatPixelTexture(int with, int height, float[] data, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: this(with, height, data, new AverageFloatSampler(), colorFormat)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FloatPixelTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="sampler">The sampler used to get the color of a region.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public FloatPixelTexture(int with, int height, float[] data, ISampler<float> sampler, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: base(with, height, 3, sampler)
|
||||
{
|
||||
#region Properties & Fields
|
||||
this._data = data;
|
||||
this.ColorFormat = colorFormat;
|
||||
|
||||
private readonly float[] _data;
|
||||
/// <inheritdoc />
|
||||
protected override ReadOnlySpan<float> Data => _data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color format the data is in.
|
||||
/// </summary>
|
||||
public ColorFormat ColorFormat { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FloatPixelTexture" /> class.
|
||||
/// A <see cref="AverageColorSampler"/> is used.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public FloatPixelTexture(int with, int height, float[] data, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: this(with, height, data, new AverageFloatSampler(), colorFormat)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FloatPixelTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="with">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The pixel-data of the texture.</param>
|
||||
/// <param name="sampler">The sampler used to get the color of a region.</param>
|
||||
/// <param name="colorFormat">The color format the data is in. (default: RGB)</param>
|
||||
public FloatPixelTexture(int with, int height, float[] data, ISampler<float> sampler, ColorFormat colorFormat = ColorFormat.RGB)
|
||||
: base(with, height, 3, sampler)
|
||||
{
|
||||
this._data = data;
|
||||
this.ColorFormat = colorFormat;
|
||||
|
||||
if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the specified size {with}x{height} * 3 bytes ({with * height * 3}).");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in ReadOnlySpan<float> pixel)
|
||||
{
|
||||
return ColorFormat switch
|
||||
{
|
||||
ColorFormat.RGB => new Color(pixel[0], pixel[1], pixel[2]),
|
||||
ColorFormat.BGR => new Color(pixel[2], pixel[1], pixel[0]),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the specified size {with}x{height} * 3 bytes ({with * height * 3}).");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in ReadOnlySpan<float> pixel)
|
||||
{
|
||||
return ColorFormat switch
|
||||
{
|
||||
ColorFormat.RGB => new Color(pixel[0], pixel[1], pixel[2]),
|
||||
ColorFormat.BGR => new Color(pixel[2], pixel[1], pixel[0]),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -10,142 +10,141 @@ using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Decorators;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Gradients
|
||||
namespace RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
/// <inheritdoc cref="AbstractDecoratable{T}" />
|
||||
/// <inheritdoc cref="IGradient" />
|
||||
/// <summary>
|
||||
/// Represents a basic gradient.
|
||||
/// </summary>
|
||||
public abstract class AbstractGradient : AbstractDecoratable<IGradientDecorator>, IGradient
|
||||
{
|
||||
/// <inheritdoc cref="AbstractDecoratable{T}" />
|
||||
/// <inheritdoc cref="IGradient" />
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Represents a basic gradient.
|
||||
/// Gets a list of the stops used by this <see cref="AbstractGradient"/>.
|
||||
/// </summary>
|
||||
public abstract class AbstractGradient : AbstractDecoratable<IGradientDecorator>, IGradient
|
||||
public ObservableCollection<GradientStop> GradientStops { get; } = new();
|
||||
|
||||
private bool _wrapGradient;
|
||||
/// <summary>
|
||||
/// Gets or sets if the Gradient wraps around if there isn't a second stop to take.
|
||||
/// Example: There is a stop at offset 0.0, 0.5 and 0.75.
|
||||
/// Without wrapping offset 1.0 will be calculated the same as 0.75; with wrapping it would be the same as 0.0.
|
||||
/// </summary>
|
||||
public bool WrapGradient
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of the stops used by this <see cref="AbstractGradient"/>.
|
||||
/// </summary>
|
||||
public ObservableCollection<GradientStop> GradientStops { get; } = new();
|
||||
|
||||
private bool _wrapGradient;
|
||||
/// <summary>
|
||||
/// Gets or sets if the Gradient wraps around if there isn't a second stop to take.
|
||||
/// Example: There is a stop at offset 0.0, 0.5 and 0.75.
|
||||
/// Without wrapping offset 1.0 will be calculated the same as 0.75; with wrapping it would be the same as 0.0.
|
||||
/// </summary>
|
||||
public bool WrapGradient
|
||||
{
|
||||
get => _wrapGradient;
|
||||
set => SetProperty(ref _wrapGradient, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? GradientChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradient"/> class.
|
||||
/// </summary>
|
||||
protected AbstractGradient()
|
||||
{
|
||||
GradientStops.CollectionChanged += GradientCollectionChanged;
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
protected AbstractGradient(params GradientStop[] gradientStops)
|
||||
{
|
||||
GradientStops.CollectionChanged += GradientCollectionChanged;
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
|
||||
foreach (GradientStop gradientStop in gradientStops)
|
||||
GradientStops.Add(gradientStop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="wrapGradient">Specifies whether the gradient should wrapp or not (see <see cref="WrapGradient"/> for an example of what this means).</param>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
protected AbstractGradient(bool wrapGradient, params GradientStop[] gradientStops)
|
||||
{
|
||||
this.WrapGradient = wrapGradient;
|
||||
|
||||
GradientStops.CollectionChanged += GradientCollectionChanged;
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
|
||||
foreach (GradientStop gradientStop in gradientStops)
|
||||
GradientStops.Add(gradientStop);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Clips the offset and ensures, that it is inside the bounds of the stop list.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset to clip.</param>
|
||||
/// <returns>The clipped offset.</returns>
|
||||
protected float ClipOffset(float offset)
|
||||
{
|
||||
float max = GradientStops.Max(stop => stop.Offset);
|
||||
if (offset > max)
|
||||
return max;
|
||||
|
||||
float min = GradientStops.Min(stop => stop.Offset);
|
||||
return offset < min ? min : offset;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Color GetColor(float offset);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Move(float offset)
|
||||
{
|
||||
offset /= 360.0f;
|
||||
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.Offset += offset;
|
||||
|
||||
while (GradientStops.All(stop => stop.Offset > 1))
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.Offset -= 1;
|
||||
|
||||
while (GradientStops.All(stop => stop.Offset < 0))
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.Offset += 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be called to indicate that the gradient was changed.
|
||||
/// </summary>
|
||||
protected void OnGradientChanged() => GradientChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private void GradientCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.OldItems != null)
|
||||
foreach (GradientStop gradientStop in e.OldItems)
|
||||
gradientStop.PropertyChanged -= GradientStopChanged;
|
||||
|
||||
if (e.NewItems != null)
|
||||
foreach (GradientStop gradientStop in e.NewItems)
|
||||
gradientStop.PropertyChanged += GradientStopChanged;
|
||||
|
||||
OnGradientChanged();
|
||||
}
|
||||
|
||||
private void GradientStopChanged(object? sender, PropertyChangedEventArgs propertyChangedEventArgs) => OnGradientChanged();
|
||||
|
||||
#endregion
|
||||
get => _wrapGradient;
|
||||
set => SetProperty(ref _wrapGradient, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? GradientChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradient"/> class.
|
||||
/// </summary>
|
||||
protected AbstractGradient()
|
||||
{
|
||||
GradientStops.CollectionChanged += GradientCollectionChanged;
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
protected AbstractGradient(params GradientStop[] gradientStops)
|
||||
{
|
||||
GradientStops.CollectionChanged += GradientCollectionChanged;
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
|
||||
foreach (GradientStop gradientStop in gradientStops)
|
||||
GradientStops.Add(gradientStop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractGradient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="wrapGradient">Specifies whether the gradient should wrapp or not (see <see cref="WrapGradient"/> for an example of what this means).</param>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
protected AbstractGradient(bool wrapGradient, params GradientStop[] gradientStops)
|
||||
{
|
||||
this.WrapGradient = wrapGradient;
|
||||
|
||||
GradientStops.CollectionChanged += GradientCollectionChanged;
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
|
||||
foreach (GradientStop gradientStop in gradientStops)
|
||||
GradientStops.Add(gradientStop);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Clips the offset and ensures, that it is inside the bounds of the stop list.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset to clip.</param>
|
||||
/// <returns>The clipped offset.</returns>
|
||||
protected float ClipOffset(float offset)
|
||||
{
|
||||
float max = GradientStops.Max(stop => stop.Offset);
|
||||
if (offset > max)
|
||||
return max;
|
||||
|
||||
float min = GradientStops.Min(stop => stop.Offset);
|
||||
return offset < min ? min : offset;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Color GetColor(float offset);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Move(float offset)
|
||||
{
|
||||
offset /= 360.0f;
|
||||
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.Offset += offset;
|
||||
|
||||
while (GradientStops.All(stop => stop.Offset > 1))
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.Offset -= 1;
|
||||
|
||||
while (GradientStops.All(stop => stop.Offset < 0))
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.Offset += 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be called to indicate that the gradient was changed.
|
||||
/// </summary>
|
||||
protected void OnGradientChanged() => GradientChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private void GradientCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.OldItems != null)
|
||||
foreach (GradientStop gradientStop in e.OldItems)
|
||||
gradientStop.PropertyChanged -= GradientStopChanged;
|
||||
|
||||
if (e.NewItems != null)
|
||||
foreach (GradientStop gradientStop in e.NewItems)
|
||||
gradientStop.PropertyChanged += GradientStopChanged;
|
||||
|
||||
OnGradientChanged();
|
||||
}
|
||||
|
||||
private void GradientStopChanged(object? sender, PropertyChangedEventArgs propertyChangedEventArgs) => OnGradientChanged();
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -3,50 +3,49 @@
|
||||
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Gradients
|
||||
namespace RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stop on a gradient.
|
||||
/// </summary>
|
||||
public class GradientStop : AbstractBindable
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private float _offset;
|
||||
/// <summary>
|
||||
/// Represents a stop on a gradient.
|
||||
/// Gets or sets the percentage offset to place this <see cref="GradientStop"/>. This should be inside the range of [0..1] but it's not necessary.
|
||||
/// </summary>
|
||||
public class GradientStop : AbstractBindable
|
||||
public float Offset
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private float _offset;
|
||||
/// <summary>
|
||||
/// Gets or sets the percentage offset to place this <see cref="GradientStop"/>. This should be inside the range of [0..1] but it's not necessary.
|
||||
/// </summary>
|
||||
public float Offset
|
||||
{
|
||||
get => _offset;
|
||||
set => SetProperty(ref _offset, value);
|
||||
}
|
||||
|
||||
private Color _color;
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Color"/> of this <see cref="GradientStop"/>.
|
||||
/// </summary>
|
||||
public Color Color
|
||||
{
|
||||
get => _color;
|
||||
set => SetProperty(ref _color, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GradientStop"/> class.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to place this <see cref="GradientStop"/>.</param>
|
||||
/// <param name="color">The <see cref="Color"/> of the <see cref="GradientStop"/>.</param>
|
||||
public GradientStop(float offset, Color color)
|
||||
{
|
||||
this.Offset = offset;
|
||||
this.Color = color;
|
||||
}
|
||||
|
||||
#endregion
|
||||
get => _offset;
|
||||
set => SetProperty(ref _offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
private Color _color;
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Color"/> of this <see cref="GradientStop"/>.
|
||||
/// </summary>
|
||||
public Color Color
|
||||
{
|
||||
get => _color;
|
||||
set => SetProperty(ref _color, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GradientStop"/> class.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to place this <see cref="GradientStop"/>.</param>
|
||||
/// <param name="color">The <see cref="Color"/> of the <see cref="GradientStop"/>.</param>
|
||||
public GradientStop(float offset, Color color)
|
||||
{
|
||||
this.Offset = offset;
|
||||
this.Color = color;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -4,29 +4,28 @@ using System;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Decorators;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Gradients
|
||||
namespace RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a basic gradient.
|
||||
/// </summary>
|
||||
public interface IGradient : IDecoratable<IGradientDecorator>
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a basic gradient.
|
||||
/// Occurs if the <see cref="IGradient"/> is changed.
|
||||
/// </summary>
|
||||
public interface IGradient : IDecoratable<IGradientDecorator>
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs if the <see cref="IGradient"/> is changed.
|
||||
/// </summary>
|
||||
event EventHandler GradientChanged;
|
||||
event EventHandler GradientChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Color"/> of the <see cref="IGradient"/> on the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to take the <see cref="Color"/> from.</param>
|
||||
/// <returns>The <see cref="Color"/> at the specific offset.</returns>
|
||||
Color GetColor(float offset);
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Color"/> of the <see cref="IGradient"/> on the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to take the <see cref="Color"/> from.</param>
|
||||
/// <returns>The <see cref="Color"/> at the specific offset.</returns>
|
||||
Color GetColor(float offset);
|
||||
|
||||
/// <summary>
|
||||
/// Moves the <see cref="IGradient"/> by the provided offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset the <see cref="IGradient"/> should be moved.</param>
|
||||
void Move(float offset);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Moves the <see cref="IGradient"/> by the provided offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset the <see cref="IGradient"/> should be moved.</param>
|
||||
void Move(float offset);
|
||||
}
|
||||
@@ -5,148 +5,147 @@ using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Gradients
|
||||
namespace RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a linear interpolated gradient with n stops.
|
||||
/// </summary>
|
||||
public class LinearGradient : AbstractGradient
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private bool _isOrderedGradientListDirty = true;
|
||||
private LinkedList<GradientStop> _orderedGradientStops = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a linear interpolated gradient with n stops.
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.Gradients.LinearGradient" /> class.
|
||||
/// </summary>
|
||||
public class LinearGradient : AbstractGradient
|
||||
public LinearGradient()
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private bool _isOrderedGradientListDirty = true;
|
||||
private LinkedList<GradientStop> _orderedGradientStops = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.Gradients.LinearGradient" /> class.
|
||||
/// </summary>
|
||||
public LinearGradient()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.Gradients.LinearGradient" /> class.
|
||||
/// </summary>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
public LinearGradient(params GradientStop[] gradientStops)
|
||||
: base(gradientStops)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.Gradients.AbstractGradient" /> class.
|
||||
/// </summary>
|
||||
/// <param name="wrapGradient">Specifies whether the gradient should wrapp or not (see <see cref="P:RGB.NET.Presets.Textures.Gradients.AbstractGradient.WrapGradient" /> for an example of what this means).</param>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
public LinearGradient(bool wrapGradient, params GradientStop[] gradientStops)
|
||||
: base(wrapGradient, gradientStops)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
void OnGradientStopOnPropertyChanged(object? sender, PropertyChangedEventArgs args) => _isOrderedGradientListDirty = true;
|
||||
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.PropertyChanged += OnGradientStopOnPropertyChanged;
|
||||
|
||||
GradientStops.CollectionChanged += (_, args) =>
|
||||
{
|
||||
if (args.OldItems != null)
|
||||
foreach (GradientStop gradientStop in args.OldItems)
|
||||
gradientStop.PropertyChanged -= OnGradientStopOnPropertyChanged;
|
||||
|
||||
if (args.NewItems != null)
|
||||
foreach (GradientStop gradientStop in args.NewItems)
|
||||
gradientStop.PropertyChanged += OnGradientStopOnPropertyChanged;
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets the linear interpolated <see cref="T:RGB.NET.Core.Color" /> at the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to take the color from.</param>
|
||||
/// <returns>The <see cref="T:RGB.NET.Core.Color" /> at the specific offset.</returns>
|
||||
public override Color GetColor(float offset)
|
||||
{
|
||||
if (GradientStops.Count == 0) return Color.Transparent;
|
||||
if (GradientStops.Count == 1) return GradientStops[0].Color;
|
||||
|
||||
if (_isOrderedGradientListDirty)
|
||||
_orderedGradientStops = new LinkedList<GradientStop>(GradientStops.OrderBy(x => x.Offset));
|
||||
|
||||
(GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, _orderedGradientStops, WrapGradient);
|
||||
|
||||
float blendFactor = 0;
|
||||
if (!gsBefore.Offset.Equals(gsAfter.Offset))
|
||||
blendFactor = ((offset - gsBefore.Offset) / (gsAfter.Offset - gsBefore.Offset));
|
||||
|
||||
float colA = ((gsAfter.Color.A - gsBefore.Color.A) * blendFactor) + gsBefore.Color.A;
|
||||
float colR = ((gsAfter.Color.R - gsBefore.Color.R) * blendFactor) + gsBefore.Color.R;
|
||||
float colG = ((gsAfter.Color.G - gsBefore.Color.G) * blendFactor) + gsBefore.Color.G;
|
||||
float colB = ((gsAfter.Color.B - gsBefore.Color.B) * blendFactor) + gsBefore.Color.B;
|
||||
|
||||
return new Color(colA, colR, colG, colB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the two <see cref="GradientStop"/>s encapsulating the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The reference offset.</param>
|
||||
/// <param name="orderedStops">The ordered list of <see cref="GradientStop"/> to choose from.</param>
|
||||
/// <param name="wrap">Bool indicating if the gradient should be wrapped or not.</param>
|
||||
/// <returns>The two <see cref="GradientStop"/>s encapsulating the specified offset.</returns>
|
||||
protected virtual (GradientStop gsBefore, GradientStop gsAfter) GetEnclosingGradientStops(float offset, LinkedList<GradientStop> orderedStops, bool wrap)
|
||||
{
|
||||
LinkedList<GradientStop> gradientStops = new(orderedStops);
|
||||
|
||||
if (wrap)
|
||||
{
|
||||
GradientStop? gsBefore, gsAfter;
|
||||
|
||||
do
|
||||
{
|
||||
gsBefore = gradientStops.LastOrDefault(n => n.Offset <= offset);
|
||||
if (gsBefore == null)
|
||||
{
|
||||
GradientStop lastStop = gradientStops.Last!.Value;
|
||||
gradientStops.AddFirst(new GradientStop(lastStop.Offset - 1, lastStop.Color));
|
||||
gradientStops.RemoveLast();
|
||||
}
|
||||
|
||||
gsAfter = gradientStops.FirstOrDefault(n => n.Offset >= offset);
|
||||
if (gsAfter == null)
|
||||
{
|
||||
GradientStop firstStop = gradientStops.First!.Value;
|
||||
gradientStops.AddLast(new GradientStop(firstStop.Offset + 1, firstStop.Color));
|
||||
gradientStops.RemoveFirst();
|
||||
}
|
||||
|
||||
} while ((gsBefore == null) || (gsAfter == null));
|
||||
|
||||
return (gsBefore, gsAfter);
|
||||
}
|
||||
|
||||
offset = ClipOffset(offset);
|
||||
return (gradientStops.Last(n => n.Offset <= offset), gradientStops.First(n => n.Offset >= offset));
|
||||
}
|
||||
|
||||
#endregion
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.Gradients.LinearGradient" /> class.
|
||||
/// </summary>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
public LinearGradient(params GradientStop[] gradientStops)
|
||||
: base(gradientStops)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.Gradients.AbstractGradient" /> class.
|
||||
/// </summary>
|
||||
/// <param name="wrapGradient">Specifies whether the gradient should wrapp or not (see <see cref="P:RGB.NET.Presets.Textures.Gradients.AbstractGradient.WrapGradient" /> for an example of what this means).</param>
|
||||
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
|
||||
public LinearGradient(bool wrapGradient, params GradientStop[] gradientStops)
|
||||
: base(wrapGradient, gradientStops)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
void OnGradientStopOnPropertyChanged(object? sender, PropertyChangedEventArgs args) => _isOrderedGradientListDirty = true;
|
||||
|
||||
foreach (GradientStop gradientStop in GradientStops)
|
||||
gradientStop.PropertyChanged += OnGradientStopOnPropertyChanged;
|
||||
|
||||
GradientStops.CollectionChanged += (_, args) =>
|
||||
{
|
||||
if (args.OldItems != null)
|
||||
foreach (GradientStop gradientStop in args.OldItems)
|
||||
gradientStop.PropertyChanged -= OnGradientStopOnPropertyChanged;
|
||||
|
||||
if (args.NewItems != null)
|
||||
foreach (GradientStop gradientStop in args.NewItems)
|
||||
gradientStop.PropertyChanged += OnGradientStopOnPropertyChanged;
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets the linear interpolated <see cref="T:RGB.NET.Core.Color" /> at the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to take the color from.</param>
|
||||
/// <returns>The <see cref="T:RGB.NET.Core.Color" /> at the specific offset.</returns>
|
||||
public override Color GetColor(float offset)
|
||||
{
|
||||
if (GradientStops.Count == 0) return Color.Transparent;
|
||||
if (GradientStops.Count == 1) return GradientStops[0].Color;
|
||||
|
||||
if (_isOrderedGradientListDirty)
|
||||
_orderedGradientStops = new LinkedList<GradientStop>(GradientStops.OrderBy(x => x.Offset));
|
||||
|
||||
(GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, _orderedGradientStops, WrapGradient);
|
||||
|
||||
float blendFactor = 0;
|
||||
if (!gsBefore.Offset.Equals(gsAfter.Offset))
|
||||
blendFactor = ((offset - gsBefore.Offset) / (gsAfter.Offset - gsBefore.Offset));
|
||||
|
||||
float colA = ((gsAfter.Color.A - gsBefore.Color.A) * blendFactor) + gsBefore.Color.A;
|
||||
float colR = ((gsAfter.Color.R - gsBefore.Color.R) * blendFactor) + gsBefore.Color.R;
|
||||
float colG = ((gsAfter.Color.G - gsBefore.Color.G) * blendFactor) + gsBefore.Color.G;
|
||||
float colB = ((gsAfter.Color.B - gsBefore.Color.B) * blendFactor) + gsBefore.Color.B;
|
||||
|
||||
return new Color(colA, colR, colG, colB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the two <see cref="GradientStop"/>s encapsulating the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The reference offset.</param>
|
||||
/// <param name="orderedStops">The ordered list of <see cref="GradientStop"/> to choose from.</param>
|
||||
/// <param name="wrap">Bool indicating if the gradient should be wrapped or not.</param>
|
||||
/// <returns>The two <see cref="GradientStop"/>s encapsulating the specified offset.</returns>
|
||||
protected virtual (GradientStop gsBefore, GradientStop gsAfter) GetEnclosingGradientStops(float offset, LinkedList<GradientStop> orderedStops, bool wrap)
|
||||
{
|
||||
LinkedList<GradientStop> gradientStops = new(orderedStops);
|
||||
|
||||
if (wrap)
|
||||
{
|
||||
GradientStop? gsBefore, gsAfter;
|
||||
|
||||
do
|
||||
{
|
||||
gsBefore = gradientStops.LastOrDefault(n => n.Offset <= offset);
|
||||
if (gsBefore == null)
|
||||
{
|
||||
GradientStop lastStop = gradientStops.Last!.Value;
|
||||
gradientStops.AddFirst(new GradientStop(lastStop.Offset - 1, lastStop.Color));
|
||||
gradientStops.RemoveLast();
|
||||
}
|
||||
|
||||
gsAfter = gradientStops.FirstOrDefault(n => n.Offset >= offset);
|
||||
if (gsAfter == null)
|
||||
{
|
||||
GradientStop firstStop = gradientStops.First!.Value;
|
||||
gradientStops.AddLast(new GradientStop(firstStop.Offset + 1, firstStop.Color));
|
||||
gradientStops.RemoveFirst();
|
||||
}
|
||||
|
||||
} while ((gsBefore == null) || (gsAfter == null));
|
||||
|
||||
return (gsBefore, gsAfter);
|
||||
}
|
||||
|
||||
offset = ClipOffset(offset);
|
||||
return (gradientStops.Last(n => n.Offset <= offset), gradientStops.First(n => n.Offset >= offset));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -5,105 +5,104 @@ using System;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Decorators;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Gradients
|
||||
namespace RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
/// <inheritdoc cref="AbstractDecoratable{T}" />
|
||||
/// <inheritdoc cref="IGradient" />
|
||||
/// <summary>
|
||||
/// Represents a rainbow gradient which circles through all colors of the HUE-color-space.<br />
|
||||
/// See <see href="http://upload.wikimedia.org/wikipedia/commons/a/ad/HueScale.svg" /> as reference.
|
||||
/// </summary>
|
||||
public class RainbowGradient : AbstractDecoratable<IGradientDecorator>, IGradient
|
||||
{
|
||||
/// <inheritdoc cref="AbstractDecoratable{T}" />
|
||||
/// <inheritdoc cref="IGradient" />
|
||||
#region Properties & Fields
|
||||
|
||||
private float _startHue;
|
||||
/// <summary>
|
||||
/// Represents a rainbow gradient which circles through all colors of the HUE-color-space.<br />
|
||||
/// See <see href="http://upload.wikimedia.org/wikipedia/commons/a/ad/HueScale.svg" /> as reference.
|
||||
/// Gets or sets the hue (in degrees) to start from.
|
||||
/// </summary>
|
||||
public class RainbowGradient : AbstractDecoratable<IGradientDecorator>, IGradient
|
||||
public float StartHue
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private float _startHue;
|
||||
/// <summary>
|
||||
/// Gets or sets the hue (in degrees) to start from.
|
||||
/// </summary>
|
||||
public float StartHue
|
||||
{
|
||||
get => _startHue;
|
||||
set => SetProperty(ref _startHue, value);
|
||||
}
|
||||
|
||||
private float _endHue;
|
||||
/// <summary>
|
||||
/// Gets or sets the hue (in degrees) to end the with.
|
||||
/// </summary>
|
||||
public float EndHue
|
||||
{
|
||||
get => _endHue;
|
||||
set => SetProperty(ref _endHue, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? GradientChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RainbowGradient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="startHue">The hue (in degrees) to start from (default: 0)</param>
|
||||
/// <param name="endHue">The hue (in degrees) to end with (default: 360)</param>
|
||||
public RainbowGradient(float startHue = 0, float endHue = 360)
|
||||
{
|
||||
this.StartHue = startHue;
|
||||
this.EndHue = endHue;
|
||||
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets the color on the rainbow at the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to take the color from.</param>
|
||||
/// <returns>The color at the specific offset.</returns>
|
||||
public Color GetColor(float offset)
|
||||
{
|
||||
float range = EndHue - StartHue;
|
||||
float hue = StartHue + (range * offset);
|
||||
return HSVColor.Create(hue, 1, 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Move(float offset)
|
||||
{
|
||||
// RainbowGradient is calculated inverse
|
||||
offset *= -1;
|
||||
|
||||
StartHue += offset;
|
||||
EndHue += offset;
|
||||
|
||||
while ((StartHue > 360) && (EndHue > 360))
|
||||
{
|
||||
StartHue -= 360;
|
||||
EndHue -= 360;
|
||||
}
|
||||
while ((StartHue < -360) && (EndHue < -360))
|
||||
{
|
||||
StartHue += 360;
|
||||
EndHue += 360;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be called to indicate that the gradient was changed.
|
||||
/// </summary>
|
||||
protected void OnGradientChanged() => GradientChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
get => _startHue;
|
||||
set => SetProperty(ref _startHue, value);
|
||||
}
|
||||
}
|
||||
|
||||
private float _endHue;
|
||||
/// <summary>
|
||||
/// Gets or sets the hue (in degrees) to end the with.
|
||||
/// </summary>
|
||||
public float EndHue
|
||||
{
|
||||
get => _endHue;
|
||||
set => SetProperty(ref _endHue, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? GradientChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RainbowGradient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="startHue">The hue (in degrees) to start from (default: 0)</param>
|
||||
/// <param name="endHue">The hue (in degrees) to end with (default: 360)</param>
|
||||
public RainbowGradient(float startHue = 0, float endHue = 360)
|
||||
{
|
||||
this.StartHue = startHue;
|
||||
this.EndHue = endHue;
|
||||
|
||||
PropertyChanged += (_, _) => OnGradientChanged();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets the color on the rainbow at the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The percentage offset to take the color from.</param>
|
||||
/// <returns>The color at the specific offset.</returns>
|
||||
public Color GetColor(float offset)
|
||||
{
|
||||
float range = EndHue - StartHue;
|
||||
float hue = StartHue + (range * offset);
|
||||
return HSVColor.Create(hue, 1, 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Move(float offset)
|
||||
{
|
||||
// RainbowGradient is calculated inverse
|
||||
offset *= -1;
|
||||
|
||||
StartHue += offset;
|
||||
EndHue += offset;
|
||||
|
||||
while ((StartHue > 360) && (EndHue > 360))
|
||||
{
|
||||
StartHue -= 360;
|
||||
EndHue -= 360;
|
||||
}
|
||||
while ((StartHue < -360) && (EndHue < -360))
|
||||
{
|
||||
StartHue += 360;
|
||||
EndHue += 360;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be called to indicate that the gradient was changed.
|
||||
/// </summary>
|
||||
protected void OnGradientChanged() => GradientChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -9,74 +9,73 @@ using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Helper;
|
||||
using RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a texture drawing a linear gradient.
|
||||
/// </summary>
|
||||
public sealed class LinearGradientTexture : AbstractGradientTexture
|
||||
{
|
||||
/// <inheritdoc />
|
||||
#region Properties & Fields
|
||||
|
||||
private Point _startPoint = new(0, 0.5f);
|
||||
/// <summary>
|
||||
/// Represents a texture drawing a linear gradient.
|
||||
/// Gets or sets the start <see cref="Point"/> (as percentage in the range [0..1]) of the <see cref="IGradient"/> drawn by this <see cref="LinearGradientTexture"/>. (default: 0.0, 0.5)
|
||||
/// </summary>
|
||||
public sealed class LinearGradientTexture : AbstractGradientTexture
|
||||
public Point StartPoint
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private Point _startPoint = new(0, 0.5f);
|
||||
/// <summary>
|
||||
/// Gets or sets the start <see cref="Point"/> (as percentage in the range [0..1]) of the <see cref="IGradient"/> drawn by this <see cref="LinearGradientTexture"/>. (default: 0.0, 0.5)
|
||||
/// </summary>
|
||||
public Point StartPoint
|
||||
{
|
||||
get => _startPoint;
|
||||
set => SetProperty(ref _startPoint, value);
|
||||
}
|
||||
|
||||
private Point _endPoint = new(1, 0.5f);
|
||||
/// <summary>
|
||||
/// Gets or sets the end <see cref="Point"/> (as percentage in the range [0..1]) of the <see cref="IGradient"/> drawn by this <see cref="LinearGradientTexture"/>. (default: 1.0, 0.5)
|
||||
/// </summary>
|
||||
public Point EndPoint
|
||||
{
|
||||
get => _endPoint;
|
||||
set => SetProperty(ref _endPoint, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" />.</param>
|
||||
public LinearGradientTexture(Size size, IGradient gradient)
|
||||
: base(size, gradient)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" />.</param>
|
||||
/// <param name="startPoint">The start <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
/// <param name="endPoint">The end <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
public LinearGradientTexture(Size size, IGradient gradient, Point startPoint, Point endPoint)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.StartPoint = startPoint;
|
||||
this.EndPoint = endPoint;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in Point point)
|
||||
{
|
||||
float offset = GradientHelper.CalculateLinearGradientOffset(StartPoint, EndPoint, point);
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
|
||||
#endregion
|
||||
get => _startPoint;
|
||||
set => SetProperty(ref _startPoint, value);
|
||||
}
|
||||
}
|
||||
|
||||
private Point _endPoint = new(1, 0.5f);
|
||||
/// <summary>
|
||||
/// Gets or sets the end <see cref="Point"/> (as percentage in the range [0..1]) of the <see cref="IGradient"/> drawn by this <see cref="LinearGradientTexture"/>. (default: 1.0, 0.5)
|
||||
/// </summary>
|
||||
public Point EndPoint
|
||||
{
|
||||
get => _endPoint;
|
||||
set => SetProperty(ref _endPoint, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" />.</param>
|
||||
public LinearGradientTexture(Size size, IGradient gradient)
|
||||
: base(size, gradient)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The <see cref="T:RGB.NET.Presets.Gradients.IGradient" /> drawn by this <see cref="T:RGB.NET.Presets.Textures.LinearGradientTexture" />.</param>
|
||||
/// <param name="startPoint">The start <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
/// <param name="endPoint">The end <see cref="T:RGB.NET.Core.Point" /> (as percentage in the range [0..1]).</param>
|
||||
public LinearGradientTexture(Size size, IGradient gradient, Point startPoint, Point endPoint)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.StartPoint = startPoint;
|
||||
this.EndPoint = endPoint;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in Point point)
|
||||
{
|
||||
float offset = GradientHelper.CalculateLinearGradientOffset(StartPoint, EndPoint, point);
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -6,76 +6,75 @@ using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Helper;
|
||||
using RGB.NET.Presets.Textures.Gradients;
|
||||
|
||||
namespace RGB.NET.Presets.Textures
|
||||
namespace RGB.NET.Presets.Textures;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a texture drawing a radial gradient around a center point.
|
||||
/// </summary>
|
||||
public sealed class RadialGradientTexture : AbstractGradientTexture
|
||||
{
|
||||
/// <inheritdoc />
|
||||
#region Properties & Fields
|
||||
|
||||
private float _referenceDistance = GradientHelper.CalculateDistance(new Point(0.5f, 0.5f), new Point(0, 0));
|
||||
|
||||
private Point _center = new(0.5f, 0.5f);
|
||||
/// <summary>
|
||||
/// Represents a texture drawing a radial gradient around a center point.
|
||||
/// Gets or sets the center <see cref="Point"/> (as percentage in the range [0..1]) around which the <see cref="RadialGradientTexture"/> should be drawn. (default: 0.5, 0.5)
|
||||
/// </summary>
|
||||
public sealed class RadialGradientTexture : AbstractGradientTexture
|
||||
public Point Center
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private float _referenceDistance = GradientHelper.CalculateDistance(new Point(0.5f, 0.5f), new Point(0, 0));
|
||||
|
||||
private Point _center = new(0.5f, 0.5f);
|
||||
/// <summary>
|
||||
/// Gets or sets the center <see cref="Point"/> (as percentage in the range [0..1]) around which the <see cref="RadialGradientTexture"/> should be drawn. (default: 0.5, 0.5)
|
||||
/// </summary>
|
||||
public Point Center
|
||||
get => _center;
|
||||
set
|
||||
{
|
||||
get => _center;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _center, value))
|
||||
CalculateReferenceDistance();
|
||||
}
|
||||
if (SetProperty(ref _center, value))
|
||||
CalculateReferenceDistance();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.RadialGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The gradient drawn by the brush.</param>
|
||||
public RadialGradientTexture(Size size, IGradient gradient)
|
||||
: base(size, gradient)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.RadialGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The gradient drawn by the brush.</param>
|
||||
/// <param name="center">The center point (as percentage in the range [0..1]).</param>
|
||||
public RadialGradientTexture(Size size, IGradient gradient, Point center)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.Center = center;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private void CalculateReferenceDistance()
|
||||
{
|
||||
float referenceX = Center.X < 0.5f ? 1 : 0;
|
||||
float referenceY = Center.Y < 0.5f ? 1 : 0;
|
||||
_referenceDistance = GradientHelper.CalculateDistance(new Point(referenceX, referenceY), Center);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in Point point)
|
||||
{
|
||||
float distance = GradientHelper.CalculateDistance(point, Center);
|
||||
float offset = distance / _referenceDistance;
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.RadialGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The gradient drawn by the brush.</param>
|
||||
public RadialGradientTexture(Size size, IGradient gradient)
|
||||
: base(size, gradient)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Presets.Textures.RadialGradientTexture" /> class.
|
||||
/// </summary>
|
||||
/// <param name="size">The size of the texture.</param>
|
||||
/// <param name="gradient">The gradient drawn by the brush.</param>
|
||||
/// <param name="center">The center point (as percentage in the range [0..1]).</param>
|
||||
public RadialGradientTexture(Size size, IGradient gradient, Point center)
|
||||
: base(size, gradient)
|
||||
{
|
||||
this.Center = center;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private void CalculateReferenceDistance()
|
||||
{
|
||||
float referenceX = Center.X < 0.5f ? 1 : 0;
|
||||
float referenceY = Center.Y < 0.5f ? 1 : 0;
|
||||
_referenceDistance = GradientHelper.CalculateDistance(new Point(referenceX, referenceY), Center);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Color GetColor(in Point point)
|
||||
{
|
||||
float distance = GradientHelper.CalculateDistance(point, Center);
|
||||
float offset = distance / _referenceDistance;
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,34 +1,33 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Sampler
|
||||
namespace RGB.NET.Presets.Textures.Sampler;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a sampled that averages multiple byte-data entries.
|
||||
/// </summary>
|
||||
public class AverageByteSampler : ISampler<byte>
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a sampled that averages multiple byte-data entries.
|
||||
/// </summary>
|
||||
public class AverageByteSampler : ISampler<byte>
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Sample(in SamplerInfo<byte> info, in Span<byte> pixelData)
|
||||
{
|
||||
#region Methods
|
||||
int count = info.Width * info.Height;
|
||||
if (count == 0) return;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Sample(in SamplerInfo<byte> info, in Span<byte> pixelData)
|
||||
{
|
||||
int count = info.Width * info.Height;
|
||||
if (count == 0) return;
|
||||
ReadOnlySpan<byte> data = info.Data;
|
||||
|
||||
ReadOnlySpan<byte> data = info.Data;
|
||||
int dataLength = pixelData.Length;
|
||||
Span<uint> sums = stackalloc uint[dataLength];
|
||||
for (int i = 0; i < data.Length; i += dataLength)
|
||||
for (int j = 0; j < sums.Length; j++)
|
||||
sums[j] += data[i + j];
|
||||
|
||||
int dataLength = pixelData.Length;
|
||||
Span<uint> sums = stackalloc uint[dataLength];
|
||||
for (int i = 0; i < data.Length; i += dataLength)
|
||||
for (int j = 0; j < sums.Length; j++)
|
||||
sums[j] += data[i + j];
|
||||
|
||||
float divisor = count * byte.MaxValue;
|
||||
for (int i = 0; i < pixelData.Length; i++)
|
||||
pixelData[i] = (sums[i] / divisor).GetByteValueFromPercentage();
|
||||
}
|
||||
|
||||
#endregion
|
||||
float divisor = count * byte.MaxValue;
|
||||
for (int i = 0; i < pixelData.Length; i++)
|
||||
pixelData[i] = (sums[i] / divisor).GetByteValueFromPercentage();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,33 +1,32 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Presets.Textures.Sampler
|
||||
namespace RGB.NET.Presets.Textures.Sampler;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a sampled that averages multiple float-data entries.
|
||||
/// </summary>
|
||||
public class AverageFloatSampler : ISampler<float>
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a sampled that averages multiple float-data entries.
|
||||
/// </summary>
|
||||
public class AverageFloatSampler : ISampler<float>
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Sample(in SamplerInfo<float> info, in Span<float> pixelData)
|
||||
{
|
||||
#region Methods
|
||||
int count = info.Width * info.Height;
|
||||
if (count == 0) return;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Sample(in SamplerInfo<float> info, in Span<float> pixelData)
|
||||
{
|
||||
int count = info.Width * info.Height;
|
||||
if (count == 0) return;
|
||||
ReadOnlySpan<float> data = info.Data;
|
||||
|
||||
ReadOnlySpan<float> data = info.Data;
|
||||
int dataLength = pixelData.Length;
|
||||
Span<float> sums = stackalloc float[dataLength];
|
||||
for (int i = 0; i < data.Length; i += dataLength)
|
||||
for (int j = 0; j < sums.Length; j++)
|
||||
sums[j] += data[i + j];
|
||||
|
||||
int dataLength = pixelData.Length;
|
||||
Span<float> sums = stackalloc float[dataLength];
|
||||
for (int i = 0; i < data.Length; i += dataLength)
|
||||
for (int j = 0; j < sums.Length; j++)
|
||||
sums[j] += data[i + j];
|
||||
|
||||
for (int i = 0; i < pixelData.Length; i++)
|
||||
pixelData[i] = sums[i] / count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
for (int i = 0; i < pixelData.Length; i++)
|
||||
pixelData[i] = sums[i] / count;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in new issue
Block a user