// ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using RGB.NET.Core.Layout; namespace RGB.NET.Core { /// /// /// /// Represents a generic RGB-device. /// public abstract class AbstractRGBDevice : AbstractBindable, IRGBDevice where TDeviceInfo : class, IRGBDeviceInfo { #region Properties & Fields RGBSurface? IRGBDevice.Surface { get; set; } /// public abstract TDeviceInfo DeviceInfo { get; } /// IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo; private Point _location = new(0, 0); /// public Point Location { get => _location; set { if (SetProperty(ref _location, value)) UpdateActualData(); } } private Size _size = Size.Invalid; /// public Size Size { get => _size; set { if (SetProperty(ref _size, value)) UpdateActualData(); } } private Size _actualSize; /// public Size ActualSize { get => _actualSize; private set => SetProperty(ref _actualSize, value); } private Rectangle _deviceRectangle; /// public Rectangle DeviceRectangle { get => _deviceRectangle; private set => SetProperty(ref _deviceRectangle, value); } private Scale _scale = new(1); /// public Scale Scale { get => _scale; set { if (SetProperty(ref _scale, value)) UpdateActualData(); } } private Rotation _rotation = new(0); /// public Rotation Rotation { get => _rotation; set { if (SetProperty(ref _rotation, value)) UpdateActualData(); } } /// /// Gets or sets if the device needs to be flushed on every update. /// protected bool RequiresFlush { get; set; } = false; /// /// Gets a dictionary containing all of the . /// protected Dictionary LedMapping { get; } = new(); #region Indexer /// 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)); /// IEnumerable IRGBDevice.this[Rectangle referenceRect, double minOverlayPercentage] => LedMapping.Values.Where(x => referenceRect.CalculateIntersectPercentage(x.LedRectangle) >= minOverlayPercentage); #endregion #endregion #region Methods private void UpdateActualData() { ActualSize = Size * Scale; DeviceRectangle = new Rectangle(Location, new Rectangle(new Rectangle(Location, ActualSize).Rotate(Rotation)).Size); } /// public virtual void Update(bool flushLeds = false) { // Device-specific updates DeviceUpdate(); // Send LEDs to SDK List ledsToUpdate = GetLedsToUpdate(flushLeds)?.ToList() ?? new List(); foreach (Led ledToUpdate in ledsToUpdate) ledToUpdate.Update(); UpdateLeds(ledsToUpdate); } protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)); /// public virtual void Dispose() { try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ } } /// /// Performs device specific updates. /// protected virtual void DeviceUpdate() { } /// /// Sends all the updated to the device. /// protected abstract void UpdateLeds(IEnumerable ledsToUpdate); /// /// Initializes the with the specified id. /// /// The to initialize. /// The location of the to initialize. /// The size of the to initialize. /// The initialized led. public virtual Led? AddLed(LedId ledId, Point location, Size size, object? customData = null) { if ((ledId == LedId.Invalid) || LedMapping.ContainsKey(ledId)) return null; Led led = new(this, ledId, location, size, customData); LedMapping.Add(ledId, led); return led; } public virtual Led? RemoveLed(LedId ledId) { if (ledId == LedId.Invalid) return null; if (!LedMapping.TryGetValue(ledId, out Led? led)) return null; LedMapping.Remove(ledId); return led; } #region Enumerator /// /// /// Returns an enumerator that iterates over all of the . /// /// An enumerator for all of the . public IEnumerator GetEnumerator() => LedMapping.Values.GetEnumerator(); /// /// /// Returns an enumerator that iterates over all of the . /// /// An enumerator for all of the . IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion #endregion } }