A game about forced loneliness, made by TACStudios
1using System;
2using System.Linq;
3using System.Collections.Generic;
4using UnityEngine;
5
6namespace UnityEditor.U2D.Sprites
7{
8 internal class TextureImporterDataProviderFactory :
9 ISpriteDataProviderFactory<Texture2D>,
10 ISpriteDataProviderFactory<Sprite>,
11 ISpriteDataProviderFactory<TextureImporter>,
12 ISpriteDataProviderFactory<GameObject>
13 {
14 public ISpriteEditorDataProvider CreateDataProvider(Texture2D obj)
15 {
16 var ti = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj)) as TextureImporter;
17 if (ti != null)
18 return new TextureImporterDataProvider(ti);
19 return null;
20 }
21
22 public ISpriteEditorDataProvider CreateDataProvider(Sprite obj)
23 {
24 var ti = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj)) as TextureImporter;
25 if (ti != null)
26 return new TextureImporterDataProvider(ti);
27 return null;
28 }
29
30 public ISpriteEditorDataProvider CreateDataProvider(GameObject obj)
31 {
32 var spriteRenderer = obj.GetComponent<SpriteRenderer>();
33 if (spriteRenderer != null && spriteRenderer.sprite != null)
34 {
35 var ti = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spriteRenderer.sprite)) as TextureImporter;
36 if (ti != null)
37 return new TextureImporterDataProvider(ti);
38 }
39 return null;
40 }
41
42 public ISpriteEditorDataProvider CreateDataProvider(TextureImporter obj)
43 {
44 return new TextureImporterDataProvider(obj);
45 }
46
47 [SpriteEditorAssetPathProviderAttribute]
48 static string GetAssetPathFromSpriteRenderer(UnityEngine.Object obj)
49 {
50 var go = obj as GameObject;
51 if (go != null)
52 {
53 var spriteRenderer = go.GetComponent<SpriteRenderer>();
54 if (spriteRenderer != null && spriteRenderer.sprite != null)
55 return AssetDatabase.GetAssetPath(spriteRenderer.sprite);
56 }
57 return null;
58 }
59
60 [SpriteObjectProvider]
61 static Sprite GetSpriteObjectFromSpriteRenderer(UnityEngine.Object obj)
62 {
63 var go = obj as GameObject;
64 if (go != null)
65 {
66 var spriteRenderer = go.GetComponent<SpriteRenderer>();
67 if (spriteRenderer != null)
68 return spriteRenderer.sprite;
69 }
70 return null;
71 }
72 }
73
74 internal class TextureImporterDataProvider : ISpriteEditorDataProvider, ISpriteNameFileIdDataProvider
75 {
76 TextureImporter m_TextureImporter;
77 SpriteNameFileIdPairExt[] m_NameFileIdPairs;
78 List<SpriteDataExt> m_SpritesMultiple;
79 SpriteDataExt m_SpriteSingle;
80 Dictionary<string, string> m_CustomMetadata;
81
82 SpriteImportMode m_SpriteImportMode = SpriteImportMode.None;
83 SecondarySpriteTexture[] m_SecondaryTextureDataTransfer;
84 SerializedObject m_CachedSerializedObject;
85
86 internal TextureImporterDataProvider(TextureImporter importer)
87 {
88 m_TextureImporter = importer;
89 if (m_TextureImporter != null)
90 {
91 m_SpriteImportMode = m_TextureImporter.spriteImportMode;
92 m_CachedSerializedObject = new SerializedObject(m_TextureImporter);
93 }
94 }
95
96 public Dictionary<string, string> customMetadata => m_CustomMetadata;
97
98 float ISpriteEditorDataProvider.pixelsPerUnit
99 {
100 get { return m_TextureImporter.spritePixelsPerUnit; }
101 }
102
103 UnityEngine.Object ISpriteEditorDataProvider.targetObject
104 {
105 get { return m_TextureImporter; }
106 }
107
108 public SpriteImportMode spriteImportMode
109 {
110 get { return m_SpriteImportMode; }
111 }
112
113 SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects()
114 {
115 return spriteImportMode == SpriteImportMode.Multiple ? m_SpritesMultiple.Select(x => new SpriteDataExt(x) as SpriteRect).ToArray() : new[] { new SpriteDataExt(m_SpriteSingle) };
116 }
117
118 public SerializedObject GetSerializedObject()
119 {
120 m_CachedSerializedObject?.UpdateIfRequiredOrScript();
121 return m_CachedSerializedObject;
122 }
123
124 public string assetPath
125 {
126 get { return m_TextureImporter.assetPath; }
127 }
128
129 public void GetWidthAndHeight(ref int width, ref int height)
130 {
131 m_TextureImporter.GetWidthAndHeight(ref width, ref height);
132 }
133
134 void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects)
135 {
136 if (spriteImportMode != SpriteImportMode.Multiple && spriteImportMode != SpriteImportMode.None && spriteRects.Length == 1)
137 {
138 m_SpriteSingle.CopyFromSpriteRect(spriteRects[0]);
139 }
140 else if (spriteImportMode == SpriteImportMode.Multiple)
141 {
142 Dictionary<GUID, SpriteRect> newSprites = new Dictionary<GUID, SpriteRect>();
143 foreach (var newSprite in spriteRects)
144 {
145 newSprites.Add(newSprite.spriteID, newSprite);
146 }
147 HashSet<long> internalIdUsed = new HashSet<long>();
148 for (int i = m_SpritesMultiple.Count - 1; i >= 0; --i)
149 {
150 var spriteID = m_SpritesMultiple[i].spriteID;
151 if (newSprites.TryGetValue(spriteID, out SpriteRect smd))
152 {
153 m_SpritesMultiple[i].CopyFromSpriteRect(smd);
154 internalIdUsed.Add(m_SpritesMultiple[i].internalID);
155 newSprites.Remove(spriteID);
156 }
157 else
158 {
159 m_SpritesMultiple.RemoveAt(i);
160 }
161 }
162 // Add new ones
163 var nameIdTable = GetSerializedNameFileIdTable(GetSerializedObject());
164 // First pass map by id
165 var values = newSprites.Values.ToArray();
166 foreach (var newSprite in values)
167 {
168 var newSpriteRect = new SpriteDataExt(newSprite);
169 var nameIdPair = nameIdTable.FirstOrDefault(x => x.GetFileGUID() == newSprite.spriteID);
170 if (nameIdPair != null && !internalIdUsed.Contains(nameIdPair.internalID))
171 {
172 newSpriteRect.internalID = nameIdPair.internalID;
173 internalIdUsed.Add(nameIdPair.internalID);
174 m_SpritesMultiple.Add(newSpriteRect);
175 newSprites.Remove(newSprite.spriteID);
176 }
177 }
178 //Second pass map by name
179 foreach (var newSprite in newSprites.Values)
180 {
181 var newSpriteRect = new SpriteDataExt(newSprite);
182 var nameIdPair = nameIdTable.FirstOrDefault(x => x.name == newSprite.name);
183 if (nameIdPair != null && !internalIdUsed.Contains(nameIdPair.internalID))
184 newSpriteRect.internalID = nameIdPair.internalID;
185
186 internalIdUsed.Add(newSpriteRect.internalID);
187 m_SpritesMultiple.Add(newSpriteRect);
188 }
189 }
190 }
191
192 IEnumerable<SpriteNameFileIdPair> ISpriteNameFileIdDataProvider.GetNameFileIdPairs()
193 {
194 return m_NameFileIdPairs.ToArray<SpriteNameFileIdPair>();
195 }
196
197 void ISpriteNameFileIdDataProvider.SetNameFileIdPairs(IEnumerable<SpriteNameFileIdPair> pairs)
198 {
199 var newFileIdPair = new SpriteNameFileIdPairExt[pairs.Count()];
200 var count = 0;
201 foreach (var pair in pairs)
202 {
203 var guid = pair.GetFileGUID();
204 var internalId = (long)guid.GetHashCode();
205 //check if guid is in current name id table
206 var idPair = m_NameFileIdPairs.FirstOrDefault(x => x.GetFileGUID() == guid);
207 if (idPair != null)
208 internalId = idPair.internalID;
209 else
210 {
211 // check if guid is in current sprite list
212 var sr = m_SpritesMultiple.FirstOrDefault(x => x.spriteID == guid);
213 if (sr != null)
214 internalId = sr.internalID;
215 }
216 newFileIdPair[count] = new SpriteNameFileIdPairExt(pair.name, guid, internalId);
217 count++;
218 }
219
220 m_NameFileIdPairs = newFileIdPair;
221 }
222
223 internal SpriteRect GetSpriteData(GUID guid)
224 {
225 return spriteImportMode == SpriteImportMode.Multiple ? m_SpritesMultiple.FirstOrDefault(x => x.spriteID == guid) : m_SpriteSingle;
226 }
227
228 internal int GetSpriteDataIndex(GUID guid)
229 {
230 switch (spriteImportMode)
231 {
232 case SpriteImportMode.Single:
233 case SpriteImportMode.Polygon:
234 return 0;
235 case SpriteImportMode.Multiple:
236 {
237 return m_SpritesMultiple.FindIndex(x => x.spriteID == guid);
238 }
239 default:
240 throw new InvalidOperationException(string.Format("Sprite with GUID {0} not found", guid));
241 }
242 }
243
244 void ISpriteEditorDataProvider.Apply()
245 {
246 var so = GetSerializedObject();
247 m_SpriteSingle.Apply(so);
248
249 var spriteSheet = so.FindProperty("m_SpriteSheet");
250 var spriteSheetSprites = spriteSheet.FindPropertyRelative("m_Sprites");
251 Dictionary<GUID, SpriteDataExt> newSprites = new Dictionary<GUID, SpriteDataExt>();
252 foreach (var newSprite in m_SpritesMultiple)
253 {
254 newSprites.Add(newSprite.spriteID, newSprite);
255 }
256
257 if (spriteSheetSprites.arraySize > 0)
258 {
259 var validateCurrent = spriteSheetSprites.GetArrayElementAtIndex(0);
260 for (int i = 0; i < spriteSheetSprites.arraySize; ++i)
261 {
262 var guid = SpriteRect.GetSpriteIDFromSerializedProperty(validateCurrent);
263 // find the GUID in our sprite list and apply to it;
264 if (newSprites.TryGetValue(guid, out SpriteDataExt smd))
265 {
266 smd.Apply(validateCurrent);
267 newSprites.Remove(guid);
268 validateCurrent.Next(false);
269 }
270 else// we can't find it, it is already deleted
271 {
272 spriteSheetSprites.DeleteArrayElementAtIndex(i);
273 --i;
274 }
275 }
276 }
277
278 // Add new ones
279 int newCount = newSprites.Count();
280 if (newCount > 0)
281 {
282 var idx = spriteSheetSprites.arraySize;
283 spriteSheetSprites.arraySize += newCount;
284 var addCurrent = spriteSheetSprites.GetArrayElementAtIndex(idx);
285 foreach (var newSprite in newSprites.Values)
286 {
287 newSprite.Apply(addCurrent);
288 addCurrent.Next(false);
289 }
290 }
291
292 var noOfPairs = m_NameFileIdPairs.Length;
293 var pairsSo = spriteSheet.FindPropertyRelative("m_NameFileIdTable");
294 pairsSo.arraySize = noOfPairs;
295 if (noOfPairs > 0)
296 {
297 var element = pairsSo.GetArrayElementAtIndex(0);
298 foreach (var pair in m_NameFileIdPairs)
299 {
300 pair.Apply(element);
301 element.Next(false);
302 }
303 }
304
305 SpriteSecondaryTextureDataTransfer.Apply(so, m_SecondaryTextureDataTransfer);
306 SpriteCustomDataTransfer.Apply(spriteSheet, m_CustomMetadata);
307
308 so.ApplyModifiedPropertiesWithoutUndo();
309 }
310
311 void ISpriteEditorDataProvider.InitSpriteEditorDataProvider()
312 {
313 var so = GetSerializedObject();
314
315 var spriteSheet = so.FindProperty("m_SpriteSheet");
316 var spriteSheetSprites = spriteSheet.FindPropertyRelative("m_Sprites");
317 m_SpritesMultiple = new List<SpriteDataExt>();
318 m_SpriteSingle = new SpriteDataExt(so);
319
320 if (spriteSheetSprites.arraySize > 0)
321 {
322 var sp = spriteSheetSprites.GetArrayElementAtIndex(0);
323 for (var i = 0; i < spriteSheetSprites.arraySize; ++i)
324 {
325 var data = new SpriteDataExt(sp);
326 m_SpritesMultiple.Add(data);
327 sp.Next(false);
328 }
329 }
330
331 m_SecondaryTextureDataTransfer = SpriteSecondaryTextureDataTransfer.Load(so);
332 m_CustomMetadata = SpriteCustomDataTransfer.Load(spriteSheet);
333
334 m_NameFileIdPairs = GetSerializedNameFileIdTable(so);
335 }
336
337 SpriteNameFileIdPairExt[] GetSerializedNameFileIdTable(SerializedObject so)
338 {
339 var nameFileIdTableSo = so.FindProperty("m_SpriteSheet.m_NameFileIdTable");
340 var arraySize = nameFileIdTableSo.arraySize;
341 var nameFileIdPairs = new SpriteNameFileIdPairExt[arraySize];
342 if (nameFileIdPairs.Length > 0)
343 {
344 var sp = nameFileIdTableSo.GetArrayElementAtIndex(0);
345 for (var i = 0; i < nameFileIdTableSo.arraySize; ++i)
346 {
347 var spriteNameFileId = SpriteNameFileIdPairExt.GetValue(sp);
348 // check if this internal nid is already in one of the sprite.
349 // We don't check name as changing internal id can cause reference to be lost
350 var spriteRect = m_SpritesMultiple.FirstOrDefault(x => x.internalID == spriteNameFileId.internalID);
351 if (spriteRect != null)
352 spriteNameFileId.SetFileGUID(spriteRect.spriteID);
353 nameFileIdPairs[i] = spriteNameFileId;
354 sp.Next(false);
355 }
356 }
357
358 return nameFileIdPairs;
359 }
360
361 T ISpriteEditorDataProvider.GetDataProvider<T>()
362 {
363 if (typeof(T) == typeof(ISpriteBoneDataProvider))
364 {
365 return new SpriteBoneDataTransfer(this) as T;
366 }
367 if (typeof(T) == typeof(ISpriteMeshDataProvider))
368 {
369 return new SpriteMeshDataTransfer(this) as T;
370 }
371 if (typeof(T) == typeof(ISpriteOutlineDataProvider))
372 {
373 return new SpriteOutlineDataTransfer(this) as T;
374 }
375 if (typeof(T) == typeof(ISpritePhysicsOutlineDataProvider))
376 {
377 return new SpritePhysicsOutlineDataTransfer(this) as T;
378 }
379 if (typeof(T) == typeof(ITextureDataProvider))
380 {
381 return new SpriteTextureDataTransfer(this) as T;
382 }
383 if (typeof(T) == typeof(ISecondaryTextureDataProvider))
384 {
385 return new SpriteSecondaryTextureDataTransfer(this) as T;
386 }
387 if (typeof(T) == typeof(ISpriteCustomDataProvider))
388 {
389 return new SpriteCustomDataTransfer(this) as T;
390 }
391 else
392 return this as T;
393 }
394
395 bool ISpriteEditorDataProvider.HasDataProvider(Type type)
396 {
397 if (type == typeof(ISpriteBoneDataProvider) ||
398 type == typeof(ISpriteMeshDataProvider) ||
399 type == typeof(ISpriteOutlineDataProvider) ||
400 type == typeof(ISpritePhysicsOutlineDataProvider) ||
401 type == typeof(ITextureDataProvider) ||
402 type == typeof(ISecondaryTextureDataProvider) ||
403 type == typeof(ISpriteCustomDataProvider))
404 {
405 return true;
406 }
407 else
408 return type.IsAssignableFrom(GetType());
409 }
410
411 public override bool Equals(object a)
412 {
413 return this == (a as TextureImporterDataProvider);
414 }
415
416 public override int GetHashCode()
417 {
418 return base.GetHashCode();
419 }
420
421 public static bool operator!=(TextureImporterDataProvider t1, TextureImporterDataProvider t2)
422 {
423 return !(t1 == t2);
424 }
425
426 public static bool operator==(TextureImporterDataProvider t1, TextureImporterDataProvider t2)
427 {
428 if (ReferenceEquals(null, t1) && (!ReferenceEquals(null, t2) && t2.m_TextureImporter == null) ||
429 ReferenceEquals(null, t2) && (!ReferenceEquals(null, t1) && t1.m_TextureImporter == null))
430 return true;
431
432 if (!ReferenceEquals(null, t1) && !ReferenceEquals(null, t2))
433 {
434 if (t1.m_TextureImporter == null && t2.m_TextureImporter == null ||
435 t1.m_TextureImporter == t2.m_TextureImporter)
436 return true;
437 }
438 if (ReferenceEquals(t1, t2))
439 return true;
440
441 return false;
442 }
443
444 public SecondarySpriteTexture[] secondaryTextures
445 {
446 get { return m_SecondaryTextureDataTransfer; }
447 set { m_SecondaryTextureDataTransfer = value; }
448 }
449 }
450}