diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs
index 59d0eae..3a418f3 100644
--- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs
+++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs
@@ -31,8 +31,8 @@ namespace RGB.NET.Core
///
public Size Size
{
- get => _size;
- set => SetProperty(ref _size, value);
+ get => _size * Scale;
+ protected set => SetProperty(ref _size, value);
}
private Point _location = new Point(0, 0);
@@ -43,6 +43,18 @@ namespace RGB.NET.Core
set => SetProperty(ref _location, value);
}
+ private Scale _scale = new Scale(1);
+ ///
+ public Scale Scale
+ {
+ get => _scale;
+ set
+ {
+ if (SetProperty(ref _scale, value))
+ OnPropertyChanged(nameof(Size));
+ }
+ }
+
///
/// Gets or sets if the device needs to be flushed on every update.
///
@@ -67,11 +79,11 @@ namespace RGB.NET.Core
Led IRGBDevice.this[LedId ledId] => LedMapping.TryGetValue(ledId, out Led led) ? led : null;
///
- Led IRGBDevice.this[Point location] => LedMapping.Values.FirstOrDefault(x => x.LedRectangle.Contains(location));
+ Led IRGBDevice.this[Point location] => LedMapping.Values.FirstOrDefault(x => x.ActualLedRectangle.Contains(location));
///
IEnumerable IRGBDevice.this[Rectangle referenceRect, double minOverlayPercentage]
- => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.LedRectangle) >= minOverlayPercentage);
+ => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.ActualLedRectangle) >= minOverlayPercentage);
#endregion
diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs
index 9ba17c4..9321850 100644
--- a/RGB.NET.Core/Devices/IRGBDevice.cs
+++ b/RGB.NET.Core/Devices/IRGBDevice.cs
@@ -27,6 +27,8 @@ namespace RGB.NET.Core
/// Gets a copy of the of the whole .
///
Size Size { get; }
+
+ Scale Scale { get; set; }
///
/// Gets or sets the of the .
diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs
index 27bf4ed..a52cc6d 100644
--- a/RGB.NET.Core/Leds/Led.cs
+++ b/RGB.NET.Core/Leds/Led.cs
@@ -1,6 +1,7 @@
// ReSharper disable MemberCanBePrivate.Global
using System;
+using System.ComponentModel;
using System.Diagnostics;
namespace RGB.NET.Core
@@ -54,14 +55,19 @@ namespace RGB.NET.Core
set
{
if (SetProperty(ref _ledRectangle, value))
+ {
+ OnPropertyChanged(nameof(ActualLedRectangle));
OnPropertyChanged(nameof(AbsoluteLedRectangle));
+ }
}
}
+ public Rectangle ActualLedRectangle => new Rectangle(LedRectangle.Location * Device.Scale, LedRectangle.Size * Device.Scale);
+
///
/// Gets a rectangle representing the physical location of the on the .
///
- public Rectangle AbsoluteLedRectangle => (LedRectangle.Location + Device.Location) + new Size(LedRectangle.Size.Width, LedRectangle.Size.Height);
+ public Rectangle AbsoluteLedRectangle => new Rectangle(ActualLedRectangle.Location + Device.Location, ActualLedRectangle.Size);
///
/// Indicates whether the is about to change it's color.
@@ -152,17 +158,26 @@ namespace RGB.NET.Core
this.LedRectangle = ledRectangle;
this.CustomData = customData;
- device.PropertyChanged += (sender, args) =>
- {
- OnPropertyChanged(nameof(LedRectangle));
- OnPropertyChanged(nameof(AbsoluteLedRectangle));
- };
+ device.PropertyChanged += DevicePropertyChanged;
}
#endregion
#region Methods
+ private void DevicePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if ((e.PropertyName == nameof(IRGBDevice.Location)))
+ {
+ OnPropertyChanged(nameof(AbsoluteLedRectangle));
+ }
+ else if ((e.PropertyName == nameof(IRGBDevice.Scale)))
+ {
+ OnPropertyChanged(nameof(ActualLedRectangle));
+ OnPropertyChanged(nameof(AbsoluteLedRectangle));
+ }
+ }
+
///
/// Converts the and the of this to a human-readable string.
///
@@ -210,7 +225,7 @@ namespace RGB.NET.Core
/// Converts a to a .
///
/// The to convert.
- public static implicit operator Rectangle(Led led) => led?.LedRectangle ?? new Rectangle();
+ public static implicit operator Rectangle(Led led) => led?.ActualLedRectangle ?? new Rectangle();
#endregion
}
diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs
index 58eb2d9..38be165 100644
--- a/RGB.NET.Core/Positioning/Point.cs
+++ b/RGB.NET.Core/Positioning/Point.cs
@@ -149,6 +149,8 @@ namespace RGB.NET.Core
return new Point(point1.X / point2.X, point1.Y / point2.Y);
}
+ public static Point operator *(Point point, Scale scale) => new Point(point.X * scale.Horizontal, point.Y * scale.Vertical);
+
#endregion
}
}
diff --git a/RGB.NET.Core/Positioning/Scale.cs b/RGB.NET.Core/Positioning/Scale.cs
new file mode 100644
index 0000000..42558e5
--- /dev/null
+++ b/RGB.NET.Core/Positioning/Scale.cs
@@ -0,0 +1,46 @@
+namespace RGB.NET.Core
+{
+ public struct Scale
+ {
+ #region Properties & Fields
+
+ public double Horizontal { get; }
+ public double Vertical { get; }
+
+ #endregion
+
+ #region Constructors
+
+ public Scale(double scale = 1.0) : this(scale, scale)
+ { }
+
+ public Scale(double horizontal, double vertical)
+ {
+ this.Horizontal = horizontal;
+ this.Vertical = vertical;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public bool Equals(Scale other) => Horizontal.EqualsInTolerance(other.Horizontal) && Vertical.EqualsInTolerance(other.Vertical);
+ public override bool Equals(object obj) => obj is Scale other && Equals(other);
+ public override int GetHashCode() { unchecked { return (Horizontal.GetHashCode() * 397) ^ Vertical.GetHashCode(); } }
+
+ public void Deconstruct(out double horizontalScale, out double verticalScale)
+ {
+ horizontalScale = Horizontal;
+ verticalScale = Vertical;
+ }
+
+ #endregion
+
+ #region Operators
+
+ public static implicit operator Scale(double scale) => new Scale(scale);
+ public static implicit operator Scale((double horizontal, double vertical) scale) => new Scale(scale.horizontal, scale.vertical);
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs
index d6b7c6f..8342c4f 100644
--- a/RGB.NET.Core/Positioning/Size.cs
+++ b/RGB.NET.Core/Positioning/Size.cs
@@ -94,6 +94,12 @@ namespace RGB.NET.Core
}
}
+ public void Deconstruct(out double width, out double height)
+ {
+ width = Width;
+ height = Height;
+ }
+
#endregion
#region Operators
@@ -172,6 +178,8 @@ namespace RGB.NET.Core
/// A new representing the division of the and the provided factor.
public static Size operator /(Size size, double factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor);
+ public static Size operator *(Size size, Scale scale) => new Size(size.Width * scale.Horizontal, size.Height * scale.Vertical);
+
#endregion
}
}
diff --git a/RGB.NET.Groups/Groups/RectangleLedGroup.cs b/RGB.NET.Groups/Groups/RectangleLedGroup.cs
index 18ffb8c..9958a0d 100644
--- a/RGB.NET.Groups/Groups/RectangleLedGroup.cs
+++ b/RGB.NET.Groups/Groups/RectangleLedGroup.cs
@@ -59,7 +59,7 @@ namespace RGB.NET.Groups
/// (optional) The minimal percentage overlay a must have with the to be taken into the . (default: 0.5)
/// (optional) Specifies whether this should be automatically attached or not. (default: true)
public RectangleLedGroup(Led fromLed, Led toLed, double minOverlayPercentage = 0.5, bool autoAttach = true)
- : this(new Rectangle(fromLed.LedRectangle, toLed.LedRectangle), minOverlayPercentage, autoAttach)
+ : this(new Rectangle(fromLed.ActualLedRectangle, toLed.ActualLedRectangle), minOverlayPercentage, autoAttach)
{ }
///