MagicaAvatarRuntime.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. public class MagicaAvatarRuntime : MagicaAvatarAccess
  12. {
  13. /// <summary>
  14. /// このアバターが保持するボーン辞書
  15. /// </summary>
  16. private Dictionary<string, Transform> boneDict = new Dictionary<string, Transform>();
  17. /// <summary>
  18. /// このアバターが保持するボーンの参照数
  19. /// </summary>
  20. private Dictionary<Transform, int> boneReferenceDict = new Dictionary<Transform, int>();
  21. /// <summary>
  22. /// アバターパーツリスト
  23. /// </summary>
  24. private List<MagicaAvatarParts> avatarPartsList = new List<MagicaAvatarParts>();
  25. /// <summary>
  26. /// このアバターが保持するコライダーリスト
  27. /// </summary>
  28. /// <typeparam name="ColliderComponent"></typeparam>
  29. /// <returns></returns>
  30. private List<ColliderComponent> colliderList = new List<ColliderComponent>();
  31. //=========================================================================================
  32. /// <summary>
  33. /// 初期設定
  34. /// </summary>
  35. public override void Create()
  36. {
  37. CreateBoneDict();
  38. CreateColliderList();
  39. }
  40. /// <summary>
  41. /// 破棄
  42. /// </summary>
  43. public override void Dispose()
  44. {
  45. }
  46. /// <summary>
  47. /// 有効化
  48. /// </summary>
  49. public override void Active()
  50. {
  51. }
  52. /// <summary>
  53. /// 無効化
  54. /// </summary>
  55. public override void Inactive()
  56. {
  57. }
  58. //=========================================================================================
  59. public int AvatarPartsCount
  60. {
  61. get
  62. {
  63. return avatarPartsList.Count;
  64. }
  65. }
  66. public MagicaAvatarParts GetAvatarParts(int index)
  67. {
  68. return avatarPartsList[index];
  69. }
  70. //=========================================================================================
  71. /// <summary>
  72. /// すべてのボーンを辞書に登録する
  73. /// この時にボーン名に重複があると着せ替えのときに問題を起こす可能性がある
  74. /// </summary>
  75. private void CreateBoneDict()
  76. {
  77. var tlist = owner.GetComponentsInChildren<Transform>();
  78. foreach (var t in tlist)
  79. {
  80. if (boneDict.ContainsKey(t.name))
  81. {
  82. // Duplication name!
  83. Debug.LogWarning(string.Format("{0} [{1}]", Define.GetErrorMessage(Define.Error.OverlappingTransform), t.name));
  84. }
  85. else
  86. {
  87. boneDict.Add(t.name, t);
  88. boneReferenceDict.Add(t, 1); // 参照数1で初期化
  89. }
  90. }
  91. }
  92. /// <summary>
  93. /// アバターが保持するコライダーをリスト化する
  94. /// </summary>
  95. private void CreateColliderList()
  96. {
  97. var clist = owner.GetComponentsInChildren<ColliderComponent>();
  98. if (clist != null && clist.Length > 0)
  99. {
  100. colliderList.AddRange(clist);
  101. }
  102. }
  103. /// <summary>
  104. /// 現在アバターが保有するコライダー数を取得する
  105. /// </summary>
  106. /// <returns></returns>
  107. public int GetColliderCount()
  108. {
  109. if (Application.isPlaying)
  110. {
  111. return colliderList.Count;
  112. }
  113. else
  114. {
  115. return owner.GetComponentsInChildren<ColliderComponent>().Length;
  116. }
  117. }
  118. //=========================================================================================
  119. /// <summary>
  120. /// ゲームオブジェクト名が重複するトランスフォームのリストを返す
  121. /// </summary>
  122. /// <returns></returns>
  123. public List<Transform> CheckOverlappingTransform()
  124. {
  125. var boneHash = new HashSet<string>();
  126. var overlapList = new List<Transform>();
  127. var tlist = owner.GetComponentsInChildren<Transform>();
  128. var root = owner.transform;
  129. foreach (var t in tlist)
  130. {
  131. if (t == root)
  132. continue;
  133. if (boneHash.Contains(t.name))
  134. {
  135. overlapList.Add(t);
  136. }
  137. else
  138. {
  139. boneHash.Add(t.name);
  140. }
  141. }
  142. return overlapList;
  143. }
  144. //=========================================================================================
  145. /// <summary>
  146. /// アバターパーツの追加
  147. /// </summary>
  148. /// <param name="parts"></param>
  149. public int AddAvatarParts(MagicaAvatarParts parts)
  150. {
  151. if (parts == null)
  152. return 0;
  153. //Debug.Log("AddAvatarParts:" + parts.name);
  154. // すでに着せ替え済みならば何もしない
  155. if (parts.HasParent)
  156. return parts.PartsId;
  157. // アクティブ化する
  158. if (parts.gameObject.activeSelf == false)
  159. parts.gameObject.SetActive(true);
  160. // 初期化(すでに初期化済みならば何もしない)
  161. owner.Init();
  162. // スキンメッシュレンダラーリスト
  163. var skinRendererList = parts.GetComponentsInChildren<SkinnedMeshRenderer>();
  164. //Debug.Log("skinRendererList:" + skinRendererList.Length);
  165. // Magicaコンポーネントリスト
  166. //var magicaComponentList = parts.GetComponentsInChildren<CoreComponent>();
  167. var magicaComponentList = parts.GetMagicaComponentList();
  168. //Debug.Log("magicaComponentList:" + magicaComponentList.Length);
  169. // パーツを子として追加する
  170. var root = owner.transform;
  171. var croot = parts.transform;
  172. parts.transform.SetParent(root, false);
  173. parts.transform.localPosition = Vector3.zero;
  174. parts.transform.localRotation = Quaternion.identity;
  175. parts.ParentAvatar = owner;
  176. avatarPartsList.Add(parts);
  177. // 必要なボーンを移植する
  178. var partsBoneDict = parts.GetBoneDict();
  179. foreach (var bone in partsBoneDict.Values)
  180. {
  181. if (bone != croot)
  182. AddBone(root, croot, bone);
  183. }
  184. // すべてのボーン参照数を加算する
  185. foreach (var bone in partsBoneDict.Values)
  186. {
  187. if (bone != croot)
  188. {
  189. var t = boneDict[bone.name];
  190. boneReferenceDict[t]++;
  191. //Debug.Log("reference[" + t.name + "]:" + boneReferenceDict[t]);
  192. }
  193. }
  194. // ボーンの交換情報作成
  195. var boneReplaceDict = new Dictionary<Transform, Transform>();
  196. foreach (var bone in partsBoneDict.Values)
  197. {
  198. if (bone != croot)
  199. {
  200. boneReplaceDict.Add(bone, boneDict[bone.name]);
  201. }
  202. else
  203. {
  204. boneReplaceDict.Add(bone, root);
  205. }
  206. }
  207. #if false
  208. foreach (var kv in avatar.Runtime.boneReplaceDict)
  209. {
  210. if (kv.Key != kv.Value)
  211. {
  212. Debug.Log("置換[" + kv.Key.name + "]->[" + kv.Value.name + "]");
  213. }
  214. }
  215. #endif
  216. // スキンメッシュレンダラー置換
  217. foreach (var skinRenderer in skinRendererList)
  218. {
  219. ReplaceSkinMeshRenderer(skinRenderer, boneReplaceDict);
  220. }
  221. // Magicaコンポーネント置換
  222. foreach (var comp in magicaComponentList)
  223. {
  224. ReplaceMagicaComponent(comp, boneReplaceDict);
  225. }
  226. // Magicaコンポーネントに本体のコライダーを追加する
  227. if (colliderList.Count > 0)
  228. {
  229. foreach (var comp in magicaComponentList)
  230. {
  231. var cloth = comp as BaseCloth;
  232. if (cloth && cloth.TeamData.MergeAvatarCollider)
  233. {
  234. // 初期化
  235. cloth.Init();
  236. foreach (var col in colliderList)
  237. {
  238. cloth.AddCollider(col);
  239. }
  240. }
  241. }
  242. }
  243. // パーツの機能は停止させる
  244. parts.gameObject.SetActive(false);
  245. // イベント
  246. owner.OnAttachParts.Invoke(owner, parts);
  247. return parts.PartsId;
  248. }
  249. /// <summary>
  250. /// 指定ボーンを親に追加する
  251. /// </summary>
  252. /// <param name="root"></param>
  253. /// <param name="croot"></param>
  254. /// <param name="bone"></param>
  255. private void AddBone(Transform root, Transform croot, Transform bone)
  256. {
  257. if (boneDict.ContainsKey(bone.name))
  258. {
  259. // すでに登録済み
  260. return;
  261. }
  262. // ボーンを追加する親ボーンを検索する
  263. Transform attachBone = root;
  264. Transform before = bone;
  265. Transform t = bone.parent;
  266. while (t && t != croot)
  267. {
  268. if (boneDict.ContainsKey(t.name))
  269. {
  270. attachBone = boneDict[t.name];
  271. break;
  272. }
  273. before = t;
  274. t = t.parent;
  275. }
  276. // ボーン追加
  277. before.SetParent(attachBone, false);
  278. //Debug.Log("Add attach:" + attachBone.name + " before:" + before.name);
  279. // before以下を辞書に登録する
  280. var blist = before.GetComponentsInChildren<Transform>();
  281. foreach (var b in blist)
  282. {
  283. if (boneDict.ContainsKey(b.name))
  284. {
  285. // Duplication name!
  286. Debug.LogWarning(string.Format("{0} [{1}]", Define.GetErrorMessage(Define.Error.AddOverlappingTransform), b.name));
  287. }
  288. else
  289. {
  290. boneDict.Add(b.name, b);
  291. boneReferenceDict.Add(b, 0); // まず参照数0で初期化
  292. }
  293. }
  294. }
  295. /// <summary>
  296. /// スキンメッシュレンダラーのボーン置換
  297. /// </summary>
  298. /// <param name="skinRenderer"></param>
  299. private void ReplaceSkinMeshRenderer(SkinnedMeshRenderer skinRenderer, Dictionary<Transform, Transform> boneReplaceDict)
  300. {
  301. // ルートボーン置換
  302. skinRenderer.rootBone = MeshUtility.GetReplaceBone(skinRenderer.rootBone, boneReplaceDict);
  303. // ボーン置換
  304. var bones = skinRenderer.bones;
  305. for (int i = 0; i < bones.Length; i++)
  306. {
  307. bones[i] = MeshUtility.GetReplaceBone(bones[i], boneReplaceDict);
  308. }
  309. skinRenderer.bones = bones;
  310. }
  311. /// <summary>
  312. /// Magicaコンポーネントの置換
  313. /// </summary>
  314. /// <param name="comp"></param>
  315. private void ReplaceMagicaComponent(CoreComponent comp, Dictionary<Transform, Transform> boneReplaceDict)
  316. {
  317. comp.ChangeAvatar(boneReplaceDict);
  318. }
  319. /// <summary>
  320. /// アバターパーツの削除
  321. /// </summary>
  322. /// <param name="parts"></param>
  323. public void RemoveAvatarParts(MagicaAvatarParts parts)
  324. {
  325. //Debug.Log("RemoveAvatarParts:" + parts.name);
  326. if (parts == null)
  327. return;
  328. if (avatarPartsList.Contains(parts) == false)
  329. return;
  330. // 接続を切る
  331. parts.ParentAvatar = null;
  332. avatarPartsList.Remove(parts);
  333. // 参照数を1つ減らし削除するボーンをリスト化する
  334. var removeBoneList = new List<Transform>();
  335. var croot = parts.transform;
  336. foreach (var bone in parts.GetBoneDict().Values)
  337. {
  338. if (bone == null)
  339. continue;
  340. if (bone != croot)
  341. {
  342. var t = boneDict[bone.name];
  343. boneReferenceDict[t]--;
  344. if (boneReferenceDict[t] == 0)
  345. {
  346. boneReferenceDict.Remove(t);
  347. boneDict.Remove(t.name);
  348. removeBoneList.Add(t);
  349. }
  350. //Debug.Log("reference[" + t.name + "]:" + boneReferenceDict[t]);
  351. }
  352. }
  353. // ボーン削除
  354. foreach (var bone in removeBoneList)
  355. {
  356. if (bone)
  357. {
  358. GameObject.Destroy(bone.gameObject);
  359. }
  360. }
  361. #if false
  362. foreach (var bone in boneDict.Values)
  363. {
  364. if (bone)
  365. Debug.Log("残 bone:" + bone.name);
  366. }
  367. foreach (var kv in boneReferenceDict)
  368. {
  369. if (kv.Key)
  370. Debug.Log("残 reference[" + kv.Key.name + "]:" + kv.Value);
  371. }
  372. #endif
  373. // 本体コライダーを削除する
  374. if (colliderList.Count > 0)
  375. {
  376. // Magicaコンポーネントリスト
  377. var magicaComponentList = parts.GetMagicaComponentList();
  378. foreach (var comp in magicaComponentList)
  379. {
  380. var cloth = comp as BaseCloth;
  381. if (cloth)
  382. {
  383. foreach (var col in colliderList)
  384. {
  385. cloth.RemoveCollider(col);
  386. }
  387. }
  388. }
  389. }
  390. // パーツ削除
  391. GameObject.Destroy(parts.gameObject);
  392. // イベント
  393. owner.OnDetachParts.Invoke(owner);
  394. }
  395. /// <summary>
  396. /// アバターパーツの削除(パーツID)
  397. /// </summary>
  398. /// <param name="partsId"></param>
  399. public void RemoveAvatarParts(int partsId)
  400. {
  401. var parts = avatarPartsList.Find((p) => p.PartsId == partsId);
  402. RemoveAvatarParts(parts);
  403. }
  404. }
  405. }