MoveItemManager.cs 13 KB

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