167 lines
6.0 KiB
C#
167 lines
6.0 KiB
C#
|
// Magica Cloth 2.
|
|||
|
// Copyright (c) 2023 MagicaSoft.
|
|||
|
// https://magicasoft.jp
|
|||
|
using System;
|
|||
|
using System.Runtime.CompilerServices;
|
|||
|
|
|||
|
namespace MagicaCloth2
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 頂点の属性
|
|||
|
/// </summary>
|
|||
|
[System.Serializable]
|
|||
|
public struct VertexAttribute : IEquatable<VertexAttribute>
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// ビットフラグ
|
|||
|
/// </summary>
|
|||
|
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);
|
|||
|
|
|||
|
//=========================================================================================
|
|||
|
/// <summary>
|
|||
|
/// 属性値(ビットフラグ)
|
|||
|
/// </summary>
|
|||
|
public byte Value;
|
|||
|
|
|||
|
//=========================================================================================
|
|||
|
public VertexAttribute(byte initialValue = 0)
|
|||
|
{
|
|||
|
Value = initialValue;
|
|||
|
}
|
|||
|
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public void Clear()
|
|||
|
{
|
|||
|
Value = 0;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// フラグ設定
|
|||
|
/// </summary>
|
|||
|
/// <param name="flag"></param>
|
|||
|
/// <param name="sw"></param>
|
|||
|
[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);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// フラグ判定
|
|||
|
/// </summary>
|
|||
|
/// <param name="flag"></param>
|
|||
|
/// <returns></returns>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsSet(byte flag)
|
|||
|
{
|
|||
|
return (Value & flag) != 0;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 無効属性判定(Move/Fixed/Ignoreのどれでもない場合)
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsInvalid() => IsSet(Flag_Fixed | Flag_Move) == false;
|
|||
|
//public bool IsInvalid() => IsSet(Flag_Fixed | Flag_Move | Flag_Ignore) == false;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 固定属性判定
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsFixed() => IsSet(Flag_Fixed);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 移動属性判定
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsMove() => IsSet(Flag_Move);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 移動しないパーティクルか判定する
|
|||
|
/// これは固定属性以外にも掴まれたことにより動かなくなったパーティクルも含まれる
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsDontMove() => !IsSet(Flag_Move);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 無視属性判定
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
//public bool IsIgnore() => IsSet(Flag_Ignore);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// モーション制約の有効判定
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsMotion() => IsSet(Flag_InvalidMotion) == false;
|
|||
|
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
public bool IsDisableCollision() => IsSet(Flag_DisableCollision);
|
|||
|
|
|||
|
//=========================================================================================
|
|||
|
/// <summary>
|
|||
|
/// 2つの頂点属性を結合して新しい属性を返す
|
|||
|
/// 基本的に属性値が低い方が優先される(無効(0)>固定(1)>移動(2))
|
|||
|
/// </summary>
|
|||
|
/// <param name="attr1"></param>
|
|||
|
/// <param name="attr2"></param>
|
|||
|
/// <returns></returns>
|
|||
|
[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; }
|
|||
|
}
|
|||
|
}
|