源战役客户端
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.

1092 lines
47 KiB

  1. #if UNITY_EDITOR
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using UnityEngine.UI;
  8. using LuaFramework;
  9. namespace U3DExtends
  10. {
  11. public static class UIEditorHelper
  12. {
  13. public static void SetImageByPath(string assetPath, Image image, bool isNativeSize = true)
  14. {
  15. Object newImg = UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, typeof(Sprite));
  16. Undo.RecordObject(image, "Change Image");//有了这句才可以用ctrl+z撤消此赋值操作
  17. image.sprite = newImg as Sprite;
  18. if (isNativeSize)
  19. image.SetNativeSize();
  20. EditorUtility.SetDirty(image);
  21. }
  22. [MenuItem("Edit/Copy Names " + Configure.ShortCut.CopyNodesName, false, 2)]
  23. public static void CopySelectWidgetName()
  24. {
  25. string result = "";
  26. foreach (var item in Selection.gameObjects)
  27. {
  28. string item_name = item.name;
  29. Transform root_trans = item.transform.parent;
  30. while (root_trans != null && root_trans.GetComponent<Canvas>() == null)
  31. {
  32. if (root_trans.parent != null && root_trans.parent.GetComponent<Canvas>() == null)
  33. item_name = root_trans.name + "/" + item_name;
  34. else
  35. break;
  36. root_trans = root_trans.parent;
  37. }
  38. result = result + "\"" + item_name + "\", ";
  39. }
  40. //复制到系统全局的粘贴板上
  41. GUIUtility.systemCopyBuffer = result;
  42. Debug.Log("Copy Nodes Name Succeed!");
  43. Debug.Log(result);
  44. }
  45. [MenuItem("Edit/Copy Names With Components " + Configure.ShortCut.CopyNodesComponentName, false, 2)]
  46. public static void CopySelectWidgetNameWithComponents()
  47. {
  48. string result = "";
  49. foreach (var item in Selection.gameObjects)
  50. {
  51. string item_name = item.name;
  52. Transform root_trans = item.transform.parent;
  53. while (root_trans != null && root_trans.GetComponent<Canvas>() == null)
  54. {
  55. if (root_trans.parent != null && root_trans.parent.GetComponent<Canvas>() == null)
  56. {
  57. item_name = root_trans.name + "/" + item_name;
  58. }
  59. else
  60. break;
  61. root_trans = root_trans.parent;
  62. }
  63. item_name = item_name + ":obj";
  64. if (item.GetComponent<ImageExtend>() != null)
  65. {
  66. item_name = item_name + ":imgex";
  67. }
  68. else if (item.GetComponent<Image>() != null)
  69. {
  70. item_name = item_name + ":img";
  71. }
  72. else if (item.GetComponent<RawImage>() != null)
  73. {
  74. item_name = item_name + ":raw";
  75. }
  76. if (item.GetComponent<AdaptiveText>() != null)
  77. {
  78. item_name = item_name + ":adtxt";
  79. }
  80. else if (item.GetComponent<Text>() != null)
  81. {
  82. item_name = item_name + ":txt";
  83. }
  84. if (item.GetComponent<Outline>() != null)
  85. {
  86. item_name = item_name + ":outline";
  87. }
  88. result = result + "\"" + item_name + "\", ";
  89. }
  90. //复制到系统全局的粘贴板上
  91. GUIUtility.systemCopyBuffer = result;
  92. Debug.Log("Copy Nodes Name Succeed!");
  93. Debug.Log(result);
  94. }
  95. public static Transform GetRootLayout(Transform trans)
  96. {
  97. Transform result = null;
  98. Canvas canvas = trans.GetComponentInParent<Canvas>();
  99. if (canvas != null)
  100. {
  101. foreach (var item in canvas.transform.GetComponentsInChildren<RectTransform>())
  102. {
  103. if (item.GetComponent<Decorate>() == null && canvas.transform != item)
  104. {
  105. result = item;
  106. break;
  107. }
  108. }
  109. }
  110. return result;
  111. }
  112. static public GameObject GetUITestRootNode()
  113. {
  114. GameObject testUI = GameObject.Find(Configure.UITestNodeName);
  115. if (!testUI)
  116. {
  117. testUI = new GameObject(Configure.UITestNodeName, typeof(RectTransform));
  118. RectTransform trans = testUI.GetComponent<RectTransform>();
  119. trans.position = Configure.UITestNodePos;
  120. trans.sizeDelta = Configure.UITestNodeSize;
  121. var parentNode = GameObject.Find(Configure.UITestParentNodeName).GetComponent<Transform>();
  122. Debug.Log("parentNode : "+(parentNode!=null));
  123. trans.SetParent(parentNode);
  124. testUI.AddComponent<ReopenLayoutOnExitGame>();
  125. }
  126. return testUI;
  127. }
  128. static public Transform GetContainerUnderMouse(Vector3 mouse_abs_pos, GameObject ignore_obj = null)
  129. {
  130. GameObject testUI = UIEditorHelper.GetUITestRootNode();
  131. List<RectTransform> list = new List<RectTransform>();
  132. Canvas[] containers = Transform.FindObjectsOfType<Canvas>();
  133. Vector3[] corners = new Vector3[4];
  134. foreach (var item in containers)
  135. {
  136. if (ignore_obj == item.gameObject || item.transform.parent != testUI.transform)
  137. continue;
  138. RectTransform trans = item.transform as RectTransform;
  139. if (trans != null)
  140. {
  141. //获取节点的四个角的世界坐标,分别按顺序为左下左上,右上右下
  142. trans.GetWorldCorners(corners);
  143. if (mouse_abs_pos.x >= corners[0].x && mouse_abs_pos.y <= corners[1].y && mouse_abs_pos.x <= corners[2].x && mouse_abs_pos.y >= corners[3].y)
  144. {
  145. list.Add(trans);
  146. }
  147. }
  148. }
  149. if (list.Count <= 0)
  150. return null;
  151. list.Sort((RectTransform a, RectTransform b) => { return (a.GetSiblingIndex() == b.GetSiblingIndex()) ? 0 : ((a.GetSiblingIndex() < b.GetSiblingIndex()) ? 1 : -1); }
  152. );
  153. return GetRootLayout(list[0]);
  154. }
  155. public static GameObject CreatNewLayout(bool isNeedLayout = true)
  156. {
  157. GameObject testUI = UIEditorHelper.GetUITestRootNode();
  158. string file_path = Path.Combine(Configure.ResAssetsPath, "Canvas.prefab");
  159. file_path = FileUtil.GetProjectRelativePath(file_path);
  160. GameObject layout_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(file_path, typeof(UnityEngine.Object)) as GameObject;
  161. GameObject layout = GameObject.Instantiate(layout_prefab) as GameObject;
  162. layout.transform.SetParent(testUI.transform);
  163. Vector3 last_pos = layout.transform.localPosition;
  164. layout.transform.localPosition = new Vector3(last_pos.x, last_pos.y, 0);
  165. if (!isNeedLayout)
  166. {
  167. Transform child = layout.transform.Find("Layout");
  168. // layout.transform.DetachChildren();
  169. if (child!=null)
  170. Undo.DestroyObjectImmediate(child.gameObject);
  171. }
  172. Selection.activeGameObject = layout;
  173. RectTransform trans = layout.transform as RectTransform;
  174. SceneView.lastActiveSceneView.MoveToView(trans);
  175. return layout;
  176. }
  177. public static bool SelectPicForDecorate(Decorate decorate)
  178. {
  179. if (decorate != null)
  180. {
  181. string default_path = PathSaver.GetInstance().GetLastPath(PathType.OpenDecorate);
  182. string spr_path = EditorUtility.OpenFilePanel("加载外部图片", default_path, "");
  183. if (spr_path.Length > 0)
  184. {
  185. decorate.SprPath = spr_path;
  186. PathSaver.GetInstance().SetLastPath(PathType.OpenDecorate, spr_path);
  187. return true;
  188. }
  189. }
  190. return false;
  191. }
  192. public static Decorate CreateEmptyDecorate(Transform parent)
  193. {
  194. string file_path = Path.Combine(Configure.ResAssetsPath, "Decorate.prefab");
  195. file_path = FileUtil.GetProjectRelativePath(file_path);
  196. GameObject decorate_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(file_path, typeof(UnityEngine.Object)) as GameObject;
  197. GameObject decorate = GameObject.Instantiate(decorate_prefab) as GameObject;
  198. decorate.transform.SetParent(parent);
  199. RectTransform rectTrans = decorate.transform as RectTransform;
  200. rectTrans.SetAsFirstSibling();
  201. rectTrans.localPosition = Vector3.zero;
  202. rectTrans.localScale = Vector3.one;
  203. Decorate decor = rectTrans.GetComponent<Decorate>();
  204. return decor;
  205. }
  206. public static void CreateDecorate()
  207. {
  208. if (Selection.activeTransform != null)
  209. {
  210. Canvas canvas = Selection.activeTransform.GetComponentInParent<Canvas>();
  211. if (canvas != null)
  212. {
  213. Decorate decor = CreateEmptyDecorate(canvas.transform);
  214. Selection.activeTransform = decor.transform;
  215. if (Configure.OpenSelectPicDialogWhenAddDecorate)
  216. {
  217. bool isSucceed = UIEditorHelper.SelectPicForDecorate(decor);
  218. if (!isSucceed)
  219. GameObject.DestroyImmediate(decor.gameObject);
  220. }
  221. }
  222. }
  223. }
  224. // [MenuItem("UIEditor/清空界面 " + Configure.ShortCut.ClearAllCanvas)]
  225. public static void ClearAllCanvas()
  226. {
  227. bool isDeleteAll = EditorUtility.DisplayDialog("警告", "是否清空掉所有界面?", "干!", "不了");
  228. if (isDeleteAll)
  229. {
  230. GameObject test = GameObject.Find(Configure.UITestNodeName);
  231. if (test != null)
  232. {
  233. LayoutInfo[] allLayouts = test.transform.GetComponentsInChildren<LayoutInfo>(true);
  234. foreach (var item in allLayouts)
  235. {
  236. Undo.DestroyObjectImmediate(item.gameObject);
  237. }
  238. // GameObject.DestroyImmediate(test);
  239. }
  240. }
  241. }
  242. public static void LoadLayoutWithFolder()
  243. {
  244. string default_path = PathSaver.GetInstance().GetLastPath(PathType.SaveLayout);
  245. string select_path = EditorUtility.OpenFolderPanel("Open Layout", default_path, "");
  246. PathSaver.GetInstance().SetLastPath(PathType.SaveLayout, select_path);
  247. if (select_path.Length > 0)
  248. {
  249. string[] file_paths = Directory.GetFiles(select_path, "*.prefab");
  250. foreach (var path in file_paths)
  251. {
  252. LoadLayoutByPath(path);
  253. }
  254. }
  255. UILayoutTool.ResortAllLayout();
  256. }
  257. private static GameObject GetLoadedLayout(string layoutPath)
  258. {
  259. GameObject testUI = UIEditorHelper.GetUITestRootNode();
  260. if (testUI != null)
  261. {
  262. LayoutInfo[] layoutInfos = testUI.GetComponentsInChildren<LayoutInfo>(true);
  263. foreach (var item in layoutInfos)
  264. {
  265. if (item.LayoutPath == layoutPath)
  266. return item.gameObject;
  267. }
  268. }
  269. return null;
  270. }
  271. //从界面的Canvas里取到真实的界面prefab
  272. public static Transform GetRealLayout(GameObject anyObj)
  273. {
  274. LayoutInfo layoutInfo = anyObj.GetComponentInParent<LayoutInfo>();
  275. Transform real_layout = null;
  276. if (layoutInfo == null)
  277. return real_layout;
  278. if (layoutInfo.LayoutPath != string.Empty)
  279. {
  280. string just_name = System.IO.Path.GetFileNameWithoutExtension(layoutInfo.LayoutPath);
  281. for (int i = 0; i < layoutInfo.transform.childCount; i++)
  282. {
  283. Transform child = layoutInfo.transform.GetChild(i);
  284. if (child.name.StartsWith(just_name))
  285. {
  286. real_layout = child;
  287. break;
  288. }
  289. }
  290. }
  291. else
  292. {
  293. //界面是新建的,未保存过的情况下取其子节点
  294. Canvas layout = anyObj.GetComponentInParent<Canvas>();
  295. for (int i = 0; i < layout.transform.childCount; i++)
  296. {
  297. Transform child = layout.transform.GetChild(i);
  298. if (child.GetComponent<Decorate>() != null)
  299. continue;
  300. real_layout = child.transform;
  301. break;
  302. }
  303. }
  304. return real_layout;
  305. }
  306. public static void DelayReLoadLayout(GameObject o, bool isQuiet)
  307. {
  308. System.Action<PlayModeStateChange> p = null;
  309. p = new System.Action<PlayModeStateChange>((PlayModeStateChange c) => {
  310. Debug.Log("reload !");
  311. ReLoadLayout(o, isQuiet);
  312. UnityEditor.EditorApplication.playModeStateChanged -= p;
  313. });
  314. UnityEditor.EditorApplication.playModeStateChanged += p;
  315. }
  316. public static void ReLoadLayout(GameObject o, bool isQuiet)
  317. {
  318. GameObject saveObj = o == null ? Selection.activeGameObject : (o as GameObject);
  319. if (saveObj == null)
  320. return;
  321. LayoutInfo layoutInfo = saveObj.GetComponentInParent<LayoutInfo>();
  322. if (layoutInfo != null && layoutInfo.LayoutPath != string.Empty)
  323. {
  324. bool is_reopen = isQuiet || EditorUtility.DisplayDialog("警告", "是否重新加载?", "来吧", "不了");
  325. if (is_reopen)
  326. {
  327. string just_name = System.IO.Path.GetFileNameWithoutExtension(layoutInfo.LayoutPath);
  328. Transform real_layout = GetRealLayout(layoutInfo.gameObject);
  329. if (real_layout)
  330. {
  331. string select_path = FileUtil.GetProjectRelativePath(layoutInfo.LayoutPath);
  332. Object prefab = AssetDatabase.LoadAssetAtPath(select_path, typeof(Object));
  333. GameObject new_view = PrefabUtility.InstantiateAttachedAsset(prefab) as GameObject;
  334. new_view.transform.SetParent(layoutInfo.transform);
  335. new_view.transform.localPosition = real_layout.localPosition;
  336. new_view.transform.localScale = Vector3.one;
  337. new_view.name = just_name;
  338. // PrefabUtility.DisconnectPrefabInstance(new_view);//链接中的话删里面的子节点时会报警告,所以还是一直失联的好,保存时直接覆盖pref
  339. Undo.DestroyObjectImmediate(real_layout.gameObject);
  340. Debug.Log("Reload Layout Succeed!");
  341. layoutInfo.ApplyConfig(select_path);
  342. }
  343. }
  344. }
  345. else
  346. Debug.Log("Try to reload unsaved layout failed");
  347. }
  348. public static Transform LoadLayoutByPath(string select_path)
  349. {
  350. //Debug.Log("select_path : "+select_path);
  351. GameObject new_layout = CreatNewLayout(false);
  352. new_layout.transform.localPosition = new Vector3(new_layout.transform.localPosition.x, new_layout.transform.localPosition.y, 0);
  353. LayoutInfo layoutInfo = new_layout.GetComponent<LayoutInfo>();
  354. layoutInfo.LayoutPath = select_path;
  355. if (!File.Exists(select_path))
  356. {
  357. Debug.Log("UIEditorHelper:LoadLayoutByPath cannot find layout file:"+select_path);
  358. return null;
  359. }
  360. string asset_relate_path = select_path;
  361. if (!select_path.StartsWith("Assets/"))
  362. asset_relate_path = FileUtil.GetProjectRelativePath(select_path);
  363. Object prefab = AssetDatabase.LoadAssetAtPath(asset_relate_path, typeof(Object));
  364. GameObject new_view = PrefabUtility.InstantiateAttachedAsset(prefab) as GameObject;
  365. new_view.transform.SetParent(new_layout.transform);
  366. new_view.transform.localPosition = Vector3.zero;
  367. new_view.transform.localScale = Vector3.one;
  368. string just_name = System.IO.Path.GetFileNameWithoutExtension(asset_relate_path);
  369. new_view.name = just_name;
  370. new_layout.gameObject.name = just_name + "_Canvas";
  371. #if !UNITY_2018_3_OR_NEWER
  372. PrefabUtility.DisconnectPrefabInstance(new_view);//链接中的话删里面的子节点时会报警告,所以还是一直失联的好,保存时直接覆盖prefab就行了
  373. #endif
  374. //打开界面时,从项目临时文件夹找到对应界面的参照图配置,然后生成参照图
  375. layoutInfo.ApplyConfig(asset_relate_path);
  376. ReopenLayoutOnExitGame.RecordOpenLayout(select_path, new_layout.transform.localPosition);
  377. return new_layout.transform;
  378. }
  379. //[MenuItem("UIEditor/加载界面 " + Configure.ShortCut.LoadUIPrefab, false, 1)]
  380. public static void LoadLayout()
  381. {
  382. string default_path = PathSaver.GetInstance().GetLastPath(PathType.SaveLayout);
  383. string select_path = EditorUtility.OpenFilePanel("Open Layout", default_path, "prefab");
  384. PathSaver.GetInstance().SetLastPath(PathType.SaveLayout, select_path);
  385. if (select_path.Length > 0)
  386. {
  387. //检查是否已打开同名界面
  388. GameObject loaded_layout = GetLoadedLayout(select_path);
  389. if (loaded_layout!=null)
  390. {
  391. bool is_reopen = EditorUtility.DisplayDialog("警告", "已打开同名界面,是否重新加载?", "来吧", "不了");
  392. if (is_reopen)
  393. {
  394. //Undo.DestroyObjectImmediate(loaded_layout);
  395. ReLoadLayout(loaded_layout, true);
  396. }
  397. return;
  398. }
  399. LoadLayoutByPath(select_path);
  400. }
  401. }
  402. //[MenuItem("UIEditor/Operate/锁定")]
  403. public static void LockWidget()
  404. {
  405. if (Selection.gameObjects.Length > 0)
  406. {
  407. Selection.gameObjects[0].hideFlags = HideFlags.NotEditable;
  408. }
  409. }
  410. //[MenuItem("UIEditor/Operate/解锁")]
  411. public static void UnLockWidget()
  412. {
  413. if (Selection.gameObjects.Length > 0)
  414. {
  415. Selection.gameObjects[0].hideFlags = HideFlags.None;
  416. }
  417. }
  418. //是否支持解体
  419. public static bool IsNodeCanDivide(GameObject obj)
  420. {
  421. if (obj == null)
  422. return false;
  423. return obj.transform != null && obj.transform.childCount > 0 && obj.GetComponent<Canvas>() == null && obj.transform.parent != null && obj.transform.parent.GetComponent<Canvas>() == null;
  424. }
  425. public static bool SaveTextureToPNG(Texture inputTex, string save_file_name)
  426. {
  427. RenderTexture temp = RenderTexture.GetTemporary(inputTex.width, inputTex.height, 0, RenderTextureFormat.ARGB32);
  428. Graphics.Blit(inputTex, temp);
  429. bool ret = SaveRenderTextureToPNG(temp, save_file_name);
  430. RenderTexture.ReleaseTemporary(temp);
  431. return ret;
  432. }
  433. //将RenderTexture保存成一张png图片
  434. public static bool SaveRenderTextureToPNG(RenderTexture rt, string save_file_name)
  435. {
  436. RenderTexture prev = RenderTexture.active;
  437. RenderTexture.active = rt;
  438. Texture2D png = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
  439. png.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
  440. byte[] bytes = png.EncodeToPNG();
  441. string directory = Path.GetDirectoryName(save_file_name);
  442. if (!Directory.Exists(directory))
  443. Directory.CreateDirectory(directory);
  444. FileStream file = File.Open(save_file_name, FileMode.Create);
  445. BinaryWriter writer = new BinaryWriter(file);
  446. writer.Write(bytes);
  447. file.Close();
  448. Texture2D.DestroyImmediate(png);
  449. png = null;
  450. RenderTexture.active = prev;
  451. return true;
  452. }
  453. public static Texture2D LoadTextureInLocal(string file_path)
  454. {
  455. //创建文件读取流
  456. FileStream fileStream = new FileStream(file_path, FileMode.Open, FileAccess.Read);
  457. fileStream.Seek(0, SeekOrigin.Begin);
  458. //创建文件长度缓冲区
  459. byte[] bytes = new byte[fileStream.Length];
  460. //读取文件
  461. fileStream.Read(bytes, 0, (int)fileStream.Length);
  462. //释放文件读取流
  463. fileStream.Close();
  464. fileStream.Dispose();
  465. fileStream = null;
  466. //创建Texture
  467. int width = 300;
  468. int height = 372;
  469. Texture2D texture = new Texture2D(width, height);
  470. texture.LoadImage(bytes);
  471. return texture;
  472. }
  473. private static Vector2 HalfVec = new Vector2(0.5f, 0.5f);
  474. //加载外部资源为Sprite
  475. public static Sprite LoadSpriteInLocal(string file_path)
  476. {
  477. if (!File.Exists(file_path))
  478. {
  479. Debug.Log("LoadSpriteInLocal() cannot find sprite file : " + file_path);
  480. return null;
  481. }
  482. Texture2D texture = LoadTextureInLocal(file_path);
  483. //创建Sprite
  484. Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), UIEditorHelper.HalfVec);
  485. return sprite;
  486. }
  487. public static Texture GetAssetPreview(GameObject obj)
  488. {
  489. GameObject canvas_obj = null;
  490. GameObject clone = GameObject.Instantiate(obj);
  491. Transform cloneTransform = clone.transform;
  492. bool isUINode = false;
  493. if (cloneTransform is RectTransform)
  494. {
  495. //如果是UGUI节点的话就要把它们放在Canvas下了
  496. canvas_obj = new GameObject("render canvas", typeof(Canvas));
  497. Canvas canvas = canvas_obj.GetComponent<Canvas>();
  498. cloneTransform.SetParent(canvas_obj.transform);
  499. cloneTransform.localPosition = Vector3.zero;
  500. canvas_obj.transform.position = new Vector3(-1000, -1000, -1000);
  501. canvas_obj.layer = 21;//放在21层,摄像机也只渲染此层的,避免混入了奇怪的东西
  502. isUINode = true;
  503. }
  504. else
  505. cloneTransform.position = new Vector3(-1000, -1000, -1000);
  506. Transform[] all = clone.GetComponentsInChildren<Transform>();
  507. foreach (Transform trans in all)
  508. {
  509. trans.gameObject.layer = 21;
  510. }
  511. Bounds bounds = GetBounds(clone);
  512. Vector3 Min = bounds.min;
  513. Vector3 Max = bounds.max;
  514. GameObject cameraObj = new GameObject("render camera");
  515. Camera renderCamera = cameraObj.AddComponent<Camera>();
  516. renderCamera.backgroundColor = new Color(0.8f, 0.8f, 0.8f, 1f);
  517. renderCamera.clearFlags = CameraClearFlags.Color;
  518. renderCamera.cameraType = CameraType.Preview;
  519. renderCamera.cullingMask = 1 << 21;
  520. if (isUINode)
  521. {
  522. cameraObj.transform.position = new Vector3((Max.x + Min.x) / 2f, (Max.y + Min.y) / 2f, cloneTransform.position.z-100);
  523. Vector3 center = new Vector3(cloneTransform.position.x+0.01f, (Max.y + Min.y) / 2f, cloneTransform.position.z);//+0.01f是为了去掉Unity自带的摄像机旋转角度为0的打印,太烦人了
  524. cameraObj.transform.LookAt(center);
  525. renderCamera.orthographic = true;
  526. float width = Max.x - Min.x;
  527. float height = Max.y - Min.y;
  528. float max_camera_size = width > height ? width : height;
  529. renderCamera.orthographicSize = max_camera_size / 2;//预览图要尽量少点空白
  530. }
  531. else
  532. {
  533. cameraObj.transform.position = new Vector3((Max.x + Min.x) / 2f, (Max.y + Min.y) / 2f, Max.z + (Max.z - Min.z));
  534. Vector3 center = new Vector3(cloneTransform.position.x+0.01f, (Max.y + Min.y) / 2f, cloneTransform.position.z);
  535. cameraObj.transform.LookAt(center);
  536. int angle = (int)(Mathf.Atan2((Max.y - Min.y) / 2, (Max.z - Min.z)) * 180 / 3.1415f * 2);
  537. renderCamera.fieldOfView = angle;
  538. }
  539. RenderTexture texture = new RenderTexture(128, 128, 0, RenderTextureFormat.Default);
  540. renderCamera.targetTexture = texture;
  541. Undo.DestroyObjectImmediate(cameraObj);
  542. Undo.PerformUndo();//不知道为什么要删掉再Undo回来后才Render得出来UI的节点,3D节点是没这个问题的,估计是Canvas创建后没那么快有效?
  543. renderCamera.RenderDontRestore();
  544. RenderTexture tex = new RenderTexture(128, 128, 0, RenderTextureFormat.Default);
  545. Graphics.Blit(texture, tex);
  546. Object.DestroyImmediate(canvas_obj);
  547. Object.DestroyImmediate(cameraObj);
  548. return tex;
  549. }
  550. public static Bounds GetBounds(GameObject obj)
  551. {
  552. Vector3 Min = new Vector3(99999, 99999, 99999);
  553. Vector3 Max = new Vector3(-99999, -99999, -99999);
  554. MeshRenderer[] renders = obj.GetComponentsInChildren<MeshRenderer>();
  555. if (renders.Length > 0)
  556. {
  557. for (int i = 0; i < renders.Length; i++)
  558. {
  559. if (renders[i].bounds.min.x < Min.x)
  560. Min.x = renders[i].bounds.min.x;
  561. if (renders[i].bounds.min.y < Min.y)
  562. Min.y = renders[i].bounds.min.y;
  563. if (renders[i].bounds.min.z < Min.z)
  564. Min.z = renders[i].bounds.min.z;
  565. if (renders[i].bounds.max.x > Max.x)
  566. Max.x = renders[i].bounds.max.x;
  567. if (renders[i].bounds.max.y > Max.y)
  568. Max.y = renders[i].bounds.max.y;
  569. if (renders[i].bounds.max.z > Max.z)
  570. Max.z = renders[i].bounds.max.z;
  571. }
  572. }
  573. else
  574. {
  575. RectTransform[] rectTrans = obj.GetComponentsInChildren<RectTransform>();
  576. Vector3[] corner = new Vector3[4];
  577. for (int i = 0; i < rectTrans.Length; i++)
  578. {
  579. //获取节点的四个角的世界坐标,分别按顺序为左下左上,右上右下
  580. rectTrans[i].GetWorldCorners(corner);
  581. if (corner[0].x < Min.x)
  582. Min.x = corner[0].x;
  583. if (corner[0].y < Min.y)
  584. Min.y = corner[0].y;
  585. if (corner[0].z < Min.z)
  586. Min.z = corner[0].z;
  587. if (corner[2].x > Max.x)
  588. Max.x = corner[2].x;
  589. if (corner[2].y > Max.y)
  590. Max.y = corner[2].y;
  591. if (corner[2].z > Max.z)
  592. Max.z = corner[2].z;
  593. }
  594. }
  595. Vector3 center = (Min + Max) / 2;
  596. Vector3 size = new Vector3(Max.x - Min.x, Max.y - Min.y, Max.z - Min.z);
  597. return new Bounds(center, size);
  598. }
  599. //[MenuItem("UIEditor/另存为 ")]
  600. public static void SaveAnotherLayoutMenu()
  601. {
  602. if (Selection.activeGameObject == null)
  603. {
  604. EditorUtility.DisplayDialog("Warning", "I don't know which prefab you want to save", "Ok");
  605. return;
  606. }
  607. LayoutInfo layout = Selection.activeGameObject.GetComponentInParent<LayoutInfo>();
  608. if (layout != null)
  609. {
  610. GameObject editingView = layout.EditingView;
  611. if (editingView != null)
  612. {
  613. UIEditorHelper.SaveAnotherLayout(layout.GetComponent<Canvas>(), editingView.transform);
  614. }
  615. }
  616. // for (int i = 0; i < layout.transform.childCount; i++)
  617. // {
  618. // Transform child = layout.transform.GetChild(i);
  619. // if (child.GetComponent<Decorate>() != null)
  620. // continue;
  621. // GameObject child_obj = child.gameObject;
  622. // //Debug.Log("child type :" + PrefabUtility.GetPrefabType(child_obj));
  623. // //判断选择的物体,是否为预设
  624. // PrefabType cur_prefab_type = PrefabUtility.GetPrefabType(child_obj);
  625. // UIEditorHelper.SaveAnotherLayout(layout, child);
  626. // break;
  627. // }
  628. }
  629. public static void SaveAnotherLayout(Canvas layout, Transform child)
  630. {
  631. if (child.GetComponent<Decorate>() != null)
  632. return;
  633. GameObject child_obj = child.gameObject;
  634. //Debug.Log("child type :" + PrefabUtility.GetPrefabType(child_obj));
  635. //判断选择的物体,是否为预设
  636. PrefabType cur_prefab_type = PrefabUtility.GetPrefabType(child_obj);
  637. //不是预设的话说明还没保存过的,弹出保存框
  638. string default_path = PathSaver.GetInstance().GetLastPath(PathType.SaveLayout);
  639. string save_path = EditorUtility.SaveFilePanel("Save Layout", default_path, "prefab_name", "prefab");
  640. if (save_path == "")
  641. return;
  642. string full_path = save_path;
  643. PathSaver.GetInstance().SetLastPath(PathType.SaveLayout, save_path);
  644. save_path = FileUtil.GetProjectRelativePath(save_path);
  645. if (save_path == "")
  646. {
  647. Debug.Log("wrong path to save layout, is this project path? : " + full_path);
  648. EditorUtility.DisplayDialog("error", "wrong path to save layout, is this project path? : " + full_path, "ok");
  649. return;
  650. }
  651. Object new_prefab = PrefabUtility.CreateEmptyPrefab(save_path);
  652. PrefabUtility.ReplacePrefab(child_obj, new_prefab, ReplacePrefabOptions.ConnectToPrefab);
  653. LayoutInfo layoutInfo = layout.GetComponent<LayoutInfo>();
  654. if (layoutInfo != null)
  655. layoutInfo.LayoutPath = full_path;
  656. string just_name = System.IO.Path.GetFileNameWithoutExtension(save_path);
  657. child_obj.name = just_name;
  658. layout.gameObject.name = just_name + "_Canvas";
  659. //刷新
  660. AssetDatabase.Refresh();
  661. if (Configure.IsShowDialogWhenSaveLayout)
  662. EditorUtility.DisplayDialog("Tip", "Save Succeed!", "Ok");
  663. //保存时先记录一下,如果是运行游戏时保存了,结束游戏时就要重新加载界面了,不然会重置回运行游戏前的
  664. ReloadLayoutOnExitGame reloadCom = layout.GetComponent<ReloadLayoutOnExitGame>();
  665. if (reloadCom)
  666. reloadCom.SetHadSaveOnRunTime(true);
  667. Debug.Log("Save Succeed!");
  668. layoutInfo.SaveToConfigFile();
  669. }
  670. //[MenuItem("UIEditor/保存 " + Configure.ShortCut.SaveUIPrefab, false, 2)]
  671. public static void SaveLayout(GameObject o, bool isQuiet)
  672. {
  673. GameObject saveObj = o == null ? Selection.activeGameObject : (o as GameObject);
  674. if (saveObj == null)
  675. {
  676. EditorUtility.DisplayDialog("Warning", "I don't know which prefab you want to save", "Ok");
  677. return;
  678. }
  679. Canvas layout = saveObj.GetComponentInParent<Canvas>();
  680. if (layout == null)
  681. {
  682. EditorUtility.DisplayDialog("Warning", "select any layout below UITestNode/canvas to save", "Ok");
  683. return;
  684. }
  685. Transform real_layout = GetRealLayout(saveObj);
  686. if (real_layout != null)
  687. {
  688. GameObject child_obj = real_layout.gameObject;
  689. //判断选择的物体,是否为预设
  690. PrefabType cur_prefab_type = PrefabUtility.GetPrefabType(child_obj);
  691. if (PrefabUtility.GetPrefabType(child_obj) == PrefabType.PrefabInstance || cur_prefab_type == PrefabType.DisconnectedPrefabInstance)
  692. {
  693. UnityEngine.Object parentObject = PrefabUtility.GetCorrespondingObjectFromSource(child_obj);
  694. //替换预设,Note:只能用ConnectToPrefab,不然会重复加多几个同名控件的
  695. PrefabUtility.ReplacePrefab(child_obj, parentObject, ReplacePrefabOptions.Default);
  696. //刷新
  697. AssetDatabase.Refresh();
  698. if (Configure.IsShowDialogWhenSaveLayout && !isQuiet)
  699. EditorUtility.DisplayDialog("Tip", "Save Succeed!", "Ok");
  700. //保存时先记录一下,如果是运行游戏时保存了,结束游戏时就要重新加载界面了,不然会重置回运行游戏前的
  701. ReloadLayoutOnExitGame reloadCom = layout.GetComponent<ReloadLayoutOnExitGame>();
  702. if (reloadCom)
  703. reloadCom.SetHadSaveOnRunTime(true);
  704. Debug.Log("Save Succeed!");
  705. LayoutInfo layoutInfo = layout.GetComponent<LayoutInfo>();
  706. if (layoutInfo != null)
  707. layoutInfo.SaveToConfigFile();
  708. }
  709. else
  710. {
  711. UIEditorHelper.SaveAnotherLayout(layout, real_layout);
  712. }
  713. }
  714. else
  715. {
  716. Debug.Log("save failed!are you select any widget below canvas?");
  717. }
  718. }
  719. static public string ObjectToGUID(UnityEngine.Object obj)
  720. {
  721. string path = AssetDatabase.GetAssetPath(obj);
  722. return (!string.IsNullOrEmpty(path)) ? AssetDatabase.AssetPathToGUID(path) : null;
  723. }
  724. static MethodInfo s_GetInstanceIDFromGUID;
  725. static public UnityEngine.Object GUIDToObject(string guid)
  726. {
  727. if (string.IsNullOrEmpty(guid)) return null;
  728. if (s_GetInstanceIDFromGUID == null)
  729. s_GetInstanceIDFromGUID = typeof(AssetDatabase).GetMethod("GetInstanceIDFromGUID", BindingFlags.Static | BindingFlags.NonPublic);
  730. int id = (int)s_GetInstanceIDFromGUID.Invoke(null, new object[] { guid });
  731. if (id != 0) return EditorUtility.InstanceIDToObject(id);
  732. string path = AssetDatabase.GUIDToAssetPath(guid);
  733. if (string.IsNullOrEmpty(path)) return null;
  734. return AssetDatabase.LoadAssetAtPath(path, typeof(UnityEngine.Object));
  735. }
  736. static public T GUIDToObject<T>(string guid) where T : UnityEngine.Object
  737. {
  738. UnityEngine.Object obj = GUIDToObject(guid);
  739. if (obj == null) return null;
  740. System.Type objType = obj.GetType();
  741. if (objType == typeof(T) || objType.IsSubclassOf(typeof(T))) return obj as T;
  742. if (objType == typeof(GameObject) && typeof(T).IsSubclassOf(typeof(Component)))
  743. {
  744. GameObject go = obj as GameObject;
  745. return go.GetComponent(typeof(T)) as T;
  746. }
  747. return null;
  748. }
  749. static public void SetEnum(string name, System.Enum val)
  750. {
  751. EditorPrefs.SetString(name, val.ToString());
  752. }
  753. static public T GetEnum<T>(string name, T defaultValue)
  754. {
  755. string val = EditorPrefs.GetString(name, defaultValue.ToString());
  756. string[] names = System.Enum.GetNames(typeof(T));
  757. System.Array values = System.Enum.GetValues(typeof(T));
  758. for (int i = 0; i < names.Length; ++i)
  759. {
  760. if (names[i] == val)
  761. return (T)values.GetValue(i);
  762. }
  763. return defaultValue;
  764. }
  765. static public void DrawTiledTexture(Rect rect, Texture tex)
  766. {
  767. GUI.BeginGroup(rect);
  768. {
  769. int width = Mathf.RoundToInt(rect.width);
  770. int height = Mathf.RoundToInt(rect.height);
  771. for (int y = 0; y < height; y += tex.height)
  772. {
  773. for (int x = 0; x < width; x += tex.width)
  774. {
  775. GUI.DrawTexture(new Rect(x, y, tex.width, tex.height), tex);
  776. }
  777. }
  778. }
  779. GUI.EndGroup();
  780. }
  781. static Texture2D CreateCheckerTex(Color c0, Color c1)
  782. {
  783. Texture2D tex = new Texture2D(16, 16);
  784. tex.name = "[Generated] Checker Texture";
  785. tex.hideFlags = HideFlags.DontSave;
  786. for (int y = 0; y < 8; ++y) for (int x = 0; x < 8; ++x) tex.SetPixel(x, y, c1);
  787. for (int y = 8; y < 16; ++y) for (int x = 0; x < 8; ++x) tex.SetPixel(x, y, c0);
  788. for (int y = 0; y < 8; ++y) for (int x = 8; x < 16; ++x) tex.SetPixel(x, y, c0);
  789. for (int y = 8; y < 16; ++y) for (int x = 8; x < 16; ++x) tex.SetPixel(x, y, c1);
  790. tex.Apply();
  791. tex.filterMode = FilterMode.Point;
  792. return tex;
  793. }
  794. static Texture2D mBackdropTex;
  795. static public Texture2D backdropTexture
  796. {
  797. get
  798. {
  799. if (mBackdropTex == null) mBackdropTex = CreateCheckerTex(
  800. new Color(0.1f, 0.1f, 0.1f, 0.5f),
  801. new Color(0.2f, 0.2f, 0.2f, 0.5f));
  802. return mBackdropTex;
  803. }
  804. }
  805. static private Transform GetGoodContainer(Transform trans)
  806. {
  807. if (trans == null)
  808. return null;
  809. if (trans.GetComponent<Canvas>() != null || trans.GetComponent<Decorate>() != null)
  810. return GetRealLayout(trans.gameObject);
  811. return trans;
  812. }
  813. static public void AddImageComponent()
  814. {
  815. if (Selection.activeGameObject == null)
  816. return;
  817. Image old_img = Selection.activeGameObject.GetComponent<Image>();
  818. if (old_img != null)
  819. {
  820. bool isOk = EditorUtility.DisplayDialog("警告", "该GameObject已经有Image组件了,你想替换吗?", "来吧", "算了");
  821. if (isOk)
  822. {
  823. //Selection.activeGameObject.
  824. }
  825. }
  826. Image img = Selection.activeGameObject.AddComponent<Image>();
  827. img.raycastTarget = false;
  828. }
  829. static public void AddHorizontalLayoutComponent()
  830. {
  831. if (Selection.activeGameObject == null)
  832. return;
  833. HorizontalLayoutGroup layout = Selection.activeGameObject.AddComponent<HorizontalLayoutGroup>();
  834. layout.childForceExpandWidth = false;
  835. layout.childForceExpandHeight = false;
  836. layout.childControlWidth = false;
  837. layout.childControlHeight = false;
  838. }
  839. static public void AddVerticalLayoutComponent()
  840. {
  841. if (Selection.activeGameObject == null)
  842. return;
  843. VerticalLayoutGroup layout = Selection.activeGameObject.AddComponent<VerticalLayoutGroup>();
  844. layout.childForceExpandWidth = false;
  845. layout.childForceExpandHeight = false;
  846. layout.childControlWidth = false;
  847. layout.childControlHeight = false;
  848. }
  849. static public void AddGridLayoutGroupComponent()
  850. {
  851. if (Selection.activeGameObject == null)
  852. return;
  853. GridLayoutGroup layout = Selection.activeGameObject.AddComponent<GridLayoutGroup>();
  854. }
  855. static public void CreateEmptyObj()
  856. {
  857. if (Selection.activeGameObject == null)
  858. return;
  859. GameObject go = new GameObject(CommonHelper.GenerateUniqueName(Selection.activeGameObject, "GameObject"), typeof(RectTransform));
  860. go.transform.SetParent(GetGoodContainer(Selection.activeTransform), false);
  861. Selection.activeGameObject = go;
  862. }
  863. static public void CreateImageObj()
  864. {
  865. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  866. {
  867. GameObject go = new GameObject(CommonHelper.GenerateUniqueName(Selection.activeGameObject, "Image"), typeof(Image));
  868. go.GetComponent<Image>().raycastTarget = false;
  869. go.transform.SetParent(GetGoodContainer(Selection.activeTransform), false);
  870. Selection.activeGameObject = go;
  871. }
  872. }
  873. static public void CreateRawImageObj()
  874. {
  875. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  876. {
  877. GameObject go = new GameObject(CommonHelper.GenerateUniqueName(Selection.activeGameObject, "RawImage"), typeof(RawImage));
  878. go.GetComponent<RawImage>().raycastTarget = false;
  879. go.transform.SetParent(GetGoodContainer(Selection.activeTransform), false);
  880. Selection.activeGameObject = go;
  881. }
  882. }
  883. static public void CreateButtonObj()
  884. {
  885. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  886. {
  887. Transform last_trans = Selection.activeTransform;
  888. bool isOk = EditorApplication.ExecuteMenuItem("GameObject/UI/Button");
  889. if (isOk)
  890. {
  891. Selection.activeGameObject.name = CommonHelper.GenerateUniqueName(Selection.activeGameObject, "Button");
  892. Selection.activeTransform.SetParent(GetGoodContainer(last_trans), false);
  893. }
  894. }
  895. }
  896. static public void CreateTextObj()
  897. {
  898. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  899. {
  900. GameObject go = new GameObject(CommonHelper.GenerateUniqueName(Selection.activeGameObject, "Text"), typeof(Text));
  901. Text txt = go.GetComponent<Text>();
  902. txt.raycastTarget = false;
  903. txt.text = "I am a Text";
  904. go.transform.SetParent(GetGoodContainer(Selection.activeTransform), false);
  905. go.transform.localPosition = Vector3.zero;
  906. Selection.activeGameObject = go;
  907. }
  908. }
  909. static public void CreateAdaptiveTextObj()
  910. {
  911. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  912. {
  913. GameObject go = new GameObject(CommonHelper.GenerateUniqueName(Selection.activeGameObject, "AdaptiveText"), typeof(AdaptiveText));
  914. AdaptiveText txt = go.GetComponent<AdaptiveText>();
  915. txt.raycastTarget = false;
  916. txt.need_adaptive = true;
  917. txt.text = "I am a Text";
  918. go.transform.SetParent(GetGoodContainer(Selection.activeTransform), false);
  919. go.transform.localPosition = Vector3.zero;
  920. Selection.activeGameObject = go;
  921. }
  922. }
  923. static private void InitScrollView(bool isHorizontal)
  924. {
  925. ScrollRect scroll = Selection.activeTransform.GetComponent<ScrollRect>();
  926. if (scroll==null)
  927. return;
  928. Image img = Selection.activeTransform.GetComponent<Image>();
  929. if (img != null)
  930. Object.DestroyImmediate(img);
  931. scroll.horizontal = isHorizontal;
  932. scroll.vertical = !isHorizontal;
  933. scroll.horizontalScrollbar = null;
  934. scroll.verticalScrollbar = null;
  935. Transform horizontalObj = Selection.activeTransform.Find("Scrollbar Horizontal");
  936. if (horizontalObj != null)
  937. GameObject.DestroyImmediate(horizontalObj.gameObject);
  938. Transform verticalObj = Selection.activeTransform.Find("Scrollbar Vertical");
  939. if (verticalObj != null)
  940. GameObject.DestroyImmediate(verticalObj.gameObject);
  941. RectTransform viewPort = Selection.activeTransform.Find("Viewport") as RectTransform;
  942. if (viewPort != null)
  943. {
  944. viewPort.offsetMin = new Vector2(0, 0);
  945. viewPort.offsetMax = new Vector2(0, 0);
  946. }
  947. }
  948. static public void CreateHScrollViewObj()
  949. {
  950. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  951. {
  952. Transform last_trans = Selection.activeTransform;
  953. bool isOk = EditorApplication.ExecuteMenuItem("GameObject/UI/Scroll View");
  954. if (isOk)
  955. {
  956. Selection.activeGameObject.name = CommonHelper.GenerateUniqueName(Selection.activeGameObject, "ScrollView");
  957. Selection.activeTransform.SetParent(GetGoodContainer(last_trans), false);
  958. InitScrollView(true);
  959. }
  960. }
  961. }
  962. static public void CreateVScrollViewObj()
  963. {
  964. if (Selection.activeTransform && Selection.activeTransform.GetComponentInParent<Canvas>())
  965. {
  966. Transform last_trans = Selection.activeTransform;
  967. bool isOk = EditorApplication.ExecuteMenuItem("GameObject/UI/Scroll View");
  968. if (isOk)
  969. {
  970. Selection.activeGameObject.name = CommonHelper.GenerateUniqueName(Selection.activeGameObject, "ScrollView");
  971. Selection.activeTransform.SetParent(GetGoodContainer(last_trans), false);
  972. InitScrollView(false);
  973. }
  974. }
  975. }
  976. static public string GenMD5String(string str)
  977. {
  978. System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  979. str = System.BitConverter.ToString(md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str)), 4, 8);
  980. return str.Replace("-", "");
  981. }
  982. public static void SaveAnotherLayoutContextMenu()
  983. {
  984. SaveAnotherLayoutMenu();
  985. }
  986. public static void SaveLayoutForMenu()
  987. {
  988. SaveLayout(null, false);
  989. }
  990. public static void CreatNewLayoutForMenu()
  991. {
  992. CreatNewLayout();
  993. }
  994. public static void ReLoadLayoutForMenu()
  995. {
  996. ReLoadLayout(null, false);
  997. }
  998. }
  999. }
  1000. #endif