// Magica Cloth 2. // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System; using System.Runtime.CompilerServices; namespace MagicaCloth2 { /// /// 頂点の属性 /// [System.Serializable] public struct VertexAttribute : IEquatable { /// /// ビットフラグ /// public const byte Flag_Fixed = 0x01; // 固定 public const byte Flag_Move = 0x02; // 移動 //public const byte Flag_Ignore = 0x04; // 無視(シミュレーションの対象としない):一旦オミット! public const byte Flag_InvalidMotion = 0x08; // モーション制約無効 public const byte Flag_DisableCollision = 0x10; // コリジョン無効 public const byte Flag_Triangle = 0x80; // この頂点はトライアングルに属している public static readonly VertexAttribute Invalid = new VertexAttribute(); public static readonly VertexAttribute Fixed = new VertexAttribute(Flag_Fixed); public static readonly VertexAttribute Move = new VertexAttribute(Flag_Move); public static readonly VertexAttribute DisableCollision = new VertexAttribute(Flag_DisableCollision); //========================================================================================= /// /// 属性値(ビットフラグ) /// public byte Value; //========================================================================================= public VertexAttribute(byte initialValue = 0) { Value = initialValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() { Value = 0; } /// /// フラグ設定 /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetFlag(byte flag, bool sw) { if (sw) Value |= flag; else Value = (byte)(Value & ~flag); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetFlag(VertexAttribute attr, bool sw) { if (sw) Value |= attr.Value; else Value = (byte)(Value & ~attr.Value); } /// /// フラグ判定 /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsSet(byte flag) { return (Value & flag) != 0; } /// /// 無効属性判定(Move/Fixed/Ignoreのどれでもない場合) /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsInvalid() => IsSet(Flag_Fixed | Flag_Move) == false; //public bool IsInvalid() => IsSet(Flag_Fixed | Flag_Move | Flag_Ignore) == false; /// /// 固定属性判定 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsFixed() => IsSet(Flag_Fixed); /// /// 移動属性判定 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsMove() => IsSet(Flag_Move); /// /// 移動しないパーティクルか判定する /// これは固定属性以外にも掴まれたことにより動かなくなったパーティクルも含まれる /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsDontMove() => !IsSet(Flag_Move); /// /// 無視属性判定 /// /// //[MethodImpl(MethodImplOptions.AggressiveInlining)] //public bool IsIgnore() => IsSet(Flag_Ignore); /// /// モーション制約の有効判定 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsMotion() => IsSet(Flag_InvalidMotion) == false; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsDisableCollision() => IsSet(Flag_DisableCollision); //========================================================================================= /// /// 2つの頂点属性を結合して新しい属性を返す /// 基本的に属性値が低い方が優先される(無効(0)>固定(1)>移動(2)) /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static VertexAttribute JoinAttribute(VertexAttribute attr1, VertexAttribute attr2) { // todo:ここは頂点属性が増えると厄介かも return attr1.Value < attr2.Value ? attr1 : attr2; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(VertexAttribute other) { return Value == other.Value; } public override bool Equals(object obj) { return obj is VertexAttribute converted && Equals(converted); } public override int GetHashCode() { return Value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(VertexAttribute lhs, VertexAttribute rhs) { return lhs.Value == rhs.Value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(VertexAttribute lhs, VertexAttribute rhs) { return lhs.Value != rhs.Value; } } }