暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

PSDImporter.cs 61KB

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