SelectionData.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. namespace MagicaCloth
  7. {
  8. /// <summary>
  9. /// クロス選択データ
  10. /// </summary>
  11. [System.Serializable]
  12. public class SelectionData : ShareDataObject
  13. {
  14. /// <summary>
  15. /// データバージョン
  16. /// </summary>
  17. private const int DATA_VERSION = 2;
  18. /// <summary>
  19. /// 頂点選択データタイプ
  20. /// </summary>
  21. public const int Invalid = 0;
  22. public const int Move = 1;
  23. public const int Fixed = 2;
  24. public const int Extend = 3; // 固定としてマークするがローテーションライン計算からは除外する
  25. /// <summary>
  26. /// レンダーデフォーマーごとの選択データ
  27. /// </summary>
  28. [System.Serializable]
  29. public class DeformerSelection : IDataHash
  30. {
  31. /// <summary>
  32. /// レンダーデフォーマーの頂点と1対1に対応
  33. /// </summary>
  34. public List<int> selectData = new List<int>();
  35. /// <summary>
  36. /// 頂点ハッシュリスト(オプション)
  37. /// </summary>
  38. public List<ulong> vertexHashList = new List<ulong>();
  39. public int GetDataHash()
  40. {
  41. return selectData.GetDataHash();
  42. }
  43. public bool Compare(DeformerSelection data)
  44. {
  45. if (selectData.Count != data.selectData.Count)
  46. return false;
  47. for (int i = 0; i < selectData.Count; i++)
  48. {
  49. if (selectData[i] != data.selectData[i])
  50. return false;
  51. }
  52. if (vertexHashList.Count != data.vertexHashList.Count)
  53. return false;
  54. for (int i = 0; i < vertexHashList.Count; i++)
  55. {
  56. if (vertexHashList[i] != data.vertexHashList[i])
  57. return false;
  58. }
  59. return true;
  60. }
  61. }
  62. public List<DeformerSelection> selectionList = new List<DeformerSelection>();
  63. //=========================================================================================
  64. public int DeformerCount
  65. {
  66. get
  67. {
  68. return selectionList.Count;
  69. }
  70. }
  71. //=========================================================================================
  72. /// <summary>
  73. /// データハッシュ計算
  74. /// </summary>
  75. /// <returns></returns>
  76. public override int GetDataHash()
  77. {
  78. int hash = 0;
  79. hash += selectionList.GetDataHash();
  80. return hash;
  81. }
  82. //=========================================================================================
  83. public override int GetVersion()
  84. {
  85. return DATA_VERSION;
  86. }
  87. /// <summary>
  88. /// 現在のデータが正常(実行できる状態)か返す
  89. /// </summary>
  90. /// <returns></returns>
  91. public override Define.Error VerifyData()
  92. {
  93. if (dataHash == 0)
  94. return Define.Error.InvalidDataHash;
  95. //if (dataVersion != GetVersion())
  96. // return Define.Error.DataVersionMismatch;
  97. if (selectionList.Count == 0)
  98. return Define.Error.SelectionCountZero;
  99. return Define.Error.None;
  100. }
  101. //=========================================================================================
  102. /// <summary>
  103. /// 引数の選択データの内容を比較する
  104. /// </summary>
  105. /// <param name="sel"></param>
  106. /// <returns></returns>
  107. public bool Compare(SelectionData sel)
  108. {
  109. if (selectionList.Count != sel.selectionList.Count)
  110. return false;
  111. for (int i = 0; i < selectionList.Count; i++)
  112. {
  113. if (selectionList[i].Compare(sel.selectionList[i]) == false)
  114. return false;
  115. }
  116. return true;
  117. }
  118. /// <summary>
  119. /// メッシュデータの各頂点の選択情報を取得する
  120. /// </summary>
  121. /// <param name="meshData"></param>
  122. /// <returns></returns>
  123. public List<int> GetSelectionData(MeshData meshData, List<MeshData> childMeshDataList)
  124. {
  125. List<int> selects = new List<int>();
  126. if (meshData != null)
  127. {
  128. // 親頂点に影響する子頂点情報
  129. Dictionary<int, List<uint>> dict = meshData.GetVirtualToChildVertexDict();
  130. // 現在の選択データの頂点ハッシュ辞書リスト
  131. var hashList = GetSelectionVertexHashList();
  132. int vcnt = meshData.VertexCount;
  133. for (int i = 0; i < vcnt; i++)
  134. {
  135. int data = GetSelection(meshData, i, dict, childMeshDataList, hashList);
  136. selects.Add(data);
  137. }
  138. }
  139. else
  140. {
  141. // そのまま
  142. if (selectionList.Count > 0)
  143. {
  144. selects = new List<int>(selectionList[0].selectData);
  145. }
  146. }
  147. return selects;
  148. }
  149. /// <summary>
  150. /// メッシュデータの指定インデクスの選択情報を取得する
  151. /// </summary>
  152. /// <param name="meshData"></param>
  153. /// <param name="vindex"></param>
  154. /// <returns></returns>
  155. private int GetSelection(MeshData meshData, int vindex, Dictionary<int, List<uint>> dict, List<MeshData> childMeshDataList, List<Dictionary<ulong, int>> hashList)
  156. {
  157. int data = Invalid;
  158. // セレクションデータ読み込み
  159. if (meshData != null && meshData.ChildCount > 0)
  160. {
  161. // 親頂点に影響する子頂点情報から取得
  162. if (dict.ContainsKey(vindex))
  163. {
  164. foreach (var pack in dict[vindex])
  165. {
  166. int cmindex = DataUtility.Unpack16Hi(pack);
  167. int cvindex = DataUtility.Unpack16Low(pack);
  168. if (cmindex < selectionList.Count && cvindex < selectionList[cmindex].selectData.Count)
  169. {
  170. // 頂点ハッシュがある場合はハッシュからインデックスを取得する
  171. // 現在メッシュの頂点ハッシュ
  172. ulong vhash = 0;
  173. if (childMeshDataList != null && cmindex < childMeshDataList.Count)
  174. {
  175. var cmdata = childMeshDataList[cmindex];
  176. if (cmdata != null && cvindex < cmdata.VertexHashCount)
  177. {
  178. vhash = cmdata.vertexHashList[cvindex];
  179. }
  180. }
  181. // セレクションデータに頂点ハッシュが記録されているならば照合する
  182. if (vhash != 0 && cmindex < hashList.Count)
  183. {
  184. if (hashList[cmindex].ContainsKey(vhash))
  185. {
  186. // ハッシュ値に紐づく頂点ペイントデータに入れ替える
  187. cvindex = hashList[cmindex][vhash];
  188. }
  189. }
  190. data = Mathf.Max(selectionList[cmindex].selectData[cvindex], data);
  191. }
  192. }
  193. }
  194. }
  195. else
  196. {
  197. // そのまま
  198. int dindex = 0;
  199. if (dindex < selectionList.Count)
  200. {
  201. if (vindex < selectionList[dindex].selectData.Count)
  202. data = selectionList[dindex].selectData[vindex];
  203. }
  204. }
  205. return data;
  206. }
  207. /// <summary>
  208. /// メッシュ頂点の選択データを設定する
  209. /// </summary>
  210. /// <param name="meshData"></param>
  211. /// <param name="selects"></param>
  212. public void SetSelectionData(MeshData meshData, List<int> selects, List<MeshData> childMeshDataList)
  213. {
  214. // 選択データ初期化
  215. selectionList.Clear();
  216. if (meshData != null && meshData.ChildCount > 0)
  217. {
  218. for (int i = 0; i < meshData.ChildCount; i++)
  219. {
  220. var dsel = new DeformerSelection();
  221. int cvcnt = meshData.childDataList[i].VertexCount;
  222. for (int j = 0; j < cvcnt; j++)
  223. {
  224. dsel.selectData.Add(Invalid);
  225. dsel.vertexHashList.Add(0); // ハッシュ0=無効
  226. }
  227. selectionList.Add(dsel);
  228. }
  229. }
  230. else
  231. {
  232. // そのまま
  233. var dsel = new DeformerSelection();
  234. int cvcnt = selects.Count;
  235. for (int j = 0; j < cvcnt; j++)
  236. {
  237. dsel.selectData.Add(Invalid);
  238. dsel.vertexHashList.Add(0); // ハッシュ0=無効
  239. }
  240. selectionList.Add(dsel);
  241. }
  242. // 選択データに追加
  243. for (int i = 0; i < selects.Count; i++)
  244. {
  245. int data = selects[i];
  246. if (meshData != null && meshData.ChildCount > 0)
  247. {
  248. // 親頂点に影響する子頂点情報
  249. Dictionary<int, List<uint>> dict = meshData.GetVirtualToChildVertexDict();
  250. // 親頂点に影響する子頂点に記録
  251. if (dict.ContainsKey(i))
  252. {
  253. foreach (var pack in dict[i])
  254. {
  255. int cmindex = DataUtility.Unpack16Hi(pack);
  256. int cvindex = DataUtility.Unpack16Low(pack);
  257. selectionList[cmindex].selectData[cvindex] = data;
  258. // 頂点ハッシュも記録
  259. if (cmindex < childMeshDataList.Count)
  260. {
  261. var cmdata = childMeshDataList[cmindex];
  262. if (cmdata != null && cvindex < cmdata.VertexHashCount)
  263. {
  264. selectionList[cmindex].vertexHashList[cvindex] = cmdata.vertexHashList[cvindex];
  265. }
  266. }
  267. }
  268. }
  269. }
  270. else
  271. {
  272. // そのまま
  273. selectionList[0].selectData[i] = data;
  274. }
  275. }
  276. // データハッシュ設定
  277. CreateVerifyData();
  278. }
  279. /// <summary>
  280. /// セレクションデータに格納されている子メッシュの頂点ハッシュを辞書にして返す
  281. /// </summary>
  282. /// <param name="childMeshDataList"></param>
  283. /// <returns></returns>
  284. private List<Dictionary<ulong, int>> GetSelectionVertexHashList()
  285. {
  286. var hashList = new List<Dictionary<ulong, int>>();
  287. foreach (var sel in selectionList)
  288. {
  289. Dictionary<ulong, int> hashDict = new Dictionary<ulong, int>();
  290. for (int i = 0; i < sel.vertexHashList.Count; i++)
  291. {
  292. hashDict[sel.vertexHashList[i]] = i;
  293. }
  294. hashList.Add(hashDict);
  295. }
  296. return hashList;
  297. }
  298. }
  299. }