源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

697 rivejä
17 KiB

4 viikkoa sitten
  1. using UnityEditor;
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text.RegularExpressions;
  8. namespace U3DExtends {
  9. public class PrefabWin : EditorWindow
  10. {
  11. private static int _labelDefaultFontSize;
  12. [MenuItem("Window/PrefabWin", false, 9)]
  13. static public void OpenPrefabTool()
  14. {
  15. _labelDefaultFontSize = EditorStyles.label.fontSize;
  16. PrefabWin prefabWin = (PrefabWin)EditorWindow.GetWindow<PrefabWin>(false, "Prefab Win", true);
  17. prefabWin.autoRepaintOnSceneChange = true;
  18. prefabWin.Show();
  19. }
  20. static public PrefabWin instance;
  21. class Item
  22. {
  23. public GameObject prefab;
  24. public string guid;
  25. public Texture tex;
  26. public bool dynamicTex = false;
  27. }
  28. enum Mode
  29. {
  30. CompactMode,
  31. IconMode,
  32. DetailedMode,
  33. }
  34. const int cellPadding = 4;
  35. float mSizePercent = 0.5f;
  36. public float SizePercent
  37. {
  38. get { return mSizePercent; }
  39. set
  40. {
  41. if (mSizePercent != value)
  42. {
  43. mReset = true;
  44. mSizePercent = value;
  45. mCellSize = Mathf.FloorToInt(80 * SizePercent + 10);
  46. EditorPrefs.SetFloat("PrefabWin_SizePercent", mSizePercent);
  47. }
  48. }
  49. }
  50. int mCellSize=50;
  51. int cellSize { get { return mCellSize; } }
  52. int mTab = 0;
  53. Mode mMode = Mode.CompactMode;
  54. Vector2 mPos = Vector2.zero;
  55. bool mMouseIsInside = false;
  56. GUIContent mContent;
  57. GUIStyle mStyle;
  58. BetterList<Item> mItems = new BetterList<Item>();
  59. GameObject[] draggedObjects
  60. {
  61. get
  62. {
  63. if (DragAndDrop.objectReferences == null || DragAndDrop.objectReferences.Length == 0)
  64. return null;
  65. return DragAndDrop.objectReferences.Where(x=>x as GameObject).Cast<GameObject>().ToArray();
  66. }
  67. set
  68. {
  69. if (value != null)
  70. {
  71. DragAndDrop.PrepareStartDrag();
  72. DragAndDrop.objectReferences = value;
  73. draggedObjectIsOurs = true;
  74. }
  75. else DragAndDrop.AcceptDrag();
  76. }
  77. }
  78. bool draggedObjectIsOurs
  79. {
  80. get
  81. {
  82. object obj = DragAndDrop.GetGenericData("Prefab Tool");
  83. if (obj == null) return false;
  84. return (bool)obj;
  85. }
  86. set
  87. {
  88. DragAndDrop.SetGenericData("Prefab Tool", value);
  89. }
  90. }
  91. void OnEnable ()
  92. {
  93. instance = this;
  94. Load();
  95. mContent = new GUIContent();
  96. mStyle = new GUIStyle();
  97. mStyle.alignment = TextAnchor.MiddleCenter;
  98. mStyle.padding = new RectOffset(2, 2, 2, 2);
  99. mStyle.clipping = TextClipping.Clip;
  100. mStyle.wordWrap = true;
  101. mStyle.stretchWidth = false;
  102. mStyle.stretchHeight = false;
  103. mStyle.normal.textColor = UnityEditor.EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.5f) : new Color(0f, 0f, 0f, 0.5f);
  104. mStyle.normal.background = null;
  105. }
  106. void OnDisable ()
  107. {
  108. instance = null;
  109. foreach (Item item in mItems) DestroyTexture(item);
  110. Save();
  111. }
  112. void OnSelectionChange () { Repaint(); }
  113. public void Reset ()
  114. {
  115. foreach (Item item in mItems) DestroyTexture(item);
  116. mItems.Clear();
  117. if (mTab == 0 && Configure.PrefabWinFirstSearchPath!="")
  118. {
  119. List<string> filtered = new List<string>();
  120. string[] allAssets = AssetDatabase.GetAllAssetPaths();
  121. foreach (string s in allAssets)
  122. {
  123. //search prefab files in folder:Configure.PrefabWinFirstSearchPath
  124. bool isComeFromPrefab = Regex.IsMatch(s, Configure.PrefabWinFirstSearchPath+@"/((?!/).)*\.prefab");
  125. if (isComeFromPrefab)
  126. filtered.Add(s);
  127. }
  128. filtered.Sort(string.Compare);
  129. foreach (string s in filtered) AddGUID(AssetDatabase.AssetPathToGUID(s), -1);
  130. RectivateLights();
  131. }
  132. }
  133. void AddItem (GameObject go, int index)
  134. {
  135. string guid = U3DExtends.UIEditorHelper.ObjectToGUID(go);
  136. if (string.IsNullOrEmpty(guid))
  137. {
  138. string path = EditorUtility.SaveFilePanelInProject("Save a prefab",
  139. go.name + ".prefab", "prefab", "Save prefab as...", "");
  140. if (string.IsNullOrEmpty(path)) return;
  141. go = PrefabUtility.CreatePrefab(path, go);
  142. if (go == null) return;
  143. guid = U3DExtends.UIEditorHelper.ObjectToGUID(go);
  144. if (string.IsNullOrEmpty(guid)) return;
  145. }
  146. Item ent = new Item();
  147. ent.prefab = go;
  148. ent.guid = guid;
  149. GeneratePreview(ent);
  150. RectivateLights();
  151. if (index < mItems.size) mItems.Insert(index, ent);
  152. else mItems.Add(ent);
  153. Save();
  154. }
  155. Item AddGUID (string guid, int index)
  156. {
  157. GameObject go = U3DExtends.UIEditorHelper.GUIDToObject<GameObject>(guid);
  158. if (go != null)
  159. {
  160. Item ent = new Item();
  161. ent.prefab = go;
  162. ent.guid = guid;
  163. GeneratePreview(ent, false);
  164. if (index < mItems.size) mItems.Insert(index, ent);
  165. else mItems.Add(ent);
  166. return ent;
  167. }
  168. return null;
  169. }
  170. void RemoveItem (object obj)
  171. {
  172. if (this == null) return;
  173. int index = (int)obj;
  174. if (index < mItems.size && index > -1)
  175. {
  176. Item item = mItems[index];
  177. DestroyTexture(item);
  178. mItems.RemoveAt(index);
  179. }
  180. Save();
  181. }
  182. Item FindItem (GameObject go)
  183. {
  184. for (int i = 0; i < mItems.size; ++i)
  185. if (mItems[i].prefab == go)
  186. return mItems[i];
  187. return null;
  188. }
  189. string saveKey { get { return "PrefabWin " + Application.dataPath + " " + mTab; } }
  190. void Save ()
  191. {
  192. string data = "";
  193. if (mItems.size > 0)
  194. {
  195. string guid = mItems[0].guid;
  196. StringBuilder sb = new StringBuilder();
  197. sb.Append(guid);
  198. for (int i = 1; i < mItems.size; ++i)
  199. {
  200. guid = mItems[i].guid;
  201. if (string.IsNullOrEmpty(guid))
  202. {
  203. Debug.LogWarning("Unable to save " + mItems[i].prefab.name);
  204. }
  205. else
  206. {
  207. sb.Append('|');
  208. sb.Append(mItems[i].guid);
  209. }
  210. }
  211. data = sb.ToString();
  212. }
  213. EditorPrefs.SetString(saveKey, data);
  214. }
  215. void Load ()
  216. {
  217. mTab = EditorPrefs.GetInt("PrefabWin Prefab Tab", 0);
  218. SizePercent = EditorPrefs.GetFloat("PrefabWin_SizePercent", 0.5f);
  219. foreach (Item item in mItems) DestroyTexture(item);
  220. mItems.Clear();
  221. string data = EditorPrefs.GetString(saveKey, "");
  222. //data = "";//For test
  223. if (string.IsNullOrEmpty(data))
  224. {
  225. Reset();
  226. }
  227. else
  228. {
  229. if (string.IsNullOrEmpty(data)) return;
  230. string[] guids = data.Split('|');
  231. foreach (string s in guids) AddGUID(s, -1);
  232. RectivateLights();
  233. }
  234. }
  235. void DestroyTexture (Item item)
  236. {
  237. if (item != null && item.dynamicTex && item.tex != null)
  238. {
  239. DestroyImmediate(item.tex);
  240. item.dynamicTex = false;
  241. item.tex = null;
  242. }
  243. }
  244. void UpdateVisual ()
  245. {
  246. if (draggedObjects == null) DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
  247. else if (draggedObjectIsOurs) DragAndDrop.visualMode = DragAndDropVisualMode.Move;
  248. else DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
  249. }
  250. Item CreateItemByPath (string path)
  251. {
  252. if (!string.IsNullOrEmpty(path))
  253. {
  254. path = FileUtil.GetProjectRelativePath(path);
  255. string guid = AssetDatabase.AssetPathToGUID(path);
  256. if (!string.IsNullOrEmpty(guid))
  257. {
  258. GameObject go = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;
  259. Item ent = new Item();
  260. ent.prefab = go;
  261. ent.guid = guid;
  262. GeneratePreview(ent);
  263. return ent;
  264. }
  265. else Debug.Log("No GUID");
  266. }
  267. return null;
  268. }
  269. void GeneratePreview (Item item, bool isReCreate = true)
  270. {
  271. if (item == null || item.prefab == null) return;
  272. {
  273. string preview_path = Configure.ResAssetsPath + "/Preview/" + item.prefab.name + ".png";
  274. if (!isReCreate && File.Exists(preview_path))
  275. {
  276. Texture texture = UIEditorHelper.LoadTextureInLocal(preview_path);
  277. item.tex = texture;
  278. }
  279. else
  280. {
  281. Texture Tex = UIEditorHelper.GetAssetPreview(item.prefab);
  282. if (Tex != null)
  283. {
  284. DestroyTexture(item);
  285. item.tex = Tex;
  286. UIEditorHelper.SaveTextureToPNG(Tex, preview_path);
  287. }
  288. }
  289. item.dynamicTex = false;
  290. return;
  291. }
  292. }
  293. static Transform FindChild (Transform t, string startsWith)
  294. {
  295. if (t.name.StartsWith(startsWith)) return t;
  296. for (int i = 0, imax = t.childCount; i < imax; ++i)
  297. {
  298. Transform ch = FindChild(t.GetChild(i), startsWith);
  299. if (ch != null) return ch;
  300. }
  301. return null;
  302. }
  303. static BetterList<Light> mLights;
  304. static void RectivateLights ()
  305. {
  306. if (mLights != null)
  307. {
  308. for (int i = 0; i < mLights.size; ++i)
  309. mLights[i].enabled = true;
  310. mLights = null;
  311. }
  312. }
  313. int GetCellUnderMouse (int spacingX, int spacingY)
  314. {
  315. Vector2 pos = Event.current.mousePosition + mPos;
  316. int topPadding = 24;
  317. int x = cellPadding, y = cellPadding + topPadding;
  318. if (pos.y < y) return -1;
  319. float width = Screen.width - cellPadding + mPos.x;
  320. float height = Screen.height - cellPadding + mPos.y;
  321. int index = 0;
  322. for (; ; ++index)
  323. {
  324. Rect rect = new Rect(x, y, spacingX, spacingY);
  325. if (rect.Contains(pos)) break;
  326. x += spacingX;
  327. if (x + spacingX > width)
  328. {
  329. if (pos.x > x) return -1;
  330. y += spacingY;
  331. x = cellPadding;
  332. if (y + spacingY > height) return -1;
  333. }
  334. }
  335. return index;
  336. }
  337. bool mReset = false;
  338. private List<Item> _selections = new List<Item>();
  339. void OnGUI ()
  340. {
  341. Event currentEvent = Event.current;
  342. EventType type = currentEvent.type;
  343. int x = cellPadding, y = cellPadding;
  344. int width = Screen.width - cellPadding;
  345. int spacingX = cellSize + cellPadding;
  346. int spacingY = spacingX;
  347. if (mMode == Mode.DetailedMode) spacingY += 32;
  348. GameObject[] draggeds = draggedObjects;
  349. bool isDragging = (draggeds != null);
  350. int indexUnderMouse = GetCellUnderMouse(spacingX, spacingY);
  351. if (isDragging)
  352. {
  353. foreach (var gameObject in draggeds)
  354. {
  355. var result = FindItem(gameObject);
  356. if (result != null)
  357. {
  358. _selections.Add(result);
  359. }
  360. }
  361. }
  362. string searchFilter = EditorPrefs.GetString("PrefabWin_SearchFilter", null);
  363. int newTab = mTab;
  364. GUILayout.BeginHorizontal();
  365. if (GUILayout.Toggle(newTab == 0, "通用控件", "ButtonLeft")) newTab = 0;
  366. if (GUILayout.Toggle(newTab == 1, "其它模板", "ButtonRight")) newTab = 1;
  367. GUILayout.EndHorizontal();
  368. if (mTab != newTab)
  369. {
  370. Save();
  371. mTab = newTab;
  372. mReset = true;
  373. EditorPrefs.SetInt("PrefabWin Prefab Tab", mTab);
  374. Load();
  375. }
  376. if (mReset && type == EventType.Repaint)
  377. {
  378. mReset = false;
  379. foreach (Item item in mItems) GeneratePreview(item, false);
  380. RectivateLights();
  381. }
  382. bool eligibleToDrag = (currentEvent.mousePosition.y < Screen.height - 40);
  383. if (type == EventType.MouseDown)
  384. {
  385. mMouseIsInside = true;
  386. }
  387. else if (type == EventType.MouseDrag)
  388. {
  389. mMouseIsInside = true;
  390. if (indexUnderMouse != -1 && eligibleToDrag)
  391. {
  392. if (draggedObjectIsOurs) DragAndDrop.StartDrag("Prefab Tool");
  393. currentEvent.Use();
  394. }
  395. }
  396. else if (type == EventType.MouseUp)
  397. {
  398. DragAndDrop.PrepareStartDrag();
  399. mMouseIsInside = false;
  400. Repaint();
  401. }
  402. else if (type == EventType.DragUpdated)
  403. {
  404. mMouseIsInside = true;
  405. UpdateVisual();
  406. currentEvent.Use();
  407. }
  408. else if (type == EventType.DragPerform)
  409. {
  410. if (draggeds != null)
  411. {
  412. if (_selections != null)
  413. {
  414. foreach (var selection in _selections)
  415. {
  416. DestroyTexture(selection);
  417. mItems.Remove(selection);
  418. }
  419. }
  420. foreach (var dragged in draggeds)
  421. {
  422. AddItem(dragged, indexUnderMouse);
  423. ++indexUnderMouse;
  424. }
  425. draggeds = null;
  426. }
  427. mMouseIsInside = false;
  428. currentEvent.Use();
  429. }
  430. else if (type == EventType.DragExited || type == EventType.Ignore)
  431. {
  432. mMouseIsInside = false;
  433. }
  434. if (!mMouseIsInside)
  435. {
  436. _selections.Clear();
  437. draggeds = null;
  438. }
  439. BetterList<int> indices = new BetterList<int>();
  440. for (int i = 0; i < mItems.size; )
  441. {
  442. if (draggeds != null && indices.size == indexUnderMouse)
  443. indices.Add(-1);
  444. var has = _selections.Exists(item => item == mItems[i]);
  445. if (!has)
  446. {
  447. if (string.IsNullOrEmpty(searchFilter) ||
  448. mItems[i].prefab.name.IndexOf(searchFilter, System.StringComparison.CurrentCultureIgnoreCase) != -1)
  449. indices.Add(i);
  450. }
  451. ++i;
  452. }
  453. if (!indices.Contains(-1)) indices.Add(-1);
  454. if (eligibleToDrag && type == EventType.MouseDown && indexUnderMouse > -1)
  455. {
  456. GUIUtility.keyboardControl = 0;
  457. if (currentEvent.button == 0 && indexUnderMouse < indices.size)
  458. {
  459. int index = indices[indexUnderMouse];
  460. if (index != -1 && index < mItems.size)
  461. {
  462. _selections.Add(mItems[index]);
  463. draggedObjects = _selections.Select(item => item.prefab).ToArray();
  464. draggeds = _selections.Select(item=>item.prefab).ToArray();
  465. currentEvent.Use();
  466. }
  467. }
  468. }
  469. mPos = EditorGUILayout.BeginScrollView(mPos);
  470. {
  471. Color normal = new Color(1f, 1f, 1f, 0.5f);
  472. for (int i = 0; i < indices.size; ++i)
  473. {
  474. int index = indices[i];
  475. Item ent = (index != -1) ? mItems[index] : _selections.Count == 0 ? null : _selections[0];
  476. if (ent != null && ent.prefab == null)
  477. {
  478. mItems.RemoveAt(index);
  479. continue;
  480. }
  481. Rect rect = new Rect(x, y, cellSize, cellSize);
  482. Rect inner = rect;
  483. inner.xMin += 2f;
  484. inner.xMax -= 2f;
  485. inner.yMin += 2f;
  486. inner.yMax -= 2f;
  487. rect.yMax -= 1f;
  488. if (!isDragging && (mMode == Mode.CompactMode || (ent == null || ent.tex != null)))
  489. mContent.tooltip = (ent != null) ? ent.prefab.name : "Click to add";
  490. else mContent.tooltip = "";
  491. //if (ent == selection)
  492. {
  493. GUI.color = normal;
  494. U3DExtends.UIEditorHelper.DrawTiledTexture(inner, U3DExtends.UIEditorHelper.backdropTexture);
  495. }
  496. GUI.color = Color.white;
  497. GUI.backgroundColor = normal;
  498. if (GUI.Button(rect, mContent, "Button"))
  499. {
  500. if (ent == null || currentEvent.button == 0)
  501. {
  502. string path = EditorUtility.OpenFilePanel("Add a prefab", "", "prefab");
  503. if (!string.IsNullOrEmpty(path))
  504. {
  505. Item newEnt = CreateItemByPath(path);
  506. if (newEnt != null)
  507. {
  508. mItems.Add(newEnt);
  509. Save();
  510. }
  511. }
  512. }
  513. else if (currentEvent.button == 1)
  514. {
  515. //ContextMenu.AddItem("Update Preview", false, UpdatePreView, index);
  516. ContextMenu.AddItemWithArge("Delete", false, RemoveItem, index);
  517. ContextMenu.Show();
  518. }
  519. }
  520. string caption = (ent == null) ? "" : ent.prefab.name.Replace("Control - ", "");
  521. if (ent != null)
  522. {
  523. if (ent.tex == null)
  524. {
  525. //texture may be destroy after exit game
  526. GeneratePreview(ent, false);
  527. }
  528. if (ent.tex != null)
  529. {
  530. GUI.DrawTexture(inner, ent.tex);
  531. var labelPos = new Rect(inner);
  532. var labelStyle = EditorStyles.label;
  533. labelPos.height = labelStyle.lineHeight;
  534. labelPos.y = inner.height - labelPos.height + 5;
  535. labelStyle.fontSize = (int) (_labelDefaultFontSize * SizePercent);
  536. labelStyle.alignment = TextAnchor.LowerCenter;
  537. {
  538. GUI.Label(labelPos, ent.prefab.name,labelStyle);
  539. }
  540. labelStyle.alignment = TextAnchor.UpperLeft;
  541. labelStyle.fontSize = _labelDefaultFontSize;
  542. }
  543. else if (mMode != Mode.DetailedMode)
  544. {
  545. GUI.Label(inner, caption, mStyle);
  546. caption = "";
  547. }
  548. }
  549. else GUI.Label(inner, "Add", mStyle);
  550. if (mMode == Mode.DetailedMode)
  551. {
  552. GUI.backgroundColor = new Color(1f, 1f, 1f, 0.5f);
  553. GUI.contentColor = new Color(1f, 1f, 1f, 0.7f);
  554. GUI.Label(new Rect(rect.x, rect.y + rect.height, rect.width, 32f), caption, "ProgressBarBack");
  555. GUI.contentColor = Color.white;
  556. GUI.backgroundColor = Color.white;
  557. }
  558. x += spacingX;
  559. if (x + spacingX > width)
  560. {
  561. y += spacingY;
  562. x = cellPadding;
  563. }
  564. }
  565. GUILayout.Space(y + spacingY);
  566. }
  567. EditorGUILayout.EndScrollView();
  568. //if (mTab == 0)
  569. {
  570. //EditorGUILayout.BeginHorizontal();
  571. //bool isCreateBackground = GUILayout.Button("背景");
  572. //if (isCreateBackground)
  573. // EditorApplication.ExecuteMenuItem("UIEditor/创建/Background");
  574. //bool isCreateDecorate = GUILayout.Button("参考图");
  575. //if (isCreateDecorate)
  576. // EditorApplication.ExecuteMenuItem("UIEditor/创建/Decorate");
  577. //EditorGUILayout.EndHorizontal();
  578. }
  579. //else if (mTab != 0)
  580. {
  581. GUILayout.BeginHorizontal();
  582. {
  583. string after = EditorGUILayout.TextField("", searchFilter, "SearchTextField", GUILayout.Width(Screen.width - 20f));
  584. if (GUILayout.Button("", "SearchCancelButton", GUILayout.Width(18f)))
  585. {
  586. after = "";
  587. GUIUtility.keyboardControl = 0;
  588. }
  589. if (searchFilter != after)
  590. {
  591. EditorPrefs.SetString("PrefabWin_SearchFilter", after);
  592. searchFilter = after;
  593. }
  594. }
  595. GUILayout.EndHorizontal();
  596. }
  597. SizePercent = EditorGUILayout.Slider(SizePercent, 0, 1);
  598. }
  599. }
  600. }