MoveItemManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Sirenix.OdinInspector;
  5. using System;
  6. using UnityEngine.UI;
  7. using System.IO;
  8. using System.Linq;
  9. using QFramework;
  10. using System.Reflection;
  11. public class MoveItemManager : MonoBehaviour
  12. {
  13. public static MoveItemManager instance;
  14. [TabGroup("配置相关")]
  15. [LabelText("设备名称")]
  16. [ValidateInput("IsValid")]
  17. public string deviceName;
  18. private bool IsValid(string value)
  19. {
  20. return !string.IsNullOrEmpty(value);
  21. }
  22. [TabGroup("配置相关")]
  23. [TableList]
  24. public List<MoveItemInfo> moveItemInfos;
  25. /// <summary>
  26. /// 使用音频控制结束
  27. /// </summary>
  28. bool useAudioCtrl;
  29. public ModelItem m_CurrentSelectModelItem;
  30. private void Awake()
  31. {
  32. instance = this;
  33. UIKit.OpenPanel<AutoDisassemblyPanel>();
  34. }
  35. public void Update()
  36. {
  37. Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  38. RaycastHit hit;
  39. if (Physics.Raycast(ray, out hit))
  40. {
  41. ModelItem modelItem = GetParentPartMarkWithModelItem(hit.collider.transform);
  42. if (m_CurrentSelectModelItem != modelItem)
  43. {
  44. if (m_CurrentSelectModelItem != null)
  45. {
  46. m_CurrentSelectModelItem.CloseHighlighter();
  47. }
  48. m_CurrentSelectModelItem = modelItem;
  49. m_CurrentSelectModelItem.OpenHighlighter();
  50. }
  51. // 处理射线击中的对象
  52. if (modelItem != null)
  53. {
  54. UIKit.GetPanel<AutoDisassemblyPanel>().SetSubTitleText(modelItem.name);
  55. }
  56. }
  57. else
  58. {
  59. if (m_CurrentSelectModelItem != null)
  60. {
  61. m_CurrentSelectModelItem.CloseHighlighter();
  62. m_CurrentSelectModelItem = null;
  63. UIKit.GetPanel<AutoDisassemblyPanel>().SetSubTitleText("");
  64. }
  65. }
  66. }
  67. /// <summary>
  68. /// 查找携带PartMark的节点
  69. /// </summary>
  70. /// <param name="traget"></param>
  71. /// <returns></returns>
  72. private ModelItem GetParentPartMarkWithModelItem(Transform traget)
  73. {
  74. ModelItem tmpMark = traget.GetComponent<ModelItem>();
  75. if (tmpMark == null && traget.parent != null)
  76. {
  77. tmpMark = GetParentPartMarkWithModelItem(traget.parent);
  78. }
  79. return tmpMark;
  80. }
  81. /// <summary>
  82. /// 正向播放
  83. /// </summary>
  84. public void PlayPlayMoveItem()
  85. {
  86. StopAllCoroutines();
  87. SetInitState();
  88. PlayMoveItemByIndex();
  89. }
  90. /// <summary>
  91. /// 反向播放
  92. /// </summary>
  93. public void PlayMoveItemByReverse()
  94. {
  95. StopAllCoroutines();
  96. SetFinalState();
  97. PlayMoveItemByReverseIndex(moveItemInfos.Count - 1);
  98. }
  99. /// <summary>
  100. /// 正向播放
  101. /// </summary>
  102. /// <param name="index"></param>
  103. private void PlayMoveItemByIndex(int index = 0)
  104. {
  105. StopAllCoroutines();
  106. Debug.Log("播放" + moveItemInfos[index].moveItem.name);
  107. UIKit.GetPanel<AutoDisassemblyPanel>().SetSubTitleText(moveItemInfos[index].moveItem.name);
  108. StartCoroutine(AudioHelper.LoadSpecifiedAudioFile("Config/Audios/内部结构拆解/" + deviceName, moveItemInfos[index].moveItem.name,
  109. len =>
  110. {
  111. if (len > moveItemInfos[index].moveItem.m_Duration)
  112. {
  113. Debug.Log("音频长");
  114. useAudioCtrl = true;
  115. }
  116. else
  117. {
  118. Debug.Log("动画长");
  119. useAudioCtrl = false;
  120. }
  121. },
  122. () =>
  123. {
  124. if (useAudioCtrl)
  125. {
  126. Debug.Log("音频回调");
  127. OnPlayMoveItemByIndexCallBack(index);
  128. }
  129. }));
  130. StartCoroutine(MovePathByItem(moveItemInfos[index], false,
  131. () =>
  132. {
  133. if (!useAudioCtrl)
  134. {
  135. Debug.Log("动画回调");
  136. OnPlayMoveItemByIndexCallBack(index);
  137. }
  138. }));
  139. }
  140. /// <summary>
  141. /// 正向播放完成一条回调
  142. /// </summary>
  143. /// <param name="index"></param>
  144. private void OnPlayMoveItemByIndexCallBack(int index)
  145. {
  146. moveItemInfos[index].moveItem.gameObject.SetActive(false);
  147. moveItemInfos[index].modelItem.gameObject.SetActive(true);
  148. moveItemInfos[index].finish = true;
  149. if (index + 1 > moveItemInfos.Count - 1)
  150. {
  151. Debug.Log("正播播放序列完成");
  152. //UIKit.ClosePanel<AutoDisassemblyPanel>();
  153. //if (m_Reverse)
  154. //{
  155. // PlayMoveItemByReverseIndex(moveItemInfos.Count - 1);
  156. //}
  157. }
  158. else
  159. {
  160. PlayMoveItemByIndex(index + 1);
  161. }
  162. }
  163. /// <summary>
  164. /// 反向播放
  165. /// </summary>
  166. /// <param name="index"></param>
  167. private void PlayMoveItemByReverseIndex(int index)
  168. {
  169. StopAllCoroutines();
  170. Debug.Log("反向播放" + moveItemInfos[index].moveItem.name);
  171. UIKit.GetPanel<AutoDisassemblyPanel>().SetSubTitleText(moveItemInfos[index].moveItem.name);
  172. StartCoroutine(AudioHelper.LoadSpecifiedAudioFile("Config/Audios/内部结构拆解/" + deviceName, moveItemInfos[index].moveItem.name, len =>
  173. {
  174. if (len > moveItemInfos[index].moveItem.m_Duration)
  175. {
  176. Debug.Log("音频长");
  177. useAudioCtrl = true;
  178. }
  179. else
  180. {
  181. Debug.Log("动画长");
  182. useAudioCtrl = false;
  183. }
  184. },
  185. () =>
  186. {
  187. if (useAudioCtrl)
  188. {
  189. Debug.Log("音频回调");
  190. OnPlayMoveItemByReverseIndexCallBack(index);
  191. }
  192. }));
  193. StartCoroutine(MovePathByItem(moveItemInfos[index], true,
  194. () =>
  195. {
  196. if (!useAudioCtrl)
  197. {
  198. Debug.Log("动画回调");
  199. OnPlayMoveItemByReverseIndexCallBack(index);
  200. }
  201. }));
  202. }
  203. /// <summary>
  204. /// 反向播放完成一条回调
  205. /// </summary>
  206. /// <param name="index"></param>
  207. private void OnPlayMoveItemByReverseIndexCallBack(int index)
  208. {
  209. moveItemInfos[index].finish = false;
  210. if (index - 1 < 0)
  211. {
  212. Debug.Log("反向播放序列完成");
  213. //UIKit.ClosePanel<AutoDisassemblyPanel>();
  214. }
  215. else
  216. {
  217. PlayMoveItemByReverseIndex(index - 1);
  218. }
  219. }
  220. IEnumerator MovePathByItem(MoveItemInfo moveItemInfo, bool isReverse, Action finishedCallBack = null)
  221. {
  222. float timer = 0;
  223. float lerp = 0;
  224. while (timer < moveItemInfo.moveItem.m_Duration)
  225. {
  226. MoveItem moveItem = moveItemInfo.moveItem;
  227. moveItem.gameObject.SetActive(true);
  228. moveItem.OpenHighter(true);
  229. lerp = isReverse ? (1 - timer / moveItem.m_Duration) : timer / moveItem.m_Duration;
  230. if (moveItem.m_UserGlobalDirection)
  231. {
  232. moveItemInfo.moveItem.transform.position = Vector3.Lerp(moveItemInfo.initPosition,
  233. moveItemInfo.initPosition + moveItem.m_Direction, lerp);
  234. }
  235. else
  236. {
  237. moveItemInfo.moveItem.transform.position = Vector3.Lerp(moveItemInfo.initPosition,
  238. moveItemInfo.initPosition + moveItem.transform.TransformDirection(moveItem.m_Direction), lerp);
  239. }
  240. timer += Time.deltaTime;
  241. yield return new WaitForEndOfFrame();
  242. }
  243. moveItemInfo.moveItem?.OpenHighter(false);
  244. finishedCallBack.Invoke();
  245. }
  246. /// <summary>
  247. /// 获取所有的组件
  248. /// </summary>
  249. [TabGroup("配置相关")]
  250. [Button("获取所有的组件")]
  251. [GUIColor("GetColor")]
  252. private void GetAllMoveItems()
  253. {
  254. moveItemInfos = new List<MoveItemInfo>();
  255. MoveItem[] moveItems = transform.GetComponentsInChildren<MoveItem>();
  256. ModelItem[] modelItems = transform.GetComponentsInChildren<ModelItem>();
  257. int count = Mathf.Min(moveItems.Length, modelItems.Length);
  258. for (int i = 0; i < count; i++)
  259. {
  260. MoveItemInfo moveItemInfo = new MoveItemInfo();
  261. moveItemInfo.moveItem = moveItems[i];
  262. moveItemInfo.modelItem = modelItems[i];
  263. moveItemInfo.initPosition = moveItems[i].transform.position;
  264. moveItemInfos.Add(moveItemInfo);
  265. }
  266. //foreach (var item in moveItems)
  267. //{
  268. // MoveItemInfo moveItemInfo = new MoveItemInfo();
  269. // moveItemInfo.moveItem = item;
  270. // moveItemInfo.initPosition = item.transform.position;
  271. // moveItemInfos.Add(moveItemInfo);
  272. //}
  273. }
  274. private Color GetColor()
  275. {
  276. if (moveItemInfos.Count == 0 || moveItemInfos == null)
  277. {
  278. return Color.red;
  279. }
  280. else
  281. {
  282. return Color.green;
  283. }
  284. }
  285. /// <summary>
  286. /// 导出部件数据
  287. /// </summary>
  288. [TabGroup("工具相关")]
  289. [Button("1.导出所有部件名称到表格(先去根据表格配音)")]
  290. private void ExportPartData()
  291. {
  292. List<MoveData> partMarkNames = new List<MoveData>();
  293. foreach (var item in moveItemInfos)
  294. {
  295. MoveData partMarkName = new MoveData();
  296. partMarkName.moveName = item.moveItem.name;
  297. if (partMarkNames.Find(t => t.moveName == partMarkName.moveName) == null) partMarkNames.Add(partMarkName);
  298. }
  299. ExcelHelper.WriteInfoToExcel<MoveData>(Application.streamingAssetsPath + "/" + deviceName + GlobalConfig.excelSuffix, partMarkNames);
  300. }
  301. /// <summary>
  302. /// 重命名音频名称,只能重命名数字的文件
  303. /// </summary>
  304. [TabGroup("工具相关")]
  305. [Button("2.重命名音频名称(初始配音名字为数字)")]
  306. private void ReNameAudioClipName()
  307. {
  308. //表格路径
  309. string tmpExcelPath = PathHelper.CombineFilePath(PathHelper.m_ReadOnlyPath, deviceName) + GlobalConfig.excelSuffix;
  310. //音频路径完整路径信息
  311. string audioPath = PathHelper.CombineFilePath(PathHelper.m_ReadOnlyPath, "Config/Audios/内部结构拆解/" + deviceName);
  312. List<MoveData> tmpMoveDatas = ExcelHelper.ReadInfoFromExcel<MoveData>(tmpExcelPath, 1);
  313. DirectoryInfo directoryInfo = new DirectoryInfo(audioPath);
  314. FileInfo[] files = directoryInfo.GetFiles("*.mp3");
  315. FileInfo[] sortedFiles = files.OrderBy(f => int.Parse(Path.GetFileNameWithoutExtension(f.FullName))).ToArray();
  316. if (tmpMoveDatas.Count != sortedFiles.Length)
  317. {
  318. Debug.LogError("重命名失败");
  319. }
  320. else
  321. {
  322. for (int i = 0; i < tmpMoveDatas.Count; i++)
  323. {
  324. string newPath = Path.Combine(directoryInfo.FullName, tmpMoveDatas[i].moveName) + ".mp3";
  325. sortedFiles[i].MoveTo(newPath);
  326. }
  327. }
  328. }
  329. /// <summary>
  330. /// 设置初始状态
  331. /// </summary>`
  332. private void SetInitState()
  333. {
  334. foreach (var info in moveItemInfos)
  335. {
  336. MoveItem moveItem = info.moveItem;
  337. ModelItem modelItem = info.modelItem;
  338. moveItem.SetInitState(info.initPosition);
  339. moveItem.OpenHighter(false);
  340. moveItem.gameObject.SetActive(true);
  341. modelItem.gameObject.SetActive(false);
  342. }
  343. }
  344. /// <summary>
  345. /// 设置最终状态
  346. /// </summary>
  347. private void SetFinalState()
  348. {
  349. foreach (var info in moveItemInfos)
  350. {
  351. MoveItem moveItem = info.moveItem;
  352. ModelItem modelItem = info.modelItem;
  353. moveItem.SetFianlState();
  354. moveItem.OpenHighter(false);
  355. moveItem.gameObject.SetActive(false);
  356. modelItem.gameObject.SetActive(true);
  357. }
  358. }
  359. public void SetModelActive(bool isActive)
  360. {
  361. foreach (var item in moveItemInfos)
  362. {
  363. item.modelItem.gameObject.SetActive(isActive);
  364. }
  365. }
  366. }
  367. [Serializable]
  368. public class MoveItemInfo
  369. {
  370. [GUIColor("FinishedStateColor")]
  371. public MoveItem moveItem;
  372. public ModelItem modelItem;
  373. [LabelText("父级对象")]
  374. /// <summary>
  375. /// 初始化位置
  376. /// </summary>
  377. [HideInInspector]
  378. public Vector3 initPosition;
  379. [LabelText("是否完成")]
  380. public bool finish;
  381. private Color FinishedStateColor()
  382. {
  383. if (finish)
  384. {
  385. return new Color(0.7f, 1f, 0.7f);
  386. }
  387. return GUI.color;
  388. }
  389. }
  390. public class MoveData
  391. {
  392. public string moveName;
  393. }