暫無描述
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 63KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  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 System.Reflection;
  9. using UnityEditor.AssetImporters;
  10. using UnityEditor.U2D.Common;
  11. using UnityEditor.U2D.Sprites;
  12. using UnityEngine.U2D;
  13. using UnityEngine.Scripting.APIUpdating;
  14. #if ENABLE_2D_ANIMATION
  15. using UnityEditor.U2D.Animation;
  16. using UnityEngine.U2D.Animation;
  17. #endif
  18. namespace UnityEditor.U2D.PSD
  19. {
  20. /// <summary>
  21. /// ScriptedImporter to import Photoshop files
  22. /// </summary>
  23. // Version using unity release + 5 digit padding for future upgrade. Eg 2021.2 -> 21200000
  24. [ScriptedImporter(23100002, new string[] {"psb"}, new[] {"psd"}, AllowCaching = true)]
  25. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.psdimporter@latest")]
  26. [MovedFrom("UnityEditor.Experimental.AssetImporters")]
  27. public partial class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider
  28. {
  29. internal enum ELayerMappingOption
  30. {
  31. UseLayerName,
  32. UseLayerNameCaseSensitive,
  33. UseLayerId
  34. }
  35. IPSDLayerMappingStrategy[] m_MappingCompare =
  36. {
  37. new LayerMappingUseLayerName(),
  38. new LayerMappingUseLayerNameCaseSensitive(),
  39. new LayerMappingUserLayerID(),
  40. };
  41. [SerializeField] TextureImporterSettings m_TextureImporterSettings = new TextureImporterSettings()
  42. {
  43. mipmapEnabled = true,
  44. mipmapFilter = TextureImporterMipFilter.BoxFilter,
  45. sRGBTexture = true,
  46. borderMipmap = false,
  47. mipMapsPreserveCoverage = false,
  48. alphaTestReferenceValue = 0.5f,
  49. readable = false,
  50. #if ENABLE_TEXTURE_STREAMING
  51. streamingMipmaps = false,
  52. streamingMipmapsPriority = 0,
  53. #endif
  54. fadeOut = false,
  55. mipmapFadeDistanceStart = 1,
  56. mipmapFadeDistanceEnd = 3,
  57. convertToNormalMap = false,
  58. heightmapScale = 0.25F,
  59. normalMapFilter = 0,
  60. generateCubemap = TextureImporterGenerateCubemap.AutoCubemap,
  61. cubemapConvolution = 0,
  62. seamlessCubemap = false,
  63. npotScale = TextureImporterNPOTScale.ToNearest,
  64. spriteMode = (int) SpriteImportMode.Multiple,
  65. spriteExtrude = 1,
  66. spriteMeshType = SpriteMeshType.Tight,
  67. spriteAlignment = (int) SpriteAlignment.Center,
  68. spritePivot = new Vector2(0.5f, 0.5f),
  69. spritePixelsPerUnit = 100.0f,
  70. spriteBorder = new Vector4(0.0f, 0.0f, 0.0f, 0.0f),
  71. alphaSource = TextureImporterAlphaSource.FromInput,
  72. alphaIsTransparency = true,
  73. spriteTessellationDetail = -1.0f,
  74. textureType = TextureImporterType.Sprite,
  75. textureShape = TextureImporterShape.Texture2D,
  76. filterMode = FilterMode.Bilinear,
  77. aniso = 1,
  78. mipmapBias = 0.0f,
  79. wrapModeU = TextureWrapMode.Repeat,
  80. wrapModeV = TextureWrapMode.Repeat,
  81. wrapModeW = TextureWrapMode.Repeat,
  82. swizzleR = TextureImporterSwizzle.R,
  83. swizzleG = TextureImporterSwizzle.G,
  84. swizzleB = TextureImporterSwizzle.B,
  85. swizzleA = TextureImporterSwizzle.A,
  86. };
  87. [SerializeField] List<SpriteMetaData> m_SingleSpriteImportData = new List<SpriteMetaData>(1) { new SpriteMetaData() };
  88. [SerializeField] List<SpriteMetaData> m_MultiSpriteImportData = new List<SpriteMetaData>();
  89. [SerializeField] List<SpriteMetaData> m_LayeredSpriteImportData = new List<SpriteMetaData>();
  90. // --- Obsolete sprite import data containers
  91. // SpriteData for both single and multiple mode
  92. [Obsolete("This data has now been merged into m_MultiSpriteImportData and m_SingleSpriteImportData")]
  93. [SerializeField] List<SpriteMetaData> m_SpriteImportData = new List<SpriteMetaData>(); // we use index 0 for single sprite and the rest for multiple sprites
  94. // SpriteData for Rig mode
  95. [Obsolete("This data has now been merged into m_LayeredSpriteImportData")]
  96. [SerializeField] List<SpriteMetaData> m_RigSpriteImportData = new List<SpriteMetaData>();
  97. // SpriteData for shared rig mode
  98. [Obsolete("This data has now been merged into m_LayeredSpriteImportData")]
  99. [SerializeField] List<SpriteMetaData> m_SharedRigSpriteImportData = new List<SpriteMetaData>();
  100. [Obsolete("This data has now been merged into m_LayeredSpriteImportData")]
  101. [SerializeField] List<SpriteMetaData> m_MosaicSpriteImportData = new List<SpriteMetaData>();
  102. // --- End obsolete sprite import data containers
  103. #if ENABLE_2D_ANIMATION
  104. // CharacterData for shared rig mode
  105. [SerializeField] CharacterData m_SharedRigCharacterData = new CharacterData();
  106. // CharacterData for Rig mode
  107. [SerializeField] CharacterData m_CharacterData = new CharacterData();
  108. #endif
  109. [SerializeField]
  110. List<TextureImporterPlatformSettings> m_PlatformSettings = new List<TextureImporterPlatformSettings>();
  111. [SerializeField]
  112. bool m_MosaicLayers = true;
  113. [SerializeField]
  114. bool m_CharacterMode = true;
  115. [SerializeField]
  116. Vector2 m_DocumentPivot = Vector2.zero;
  117. [SerializeField]
  118. SpriteAlignment m_DocumentAlignment = SpriteAlignment.BottomCenter;
  119. [SerializeField]
  120. bool m_ImportHiddenLayers = false;
  121. [SerializeField]
  122. ELayerMappingOption m_LayerMappingOption = ELayerMappingOption.UseLayerId;
  123. [SerializeField]
  124. bool m_GeneratePhysicsShape = false;
  125. [SerializeField]
  126. bool m_PaperDollMode = false;
  127. [SerializeField]
  128. bool m_KeepDupilcateSpriteName = true;
  129. [SerializeField]
  130. int m_Padding = 4;
  131. [SerializeField]
  132. ushort m_SpriteSizeExpand = 0;
  133. [SerializeField]
  134. string m_SkeletonAssetReferenceID = null;
  135. [SerializeField]
  136. ScriptableObject m_Pipeline;
  137. [SerializeField]
  138. string m_PipelineVersion;
  139. #if ENABLE_2D_ANIMATION
  140. [SerializeField]
  141. SpriteCategoryList m_SpriteCategoryList = new SpriteCategoryList() {categories = new List<SpriteCategory>()};
  142. #endif
  143. GameObjectCreationFactory m_GameObjectFactory = new GameObjectCreationFactory(null);
  144. PSDImportData m_ImportData;
  145. internal PSDImportData importData
  146. {
  147. get
  148. {
  149. var returnValue = m_ImportData;
  150. if (returnValue == null && !PSDImporterAssetPostProcessor.ContainsImporter(this))
  151. // Using LoadAllAssetsAtPath because PSDImportData is hidden
  152. returnValue = AssetDatabase.LoadAllAssetsAtPath(assetPath).FirstOrDefault(x => x is PSDImportData) as PSDImportData;
  153. if (returnValue == null)
  154. returnValue = ScriptableObject.CreateInstance<PSDImportData>();
  155. m_ImportData = returnValue;
  156. return returnValue;
  157. }
  158. }
  159. internal int textureActualWidth
  160. {
  161. get => importData.textureActualWidth;
  162. private set =>importData.textureActualWidth = value;
  163. }
  164. internal int textureActualHeight
  165. {
  166. get => importData.textureActualHeight;
  167. private set =>importData.textureActualHeight = value;
  168. }
  169. [SerializeField]
  170. string m_SpritePackingTag = "";
  171. [SerializeField]
  172. bool m_ResliceFromLayer = false;
  173. [SerializeField]
  174. PSDLayerImportSetting[] m_PSDLayerImportSetting;
  175. [SerializeField]
  176. List<PSDLayer> m_PsdLayers = new List<PSDLayer>();
  177. // --- Obsolete psd layer containers
  178. [Obsolete("This data has now been merged into m_PsdLayers")]
  179. [SerializeField] List<PSDLayer> m_MosaicPSDLayers = new List<PSDLayer>();
  180. [Obsolete("This data has now been merged into m_PsdLayers")]
  181. [SerializeField] List<PSDLayer> m_RigPSDLayers = new List<PSDLayer>();
  182. [Obsolete("This data has now been merged into m_PsdLayers")]
  183. [SerializeField] List<PSDLayer> m_SharedRigPSDLayers = new List<PSDLayer>();
  184. // --- End obsolete psd layer containers
  185. // Use for inspector to check if the file node is checked
  186. [SerializeField]
  187. #pragma warning disable 169, 414
  188. bool m_ImportFileNodeState = true;
  189. // Used by platform settings to mark it dirty so that it will trigger a reimport
  190. [SerializeField]
  191. #pragma warning disable 169, 414
  192. long m_PlatformSettingsDirtyTick;
  193. [SerializeField]
  194. bool m_SpriteSizeExpandChanged = false;
  195. [SerializeField]
  196. bool m_GenerateGOHierarchy = false;
  197. [SerializeField]
  198. string m_TextureAssetName = null;
  199. [SerializeField]
  200. string m_PrefabAssetName = null;
  201. [SerializeField]
  202. string m_SpriteLibAssetName = null;
  203. [SerializeField]
  204. string m_SkeletonAssetName = null;
  205. [SerializeField]
  206. SecondarySpriteTexture[] m_SecondarySpriteTextures;
  207. PSDExtractLayerData[] m_ExtractData;
  208. internal bool isNPOT => Mathf.IsPowerOfTwo(importData.textureActualWidth) && Mathf.IsPowerOfTwo(importData.textureActualHeight);
  209. bool shouldProduceGameObject => m_CharacterMode && m_MosaicLayers && spriteImportModeToUse == SpriteImportMode.Multiple;
  210. bool shouldResliceFromLayer => m_ResliceFromLayer && m_MosaicLayers && spriteImportModeToUse == SpriteImportMode.Multiple;
  211. bool inCharacterMode => inMosaicMode && m_CharacterMode;
  212. float definitionScale
  213. {
  214. get
  215. {
  216. var definitionScaleW = importData.importedTextureWidth / (float)textureActualWidth;
  217. var definitionScaleH = importData.importedTextureHeight / (float)textureActualHeight;
  218. return Mathf.Min(definitionScaleW, definitionScaleH);
  219. }
  220. }
  221. internal SecondarySpriteTexture[] secondaryTextures
  222. {
  223. get => m_SecondarySpriteTextures;
  224. set => m_SecondarySpriteTextures = value;
  225. }
  226. internal SpriteBone[] mainSkeletonBones
  227. {
  228. get
  229. {
  230. #if ENABLE_2D_ANIMATION
  231. var skeleton = skeletonAsset;
  232. return skeleton != null ? skeleton.GetSpriteBones() : null;
  233. #else
  234. return null;
  235. #endif
  236. }
  237. }
  238. /// <summary>
  239. /// PSDImporter constructor.
  240. /// </summary>
  241. public PSDImporter()
  242. {
  243. m_TextureImporterSettings.swizzleA = TextureImporterSwizzle.A;
  244. m_TextureImporterSettings.swizzleR = TextureImporterSwizzle.R;
  245. m_TextureImporterSettings.swizzleG = TextureImporterSwizzle.G;
  246. m_TextureImporterSettings.swizzleB = TextureImporterSwizzle.B;
  247. }
  248. void PackImage(NativeArray<Color32>[] buffers, int[] width, int[] height, int padding, uint spriteSizeExpand, out NativeArray<Color32> outPackedBuffer, out int outPackedBufferWidth, out int outPackedBufferHeight, out RectInt[] outPackedRect, out Vector2Int[] outUVTransform, bool requireSquarePOT = false)
  249. {
  250. try
  251. {
  252. ScriptableObject pipeline = m_Pipeline;
  253. if(pipeline == null)
  254. pipeline = AssetDatabase.LoadAssetAtPath<ScriptableObject>("Packages/com.unity.2d.psdimporter/Editor/Pipeline.asset");
  255. var args = new object[] { buffers, width, height, padding, spriteSizeExpand, null, 0, 0, null, null, requireSquarePOT };
  256. pipeline.GetType().InvokeMember("PackImage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Static, null,
  257. pipeline, args);
  258. outPackedBuffer = (NativeArray<Color32>)args[5];
  259. outPackedBufferWidth = (int)args[6];
  260. outPackedBufferHeight = (int)args[7];
  261. outPackedRect = (RectInt[])args[8];
  262. outUVTransform = (Vector2Int[])args[9];
  263. }
  264. catch (Exception e)
  265. {
  266. Debug.LogError("Unable to pack image. ex:"+e.ToString(), this);
  267. ImagePacker.Pack(buffers, width, height, padding, spriteSizeExpand, out outPackedBuffer, out outPackedBufferWidth, out outPackedBufferHeight, out outPackedRect, out outUVTransform, requireSquarePOT);
  268. }
  269. }
  270. /// <summary>
  271. /// Implementation of ScriptedImporter.OnImportAsset
  272. /// </summary>
  273. /// <param name="ctx">
  274. /// This argument contains all the contextual information needed to process the import
  275. /// event and is also used by the custom importer to store the resulting Unity Asset.
  276. /// </param>
  277. public override void OnImportAsset(AssetImportContext ctx)
  278. {
  279. var fileStream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read);
  280. Document doc = null;
  281. if(m_ImportData == null)
  282. m_ImportData = ScriptableObject.CreateInstance<PSDImportData>();
  283. m_ImportData.hideFlags = HideFlags.HideInHierarchy;
  284. try
  285. {
  286. UnityEngine.Profiling.Profiler.BeginSample("OnImportAsset");
  287. UnityEngine.Profiling.Profiler.BeginSample("PsdLoad");
  288. doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream);
  289. UnityEngine.Profiling.Profiler.EndSample();
  290. m_ImportData.CreatePSDLayerData(doc.Layers);
  291. ValidatePSDLayerId(doc, m_LayerMappingOption);
  292. SetDocumentImportData(doc);
  293. importData.documentSize = new Vector2Int(doc.width, doc.height);
  294. var singleSpriteMode = m_TextureImporterSettings.textureType == TextureImporterType.Sprite && m_TextureImporterSettings.spriteMode != (int)SpriteImportMode.Multiple;
  295. TextureGenerationOutput output;
  296. if (m_TextureImporterSettings.textureType != TextureImporterType.Sprite ||
  297. m_MosaicLayers == false || singleSpriteMode)
  298. {
  299. output = ImportFlattenImage(doc, ctx);
  300. }
  301. else
  302. {
  303. output = ImportFromLayers(ctx);
  304. }
  305. if (output.texture != null && output.sprites != null)
  306. SetPhysicsOutline(GetDataProvider<ISpritePhysicsOutlineDataProvider>(), output.sprites, definitionScale, pixelsPerUnit, m_GeneratePhysicsShape);
  307. RegisterAssets(ctx, output);
  308. }
  309. catch (Exception e)
  310. {
  311. Debug.LogError($"Failed to import file {assetPath}. Error: {e.Message}\n{e.StackTrace}");
  312. }
  313. finally
  314. {
  315. fileStream.Close();
  316. if (doc != null)
  317. doc.Dispose();
  318. UnityEngine.Profiling.Profiler.EndSample();
  319. EditorUtility.SetDirty(this);
  320. }
  321. }
  322. void ValidatePSDLayerId(Document doc, ELayerMappingOption layerMappingOption)
  323. {
  324. if (layerMappingOption == ELayerMappingOption.UseLayerId)
  325. {
  326. var uniqueNameGenerator = new UniqueNameGenerator();
  327. ImportUtilities.ValidatePSDLayerId(GetPSDLayers(), doc.Layers, uniqueNameGenerator);
  328. }
  329. }
  330. TextureGenerationOutput ImportTexture(AssetImportContext ctx, NativeArray<Color32> imageData, int textureWidth, int textureHeight, SpriteMetaData[] sprites)
  331. {
  332. if (!imageData.IsCreated || imageData.Length == 0)
  333. return new TextureGenerationOutput();
  334. TextureGenerationOutput output = new TextureGenerationOutput();
  335. UnityEngine.Profiling.Profiler.BeginSample("ImportTexture");
  336. try
  337. {
  338. var platformSettings = TextureImporterUtilities.GetPlatformTextureSettings(ctx.selectedBuildTarget, in m_PlatformSettings);
  339. var textureSettings = m_TextureImporterSettings.ExtractTextureSettings();
  340. textureSettings.assetPath = ctx.assetPath;
  341. textureSettings.enablePostProcessor = true;
  342. textureSettings.containsAlpha = true;
  343. textureSettings.hdr = false;
  344. var textureAlphaSettings = m_TextureImporterSettings.ExtractTextureAlphaSettings();
  345. var textureMipmapSettings = m_TextureImporterSettings.ExtractTextureMipmapSettings();
  346. var textureCubemapSettings = m_TextureImporterSettings.ExtractTextureCubemapSettings();
  347. var textureWrapSettings = m_TextureImporterSettings.ExtractTextureWrapSettings();
  348. switch (m_TextureImporterSettings.textureType)
  349. {
  350. case TextureImporterType.Default:
  351. output = TextureGeneratorHelper.GenerateTextureDefault(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  352. break;
  353. case TextureImporterType.NormalMap:
  354. var textureNormalSettings = m_TextureImporterSettings.ExtractTextureNormalSettings();
  355. output = TextureGeneratorHelper.GenerateNormalMap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureNormalSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  356. break;
  357. case TextureImporterType.GUI:
  358. output = TextureGeneratorHelper.GenerateTextureGUI(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  359. break;
  360. case TextureImporterType.Sprite:
  361. var textureSpriteSettings = m_TextureImporterSettings.ExtractTextureSpriteSettings();
  362. textureSpriteSettings.packingTag = m_SpritePackingTag;
  363. textureSpriteSettings.qualifyForPacking = !string.IsNullOrEmpty(m_SpritePackingTag);
  364. textureSpriteSettings.spriteSheetData = new SpriteImportData[sprites.Length];
  365. textureSettings.npotScale = TextureImporterNPOTScale.None;
  366. textureSettings.secondaryTextures = secondaryTextures;
  367. for (int i = 0; i < sprites.Length; ++i)
  368. textureSpriteSettings.spriteSheetData[i] = sprites[i];
  369. output = TextureGeneratorHelper.GenerateTextureSprite(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureSpriteSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  370. break;
  371. case TextureImporterType.Cursor:
  372. output = TextureGeneratorHelper.GenerateTextureCursor(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
  373. break;
  374. case TextureImporterType.Cookie:
  375. output = TextureGeneratorHelper.GenerateCookie(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  376. break;
  377. case TextureImporterType.Lightmap:
  378. output = TextureGeneratorHelper.GenerateLightmap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureMipmapSettings, textureWrapSettings);
  379. break;
  380. case TextureImporterType.SingleChannel:
  381. output = TextureGeneratorHelper.GenerateTextureSingleChannel(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
  382. break;
  383. default:
  384. Debug.LogAssertion("Unknown texture type for import");
  385. output = default(TextureGenerationOutput);
  386. break;
  387. }
  388. }
  389. catch (Exception e)
  390. {
  391. Debug.LogError("Unable to generate Texture2D. Possibly texture size is too big to be generated. ex:"+e.ToString(), this);
  392. }
  393. finally
  394. {
  395. UnityEngine.Profiling.Profiler.EndSample();
  396. }
  397. return output;
  398. }
  399. void SetDocumentImportData(IEnumerable<BitmapLayer> layers, PSDExtractLayerData[] extractData, IPSDLayerMappingStrategy mappingStrategy, List<PSDLayer> psdLayers, PSDExtractLayerData parent = null)
  400. {
  401. for (var i = 0; i < layers.Count(); ++i)
  402. {
  403. var layer = layers.ElementAt(i);
  404. PSDLayerImportSetting importSetting = null;
  405. if (m_PSDLayerImportSetting != null && m_PSDLayerImportSetting.Length > 0)
  406. {
  407. importSetting = m_PSDLayerImportSetting.FirstOrDefault(x => mappingStrategy.Compare(x, layer));
  408. }
  409. var c = psdLayers?.FirstOrDefault(x => mappingStrategy.Compare(x, layer));
  410. if (c != null)
  411. {
  412. if(c.spriteID.Empty())
  413. c.spriteID = importSetting != null ? importSetting.spriteId : GUID.Generate();
  414. if (importSetting == null)
  415. {
  416. importSetting = new PSDLayerImportSetting()
  417. {
  418. flatten = c.flatten,
  419. importLayer = layer.Visible || m_ImportHiddenLayers,
  420. };
  421. }
  422. importSetting.spriteId = c.spriteID;
  423. }
  424. if (importSetting == null)
  425. {
  426. importSetting = new PSDLayerImportSetting()
  427. {
  428. flatten = false,
  429. importLayer = layer.Visible || m_ImportHiddenLayers,
  430. };
  431. }
  432. extractData[i] = new PSDExtractLayerData()
  433. {
  434. bitmapLayer = layer,
  435. importSetting = importSetting,
  436. };
  437. PSDExtractLayerData[] childrenExtractData = null;
  438. if (layer.ChildLayer != null)
  439. {
  440. childrenExtractData = new PSDExtractLayerData[layer.ChildLayer.Count()];
  441. SetDocumentImportData(layer.ChildLayer, childrenExtractData, mappingStrategy, psdLayers, extractData[i]);
  442. }
  443. extractData[i].children = childrenExtractData;
  444. }
  445. }
  446. void SetDocumentImportData(Document doc)
  447. {
  448. var oldPsdLayers = GetPSDLayers();
  449. var mappingStrategy = GetLayerMappingStrategy();
  450. m_ExtractData = new PSDExtractLayerData[doc.Layers.Count];
  451. SetDocumentImportData(doc.Layers, m_ExtractData, mappingStrategy, oldPsdLayers);
  452. }
  453. TextureGenerationOutput ImportFlattenImage(Document doc, AssetImportContext ctx)
  454. {
  455. TextureGenerationOutput output;
  456. var outputImageBuffer = new NativeArray<Color32>(doc.width * doc.height, Allocator.Persistent);
  457. try
  458. {
  459. FlattenImageTask.Execute(m_ExtractData, ref outputImageBuffer, m_ImportHiddenLayers, canvasSize);
  460. m_SingleSpriteImportData[0].name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath) + "_1";
  461. m_SingleSpriteImportData[0].alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  462. m_SingleSpriteImportData[0].border = m_TextureImporterSettings.spriteBorder;
  463. m_SingleSpriteImportData[0].pivot = m_TextureImporterSettings.spritePivot;
  464. m_SingleSpriteImportData[0].rect = new Rect(0, 0, doc.width, doc.height);
  465. importData.importedTextureWidth = textureActualWidth = doc.width;
  466. importData.importedTextureHeight = textureActualHeight = doc.height;
  467. var spriteImportData = GetSpriteImportData();
  468. output = ImportTexture(ctx, outputImageBuffer, doc.width, doc.height, spriteImportData.ToArray());
  469. importData.importedTextureWidth = output.texture.width;
  470. importData.importedTextureHeight = output.texture.height;
  471. }
  472. finally
  473. {
  474. outputImageBuffer.Dispose();
  475. }
  476. return output;
  477. }
  478. TextureGenerationOutput ImportFromLayers(AssetImportContext ctx)
  479. {
  480. TextureGenerationOutput output;
  481. var outputImageBuffer = default(NativeArray<Color32>);
  482. var layerIndex = new List<int>();
  483. var spriteNameHash = new UniqueNameGenerator();
  484. var platformSettings = TextureImporterUtilities.GetPlatformTextureSettings(ctx.selectedBuildTarget, in m_PlatformSettings);
  485. bool requireSquarePOT = (TextureImporterFormat.PVRTC_RGB2 <= platformSettings.format && platformSettings.format <= TextureImporterFormat.PVRTC_RGBA4);
  486. var oldPsdLayers = GetPSDLayers();
  487. List<PSDLayer> psdLayers = null;
  488. try
  489. {
  490. ExtractLayerTask.Execute(in m_ExtractData, out psdLayers, m_ImportHiddenLayers, canvasSize);
  491. var mappingStrategy = GetLayerMappingStrategy();
  492. var layerUnique = mappingStrategy.LayersUnique(psdLayers.ConvertAll(x => (IPSDLayerMappingStrategyComparable)x));
  493. if (!string.IsNullOrEmpty(layerUnique))
  494. {
  495. Debug.LogWarning(layerUnique,this);
  496. }
  497. var removedLayersSprite = oldPsdLayers.Where(x => psdLayers.FirstOrDefault(y => mappingStrategy.Compare(y, x)) == null).Select(z => z.spriteID).ToArray();
  498. var hasNewLayer = false;
  499. for (var i = 0; i < psdLayers.Count; ++i)
  500. {
  501. var j = 0;
  502. var psdLayer = psdLayers[i];
  503. for (; j < oldPsdLayers.Count; ++j)
  504. {
  505. if (mappingStrategy.Compare(psdLayer, oldPsdLayers[j]))
  506. {
  507. psdLayer.spriteName = oldPsdLayers[j].spriteName;
  508. psdLayer.mosaicPosition = oldPsdLayers[j].mosaicPosition;
  509. if (psdLayer.isImported != oldPsdLayers[j].isImported)
  510. hasNewLayer = true;
  511. break;
  512. }
  513. }
  514. if(j >= oldPsdLayers.Count)
  515. hasNewLayer = true;
  516. }
  517. var layerBuffers = new List<NativeArray<Color32>>();
  518. var layerWidth = new List<int>();
  519. var layerHeight = new List<int>();
  520. for (var i = 0; i < psdLayers.Count; ++i)
  521. {
  522. var l = psdLayers[i];
  523. var expectedBufferLength = l.width * l.height;
  524. if (l.texture.IsCreated && l.texture.Length == expectedBufferLength && l.isImported)
  525. {
  526. layerBuffers.Add(l.texture);
  527. layerIndex.Add(i);
  528. layerWidth.Add(l.width);
  529. layerHeight.Add(l.height);
  530. }
  531. }
  532. PackImage(layerBuffers.ToArray(), layerWidth.ToArray(), layerHeight.ToArray(), m_Padding, m_SpriteSizeExpand, out outputImageBuffer, out int width, out int height, out RectInt[] spriteData, out Vector2Int[] uvTransform, requireSquarePOT);
  533. var packOffsets = new Vector2[spriteData.Length];
  534. for (var i = 0; i < packOffsets.Length; ++i)
  535. packOffsets[i] = new Vector2((uvTransform[i].x - spriteData[i].position.x) / -1f, (uvTransform[i].y - spriteData[i].position.y) / -1f);
  536. var spriteImportData = GetSpriteImportData();
  537. if (spriteImportData.Count <= 0 || shouldResliceFromLayer || hasNewLayer)
  538. {
  539. var newSpriteMeta = new List<SpriteMetaData>();
  540. for (int i = 0; i < spriteData.Length && i < layerIndex.Count; ++i)
  541. {
  542. var psdLayer = psdLayers[layerIndex[i]];
  543. var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayer.spriteID);
  544. if (spriteSheet == null)
  545. {
  546. spriteSheet = new SpriteMetaData();
  547. spriteSheet.border = Vector4.zero;
  548. spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  549. spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
  550. spriteSheet.rect = new Rect(spriteData[i].x, spriteData[i].y, spriteData[i].width, spriteData[i].height);
  551. spriteSheet.spriteID = psdLayer.spriteID;
  552. }
  553. else
  554. {
  555. var r = spriteSheet.rect;
  556. r.position = r.position - psdLayer.mosaicPosition + spriteData[i].position;
  557. spriteSheet.rect = r;
  558. }
  559. psdLayer.spriteName = ImportUtilities.GetUniqueSpriteName(psdLayer.name, spriteNameHash, m_KeepDupilcateSpriteName);
  560. spriteSheet.name = psdLayer.spriteName;
  561. spriteSheet.spritePosition = psdLayer.layerPosition + packOffsets[i];
  562. if(shouldResliceFromLayer)
  563. spriteSheet.rect = new Rect(spriteData[i].x, spriteData[i].y, spriteData[i].width, spriteData[i].height);
  564. spriteSheet.uvTransform = uvTransform[i];
  565. psdLayer.spriteID = spriteSheet.spriteID;
  566. psdLayer.mosaicPosition = spriteData[i].position;
  567. newSpriteMeta.Add(spriteSheet);
  568. }
  569. spriteImportData.Clear();
  570. spriteImportData.AddRange(newSpriteMeta);
  571. }
  572. else
  573. {
  574. spriteImportData.RemoveAll(x => removedLayersSprite.Contains(x.spriteID));
  575. // First look for any user created SpriteRect and add those into the name hash
  576. foreach (var importData in spriteImportData)
  577. {
  578. var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == importData.spriteID);
  579. if (psdLayer == null)
  580. spriteNameHash.AddHash(importData.name);
  581. }
  582. foreach (var importData in spriteImportData)
  583. {
  584. var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == importData.spriteID);
  585. if (psdLayer == null)
  586. importData.uvTransform = new Vector2Int((int)importData.rect.position.x, (int)importData.rect.position.y);
  587. // If it is user created rect or the name has been changed before
  588. // add it into the spriteNameHash and we don't copy it over from the layer
  589. if (psdLayer == null || psdLayer.spriteName != importData.name)
  590. spriteNameHash.AddHash(importData.name);
  591. // If the sprite name has not been changed, we ensure the new
  592. // layer name is still unique and use it as the sprite name
  593. if (psdLayer != null && psdLayer.spriteName == importData.name)
  594. {
  595. psdLayer.spriteName = ImportUtilities.GetUniqueSpriteName(psdLayer.name, spriteNameHash, m_KeepDupilcateSpriteName);
  596. importData.name = psdLayer.spriteName;
  597. }
  598. }
  599. //Update names for those user has not changed and add new sprite rect based on PSD file.
  600. for (var k = 0; k < layerIndex.Count; ++k)
  601. {
  602. var i = layerIndex[k];
  603. var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[i].spriteID);
  604. var inOldLayer = oldPsdLayers.FindIndex(x => mappingStrategy.Compare(x,psdLayers[i])) != -1;
  605. if (spriteSheet == null && !inOldLayer)
  606. {
  607. spriteSheet = new SpriteMetaData();
  608. spriteImportData.Add(spriteSheet);
  609. spriteSheet.rect = new Rect(spriteData[k].x, spriteData[k].y, spriteData[k].width, spriteData[k].height);
  610. spriteSheet.border = Vector4.zero;
  611. spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
  612. spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
  613. spriteSheet.spritePosition = psdLayers[i].layerPosition;
  614. psdLayers[i].spriteName = ImportUtilities.GetUniqueSpriteName(psdLayers[i].name, spriteNameHash, m_KeepDupilcateSpriteName);
  615. spriteSheet.name = psdLayers[i].spriteName;
  616. }
  617. else if (spriteSheet != null)
  618. {
  619. var r = spriteSheet.rect;
  620. r.position = spriteSheet.rect.position - psdLayers[i].mosaicPosition + spriteData[k].position;
  621. if (inOldLayer && (m_SpriteSizeExpand > 0 || m_SpriteSizeExpandChanged))
  622. {
  623. r.width = spriteData[k].width;
  624. r.height = spriteData[k].height;
  625. }
  626. spriteSheet.rect = r;
  627. spriteSheet.spritePosition = psdLayers[i].layerPosition + packOffsets[k];
  628. }
  629. if (spriteSheet != null)
  630. {
  631. spriteSheet.uvTransform = uvTransform[k];
  632. psdLayers[i].spriteID = spriteSheet.spriteID;
  633. psdLayers[i].mosaicPosition = spriteData[k].position;
  634. }
  635. }
  636. }
  637. foreach (var l in oldPsdLayers)
  638. l.Dispose();
  639. oldPsdLayers.Clear();
  640. oldPsdLayers.AddRange(psdLayers);
  641. importData.importedTextureHeight = textureActualHeight = height;
  642. importData.importedTextureWidth = textureActualWidth = width;
  643. output = ImportTexture(ctx, outputImageBuffer, width, height, spriteImportData.ToArray());
  644. if (output.texture)
  645. {
  646. importData.importedTextureHeight = output.texture.height;
  647. importData.importedTextureWidth = output.texture.width;
  648. }
  649. }
  650. finally
  651. {
  652. if (outputImageBuffer.IsCreated)
  653. outputImageBuffer.Dispose();
  654. foreach (var l in psdLayers)
  655. l.Dispose();
  656. }
  657. return output;
  658. }
  659. internal void MigrateOlderData()
  660. {
  661. MigrateOlderSpriteImportData();
  662. MigrateOlderPsdLayerData();
  663. }
  664. void MigrateOlderSpriteImportData()
  665. {
  666. // Suppressing Obsolete warning, as this method migrate data from those obsolete containers.
  667. #pragma warning disable 0618
  668. var hasMigratedData = m_LayeredSpriteImportData.Count > 0 ||
  669. m_MultiSpriteImportData.Count > 0 ||
  670. !ImportUtilities.IsSpriteMetaDataDefault(m_SingleSpriteImportData[0]);
  671. if (hasMigratedData)
  672. return;
  673. if (inCharacterMode)
  674. {
  675. if (!string.IsNullOrEmpty(m_SkeletonAssetReferenceID) && m_SharedRigSpriteImportData.Count > 0)
  676. m_LayeredSpriteImportData = new List<SpriteMetaData>(m_SharedRigSpriteImportData);
  677. else if (m_RigSpriteImportData.Count > 0)
  678. m_LayeredSpriteImportData = new List<SpriteMetaData>(m_RigSpriteImportData);
  679. }
  680. else if (m_MosaicSpriteImportData.Count > 0)
  681. m_LayeredSpriteImportData = new List<SpriteMetaData>(m_MosaicSpriteImportData);
  682. if (m_SpriteImportData.Count > 0)
  683. {
  684. m_SingleSpriteImportData[0] = m_SpriteImportData[0];
  685. if (m_SpriteImportData.Count > 1)
  686. m_MultiSpriteImportData = m_SpriteImportData.GetRange(1, m_SpriteImportData.Count - 1);
  687. }
  688. #pragma warning restore 0618
  689. }
  690. void MigrateOlderPsdLayerData()
  691. {
  692. // Suppressing Obsolete warning, as this method migrate data from those obsolete containers.
  693. #pragma warning disable 0618
  694. var hasMigratedData = m_PsdLayers.Count > 0;
  695. if (hasMigratedData)
  696. return;
  697. if (inCharacterMode)
  698. {
  699. if (!string.IsNullOrEmpty(m_SkeletonAssetReferenceID) && m_SharedRigPSDLayers.Count > 0)
  700. m_PsdLayers = new List<PSDLayer>(m_SharedRigPSDLayers);
  701. else if (m_RigPSDLayers.Count > 0)
  702. m_PsdLayers = new List<PSDLayer>(m_RigPSDLayers);
  703. }
  704. if (m_PsdLayers.Count == 0)
  705. m_PsdLayers = new List<PSDLayer>(m_MosaicPSDLayers);
  706. #pragma warning restore 0618
  707. }
  708. void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
  709. {
  710. ctx.AddObjectToAsset("PSDImportData", m_ImportData);
  711. if ((output.sprites == null || output.sprites.Length == 0) && output.texture == null)
  712. {
  713. Debug.LogWarning(TextContent.noSpriteOrTextureImportWarning, this);
  714. return;
  715. }
  716. var assetNameGenerator = new UniqueNameGenerator();
  717. if (!string.IsNullOrEmpty(output.importInspectorWarnings))
  718. {
  719. Debug.LogWarning(output.importInspectorWarnings);
  720. }
  721. if (output.importWarnings != null && output.importWarnings.Length != 0)
  722. {
  723. foreach (var warning in output.importWarnings)
  724. Debug.LogWarning(warning);
  725. }
  726. if (output.thumbNail == null)
  727. Debug.LogWarning("Thumbnail generation fail");
  728. if (output.texture == null)
  729. {
  730. throw new Exception("Texture import fail");
  731. }
  732. var assetName = assetNameGenerator.GetUniqueName(System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath), true, this);
  733. UnityEngine.Object mainAsset = null;
  734. RegisterTextureAsset(ctx, output, assetName, ref mainAsset);
  735. RegisterSpriteLibraryAsset(ctx, output, assetName);
  736. RegisterGameObjects(ctx, output, ref mainAsset);
  737. RegisterSprites(ctx, output, assetNameGenerator);
  738. RegisterSkeletonAsset(ctx, output, assetName);
  739. ctx.SetMainObject(mainAsset);
  740. }
  741. void RegisterTextureAsset(AssetImportContext ctx, TextureGenerationOutput output, string assetName, ref UnityEngine.Object mainAsset)
  742. {
  743. var registerTextureNameId = string.IsNullOrEmpty(m_TextureAssetName) ? "Texture" : m_TextureAssetName;
  744. output.texture.name = assetName;
  745. ctx.AddObjectToAsset(registerTextureNameId, output.texture, output.thumbNail);
  746. mainAsset = output.texture;
  747. }
  748. void RegisterSpriteLibraryAsset(AssetImportContext ctx, TextureGenerationOutput output, string assetName)
  749. {
  750. #if ENABLE_2D_ANIMATION
  751. if (output.sprites == null)
  752. return;
  753. var slAsset = ProduceSpriteLibAsset(output.sprites);
  754. if (slAsset == null)
  755. return;
  756. slAsset.name = assetName;
  757. var spriteLibAssetNameId = string.IsNullOrEmpty(m_SpriteLibAssetName) ? "SpriteLibAsset" : m_SpriteLibAssetName;
  758. ctx.AddObjectToAsset(spriteLibAssetNameId, slAsset);
  759. #endif
  760. }
  761. void RegisterGameObjects(AssetImportContext ctx, TextureGenerationOutput output, ref UnityEngine.Object mainAsset)
  762. {
  763. if (output.sprites == null)
  764. return;
  765. if (!shouldProduceGameObject)
  766. return;
  767. var prefabRootNameId = string.IsNullOrEmpty(m_TextureAssetName) ? "root" : m_TextureAssetName;
  768. var registerPrefabNameId = string.IsNullOrEmpty(m_PrefabAssetName) ? "Prefab" : m_PrefabAssetName;
  769. GameObject prefab = null;
  770. if (m_PaperDollMode)
  771. prefab = OnProducePaperDollPrefab(ctx, prefabRootNameId, output.sprites);
  772. else
  773. prefab = OnProducePrefab(ctx, prefabRootNameId, output.sprites);
  774. if (prefab != null)
  775. {
  776. ctx.AddObjectToAsset(registerPrefabNameId, prefab);
  777. mainAsset = prefab;
  778. }
  779. }
  780. void RegisterSprites(AssetImportContext ctx, TextureGenerationOutput output, UniqueNameGenerator assetNameGenerator)
  781. {
  782. if (output.sprites == null)
  783. return;
  784. foreach (var s in output.sprites)
  785. {
  786. var spriteAssetName = assetNameGenerator.GetUniqueName(s.GetSpriteID().ToString(), false, s);
  787. ctx.AddObjectToAsset(spriteAssetName, s);
  788. }
  789. }
  790. void RegisterSkeletonAsset(AssetImportContext ctx, TextureGenerationOutput output, string assetName)
  791. {
  792. #if ENABLE_2D_ANIMATION
  793. var skeletonAssetNameId = string.IsNullOrEmpty(m_SkeletonAssetName) ? "SkeletonAsset" : m_SkeletonAssetName;
  794. if (output.sprites != null)
  795. {
  796. if (inCharacterMode && skeletonAsset == null)
  797. {
  798. var characterRig = ScriptableObject.CreateInstance<SkeletonAsset>();
  799. characterRig.name = assetName + " Skeleton";
  800. var bones = GetDataProvider<ICharacterDataProvider>().GetCharacterData().bones;
  801. characterRig.SetSpriteBones(bones);
  802. ctx.AddObjectToAsset(skeletonAssetNameId, characterRig);
  803. }
  804. }
  805. if (!string.IsNullOrEmpty(m_SkeletonAssetReferenceID))
  806. {
  807. var primaryAssetPath = AssetDatabase.GUIDToAssetPath(m_SkeletonAssetReferenceID);
  808. if (!string.IsNullOrEmpty(primaryAssetPath) && primaryAssetPath != assetPath)
  809. {
  810. ctx.DependsOnArtifact(primaryAssetPath);
  811. }
  812. }
  813. #endif
  814. }
  815. void BuildGroupGameObject(List<PSDLayer> psdGroup, int index, Transform root)
  816. {
  817. var psdData = psdGroup[index];
  818. if (psdData.gameObject == null)
  819. {
  820. var spriteImported = !psdGroup[index].spriteID.Empty() && psdGroup[index].isImported;
  821. var isVisibleGroup = psdData.isGroup && (ImportUtilities.VisibleInHierarchy(psdGroup, index) || m_ImportHiddenLayers) && m_GenerateGOHierarchy;
  822. if (spriteImported || isVisibleGroup)
  823. {
  824. var spriteData = GetSpriteImportData().FirstOrDefault(x => x.spriteID == psdData.spriteID);
  825. #if ENABLE_2D_ANIMATION
  826. // Determine if need to create GameObject i.e. if the sprite is not in a SpriteLib or if it is the first one
  827. var shouldCreateGo = ImportUtilities.SpriteIsMainFromSpriteLib(m_SpriteCategoryList.categories, psdData.spriteID.ToString(), out var categoryName);
  828. var goName = string.IsNullOrEmpty(categoryName) ? spriteData != null ? spriteData.name : psdData.name : categoryName;
  829. if (shouldCreateGo)
  830. #else
  831. var goName = spriteData != null ? spriteData.name : psdData.name;
  832. #endif
  833. {
  834. psdData.gameObject = m_GameObjectFactory.CreateGameObject(goName);
  835. }
  836. }
  837. if (psdData.parentIndex >= 0 && m_GenerateGOHierarchy && psdData.gameObject != null)
  838. {
  839. BuildGroupGameObject(psdGroup, psdData.parentIndex, root);
  840. root = psdGroup[psdData.parentIndex].gameObject.transform;
  841. }
  842. if (psdData.gameObject != null)
  843. {
  844. psdData.gameObject.transform.SetParent(root);
  845. psdData.gameObject.transform.SetSiblingIndex(root.childCount-1);
  846. }
  847. }
  848. }
  849. void CreateBoneGO(int index, SpriteBone[] bones, BoneGO[] bonesGO, Transform defaultRoot)
  850. {
  851. if (bonesGO[index].go != null)
  852. return;
  853. var bone = bones[index];
  854. if (bone.parentId != -1 && bonesGO[bone.parentId].go == null)
  855. CreateBoneGO(bone.parentId, bones, bonesGO, defaultRoot);
  856. var go = m_GameObjectFactory.CreateGameObject(bone.name);
  857. if (bone.parentId == -1)
  858. go.transform.SetParent(defaultRoot);
  859. else
  860. go.transform.SetParent(bonesGO[bone.parentId].go.transform);
  861. go.transform.localPosition = bone.position * 1 / pixelsPerUnit;
  862. go.transform.localRotation = bone.rotation;
  863. bonesGO[index] = new BoneGO()
  864. {
  865. go = go,
  866. index = index
  867. };
  868. }
  869. BoneGO[] CreateBonesGO(Transform root)
  870. {
  871. #if ENABLE_2D_ANIMATION
  872. if (inCharacterMode)
  873. {
  874. var characterSkeleton = GetDataProvider<ICharacterDataProvider>().GetCharacterData();
  875. var bones = characterSkeleton.bones;
  876. if (bones != null)
  877. {
  878. var boneGOs = new BoneGO[bones.Length];
  879. for (int i = 0; i < bones.Length; ++i)
  880. {
  881. CreateBoneGO(i, bones, boneGOs, root);
  882. }
  883. return boneGOs;
  884. }
  885. }
  886. #endif
  887. return new BoneGO[0];
  888. }
  889. void GetSpriteLibLabel(string spriteId, out string category, out string label)
  890. {
  891. category = "";
  892. label = "";
  893. #if ENABLE_2D_ANIMATION
  894. foreach (var cat in m_SpriteCategoryList.categories)
  895. {
  896. var index = cat.labels.FindIndex(x => x.spriteId == spriteId);
  897. if (index != -1)
  898. {
  899. category = cat.name;
  900. label = cat.labels[index].name;
  901. break;
  902. }
  903. }
  904. #endif
  905. }
  906. GameObject OnProducePaperDollPrefab(AssetImportContext ctx, string assetName, Sprite[] sprites)
  907. {
  908. GameObject root = null;
  909. if (sprites != null && sprites.Length > 0)
  910. {
  911. root = new GameObject();
  912. root.name = assetName + "_GO";
  913. #if ENABLE_2D_ANIMATION
  914. var spriteImportData = GetSpriteImportData();
  915. var psdLayers = GetPSDLayers();
  916. var boneGOs = CreateBonesGO(root.transform);
  917. var contextObjects = new List<UnityEngine.Object>();
  918. ctx.GetObjects(contextObjects);
  919. var spriteLib = contextObjects.Find(x => x.GetType() == typeof(SpriteLibraryAsset)) as SpriteLibraryAsset;
  920. if (spriteLib != null)
  921. root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
  922. var currentCharacterData = characterData;
  923. for (var i = 0; i < sprites.Length; ++i)
  924. {
  925. if (ImportUtilities.SpriteIsMainFromSpriteLib(m_SpriteCategoryList.categories, sprites[i].GetSpriteID().ToString(), out var categoryName))
  926. {
  927. var spriteBones = currentCharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == sprites[i].GetSpriteID()).bones;
  928. var rootBone = root;
  929. if (spriteBones != null && spriteBones.Any())
  930. {
  931. var b = spriteBones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]).OrderBy(x => x.index);
  932. if (b.Any())
  933. rootBone = b.First().go;
  934. }
  935. var srGameObject = m_GameObjectFactory.CreateGameObject(string.IsNullOrEmpty(categoryName) ? sprites[i].name : categoryName);
  936. var sr = srGameObject.AddComponent<SpriteRenderer>();
  937. sr.sprite = sprites[i];
  938. sr.sortingOrder = psdLayers.Count - psdLayers.FindIndex(x => x.spriteID == sprites[i].GetSpriteID());
  939. srGameObject.transform.parent = rootBone.transform;
  940. var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == sprites[i].GetSpriteID());
  941. if (spriteMetaData != null)
  942. {
  943. var uvTransform = spriteMetaData.uvTransform;
  944. var outlineOffset = new Vector2(spriteMetaData.rect.x - uvTransform.x + (spriteMetaData.pivot.x * spriteMetaData.rect.width),
  945. spriteMetaData.rect.y - uvTransform.y + (spriteMetaData.pivot.y * spriteMetaData.rect.height)) * definitionScale / sprites[i].pixelsPerUnit;
  946. srGameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
  947. }
  948. GetSpriteLibLabel(sprites[i].GetSpriteID().ToString(), out var category, out var labelName);
  949. if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
  950. {
  951. var resolver = srGameObject.AddComponent<SpriteResolver>();
  952. resolver.SetCategoryAndLabel(category, labelName);
  953. resolver.ResolveSpriteToSpriteRenderer();
  954. }
  955. }
  956. }
  957. #endif
  958. }
  959. return root;
  960. }
  961. internal void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings)
  962. {
  963. var index = m_PlatformSettings.FindIndex(x => x.name == platformSettings.name);
  964. if(index < 0)
  965. m_PlatformSettings.Add(platformSettings);
  966. else
  967. m_PlatformSettings[index] = platformSettings;
  968. }
  969. internal TextureImporterPlatformSettings[] GetAllPlatformSettings()
  970. {
  971. return m_PlatformSettings.ToArray();
  972. }
  973. GameObject OnProducePrefab(AssetImportContext ctx, string assetname, Sprite[] sprites)
  974. {
  975. GameObject root = null;
  976. if (sprites != null && sprites.Length > 0)
  977. {
  978. var spriteImportData = GetSpriteImportData();
  979. root = new GameObject();
  980. root.transform.SetSiblingIndex(0);
  981. root.name = assetname + "_GO";
  982. #if ENABLE_2D_ANIMATION
  983. var currentCharacterData = characterData;
  984. var contextObjects = new List<UnityEngine.Object>();
  985. ctx.GetObjects(contextObjects);
  986. var spriteLib = contextObjects.Find(x => x.GetType() == typeof(SpriteLibraryAsset)) as SpriteLibraryAsset;
  987. if (spriteLib != null)
  988. root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
  989. CharacterData? characterSkeleton = inCharacterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
  990. #endif
  991. var psdLayers = GetPSDLayers();
  992. for (var i = 0; i < psdLayers.Count; ++i)
  993. {
  994. BuildGroupGameObject(psdLayers, i, root.transform);
  995. }
  996. var boneGOs = CreateBonesGO(root.transform);
  997. for (var i = 0; i < psdLayers.Count; ++i)
  998. {
  999. var l = psdLayers[i];
  1000. var layerSpriteID = l.spriteID;
  1001. var sprite = sprites.FirstOrDefault(x => x.GetSpriteID() == layerSpriteID);
  1002. var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == layerSpriteID);
  1003. if (sprite != null && spriteMetaData != null && l.gameObject != null)
  1004. {
  1005. var spriteRenderer = l.gameObject.AddComponent<SpriteRenderer>();
  1006. spriteRenderer.sprite = sprite;
  1007. spriteRenderer.sortingOrder = psdLayers.Count - i;
  1008. var pivot = spriteMetaData.pivot;
  1009. pivot.x *= spriteMetaData.rect.width;
  1010. pivot.y *= spriteMetaData.rect.height;
  1011. var spritePosition = spriteMetaData.spritePosition;
  1012. spritePosition.x += pivot.x;
  1013. spritePosition.y += pivot.y;
  1014. spritePosition *= (definitionScale / sprite.pixelsPerUnit);
  1015. l.gameObject.transform.position = new Vector3(spritePosition.x, spritePosition.y, 0f);
  1016. #if ENABLE_2D_ANIMATION
  1017. if (characterSkeleton != null)
  1018. {
  1019. var part = characterSkeleton.Value.parts.FirstOrDefault(x => x.spriteId == spriteMetaData.spriteID.ToString());
  1020. if (part.bones != null && part.bones.Length > 0)
  1021. {
  1022. var spriteSkin = l.gameObject.AddComponent<SpriteSkin>();
  1023. if (spriteRenderer.sprite != null && spriteRenderer.sprite.GetBindPoses().Length > 0)
  1024. {
  1025. 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]);
  1026. if (spriteBones.Any())
  1027. {
  1028. spriteSkin.SetRootBone(root.transform);
  1029. spriteSkin.SetBoneTransforms(spriteBones.Select(x => x.go.transform).ToArray());
  1030. if (spriteSkin.isValid)
  1031. spriteSkin.CalculateBounds();
  1032. }
  1033. }
  1034. }
  1035. }
  1036. GetSpriteLibLabel(layerSpriteID.ToString(), out var category, out var labelName);
  1037. if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
  1038. {
  1039. var resolver = l.gameObject.AddComponent<SpriteResolver>();
  1040. resolver.SetCategoryAndLabel(category, labelName);
  1041. resolver.ResolveSpriteToSpriteRenderer();
  1042. }
  1043. #endif
  1044. }
  1045. }
  1046. var prefabBounds = new Rect(0 , 0, importData.documentSize.x / pixelsPerUnit, importData.documentSize.y / pixelsPerUnit);
  1047. var documentPivot = (Vector3)ImportUtilities.GetPivotPoint(prefabBounds, m_DocumentAlignment, m_DocumentPivot);
  1048. for (var i = 0; i < psdLayers.Count; ++i)
  1049. {
  1050. var l = psdLayers[i];
  1051. if (l.gameObject == null || l.gameObject.GetComponent<SpriteRenderer>() == null)
  1052. continue;
  1053. var p = l.gameObject.transform.localPosition;
  1054. p -= documentPivot;
  1055. l.gameObject.transform.localPosition = p;
  1056. }
  1057. for (int i = 0; i < boneGOs.Length; ++i)
  1058. {
  1059. if (boneGOs[i].go.transform.parent != root.transform)
  1060. continue;
  1061. var p = boneGOs[i].go.transform.position;
  1062. p -= documentPivot;
  1063. boneGOs[i].go.transform.position = p;
  1064. }
  1065. }
  1066. return root;
  1067. }
  1068. int spriteDataCount
  1069. {
  1070. get
  1071. {
  1072. var spriteImportData = GetSpriteImportData();
  1073. if (inMosaicMode)
  1074. return spriteImportData.Count;
  1075. if (spriteImportModeToUse != SpriteImportMode.Multiple)
  1076. return 1;
  1077. return spriteImportData.Count - 1;
  1078. }
  1079. }
  1080. internal void Apply()
  1081. {
  1082. // Do this so that asset change save dialog will not show
  1083. var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false);
  1084. EditorPrefs.SetBool("VerifySavingAssets", false);
  1085. AssetDatabase.ForceReserializeAssets(new string[] { assetPath }, ForceReserializeAssetsOptions.ReserializeMetadata);
  1086. EditorPrefs.SetBool("VerifySavingAssets", originalValue);
  1087. }
  1088. #if ENABLE_2D_ANIMATION
  1089. SkeletonAsset skeletonAsset =>
  1090. AssetDatabase.LoadAssetAtPath<SkeletonAsset>(AssetDatabase.GUIDToAssetPath(m_SkeletonAssetReferenceID));
  1091. #endif
  1092. internal List<PSDLayer> GetPSDLayers() => m_PsdLayers;
  1093. List<SpriteMetaData> GetSpriteImportData()
  1094. {
  1095. if (spriteImportModeToUse == SpriteImportMode.Multiple)
  1096. {
  1097. if (inMosaicMode)
  1098. return m_LayeredSpriteImportData;
  1099. return m_MultiSpriteImportData;
  1100. }
  1101. return m_SingleSpriteImportData;
  1102. }
  1103. internal SpriteMetaData[] GetSpriteMetaData()
  1104. {
  1105. if (spriteImportModeToUse == SpriteImportMode.Multiple)
  1106. {
  1107. if (inMosaicMode)
  1108. return m_LayeredSpriteImportData.ToArray();
  1109. return m_MultiSpriteImportData.ToArray();
  1110. }
  1111. return new[] { new SpriteMetaData(m_SingleSpriteImportData[0]) };
  1112. }
  1113. internal SpriteRect GetSpriteData(GUID guid)
  1114. {
  1115. if (spriteImportModeToUse == SpriteImportMode.Multiple)
  1116. {
  1117. if (inMosaicMode)
  1118. return m_LayeredSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1119. return m_MultiSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
  1120. }
  1121. return m_SingleSpriteImportData[0];
  1122. }
  1123. internal Vector2 GetDocumentPivot()
  1124. {
  1125. return ImportUtilities.GetPivotPoint(new Rect(0, 0, 1, 1), m_DocumentAlignment, m_DocumentPivot);
  1126. }
  1127. internal void SetDocumentPivot(Vector2 pivot)
  1128. {
  1129. ImportUtilities.TranslatePivotPoint(pivot, new Rect(0, 0, 1, 1), out m_DocumentAlignment, out m_DocumentPivot);
  1130. }
  1131. bool inMosaicMode => spriteImportModeToUse == SpriteImportMode.Multiple && m_MosaicLayers;
  1132. SpriteImportMode spriteImportModeToUse =>
  1133. m_TextureImporterSettings.textureType != TextureImporterType.Sprite ?
  1134. SpriteImportMode.None :
  1135. (SpriteImportMode)m_TextureImporterSettings.spriteMode;
  1136. internal Vector2Int canvasSize => importData.documentSize;
  1137. #if ENABLE_2D_ANIMATION
  1138. internal CharacterData characterData
  1139. {
  1140. get
  1141. {
  1142. if (skeletonAsset != null)
  1143. return m_SharedRigCharacterData;
  1144. return m_CharacterData;
  1145. }
  1146. set
  1147. {
  1148. if (skeletonAsset != null)
  1149. m_SharedRigCharacterData = value;
  1150. else
  1151. m_CharacterData = value;
  1152. }
  1153. }
  1154. SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
  1155. {
  1156. if (!inCharacterMode || m_SpriteCategoryList.categories == null)
  1157. return null;
  1158. var categories = m_SpriteCategoryList.categories.Select(x =>
  1159. new SpriteLibCategory()
  1160. {
  1161. name = x.name,
  1162. categoryList = x.labels.Select(y =>
  1163. {
  1164. var sprite = sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y.spriteId);
  1165. return new SpriteCategoryEntry()
  1166. {
  1167. name = y.name,
  1168. sprite = sprite
  1169. };
  1170. }).ToList()
  1171. }).ToList();
  1172. categories.RemoveAll(x => x.categoryList.Count == 0);
  1173. if (categories.Count > 0)
  1174. {
  1175. // Always set version to 0 since we will never be updating this
  1176. return SpriteLibraryAsset.CreateAsset(categories, "Sprite Lib", 0);
  1177. }
  1178. return null;
  1179. }
  1180. #endif
  1181. internal void ReadTextureSettings(TextureImporterSettings dest)
  1182. {
  1183. m_TextureImporterSettings.CopyTo(dest);
  1184. }
  1185. internal IPSDLayerMappingStrategy GetLayerMappingStrategy()
  1186. {
  1187. return m_MappingCompare[(int)m_LayerMappingOption];
  1188. }
  1189. static void SetPhysicsOutline(ISpritePhysicsOutlineDataProvider physicsOutlineDataProvider, Sprite[] sprites, float definitionScale, float pixelsPerUnit, bool generatePhysicsShape)
  1190. {
  1191. foreach (var sprite in sprites)
  1192. {
  1193. var guid = sprite.GetSpriteID();
  1194. var outline = physicsOutlineDataProvider.GetOutlines(guid);
  1195. var outlineOffset = sprite.rect.size / 2;
  1196. var generated = false;
  1197. if ((outline == null || outline.Count == 0) && generatePhysicsShape)
  1198. {
  1199. InternalEditorBridge.GenerateOutlineFromSprite(sprite, 0.25f, 200, true, out var defaultOutline);
  1200. outline = new List<Vector2[]>(defaultOutline.Length);
  1201. for (var i = 0; i < defaultOutline.Length; ++i)
  1202. {
  1203. outline.Add(defaultOutline[i]);
  1204. }
  1205. generated = true;
  1206. }
  1207. if (outline != null && outline.Count > 0)
  1208. {
  1209. // Ensure that outlines are all valid.
  1210. var validOutlineCount = 0;
  1211. for (var i = 0; i < outline.Count; ++i)
  1212. validOutlineCount += ( (outline[i].Length > 2) ? 1 : 0 );
  1213. var index = 0;
  1214. var convertedOutline = new Vector2[validOutlineCount][];
  1215. var useScale = generated ? pixelsPerUnit * definitionScale : definitionScale;
  1216. for (var i = 0; i < outline.Count; ++i)
  1217. {
  1218. if (outline[i].Length > 2)
  1219. {
  1220. convertedOutline[index] = new Vector2[outline[i].Length];
  1221. for (var j = 0; j < outline[i].Length; ++j)
  1222. {
  1223. convertedOutline[index][j] = outline[i][j] * useScale + outlineOffset;
  1224. }
  1225. index++;
  1226. }
  1227. }
  1228. sprite.OverridePhysicsShape(convertedOutline);
  1229. }
  1230. }
  1231. }
  1232. }
  1233. }