No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PSDImporter.cs 73KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675
  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.U2D;
  14. using UnityEngine.U2D.Animation;
  15. using UnityEngine.Scripting.APIUpdating;
  16. namespace UnityEditor.U2D.PSD
  17. {
  18. /// <summary>
  19. /// ScriptedImporter to import Photoshop files
  20. /// </summary>
  21. // Version using unity release + 5 digit padding for future upgrade. Eg 2021.2 -> 21200000
  22. [ScriptedImporter(21200003, "psb", AllowCaching = true)]
  23. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.psdimporter@latest")]
  24. [MovedFrom("UnityEditor.Experimental.AssetImporters")]
  25. public class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider
  26. {
  27. internal enum ELayerMappingOption
  28. {
  29. UseLayerName,
  30. UseLayerNameCaseSensitive,
  31. UseLayerId
  32. }
  33. IPSDLayerMappingStrategy[] m_MappingCompare =
  34. {
  35. new LayerMappingUseLayerName(),
  36. new LayerMappingUseLayerNameCaseSensitive(),
  37. new LayerMappingUserLayerID(),
  38. };
  39. [SerializeField]
  40. TextureImporterSettings m_TextureImporterSettings = new TextureImporterSettings()
  41. {
  42. mipmapEnabled = true,
  43. mipmapFilter = TextureImporterMipFilter.BoxFilter,
  44. sRGBTexture = true,
  45. borderMipmap = false,
  46. mipMapsPreserveCoverage = false,
  47. alphaTestReferenceValue = 0.5f,
  48. readable = false,
  49. #if ENABLE_TEXTURE_STREAMING
  50. streamingMipmaps = true,
  51. #endif
  52. fadeOut = false,
  53. mipmapFadeDistanceStart = 1,
  54. mipmapFadeDistanceEnd = 3,
  55. convertToNormalMap = false,
  56. heightmapScale = 0.25F,
  57. normalMapFilter = 0,
  58. generateCubemap = TextureImporterGenerateCubemap.AutoCubemap,
  59. cubemapConvolution = 0,
  60. seamlessCubemap = false,
  61. npotScale = TextureImporterNPOTScale.ToNearest,
  62. spriteMode = (int)SpriteImportMode.Multiple,
  63. spriteExtrude = 1,
  64. spriteMeshType = SpriteMeshType.Tight,
  65. spriteAlignment = (int)SpriteAlignment.Center,
  66. spritePivot = new Vector2(0.5f, 0.5f),
  67. spritePixelsPerUnit = 100.0f,
  68. spriteBorder = new Vector4(0.0f, 0.0f, 0.0f, 0.0f),
  69. alphaSource = TextureImporterAlphaSource.FromInput,
  70. alphaIsTransparency = true,
  71. spriteTessellationDetail = -1.0f,
  72. textureType = TextureImporterType.Sprite,
  73. textureShape = TextureImporterShape.Texture2D,
  74. filterMode = FilterMode.Bilinear,
  75. aniso = 1,
  76. mipmapBias = 0.0f,
  77. wrapModeU = TextureWrapMode.Repeat,
  78. wrapModeV = TextureWrapMode.Repeat,
  79. wrapModeW = TextureWrapMode.Repeat,
  80. };
  81. [SerializeField]
  82. // SpriteData for both single and multiple mode
  83. List<SpriteMetaData> m_SpriteImportData = new List<SpriteMetaData>(); // we use index 0 for single sprite and the rest for multiple sprites
  84. [SerializeField]
  85. // SpriteData for Mosaic mode
  86. List<SpriteMetaData> m_MosaicSpriteImportData = new List<SpriteMetaData>();
  87. [SerializeField]
  88. // SpriteData for Rig mode
  89. List<SpriteMetaData> m_RigSpriteImportData = new List<SpriteMetaData>();
  90. [SerializeField]
  91. // CharacterData for Rig mode
  92. CharacterData m_CharacterData = new CharacterData();
  93. [SerializeField]
  94. // SpriteData for shared rig mode
  95. List<SpriteMetaData> m_SharedRigSpriteImportData = new List<SpriteMetaData>();
  96. [SerializeField]
  97. // CharacterData for shared rig mode
  98. CharacterData m_SharedRigCharacterData = new CharacterData();
  99. [SerializeField]
  100. List<TextureImporterPlatformSettings> m_PlatformSettings = new List<TextureImporterPlatformSettings>();
  101. [SerializeField]
  102. bool m_MosaicLayers = true;
  103. [SerializeField]
  104. bool m_CharacterMode = true;
  105. [SerializeField]
  106. Vector2 m_DocumentPivot = Vector2.zero;
  107. [SerializeField]
  108. SpriteAlignment m_DocumentAlignment = SpriteAlignment.BottomCenter;
  109. [SerializeField]
  110. bool m_ImportHiddenLayers = false;
  111. [SerializeField]
  112. ELayerMappingOption m_LayerMappingOption = ELayerMappingOption.UseLayerId;
  113. [SerializeField]
  114. bool m_GeneratePhysicsShape = false;
  115. [SerializeField]
  116. bool m_PaperDollMode = false;
  117. [SerializeField]
  118. bool m_KeepDupilcateSpriteName = true;
  119. [SerializeField]
  120. private string m_SkeletonAssetReferenceID = null;
  121. [SerializeField]
  122. SpriteCategoryList m_SpriteCategoryList = new SpriteCategoryList() {categories = new List<SpriteCategory>()};
  123. GameObjectCreationFactory m_GameObjectFactory = new GameObjectCreationFactory();
  124. internal SpriteCategoryList spriteCategoryList { get { return m_SpriteCategoryList; } set { m_SpriteCategoryList = value; } }
  125. PSDImportData m_ImportData;
  126. internal PSDImportData importData
  127. {
  128. get
  129. {
  130. var returnValue = m_ImportData;
  131. if (returnValue == null)
  132. returnValue = AssetDatabase.LoadAllAssetsAtPath(assetPath).FirstOrDefault(x => x is PSDImportData) as PSDImportData;
  133. if (returnValue == null)
  134. returnValue = ScriptableObject.CreateInstance<PSDImportData>();
  135. m_ImportData = returnValue;
  136. return returnValue;
  137. }
  138. }
  139. internal int textureActualWidth
  140. {
  141. get => importData.textureActualWidth;
  142. private set =>importData.textureActualWidth = value;
  143. }
  144. internal int textureActualHeight
  145. {
  146. get => importData.textureActualHeight;
  147. private set =>importData.textureActualHeight = value;
  148. }
  149. [SerializeField]
  150. string m_SpritePackingTag = "";
  151. [SerializeField]
  152. bool m_ResliceFromLayer = false;
  153. [SerializeField]
  154. List<PSDLayer> m_MosaicPSDLayers = new List<PSDLayer>();
  155. [SerializeField]
  156. List<PSDLayer> m_RigPSDLayers = new List<PSDLayer>();
  157. [SerializeField]
  158. List<PSDLayer> m_SharedRigPSDLayers = new List<PSDLayer>();
  159. [SerializeField]
  160. PSDLayerImportSetting[] m_PSDLayerImportSetting;
  161. [SerializeField]
  162. bool m_GenerateGOHierarchy = false;
  163. [SerializeField]
  164. string m_TextureAssetName = null;
  165. [SerializeField]
  166. string m_PrefabAssetName = null;
  167. [SerializeField]
  168. string m_SpriteLibAssetName = null;
  169. [SerializeField]
  170. string m_SkeletonAssetName = null;
  171. [SerializeField]
  172. SecondarySpriteTexture[] m_SecondarySpriteTextures;
  173. PSDExtractLayerData[] m_ExtractData;
  174. /// <summary>
  175. /// Implementation of ScriptedImporter.OnImportAsset
  176. /// </summary>
  177. /// <param name="ctx">
  178. /// This argument contains all the contextual information needed to process the import
  179. /// event and is also used by the custom importer to store the resulting Unity Asset.
  180. /// </param>
  181. public override void OnImportAsset(AssetImportContext ctx)
  182. {
  183. var fileStream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read);
  184. Document doc = null;
  185. if(m_ImportData == null)
  186. m_ImportData = ScriptableObject.CreateInstance<PSDImportData>();
  187. m_ImportData.hideFlags = HideFlags.HideInHierarchy;
  188. try
  189. {
  190. UnityEngine.Profiling.Profiler.BeginSample("OnImportAsset");
  191. UnityEngine.Profiling.Profiler.BeginSample("PsdLoad");
  192. doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream);
  193. UnityEngine.Profiling.Profiler.EndSample();
  194. m_ImportData.CreatePSDLayerData(doc.Layers);
  195. ValidatePSDLayerId(doc);
  196. SetDocumentImportData(doc);
  197. importData.documentSize = new Vector2Int(doc.width, doc.height);
  198. var singleSpriteMode = m_TextureImporterSettings.textureType == TextureImporterType.Sprite && m_TextureImporterSettings.spriteMode != (int)SpriteImportMode.Multiple;
  199. EnsureSingleSpriteExist();
  200. if (m_TextureImporterSettings.textureType != TextureImporterType.Sprite ||
  201. m_MosaicLayers == false || singleSpriteMode)
  202. {
  203. var outputImageBuffer = new NativeArray<Color32>(doc.width * doc.height, Allocator.Persistent);
  204. try
  205. {
  206. var spriteImportData = GetSpriteImportData();
  207. FlattenImageTask.Execute(m_ExtractData, ref outputImageBuffer, m_ImportHiddenLayers, canvasSize);
  208. if (spriteImportData.Count <= 0 || spriteImportData[0] == null)
  209. {
  210. spriteImportData.Add(new SpriteMetaData());
  211. }
  212. spriteImportData[0].name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath) + "_1";
  213. spriteImportData[0].alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  214. spriteImportData[0].border = m_TextureImporterSettings.spriteBorder;
  215. spriteImportData[0].pivot = m_TextureImporterSettings.spritePivot;
  216. spriteImportData[0].rect = new Rect(0, 0, doc.width, doc.height);
  217. importData.importedTextureWidth = textureActualWidth = doc.width;
  218. importData.importedTextureHeight = textureActualHeight = doc.height;
  219. var spriteRects = new SpriteMetaData[0];
  220. if (m_TextureImporterSettings.textureType == TextureImporterType.Sprite)
  221. {
  222. if (singleSpriteMode)
  223. spriteRects = new[] { spriteImportData[0] };
  224. else if (spriteImportData.Count > 1)
  225. spriteRects = spriteImportData.GetRange(1, spriteDataCount).ToArray();
  226. }
  227. var output = ImportTexture(ctx, outputImageBuffer, doc.width, doc.height, spriteRects);
  228. importData.importedTextureWidth = output.texture.width;
  229. importData.importedTextureHeight = output.texture.height;
  230. RegisterAssets(ctx, output);
  231. }
  232. finally
  233. {
  234. outputImageBuffer.Dispose();
  235. }
  236. }
  237. else
  238. {
  239. ImportFromLayers(ctx);
  240. }
  241. if (!string.IsNullOrEmpty(m_SkeletonAssetReferenceID))
  242. {
  243. var primaryAssetPath = AssetDatabase.GUIDToAssetPath(m_SkeletonAssetReferenceID);
  244. if(!string.IsNullOrEmpty(primaryAssetPath) && primaryAssetPath != assetPath)
  245. {
  246. ctx.DependsOnArtifact(primaryAssetPath);
  247. }
  248. }
  249. ctx.AddObjectToAsset("PSDImportData", m_ImportData);
  250. }
  251. finally
  252. {
  253. fileStream.Close();
  254. if (doc != null)
  255. doc.Dispose();
  256. UnityEngine.Profiling.Profiler.EndSample();
  257. EditorUtility.SetDirty(this);
  258. }
  259. }
  260. static void ValidatePSDLayerId(IEnumerable<PSDLayer> oldPsdLayer, IEnumerable<BitmapLayer> layers, UniqueNameGenerator uniqueNameGenerator)
  261. {
  262. // first check if all layers are unique. If not, we use back the previous layer id based on name match
  263. HashSet<int> uniqueIdSet = new HashSet<int>();
  264. bool useOldID = false;
  265. foreach(var layer in layers)
  266. {
  267. if (uniqueIdSet.Contains(layer.LayerID))
  268. {
  269. useOldID = true;
  270. break;
  271. }
  272. uniqueIdSet.Add(layer.LayerID);
  273. }
  274. for (int i = 0; i < layers.Count(); ++i)
  275. {
  276. var childBitmapLayer = layers.ElementAt(i);
  277. // fix case 1291323
  278. if (useOldID)
  279. {
  280. var oldLayers = oldPsdLayer.Where(x => x.name == childBitmapLayer.Name);
  281. if (oldLayers.Count() == 0)
  282. oldLayers = oldPsdLayer.Where(x => x.layerID == childBitmapLayer.Name.GetHashCode());
  283. // pick one that is not already on the list
  284. foreach (var ol in oldLayers)
  285. {
  286. if (!uniqueNameGenerator.ContainHash(ol.layerID))
  287. {
  288. childBitmapLayer.LayerID = ol.layerID;
  289. break;
  290. }
  291. }
  292. }
  293. if (uniqueNameGenerator.ContainHash(childBitmapLayer.LayerID))
  294. {
  295. var importWarning = string.Format("Layer {0}: LayerId is not unique. Mapping will be done by Layer's name.", childBitmapLayer.Name);
  296. var layerName = uniqueNameGenerator.GetUniqueName(childBitmapLayer.Name);
  297. if (layerName != childBitmapLayer.Name)
  298. importWarning += "\nLayer names are not unique. Please ensure they are unique to for SpriteRect to be mapped back correctly.";
  299. childBitmapLayer.LayerID = layerName.GetHashCode();
  300. Debug.LogWarning(importWarning);
  301. }
  302. else
  303. uniqueNameGenerator.AddHash(childBitmapLayer.LayerID);
  304. if (childBitmapLayer.ChildLayer != null)
  305. {
  306. ValidatePSDLayerId(oldPsdLayer, childBitmapLayer.ChildLayer, uniqueNameGenerator);
  307. }
  308. }
  309. }
  310. void ValidatePSDLayerId(Document doc)
  311. {
  312. if (m_LayerMappingOption == ELayerMappingOption.UseLayerId)
  313. {
  314. UniqueNameGenerator uniqueNameGenerator = new UniqueNameGenerator();
  315. ValidatePSDLayerId(GetPSDLayers(), doc.Layers, uniqueNameGenerator);
  316. }
  317. }
  318. TextureGenerationOutput ImportTexture(AssetImportContext ctx, NativeArray<Color32> imageData, int textureWidth, int textureHeight, SpriteMetaData[] sprites)
  319. {
  320. if (!imageData.IsCreated || imageData.Length == 0)
  321. return new TextureGenerationOutput();
  322. UnityEngine.Profiling.Profiler.BeginSample("ImportTexture");
  323. var platformSettings = GetPlatformTextureSettings(ctx.selectedBuildTarget);
  324. var textureSettings = m_TextureImporterSettings.ExtractTextureSettings();
  325. textureSettings.assetPath = ctx.assetPath;
  326. textureSettings.enablePostProcessor = true;
  327. textureSettings.containsAlpha = true;
  328. textureSettings.hdr = false;
  329. var textureAlphaSettings = m_TextureImporterSettings.ExtractTextureAlphaSettings();
  330. var textureMipmapSettings = m_TextureImporterSettings.ExtractTextureMipmapSettings();
  331. var textureCubemapSettings = m_TextureImporterSettings.ExtractTextureCubemapSettings();
  332. var textureWrapSettings = m_TextureImporterSettings.ExtractTextureWrapSettings();
  333. TextureGenerationOutput output;
  334. switch (m_TextureImporterSettings.textureType)
  335. {
  336. case TextureImporterType.Default:
  337. output = TextureGeneratorHelper.GenerateTextureDefault(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  338. break;
  339. case TextureImporterType.NormalMap:
  340. var textureNormalSettings = m_TextureImporterSettings.ExtractTextureNormalSettings();
  341. output = TextureGeneratorHelper.GenerateNormalMap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureNormalSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  342. break;
  343. case TextureImporterType.GUI:
  344. output = TextureGeneratorHelper.GenerateTextureGUI(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  345. break;
  346. case TextureImporterType.Sprite:
  347. var textureSpriteSettings = m_TextureImporterSettings.ExtractTextureSpriteSettings();
  348. textureSpriteSettings.packingTag = m_SpritePackingTag;
  349. textureSpriteSettings.qualifyForPacking = !string.IsNullOrEmpty(m_SpritePackingTag);
  350. textureSpriteSettings.spriteSheetData = new SpriteImportData[sprites.Length];
  351. textureSettings.npotScale = TextureImporterNPOTScale.None;
  352. textureSettings.secondaryTextures = secondaryTextures;
  353. for (int i = 0; i < sprites.Length; ++i)
  354. textureSpriteSettings.spriteSheetData[i] = sprites[i];
  355. output = TextureGeneratorHelper.GenerateTextureSprite(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureSpriteSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  356. break;
  357. case TextureImporterType.Cursor:
  358. output = TextureGeneratorHelper.GenerateTextureCursor(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  359. break;
  360. case TextureImporterType.Cookie:
  361. output = TextureGeneratorHelper.GenerateCookie(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  362. break;
  363. case TextureImporterType.Lightmap:
  364. output = TextureGeneratorHelper.GenerateLightmap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureMipmapSettings, textureWrapSettings);
  365. break;
  366. case TextureImporterType.SingleChannel:
  367. output = TextureGeneratorHelper.GenerateTextureSingleChannel(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  368. break;
  369. default:
  370. Debug.LogAssertion("Unknown texture type for import");
  371. output = default(TextureGenerationOutput);
  372. break;
  373. }
  374. UnityEngine.Profiling.Profiler.EndSample();
  375. return output;
  376. }
  377. string GetUniqueSpriteName(string name, UniqueNameGenerator generator)
  378. {
  379. if (m_KeepDupilcateSpriteName)
  380. return name;
  381. return generator.GetUniqueName(name);
  382. }
  383. void SetDocumentImportData(IEnumerable<BitmapLayer> layers, PSDExtractLayerData[] extractData, IPSDLayerMappingStrategy mappingStrategy, List<PSDLayer> psdLayers, PSDExtractLayerData parent = null)
  384. {
  385. for (int i = 0; i < layers.Count(); ++i)
  386. {
  387. var layer = layers.ElementAt(i);
  388. PSDLayerImportSetting importSetting = null;
  389. if (m_PSDLayerImportSetting != null && m_PSDLayerImportSetting.Length > 0)
  390. {
  391. importSetting = m_PSDLayerImportSetting.FirstOrDefault(x => mappingStrategy.Compare(x, layer));
  392. }
  393. var c = psdLayers?.FirstOrDefault(x => mappingStrategy.Compare(x, layer));
  394. if (c != null)
  395. {
  396. if(c.spriteID.Empty())
  397. c.spriteID = importSetting != null ? importSetting.spriteId : GUID.Generate();
  398. if (importSetting == null)
  399. {
  400. importSetting = new PSDLayerImportSetting()
  401. {
  402. flatten = c.flatten,
  403. };
  404. }
  405. importSetting.spriteId = c.spriteID;
  406. }
  407. if (importSetting == null)
  408. {
  409. importSetting = new PSDLayerImportSetting()
  410. {
  411. flatten = false
  412. };
  413. }
  414. extractData[i] = new PSDExtractLayerData()
  415. {
  416. bitmapLayer = layer,
  417. importSetting = importSetting,
  418. };
  419. PSDExtractLayerData[] childrenextractData = null;
  420. if (layer.ChildLayer != null)
  421. {
  422. childrenextractData = new PSDExtractLayerData[layer.ChildLayer.Count()];
  423. SetDocumentImportData(layer.ChildLayer, childrenextractData, mappingStrategy, psdLayers, extractData[i]);
  424. }
  425. extractData[i].children = childrenextractData;
  426. }
  427. }
  428. void SetDocumentImportData(Document doc)
  429. {
  430. var oldPsdLayers = GetPSDLayers();
  431. var mappingStrategy = GetLayerMappingStrategy();
  432. m_ExtractData = new PSDExtractLayerData[doc.Layers.Count];
  433. SetDocumentImportData(doc.Layers, m_ExtractData, mappingStrategy, oldPsdLayers);
  434. }
  435. void ImportFromLayers(AssetImportContext ctx)
  436. {
  437. var output = default(NativeArray<Color32>);
  438. var layerIndex = new List<int>();
  439. var spriteNameHash = new UniqueNameGenerator();
  440. var oldPsdLayers = GetPSDLayers();
  441. List<PSDLayer> psdLayers = null;
  442. try
  443. {
  444. ExtractLayerTask.Execute(in m_ExtractData, out psdLayers, m_ImportHiddenLayers, canvasSize);
  445. var mappingStrategy = GetLayerMappingStrategy();
  446. var layerUnique = mappingStrategy.LayersUnique(psdLayers.ConvertAll(x => (IPSDLayerMappingStrategyComparable)x));
  447. if (!string.IsNullOrEmpty(layerUnique))
  448. {
  449. Debug.LogWarning(layerUnique,this);
  450. }
  451. var removedLayersSprite = oldPsdLayers.Where(x => psdLayers.FirstOrDefault(y => mappingStrategy.Compare(y, x)) == null).Select(z => z.spriteID).ToArray();
  452. bool hasNewLayer = false;
  453. for (int i = 0; i < psdLayers.Count; ++i)
  454. {
  455. int j = 0;
  456. var psdLayer = psdLayers[i];
  457. for (; j < oldPsdLayers.Count; ++j)
  458. {
  459. if (mappingStrategy.Compare(psdLayer, oldPsdLayers[j]))
  460. {
  461. if(oldPsdLayers[j].spriteID.Empty())
  462. oldPsdLayers[j].spriteID = GUID.Generate();
  463. psdLayer.spriteID = oldPsdLayers[j].spriteID;
  464. psdLayer.spriteName = oldPsdLayers[j].spriteName;
  465. psdLayer.mosaicPosition = oldPsdLayers[j].mosaicPosition;
  466. if (psdLayer.isImported != oldPsdLayers[j].isImported)
  467. hasNewLayer = true;
  468. break;
  469. }
  470. }
  471. if(j >= oldPsdLayers.Count)
  472. hasNewLayer = true;
  473. }
  474. var layerBuffers = new List<NativeArray<Color32>>();
  475. var layerWidth = new List<int>();
  476. var layerHeight = new List<int>();
  477. for (var i = 0; i < psdLayers.Count; ++i)
  478. {
  479. var l = psdLayers[i];
  480. var expectedBufferLength = l.width * l.height;
  481. if (l.texture.IsCreated && l.texture.Length == expectedBufferLength && l.isImported)
  482. {
  483. layerBuffers.Add(l.texture);
  484. layerIndex.Add(i);
  485. layerWidth.Add(l.width);
  486. layerHeight.Add(l.height);
  487. }
  488. }
  489. const int padding = 4;
  490. ImagePacker.Pack(layerBuffers.ToArray(), layerWidth.ToArray(), layerHeight.ToArray(), padding, out output, out int width, out int height, out RectInt[] spriteData, out Vector2Int[] uvTransform);
  491. var packOffsets = new Vector2[spriteData.Length];
  492. for (var i = 0; i < packOffsets.Length; ++i)
  493. packOffsets[i] = new Vector2((uvTransform[i].x - spriteData[i].position.x) / -1f, (uvTransform[i].y - spriteData[i].position.y) / -1f);
  494. var spriteImportData = GetSpriteImportData();
  495. if (spriteImportData.Count <= 0 || shouldResliceFromLayer || hasNewLayer)
  496. {
  497. var newSpriteMeta = new List<SpriteMetaData>();
  498. for (int i = 0; i < spriteData.Length && i < layerIndex.Count; ++i)
  499. {
  500. var psdLayer = psdLayers[layerIndex[i]];
  501. var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayer.spriteID);
  502. if (spriteSheet == null)
  503. {
  504. spriteSheet = new SpriteMetaData();
  505. spriteSheet.border = Vector4.zero;
  506. spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  507. spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
  508. spriteSheet.rect = new Rect(spriteData[i].x, spriteData[i].y, spriteData[i].width, spriteData[i].height);
  509. spriteSheet.spriteID = psdLayer.spriteID;
  510. }
  511. else
  512. {
  513. var r = spriteSheet.rect;
  514. r.position = r.position - psdLayer.mosaicPosition + spriteData[i].position;
  515. spriteSheet.rect = r;
  516. }
  517. psdLayer.spriteName = GetUniqueSpriteName(psdLayer.name, spriteNameHash);
  518. spriteSheet.name = psdLayer.spriteName;
  519. spriteSheet.spritePosition = psdLayer.layerPosition + packOffsets[i];
  520. if(shouldResliceFromLayer)
  521. spriteSheet.rect = new Rect(spriteData[i].x, spriteData[i].y, spriteData[i].width, spriteData[i].height);
  522. spriteSheet.uvTransform = uvTransform[i];
  523. psdLayer.spriteID = spriteSheet.spriteID;
  524. psdLayer.mosaicPosition = spriteData[i].position;
  525. newSpriteMeta.Add(spriteSheet);
  526. }
  527. spriteImportData.Clear();
  528. spriteImportData.AddRange(newSpriteMeta);
  529. }
  530. else
  531. {
  532. spriteImportData.RemoveAll(x => removedLayersSprite.Contains(x.spriteID));
  533. // First look for any user created SpriteRect and add those into the name hash
  534. foreach (var importData in spriteImportData)
  535. {
  536. var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == importData.spriteID);
  537. if (psdLayer == null)
  538. spriteNameHash.AddHash(importData.name);
  539. }
  540. foreach (var importData in spriteImportData)
  541. {
  542. var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == importData.spriteID);
  543. if (psdLayer == null)
  544. importData.uvTransform = new Vector2Int((int)importData.rect.position.x, (int)importData.rect.position.y);
  545. // If it is user created rect or the name has been changed before
  546. // add it into the spriteNameHash and we don't copy it over from the layer
  547. if (psdLayer == null || psdLayer.spriteName != importData.name)
  548. spriteNameHash.AddHash(importData.name);
  549. // If the sprite name has not been changed, we ensure the new
  550. // layer name is still unique and use it as the sprite name
  551. if (psdLayer != null && psdLayer.spriteName == importData.name)
  552. {
  553. psdLayer.spriteName = GetUniqueSpriteName(psdLayer.name, spriteNameHash);
  554. importData.name = psdLayer.spriteName;
  555. }
  556. }
  557. //Update names for those user has not changed and add new sprite rect based on PSD file.
  558. for (int k = 0; k < layerIndex.Count; ++k)
  559. {
  560. int i = layerIndex[k];
  561. var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[i].spriteID);
  562. var inOldLayer = oldPsdLayers.FindIndex(x => mappingStrategy.Compare(x,psdLayers[i])) != -1;
  563. if (spriteSheet == null && !inOldLayer)
  564. {
  565. spriteSheet = new SpriteMetaData();
  566. spriteImportData.Add(spriteSheet);
  567. spriteSheet.rect = new Rect(spriteData[k].x, spriteData[k].y, spriteData[k].width, spriteData[k].height);
  568. spriteSheet.border = Vector4.zero;
  569. spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  570. spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
  571. spriteSheet.spritePosition = psdLayers[i].layerPosition;
  572. psdLayers[i].spriteName = GetUniqueSpriteName(psdLayers[i].name, spriteNameHash);
  573. spriteSheet.name = psdLayers[i].spriteName;
  574. }
  575. else if (spriteSheet != null)
  576. {
  577. var r = spriteSheet.rect;
  578. r.position = spriteSheet.rect.position - psdLayers[i].mosaicPosition + spriteData[k].position;
  579. spriteSheet.rect = r;
  580. spriteSheet.spritePosition = psdLayers[i].layerPosition + packOffsets[k];
  581. }
  582. if (spriteSheet != null)
  583. {
  584. spriteSheet.uvTransform = uvTransform[k];
  585. psdLayers[i].spriteID = spriteSheet.spriteID;
  586. psdLayers[i].mosaicPosition = spriteData[k].position;
  587. }
  588. }
  589. }
  590. foreach (var l in oldPsdLayers)
  591. l.Dispose();
  592. oldPsdLayers.Clear();
  593. oldPsdLayers.AddRange(psdLayers);
  594. importData.importedTextureHeight = textureActualHeight = height;
  595. importData.importedTextureWidth = textureActualWidth = width;
  596. var generatedTexture = ImportTexture(ctx, output, width, height, spriteImportData.ToArray());
  597. if (generatedTexture.texture)
  598. {
  599. importData.importedTextureHeight = generatedTexture.texture.height;
  600. importData.importedTextureWidth = generatedTexture.texture.width;
  601. }
  602. RegisterAssets(ctx, generatedTexture);
  603. }
  604. finally
  605. {
  606. if (output.IsCreated)
  607. output.Dispose();
  608. foreach (var l in oldPsdLayers)
  609. l.Dispose();
  610. }
  611. }
  612. void EnsureSingleSpriteExist()
  613. {
  614. if (m_SpriteImportData.Count <= 0)
  615. m_SpriteImportData.Add(new SpriteMetaData()); // insert default for single sprite mode
  616. }
  617. internal TextureImporterPlatformSettings GetPlatformTextureSettings(BuildTarget buildTarget)
  618. {
  619. var buildTargetName = TexturePlatformSettingsHelper.GetBuildTargetGroupName(buildTarget);
  620. TextureImporterPlatformSettings platformSettings = null;
  621. platformSettings = m_PlatformSettings.SingleOrDefault(x => x.name == buildTargetName && x.overridden == true);
  622. platformSettings = platformSettings ?? m_PlatformSettings.SingleOrDefault(x => x.name == TexturePlatformSettingsHelper.defaultPlatformName);
  623. if (platformSettings == null)
  624. {
  625. platformSettings = new TextureImporterPlatformSettings();
  626. platformSettings.name = buildTargetName;
  627. platformSettings.overridden = false;
  628. }
  629. return platformSettings;
  630. }
  631. void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
  632. {
  633. if ((output.sprites == null || output.sprites.Length == 0) && output.texture == null)
  634. {
  635. Debug.LogWarning("No Sprites or Texture are generated. Possibly because all layers in file are hidden", this);
  636. return;
  637. }
  638. SetPhysicsOutline(output.texture, output.sprites);
  639. UniqueNameGenerator assetNameHash = new UniqueNameGenerator();
  640. if (!string.IsNullOrEmpty(output.importInspectorWarnings))
  641. {
  642. Debug.LogWarning(output.importInspectorWarnings);
  643. }
  644. if (output.importWarnings != null && output.importWarnings.Length != 0)
  645. {
  646. foreach (var warning in output.importWarnings)
  647. Debug.LogWarning(warning);
  648. }
  649. if (output.thumbNail == null)
  650. Debug.LogWarning("Thumbnail generation fail");
  651. if (output.texture == null)
  652. {
  653. throw new Exception("Texture import fail");
  654. }
  655. var assetName = assetNameHash.GetUniqueName(System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath), true, this);
  656. // Setup all fixed name on the hash table
  657. var registerTextureNameId = string.IsNullOrEmpty(m_TextureAssetName) ? "Texture" : m_TextureAssetName;
  658. var prefabRootNameId = string.IsNullOrEmpty(m_TextureAssetName) ? "root" : m_TextureAssetName;
  659. var registerPrefabNameId = string.IsNullOrEmpty(m_PrefabAssetName) ? "Prefab" : m_PrefabAssetName;
  660. var spriteLibAssetNameId = string.IsNullOrEmpty(m_SpriteLibAssetName) ? "SpriteLibAsset" : m_SpriteLibAssetName;
  661. var skeletonAssetNameId = string.IsNullOrEmpty(m_SkeletonAssetName) ? "SkeletonAsset" : m_SkeletonAssetName;
  662. output.texture.name = assetName;
  663. ctx.AddObjectToAsset(registerTextureNameId, output.texture, output.thumbNail);
  664. UnityEngine.Object mainAsset = output.texture;
  665. if (output.sprites != null)
  666. {
  667. var slAsset = ProduceSpriteLibAsset(output.sprites);
  668. if (shouldProduceGameObject)
  669. {
  670. GameObject prefab = null;
  671. if (m_PaperDollMode)
  672. prefab = OnProducePaperDollPrefab(prefabRootNameId, output.sprites, slAsset);
  673. else
  674. prefab = OnProducePrefab(prefabRootNameId, output.sprites, slAsset);
  675. if (prefab != null)
  676. {
  677. ctx.AddObjectToAsset(registerPrefabNameId, prefab);
  678. mainAsset = prefab;
  679. }
  680. }
  681. foreach (var s in output.sprites)
  682. {
  683. var spriteAssetName = assetNameHash.GetUniqueName(s.GetSpriteID().ToString(), false, s);
  684. ctx.AddObjectToAsset(spriteAssetName, s);
  685. }
  686. if (slAsset != null)
  687. {
  688. slAsset.name = assetName;
  689. ctx.AddObjectToAsset(spriteLibAssetNameId, slAsset);
  690. }
  691. if (characterMode && skeletonAsset == null)
  692. {
  693. var characterRig = ScriptableObject.CreateInstance<SkeletonAsset>();
  694. characterRig.name = assetName + " Skeleton";
  695. var bones = GetDataProvider<ICharacterDataProvider>().GetCharacterData().bones;
  696. characterRig.SetSpriteBones(bones);
  697. ctx.AddObjectToAsset(skeletonAssetNameId, characterRig);
  698. }
  699. }
  700. ctx.SetMainObject(mainAsset);
  701. }
  702. bool SpriteIsMainFromSpriteLib(string spriteId, out string categoryName)
  703. {
  704. categoryName = "";
  705. if (m_SpriteCategoryList.categories != null)
  706. {
  707. foreach (var category in m_SpriteCategoryList.categories)
  708. {
  709. var index = category.labels.FindIndex(x => x.spriteId == spriteId);
  710. if (index == 0)
  711. {
  712. categoryName = category.name;
  713. return true;
  714. }
  715. if (index > 0)
  716. return false;
  717. }
  718. }
  719. return true;
  720. }
  721. bool VisibleInHierarchy(List<PSDLayer> psdGroup, int index)
  722. {
  723. var psdLayer = psdGroup[index];
  724. var parentVisible = true;
  725. if (psdLayer.parentIndex >= 0)
  726. parentVisible = VisibleInHierarchy(psdGroup, psdLayer.parentIndex);
  727. return parentVisible && psdLayer.isVisible;
  728. }
  729. void BuildGroupGameObject(List<PSDLayer> psdGroup, int index, Transform root)
  730. {
  731. var psdData = psdGroup[index];
  732. if (psdData.gameObject == null)
  733. {
  734. var spriteImported = !psdGroup[index].spriteID.Empty() && psdGroup[index].isImported;
  735. var isVisibleGroup = psdData.isGroup && (VisibleInHierarchy(psdGroup, index) || m_ImportHiddenLayers) && m_GenerateGOHierarchy;
  736. if (spriteImported || isVisibleGroup)
  737. {
  738. var spriteData = GetSpriteImportData().FirstOrDefault(x => x.spriteID == psdData.spriteID);
  739. // Determine if need to create GameObject i.e. if the sprite is not in a SpriteLib or if it is the first one
  740. string categoryName;
  741. var b = SpriteIsMainFromSpriteLib(psdData.spriteID.ToString(), out categoryName);
  742. string goName = string.IsNullOrEmpty(categoryName) ? spriteData != null ? spriteData.name : psdData.name : categoryName;
  743. if (b)
  744. psdData.gameObject = m_GameObjectFactory.CreateGameObject(goName);
  745. }
  746. if (psdData.parentIndex >= 0 && m_GenerateGOHierarchy && psdData.gameObject != null)
  747. {
  748. BuildGroupGameObject(psdGroup, psdData.parentIndex, root);
  749. root = psdGroup[psdData.parentIndex].gameObject.transform;
  750. }
  751. if (psdData.gameObject != null)
  752. {
  753. psdData.gameObject.transform.SetParent(root);
  754. psdData.gameObject.transform.SetSiblingIndex(root.childCount-1);
  755. }
  756. }
  757. }
  758. bool shouldProduceGameObject
  759. {
  760. get { return m_CharacterMode && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
  761. }
  762. bool shouldResliceFromLayer
  763. {
  764. get { return m_ResliceFromLayer && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
  765. }
  766. bool characterMode
  767. {
  768. get { return mosaicMode && m_CharacterMode; }
  769. }
  770. float definitionScale
  771. {
  772. get
  773. {
  774. float definitionScaleW = importData.importedTextureWidth / (float)textureActualWidth;
  775. float definitionScaleH = importData.importedTextureHeight / (float)textureActualHeight;
  776. return Mathf.Min(definitionScaleW, definitionScaleH);
  777. }
  778. }
  779. internal static Vector2 GetPivotPoint(Rect rect, SpriteAlignment alignment, Vector2 customPivot)
  780. {
  781. switch (alignment)
  782. {
  783. case SpriteAlignment.TopLeft:
  784. return new Vector2(rect.xMin, rect.yMax);
  785. case SpriteAlignment.TopCenter:
  786. return new Vector2(rect.center.x, rect.yMax);
  787. case SpriteAlignment.TopRight:
  788. return new Vector2(rect.xMax, rect.yMax);
  789. case SpriteAlignment.LeftCenter:
  790. return new Vector2(rect.xMin, rect.center.y);
  791. case SpriteAlignment.Center:
  792. return new Vector2(rect.center.x, rect.center.y);
  793. case SpriteAlignment.RightCenter:
  794. return new Vector2(rect.xMax, rect.center.y);
  795. case SpriteAlignment.BottomLeft:
  796. return new Vector2(rect.xMin, rect.yMin);
  797. case SpriteAlignment.BottomCenter:
  798. return new Vector2(rect.center.x, rect.yMin);
  799. case SpriteAlignment.BottomRight:
  800. return new Vector2(rect.xMax, rect.yMin);
  801. case SpriteAlignment.Custom:
  802. return new Vector2(customPivot.x * rect.width, customPivot.y * rect.height);
  803. }
  804. return Vector2.zero;
  805. }
  806. void CreateBoneGO(int index, SpriteBone[] bones, BoneGO[] bonesGO, Transform defaultRoot)
  807. {
  808. if (bonesGO[index].go != null)
  809. return;
  810. var bone = bones[index];
  811. if (bone.parentId != -1 && bonesGO[bone.parentId].go == null)
  812. CreateBoneGO(bone.parentId, bones, bonesGO, defaultRoot);
  813. var go = m_GameObjectFactory.CreateGameObject(bone.name);
  814. if (bone.parentId == -1)
  815. go.transform.SetParent(defaultRoot);
  816. else
  817. go.transform.SetParent(bonesGO[bone.parentId].go.transform);
  818. go.transform.localPosition = bone.position * 1 / pixelsPerUnit;
  819. go.transform.localRotation = bone.rotation;
  820. bonesGO[index] = new BoneGO()
  821. {
  822. go = go,
  823. index = index
  824. };
  825. }
  826. BoneGO[] CreateBonesGO(Transform root)
  827. {
  828. if (characterMode)
  829. {
  830. var characterSkeleton = GetDataProvider<ICharacterDataProvider>().GetCharacterData();
  831. var bones = characterSkeleton.bones;
  832. if (bones != null)
  833. {
  834. var boneGOs = new BoneGO[bones.Length];
  835. for (int i = 0; i < bones.Length; ++i)
  836. {
  837. CreateBoneGO(i, bones, boneGOs, root);
  838. }
  839. return boneGOs;
  840. }
  841. }
  842. return new BoneGO[0];
  843. }
  844. void GetSpriteLiblabel(string spriteId, out string category, out string label)
  845. {
  846. category = "";
  847. label = "";
  848. var index = -1;
  849. foreach (var cat in m_SpriteCategoryList.categories)
  850. {
  851. index = cat.labels.FindIndex(x => x.spriteId == spriteId);
  852. if (index != -1)
  853. {
  854. category = cat.name;
  855. label = cat.labels[index].name;
  856. break;
  857. }
  858. }
  859. }
  860. GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
  861. {
  862. GameObject root = null;
  863. CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
  864. if (sprites != null && sprites.Length > 0)
  865. {
  866. root = new GameObject();
  867. root.name = assetname + "_GO";
  868. var spriteImportData = GetSpriteImportData();
  869. var psdLayers = GetPSDLayers();
  870. var boneGOs = CreateBonesGO(root.transform);
  871. if (spriteLib != null)
  872. root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
  873. var currentCharacterData = characterData;
  874. for (int i = 0; i < sprites.Length; ++i)
  875. {
  876. string categoryName;
  877. if (SpriteIsMainFromSpriteLib(sprites[i].GetSpriteID().ToString(), out categoryName))
  878. {
  879. var spriteBones = currentCharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == sprites[i].GetSpriteID()).bones;
  880. var rootBone = root;
  881. if (spriteBones != null && spriteBones.Any())
  882. {
  883. var b = spriteBones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]).OrderBy(x => x.index);
  884. if (b.Any())
  885. rootBone = b.First().go;
  886. }
  887. var srGameObject = m_GameObjectFactory.CreateGameObject(string.IsNullOrEmpty(categoryName) ? sprites[i].name : categoryName);
  888. var sr = srGameObject.AddComponent<SpriteRenderer>();
  889. sr.sprite = sprites[i];
  890. sr.sortingOrder = psdLayers.Count - psdLayers.FindIndex(x => x.spriteID == sprites[i].GetSpriteID());
  891. srGameObject.transform.parent = rootBone.transform;
  892. var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == sprites[i].GetSpriteID());
  893. if (spriteMetaData != null)
  894. {
  895. var uvTransform = spriteMetaData.uvTransform;
  896. var outlineOffset = new Vector2(spriteMetaData.rect.x - uvTransform.x + (spriteMetaData.pivot.x * spriteMetaData.rect.width),
  897. spriteMetaData.rect.y - uvTransform.y + (spriteMetaData.pivot.y * spriteMetaData.rect.height)) * definitionScale / sprites[i].pixelsPerUnit;
  898. srGameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
  899. }
  900. var category = "";
  901. var labelName = "";
  902. GetSpriteLiblabel(sprites[i].GetSpriteID().ToString(), out category, out labelName);
  903. if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
  904. {
  905. var sresolver = srGameObject.AddComponent<SpriteResolver>();
  906. sresolver.SetCategoryAndLabel(category, labelName);
  907. sresolver.ResolveSpriteToSpriteRenderer();
  908. }
  909. }
  910. }
  911. }
  912. return root;
  913. }
  914. internal void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings)
  915. {
  916. var index = m_PlatformSettings.FindIndex(x => x.name == platformSettings.name);
  917. if(index < 0)
  918. m_PlatformSettings.Add(platformSettings);
  919. else
  920. m_PlatformSettings[index] = platformSettings;
  921. }
  922. internal TextureImporterPlatformSettings[] GetAllPlatformSettings()
  923. {
  924. return m_PlatformSettings.ToArray();
  925. }
  926. GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
  927. {
  928. GameObject root = null;
  929. CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
  930. if (sprites != null && sprites.Length > 0)
  931. {
  932. var currentCharacterData = characterData;
  933. var spriteImportData = GetSpriteImportData();
  934. root = new GameObject();
  935. root.transform.SetSiblingIndex(0);
  936. root.name = assetname + "_GO";
  937. if (spriteLib != null)
  938. root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
  939. var psdLayers = GetPSDLayers();
  940. for (var i = 0; i < psdLayers.Count; ++i)
  941. {
  942. BuildGroupGameObject(psdLayers, i, root.transform);
  943. }
  944. var boneGOs = CreateBonesGO(root.transform);
  945. for (var i = 0; i < psdLayers.Count; ++i)
  946. {
  947. var l = psdLayers[i];
  948. var layerSpriteID = l.spriteID;
  949. var sprite = sprites.FirstOrDefault(x => x.GetSpriteID() == layerSpriteID);
  950. var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == layerSpriteID);
  951. if (sprite != null && spriteMetaData != null && l.gameObject != null)
  952. {
  953. var spriteRenderer = l.gameObject.AddComponent<SpriteRenderer>();
  954. spriteRenderer.sprite = sprite;
  955. spriteRenderer.sortingOrder = psdLayers.Count - i;
  956. var pivot = spriteMetaData.pivot;
  957. pivot.x *= spriteMetaData.rect.width;
  958. pivot.y *= spriteMetaData.rect.height;
  959. var spritePosition = spriteMetaData.spritePosition;
  960. spritePosition.x += pivot.x;
  961. spritePosition.y += pivot.y;
  962. spritePosition *= (definitionScale / sprite.pixelsPerUnit);
  963. l.gameObject.transform.position = new Vector3(spritePosition.x, spritePosition.y, 0f);
  964. if (characterSkeleton != null)
  965. {
  966. var part = characterSkeleton.Value.parts.FirstOrDefault(x => x.spriteId == spriteMetaData.spriteID.ToString());
  967. if (part.bones != null && part.bones.Length > 0)
  968. {
  969. var spriteSkin = l.gameObject.AddComponent<SpriteSkin>();
  970. if (spriteRenderer.sprite != null && spriteRenderer.sprite.GetBindPoses().Length > 0)
  971. {
  972. var spriteBones = currentCharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == spriteRenderer.sprite.GetSpriteID()).bones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]);
  973. if (spriteBones.Any())
  974. {
  975. spriteSkin.rootBone = spriteBones.OrderBy(x => x.index).First().go.transform;
  976. spriteSkin.boneTransforms = spriteBones.Select(x => x.go.transform).ToArray();
  977. if (spriteSkin.isValid)
  978. spriteSkin.CalculateBounds();
  979. }
  980. }
  981. }
  982. }
  983. var category = "";
  984. var labelName = "";
  985. GetSpriteLiblabel(layerSpriteID.ToString(), out category, out labelName);
  986. if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
  987. {
  988. var sresolver = l.gameObject.AddComponent<SpriteResolver>();
  989. sresolver.SetCategoryAndLabel(category, labelName);
  990. sresolver.ResolveSpriteToSpriteRenderer();
  991. }
  992. }
  993. }
  994. var prefabBounds = new Rect(0 , 0, importData.documentSize.x / pixelsPerUnit, importData.documentSize.y / pixelsPerUnit);
  995. var documentPivot = (Vector3)GetPivotPoint(prefabBounds, m_DocumentAlignment, m_DocumentPivot);
  996. for (int i = 0; i < psdLayers.Count; ++i)
  997. {
  998. var l = psdLayers[i];
  999. if (l.gameObject == null || l.gameObject.GetComponent<SpriteRenderer>() == null)
  1000. continue;
  1001. var p = l.gameObject.transform.localPosition;
  1002. p -= documentPivot;
  1003. l.gameObject.transform.localPosition = p;
  1004. }
  1005. for (int i = 0; i < boneGOs.Length; ++i)
  1006. {
  1007. if (boneGOs[i].go.transform.parent != root.transform)
  1008. continue;
  1009. var p = boneGOs[i].go.transform.position;
  1010. p -= documentPivot;
  1011. boneGOs[i].go.transform.position = p;
  1012. }
  1013. }
  1014. return root;
  1015. }
  1016. Bounds? GetBoundingBox(GameObject root)
  1017. {
  1018. Bounds? prefabBounds1 = null;
  1019. var sr = root.GetComponent<SpriteRenderer>();
  1020. if (sr != null)
  1021. {
  1022. prefabBounds1 = sr.bounds;
  1023. }
  1024. for (int i = 0; i < root.transform.childCount; ++i)
  1025. {
  1026. var b = GetBoundingBox(root.transform.GetChild(i).gameObject);
  1027. if (prefabBounds1 == null)
  1028. prefabBounds1 = b;
  1029. else
  1030. {
  1031. if (b.HasValue)
  1032. {
  1033. var bb = prefabBounds1.Value;
  1034. bb.Encapsulate(b.Value);
  1035. prefabBounds1 = bb;
  1036. }
  1037. }
  1038. }
  1039. return prefabBounds1;
  1040. }
  1041. bool CleanUpGameobjectsWithOutRig(GameObject root)
  1042. {
  1043. var sr = root.GetComponent<SpriteRenderer>();
  1044. var canDelete = true;
  1045. if (sr != null && sr.sprite != null)
  1046. {
  1047. try
  1048. {
  1049. var bones = GetDataProvider<ISpriteBoneDataProvider>().GetBones(sr.sprite.GetSpriteID());
  1050. canDelete = bones == null || bones.Count == 0;
  1051. }
  1052. catch (Exception e)
  1053. {
  1054. Debug.LogError(e);
  1055. }
  1056. }
  1057. List<GameObject> cleanup = new List<GameObject>();
  1058. for (int i = 0; i < root.transform.childCount; ++i)
  1059. {
  1060. var go = root.transform.GetChild(i);
  1061. if (CleanUpGameobjectsWithOutRig(go.gameObject))
  1062. cleanup.Add(go.gameObject);
  1063. }
  1064. for (int i = 0; i < cleanup.Count; ++i)
  1065. GameObject.DestroyImmediate(cleanup[i]);
  1066. cleanup.Clear();
  1067. if (root.transform.childCount == 0 && canDelete)
  1068. return true;
  1069. return false;
  1070. }
  1071. // ISpriteEditorDataProvider interface
  1072. internal SpriteImportMode spriteImportMode
  1073. {
  1074. get
  1075. {
  1076. return m_TextureImporterSettings.textureType != TextureImporterType.Sprite ?
  1077. SpriteImportMode.None :
  1078. (SpriteImportMode)m_TextureImporterSettings.spriteMode;
  1079. }
  1080. }
  1081. /// <summary>
  1082. /// Implementation for ISpriteEditorDataProvider.pixelsPerUnit.
  1083. /// </summary>
  1084. SpriteImportMode ISpriteEditorDataProvider.spriteImportMode => spriteImportMode;
  1085. internal int spriteDataCount
  1086. {
  1087. get
  1088. {
  1089. var spriteImportData = GetSpriteImportData();
  1090. if (mosaicMode)
  1091. return spriteImportData.Count;
  1092. if (spriteImportMode != SpriteImportMode.Multiple)
  1093. return 1;
  1094. return spriteImportData.Count - 1;
  1095. }
  1096. }
  1097. internal UnityEngine.Object targetObject
  1098. {
  1099. get { return this; }
  1100. }
  1101. UnityEngine.Object ISpriteEditorDataProvider.targetObject => targetObject;
  1102. internal float pixelsPerUnit
  1103. {
  1104. get { return m_TextureImporterSettings.spritePixelsPerUnit; }
  1105. }
  1106. float ISpriteEditorDataProvider.pixelsPerUnit =>pixelsPerUnit;
  1107. internal T GetDataProvider<T>() where T : class
  1108. {
  1109. if (typeof(T) == typeof(ISpriteBoneDataProvider))
  1110. {
  1111. return new SpriteBoneDataProvider { dataProvider = this } as T;
  1112. }
  1113. if (typeof(T) == typeof(ISpriteMeshDataProvider))
  1114. {
  1115. return new SpriteMeshDataProvider { dataProvider = this } as T;
  1116. }
  1117. if (typeof(T) == typeof(ISpriteOutlineDataProvider))
  1118. {
  1119. return new SpriteOutlineDataProvider { dataProvider = this } as T;
  1120. }
  1121. if (typeof(T) == typeof(ISpritePhysicsOutlineDataProvider))
  1122. {
  1123. return new SpritePhysicsOutlineProvider { dataProvider = this } as T;
  1124. }
  1125. if (typeof(T) == typeof(ITextureDataProvider))
  1126. {
  1127. return new TextureDataProvider { dataProvider = this } as T;
  1128. }
  1129. if (typeof(T) == typeof(ICharacterDataProvider))
  1130. {
  1131. return characterMode ? new CharacterDataProvider { dataProvider = this } as T : null;
  1132. }
  1133. if (typeof(T) == typeof(IMainSkeletonDataProvider))
  1134. {
  1135. return characterMode && skeletonAsset != null ? new MainSkeletonDataProvider() { dataProvider = this } as T : null;
  1136. }
  1137. if (typeof(T) == typeof(ISecondaryTextureDataProvider))
  1138. {
  1139. return new SecondaryTextureDataProvider() { dataProvider = this } as T;
  1140. }
  1141. else
  1142. return this as T;
  1143. }
  1144. /// <summary>
  1145. /// Implementation for ISpriteEditorDataProvider.GetDataProvider.
  1146. /// </summary>
  1147. /// <typeparam name="T">Data provider type to retrieve.</typeparam>
  1148. /// <returns></returns>
  1149. T ISpriteEditorDataProvider.GetDataProvider<T>()
  1150. {
  1151. return GetDataProvider<T>();
  1152. }
  1153. internal bool HasDataProvider(Type type)
  1154. {
  1155. if (characterMode)
  1156. {
  1157. if (type == typeof(ICharacterDataProvider))
  1158. return true;
  1159. if (type == typeof(IMainSkeletonDataProvider) && skeletonAsset != null)
  1160. return true;
  1161. }
  1162. if (type == typeof(ISpriteBoneDataProvider) ||
  1163. type == typeof(ISpriteMeshDataProvider) ||
  1164. type == typeof(ISpriteOutlineDataProvider) ||
  1165. type == typeof(ISpritePhysicsOutlineDataProvider) ||
  1166. type == typeof(ITextureDataProvider) ||
  1167. type == typeof(ISecondaryTextureDataProvider))
  1168. {
  1169. return true;
  1170. }
  1171. else
  1172. return type.IsAssignableFrom(GetType());
  1173. }
  1174. /// <summary>
  1175. /// Implementation for ISpriteEditorDataProvider.HasDataProvider.
  1176. /// </summary>
  1177. /// <param name="type">Data provider type to query.</param>
  1178. /// <returns>True if data provider is supported, false otherwise.</returns>
  1179. bool ISpriteEditorDataProvider.HasDataProvider(Type type)
  1180. {
  1181. return HasDataProvider(type);
  1182. }
  1183. internal void AddSpriteData(SpriteRect spriteRect)
  1184. {
  1185. if (spriteImportMode != SpriteImportMode.Multiple)
  1186. Debug.LogWarning("Can only add sprite data when import mode is multiple");
  1187. else
  1188. {
  1189. GetSpriteImportData().Add(new SpriteMetaData(spriteRect));
  1190. }
  1191. }
  1192. internal void DeleteSpriteData(SpriteRect spriteRect)
  1193. {
  1194. if (spriteImportMode != SpriteImportMode.Multiple)
  1195. Debug.LogWarning("Can only add sprite data when import mode is multiple");
  1196. else
  1197. {
  1198. var spriteImportData = GetSpriteImportData();
  1199. int index = spriteImportData.FindIndex(x => x.spriteID == spriteRect.spriteID);
  1200. Assert.AreEqual(0, index, "Cannot delete Sprite from single sprite mode");
  1201. spriteImportData.RemoveAt(index);
  1202. }
  1203. }
  1204. internal int GetSpriteDataIndex(GUID guid)
  1205. {
  1206. switch (spriteImportMode)
  1207. {
  1208. case SpriteImportMode.Single:
  1209. case SpriteImportMode.Polygon:
  1210. return 0;
  1211. case SpriteImportMode.Multiple:
  1212. {
  1213. var spriteImportData = GetSpriteImportData();
  1214. return spriteImportData.FindIndex(x => x.spriteID == guid);
  1215. }
  1216. default:
  1217. throw new InvalidOperationException("GUID not found");
  1218. }
  1219. }
  1220. internal void Apply()
  1221. {
  1222. // Do this so that asset change save dialog will not show
  1223. var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false);
  1224. EditorPrefs.SetBool("VerifySavingAssets", false);
  1225. AssetDatabase.ForceReserializeAssets(new string[] { assetPath }, ForceReserializeAssetsOptions.ReserializeMetadata);
  1226. EditorPrefs.SetBool("VerifySavingAssets", originalValue);
  1227. }
  1228. /// <summary>
  1229. /// Implementation for ISpriteEditorDataProvider.Apply.
  1230. /// </summary>
  1231. void ISpriteEditorDataProvider.Apply()
  1232. {
  1233. Apply();
  1234. }
  1235. internal void InitSpriteEditorDataProvider() {}
  1236. /// <summary>
  1237. /// Implementation for ISpriteEditorDataProvider.InitSpriteEditorDataProvider.
  1238. /// </summary>
  1239. void ISpriteEditorDataProvider.InitSpriteEditorDataProvider()
  1240. {
  1241. InitSpriteEditorDataProvider();
  1242. }
  1243. internal SpriteRect[] GetSpriteRects()
  1244. {
  1245. var spriteImportData = GetSpriteImportData();
  1246. var skip = mosaicMode ? 0 : 1;
  1247. return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).Select(x => new SpriteMetaData(x) as SpriteRect).ToArray() : new[] {new SpriteMetaData(spriteImportData[0]) };
  1248. }
  1249. /// <summary>
  1250. /// Implementation for ISpriteEditorDataProvider.GetSpriteRects.
  1251. /// </summary>
  1252. /// <returns>An array of SpriteRect for the current import mode.</returns>
  1253. SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects()
  1254. {
  1255. return GetSpriteRects();
  1256. }
  1257. internal List<SpriteMetaData> GetSpriteImportData()
  1258. {
  1259. if (mosaicMode)
  1260. {
  1261. if (characterMode)
  1262. {
  1263. if (skeletonAsset != null)
  1264. {
  1265. return m_SharedRigSpriteImportData;
  1266. }
  1267. return m_RigSpriteImportData;
  1268. }
  1269. return m_MosaicSpriteImportData;
  1270. }
  1271. return m_SpriteImportData;
  1272. }
  1273. private SkeletonAsset skeletonAsset =>
  1274. AssetDatabase.LoadAssetAtPath<SkeletonAsset>(AssetDatabase.GUIDToAssetPath(m_SkeletonAssetReferenceID));
  1275. internal List<PSDLayer> GetPSDLayers()
  1276. {
  1277. if (mosaicMode)
  1278. {
  1279. if (characterMode)
  1280. {
  1281. if (skeletonAsset != null)
  1282. return m_SharedRigPSDLayers;
  1283. else
  1284. return m_RigPSDLayers;
  1285. }
  1286. return m_MosaicPSDLayers;
  1287. }
  1288. return null;
  1289. }
  1290. internal SpriteMetaData[] GetSpriteMetaData()
  1291. {
  1292. var spriteImportData = GetSpriteImportData();
  1293. var skip = mosaicMode ? 0 : 1;
  1294. return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).ToArray() : new[] { new SpriteMetaData(spriteImportData[0]) };
  1295. }
  1296. internal SpriteRect GetSpriteDataFromAllMode(GUID guid)
  1297. {
  1298. var spriteMetaData = m_RigSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1299. if(spriteMetaData == null)
  1300. spriteMetaData = m_SharedRigSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1301. if(spriteMetaData == null)
  1302. spriteMetaData = m_MosaicSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1303. if(spriteMetaData == null)
  1304. spriteMetaData = m_SpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1305. return spriteMetaData;
  1306. }
  1307. internal SpriteRect GetSpriteData(GUID guid)
  1308. {
  1309. var spriteImportData = GetSpriteImportData();
  1310. var skip = mosaicMode ? 0 : 1;
  1311. return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).FirstOrDefault(x => x.spriteID == guid) : spriteImportData[0];
  1312. }
  1313. internal void SetSpriteRects(SpriteRect[] spriteRects)
  1314. {
  1315. var spriteImportData = GetSpriteImportData();
  1316. if (spriteImportMode == SpriteImportMode.Multiple)
  1317. {
  1318. var singleSpriteID = mosaicMode ? new GUID() : spriteImportData[0].spriteID;
  1319. spriteImportData.RemoveAll(data => data.spriteID != singleSpriteID && spriteRects.FirstOrDefault(x => x.spriteID == data.spriteID) == null);
  1320. foreach (var sr in spriteRects)
  1321. {
  1322. var importData = spriteImportData.FirstOrDefault(x => x.spriteID == sr.spriteID);
  1323. if (importData == null)
  1324. spriteImportData.Add(new SpriteMetaData(sr));
  1325. else
  1326. {
  1327. importData.name = sr.name;
  1328. importData.alignment = sr.alignment;
  1329. importData.border = sr.border;
  1330. importData.pivot = sr.pivot;
  1331. importData.rect = sr.rect;
  1332. }
  1333. }
  1334. }
  1335. else if (spriteRects.Length == 1 && (spriteImportMode == SpriteImportMode.Single || spriteImportMode == SpriteImportMode.Polygon))
  1336. {
  1337. if (spriteImportData[0].spriteID == spriteRects[0].spriteID)
  1338. {
  1339. spriteImportData[0].name = spriteRects[0].name;
  1340. spriteImportData[0].alignment = spriteRects[0].alignment;
  1341. m_TextureImporterSettings.spriteAlignment = (int)spriteRects[0].alignment;
  1342. m_TextureImporterSettings.spriteBorder = spriteImportData[0].border = spriteRects[0].border;
  1343. m_TextureImporterSettings.spritePivot = spriteImportData[0].pivot = spriteRects[0].pivot;
  1344. spriteImportData[0].rect = spriteRects[0].rect;
  1345. }
  1346. else
  1347. {
  1348. spriteImportData[0] = new SpriteMetaData(spriteRects[0]);
  1349. }
  1350. }
  1351. }
  1352. /// <summary>
  1353. /// Implementation for ISpriteEditorDataProvider.SetSpriteRects.
  1354. /// </summary>
  1355. /// <param name="spriteRects">Set the SpriteRect data for the current import mode.</param>
  1356. void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects)
  1357. {
  1358. SetSpriteRects(spriteRects);
  1359. }
  1360. bool mosaicMode
  1361. {
  1362. get { return spriteImportMode == SpriteImportMode.Multiple && m_MosaicLayers; }
  1363. }
  1364. internal CharacterData characterData
  1365. {
  1366. get
  1367. {
  1368. if (skeletonAsset != null)
  1369. return m_SharedRigCharacterData;
  1370. return m_CharacterData;
  1371. }
  1372. set
  1373. {
  1374. if (skeletonAsset != null)
  1375. m_SharedRigCharacterData = value;
  1376. else
  1377. m_CharacterData = value;
  1378. }
  1379. }
  1380. internal Vector2Int canvasSize => importData.documentSize;
  1381. SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
  1382. {
  1383. if (!characterMode || m_SpriteCategoryList.categories == null)
  1384. return null;
  1385. var categories = m_SpriteCategoryList.categories.Select(x =>
  1386. new SpriteLibCategory()
  1387. {
  1388. name = x.name,
  1389. categoryList = x.labels.Select(y =>
  1390. {
  1391. var sprite = sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y.spriteId);
  1392. return new SpriteCategoryEntry()
  1393. {
  1394. name = y.name,
  1395. sprite = sprite
  1396. };
  1397. }).ToList()
  1398. }).ToList();
  1399. categories.RemoveAll(x => x.categoryList.Count == 0);
  1400. if (categories.Count > 0)
  1401. {
  1402. // Always set version to 0 since we will never be updating this
  1403. return SpriteLibraryAsset.CreateAsset(categories, "Sprite Lib", 0);
  1404. }
  1405. return null;
  1406. }
  1407. internal SecondarySpriteTexture[] secondaryTextures
  1408. {
  1409. get { return m_SecondarySpriteTextures; }
  1410. set { m_SecondarySpriteTextures = value; }
  1411. }
  1412. internal void ReadTextureSettings(TextureImporterSettings dest)
  1413. {
  1414. m_TextureImporterSettings.CopyTo(dest);
  1415. }
  1416. internal SpriteBone[] mainSkeletonBones
  1417. {
  1418. get
  1419. {
  1420. var skeleton = skeletonAsset;
  1421. return skeleton != null ? skeleton.GetSpriteBones() : null;
  1422. }
  1423. }
  1424. internal IPSDLayerMappingStrategy GetLayerMappingStrategy()
  1425. {
  1426. return m_MappingCompare[(int)m_LayerMappingOption];
  1427. }
  1428. internal bool generatePhysicsOutline
  1429. {
  1430. get => m_GeneratePhysicsShape;
  1431. }
  1432. internal bool isNPOT
  1433. {
  1434. get => Mathf.IsPowerOfTwo(importData.textureActualWidth) && Mathf.IsPowerOfTwo(importData.textureActualHeight);
  1435. }
  1436. void SetPhysicsOutline(Texture2D texture, Sprite[] sprites)
  1437. {
  1438. var scale = definitionScale;
  1439. var physicsOutlineDataProvider = GetDataProvider<ISpritePhysicsOutlineDataProvider>();
  1440. foreach (var sprite in sprites)
  1441. {
  1442. var guid = sprite.GetSpriteID();
  1443. var outline = physicsOutlineDataProvider.GetOutlines(guid);
  1444. var outlineOffset = sprite.rect.size / 2;
  1445. bool generated = false;
  1446. if ((outline == null || outline.Count == 0) && generatePhysicsOutline)
  1447. {
  1448. Vector2[][] defaultOutline;
  1449. InternalEditorBridge.GenerateOutlineFromSprite(sprite, 0.25f, 200, true, out defaultOutline);
  1450. outline = new List<Vector2[]>(defaultOutline.Length);
  1451. for (int i = 0; i < defaultOutline.Length; ++i)
  1452. {
  1453. outline.Add(defaultOutline[i]);
  1454. }
  1455. generated = true;
  1456. }
  1457. if (outline != null && outline.Count > 0)
  1458. {
  1459. // Ensure that outlines are all valid.
  1460. int validOutlineCount = 0;
  1461. for (int i = 0; i < outline.Count; ++i)
  1462. validOutlineCount = validOutlineCount + ( (outline[i].Length > 2) ? 1 : 0 );
  1463. int index = 0;
  1464. var convertedOutline = new Vector2[validOutlineCount][];
  1465. var useScale = generated ? pixelsPerUnit * scale : scale;
  1466. var useOutlineOffset = generated ? Vector2.zero : outlineOffset;
  1467. for (int i = 0; i < outline.Count; ++i)
  1468. {
  1469. if (outline[i].Length > 2)
  1470. {
  1471. convertedOutline[index] = new Vector2[outline[i].Length];
  1472. for (int j = 0; j < outline[i].Length; ++j)
  1473. {
  1474. convertedOutline[index][j] = outline[i][j] * useScale + outlineOffset;
  1475. }
  1476. index++;
  1477. }
  1478. }
  1479. sprite.OverridePhysicsShape(convertedOutline);
  1480. }
  1481. }
  1482. }
  1483. }
  1484. }