AtlasUtilityWindow.cs 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  1. namespace AtlasUtility
  2. {
  3. using UnityEditor;
  4. using UnityEngine;
  5. using System;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Reflection;
  10. using System.Collections.Generic;
  11. using Random = UnityEngine.Random;
  12. public class AtlasUtilityWindow : EditorWindow
  13. {
  14. protected class Parameter
  15. {
  16. public int Padding;
  17. public int AtlasSize;
  18. public float ScaleFactor;
  19. public string Path;
  20. public List<string> Pathes;
  21. public PackPlan PackPlan;
  22. public Texture2D Atlas;
  23. public Texture2D EditorTexture;
  24. public List<Texture2D> EditorTextures;
  25. public ScalePlatform ScalePlatform;
  26. public List<Texture2D> TextureList;
  27. public List<VirtualTexture> VirtualTextureList;
  28. }
  29. protected class TextureInfo
  30. {
  31. #region Variable
  32. public int Max
  33. {
  34. get
  35. {
  36. if (Width > Height)
  37. {
  38. return Width;
  39. }
  40. else
  41. {
  42. return Height;
  43. }
  44. }
  45. }
  46. public int Area
  47. {
  48. get { return Width * Height; }
  49. }
  50. public string Name
  51. {
  52. get { return Texture.name; }
  53. }
  54. public Rect Rect
  55. {
  56. get { return new Rect(LowerLeft.x + Padding, LowerLeft.y + Padding, Width - 2 * Padding, Height - 2 * Padding); }
  57. }
  58. public Vector2 LowerLeft;
  59. public Vector2 UpperLeft
  60. {
  61. get { return LowerLeft + new Vector2(0, Height); }
  62. }
  63. public Vector2 LowerRight
  64. {
  65. get { return LowerLeft + new Vector2(Width, 0); }
  66. }
  67. public Vector2 UpperRight
  68. {
  69. get { return LowerLeft + new Vector2(Width, Height); }
  70. }
  71. public Color[] Colors;
  72. public Vector4 Pivot;
  73. public Vector4 Border;
  74. public int Width;
  75. public int Height;
  76. public int RawWidth;
  77. public int RawHeight;
  78. public int Padding;
  79. public string GUID;
  80. public Texture2D Texture;
  81. #endregion
  82. public TextureInfo(int padding, Texture2D texture2D)
  83. {
  84. Texture = texture2D;
  85. string assetPath = AssetDatabase.GetAssetPath(texture2D);
  86. TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(assetPath);
  87. Pivot = textureImporter.spritePivot;
  88. Border = textureImporter.spriteBorder;
  89. GUID = AssetDatabase.AssetPathToGUID(assetPath);
  90. RawWidth = Texture.width;
  91. RawHeight = Texture.height;
  92. object[] args = new object[2];
  93. MethodInfo methodInfo = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
  94. methodInfo.Invoke(textureImporter, args);
  95. int originWidth = (int)args[0];
  96. int originHeight = (int)args[1];
  97. if (RawWidth < originWidth || RawHeight < originHeight)
  98. {
  99. Debug.LogWarning($"注意 {texture2D.name} 将被缩小");
  100. }
  101. if (!textureImporter.isReadable)
  102. {
  103. textureImporter.isReadable = true;
  104. textureImporter.SaveAndReimport();
  105. }
  106. Colors = texture2D.GetPixels(0, 0, RawWidth, RawHeight);
  107. Width = RawWidth + padding * 2;
  108. Height = RawHeight + padding * 2;
  109. Padding = padding;
  110. }
  111. public TextureInfo(int padding, Texture2D texture2D, int width, int height)
  112. {
  113. Width = width + padding * 2;
  114. Height = height + padding * 2;
  115. Padding = padding;
  116. Texture = texture2D;
  117. }
  118. }
  119. protected class Box
  120. {
  121. #region MyRegion
  122. public bool Valid
  123. {
  124. get
  125. {
  126. if (Width > 0 && Height > 0)
  127. {
  128. return true;
  129. }
  130. else
  131. {
  132. return false;
  133. }
  134. }
  135. }
  136. public Vector2 LowerLeft;
  137. public Vector2 UpperLeft
  138. {
  139. get { return LowerLeft + new Vector2(0, Height); }
  140. }
  141. public Vector2 LowerRight
  142. {
  143. get { return LowerLeft + new Vector2(Width, 0); }
  144. }
  145. public Vector2 UpperRight
  146. {
  147. get { return LowerLeft + new Vector2(Width, Height); }
  148. }
  149. public int Width;
  150. public int Height;
  151. #endregion
  152. public Box(int width, int height, Vector2 lowerLeft)
  153. {
  154. Width = width;
  155. Height = height;
  156. LowerLeft = lowerLeft;
  157. }
  158. public bool CanFill(TextureInfo textureInfo)
  159. {
  160. return textureInfo.Width <= Width && textureInfo.Height <= Height;
  161. }
  162. }
  163. protected class JagBox
  164. {
  165. protected class Pair
  166. {
  167. public int Low;
  168. public int High;
  169. public Pair(int low, int high)
  170. {
  171. Low = low;
  172. High = high;
  173. }
  174. }
  175. #region Variable
  176. public bool Valid
  177. {
  178. get
  179. {
  180. if (BoxList.Count == 0)
  181. {
  182. return false;
  183. }
  184. else
  185. {
  186. return true;
  187. }
  188. }
  189. }
  190. public int Width
  191. {
  192. get { return (int)BoxList.MySum(box => box.Width); }
  193. }
  194. public Vector2 UpperRight;
  195. public List<Box> BoxList;
  196. protected Dictionary<Pair, Pair> XCoordDic;
  197. protected Dictionary<Pair, Pair> YCoordDic;
  198. #endregion
  199. public JagBox(List<Box> boxList)
  200. {
  201. BoxList = boxList;
  202. if (boxList.Count == 0)
  203. {
  204. return;
  205. }
  206. UpperRight = boxList.Back(0).UpperRight;
  207. XCoordDic = new Dictionary<Pair, Pair>();
  208. YCoordDic = new Dictionary<Pair, Pair>();
  209. for (int i = 0; i < boxList.Count; i++)
  210. {
  211. Pair xPair = new Pair((int) boxList[i].LowerLeft.x, (int) boxList[i].LowerRight.x);
  212. Pair yPair = new Pair((int) boxList[i].LowerLeft.y, (int) boxList[i].UpperRight.y);
  213. XCoordDic.Add(yPair, xPair);
  214. YCoordDic.Add(xPair, yPair);
  215. }
  216. }
  217. public bool CanFill(TextureInfo textureInfo, ref int startIndex, ref int endIndex)
  218. {
  219. if (textureInfo.Width > Width)
  220. {
  221. return false;
  222. }
  223. endIndex = BoxList.Count - 1;
  224. startIndex = GetStartIndex(textureInfo.Width);
  225. reLoop:
  226. for (int i = startIndex; i <= endIndex; i++)
  227. {
  228. if (BoxList[i].Height < textureInfo.Height)
  229. {
  230. if (startIndex > 0)
  231. {
  232. startIndex--;
  233. endIndex--;
  234. goto reLoop;
  235. }
  236. else
  237. {
  238. return false;
  239. }
  240. }
  241. }
  242. return true;
  243. }
  244. protected int GetStartIndex(int fillWidth)
  245. {
  246. int x = (int)UpperRight.x - fillWidth;
  247. List<Pair> xPairList = YCoordDic.Keys.ToList();
  248. for (int i = xPairList.Count - 1; i >= 0; i--)
  249. {
  250. if (xPairList[i].Low <= x && x <= xPairList[i].High)
  251. {
  252. return i;
  253. }
  254. }
  255. throw new Exception("遇到一个Bug");
  256. }
  257. public List<JagBox> Fill(TextureInfo textureInfo, int startIndex, int endIndex)
  258. {
  259. textureInfo.LowerLeft = BoxList[endIndex].UpperRight + new Vector2(-textureInfo.Width, -textureInfo.Height);
  260. int fillWidth = textureInfo.Width;
  261. int fillHeight = textureInfo.Height;
  262. Box newLeftBox;
  263. Box newDownBox;
  264. List<Box> leftBoxList = new List<Box>();
  265. List<Box> downBoxList = new List<Box>();
  266. if (fillWidth > fillHeight)
  267. {
  268. VerticalSlice(startIndex, endIndex, fillWidth, fillHeight, out newLeftBox, out newDownBox);
  269. }
  270. else
  271. {
  272. HorizontalSlice(startIndex, endIndex, fillWidth, fillHeight, out newLeftBox, out newDownBox);
  273. }
  274. for (int i = 0; i < startIndex; i++)
  275. {
  276. leftBoxList.Add(BoxList[i]);
  277. }
  278. if (newLeftBox.Valid)
  279. {
  280. leftBoxList.Add(newLeftBox);
  281. }
  282. if (newDownBox.Valid)
  283. {
  284. downBoxList.Add(newDownBox);
  285. }
  286. for (int i = startIndex + 1; i < endIndex; i++)
  287. {
  288. downBoxList.Add(new Box(BoxList[i].Width, BoxList[i].Height - fillHeight, BoxList[i].LowerLeft));
  289. }
  290. JagBox leftJagBox = new JagBox(leftBoxList);
  291. JagBox downJagBox = new JagBox(downBoxList);
  292. List<JagBox> jagBoxList = new List<JagBox>();
  293. if (downJagBox.Valid)
  294. {
  295. jagBoxList.Add(downJagBox);
  296. }
  297. if (leftJagBox.Valid)
  298. {
  299. jagBoxList.Add(leftJagBox);
  300. }
  301. return jagBoxList;
  302. }
  303. protected void VerticalSlice(int startIndex, int endIndex, int fillWidth, int fillHeight, out Box newLeftBox, out Box newDownBox)
  304. {
  305. Box endBox = BoxList[endIndex];
  306. Box startBox = BoxList[startIndex];
  307. int relativeFillWidth = (int) (fillWidth - (endBox.UpperRight.x - startBox.UpperRight.x));
  308. int leftBoxWidth = startBox.Width - relativeFillWidth;
  309. int leftBoxHeight = startBox.Height;
  310. Vector2 leftBoxLowerLeft = startBox.LowerLeft;
  311. newLeftBox = new Box(leftBoxWidth, leftBoxHeight, leftBoxLowerLeft);
  312. int downBoxWidth = relativeFillWidth;
  313. int downBoxHeight = startBox.Height - fillHeight;
  314. Vector2 downBoxLowerLeft = startBox.LowerLeft + new Vector2(startBox.Width - relativeFillWidth, 0);
  315. newDownBox = new Box(downBoxWidth, downBoxHeight, downBoxLowerLeft);
  316. }
  317. protected void HorizontalSlice(int startIndex, int endIndex, int fillWidth, int fillHeight, out Box newLeftBox, out Box newDownBox)
  318. {
  319. Box endBox = BoxList[endIndex];
  320. Box startBox = BoxList[startIndex];
  321. int relativeFillWidth = (int)(fillWidth - (endBox.UpperRight.x - startBox.UpperRight.x));
  322. int leftBoxWidth = startBox.Width - relativeFillWidth;
  323. int leftBoxHeight = fillHeight;
  324. Vector2 leftBoxLowerLeft = startBox.LowerLeft + new Vector2(0, startBox.Height - fillHeight);
  325. newLeftBox = new Box(leftBoxWidth, leftBoxHeight, leftBoxLowerLeft);
  326. int downBoxWidth = startBox.Width;
  327. int downBoxHeight = startBox.Height - fillHeight;
  328. Vector2 downBoxLowerLeft = startBox.LowerLeft;
  329. newDownBox = new Box(downBoxWidth, downBoxHeight, downBoxLowerLeft);
  330. }
  331. }
  332. protected class Atlas
  333. {
  334. #region Variable
  335. public int Width;
  336. public int Height;
  337. public string AssetBundleName;
  338. public string AssetBundleVariant;
  339. public List<TextureInfo> TextureInfoList;
  340. #endregion
  341. public void Create(int index, Parameter parameter)
  342. {
  343. SpriteMetaData[] spriteMetaDatas = new SpriteMetaData[TextureInfoList.Count];
  344. Color[] atlasColors = new Color[Width * Height];
  345. for (int i = 0; i < TextureInfoList.Count; i++)
  346. {
  347. TextureInfo textureInfo = TextureInfoList[i];
  348. Vector2 lowerLeft = textureInfo.LowerLeft + new Vector2(parameter.Padding, parameter.Padding);
  349. spriteMetaDatas[i].rect = textureInfo.Rect;
  350. spriteMetaDatas[i].pivot = textureInfo.Pivot;
  351. spriteMetaDatas[i].name = textureInfo.Name;
  352. spriteMetaDatas[i].border = textureInfo.Border;
  353. spriteMetaDatas[i].alignment = (int)SpriteAlignment.Custom;
  354. for (int j = 0; j < textureInfo.RawHeight; j++)
  355. {
  356. for (int k = 0; k < textureInfo.RawWidth; k++)
  357. {
  358. int row = (int)lowerLeft.y + j;
  359. int column = (int)lowerLeft.x + k;
  360. atlasColors[row * Width + column] = textureInfo.Colors[j * textureInfo.RawWidth + k];
  361. }
  362. }
  363. }
  364. string path = index == 0 ? parameter.Path + ".png" : $"{parameter.Path} ({index}).png";
  365. if (File.Exists(path))
  366. {
  367. TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(path);
  368. AssetBundleName = importer.assetBundleName;
  369. AssetBundleVariant = importer.assetBundleVariant;
  370. AssetDatabase.DeleteAsset(path);
  371. AssetDatabase.Refresh();
  372. }
  373. Texture2D texture2D = new Texture2D(Width, Height, TextureFormat.RGBA32, false);
  374. texture2D.SetPixels(atlasColors);
  375. texture2D.Apply();
  376. File.WriteAllBytes(path, texture2D.EncodeToPNG());
  377. AssetDatabase.ImportAsset(path);
  378. TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(path);
  379. if (!string.IsNullOrEmpty(AssetBundleName))
  380. {
  381. textureImporter.assetBundleName = AssetBundleName;
  382. }
  383. if (!string.IsNullOrEmpty(AssetBundleVariant))
  384. {
  385. textureImporter.assetBundleVariant = AssetBundleVariant;
  386. }
  387. textureImporter.spritesheet = spriteMetaDatas;
  388. textureImporter.maxTextureSize = Mathf.Max(Width, Height);
  389. textureImporter.isReadable = true;
  390. textureImporter.alphaIsTransparency = true;
  391. textureImporter.textureType = TextureImporterType.Sprite;
  392. textureImporter.spriteImportMode = SpriteImportMode.Multiple;
  393. textureImporter.SaveAndReimport();
  394. string atlasGUID = AssetDatabase.AssetPathToGUID(path);
  395. List<AtlasReferencePair> referencePairList = new List<AtlasReferencePair>();
  396. for (int i = 0; i < spriteMetaDatas.Length; i++)
  397. {
  398. AtlasReference atlasReference = new AtlasReference((21300000 + i * 2).ToString(), atlasGUID);
  399. AtlasReference sourceAtlasReference = new AtlasReference("21300000", TextureInfoList[i].GUID);
  400. referencePairList.Add(new AtlasReferencePair(atlasReference, sourceAtlasReference));
  401. }
  402. AtlasReferenceTable.WriteAllLine(referencePairList, true);
  403. }
  404. }
  405. #region Variable
  406. protected AtlasUtility Instance;
  407. protected SerializedObject SerializedObject;
  408. protected Vector2 ScrollPosition;
  409. protected GUIStyle TitleGuiStyle;
  410. protected SerializedProperty PackSize;
  411. protected SerializedProperty packPlan;
  412. protected SerializedProperty PackPath;
  413. protected SerializedProperty PackAtlas;
  414. protected SerializedProperty PackName;
  415. protected SerializedProperty PackPadding;
  416. protected SerializedProperty TextureList;
  417. protected SerializedProperty VirtualTextureList;
  418. protected SerializedProperty SlicePath;
  419. protected SerializedProperty SliceAtlas;
  420. protected SerializedProperty SlicePadding;
  421. protected SerializedProperty SearchTarget;
  422. protected SerializedProperty PlatformSet;
  423. protected SerializedProperty ScalePadding;
  424. protected SerializedProperty ScaleFactor;
  425. protected SerializedProperty ScalePath;
  426. protected SerializedProperty ScaleName;
  427. protected SerializedProperty MobileTexture;
  428. protected SerializedProperty DesktopTexture;
  429. protected SerializedProperty EditorTexture;
  430. protected SerializedProperty LastEditorTexture;
  431. protected SerializedProperty EditorTextures;
  432. protected SerializedProperty ScalePlatform;
  433. #endregion
  434. [MenuItem("DashGame/AtlasUtility")]
  435. protected static void ShowWindow()
  436. {
  437. Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll");
  438. AtlasUtilityWindow window = GetWindow<AtlasUtilityWindow>(inspectorType);
  439. window.titleContent = new GUIContent("AtlasUtility");
  440. window.Show();
  441. }
  442. protected void OnEnable()
  443. {
  444. Instance = InstanceManager.SearchInstance<AtlasUtility>();
  445. SerializedObject = new SerializedObject(Instance);
  446. PackSize = SerializedObject.FindProperty("PackSize");
  447. PackPath = SerializedObject.FindProperty("PackPath");
  448. PackName = SerializedObject.FindProperty("PackName");
  449. SlicePath = SerializedObject.FindProperty("SlicePath");
  450. SlicePadding = SerializedObject.FindProperty("SlicePadding");
  451. PackAtlas = SerializedObject.FindProperty("PackAtlas");
  452. SearchTarget = SerializedObject.FindProperty("SearchTarget");
  453. TextureList = SerializedObject.FindProperty("TextureList");
  454. SliceAtlas = SerializedObject.FindProperty("SliceAtlas");
  455. PackPadding = SerializedObject.FindProperty("PackPadding");
  456. VirtualTextureList = SerializedObject.FindProperty("VirtualTextureList");
  457. packPlan = SerializedObject.FindProperty("PackPlan");
  458. PlatformSet = SerializedObject.FindProperty("PlatformSet");
  459. ScalePadding = SerializedObject.FindProperty("ScalePadding");
  460. ScaleFactor = SerializedObject.FindProperty("ScaleFactor");
  461. ScalePath = SerializedObject.FindProperty("ScalePath");
  462. ScaleName = SerializedObject.FindProperty("ScaleName");
  463. MobileTexture = SerializedObject.FindProperty("MobileTexture");
  464. DesktopTexture = SerializedObject.FindProperty("DesktopTexture");
  465. EditorTexture = SerializedObject.FindProperty("EditorTexture");
  466. EditorTextures = SerializedObject.FindProperty("EditorTextures");
  467. LastEditorTexture = SerializedObject.FindProperty("LastEditorTexture");
  468. ScalePlatform = SerializedObject.FindProperty("ScalePlatform");
  469. TitleGuiStyle = new GUIStyle
  470. {
  471. fontSize = 20,
  472. alignment = TextAnchor.MiddleCenter,
  473. normal = {textColor = new Color(0.75f, 0.75f, 0.75f, 1)}
  474. };
  475. }
  476. protected void Pack()
  477. {
  478. Parameter parameter = CreatePackParameter();
  479. List<TextureInfo> textureInfoList = CreateTextureInfoList(parameter);
  480. if (textureInfoList.Count == 0)
  481. {
  482. throw new Exception("没有可用的Texture");
  483. }
  484. EditorUtility.DisplayProgressBar("打包", "计算排列位置", 0.5f);
  485. List<Atlas> atlasList = new List<Atlas>();
  486. while (textureInfoList.Count > 0)
  487. {
  488. Box box = CreateBox(parameter, textureInfoList);
  489. textureInfoList = FillBox(parameter, box, textureInfoList, atlasList);
  490. }
  491. if (EditorUtility.DisplayDialog("打包", $"将新建{atlasList.Count}张图集", "继续", "取消"))
  492. {
  493. for (int i = 0; i < atlasList.Count; i++)
  494. {
  495. EditorUtility.DisplayProgressBar("打包", "新建图集", (i + 1)/(float) atlasList.Count);
  496. atlasList[i].Create(i, parameter);
  497. }
  498. }
  499. EndPack();
  500. }
  501. protected Parameter CreatePackParameter()
  502. {
  503. string directory = Instance.PackPath.TrimEnd('/', '\\') + "/";
  504. if (directory.Length < 6 || directory.Substring(0, 6).ToLower() != "assets")
  505. {
  506. throw new Exception("PackPath必须位置Assets目录内");
  507. }
  508. if (!Directory.Exists(directory))
  509. {
  510. throw new Exception("文件夹不存在");
  511. }
  512. if (string.IsNullOrEmpty(Instance.PackName) || Instance.PackName.Any(Path.GetInvalidFileNameChars().Contains))
  513. {
  514. throw new Exception("图集名字无效");
  515. }
  516. if (Instance.PackPadding < 0)
  517. {
  518. Instance.PackPadding = 0;
  519. }
  520. if (Instance.PackPlan == PackPlan.Fixed)
  521. {
  522. if (Instance.PackSize <= 2)
  523. {
  524. throw new Exception("图集尺寸必须大于2");
  525. }
  526. if (!Mathf.IsPowerOfTwo(Instance.PackSize))
  527. {
  528. throw new Exception("图集尺寸必须为2次幂");
  529. }
  530. }
  531. else if (Instance.PackPlan == PackPlan.Smallest)
  532. {
  533. if (Instance.PackSize <= 0)
  534. {
  535. Instance.PackSize = 8192;
  536. }
  537. else
  538. {
  539. Instance.PackSize = ExMath.PrevPOT(Instance.PackSize);
  540. }
  541. }
  542. for (int i = 0; i < Instance.TextureList.Count; i++)
  543. {
  544. for (int j = i+1; j < Instance.TextureList.Count; j++)
  545. {
  546. if (Instance.TextureList[i].name == Instance.TextureList[j].name)
  547. {
  548. throw new Exception($"Sprite名字重复 {Instance.TextureList[i].name}");
  549. }
  550. }
  551. }
  552. Parameter parameter = new Parameter
  553. {
  554. Path = directory + Instance.PackName,
  555. PackPlan = Instance.PackPlan,
  556. Padding = Instance.PackPadding,
  557. AtlasSize = Instance.PackSize,
  558. TextureList = Instance.TextureList,
  559. VirtualTextureList = Instance.VirtualTextureList
  560. };
  561. return parameter;
  562. }
  563. protected List<TextureInfo> CreateTextureInfoList(Parameter parameter)
  564. {
  565. List<TextureInfo> textureInfoList = new List<TextureInfo>();
  566. for (int i = 0; i < parameter.TextureList.Count; i++)
  567. {
  568. if (parameter.TextureList[i] != null)
  569. {
  570. EditorUtility.DisplayProgressBar("打包", "读取Texture", (i + 1)/(float) parameter.TextureList.Count);
  571. textureInfoList.Add(new TextureInfo(parameter.Padding, parameter.TextureList[i]));
  572. }
  573. }
  574. for (int i = 0; i < parameter.VirtualTextureList.Count; i++)
  575. {
  576. Texture2D texture = new Texture2D(parameter.VirtualTextureList[i].Width, parameter.VirtualTextureList[i].Height) {name = parameter.VirtualTextureList[i].Name};
  577. Color color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
  578. for (int j = 0; j < parameter.VirtualTextureList[i].Width; j++)
  579. {
  580. for (int k = 0; k < parameter.VirtualTextureList[i].Height; k++)
  581. {
  582. texture.SetPixel(j, k, color);
  583. }
  584. }
  585. texture.Apply();
  586. textureInfoList.Add(new TextureInfo(parameter.Padding, texture, parameter.VirtualTextureList[i].Width, parameter.VirtualTextureList[i].Height));
  587. }
  588. EditorUtility.ClearProgressBar();
  589. return textureInfoList;
  590. }
  591. protected Box CreateBox(Parameter parameter, List<TextureInfo> textureInfoList)
  592. {
  593. int maxTextureLength = (int) textureInfoList.MyMax(info => info.Max);
  594. if (maxTextureLength > parameter.AtlasSize)
  595. {
  596. EndPack();
  597. throw new Exception("一张Texture的宽或高大于了图集尺寸");
  598. }
  599. if (parameter.PackPlan == PackPlan.Fixed)
  600. {
  601. return new Box(parameter.AtlasSize, parameter.AtlasSize, new Vector2(0, 0));
  602. }
  603. else if (parameter.PackPlan == PackPlan.Smallest)
  604. {
  605. int totalArea = textureInfoList.Sum(debris => debris.Area);
  606. int length = ExMath.NextPOT(Mathf.CeilToInt(Mathf.Sqrt(totalArea)));
  607. length = Mathf.Max(length, maxTextureLength);
  608. length = Mathf.Min(length, parameter.AtlasSize);
  609. if (length* length/2f >= totalArea)
  610. {
  611. return new Box(length, length/2, new Vector2(0, 0));
  612. }
  613. else
  614. {
  615. return new Box(length, length, new Vector2(0, 0));
  616. }
  617. }
  618. else
  619. {
  620. throw new Exception();
  621. }
  622. }
  623. protected List<JagBox> CreateJagBox(List<Box> emptyBoxList)
  624. {
  625. if (emptyBoxList.Count == 0)
  626. {
  627. return new List<JagBox>(); ;
  628. }
  629. List<JagBox> jagBoxList = new List<JagBox>();
  630. reLoop :
  631. List<Box> boxList = new List<Box>() {emptyBoxList[0]};
  632. for (int i = 0; i < emptyBoxList.Count - 1; i++)
  633. {
  634. int x1 = (int)emptyBoxList[i].LowerRight.x;
  635. int x2 = (int)emptyBoxList[i + 1].LowerLeft.x;
  636. if (x1 == x2)
  637. {
  638. boxList.Add(emptyBoxList[i + 1]);
  639. emptyBoxList.RemoveAt(i--);
  640. }
  641. else
  642. {
  643. jagBoxList.Add(new JagBox(boxList));
  644. goto reLoop;
  645. }
  646. }
  647. jagBoxList.Add(new JagBox(boxList));
  648. return jagBoxList;
  649. }
  650. protected List<TextureInfo> FillBox(Parameter parameter, Box box, List<TextureInfo> textureInfoList, List<Atlas> atlasList)
  651. {
  652. textureInfoList.MySort((info1, info2) => info1.Width < info2.Width);
  653. while (true)
  654. {
  655. List<Box> emptyBoxList = new List<Box>();
  656. List<TextureInfo> usedTextureInfoList = new List<TextureInfo>();
  657. List<TextureInfo> remainTexureInfoList = new List<TextureInfo>(textureInfoList);
  658. FillChildBox(box, remainTexureInfoList, usedTextureInfoList, emptyBoxList);
  659. List<JagBox> jagBoxList = CreateJagBox(emptyBoxList);
  660. remainTexureInfoList.MySort((info1, info2) => info1.Max < info2.Max);
  661. FillJagBox(jagBoxList, remainTexureInfoList, usedTextureInfoList);
  662. if (remainTexureInfoList.Count == 0)
  663. {
  664. atlasList.Add(CreateAtlas(box, usedTextureInfoList));
  665. return remainTexureInfoList;
  666. }
  667. else
  668. {
  669. if (box.Width > box.Height)
  670. {
  671. box = new Box(box.Height, box.Width, Vector2.zero);
  672. }
  673. else if (box.Height > box.Width)
  674. {
  675. box = new Box(box.Height, box.Height, Vector2.zero);
  676. }
  677. else if (box.Width == box.Height)
  678. {
  679. int newLength = ExMath.NextPOT(box.Width + 1);
  680. if (newLength > parameter.AtlasSize)
  681. {
  682. atlasList.Add(CreateAtlas(box, usedTextureInfoList));
  683. return remainTexureInfoList;
  684. }
  685. else
  686. {
  687. box = new Box(newLength, newLength/2, Vector2.zero);
  688. }
  689. }
  690. }
  691. }
  692. }
  693. protected void FillChildBox(Box box, List<TextureInfo> remainTextureInfoList, List<TextureInfo> usedTextureInfoList, List<Box> emptyBoxList)
  694. {
  695. if (box.Valid)
  696. {
  697. for (int i = 0; i < remainTextureInfoList.Count; i++)
  698. {
  699. if (box.CanFill(remainTextureInfoList[i]))
  700. {
  701. TextureInfo textureInfo = remainTextureInfoList[i];
  702. textureInfo.LowerLeft = box.LowerLeft;
  703. remainTextureInfoList.Remove(textureInfo);
  704. usedTextureInfoList.Add(textureInfo);
  705. Vector2 upChildBoxLowerLeft = box.LowerLeft + new Vector2(0, textureInfo.Height);
  706. Vector2 rightChildBoxLowerLeft = box.LowerLeft + new Vector2(textureInfo.Width, 0);
  707. Box upChildBox = new Box(textureInfo.Width, box.Height - textureInfo.Height, upChildBoxLowerLeft);
  708. Box rightChildBox = new Box(box.Width - textureInfo.Width, box.Height, rightChildBoxLowerLeft);
  709. FillChildBox(upChildBox, remainTextureInfoList, usedTextureInfoList, emptyBoxList);
  710. FillChildBox(rightChildBox, remainTextureInfoList, usedTextureInfoList, emptyBoxList);
  711. return;
  712. }
  713. }
  714. emptyBoxList.Add(box);
  715. }
  716. }
  717. protected void FillJagBox(List<JagBox> jagBoxList, List<TextureInfo> remainTextureInfoList, List<TextureInfo> usedTextureInfoList)
  718. {
  719. for (int i = 0; i < jagBoxList.Count; i++)
  720. {
  721. for (int j = 0; j < remainTextureInfoList.Count; j++)
  722. {
  723. int startIndex = 0;
  724. int endIndex = 0;
  725. if (jagBoxList[i].CanFill(remainTextureInfoList[j], ref startIndex, ref endIndex))
  726. {
  727. jagBoxList.AddRange(jagBoxList[i].Fill(remainTextureInfoList[j], startIndex, endIndex));
  728. usedTextureInfoList.Add(remainTextureInfoList[j]);
  729. remainTextureInfoList.Remove(remainTextureInfoList[j]);
  730. break;
  731. }
  732. }
  733. }
  734. }
  735. protected Atlas CreateAtlas(Box box, List<TextureInfo> textureInfoList)
  736. {
  737. Atlas atlas = new Atlas
  738. {
  739. Width = box.Width,
  740. Height = box.Height,
  741. TextureInfoList = textureInfoList,
  742. };
  743. return atlas;
  744. }
  745. protected void EndPack()
  746. {
  747. EditorUtility.ClearProgressBar();
  748. }
  749. protected void CollectDebugInfo()
  750. {
  751. Parameter parameter = CreateDebugParameter();
  752. List<TextureInfo> textureInfoList = CreateTextureInfoList(parameter);
  753. if (textureInfoList.Count == 0)
  754. {
  755. throw new Exception("没有可用的Texture");
  756. }
  757. StringBuilder stringBuilder = new StringBuilder();
  758. for (int i = 0; i < textureInfoList.Count; i++)
  759. {
  760. stringBuilder.AppendLine($"Width:{textureInfoList[i].Width} Height:{textureInfoList[i].Height} Pivot:{textureInfoList[i].Pivot} Border:{textureInfoList[i].Border}");
  761. }
  762. StreamWriter streamWriter = new StreamWriter(parameter.Path);
  763. streamWriter.WriteLine(Application.unityVersion);
  764. streamWriter.Write(stringBuilder.ToString());
  765. streamWriter.Close();
  766. AssetDatabase.ImportAsset(parameter.Path);
  767. }
  768. protected Parameter CreateDebugParameter()
  769. {
  770. Parameter parameter = new Parameter
  771. {
  772. Path = "Assets/DebugInfo.txt".GetUnRepeatFileName(),
  773. TextureList = Instance.TextureList,
  774. VirtualTextureList = Instance.VirtualTextureList
  775. };
  776. return parameter;
  777. }
  778. protected void Slice()
  779. {
  780. Parameter parameter = CreateSliceParameter();
  781. string spriteSheetPath = AssetDatabase.GetAssetPath(parameter.Atlas);
  782. TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(spriteSheetPath);
  783. if (textureImporter.spritesheet.Length == 0)
  784. {
  785. throw new Exception("该图片不是MultipleSprite");
  786. }
  787. if (!textureImporter.isReadable)
  788. {
  789. textureImporter.isReadable = true;
  790. textureImporter.SaveAndReimport();
  791. }
  792. for (int k = 0; k < textureImporter.spritesheet.Length; k++)
  793. {
  794. SpriteMetaData metaData = textureImporter.spritesheet[k];
  795. EditorUtility.DisplayProgressBar("切图", $"新建 {metaData.name}", (k + 1)/(float) textureImporter.spritesheet.Length);
  796. int width = (int)metaData.rect.width + 2 * parameter.Padding;
  797. int height = (int)metaData.rect.height + 2 * parameter.Padding;
  798. Texture2D texture2D = new Texture2D(width, height);
  799. Color[] originColors = parameter.Atlas.GetPixels((int)metaData.rect.x, (int)metaData.rect.y, (int)metaData.rect.width, (int)metaData.rect.height);
  800. Color[] newColors = new Color[width * height];
  801. for (int i = 0; i < height; i++)
  802. {
  803. for (int j = 0; j < width; j++)
  804. {
  805. if (i < parameter.Padding || j < parameter.Padding || i >= height - parameter.Padding || j >= width - parameter.Padding)
  806. {
  807. newColors[i * width + j] = new Color(0, 0, 0, 0);
  808. }
  809. else
  810. {
  811. int x = i - parameter.Padding;
  812. int y = j - parameter.Padding;
  813. newColors[i * width + j] = originColors[x * (int)metaData.rect.width + y];
  814. }
  815. }
  816. }
  817. texture2D.SetPixels(newColors);
  818. texture2D.Apply();
  819. string spritePath = $"{parameter.Path}{metaData.name}.png".GetUnRepeatFileName();
  820. File.WriteAllBytes(spritePath, texture2D.EncodeToPNG());
  821. AssetDatabase.ImportAsset(spritePath);
  822. TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(spritePath);
  823. TextureImporterSettings importerSetting = new TextureImporterSettings();
  824. importer.ReadTextureSettings(importerSetting);
  825. importerSetting.textureType = TextureImporterType.Sprite;
  826. importerSetting.spritePivot = metaData.pivot;
  827. importerSetting.spriteBorder = metaData.border;
  828. importerSetting.spriteAlignment = metaData.alignment;
  829. importerSetting.alphaIsTransparency = true;
  830. importer.SetTextureSettings(importerSetting);
  831. importer.isReadable = true;
  832. importer.name = metaData.name;
  833. importer.spriteImportMode = SpriteImportMode.Single;
  834. importer.maxTextureSize = ExMath.NextPOT(Mathf.Max(width, height));
  835. importer.SaveAndReimport();
  836. }
  837. EditorUtility.ClearProgressBar();
  838. }
  839. protected Parameter CreateSliceParameter()
  840. {
  841. if (string.IsNullOrEmpty(Instance.SlicePath))
  842. {
  843. throw new Exception("Path不能为空");
  844. }
  845. string directory = Instance.SlicePath.TrimEnd('/', '\\') + "/";
  846. if(string.IsNullOrEmpty(directory) || !Directory.Exists(directory))
  847. {
  848. throw new Exception("文件夹不存在");
  849. }
  850. if (Instance.SlicePadding < 0)
  851. {
  852. Instance.SlicePadding = 0;
  853. }
  854. if (Instance.SliceAtlas == null)
  855. {
  856. throw new Exception("Texture为空");
  857. }
  858. Parameter parameter = new Parameter
  859. {
  860. Path = directory,
  861. Padding = Instance.SlicePadding,
  862. Atlas = Instance.SliceAtlas
  863. };
  864. return parameter;
  865. }
  866. protected void ScaleTextures(Parameter parameter)
  867. {
  868. ScaleTextureBridge(Instance.EditorTexture, parameter);
  869. for (int i = 0; i < Instance.EditorTextures.Count; i++)
  870. {
  871. parameter.Path = parameter.Pathes[i];
  872. ScaleTextureBridge(Instance.EditorTextures[i], parameter);
  873. }
  874. }
  875. protected void ScaleTextureBridge(Texture2D texture, Parameter parameter)
  876. {
  877. if (texture == null)
  878. {
  879. return;
  880. }
  881. ScaleTexture(parameter.Padding, parameter.ScaleFactor, parameter.Path, texture, parameter.ScalePlatform);
  882. }
  883. protected void ScaleTexture(int padding, float scaleFactor, string path, Texture2D editorTexture, ScalePlatform scalePlatform)
  884. {
  885. if (File.Exists(path))
  886. {
  887. Debug.LogError($"{path} 存在同名文件");
  888. return;
  889. }
  890. Texture2D texture = ScaleTextureCore(padding, scaleFactor, editorTexture);
  891. File.WriteAllBytes(path, texture.EncodeToPNG());
  892. AssetDatabase.ImportAsset(path);
  893. TextureImporter sourceTextureImporter = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(editorTexture));
  894. TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(path);
  895. TextureImporterSettings importerSetting = new TextureImporterSettings();
  896. sourceTextureImporter.ReadTextureSettings(importerSetting);
  897. importerSetting.textureType = sourceTextureImporter.textureType;
  898. importerSetting.spritePivot = sourceTextureImporter.spritePivot;
  899. importerSetting.spriteBorder = sourceTextureImporter.spriteBorder*scaleFactor;
  900. importerSetting.alphaIsTransparency = sourceTextureImporter.alphaIsTransparency;
  901. importerSetting.spritePixelsPerUnit = sourceTextureImporter.spritePixelsPerUnit/100 * 100*scaleFactor;
  902. textureImporter.spritePackingTag = sourceTextureImporter.spritePackingTag;
  903. textureImporter.SetTextureSettings(importerSetting);
  904. textureImporter.SaveAndReimport();
  905. List<PlatformReferenceSet> referenceSetList = PlatformReferenceTable.ReadAllLine();
  906. string sourceGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(editorTexture));
  907. string platformGUID = AssetDatabase.AssetPathToGUID(path);
  908. PlatformReferenceSet referenceSet = PlatformReferenceManager.GetMatchedReferenceSet(sourceGUID, referenceSetList);
  909. if (referenceSet == null)
  910. {
  911. referenceSet = new PlatformReferenceSet(editorTexture, platformGUID, scalePlatform);
  912. referenceSetList.Add(referenceSet);
  913. }
  914. else
  915. {
  916. referenceSet.SetPlatformReference(platformGUID, scalePlatform);
  917. }
  918. PlatformReferenceTable.WriteAllLine(referenceSetList);
  919. }
  920. protected Texture2D ScaleTextureCore(int padding, float factor, Texture2D sourceTexture)
  921. {
  922. if (Math.Abs(factor - 1) < 0.001)
  923. {
  924. return sourceTexture.Clone();
  925. }
  926. Texture2D texture = AddPaddingToTexture(padding, sourceTexture);
  927. int originWidth = texture.width;
  928. int originHeight = texture.height;
  929. int newWidth = (int)(originWidth * factor);
  930. int newHeight = (int)(originHeight * factor);
  931. Texture2D newTexture = new Texture2D(newWidth, newHeight);
  932. Color[] newColors = new Color[newWidth * newHeight];
  933. for (int i = 0; i < newHeight; i++)
  934. {
  935. for (int j = 0; j < newWidth; j++)
  936. {
  937. newColors[i * newWidth + j] = texture.GetPixelBilinear((j + 0.5f) / newWidth, (i + 0.5f) / newHeight);
  938. }
  939. }
  940. newTexture.SetPixels(newColors);
  941. return newTexture;
  942. }
  943. protected Texture2D AddPaddingToTexture(int padding, Texture2D texture)
  944. {
  945. if (padding == 0)
  946. {
  947. return texture;
  948. }
  949. int originWidth = texture.width;
  950. int originHeight = texture.height;
  951. int newWidth = originWidth + 2 * padding;
  952. int newHeight = originHeight + 2 * padding;
  953. Texture2D newTexture = new Texture2D(newWidth, newHeight);
  954. Color[] newColors = new Color[newWidth * newHeight];
  955. Color[] originColors = texture.GetPixels();
  956. for (int i = 0; i < originHeight; i++)
  957. {
  958. for (int j = 0; j < originWidth; j++)
  959. {
  960. newColors[(i + padding) * newWidth + (j + padding)] = originColors[i * originWidth + j];
  961. }
  962. }
  963. newTexture.SetPixels(newColors);
  964. return newTexture;
  965. }
  966. protected Parameter CreateScaleParameter()
  967. {
  968. if (string.IsNullOrEmpty(Instance.ScalePath))
  969. {
  970. throw new Exception("Path不能为空");
  971. }
  972. string directory = Instance.ScalePath.TrimEnd('/', '\\') + "/";
  973. if (!Directory.Exists(directory))
  974. {
  975. throw new Exception("文件夹不存在");
  976. }
  977. if (Instance.ScaleFactor <= 0)
  978. {
  979. throw new Exception("Factor必须大于0");
  980. }
  981. if (Instance.ScalePadding < 0)
  982. {
  983. Instance.SlicePadding = 0;
  984. }
  985. List<string> pathes = new List<string>();
  986. for (int i = 0; i < Instance.EditorTextures.Count; i++)
  987. {
  988. if (Instance.EditorTextures[i] == null)
  989. {
  990. Instance.EditorTextures.RemoveAt(i--);
  991. }
  992. else
  993. {
  994. TextureImporter importer1 = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(Instance.EditorTextures[i]));
  995. if (!importer1.isReadable)
  996. {
  997. importer1.isReadable = true;
  998. importer1.SaveAndReimport();
  999. }
  1000. pathes.Add(directory + Instance.EditorTextures[i].name + Instance.ScaleName + ".png");
  1001. }
  1002. }
  1003. if (Instance.EditorTexture == null && Instance.EditorTextures.Count == 0)
  1004. {
  1005. throw new Exception("Editor Texture为空");
  1006. }
  1007. TextureImporter importer2 = (TextureImporter) AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(Instance.EditorTexture));
  1008. if (importer2 != null && !importer2.isReadable)
  1009. {
  1010. importer2.isReadable = true;
  1011. importer2.SaveAndReimport();
  1012. }
  1013. Parameter parameter = new Parameter
  1014. {
  1015. Path = directory + Instance.ScaleName + ".png",
  1016. Pathes = pathes,
  1017. Padding = Instance.SlicePadding,
  1018. ScaleFactor = Instance.ScaleFactor,
  1019. ScalePlatform = Instance.ScalePlatform,
  1020. EditorTexture = Instance.EditorTexture,
  1021. EditorTextures = Instance.EditorTextures,
  1022. };
  1023. return parameter;
  1024. }
  1025. protected void SwitchAtlasPlatform(Platform toPlatform)
  1026. {
  1027. for (int i = 0; i < Instance.PlatformSet.Count; i++)
  1028. {
  1029. SwitchAtlasPlatformCore(Instance.PlatformSet[i], toPlatform);
  1030. }
  1031. }
  1032. protected void SwitchAtlasPlatformCore(PlatformSet platformSet, Platform toPlatform)
  1033. {
  1034. string editorPath = AssetDatabase.GetAssetPath(platformSet.EditorObject);
  1035. string mobilePath = AssetDatabase.GetAssetPath(platformSet.MobileObject);
  1036. string desktopPath = AssetDatabase.GetAssetPath(platformSet.DesktopObject);
  1037. AssetBundleManager.SwitchAssetBundle(editorPath, mobilePath, desktopPath, toPlatform);
  1038. }
  1039. public static void GetSelectedPath(ref string value)
  1040. {
  1041. if (Selection.assetGUIDs.Length > 0)
  1042. {
  1043. string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
  1044. path = Path.GetDirectoryName(path);
  1045. if (string.IsNullOrEmpty(path))
  1046. {
  1047. value = "Assets";
  1048. }
  1049. else
  1050. {
  1051. value = path;
  1052. }
  1053. }
  1054. }
  1055. public static void GetSelectedName(ref string value)
  1056. {
  1057. if (Selection.assetGUIDs.Length > 0)
  1058. {
  1059. string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
  1060. value = Path.GetFileNameWithoutExtension(path);
  1061. }
  1062. }
  1063. protected void OnGUI()
  1064. {
  1065. SerializedObject.Update();
  1066. EditorGUILayout.LabelField("AtlasUtility", TitleGuiStyle, GUILayout.Height(30));
  1067. ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);
  1068. DrawPackAtlasArea();
  1069. DrawSliceAtlasArea();
  1070. DrawSearchReferenceArea();
  1071. DrawReferenceControllArea();
  1072. DrawScaleTextureArea();
  1073. DrawDebugArea();
  1074. EditorGUILayout.EndScrollView();
  1075. SerializedObject.ApplyModifiedProperties();
  1076. }
  1077. protected void DrawPackAtlasArea()
  1078. {
  1079. Instance.PackAtlasFunction = EditorGUILayout.Foldout(Instance.PackAtlasFunction, "Pack Atlas");
  1080. if (!Instance.PackAtlasFunction)
  1081. {
  1082. EditorGUILayout.Separator();
  1083. return;
  1084. }
  1085. EditorGUILayout.Separator();
  1086. EditorGUILayout.BeginHorizontal();
  1087. EditorGUILayout.PropertyField(PackPath, new GUIContent("Path"));
  1088. if (GUILayout.Button("UseSelectedPath", GUILayout.MaxWidth(120)))
  1089. {
  1090. GetSelectedPath(ref Instance.PackPath);
  1091. }
  1092. EditorGUILayout.EndHorizontal();
  1093. EditorGUILayout.BeginHorizontal();
  1094. EditorGUILayout.PropertyField(PackName, new GUIContent("Name"));
  1095. if (GUILayout.Button("UseSelectedName", GUILayout.MaxWidth(120)))
  1096. {
  1097. GetSelectedName(ref Instance.PackName);
  1098. }
  1099. EditorGUILayout.EndHorizontal();
  1100. EditorGUILayout.PropertyField(packPlan, new GUIContent("Plan"));
  1101. if (Instance.PackPlan == PackPlan.Fixed)
  1102. {
  1103. EditorGUILayout.PropertyField(PackSize, new GUIContent("Size"));
  1104. }
  1105. else if (Instance.PackPlan == PackPlan.Smallest)
  1106. {
  1107. EditorGUILayout.PropertyField(PackSize, new GUIContent("Max Size"));
  1108. }
  1109. EditorGUILayout.PropertyField(PackAtlas, new GUIContent("Atlas"));
  1110. if (Instance.PackAtlas != null)
  1111. {
  1112. List<string> childPathList = ReferenceManager.GetChildSpritePath(AssetDatabase.GetAssetPath(Instance.PackAtlas));
  1113. for (int i = 0; i < childPathList.Count; i++)
  1114. {
  1115. Instance.TextureList.Add(AssetDatabase.LoadAssetAtPath<Texture2D>(childPathList[i]));
  1116. }
  1117. Instance.PackAtlas = null;
  1118. }
  1119. EditorGUILayout.PropertyField(PackPadding, new GUIContent("Padding"));
  1120. EditorGUILayout.PropertyField(TextureList, true);
  1121. if (GUILayout.Button("Pack", GUILayout.Height(30)))
  1122. {
  1123. Pack();
  1124. }
  1125. EditorGUILayout.Separator();
  1126. }
  1127. protected void DrawSliceAtlasArea()
  1128. {
  1129. EditorGUILayout.Separator();
  1130. Instance.SliceAtlasFunction = EditorGUILayout.Foldout(Instance.SliceAtlasFunction, "Slice Atlas");
  1131. if (!Instance.SliceAtlasFunction)
  1132. {
  1133. EditorGUILayout.Separator();
  1134. return;
  1135. }
  1136. EditorGUILayout.Separator();
  1137. EditorGUILayout.BeginHorizontal();
  1138. EditorGUILayout.PropertyField(SlicePath, new GUIContent("Path"));
  1139. if (GUILayout.Button("UseSelectedPath"))
  1140. {
  1141. GetSelectedPath(ref Instance.SlicePath);
  1142. }
  1143. EditorGUILayout.EndHorizontal();
  1144. EditorGUILayout.PropertyField(SliceAtlas, new GUIContent("Atlas"));
  1145. EditorGUILayout.PropertyField(SlicePadding, new GUIContent("Padding"));
  1146. if (GUILayout.Button("Slice", GUILayout.Height(30)))
  1147. {
  1148. Slice();
  1149. }
  1150. EditorGUILayout.Separator();
  1151. }
  1152. protected void DrawSearchReferenceArea()
  1153. {
  1154. EditorGUILayout.Separator();
  1155. Instance.SearchReferenceFunction = EditorGUILayout.Foldout(Instance.SearchReferenceFunction, "Search Reference");
  1156. if (!Instance.SearchReferenceFunction)
  1157. {
  1158. EditorGUILayout.Separator();
  1159. return;
  1160. }
  1161. EditorGUILayout.Separator();
  1162. EditorGUILayout.PropertyField(SearchTarget);
  1163. if (GUILayout.Button("SearchReference", GUILayout.Height(30)))
  1164. {
  1165. ReferenceManager.FindReference(AssetDatabase.GetAssetPath(Instance.SearchTarget));
  1166. }
  1167. EditorGUILayout.Separator();
  1168. }
  1169. protected void DrawReferenceControllArea()
  1170. {
  1171. EditorGUILayout.Separator();
  1172. Instance.PlatformControllFunction = EditorGUILayout.Foldout(Instance.PlatformControllFunction, "Platform & Reference Controll");
  1173. if (!Instance.PlatformControllFunction)
  1174. {
  1175. EditorGUILayout.Separator();
  1176. return;
  1177. }
  1178. EditorGUILayout.Separator();
  1179. EditorGUILayout.PropertyField(PlatformSet, true);
  1180. EditorGUILayout.Separator();
  1181. if (GUILayout.Button("Enable Atlas", GUILayout.Height(30)))
  1182. {
  1183. if (EditorUtility.DisplayDialog("注意", "用图集替代Sprite?", "继续", "取消"))
  1184. {
  1185. AtlasReferenceManager.EnableAtlas();
  1186. }
  1187. }
  1188. EditorGUILayout.Separator();
  1189. EditorGUILayout.Separator();
  1190. if (GUILayout.Button("Disable Atlas", GUILayout.Height(30)))
  1191. {
  1192. if (EditorUtility.DisplayDialog("注意", "还原图集到Sprite?", "继续", "取消"))
  1193. {
  1194. AtlasReferenceManager.DisableAtlas();
  1195. }
  1196. }
  1197. EditorGUILayout.Separator();
  1198. EditorGUILayout.Separator();
  1199. if (GUILayout.Button("Switch To Editor Platform", GUILayout.Height(30)))
  1200. {
  1201. if (EditorUtility.DisplayDialog("注意", "切换平台到Editor?(切换平台会Enable Atlas)", "继续", "取消"))
  1202. {
  1203. AssetDatabase.Refresh();
  1204. List<string> fromList = new List<string>();
  1205. List<string> toList = new List<string>();
  1206. AtlasReferenceManager.GetDisableFromToList(fromList, toList);
  1207. PlatformReferenceManager.GetFromToList(Platform.Editor, fromList, toList);
  1208. AtlasReferenceManager.GetEnableFromToList(fromList, toList);
  1209. ReferenceManager.ChangeReference(true, fromList, toList);
  1210. SwitchAtlasPlatform(Platform.Editor);
  1211. }
  1212. }
  1213. EditorGUILayout.Separator();
  1214. EditorGUILayout.Separator();
  1215. if (GUILayout.Button("Switch To Mobile Platform", GUILayout.Height(30)))
  1216. {
  1217. if (EditorUtility.DisplayDialog("注意", "切换平台到Mobile?(切换平台会Enable Atlas)", "继续", "取消"))
  1218. {
  1219. AssetDatabase.Refresh();
  1220. List<string> fromList = new List<string>();
  1221. List<string> toList = new List<string>();
  1222. AtlasReferenceManager.GetDisableFromToList(fromList, toList);
  1223. PlatformReferenceManager.GetFromToList(Platform.Mobile, fromList, toList);
  1224. AtlasReferenceManager.GetEnableFromToList(fromList, toList);
  1225. ReferenceManager.ChangeReference(true, fromList, toList);
  1226. SwitchAtlasPlatform(Platform.Mobile);
  1227. }
  1228. }
  1229. EditorGUILayout.Separator();
  1230. EditorGUILayout.Separator();
  1231. if (GUILayout.Button("Switch To Desktop Platform", GUILayout.Height(30)))
  1232. {
  1233. if (EditorUtility.DisplayDialog("注意", "切换平台到Desktop?(切换平台会Enable Atlas)", "继续", "取消"))
  1234. {
  1235. AssetDatabase.Refresh();
  1236. List<string> fromList = new List<string>();
  1237. List<string> toList = new List<string>();
  1238. AtlasReferenceManager.GetDisableFromToList(fromList, toList);
  1239. PlatformReferenceManager.GetFromToList(Platform.Desktop, fromList, toList);
  1240. AtlasReferenceManager.GetEnableFromToList(fromList, toList);
  1241. ReferenceManager.ChangeReference(true, fromList, toList);
  1242. SwitchAtlasPlatform(Platform.Desktop);
  1243. }
  1244. }
  1245. EditorGUILayout.Separator();
  1246. }
  1247. protected void DrawScaleTextureArea()
  1248. {
  1249. EditorGUILayout.Separator();
  1250. Instance.ScaleTextureFunction = EditorGUILayout.Foldout(Instance.ScaleTextureFunction, "Scale Texture");
  1251. if (!Instance.ScaleTextureFunction)
  1252. {
  1253. EditorGUILayout.Separator();
  1254. return;
  1255. }
  1256. EditorGUILayout.Separator();
  1257. EditorGUILayout.BeginHorizontal();
  1258. EditorGUILayout.PropertyField(ScalePath, new GUIContent("Path"));
  1259. if (GUILayout.Button("UseSelectedPath", GUILayout.MaxWidth(120)))
  1260. {
  1261. GetSelectedPath(ref Instance.ScalePath);
  1262. }
  1263. EditorGUILayout.EndHorizontal();
  1264. EditorGUILayout.PropertyField(ScaleName, new GUIContent("Name & Suffix"));
  1265. EditorGUILayout.PropertyField(ScaleFactor, new GUIContent("Factor"));
  1266. EditorGUILayout.PropertyField(ScalePadding, new GUIContent("Padding"));
  1267. EditorGUILayout.PropertyField(EditorTexture, new GUIContent("Editor Texture"));
  1268. EditorGUILayout.PropertyField(EditorTextures, new GUIContent("Editor Textures"), true);
  1269. if (Instance.EditorTexture != Instance.LastEdiotTexture)
  1270. {
  1271. if (Instance.EditorTexture != null)
  1272. {
  1273. Instance.ScaleName = Instance.EditorTexture.name;
  1274. }
  1275. PlatformReferenceSet referenceSet = PlatformReferenceManager.GetMatchedReferenceSet(Instance.EditorTexture);
  1276. if (referenceSet != null)
  1277. {
  1278. Instance.EditorTexture = referenceSet.EditorTexture;
  1279. Instance.MobileTexture = referenceSet.MobileTexture;
  1280. Instance.DesktopTexture = referenceSet.DesktopTexture;
  1281. }
  1282. else
  1283. {
  1284. Instance.MobileTexture = null;
  1285. Instance.DesktopTexture = null;
  1286. }
  1287. }
  1288. Instance.LastEdiotTexture = Instance.EditorTexture;
  1289. if (Instance.MobileTexture != null)
  1290. {
  1291. EditorGUILayout.BeginHorizontal();
  1292. EditorGUILayout.PropertyField(MobileTexture, new GUIContent("Mobile Texture"));
  1293. EditorGUILayout.EndHorizontal();
  1294. }
  1295. if (Instance.DesktopTexture != null)
  1296. {
  1297. EditorGUILayout.BeginHorizontal();
  1298. EditorGUILayout.PropertyField(DesktopTexture, new GUIContent("Desktop Texture"));
  1299. EditorGUILayout.EndHorizontal();
  1300. }
  1301. EditorGUILayout.PropertyField(ScalePlatform, new GUIContent("Target Platform"));
  1302. if (GUILayout.Button("Scale", GUILayout.Height(30)))
  1303. {
  1304. Parameter parameter = CreateScaleParameter();
  1305. ScaleTextures(parameter);
  1306. }
  1307. EditorGUILayout.Separator();
  1308. }
  1309. protected void DrawDebugArea()
  1310. {
  1311. EditorGUILayout.Separator();
  1312. Instance.DebugFunction = EditorGUILayout.Foldout(Instance.DebugFunction, "Debug");
  1313. if (!Instance.DebugFunction)
  1314. {
  1315. return;
  1316. }
  1317. if (GUILayout.Button("CollectDebugInfo", GUILayout.Height(30)))
  1318. {
  1319. CollectDebugInfo();
  1320. }
  1321. }
  1322. }
  1323. }