// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using System.Collections.Generic; using Unity.Mathematics; using UnityEngine; namespace MagicaCloth { /// /// 各オブジェクトのデータハッシュ取得拡張 /// データハッシュはGetHashCode()と違い、参照型でも値が不変となりデータ内容の比較に利用できます /// ・値型はそのままGetHashCode()を返す方式で問題ありません /// ・参照型で自分で定義したクラス/構造体は IDataHash インターフェースを継承し、int GetDataHash() を定義する必要があります /// ・参照型でシステムクラスの場合は、ここに拡張メソッドを定義してGetDataHash()を返す必要があります /// public static class DataHashExtensions { public const int NullHash = 397610387; public const int NumberHash = 932781045; /// /// すべてのObjectにGetDataHash()を定義 /// デフォルトではGetHashCode()を返す /// /// /// public static int GetDataHash(this System.Object data) { var unityObj = data as UnityEngine.Object; if (!object.ReferenceEquals(unityObj, null)) { if (unityObj != null) { if (unityObj is Transform) return (unityObj as Transform).name.GetHashCode(); else if (unityObj is GameObject) return (unityObj as GameObject).name.GetHashCode(); else if (unityObj is Mesh) { // 頂点リストとトライアングルリストを調べる var mesh = unityObj as Mesh; int hash = 0; hash += mesh.vertexCount.GetDataHash(); // 頂点数のみでよい hash += mesh.triangles.Length.GetDataHash(); // トライアングル数のみでよい hash += mesh.subMeshCount.GetDataHash(); hash += mesh.isReadable.GetDataHash(); return hash; } else return NumberHash + data.GetHashCode(); } else return NullHash; } else { if (data != null) return NumberHash + data.GetHashCode(); else return NullHash; } } public static int GetDataHash(this IDataHash data) { return data.GetDataHash(); } //========================================================================================= /// /// ネイティブ配列からデータハッシュ値を求めて返す /// 自分で定義したクラス/構造体は IDataHash インターフェースを継承し、int GetDataHash() を定義する必要があります /// /// /// /// public static int GetDataHash(this T[] data) { int hash = 0; if (data != null) foreach (var d in data) { hash = hash * 31; IDataHash dh = d as IDataHash; if (dh != null) hash += dh.GetDataHash(); else hash += d.GetDataHash(); } return hash; } /// /// リストからデータハッシュ値を求めて返す /// 自分で定義したクラス/構造体は IDataHash インターフェースを継承し、int GetDataHash() を定義する必要があります /// /// /// /// public static int GetDataHash(this List data) { int hash = 0; if (data != null) foreach (var d in data) { hash = hash * 31; IDataHash dh = d as IDataHash; if (dh != null) hash += dh.GetDataHash(); else hash += d.GetDataHash(); } return hash; } /// /// ネイティブ配列から配列数のデータハッシュを求めて返す /// /// /// /// public static int GetDataCountHash(this T[] data) { return data != null ? data.Length.GetDataHash() : NullHash; } /// /// リストからリスト数のデータハッシュを求めて返す /// /// /// /// public static int GetDataCountHash(this List data) { return data != null ? data.Count.GetDataHash() : NullHash; } /// /// Vector3のデータハッシュを求めて返す /// /// /// public static ulong GetVectorDataHash(Vector3 v) { var u = math.asuint(v); ulong x = u.x; ulong y = u.y; ulong z = u.z; x += 0x68DF0763u; y += 0x5A394F9Fu; z += 0xE094B323u; x = x ^ (x << 13); y = y ^ (y >> 17); z = z ^ (z << 15); x *= 0x9B13B92Du; y *= 0x4ABF0813u; z *= 0x86068063u; return x + y + z + 0xD75513F9u; } } }