PSDImporter.cs 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using PDNWrapper;
  5. using UnityEngine;
  6. using Unity.Collections;
  7. using System.Linq;
  8. using UnityEditor.AssetImporters;
  9. using UnityEditor.U2D.Animation;
  10. using UnityEditor.U2D.Common;
  11. using UnityEditor.U2D.Sprites;
  12. using UnityEngine.Assertions;
  13. using UnityEngine.Experimental.U2D.Animation;
  14. using UnityEngine.U2D;
  15. using UnityEngine.U2D.Animation;
  16. using UnityEngine.Scripting.APIUpdating;
  17. namespace UnityEditor.U2D.PSD
  18. {
  19. /// <summary>
  20. /// ScriptedImporter to import Photoshop files
  21. /// </summary>
  22. // Version using unity release + 5 digit padding for future upgrade. Eg 2021.2 -> 21200000
  23. [ScriptedImporter(20300000, "psb", AllowCaching = true)]
  24. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.psdimporter@latest")]
  25. [MovedFrom("UnityEditor.Experimental.AssetImporters")]
  26. public class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider
  27. {
  28. class UniqueNameGenerator
  29. {
  30. List<int> m_NameHash = new List<int>();
  31. public bool ContainHash(int i)
  32. {
  33. return m_NameHash.Contains(i);
  34. }
  35. public void AddHash(int i)
  36. {
  37. m_NameHash.Add(i);
  38. }
  39. public string GetUniqueName(string name)
  40. {
  41. return PSDImporter.GetUniqueName(name, m_NameHash);
  42. }
  43. }
  44. class GameObjectCreationFactory : UniqueNameGenerator
  45. {
  46. public GameObject CreateGameObject(string name, params System.Type[] components)
  47. {
  48. var newName = GetUniqueName(name);
  49. return new GameObject(newName, components);
  50. }
  51. }
  52. struct BoneGO
  53. {
  54. public GameObject go;
  55. public int index;
  56. }
  57. [SerializeField]
  58. TextureImporterSettings m_TextureImporterSettings = new TextureImporterSettings() {
  59. mipmapEnabled = true,
  60. mipmapFilter = TextureImporterMipFilter.BoxFilter,
  61. sRGBTexture = true,
  62. borderMipmap = false,
  63. mipMapsPreserveCoverage = false,
  64. alphaTestReferenceValue = 0.5f,
  65. readable = false,
  66. #if ENABLE_TEXTURE_STREAMING
  67. streamingMipmaps = true,
  68. #endif
  69. fadeOut = false,
  70. mipmapFadeDistanceStart = 1,
  71. mipmapFadeDistanceEnd = 3,
  72. convertToNormalMap = false,
  73. heightmapScale = 0.25F,
  74. normalMapFilter = 0,
  75. generateCubemap = TextureImporterGenerateCubemap.AutoCubemap,
  76. cubemapConvolution = 0,
  77. seamlessCubemap = false,
  78. npotScale = TextureImporterNPOTScale.ToNearest,
  79. spriteMode = (int)SpriteImportMode.Multiple,
  80. spriteExtrude = 1,
  81. spriteMeshType = SpriteMeshType.Tight,
  82. spriteAlignment = (int)SpriteAlignment.Center,
  83. spritePivot = new Vector2(0.5f, 0.5f),
  84. spritePixelsPerUnit = 100.0f,
  85. spriteBorder = new Vector4(0.0f, 0.0f, 0.0f, 0.0f),
  86. alphaSource = TextureImporterAlphaSource.FromInput,
  87. alphaIsTransparency = true,
  88. spriteTessellationDetail = -1.0f,
  89. textureType = TextureImporterType.Sprite,
  90. textureShape = TextureImporterShape.Texture2D,
  91. filterMode = FilterMode.Bilinear,
  92. aniso = 1,
  93. mipmapBias = 0.0f,
  94. wrapModeU = TextureWrapMode.Repeat,
  95. wrapModeV = TextureWrapMode.Repeat,
  96. wrapModeW = TextureWrapMode.Repeat,
  97. };
  98. [SerializeField]
  99. List<SpriteMetaData> m_SpriteImportData = new List<SpriteMetaData>(); // we use index 0 for single sprite and the rest for multiple sprites
  100. [SerializeField]
  101. List<SpriteMetaData> m_MosaicSpriteImportData = new List<SpriteMetaData>();
  102. [SerializeField]
  103. List<SpriteMetaData> m_RigSpriteImportData = new List<SpriteMetaData>();
  104. [SerializeField]
  105. List<TextureImporterPlatformSettings> m_PlatformSettings = new List<TextureImporterPlatformSettings>();
  106. [SerializeField]
  107. bool m_MosaicLayers = true;
  108. [SerializeField]
  109. Vector2 m_DocumentPivot = Vector2.zero;
  110. [SerializeField]
  111. SpriteAlignment m_DocumentAlignment = SpriteAlignment.BottomCenter;
  112. [SerializeField]
  113. bool m_ImportHiddenLayers = false;
  114. [SerializeField]
  115. int m_ImportedTextureWidth;
  116. [SerializeField]
  117. int m_ImportedTextureHeight;
  118. [SerializeField]
  119. Vector2Int m_DocumentSize;
  120. [SerializeField]
  121. bool m_PaperDollMode = false;
  122. [SerializeField]
  123. bool m_KeepDupilcateSpriteName = false;
  124. [SerializeField]
  125. SpriteCategoryList m_SpriteCategoryList = new SpriteCategoryList() {categories = new List<SpriteCategory>()};
  126. GameObjectCreationFactory m_GameObjectFactory = new GameObjectCreationFactory();
  127. internal SpriteCategoryList spriteCategoryList { get { return m_SpriteCategoryList; } set { m_SpriteCategoryList = value; } }
  128. [SerializeField]
  129. int m_TextureActualWidth;
  130. internal int textureActualWidth
  131. {
  132. get { return m_TextureActualWidth; }
  133. private set { m_TextureActualWidth = value; }
  134. }
  135. [SerializeField]
  136. int m_TextureActualHeight;
  137. internal int textureActualHeight
  138. {
  139. get { return m_TextureActualHeight; }
  140. private set { m_TextureActualHeight = value; }
  141. }
  142. [SerializeField]
  143. string m_SpritePackingTag = "";
  144. [SerializeField]
  145. bool m_ResliceFromLayer = false;
  146. [SerializeField]
  147. bool m_CharacterMode = true;
  148. [SerializeField]
  149. List<PSDLayer> m_MosaicPSDLayers = new List<PSDLayer>();
  150. [SerializeField]
  151. List<PSDLayer> m_RigPSDLayers = new List<PSDLayer>();
  152. [SerializeField]
  153. CharacterData m_CharacterData = new CharacterData();
  154. [SerializeField]
  155. bool m_GenerateGOHierarchy = false;
  156. [SerializeField]
  157. string m_TextureAssetName = null;
  158. [SerializeField]
  159. string m_PrefabAssetName = null;
  160. [SerializeField]
  161. string m_SpriteLibAssetName = null;
  162. [SerializeField]
  163. SecondarySpriteTexture[] m_SecondarySpriteTextures;
  164. /// <summary>
  165. /// Implementation of ScriptedImporter.OnImportAsset
  166. /// </summary>
  167. /// <param name="ctx">
  168. /// This argument contains all the contextual information needed to process the import
  169. /// event and is also used by the custom importer to store the resulting Unity Asset.
  170. /// </param>
  171. public override void OnImportAsset(AssetImportContext ctx)
  172. {
  173. FileStream fileStream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read);
  174. Document doc = null;
  175. try
  176. {
  177. UnityEngine.Profiling.Profiler.BeginSample("OnImportAsset");
  178. UnityEngine.Profiling.Profiler.BeginSample("PsdLoad");
  179. doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream);
  180. UnityEngine.Profiling.Profiler.EndSample();
  181. ValidatePSDLayerId(doc);
  182. m_DocumentSize = new Vector2Int(doc.width, doc.height);
  183. bool singleSpriteMode = m_TextureImporterSettings.textureType == TextureImporterType.Sprite && m_TextureImporterSettings.spriteMode != (int)SpriteImportMode.Multiple;
  184. EnsureSingleSpriteExist();
  185. if (m_TextureImporterSettings.textureType != TextureImporterType.Sprite ||
  186. m_MosaicLayers == false || singleSpriteMode)
  187. {
  188. var image = new NativeArray<Color32>(doc.width * doc.height, Allocator.Persistent);
  189. try
  190. {
  191. var spriteImportData = GetSpriteImportData();
  192. FlattenImageTask.Execute(doc.Layers, m_ImportHiddenLayers, doc.width, doc.height, image);
  193. int spriteCount = spriteDataCount;
  194. int spriteIndexStart = 1;
  195. if (spriteImportData.Count <= 0 || spriteImportData[0] == null)
  196. {
  197. spriteImportData.Add(new SpriteMetaData());
  198. }
  199. spriteImportData[0].name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath) + "_1";
  200. spriteImportData[0].alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  201. spriteImportData[0].border = m_TextureImporterSettings.spriteBorder;
  202. spriteImportData[0].pivot = m_TextureImporterSettings.spritePivot;
  203. spriteImportData[0].rect = new Rect(0, 0, doc.width, doc.height);
  204. if (singleSpriteMode)
  205. {
  206. spriteCount = 1;
  207. spriteIndexStart = 0;
  208. }
  209. textureActualWidth = doc.width;
  210. textureActualHeight = doc.height;
  211. var output = ImportTexture(ctx, image, doc.width, doc.height, spriteIndexStart, spriteCount);
  212. RegisterAssets(ctx, output);
  213. }
  214. finally
  215. {
  216. image.Dispose();
  217. }
  218. }
  219. else
  220. {
  221. ImportFromLayers(ctx, doc);
  222. }
  223. }
  224. finally
  225. {
  226. fileStream.Close();
  227. if (doc != null)
  228. doc.Dispose();
  229. UnityEngine.Profiling.Profiler.EndSample();
  230. EditorUtility.SetDirty(this);
  231. }
  232. // Debug Profiler.
  233. // UnityEngine.Profiling.Memory.Experimental.MemoryProfiler.TakeSnapshot("snapshot.snap", MemorySnapshotFinish, CaptureFlags.ManagedObjects | CaptureFlags.NativeObjects | CaptureFlags.NativeAllocations | CaptureFlags.NativeStackTraces);
  234. }
  235. static void ValidatePSDLayerId(List<BitmapLayer> layers, UniqueNameGenerator uniqueNameGenerator)
  236. {
  237. for (int i = 0; i < layers.Count; ++i)
  238. {
  239. if (uniqueNameGenerator.ContainHash(layers[i].LayerID))
  240. {
  241. var importWarning = string.Format("Layer {0}: LayerId is not unique. Mapping will be done by Layer's name.", layers[i].Name);
  242. var layerName = uniqueNameGenerator.GetUniqueName(layers[i].Name);
  243. if (layerName != layers[i].Name)
  244. importWarning += "\nLayer names are not unique. Please ensure they are unique to for SpriteRect to be mapped back correctly.";
  245. layers[i].LayerID = layerName.GetHashCode();
  246. Debug.LogWarning(importWarning);
  247. }
  248. else
  249. uniqueNameGenerator.AddHash(layers[i].LayerID);
  250. if (layers[i].ChildLayer != null)
  251. {
  252. ValidatePSDLayerId(layers[i].ChildLayer, uniqueNameGenerator);
  253. }
  254. }
  255. }
  256. void ValidatePSDLayerId(Document doc)
  257. {
  258. UniqueNameGenerator uniqueNameGenerator = new UniqueNameGenerator();
  259. ValidatePSDLayerId(doc.Layers, uniqueNameGenerator);
  260. }
  261. TextureGenerationOutput ImportTexture(AssetImportContext ctx, NativeArray<Color32> imageData, int textureWidth, int textureHeight, int spriteStart, int spriteCount)
  262. {
  263. if (!imageData.IsCreated || imageData.Length == 0)
  264. return new TextureGenerationOutput();
  265. UnityEngine.Profiling.Profiler.BeginSample("ImportTexture");
  266. var platformSettings = GetPlatformTextureSettings(ctx.selectedBuildTarget);
  267. var textureSettings = m_TextureImporterSettings.ExtractTextureSettings();
  268. textureSettings.assetPath = ctx.assetPath;
  269. textureSettings.enablePostProcessor = true;
  270. textureSettings.containsAlpha = true;
  271. textureSettings.hdr = false;
  272. var textureAlphaSettings = m_TextureImporterSettings.ExtractTextureAlphaSettings();
  273. var textureMipmapSettings = m_TextureImporterSettings.ExtractTextureMipmapSettings();
  274. var textureCubemapSettings = m_TextureImporterSettings.ExtractTextureCubemapSettings();
  275. var textureWrapSettings = m_TextureImporterSettings.ExtractTextureWrapSettings();
  276. TextureGenerationOutput output;
  277. switch (m_TextureImporterSettings.textureType)
  278. {
  279. case TextureImporterType.Default:
  280. output = TextureGeneratorHelper.GenerateTextureDefault(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  281. break;
  282. case TextureImporterType.NormalMap:
  283. var textureNormalSettings = m_TextureImporterSettings.ExtractTextureNormalSettings();
  284. output = TextureGeneratorHelper.GenerateNormalMap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureNormalSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  285. break;
  286. case TextureImporterType.GUI:
  287. output = TextureGeneratorHelper.GenerateTextureGUI(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  288. break;
  289. case TextureImporterType.Sprite:
  290. var textureSpriteSettings = m_TextureImporterSettings.ExtractTextureSpriteSettings();
  291. textureSpriteSettings.packingTag = m_SpritePackingTag;
  292. textureSpriteSettings.qualifyForPacking = !string.IsNullOrEmpty(m_SpritePackingTag);
  293. textureSpriteSettings.spriteSheetData = new UnityEditor.AssetImporters.SpriteImportData[spriteCount];
  294. textureSettings.npotScale = TextureImporterNPOTScale.None;
  295. textureSettings.secondaryTextures = secondaryTextures;
  296. var spriteImportData = GetSpriteImportData();
  297. for (int i = 0; i < spriteCount; ++i)
  298. {
  299. //AutoGenerateSpriteSkinData(m_SpriteImportData[spriteStart + i]);
  300. textureSpriteSettings.spriteSheetData[i] = spriteImportData[spriteStart + i];
  301. }
  302. output = TextureGeneratorHelper.GenerateTextureSprite(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureSpriteSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  303. break;
  304. case TextureImporterType.Cursor:
  305. output = TextureGeneratorHelper.GenerateTextureCursor(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  306. break;
  307. case TextureImporterType.Cookie:
  308. output = TextureGeneratorHelper.GenerateCookie(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  309. break;
  310. case TextureImporterType.Lightmap:
  311. output = TextureGeneratorHelper.GenerateLightmap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureMipmapSettings, textureWrapSettings);
  312. break;
  313. case TextureImporterType.SingleChannel:
  314. output = TextureGeneratorHelper.GenerateTextureSingleChannel(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  315. break;
  316. default:
  317. Debug.LogAssertion("Unknown texture type for import");
  318. output = default(TextureGenerationOutput);
  319. break;
  320. }
  321. UnityEngine.Profiling.Profiler.EndSample();
  322. return output;
  323. }
  324. void AutoGenerateSpriteSkinData(SpriteMetaData metaData)
  325. {
  326. //If bone data exist but skinning data doesn't exist, auto generate them
  327. if (metaData.spriteBone != null && metaData.spriteBone.Count > 0 &&
  328. (metaData.vertices == null || metaData.vertices.Count == 0))
  329. {
  330. var spriteMeshDataController = new SpriteMeshDataController();
  331. var smd = new SpriteMeshData();
  332. smd.spriteID = metaData.spriteID;
  333. smd.frame = metaData.rect;
  334. smd.pivot = metaData.pivot;
  335. smd.bones = ModuleUtility.CreateSpriteBoneData(metaData.spriteBone.ToArray(), Matrix4x4.TRS(metaData.rect.position, Quaternion.identity, Vector3.one));
  336. spriteMeshDataController.spriteMeshData = smd;
  337. spriteMeshDataController.OutlineFromAlpha(new OutlineGenerator(), GetDataProvider<ITextureDataProvider>(), 0.05f, 200);
  338. spriteMeshDataController.Triangulate(new Triangulator());
  339. spriteMeshDataController.Subdivide(new Triangulator(), 0.25f);
  340. spriteMeshDataController.CalculateWeights(new BoundedBiharmonicWeightsGenerator(), null, 0.01f);
  341. spriteMeshDataController.SortTrianglesByDepth();
  342. List<Vertex2DMetaData> vmd = new List<Vertex2DMetaData>(smd.vertices.Count);
  343. foreach (var v in smd.vertices)
  344. vmd.Add(new Vertex2DMetaData() { position = v.position - smd.frame.position, boneWeight = v.editableBoneWeight.ToBoneWeight(true) });
  345. List<Vector2Int> emd = new List<Vector2Int>(smd.edges.Count);
  346. foreach (var e in smd.edges)
  347. emd.Add(new Vector2Int(e.index1, e.index2));
  348. metaData.vertices = vmd;
  349. metaData.indices = smd.indices.ToArray();
  350. metaData.edges = emd.ToArray();
  351. }
  352. }
  353. string GetUniqueSpriteName(string name, List<int> namehash)
  354. {
  355. if (m_KeepDupilcateSpriteName)
  356. return name;
  357. return GetUniqueName(name, namehash);
  358. }
  359. void ImportFromLayers(AssetImportContext ctx, Document doc)
  360. {
  361. NativeArray<Color32> output = default(NativeArray<Color32>);
  362. List<int> layerIndex = new List<int>();
  363. List<int> spriteNameHash = new List<int>();
  364. var oldPsdLayers = GetPSDLayers();
  365. try
  366. {
  367. var psdLayers = new List<PSDLayer>();
  368. ExtractLayerTask.Execute(psdLayers, doc.Layers, m_ImportHiddenLayers);
  369. var removedLayersSprite = oldPsdLayers.Where(x => psdLayers.FirstOrDefault(y => y.layerID == x.layerID) == null).Select(z => z.spriteID).ToArray();
  370. for (int i = 0; i < psdLayers.Count; ++i)
  371. {
  372. int j = 0;
  373. var psdLayer = psdLayers[i];
  374. for (; j < oldPsdLayers.Count; ++j)
  375. {
  376. if (psdLayer.layerID == oldPsdLayers[j].layerID)
  377. {
  378. psdLayer.spriteID = oldPsdLayers[j].spriteID;
  379. psdLayer.spriteName = oldPsdLayers[j].spriteName;
  380. psdLayer.mosaicPosition = oldPsdLayers[j].mosaicPosition;
  381. break;
  382. }
  383. }
  384. }
  385. int expectedBufferLength = doc.width * doc.height;
  386. var layerBuffers = new List<NativeArray<Color32>>();
  387. for (int i = 0; i < psdLayers.Count; ++i)
  388. {
  389. var l = psdLayers[i];
  390. if (l.texture.IsCreated && l.texture.Length == expectedBufferLength)
  391. {
  392. layerBuffers.Add(l.texture);
  393. layerIndex.Add(i);
  394. }
  395. }
  396. RectInt[] spritedata;
  397. int width, height;
  398. int padding = 4;
  399. Vector2Int[] uvTransform;
  400. ImagePacker.Pack(layerBuffers.ToArray(), doc.width, doc.height, padding, out output, out width, out height, out spritedata, out uvTransform);
  401. var spriteImportData = GetSpriteImportData();
  402. if (spriteImportData.Count <= 0 || shouldResliceFromLayer)
  403. {
  404. var newSpriteMeta = new List<SpriteMetaData>();
  405. for (int i = 0; i < spritedata.Length && i < layerIndex.Count; ++i)
  406. {
  407. var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[layerIndex[i]].spriteID);
  408. if (spriteSheet == null)
  409. {
  410. spriteSheet = new SpriteMetaData();
  411. spriteSheet.border = Vector4.zero;
  412. spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  413. spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
  414. }
  415. psdLayers[layerIndex[i]].spriteName = GetUniqueSpriteName(psdLayers[layerIndex[i]].name, spriteNameHash);
  416. spriteSheet.name = psdLayers[layerIndex[i]].spriteName;
  417. spriteSheet.rect = new Rect(spritedata[i].x, spritedata[i].y, spritedata[i].width, spritedata[i].height);
  418. spriteSheet.uvTransform = uvTransform[i];
  419. psdLayers[layerIndex[i]].spriteID = spriteSheet.spriteID;
  420. psdLayers[layerIndex[i]].mosaicPosition = spritedata[i].position;
  421. newSpriteMeta.Add(spriteSheet);
  422. }
  423. spriteImportData.Clear();
  424. spriteImportData.AddRange(newSpriteMeta);
  425. }
  426. else
  427. {
  428. spriteImportData.RemoveAll(x => removedLayersSprite.Contains(x.spriteID));
  429. // First look for any user created SpriteRect and add those into the name hash
  430. foreach (var spriteData in spriteImportData)
  431. {
  432. var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID);
  433. if (psdLayer == null)
  434. spriteNameHash.Add(spriteData.name.GetHashCode());
  435. }
  436. foreach (var spriteData in spriteImportData)
  437. {
  438. var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID);
  439. if (psdLayer == null)
  440. spriteData.uvTransform = new Vector2Int((int)spriteData.rect.position.x, (int)spriteData.rect.position.y);
  441. // If it is user created rect or the name has been changed before
  442. // add it into the spriteNameHash and we don't copy it over from the layer
  443. if (psdLayer == null || psdLayer.spriteName != spriteData.name)
  444. spriteNameHash.Add(spriteData.name.GetHashCode());
  445. // If the sprite name has not been changed, we ensure the new
  446. // layer name is still unique and use it as the sprite name
  447. if (psdLayer != null && psdLayer.spriteName == spriteData.name)
  448. {
  449. psdLayer.spriteName = GetUniqueSpriteName(psdLayer.name, spriteNameHash);
  450. spriteData.name = psdLayer.spriteName;
  451. }
  452. }
  453. //Update names for those user has not changed and add new sprite rect based on PSD file.
  454. for (int k = 0; k < layerIndex.Count; ++k)
  455. {
  456. int i = layerIndex[k];
  457. var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[i].spriteID);
  458. var inOldLayer = oldPsdLayers.FindIndex(x => x.layerID == psdLayers[i].layerID) != -1;
  459. if (spriteSheet == null && !inOldLayer)
  460. {
  461. spriteSheet = new SpriteMetaData();
  462. spriteImportData.Add(spriteSheet);
  463. spriteSheet.rect = new Rect(spritedata[k].x, spritedata[k].y, spritedata[k].width, spritedata[k].height);
  464. spriteSheet.border = Vector4.zero;
  465. spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  466. spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
  467. psdLayers[i].spriteName = GetUniqueSpriteName(psdLayers[i].name, spriteNameHash);
  468. spriteSheet.name = psdLayers[i].spriteName;
  469. }
  470. else if (spriteSheet != null)
  471. {
  472. var r = spriteSheet.rect;
  473. r.position = spriteSheet.rect.position - psdLayers[i].mosaicPosition + spritedata[k].position;
  474. spriteSheet.rect = r;
  475. }
  476. if (spriteSheet != null)
  477. {
  478. spriteSheet.uvTransform = uvTransform[k];
  479. psdLayers[i].spriteID = spriteSheet.spriteID;
  480. psdLayers[i].mosaicPosition = spritedata[k].position;
  481. }
  482. }
  483. }
  484. foreach (var l in oldPsdLayers)
  485. l.Dispose();
  486. oldPsdLayers.Clear();
  487. oldPsdLayers.AddRange(psdLayers);
  488. m_ImportedTextureHeight = textureActualHeight = height;
  489. m_ImportedTextureWidth = textureActualWidth = width;
  490. var generatedTexture = ImportTexture(ctx, output, width, height, 0, spriteImportData.Count);
  491. if (generatedTexture.texture)
  492. {
  493. m_ImportedTextureHeight = generatedTexture.texture.height;
  494. m_ImportedTextureWidth = generatedTexture.texture.width;
  495. }
  496. RegisterAssets(ctx, generatedTexture);
  497. }
  498. finally
  499. {
  500. if (output.IsCreated)
  501. output.Dispose();
  502. foreach (var l in oldPsdLayers)
  503. l.Dispose();
  504. }
  505. }
  506. void MemorySnapshotFinish(string path, bool done)
  507. {
  508. }
  509. void EnsureSingleSpriteExist()
  510. {
  511. if (m_SpriteImportData.Count <= 0)
  512. m_SpriteImportData.Add(new SpriteMetaData()); // insert default for single sprite mode
  513. }
  514. internal TextureImporterPlatformSettings GetPlatformTextureSettings(BuildTarget buildTarget)
  515. {
  516. var buildTargetName = TexturePlatformSettingsHelper.GetBuildTargetName(buildTarget);
  517. TextureImporterPlatformSettings platformSettings = null;
  518. platformSettings = m_PlatformSettings.SingleOrDefault(x => x.name == buildTargetName && x.overridden == true);
  519. platformSettings = platformSettings ?? m_PlatformSettings.SingleOrDefault(x => x.name == TexturePlatformSettingsHelper.defaultPlatformName);
  520. if (platformSettings == null)
  521. {
  522. platformSettings = new TextureImporterPlatformSettings();
  523. platformSettings.name = buildTargetName;
  524. platformSettings.overridden = false;
  525. }
  526. return platformSettings;
  527. }
  528. void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
  529. {
  530. List<int> assetNameHash = new List<int>();
  531. if (!string.IsNullOrEmpty(output.importInspectorWarnings))
  532. {
  533. Debug.LogWarning(output.importInspectorWarnings);
  534. }
  535. if (output.importWarnings != null && output.importWarnings.Length != 0)
  536. {
  537. foreach (var warning in output.importWarnings)
  538. Debug.LogWarning(warning);
  539. }
  540. if (output.thumbNail == null)
  541. Debug.LogWarning("Thumbnail generation fail");
  542. if (output.texture == null)
  543. {
  544. throw new Exception("Texture import fail");
  545. }
  546. var assetName = GetUniqueName(System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath), assetNameHash, true);
  547. // Setup all fixed name on the hash table
  548. if (string.IsNullOrEmpty(m_TextureAssetName))
  549. m_TextureAssetName = GetUniqueName(string.Format("{0} Texture",assetName), assetNameHash, true);
  550. if (string.IsNullOrEmpty(m_PrefabAssetName))
  551. m_PrefabAssetName = GetUniqueName(string.Format("{0} Prefab", assetName), assetNameHash, true);
  552. if (string.IsNullOrEmpty(m_SpriteLibAssetName))
  553. m_SpriteLibAssetName = GetUniqueName(string.Format("{0} Sprite Lib", assetName), assetNameHash, true);
  554. output.texture.name = assetName;
  555. ctx.AddObjectToAsset(m_TextureAssetName, output.texture, output.thumbNail);
  556. UnityEngine.Object mainAsset = output.texture;
  557. if (output.sprites != null)
  558. {
  559. var slAsset = ProduceSpriteLibAsset(output.sprites);
  560. if (shouldProduceGameObject)
  561. {
  562. GameObject prefab = null;
  563. if (m_PaperDollMode)
  564. prefab = OnProducePaperDollPrefab(m_TextureAssetName, output.sprites, slAsset);
  565. else
  566. prefab = OnProducePrefab(m_TextureAssetName, output.sprites, slAsset);
  567. if (prefab != null)
  568. {
  569. ctx.AddObjectToAsset(m_PrefabAssetName, prefab);
  570. mainAsset = prefab;
  571. }
  572. }
  573. foreach (var s in output.sprites)
  574. {
  575. var spriteAssetName = GetUniqueName(s.GetSpriteID().ToString(), assetNameHash, false, s);
  576. ctx.AddObjectToAsset(spriteAssetName, s);
  577. }
  578. if (slAsset != null)
  579. {
  580. slAsset.name = assetName;
  581. ctx.AddObjectToAsset(m_SpriteLibAssetName, slAsset);
  582. }
  583. }
  584. ctx.SetMainObject(mainAsset);
  585. }
  586. bool SpriteIsMainFromSpriteLib(string spriteId, out string categoryName)
  587. {
  588. categoryName = "";
  589. if (m_SpriteCategoryList.categories != null)
  590. {
  591. foreach (var category in m_SpriteCategoryList.categories)
  592. {
  593. var index = category.labels.FindIndex(x => x.spriteId == spriteId);
  594. if (index == 0)
  595. {
  596. categoryName = category.name;
  597. return true;
  598. }
  599. if (index > 0)
  600. return false;
  601. }
  602. }
  603. return true;
  604. }
  605. void BuildGroupGameObject(List<PSDLayer> psdGroup, int index, Transform root)
  606. {
  607. var spriteData = GetSpriteImportData().FirstOrDefault(x => x.spriteID == psdGroup[index].spriteID);
  608. if (psdGroup[index].gameObject == null)
  609. {
  610. if (m_GenerateGOHierarchy || (!psdGroup[index].spriteID.Empty() && psdGroup[index].isGroup == false))
  611. {
  612. // Determine if need to create GameObject i.e. if the sprite is not in a SpriteLib or if it is the first one
  613. string categoryName;
  614. var b = SpriteIsMainFromSpriteLib(psdGroup[index].spriteID.ToString(), out categoryName);
  615. string goName = string.IsNullOrEmpty(categoryName) ? spriteData != null ? spriteData.name : psdGroup[index].name : categoryName;
  616. if (b)
  617. psdGroup[index].gameObject = m_GameObjectFactory.CreateGameObject(goName);
  618. }
  619. if (psdGroup[index].parentIndex >= 0 && m_GenerateGOHierarchy)
  620. {
  621. BuildGroupGameObject(psdGroup, psdGroup[index].parentIndex, root);
  622. root = psdGroup[psdGroup[index].parentIndex].gameObject.transform;
  623. }
  624. if (psdGroup[index].gameObject != null)
  625. {
  626. psdGroup[index].gameObject.transform.SetParent(root);
  627. psdGroup[index].gameObject.transform.SetSiblingIndex(root.childCount-1);
  628. }
  629. }
  630. }
  631. bool shouldProduceGameObject
  632. {
  633. get { return m_CharacterMode && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
  634. }
  635. bool shouldResliceFromLayer
  636. {
  637. get { return m_ResliceFromLayer && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
  638. }
  639. bool characterMode
  640. {
  641. get { return mosaicMode && m_CharacterMode == true; }
  642. }
  643. float definitionScale
  644. {
  645. get
  646. {
  647. float definitionScaleW = m_ImportedTextureWidth / (float)textureActualWidth;
  648. float definitionScaleH = m_ImportedTextureHeight / (float)textureActualHeight;
  649. return Mathf.Min(definitionScaleW, definitionScaleH);
  650. }
  651. }
  652. private Vector2 GetPivotPoint(Rect rect, SpriteAlignment alignment)
  653. {
  654. switch (alignment)
  655. {
  656. case SpriteAlignment.TopLeft:
  657. return new Vector2(rect.xMin, rect.yMax);
  658. case SpriteAlignment.TopCenter:
  659. return new Vector2(rect.center.x, rect.yMax);
  660. case SpriteAlignment.TopRight:
  661. return new Vector2(rect.xMax, rect.yMax);
  662. case SpriteAlignment.LeftCenter:
  663. return new Vector2(rect.xMin, rect.center.y);
  664. case SpriteAlignment.Center:
  665. return new Vector2(rect.center.x, rect.center.y);
  666. case SpriteAlignment.RightCenter:
  667. return new Vector2(rect.xMax, rect.center.y);
  668. case SpriteAlignment.BottomLeft:
  669. return new Vector2(rect.xMin, rect.yMin);
  670. case SpriteAlignment.BottomCenter:
  671. return new Vector2(rect.center.x, rect.yMin);
  672. case SpriteAlignment.BottomRight:
  673. return new Vector2(rect.xMax, rect.yMin);
  674. case SpriteAlignment.Custom:
  675. return new Vector2(m_DocumentPivot.x * rect.width, m_DocumentPivot.y * rect.height);
  676. }
  677. return Vector2.zero;
  678. }
  679. void CreateBoneGO(int index, SpriteBone[] bones, BoneGO[] bonesGO, Transform defaultRoot)
  680. {
  681. if (bonesGO[index].go != null)
  682. return;
  683. var bone = bones[index];
  684. if (bone.parentId != -1 && bonesGO[bone.parentId].go == null)
  685. CreateBoneGO(bone.parentId, bones, bonesGO, defaultRoot);
  686. var go = m_GameObjectFactory.CreateGameObject(bone.name);
  687. if (bone.parentId == -1)
  688. go.transform.SetParent(defaultRoot);
  689. else
  690. go.transform.SetParent(bonesGO[bone.parentId].go.transform);
  691. go.transform.localPosition = bone.position * 1 / pixelsPerUnit;
  692. go.transform.localRotation = bone.rotation;
  693. bonesGO[index] = new BoneGO()
  694. {
  695. go = go,
  696. index = index
  697. };
  698. }
  699. BoneGO[] CreateBonesGO(Transform root)
  700. {
  701. if (characterMode)
  702. {
  703. var characterSkeleton = GetDataProvider<ICharacterDataProvider>().GetCharacterData();
  704. var bones = characterSkeleton.bones;
  705. if (bones != null)
  706. {
  707. var boneGOs = new BoneGO[bones.Length];
  708. for (int i = 0; i < bones.Length; ++i)
  709. {
  710. CreateBoneGO(i, bones, boneGOs, root);
  711. }
  712. return boneGOs;
  713. }
  714. }
  715. return new BoneGO[0];
  716. }
  717. void GetSpriteLiblabel(string spriteId, out string category, out string label)
  718. {
  719. category = "";
  720. label = "";
  721. var index = -1;
  722. foreach (var cat in m_SpriteCategoryList.categories)
  723. {
  724. index = cat.labels.FindIndex(x => x.spriteId == spriteId);
  725. if (index != -1)
  726. {
  727. category = cat.name;
  728. label = cat.labels[index].name;
  729. break;
  730. }
  731. }
  732. }
  733. GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
  734. {
  735. GameObject root = null;
  736. CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
  737. if (sprites != null && sprites.Length > 0)
  738. {
  739. root = new GameObject();
  740. root.name = assetname + "_GO";
  741. var spriteImportData = GetSpriteImportData();
  742. var psdLayers = GetPSDLayers();
  743. var boneGOs = CreateBonesGO(root.transform);
  744. if (spriteLib != null)
  745. root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
  746. for (int i = 0; i < sprites.Length; ++i)
  747. {
  748. string categoryName;
  749. if (SpriteIsMainFromSpriteLib(sprites[i].GetSpriteID().ToString(), out categoryName))
  750. {
  751. var spriteBones = m_CharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == sprites[i].GetSpriteID()).bones;
  752. var rootBone = root;
  753. if (spriteBones != null && spriteBones.Any())
  754. {
  755. var b = spriteBones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]).OrderBy(x => x.index);
  756. if (b.Any())
  757. rootBone = b.First().go;
  758. }
  759. var srGameObject = m_GameObjectFactory.CreateGameObject(string.IsNullOrEmpty(categoryName) ? sprites[i].name : categoryName);
  760. var sr = srGameObject.AddComponent<SpriteRenderer>();
  761. sr.sprite = sprites[i];
  762. sr.sortingOrder = psdLayers.Count - psdLayers.FindIndex(x => x.spriteID == sprites[i].GetSpriteID());
  763. srGameObject.transform.parent = rootBone.transform;
  764. var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == sprites[i].GetSpriteID());
  765. if (spriteMetaData != null)
  766. {
  767. var uvTransform = spriteMetaData.uvTransform;
  768. var outlineOffset = new Vector2(spriteMetaData.rect.x - uvTransform.x + (spriteMetaData.pivot.x * spriteMetaData.rect.width),
  769. spriteMetaData.rect.y - uvTransform.y + (spriteMetaData.pivot.y * spriteMetaData.rect.height)) * definitionScale / sprites[i].pixelsPerUnit;
  770. srGameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
  771. }
  772. var category = "";
  773. var labelName = "";
  774. GetSpriteLiblabel(sprites[i].GetSpriteID().ToString(), out category, out labelName);
  775. if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
  776. {
  777. var sresolver = srGameObject.AddComponent<SpriteResolver>();
  778. sresolver.SetCategoryAndLabel(category, labelName);
  779. sresolver.ResolveSpriteToSpriteRenderer();
  780. }
  781. }
  782. }
  783. }
  784. return root;
  785. }
  786. internal void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings)
  787. {
  788. var index = m_PlatformSettings.FindIndex(x => x.name == platformSettings.name);
  789. if(index < 0)
  790. m_PlatformSettings.Add(platformSettings);
  791. else
  792. m_PlatformSettings[index] = platformSettings;
  793. }
  794. internal TextureImporterPlatformSettings[] GetAllPlatformSettings()
  795. {
  796. return m_PlatformSettings.ToArray();
  797. }
  798. GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
  799. {
  800. GameObject root = null;
  801. CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
  802. if (sprites != null && sprites.Length > 0)
  803. {
  804. var spriteImportData = GetSpriteImportData();
  805. root = new GameObject();
  806. root.transform.SetSiblingIndex(0);
  807. root.name = assetname + "_GO";
  808. if (spriteLib != null)
  809. root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
  810. var psdLayers = GetPSDLayers();
  811. for (int i = 0; i < psdLayers.Count; ++i)
  812. {
  813. BuildGroupGameObject(psdLayers, i, root.transform);
  814. }
  815. var boneGOs = CreateBonesGO(root.transform);
  816. for (int i = 0; i < psdLayers.Count; ++i)
  817. {
  818. var l = psdLayers[i];
  819. GUID layerSpriteID = l.spriteID;
  820. var sprite = sprites.FirstOrDefault(x => x.GetSpriteID() == layerSpriteID);
  821. var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == layerSpriteID);
  822. if (sprite != null && spriteMetaData != null && l.gameObject != null)
  823. {
  824. var spriteRenderer = l.gameObject.AddComponent<SpriteRenderer>();
  825. spriteRenderer.sprite = sprite;
  826. spriteRenderer.sortingOrder = psdLayers.Count - i;
  827. var uvTransform = spriteMetaData.uvTransform;
  828. var outlineOffset = new Vector2(spriteMetaData.rect.x - uvTransform.x + (spriteMetaData.pivot.x * spriteMetaData.rect.width),
  829. spriteMetaData.rect.y - uvTransform.y + (spriteMetaData.pivot.y * spriteMetaData.rect.height)) * definitionScale / sprite.pixelsPerUnit;
  830. l.gameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
  831. if (characterSkeleton != null)
  832. {
  833. var part = characterSkeleton.Value.parts.FirstOrDefault(x => x.spriteId == spriteMetaData.spriteID.ToString());
  834. if (part.bones != null && part.bones.Length > 0)
  835. {
  836. var spriteSkin = l.gameObject.AddComponent<SpriteSkin>();
  837. if (spriteRenderer.sprite != null && spriteRenderer.sprite.GetBindPoses().Length > 0)
  838. {
  839. var spriteBones = m_CharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == spriteRenderer.sprite.GetSpriteID()).bones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]);
  840. if (spriteBones.Any())
  841. {
  842. spriteSkin.rootBone = spriteBones.OrderBy(x => x.index).First().go.transform;
  843. spriteSkin.boneTransforms = spriteBones.Select(x => x.go.transform).ToArray();
  844. if (spriteSkin.isValid)
  845. spriteSkin.CalculateBounds();
  846. }
  847. }
  848. }
  849. }
  850. var category = "";
  851. var labelName = "";
  852. GetSpriteLiblabel(layerSpriteID.ToString(), out category, out labelName);
  853. if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
  854. {
  855. var sresolver = l.gameObject.AddComponent<SpriteResolver>();
  856. sresolver.SetCategoryAndLabel(category, labelName);
  857. sresolver.ResolveSpriteToSpriteRenderer();
  858. }
  859. }
  860. }
  861. var prefabBounds = new Rect(0 , 0, m_DocumentSize.x / pixelsPerUnit, m_DocumentSize.y / pixelsPerUnit);
  862. var documentPivot = (Vector3)GetPivotPoint(prefabBounds, m_DocumentAlignment);
  863. for (int i = 0; i < psdLayers.Count; ++i)
  864. {
  865. var l = psdLayers[i];
  866. if (l.gameObject == null || l.gameObject.GetComponent<SpriteRenderer>() == null)
  867. continue;
  868. var p = l.gameObject.transform.localPosition;
  869. p -= documentPivot;
  870. l.gameObject.transform.localPosition = p;
  871. }
  872. for (int i = 0; i < boneGOs.Length; ++i)
  873. {
  874. if (boneGOs[i].go.transform.parent != root.transform)
  875. continue;
  876. var p = boneGOs[i].go.transform.position;
  877. p -= documentPivot;
  878. boneGOs[i].go.transform.position = p;
  879. }
  880. }
  881. return root;
  882. }
  883. Bounds? GetBoundingBox(GameObject root)
  884. {
  885. Bounds? prefabBounds1 = null;
  886. var sr = root.GetComponent<SpriteRenderer>();
  887. if (sr != null)
  888. {
  889. prefabBounds1 = sr.bounds;
  890. }
  891. for (int i = 0; i < root.transform.childCount; ++i)
  892. {
  893. var b = GetBoundingBox(root.transform.GetChild(i).gameObject);
  894. if (prefabBounds1 == null)
  895. prefabBounds1 = b;
  896. else
  897. {
  898. if (b.HasValue)
  899. {
  900. var bb = prefabBounds1.Value;
  901. bb.Encapsulate(b.Value);
  902. prefabBounds1 = bb;
  903. }
  904. }
  905. }
  906. return prefabBounds1;
  907. }
  908. bool CleanUpGameobjectsWithOutRig(GameObject root)
  909. {
  910. var sr = root.GetComponent<SpriteRenderer>();
  911. var canDelete = true;
  912. if (sr != null && sr.sprite != null)
  913. {
  914. try
  915. {
  916. var bones = GetDataProvider<ISpriteBoneDataProvider>().GetBones(sr.sprite.GetSpriteID());
  917. canDelete = bones == null || bones.Count == 0;
  918. }
  919. catch (Exception e)
  920. {
  921. Debug.LogError(e);
  922. }
  923. }
  924. List<GameObject> cleanup = new List<GameObject>();
  925. for (int i = 0; i < root.transform.childCount; ++i)
  926. {
  927. var go = root.transform.GetChild(i);
  928. if (CleanUpGameobjectsWithOutRig(go.gameObject))
  929. cleanup.Add(go.gameObject);
  930. }
  931. for (int i = 0; i < cleanup.Count; ++i)
  932. GameObject.DestroyImmediate(cleanup[i]);
  933. cleanup.Clear();
  934. if (root.transform.childCount == 0 && canDelete)
  935. return true;
  936. return false;
  937. }
  938. static string SanitizeName(string name)
  939. {
  940. string newName = null;
  941. // We can't create asset name with these name.
  942. if ((name.Length == 2 && name[0] == '.' && name[1] == '.')
  943. || (name.Length == 1 && name[0] == '.')
  944. || (name.Length == 1 && name[0] == '/'))
  945. newName += name + "_";
  946. if (!string.IsNullOrEmpty(newName))
  947. {
  948. Debug.LogWarning(string.Format("File contains layer with invalid name for generating asset. {0} is renamed to {1}", name, newName));
  949. return newName;
  950. }
  951. return name;
  952. }
  953. static string GetUniqueName(string name, List<int> stringHash, bool logNewNameGenerated = false, UnityEngine.Object context = null)
  954. {
  955. string uniqueName = string.Copy(SanitizeName(name));
  956. int index = 1;
  957. while (true)
  958. {
  959. int hash = uniqueName.GetHashCode();
  960. var p = stringHash.Where(x => x == hash);
  961. if (!p.Any())
  962. {
  963. stringHash.Add(hash);
  964. if (logNewNameGenerated && name != uniqueName)
  965. Debug.Log(string.Format("Asset name {0} is changed to {1} to ensure uniqueness", name, uniqueName), context);
  966. return uniqueName;
  967. }
  968. uniqueName = string.Format("{0}_{1}", name, index);
  969. ++index;
  970. }
  971. }
  972. // ISpriteEditorDataProvider interface
  973. internal SpriteImportMode spriteImportMode
  974. {
  975. get
  976. {
  977. return m_TextureImporterSettings.textureType != TextureImporterType.Sprite ?
  978. SpriteImportMode.None :
  979. (SpriteImportMode)m_TextureImporterSettings.spriteMode;
  980. }
  981. }
  982. SpriteImportMode ISpriteEditorDataProvider.spriteImportMode => spriteImportMode;
  983. internal int spriteDataCount
  984. {
  985. get
  986. {
  987. var spriteImportData = GetSpriteImportData();
  988. if (mosaicMode)
  989. return spriteImportData.Count;
  990. if (spriteImportMode != SpriteImportMode.Multiple)
  991. return 1;
  992. return spriteImportData.Count - 1;
  993. }
  994. }
  995. internal UnityEngine.Object targetObject
  996. {
  997. get { return this; }
  998. }
  999. UnityEngine.Object ISpriteEditorDataProvider.targetObject => targetObject;
  1000. internal float pixelsPerUnit
  1001. {
  1002. get { return m_TextureImporterSettings.spritePixelsPerUnit; }
  1003. }
  1004. float ISpriteEditorDataProvider.pixelsPerUnit =>pixelsPerUnit;
  1005. internal T GetDataProvider<T>() where T : class
  1006. {
  1007. if (typeof(T) == typeof(ISpriteBoneDataProvider))
  1008. {
  1009. return new SpriteBoneDataProvider { dataProvider = this } as T;
  1010. }
  1011. if (typeof(T) == typeof(ISpriteMeshDataProvider))
  1012. {
  1013. return new SpriteMeshDataProvider { dataProvider = this } as T;
  1014. }
  1015. if (typeof(T) == typeof(ISpriteOutlineDataProvider))
  1016. {
  1017. return new SpriteOutlineDataProvider { dataProvider = this } as T;
  1018. }
  1019. if (typeof(T) == typeof(ISpritePhysicsOutlineDataProvider))
  1020. {
  1021. return new SpritePhysicsOutlineProvider { dataProvider = this } as T;
  1022. }
  1023. if (typeof(T) == typeof(ITextureDataProvider))
  1024. {
  1025. return new TextureDataProvider { dataProvider = this } as T;
  1026. }
  1027. if (typeof(T) == typeof(ICharacterDataProvider))
  1028. {
  1029. return characterMode ? new CharacterDataProvider { dataProvider = this } as T : null;
  1030. }
  1031. if (typeof(T) == typeof(ISpriteLibDataProvider))
  1032. {
  1033. return new SpriteLibraryDataProvider() { dataProvider = this } as T;
  1034. }
  1035. if (typeof(T) == typeof(ISecondaryTextureDataProvider))
  1036. {
  1037. return new SecondaryTextureDataProvider() { dataProvider = this } as T;
  1038. }
  1039. else
  1040. return this as T;
  1041. }
  1042. T ISpriteEditorDataProvider.GetDataProvider<T>()
  1043. {
  1044. return GetDataProvider<T>();
  1045. }
  1046. internal bool HasDataProvider(Type type)
  1047. {
  1048. if (characterMode && type == typeof(ICharacterDataProvider))
  1049. return true;
  1050. if (type == typeof(ISpriteBoneDataProvider) ||
  1051. type == typeof(ISpriteMeshDataProvider) ||
  1052. type == typeof(ISpriteOutlineDataProvider) ||
  1053. type == typeof(ISpritePhysicsOutlineDataProvider) ||
  1054. type == typeof(ITextureDataProvider) ||
  1055. type == typeof(ISpriteLibDataProvider) ||
  1056. type == typeof(ISecondaryTextureDataProvider))
  1057. {
  1058. return true;
  1059. }
  1060. else
  1061. return type.IsAssignableFrom(GetType());
  1062. }
  1063. bool ISpriteEditorDataProvider.HasDataProvider(Type type)
  1064. {
  1065. return HasDataProvider(type);
  1066. }
  1067. internal void AddSpriteData(SpriteRect spriteRect)
  1068. {
  1069. if (spriteImportMode != SpriteImportMode.Multiple)
  1070. Debug.LogWarning("Can only add sprite data when import mode is multiple");
  1071. else
  1072. {
  1073. GetSpriteImportData().Add(new SpriteMetaData(spriteRect));
  1074. }
  1075. }
  1076. internal void DeleteSpriteData(SpriteRect spriteRect)
  1077. {
  1078. if (spriteImportMode != SpriteImportMode.Multiple)
  1079. Debug.LogWarning("Can only add sprite data when import mode is multiple");
  1080. else
  1081. {
  1082. var spriteImportData = GetSpriteImportData();
  1083. int index = spriteImportData.FindIndex(x => x.spriteID == spriteRect.spriteID);
  1084. Assert.AreEqual(0, index, "Cannot delete Sprite from single sprite mode");
  1085. spriteImportData.RemoveAt(index);
  1086. }
  1087. }
  1088. internal int GetSpriteDataIndex(GUID guid)
  1089. {
  1090. switch (spriteImportMode)
  1091. {
  1092. case SpriteImportMode.Single:
  1093. case SpriteImportMode.Polygon:
  1094. return 0;
  1095. case SpriteImportMode.Multiple:
  1096. {
  1097. var spriteImportData = GetSpriteImportData();
  1098. return spriteImportData.FindIndex(x => x.spriteID == guid);
  1099. }
  1100. default:
  1101. throw new InvalidOperationException("GUID not found");
  1102. }
  1103. }
  1104. internal void Apply()
  1105. {
  1106. // Do this so that asset change save dialog will not show
  1107. var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false);
  1108. EditorPrefs.SetBool("VerifySavingAssets", false);
  1109. AssetDatabase.ForceReserializeAssets(new string[] { assetPath }, ForceReserializeAssetsOptions.ReserializeMetadata);
  1110. EditorPrefs.SetBool("VerifySavingAssets", originalValue);
  1111. }
  1112. void ISpriteEditorDataProvider.Apply()
  1113. {
  1114. Apply();
  1115. }
  1116. internal void InitSpriteEditorDataProvider() {}
  1117. void ISpriteEditorDataProvider.InitSpriteEditorDataProvider()
  1118. {
  1119. InitSpriteEditorDataProvider();
  1120. }
  1121. internal SpriteRect[] GetSpriteRects()
  1122. {
  1123. var spriteImportData = GetSpriteImportData();
  1124. var skip = mosaicMode ? 0 : 1;
  1125. return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).Select(x => new SpriteMetaData(x) as SpriteRect).ToArray() : new[] {new SpriteMetaData(spriteImportData[0]) };
  1126. }
  1127. SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects()
  1128. {
  1129. return GetSpriteRects();
  1130. }
  1131. List<SpriteMetaData> GetSpriteImportData()
  1132. {
  1133. return mosaicMode ? (characterMode ? m_RigSpriteImportData : m_MosaicSpriteImportData) : m_SpriteImportData;
  1134. }
  1135. internal List<PSDLayer> GetPSDLayers()
  1136. {
  1137. return mosaicMode ? (characterMode ? m_RigPSDLayers : m_MosaicPSDLayers) : null;
  1138. }
  1139. internal SpriteMetaData[] GetSpriteMetaData()
  1140. {
  1141. var spriteImportData = GetSpriteImportData();
  1142. var skip = mosaicMode ? 0 : 1;
  1143. return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).ToArray() : new[] { new SpriteMetaData(spriteImportData[0]) };
  1144. }
  1145. internal SpriteRect GetSpriteDataFromAllMode(GUID guid)
  1146. {
  1147. var spriteMetaData = m_RigSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1148. if(spriteMetaData == null)
  1149. spriteMetaData = m_MosaicSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1150. if(spriteMetaData == null)
  1151. spriteMetaData = m_SpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1152. return spriteMetaData;
  1153. }
  1154. internal SpriteRect GetSpriteData(GUID guid)
  1155. {
  1156. var spriteImportData = GetSpriteImportData();
  1157. var skip = mosaicMode ? 0 : 1;
  1158. return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).FirstOrDefault(x => x.spriteID == guid) : spriteImportData[0];
  1159. }
  1160. internal void SetSpriteRects(SpriteRect[] spriteRects)
  1161. {
  1162. var spriteImportData = GetSpriteImportData();
  1163. if (spriteImportMode == SpriteImportMode.Multiple)
  1164. {
  1165. var singleSpriteID = mosaicMode ? new GUID() : spriteImportData[0].spriteID;
  1166. spriteImportData.RemoveAll(data => data.spriteID != singleSpriteID && spriteRects.FirstOrDefault(x => x.spriteID == data.spriteID) == null);
  1167. foreach (var sr in spriteRects)
  1168. {
  1169. var importData = spriteImportData.FirstOrDefault(x => x.spriteID == sr.spriteID);
  1170. if (importData == null)
  1171. spriteImportData.Add(new SpriteMetaData(sr));
  1172. else
  1173. {
  1174. importData.name = sr.name;
  1175. importData.alignment = sr.alignment;
  1176. importData.border = sr.border;
  1177. importData.pivot = sr.pivot;
  1178. importData.rect = sr.rect;
  1179. }
  1180. }
  1181. }
  1182. else if (spriteRects.Length == 1 && (spriteImportMode == SpriteImportMode.Single || spriteImportMode == SpriteImportMode.Polygon))
  1183. {
  1184. if (spriteImportData[0].spriteID == spriteRects[0].spriteID)
  1185. {
  1186. spriteImportData[0].name = spriteRects[0].name;
  1187. spriteImportData[0].alignment = spriteRects[0].alignment;
  1188. m_TextureImporterSettings.spriteAlignment = (int)spriteRects[0].alignment;
  1189. m_TextureImporterSettings.spriteBorder = spriteImportData[0].border = spriteRects[0].border;
  1190. m_TextureImporterSettings.spritePivot = spriteImportData[0].pivot = spriteRects[0].pivot;
  1191. spriteImportData[0].rect = spriteRects[0].rect;
  1192. }
  1193. else
  1194. {
  1195. spriteImportData[0] = new SpriteMetaData(spriteRects[0]);
  1196. }
  1197. }
  1198. }
  1199. void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects)
  1200. {
  1201. SetSpriteRects(spriteRects);
  1202. }
  1203. bool mosaicMode
  1204. {
  1205. get { return spriteImportMode == SpriteImportMode.Multiple && m_MosaicLayers; }
  1206. }
  1207. internal CharacterData characterData
  1208. {
  1209. get { return m_CharacterData; }
  1210. set { m_CharacterData = value; }
  1211. }
  1212. internal Vector2Int documentSize
  1213. {
  1214. get { return m_DocumentSize; }
  1215. }
  1216. SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
  1217. {
  1218. if (!characterMode || m_SpriteCategoryList.categories == null)
  1219. return null;
  1220. var sla = ScriptableObject.CreateInstance<SpriteLibraryAsset>();
  1221. sla.name = "Sprite Lib";
  1222. sla.categories = m_SpriteCategoryList.categories.Select(x =>
  1223. new SpriteLibCategory()
  1224. {
  1225. name = x.name,
  1226. categoryList = x.labels.Select(y =>
  1227. {
  1228. var sprite = sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y.spriteId);
  1229. return new Categorylabel()
  1230. {
  1231. name = y.name,
  1232. sprite = sprite
  1233. };
  1234. }).ToList()
  1235. }).ToList();
  1236. sla.categories.RemoveAll(x => x.categoryList.Count == 0);
  1237. if (sla.categories.Count > 0)
  1238. {
  1239. sla.UpdateHashes();
  1240. return sla;
  1241. }
  1242. return null;
  1243. }
  1244. internal SecondarySpriteTexture[] secondaryTextures
  1245. {
  1246. get { return m_SecondarySpriteTextures; }
  1247. set { m_SecondarySpriteTextures = value; }
  1248. }
  1249. internal void ReadTextureSettings(TextureImporterSettings dest)
  1250. {
  1251. m_TextureImporterSettings.CopyTo(dest);
  1252. }
  1253. }
  1254. }