/* Copyright (c) 2022-present miku-666, MattNL * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ using System; using System.Collections.Specialized; using System.Text.RegularExpressions; namespace PckStudio.Core.Skin { /// /// Represents a Skin Anim value where flags can be set /// public class SkinANIM : ICloneable, IEquatable, IEquatable { public static readonly SkinANIM Empty = new SkinANIM(0); private BitVector32 _flags; private static readonly Regex _validator = new Regex(@"^0x[0-9a-f]{1,8}\b", RegexOptions.IgnoreCase); public SkinANIM(SkinAnimMask mask) : this((int)mask) { } private SkinANIM(int mask) { _flags = new BitVector32(mask); } public override string ToString() => "0x" + _flags.Data.ToString("x8"); public static bool IsValidANIM(string anim) { return !string.IsNullOrWhiteSpace(anim) && _validator.IsMatch(anim); } public static SkinANIM FromString(string value) => IsValidANIM(value) ? new SkinANIM(Convert.ToInt32(value.TrimEnd(' ', '\n', '\r'), 16)) : Empty; public static SkinANIM operator |(SkinANIM @this, SkinANIM other) => new SkinANIM(@this._flags.Data | other._flags.Data); public static SkinANIM operator |(SkinANIM @this, SkinAnimMask mask) => new SkinANIM(@this._flags.Data | (int)mask); public static SkinANIM operator &(SkinANIM @this, SkinAnimMask mask) => new SkinANIM(@this._flags.Data & (int)mask); public static SkinANIM FromValue(int value) => new SkinANIM(value); public int ToValue() => _flags.Data; public static implicit operator SkinANIM(SkinAnimMask mask) => new SkinANIM(mask); public static bool operator ==(SkinANIM @this, SkinAnimMask mask) => @this.Equals(mask); public static bool operator !=(SkinANIM @this, SkinAnimMask mask) => !@this.Equals(mask); public static bool operator ==(SkinANIM @this, SkinANIM other) => @this.Equals(other); public static bool operator !=(SkinANIM @this, SkinANIM other) => !@this.Equals(other); public bool Equals(SkinANIM other) { return _flags.Data == other._flags.Data; } public bool Equals(SkinAnimMask other) { return _flags.Data == (int)other; } public override bool Equals(object obj) => obj is SkinANIM a && Equals(a); public override int GetHashCode() => _flags.Data; /// /// Sets the desired flag in the bitfield /// /// ANIM Flag to set /// State of the flag public SkinANIM SetFlag(SkinAnimFlag flag, bool state) { if (!Enum.IsDefined(typeof(SkinAnimFlag), flag)) throw new ArgumentOutOfRangeException(nameof(flag)); return new SkinANIM(state ? _flags.Data | 1 << (int)flag : _flags.Data & ~(1 << (int)flag)); } /// /// Gets flag state /// /// Flag to check /// True if flag is set, otherwise false public bool GetFlag(SkinAnimFlag flag) { if (!Enum.IsDefined(typeof(SkinAnimFlag), flag)) throw new ArgumentOutOfRangeException(nameof(flag)); return _flags[1 << (int)flag]; } public object Clone() { return MemberwiseClone(); } } }