DataHashExtensions.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using Unity.Mathematics;
  6. using UnityEngine;
  7. namespace MagicaCloth
  8. {
  9. /// <summary>
  10. /// 各オブジェクトのデータハッシュ取得拡張
  11. /// データハッシュはGetHashCode()と違い、参照型でも値が不変となりデータ内容の比較に利用できます
  12. /// ・値型はそのままGetHashCode()を返す方式で問題ありません
  13. /// ・参照型で自分で定義したクラス/構造体は IDataHash インターフェースを継承し、int GetDataHash() を定義する必要があります
  14. /// ・参照型でシステムクラスの場合は、ここに拡張メソッドを定義してGetDataHash()を返す必要があります
  15. /// </summary>
  16. public static class DataHashExtensions
  17. {
  18. public const int NullHash = 397610387;
  19. public const int NumberHash = 932781045;
  20. /// <summary>
  21. /// すべてのObjectにGetDataHash()を定義
  22. /// デフォルトではGetHashCode()を返す
  23. /// </summary>
  24. /// <param name="data"></param>
  25. /// <returns></returns>
  26. public static int GetDataHash(this System.Object data)
  27. {
  28. var unityObj = data as UnityEngine.Object;
  29. if (!object.ReferenceEquals(unityObj, null))
  30. {
  31. if (unityObj != null)
  32. {
  33. if (unityObj is Transform)
  34. return (unityObj as Transform).name.GetHashCode();
  35. else if (unityObj is GameObject)
  36. return (unityObj as GameObject).name.GetHashCode();
  37. else if (unityObj is Mesh)
  38. {
  39. // 頂点リストとトライアングルリストを調べる
  40. var mesh = unityObj as Mesh;
  41. int hash = 0;
  42. hash += mesh.vertexCount.GetDataHash(); // 頂点数のみでよい
  43. hash += mesh.triangles.Length.GetDataHash(); // トライアングル数のみでよい
  44. hash += mesh.subMeshCount.GetDataHash();
  45. hash += mesh.isReadable.GetDataHash();
  46. return hash;
  47. }
  48. else
  49. return NumberHash + data.GetHashCode();
  50. }
  51. else
  52. return NullHash;
  53. }
  54. else
  55. {
  56. if (data != null)
  57. return NumberHash + data.GetHashCode();
  58. else
  59. return NullHash;
  60. }
  61. }
  62. public static int GetDataHash(this IDataHash data)
  63. {
  64. return data.GetDataHash();
  65. }
  66. //=========================================================================================
  67. /// <summary>
  68. /// ネイティブ配列からデータハッシュ値を求めて返す
  69. /// 自分で定義したクラス/構造体は IDataHash インターフェースを継承し、int GetDataHash() を定義する必要があります
  70. /// </summary>
  71. /// <typeparam name="T"></typeparam>
  72. /// <param name="data"></param>
  73. /// <returns></returns>
  74. public static int GetDataHash<T>(this T[] data)
  75. {
  76. int hash = 0;
  77. if (data != null)
  78. foreach (var d in data)
  79. {
  80. hash = hash * 31;
  81. IDataHash dh = d as IDataHash;
  82. if (dh != null)
  83. hash += dh.GetDataHash();
  84. else
  85. hash += d.GetDataHash();
  86. }
  87. return hash;
  88. }
  89. /// <summary>
  90. /// リストからデータハッシュ値を求めて返す
  91. /// 自分で定義したクラス/構造体は IDataHash インターフェースを継承し、int GetDataHash() を定義する必要があります
  92. /// </summary>
  93. /// <typeparam name="T"></typeparam>
  94. /// <param name="data"></param>
  95. /// <returns></returns>
  96. public static int GetDataHash<T>(this List<T> data)
  97. {
  98. int hash = 0;
  99. if (data != null)
  100. foreach (var d in data)
  101. {
  102. hash = hash * 31;
  103. IDataHash dh = d as IDataHash;
  104. if (dh != null)
  105. hash += dh.GetDataHash();
  106. else
  107. hash += d.GetDataHash();
  108. }
  109. return hash;
  110. }
  111. /// <summary>
  112. /// ネイティブ配列から配列数のデータハッシュを求めて返す
  113. /// </summary>
  114. /// <typeparam name="T"></typeparam>
  115. /// <param name="data"></param>
  116. /// <returns></returns>
  117. public static int GetDataCountHash<T>(this T[] data)
  118. {
  119. return data != null ? data.Length.GetDataHash() : NullHash;
  120. }
  121. /// <summary>
  122. /// リストからリスト数のデータハッシュを求めて返す
  123. /// </summary>
  124. /// <typeparam name="T"></typeparam>
  125. /// <param name="data"></param>
  126. /// <returns></returns>
  127. public static int GetDataCountHash<T>(this List<T> data)
  128. {
  129. return data != null ? data.Count.GetDataHash() : NullHash;
  130. }
  131. /// <summary>
  132. /// Vector3のデータハッシュを求めて返す
  133. /// </summary>
  134. /// <param name="v"></param>
  135. /// <returns></returns>
  136. public static ulong GetVectorDataHash(Vector3 v)
  137. {
  138. var u = math.asuint(v);
  139. ulong x = u.x;
  140. ulong y = u.y;
  141. ulong z = u.z;
  142. x += 0x68DF0763u;
  143. y += 0x5A394F9Fu;
  144. z += 0xE094B323u;
  145. x = x ^ (x << 13);
  146. y = y ^ (y >> 17);
  147. z = z ^ (z << 15);
  148. x *= 0x9B13B92Du;
  149. y *= 0x4ABF0813u;
  150. z *= 0x86068063u;
  151. return x + y + z + 0xD75513F9u;
  152. }
  153. }
  154. }