using Newtonsoft.Json; using RhythmBase.Converters; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace RhythmBase.Components { /// /// A size whose horizontal and vertical coordinates are nullable /// [JsonConverter(typeof(RDPointsConverter))] [DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")] public struct RDSizeI(int? width, int? height) : IRDVortex { /// /// Initializes a new instance of the struct with the specified point. /// /// The point to initialize the size with. public RDSizeI(RDPointI pt) : this(pt.X, pt.Y) { } /// /// Gets a value indicating whether this size is empty (both width and height are null). /// public readonly bool IsEmpty => Width == null && Height == null; /// /// Gets or sets the width of the size. /// public int? Width { get; set; } = width; /// /// Gets or sets the height of the size. /// public int? Height { get; set; } = height; /// /// Gets the area of the size (width multiplied by height). /// public readonly int? Area => Width * Height; /// /// Adds two sizes together. /// /// The first size. /// The second size. /// The sum of the two sizes. public static RDSizeI Add(RDSizeI sz1, RDSizeI sz2) => new(sz1.Width + sz2.Width, sz1.Height + sz2.Height); /// /// Truncates the specified size to the nearest integer values. /// /// The size to truncate. /// The truncated size. public static RDSizeI Truncate(RDSize value) => new( (int)Math.Round((value.Width == null) ? 0.0 : Math.Truncate((double)value.Width.Value)), (int)Math.Round((value.Height == null) ? 0.0 : Math.Truncate((double)value.Height.Value))); /// /// Subtracts one size from another. /// /// The size to subtract from. /// The size to subtract. /// The difference between the two sizes. public static RDSizeI Subtract(RDSizeI sz1, RDSizeI sz2) => new(sz1.Width - sz2.Width, sz1.Height - sz2.Height); /// /// Rounds the specified size up to the nearest integer values. /// /// The size to round up. /// The rounded size. public static RDSizeI Ceiling(RDSize value) => new( (int)Math.Round((value.Width == null) ? 0.0 : Math.Ceiling((double)value.Width.Value)), (int)Math.Round((value.Height == null) ? 0.0 : Math.Ceiling((double)value.Height.Value))); /// /// Rounds the specified size to the nearest integer values. /// /// The size to round. /// The rounded size. public static RDSizeI Round(RDSize value) => new( new int?((int)Math.Round((value.Width == null) ? 0.0 : Math.Round((double)value.Width.Value))), new int?((int)Math.Round((value.Height == null) ? 0.0 : Math.Round((double)value.Height.Value)))); /// public override readonly bool Equals([NotNullWhen(true)] object? obj) => obj is RDSizeI e && Equals(e); /// public override readonly int GetHashCode() => HashCode.Combine(Width, Height); /// public override readonly string ToString() => $"[{Width},{Height}]"; /// public readonly bool Equals(RDSizeI other) => Width == other.Width && Height == other.Height; /// public static RDSizeI operator +(RDSizeI sz1, RDSizeI sz2) => Add(sz1, sz2); /// public static RDSizeI operator -(RDSizeI sz1, RDSizeI sz2) => Subtract(sz1, sz2); /// public static RDSize operator *(float left, RDSizeI right) => new(left * right.Width, left * right.Height); /// public static RDSize operator *(RDSizeI left, float right) => new(left.Width * right, left.Height * right); /// public static RDSizeI operator *(int left, RDSizeI right) => new(left * right.Width, left * right.Height); /// public static RDSizeI operator *(RDSizeI left, int? right) => new(left.Width * right, left.Height * right); /// public static RDSize operator /(RDSizeI left, float right) => new(left.Width / right, left.Height / right); /// public static RDSizeI operator /(RDSizeI left, int? right) => new(left.Width / right, left.Height / right); /// public static bool operator ==(RDSizeI sz1, RDSizeI sz2) => sz1.Equals(sz2); /// public static bool operator !=(RDSizeI sz1, RDSizeI sz2) => !sz1.Equals(sz2); /// /// Implicitly converts an to an . /// /// The to convert. /// A new with the same width and height. public static implicit operator RDSize(RDSizeI p) => new(p.Width, p.Height); /// /// Implicitly converts an to an . /// /// The to convert. /// A new with the same width and height. public static implicit operator RDSizeE(RDSizeI p) => new(p.Width, p.Height); /// /// Explicitly converts an to an . /// /// The to convert. /// A new with the same width and height. public static explicit operator RDPointI(RDSizeI size) => new(size.Width, size.Height); private readonly string GetDebuggerDisplay() => ToString(); } }