com.typhoon.unitysdk 1.0.37 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2849 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.IO;
4
+ using System.Linq;
5
+ using System.Reflection;
6
+ using System.Text;
7
+ using System.Threading.Tasks;
8
+ using UnityEditor;
9
+ using UnityEditor.IMGUI.Controls;
10
+ using UnityEngine;
11
+ using Object = UnityEngine.Object;
12
+ #if UNITY_2020_1_OR_NEWER
13
+ using SourceTextureInformation = UnityEditor.AssetImporters.SourceTextureInformation;
14
+ #else
15
+ using SourceTextureInformation = UnityEditor.Experimental.AssetImporters.SourceTextureInformation;
16
+ #endif
17
+
18
+ namespace TyphoonUnitySDK
19
+ {
20
+ /// <summary>
21
+ /// 压缩工具
22
+ /// </summary>
23
+ public class XCompressTool : EditorWindow
24
+ {
25
+
26
+ public struct PathDepth
27
+ {
28
+ public string Path;
29
+ public string Name;
30
+ public int Depth;
31
+ public List<string> Paths;
32
+
33
+ public PathDepth(string path, string name, int depth, List<string> paths)
34
+ {
35
+ Path = path;
36
+ Name = name;
37
+ Depth = depth;
38
+ Paths = paths;
39
+ }
40
+ }
41
+
42
+ public class FolderTree : TreeView
43
+ {
44
+ public class ItemData
45
+ {
46
+ public PathDepth PathDepth;
47
+ public int? Count;
48
+
49
+ public ItemData(PathDepth pathDepth)
50
+ {
51
+ PathDepth = pathDepth;
52
+ }
53
+ }
54
+
55
+ //文件夹-图片数量字典1(原始路径)
56
+ private Dictionary<string, int> _originalTexMap = new Dictionary<string, int>();
57
+
58
+ //文件夹-图片数量字典2(unity路径使用/)
59
+ private Dictionary<string, int> _folderTexMap = new Dictionary<string, int>();
60
+ private Dictionary<int, ItemData> _idMap = new Dictionary<int, ItemData>();
61
+ private HashSet<string> _filterFolders = new HashSet<string>();
62
+
63
+ public event Action OnFolderFilterChanged = null;
64
+
65
+ public event Action OnClickTreeItem = null;
66
+
67
+ private int _pingId;
68
+
69
+ public FolderTree(TreeViewState state, Dictionary<string, int> folderMap) : base(state)
70
+ {
71
+ _originalTexMap = folderMap;
72
+ foreach (var pair in folderMap)
73
+ {
74
+ var path = pair.Key.Replace("\\", "/");
75
+ _folderTexMap[path] = pair.Value;
76
+ }
77
+
78
+ Reload();
79
+ }
80
+
81
+ protected override TreeViewItem BuildRoot()
82
+ {
83
+ var root = new TreeViewItem { id = 0, depth = -1, displayName = "Root" };
84
+ var depthMap = new Dictionary<string, PathDepth>();
85
+ var folders = _folderTexMap.Keys.ToList();
86
+ //拆分文件夹目录
87
+ foreach (var folder in folders)
88
+ {
89
+ var depths = ParseToPathDepths(folder);
90
+ foreach (var depth in depths)
91
+ {
92
+ depthMap[depth.Path] = depth;
93
+ }
94
+ }
95
+
96
+ var list = depthMap.Values.ToList();
97
+ //深度排序
98
+ list.Sort((a, b) =>
99
+ {
100
+ var pathA = a.Paths;
101
+ var pathB = b.Paths;
102
+ var result = 0;
103
+ for (int i = 0; i < pathA.Count && i < pathB.Count; i++)
104
+ {
105
+ var nameA = pathA[i];
106
+ var nameB = pathB[i];
107
+ result = String.Compare(nameA, nameB, StringComparison.Ordinal);
108
+ if (result != 0)
109
+ {
110
+ return result;
111
+ }
112
+ }
113
+
114
+ return pathA.Count.CompareTo(pathB.Count);
115
+ });
116
+ var tree = new List<TreeViewItem>();
117
+ var id = 0;
118
+ //生成层级树
119
+ foreach (var element in list)
120
+ {
121
+ id += 1;
122
+ tree.Add(new TreeViewItem(id, element.Depth, element.Name));
123
+ _idMap[id] = new ItemData(element);
124
+ }
125
+
126
+ //根据层级生成
127
+ SetupParentsAndChildrenFromDepths(root, tree);
128
+ return root;
129
+ }
130
+
131
+ private List<PathDepth> ParseToPathDepths(string path)
132
+ {
133
+ //创建
134
+ var depths = new List<PathDepth>();
135
+ var stack = new Stack<string>();
136
+ var check = path;
137
+ while (!string.IsNullOrEmpty(check))
138
+ {
139
+ var name = Path.GetFileName(check);
140
+ check = Path.GetDirectoryName(check);
141
+ stack.Push(name);
142
+ }
143
+
144
+ var sb = new StringBuilder();
145
+ var depth = 0;
146
+ var paths = new List<string>();
147
+ while (stack.Count > 0)
148
+ {
149
+ var name = stack.Pop();
150
+ if (depth != 0)
151
+ {
152
+ sb.Append("/");
153
+ }
154
+
155
+ paths.Add(name);
156
+ sb.Append(name);
157
+ depth += 1;
158
+ depths.Add(new PathDepth(sb.ToString(), name, depth, paths.ToList()));
159
+ }
160
+
161
+ return depths;
162
+ }
163
+
164
+ public bool IsChanged(Dictionary<string, int> folderMap)
165
+ {
166
+ if (_originalTexMap.Count != folderMap.Count)
167
+ {
168
+ return true;
169
+ }
170
+
171
+ foreach (var pair in _originalTexMap)
172
+ {
173
+ var key = pair.Key;
174
+ var value = pair.Value;
175
+ if (folderMap.TryGetValue(key, out var match))
176
+ {
177
+ if (match == value)
178
+ {
179
+ continue;
180
+ }
181
+ }
182
+
183
+ return true;
184
+ }
185
+
186
+ return false;
187
+ }
188
+
189
+ private int GetTextureCount(int id)
190
+ {
191
+ var data = _idMap[id];
192
+ if (data.Count == null)
193
+ {
194
+ var total = 0;
195
+ foreach (var pair in _folderTexMap)
196
+ {
197
+ var key = pair.Key;
198
+ var count = pair.Value;
199
+ if (key.StartsWith(data.PathDepth.Path))
200
+ {
201
+ total += count;
202
+ }
203
+ }
204
+
205
+ data.Count = total;
206
+ }
207
+
208
+ return data.Count.Value;
209
+ }
210
+
211
+ protected override void RowGUI(RowGUIArgs args)
212
+ {
213
+ args.label = $"{args.label}({GetTextureCount(args.item.id)})";
214
+ base.RowGUI(args);
215
+ if (_pingId == args.item.id)
216
+ {
217
+ var rect = args.rowRect;
218
+ EditorGUI.DrawRect(rect, Color.cyan * 0.3f);
219
+ }
220
+ }
221
+
222
+
223
+ protected override void SingleClickedItem(int id)
224
+ {
225
+ base.SingleClickedItem(id);
226
+ OnClickTreeItem?.Invoke();
227
+ }
228
+
229
+ protected override void SelectionChanged(IList<int> selectedIds)
230
+ {
231
+ base.SelectionChanged(selectedIds);
232
+ _filterFolders.Clear();
233
+ foreach (var id in selectedIds)
234
+ {
235
+ _filterFolders.Add(_idMap[id].PathDepth.Path);
236
+ }
237
+
238
+ OnFolderFilterChanged?.Invoke();
239
+ }
240
+
241
+ public void Release()
242
+ {
243
+ OnFolderFilterChanged = null;
244
+ OnClickTreeItem = null;
245
+ }
246
+
247
+ public HashSet<string> GetFilterFolder() => _filterFolders;
248
+
249
+ public bool TryGetItemDataFormTexturePath(string path, out ItemData data, out int id)
250
+ {
251
+ id = -1;
252
+ data = null;
253
+ if (string.IsNullOrEmpty(path))
254
+ {
255
+ return false;
256
+ }
257
+
258
+ var folder = Path.GetDirectoryName(path);
259
+ folder = folder.Replace("\\", "/");
260
+ foreach (var pair in _idMap)
261
+ {
262
+ var key = pair.Key;
263
+ var value = pair.Value;
264
+ if (value.PathDepth.Path == folder)
265
+ {
266
+ id = key;
267
+ data = value;
268
+ return true;
269
+ }
270
+ }
271
+
272
+ return false;
273
+ }
274
+
275
+
276
+ public List<int> FindTreeItemIdsByFolder(string folder)
277
+ {
278
+ var result = new List<int>();
279
+ foreach (var pair in _idMap)
280
+ {
281
+ if (folder.StartsWith(pair.Value.PathDepth.Path))
282
+ {
283
+ result.Add(pair.Key);
284
+ }
285
+ }
286
+
287
+ return result;
288
+ }
289
+
290
+ public void PingFolder(string texturePath, bool expand)
291
+ {
292
+ _pingId = -1;
293
+ if (TryGetItemDataFormTexturePath(texturePath, out var match, out var id))
294
+ {
295
+ _pingId = id;
296
+ if (expand)
297
+ {
298
+ var ids = FindTreeItemIdsByFolder(_idMap[id].PathDepth.Path); //GetExpanded().Union().ToList();
299
+ SetExpanded(ids);
300
+ }
301
+ }
302
+ }
303
+ }
304
+
305
+ private enum SelectMode
306
+ {
307
+ Single,
308
+ Shift,
309
+ Ctrl,
310
+ }
311
+
312
+ //焦点场景
313
+ private enum FocusScene
314
+ {
315
+ FolderTree,
316
+ ItemView,
317
+ }
318
+
319
+ //GUI布局场景
320
+ private enum LayoutScene
321
+ {
322
+ Left,
323
+ Center,
324
+ }
325
+
326
+ //图片信息
327
+ public class TextureInfo
328
+ {
329
+ public string Guid;
330
+ private Texture _texture;
331
+
332
+ private Dictionary<BuildTarget, TextureImporterFormat> _defaultFormatMap =
333
+ new Dictionary<BuildTarget, TextureImporterFormat>();
334
+
335
+ public Texture Texture
336
+ {
337
+ get
338
+ {
339
+ if (_texture == null)
340
+ {
341
+ _texture = AssetDatabase.LoadAssetAtPath<Texture>(GetImporter(Guid).assetPath);
342
+ }
343
+
344
+ return _texture;
345
+ }
346
+ }
347
+
348
+ public TextureImporterFormat DefaultFormat
349
+ {
350
+ get
351
+ {
352
+ if (_defaultFormatMap.TryGetValue(_filterBuildTarget, out var match))
353
+ {
354
+ return match;
355
+ }
356
+
357
+ var format = GetImporter(Guid)
358
+ .GetAutomaticFormat(BuildPipeline.GetBuildTargetName(_filterBuildTarget));
359
+ _defaultFormatMap[_filterBuildTarget] = format;
360
+ return format;
361
+ }
362
+ }
363
+
364
+ public TextureImporterPlatformSettings Settings => GetImporter(Guid)
365
+ .GetPlatformTextureSettings(BuildPipeline.GetBuildTargetName(_filterBuildTarget));
366
+
367
+ public string Name => Texture.name;
368
+ public SourceTextureInformation SourceInfo;
369
+ }
370
+
371
+ //属性栏配置
372
+ public class PropertyTabBinding
373
+ {
374
+ public PropertyTab EnumType;
375
+ public float LabelWidth;
376
+ public bool CanSort => SortDelegate != null;
377
+ public Action<List<string>, bool> SortDelegate;
378
+
379
+
380
+ public PropertyTabBinding(PropertyTab enumType, float labelWidth,
381
+ Action<List<string>, bool> sortDelegate)
382
+ {
383
+ EnumType = enumType;
384
+ LabelWidth = labelWidth;
385
+ SortDelegate = sortDelegate;
386
+ }
387
+ }
388
+
389
+ //元素高度
390
+ private const float ITEM_HEIGHT = 22;
391
+ private static int PROPERTY_TITLE_BAR_HEIGHT = 24;
392
+ private const float ITEM_EDGE_RANGE = 60;
393
+ private const float INSPECTOR_VIEW_HEIGHT = 1000;
394
+ private const float PREVIEW_HEIGHT = 260;
395
+ private static RectOffset _item_padding = null;
396
+
397
+ private static Dictionary<string, int> _lastSortMap = new Dictionary<string, int>();
398
+
399
+ private static RectOffset ITEM_PADDING
400
+ {
401
+ get
402
+ {
403
+ if (_item_padding == null)
404
+ {
405
+ _item_padding = new RectOffset(10, 10, PROPERTY_TITLE_BAR_HEIGHT + 2, 30);
406
+ }
407
+
408
+ return _item_padding;
409
+ }
410
+ }
411
+
412
+
413
+ private static Dictionary<string, string> FormatNames = new Dictionary<string, string>()
414
+ {
415
+ { "Alpha8", "Alpha 8" },
416
+ { "ARGB16", "ARGB 16 bits" },
417
+ { "RGB24", "RGB 24 bits" },
418
+ { "RGBA32", "RGBA 32 bits" },
419
+ { "ARGB32", "ARGB 32 bits" },
420
+ { "RGB16", "RGB 16 bits" },
421
+ { "R16", "R 16 bits" },
422
+ { "DXT1", "RGB DXT 1" },
423
+ { "DXT5", "RGBA DXT 5" },
424
+ { "RGBA16", "RGBA 16 bits" },
425
+ { "RHalf", "R Half" },
426
+ { "RGHalf", "RG Half" },
427
+ { "RGBAHalf", "RGBA Half" },
428
+ { "RFloat", "R Float" },
429
+ { "RGFloat", "RG Float" },
430
+ { "RGBAFloat", "RGBA Float" },
431
+ { "RGB9E5", "RGB9e5 32 bits" },
432
+ { "BC6H", "RGB HDR BC6H" },
433
+ { "BC7", "RGBA BC7" },
434
+ { "BC4", "R BC4" },
435
+ { "BC5", "RG BC5" },
436
+ { "DXT1Crunched", "RGB Crunched DXT 1" },
437
+ { "DXT5Crunched", "RGBA Crunched DXT 5" },
438
+ { "PVRTC_RGB2", "RGB PVRTC 2 bits" },
439
+ { "PVRTC_RGBA2", "RGBA PVRTC 2 bits" },
440
+ { "PVRTC_RGB4", "RGB PVRTC 4 bits" },
441
+ { "PVRTC_RGBA4", "RGBA PVRTC 4 bits" },
442
+ { "ETC_RGB4", "RGB ETC 4 bits" },
443
+ { "EAC_R", "R EAC 4 bits" },
444
+ { "EAC_R_SIGNED", "R EAC Signed 4 bits" },
445
+ { "EAC_RG", "RG EAC 8 bits" },
446
+ { "EAC_RG_SIGNED", "RG EAC Signed 8 bits" },
447
+ { "ETC2_RGB4", "RGB ETC2 4 bits" },
448
+ { "ETC2_RGB4_PUNCHTHROUGH_ALPHA", "RGB +1-bit Alpha ETC2 4 bits" },
449
+ { "ETC2_RGBA8", "RGBA ETC2 8 bits" },
450
+ { "ASTC_4x4", "RGB(A) ASTC 4x4 block" },
451
+ { "ASTC_RGB_4x4", "RGB ASTC 4x4 block" },
452
+ { "ASTC_5x5", "RGB(A) ASTC 5x5 block" },
453
+ { "ASTC_RGB_5x5", "RGB ASTC 5x5 block" },
454
+ { "ASTC_6x6", "RGB(A) ASTC 6x6 block" },
455
+ { "ASTC_RGB_6x6", "RGB ASTC 6x6 block" },
456
+ { "ASTC_8x8", "RGB(A) ASTC 8x8 block" },
457
+ { "ASTC_RGB_8x8", "RGB ASTC 8x8 block" },
458
+ { "ASTC_10x10", "RGB(A) ASTC 10x10 block" },
459
+ { "ASTC_RGB_10x10", "RGB ASTC 10x10 block" },
460
+ { "ASTC_12x12", "RGB(A) ASTC 12x12 block" },
461
+ { "ASTC_RGB_12x12", "RGB ASTC 12x12 block" },
462
+ { "ASTC_RGBA_4x4", "RGBA ASTC 4x4 block" },
463
+ { "ASTC_RGBA_5x5", "RGBA ASTC 5x5 block" },
464
+ { "ASTC_RGBA_6x6", "RGBA ASTC 6x6 block" },
465
+ { "ASTC_RGBA_8x8", "RGBA ASTC 8x8 block" },
466
+ { "ASTC_RGBA_10x10", "RGBA ASTC 10x10 block" },
467
+ { "ASTC_RGBA_12x12", "RGBA ASTC 12x12 block" },
468
+ { "RG16", "RG 16" },
469
+ { "R8", "R 8" },
470
+ { "ETC_RGB4Crunched", "RGB Crunched ETC" },
471
+ { "ETC2_RGBA8Crunched", "RGBA Crunched ETC" },
472
+ { "ASTC_HDR_4x4", "RGB(A) ASTC HDR 4x4 block" },
473
+ { "ASTC_HDR_5x5", "RGB(A) ASTC HDR 5x5 block" },
474
+ { "ASTC_HDR_6x6", "RGB(A) ASTC HDR 6x6 block" },
475
+ { "ASTC_HDR_8x8", "RGB(A) ASTC HDR 8x8 block" },
476
+ { "ASTC_HDR_10x10", "RGB(A) ASTC HDR 10x10 block" },
477
+ { "ASTC_HDR_12x12", "RGB(A) ASTC HDR 12x12 block" },
478
+ { "RG32", "RG 32 bit" },
479
+ { "RGB48", "RGB 48 bit" },
480
+ { "RGBA64", "RGBA 64 bit" },
481
+ };
482
+
483
+
484
+ public enum PropertyTab
485
+ {
486
+ NO,
487
+ Name,
488
+ Override,
489
+ Format,
490
+ MaxSize,
491
+ SourceSize,
492
+ MipMap,
493
+ NpotScale,
494
+ Path,
495
+ Type,
496
+ }
497
+
498
+ private const string CONTROL_NAME_SEARCH_BAR = "CONTROL_NAME_SEARCH_BAR";
499
+
500
+ private const string CONTROL_FOLDER_SEARCH_BAR = "CONTROL_FOLDER_SEARCH_BAR";
501
+
502
+ //平台选择
503
+ private static List<BuildTarget> FILTER_BUILD_TARGET
504
+ {
505
+ get
506
+ {
507
+ if (_FILTER_BUILD_TARGET == null)
508
+ {
509
+ _FILTER_BUILD_TARGET = new List<BuildTarget>();
510
+ var check = new Dictionary<BuildTarget, BuildTargetGroup>()
511
+ {
512
+ { BuildTarget.Android, BuildTargetGroup.Android },
513
+ { BuildTarget.iOS, BuildTargetGroup.iOS },
514
+ { BuildTarget.WebGL, BuildTargetGroup.WebGL },
515
+ { BuildTarget.StandaloneWindows, BuildTargetGroup.Standalone },
516
+ { BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone },
517
+ { BuildTarget.StandaloneLinux64, BuildTargetGroup.Standalone },
518
+ };
519
+
520
+ foreach (var pair in check)
521
+ {
522
+ if (BuildPipeline.IsBuildTargetSupported(pair.Value, pair.Key))
523
+ {
524
+ _FILTER_BUILD_TARGET.Add(pair.Key);
525
+ }
526
+ }
527
+ }
528
+
529
+ return _FILTER_BUILD_TARGET;
530
+ }
531
+ }
532
+
533
+
534
+ private static List<BuildTarget> _FILTER_BUILD_TARGET = null;
535
+
536
+
537
+ //筛选发生变化
538
+ private static event Action OnFilterChanged = null;
539
+
540
+ //选择项变化
541
+ private static event Action OnSelectChanged = null;
542
+
543
+ private static float LEFT_MENU_WIDTH = 268;
544
+
545
+ //过滤TextureImporterType
546
+ private static TextureImporterType[] FILTER_TEXTURE_TYPE = GetValidEnumValues<TextureImporterType>();
547
+
548
+ //过滤TextureImporterShape
549
+ private static TextureImporterShape[] FILTER_SHAPE_TYPE = GetValidEnumValues<TextureImporterShape>();
550
+
551
+ private static Dictionary<TextureImporterFormat, string> _formatNamesRemap = null;
552
+
553
+ private static string GetFormatName(TextureImporterFormat format)
554
+ {
555
+ if (_formatNamesRemap == null)
556
+ {
557
+ _formatNamesRemap = new Dictionary<TextureImporterFormat, string>();
558
+ foreach (var kv in FormatNames)
559
+ {
560
+ var key = kv.Key;
561
+ var name = kv.Value;
562
+ try
563
+ {
564
+ var enumType = (TextureImporterFormat)Enum.Parse(typeof(TextureImporterFormat), key);
565
+ _formatNamesRemap[enumType] = name;
566
+ }
567
+ catch (Exception e)
568
+ {
569
+ }
570
+ }
571
+ }
572
+
573
+ if (_formatNamesRemap.TryGetValue(format, out var match))
574
+ {
575
+ return match;
576
+ }
577
+
578
+ return format.ToString();
579
+ }
580
+
581
+ //选中的实例
582
+ private static HashSet<string> _selectGuids = new HashSet<string>();
583
+ private static TextureImporter[] _selectImporters;
584
+ private static HashSet<string> _selectImportersGuids = new HashSet<string>();
585
+ private static bool _previewGUIFlag = true;
586
+ private static Vector2 _scrollLeftWindow;
587
+ private static bool _filterFlag = true;
588
+ private static FolderTree _folderTree;
589
+ private static TreeViewState _treeViewState;
590
+ private static string _searchTreeTxt;
591
+ private static bool _multipleInspector = false;
592
+ private static HashSet<string> _cacheSelectTextures = new HashSet<string>();
593
+ private static HashSet<string> _cacheSelectCubeMap = new HashSet<string>();
594
+ private static HashSet<string> _hoverSelect = new HashSet<string>();
595
+
596
+ //缓存的排序类型
597
+ private static PropertyTab? _cacheSortBy = null;
598
+
599
+ //排序状态
600
+ private static Dictionary<PropertyTab, bool> _sortReverseMap = new Dictionary<PropertyTab, bool>();
601
+
602
+
603
+ [MenuItem("TyphoonSDK/工具箱/纹理压缩")]
604
+ private static void Open()
605
+ {
606
+ var window = GetWindow<XCompressTool>();
607
+ window.minSize = new Vector2(1280, 800);
608
+ window.titleContent = new GUIContent("纹理压缩");
609
+ window.Show();
610
+ }
611
+
612
+
613
+ /// <summary>
614
+ /// TextureImporter
615
+ /// </summary>
616
+ private static Dictionary<string, TextureImporter> _importers = new Dictionary<string, TextureImporter>();
617
+
618
+ private static Dictionary<string, TextureInfo> _infos = new Dictionary<string, TextureInfo>();
619
+
620
+ //默认排序
621
+ private static Dictionary<string, int> _defaultOrders = new Dictionary<string, int>();
622
+
623
+ private Dictionary<string, Rect> _itemsRects = new Dictionary<string, Rect>();
624
+
625
+
626
+ private static Vector2 _scroll;
627
+
628
+ //过滤图片类型
629
+ private static HashSet<TextureImporterType> _filterTextureType =
630
+ new HashSet<TextureImporterType>(FILTER_TEXTURE_TYPE);
631
+
632
+ //过滤shape类型
633
+ private static HashSet<TextureImporterShape> _filterShapeType =
634
+ new HashSet<TextureImporterShape>(FILTER_SHAPE_TYPE);
635
+
636
+ //过滤平台
637
+ private static BuildTarget _filterBuildTarget = BuildTarget.Android;
638
+
639
+ private static Editor _assetEditor = null;
640
+ private static Editor _inspectorEditor = null;
641
+ private static Editor InspectorEditor => _inspectorEditor;
642
+
643
+ private static PropertyTabBinding[] _propertyTabBindings = new[]
644
+ {
645
+ new PropertyTabBinding(PropertyTab.NO, 40, null),
646
+ new PropertyTabBinding(PropertyTab.Name, 260, SortByName),
647
+ new PropertyTabBinding(PropertyTab.Override, 90, SortByOverride),
648
+ new PropertyTabBinding(PropertyTab.Format, 260, SortByFormat),
649
+ new PropertyTabBinding(PropertyTab.MaxSize, 90, SortByMaxSize),
650
+ new PropertyTabBinding(PropertyTab.SourceSize, 120, SortBySourceSize),
651
+ new PropertyTabBinding(PropertyTab.MipMap, 90, SortByMipMap),
652
+ new PropertyTabBinding(PropertyTab.NpotScale, 120, SortByNpotScale),
653
+ new PropertyTabBinding(PropertyTab.Type, 140, SortByTextureType),
654
+ new PropertyTabBinding(PropertyTab.Path, 800, SortByPath),
655
+ };
656
+
657
+ private static Dictionary<PropertyTab, PropertyTabBinding> _propertyTabMap = null;
658
+
659
+ //属性宽度
660
+ private static Dictionary<PropertyTab, PropertyTabBinding> PropertyTabMap
661
+ {
662
+ get
663
+ {
664
+ if (_propertyTabMap == null)
665
+ {
666
+ _propertyTabMap = new Dictionary<PropertyTab, PropertyTabBinding>();
667
+ foreach (var binding in _propertyTabBindings)
668
+ {
669
+ _propertyTabMap[binding.EnumType] = binding;
670
+ }
671
+ }
672
+
673
+ return _propertyTabMap;
674
+ }
675
+ }
676
+
677
+
678
+ //区域范围
679
+ private static Rect _leftArea;
680
+ private static Rect _centerArea;
681
+ private static Rect _inspectorArea;
682
+ private static Rect _searchBarArea;
683
+ private static Rect _itemsArea;
684
+ private static Rect _searchFolderArea;
685
+
686
+
687
+ //搜索栏
688
+ private static string _searchTxt = "";
689
+ private static Rect _searchBarRange;
690
+ private static Vector2 _itemWindowScroll;
691
+ private List<string> _matchItems = new List<string>();
692
+ private static int _inspectorWidth = 360;
693
+ private static Vector2 _scrollInspector;
694
+ private string _lastSelectGuid;
695
+ private FocusScene _focusScene = FocusScene.ItemView;
696
+ private LayoutScene _lastLayoutScene = LayoutScene.Center;
697
+
698
+ private async void OnEnable()
699
+ {
700
+ //读取当前配置
701
+ _filterBuildTarget = EditorUserBuildSettings.activeBuildTarget;
702
+ _filterTextureType = new HashSet<TextureImporterType>(FILTER_TEXTURE_TYPE);
703
+ _filterShapeType = new HashSet<TextureImporterShape>(FILTER_SHAPE_TYPE);
704
+ _folderTree?.Release();
705
+ _folderTree = null;
706
+ await UpdateDatabaseAsync();
707
+ UpdateMatchItems();
708
+ OnSelectChanged -= WhenSelectChanged;
709
+ OnSelectChanged += WhenSelectChanged;
710
+ }
711
+
712
+ private void OnGUI()
713
+ {
714
+ if (EditorApplication.isCompiling && (_assetEditor != null || _inspectorEditor != null))
715
+ {
716
+ DestroyImmediate(_assetEditor, true);
717
+ DestroyImmediate(_inspectorEditor, true);
718
+ }
719
+
720
+ HandleEvent();
721
+ var rect = new Rect(0, 0, position.width, position.height);
722
+ var rectLeftMenu = new Rect(0, 0, LEFT_MENU_WIDTH, rect.height);
723
+ _leftArea = rectLeftMenu;
724
+ DrawLeftGUI(rectLeftMenu);
725
+ var rectLine = rectLeftMenu;
726
+ rectLine.width = 1;
727
+ rectLine.x = rectLeftMenu.xMax;
728
+ EditorGUI.DrawRect(rectLine, Color.black);
729
+ var rectCenter = rectLeftMenu;
730
+ rectCenter.x = rectLeftMenu.xMax;
731
+ rectCenter.width = rect.xMax - rectLeftMenu.xMax;
732
+ rectCenter.width -= _inspectorWidth;
733
+ rectCenter.width -= 2;
734
+ _centerArea = rectCenter;
735
+
736
+ DrawCenterGUI(rectCenter);
737
+
738
+ rectLine = rectCenter;
739
+ rectLine.width = 1;
740
+ rectLine.x = rectCenter.xMax;
741
+ EditorGUI.DrawRect(rectLine, Color.black);
742
+
743
+ var rectInspector = rectCenter;
744
+ rectInspector.x = rectCenter.xMax;
745
+ rectInspector.x += 2;
746
+ rectInspector.width = rect.xMax - rectInspector.x;
747
+ _inspectorArea = rectInspector;
748
+ DrawRightGUI(rectInspector);
749
+ }
750
+
751
+ private async void OnFocus()
752
+ {
753
+ OnSelectChanged -= WhenSelectChanged;
754
+ OnSelectChanged += WhenSelectChanged;
755
+ OnFilterChanged -= WhenFilterChanged;
756
+ OnFilterChanged += WhenFilterChanged;
757
+ await UpdateDatabaseAsync();
758
+ UpdateMatchItems(false);
759
+ }
760
+
761
+ //异步加载纹理数据库
762
+ private async Task UpdateDatabaseAsync()
763
+ {
764
+ //缓存旧数据
765
+ var cache = _importers;
766
+ _importers = new Dictionary<string, TextureImporter>();
767
+ var guids = AssetDatabase.FindAssets("t:texture", new[] { "Assets" });
768
+ _defaultOrders.Clear();
769
+ var order = 0;
770
+ foreach (var guid in guids)
771
+ {
772
+ order += 1;
773
+ _defaultOrders[guid] = order;
774
+ }
775
+
776
+ var append = new HashSet<string>();
777
+ foreach (var guid in guids)
778
+ {
779
+ if (cache.TryGetValue(guid, out var match))
780
+ {
781
+ //存在缓存条目
782
+ if (match != null)
783
+ {
784
+ _importers[guid] = match;
785
+ }
786
+ else
787
+ {
788
+ append.Add(guid);
789
+ }
790
+ }
791
+ else
792
+ {
793
+ //如果没有条目
794
+ append.Add(guid);
795
+ }
796
+ }
797
+
798
+ var total = append.Count;
799
+ var current = 0;
800
+ var nextCheck = EditorApplication.timeSinceStartup + 1f;
801
+ foreach (var element in append)
802
+ {
803
+ current += 1;
804
+ var process = (float)current / total;
805
+ var path = AssetDatabase.GUIDToAssetPath(element);
806
+ var importer = AssetImporter.GetAtPath(path) as TextureImporter;
807
+ if (importer != null)
808
+ {
809
+ _importers[element] = importer;
810
+ }
811
+
812
+ if (EditorApplication.timeSinceStartup > nextCheck)
813
+ {
814
+ EditorUtility.DisplayProgressBar("请稍等...", $"读取纹理...{(process * 100).ToString("F1")}%", process);
815
+ nextCheck = EditorApplication.timeSinceStartup + 2;
816
+ await Task.Yield();
817
+ }
818
+ }
819
+
820
+ //更新文件夹
821
+ var folderMap = new Dictionary<string, int>();
822
+ foreach (var pair in _importers)
823
+ {
824
+ var folder = Path.GetDirectoryName(pair.Value.assetPath);
825
+ if (folder != null)
826
+ {
827
+ if (!folderMap.ContainsKey(folder))
828
+ {
829
+ folderMap[folder] = 0;
830
+ }
831
+
832
+ folderMap[folder] += 1;
833
+ }
834
+ }
835
+
836
+ //查看是否一致
837
+ if (_folderTree == null || _folderTree.IsChanged(folderMap))
838
+ {
839
+ _folderTree?.Release();
840
+ _treeViewState = new TreeViewState();
841
+ _folderTree = new FolderTree(_treeViewState, folderMap);
842
+ _folderTree.OnFolderFilterChanged += WhenFolderFilterChanged;
843
+ _folderTree.OnClickTreeItem += WhenClickFolderTree;
844
+ }
845
+
846
+ EditorUtility.ClearProgressBar();
847
+ }
848
+
849
+
850
+ private void WhenFolderFilterChanged()
851
+ {
852
+ UpdateMatchItems();
853
+ }
854
+
855
+ //更新匹配项
856
+ private void UpdateMatchItems(bool resort = true)
857
+ {
858
+ _matchItems = new List<string>();
859
+ var filterFolder = new HashSet<string>();
860
+ if (_folderTree != null)
861
+ {
862
+ filterFolder = new HashSet<string>(_folderTree.GetFilterFolder());
863
+ }
864
+
865
+ //从文件夹中过滤
866
+ var searchTxtLow = string.IsNullOrEmpty(_searchTxt) ? "" : _searchTxt.ToLower();
867
+ foreach (var pair in _importers)
868
+ {
869
+ var guid = pair.Key;
870
+ var import = pair.Value;
871
+ var inside = filterFolder.Count <= 0;
872
+ foreach (var filter in filterFolder)
873
+ {
874
+ if (import.assetPath.StartsWith(filter))
875
+ {
876
+ inside = true;
877
+ break;
878
+ }
879
+ }
880
+
881
+ if (!inside)
882
+ {
883
+ continue;
884
+ }
885
+
886
+ if (!_filterTextureType.Contains(import.textureType))
887
+ {
888
+ continue;
889
+ }
890
+
891
+ if (!_filterShapeType.Contains(import.textureShape))
892
+ {
893
+ continue;
894
+ }
895
+
896
+ if (!string.IsNullOrEmpty(searchTxtLow))
897
+ {
898
+ if (!import.assetPath.ToLower().Contains(searchTxtLow))
899
+ {
900
+ continue;
901
+ }
902
+ }
903
+
904
+ _matchItems.Add(guid);
905
+ }
906
+
907
+ if (resort)
908
+ {
909
+ if (_cacheSortBy == null)
910
+ {
911
+ //按默认排序
912
+ SortByDefault();
913
+ }
914
+ else
915
+ {
916
+ var tab = _cacheSortBy.Value;
917
+ var binding = GetPropertyTabBinding(tab);
918
+ binding.SortDelegate?.Invoke(_matchItems, GetSortState(tab));
919
+ }
920
+
921
+ _lastSortMap.Clear();
922
+ var index = 0;
923
+ foreach (var guid in _matchItems)
924
+ {
925
+ index += 1;
926
+ _lastSortMap[guid] = index;
927
+ }
928
+ }
929
+ else
930
+ {
931
+ //同步上一次的排序
932
+ _matchItems.Sort((a, b) =>
933
+ {
934
+ if (!_lastSortMap.TryGetValue(a, out var indexA))
935
+ {
936
+ indexA = -1;
937
+ }
938
+
939
+ if (!_lastSortMap.TryGetValue(b, out var indexB))
940
+ {
941
+ indexB = -1;
942
+ }
943
+
944
+ return indexA.CompareTo(indexB);
945
+ });
946
+ }
947
+ }
948
+
949
+ #region 左侧GUI
950
+
951
+ //左侧GUI
952
+ private void DrawLeftGUI(Rect view)
953
+ {
954
+ EditorGUI.DrawRect(view, Color.black * 0.2f);
955
+ var menuView = view;
956
+ var center = menuView.center;
957
+ menuView.width -= 8;
958
+ menuView.height -= 8;
959
+ menuView.center = center;
960
+ GUILayout.BeginArea(menuView);
961
+ _scrollLeftWindow = GUILayout.BeginScrollView(_scrollLeftWindow);
962
+ DrawFilterBuildTargetGUI();
963
+ GUILayout.Space(3);
964
+ var last = DrawHeader("目录", GUILayout.Height(24));
965
+ var rectSearchTree = last;
966
+ rectSearchTree.height = 20;
967
+ rectSearchTree.y = last.yMax;
968
+ var searchTxtArea = rectSearchTree;
969
+ searchTxtArea.width -= 20;
970
+ var clearBtnArea = searchTxtArea;
971
+ clearBtnArea.width = rectSearchTree.xMax - searchTxtArea.xMax;
972
+ clearBtnArea.x = searchTxtArea.xMax;
973
+ clearBtnArea.width -= 2;
974
+ clearBtnArea.x += 1;
975
+ if (_folderTree != null)
976
+ {
977
+ GUI.SetNextControlName(CONTROL_FOLDER_SEARCH_BAR);
978
+ _folderTree.searchString = GUI.TextArea(searchTxtArea, _folderTree.searchString);
979
+ if (GUI.GetNameOfFocusedControl() == CONTROL_FOLDER_SEARCH_BAR)
980
+ {
981
+ EditorGUI.DrawRect(searchTxtArea, Color.blue * 0.4f);
982
+ }
983
+
984
+ if (GUI.Button(clearBtnArea, "×"))
985
+ {
986
+ _folderTree.searchString = string.Empty;
987
+ GUI.FocusControl("");
988
+ }
989
+
990
+ if (string.IsNullOrEmpty(_folderTree.searchString) && GUI.GetNameOfFocusedControl() !=
991
+ CONTROL_FOLDER_SEARCH_BAR)
992
+ {
993
+ GUI.Label(searchTxtArea, "搜索...", Styles.SearchTips);
994
+ }
995
+ }
996
+
997
+ var rectFolderTree = menuView;
998
+ rectFolderTree.y = rectSearchTree.yMax;
999
+ rectFolderTree.y += 2;
1000
+ rectFolderTree.height = menuView.yMax - rectFolderTree.y;
1001
+ rectFolderTree.width += 4;
1002
+ rectFolderTree.x -= 4;
1003
+ if (_folderTree != null)
1004
+ {
1005
+ _folderTree.OnGUI(rectFolderTree);
1006
+ }
1007
+
1008
+ _searchFolderArea = rectSearchTree;
1009
+ _searchFolderArea.position += menuView.position;
1010
+ //目录
1011
+ // DrawFolderTree();
1012
+ GUILayout.EndScrollView();
1013
+ GUILayout.EndArea();
1014
+ }
1015
+
1016
+ private void DrawFilterBuildTargetGUI()
1017
+ {
1018
+ var rect = DrawHeader("所选平台:", GUILayout.Height(26));
1019
+ var btnPopUp = CreateRightTopRect(rect, rect.width - 80, 4);
1020
+ if (!FILTER_BUILD_TARGET.Contains(_filterBuildTarget))
1021
+ {
1022
+ SelectBuildTarget(FILTER_BUILD_TARGET.First());
1023
+ }
1024
+
1025
+ var btnTxt = _filterBuildTarget.ToString();
1026
+ if (GUI.Button(btnPopUp, btnTxt, "PopUp"))
1027
+ {
1028
+ var menu = new GenericMenu();
1029
+ foreach (var buildTarget in FILTER_BUILD_TARGET)
1030
+ {
1031
+ menu.AddItem(new GUIContent(buildTarget.ToString()), false, () =>
1032
+ {
1033
+ _filterBuildTarget = buildTarget;
1034
+ //重置选择
1035
+ EditorUserBuildSettings.selectedBuildTargetGroup =
1036
+ BuildPipeline.GetBuildTargetGroup(buildTarget);
1037
+ });
1038
+ }
1039
+
1040
+ menu.ShowAsContext();
1041
+ }
1042
+ }
1043
+
1044
+ private void SelectBuildTarget(BuildTarget target)
1045
+ {
1046
+ _filterBuildTarget = target;
1047
+ ClearSortCache();
1048
+ OnFilterChanged?.Invoke();
1049
+ }
1050
+
1051
+ //快速过滤工具栏
1052
+ private void DrawFastFilterToolBar()
1053
+ {
1054
+ var rect = DrawHeader("过滤器", GUILayout.Height(24));
1055
+ var rectBtnFlag = CreateRightTopRect(rect, 60, 2);
1056
+ var txt = _filterFlag ? "收起▲" : "展开▼";
1057
+ if (GUI.Button(rectBtnFlag, txt))
1058
+ {
1059
+ _filterFlag = !_filterFlag;
1060
+ }
1061
+
1062
+ if (_filterFlag)
1063
+ {
1064
+ GUILayout.Space(3);
1065
+ GUILayout.BeginHorizontal();
1066
+ GUILayout.Label("快速过滤:", GUILayout.Width(90));
1067
+ if (GUILayout.Button("所有", GUILayout.Width(100)))
1068
+ {
1069
+ _filterTextureType = new HashSet<TextureImporterType>(FILTER_TEXTURE_TYPE);
1070
+ _filterShapeType = new HashSet<TextureImporterShape>(FILTER_SHAPE_TYPE);
1071
+ ClearSortCache();
1072
+ OnFilterChanged?.Invoke();
1073
+ }
1074
+
1075
+ if (GUILayout.Button("Default(2D)", GUILayout.Width(100)))
1076
+ {
1077
+ _filterTextureType = new HashSet<TextureImporterType>(new[] { TextureImporterType.Default });
1078
+ _filterShapeType = new HashSet<TextureImporterShape>(new[] { TextureImporterShape.Texture2D });
1079
+ ClearSortCache();
1080
+ OnFilterChanged?.Invoke();
1081
+ }
1082
+
1083
+ if (GUILayout.Button("Sprite(2D)", GUILayout.Width(100)))
1084
+ {
1085
+ _filterTextureType = new HashSet<TextureImporterType>(new[] { TextureImporterType.Sprite });
1086
+ _filterShapeType = new HashSet<TextureImporterShape>(new[] { TextureImporterShape.Texture2D });
1087
+ ClearSortCache();
1088
+ OnFilterChanged?.Invoke();
1089
+ }
1090
+
1091
+ GUILayout.EndHorizontal();
1092
+ }
1093
+ }
1094
+
1095
+ //过滤Texture Type
1096
+ private void DrawFilterTextureImporterTypeGUI()
1097
+ {
1098
+ if (_filterFlag)
1099
+ {
1100
+ GUILayout.Space(3);
1101
+ GUILayout.BeginHorizontal();
1102
+ GUILayout.Label("Texture Type:", GUILayout.Width(90));
1103
+ if (GUILayout.Button("全选", GUILayout.Width(50)))
1104
+ {
1105
+ SelectAllFilterTextureType();
1106
+ }
1107
+
1108
+ if (GUILayout.Button("全不选", GUILayout.Width(50)))
1109
+ {
1110
+ ClearAllFilterTextureType();
1111
+ }
1112
+
1113
+ foreach (var element in FILTER_TEXTURE_TYPE)
1114
+ {
1115
+ var isOn = _filterTextureType.Contains(element);
1116
+ var tog = isOn;
1117
+ var txt = element.ToString();
1118
+ tog = GUILayout.Toggle(tog, txt, Styles.ToggleFlex);
1119
+ if (isOn != tog)
1120
+ {
1121
+ if (tog)
1122
+ {
1123
+ AddFilterTextureType(element);
1124
+ }
1125
+ else
1126
+ {
1127
+ RemoveFilterTextureType(element);
1128
+ }
1129
+ }
1130
+ }
1131
+
1132
+ GUILayout.EndHorizontal();
1133
+ }
1134
+ }
1135
+
1136
+ private void AddFilterTextureType(TextureImporterType type)
1137
+ {
1138
+ _filterTextureType.Add(type);
1139
+ ClearSortCache();
1140
+ //更新
1141
+ OnFilterChanged?.Invoke();
1142
+ }
1143
+
1144
+ private void RemoveFilterTextureType(TextureImporterType type)
1145
+ {
1146
+ _filterTextureType.Remove(type);
1147
+ ClearSortCache();
1148
+ OnFilterChanged?.Invoke();
1149
+ }
1150
+
1151
+ private void SelectAllFilterTextureType()
1152
+ {
1153
+ _filterTextureType = new HashSet<TextureImporterType>(FILTER_TEXTURE_TYPE);
1154
+ ClearSortCache();
1155
+ OnFilterChanged?.Invoke();
1156
+ }
1157
+
1158
+ private void ClearAllFilterTextureType()
1159
+ {
1160
+ _filterTextureType = new HashSet<TextureImporterType>();
1161
+ ClearSortCache();
1162
+ OnFilterChanged?.Invoke();
1163
+ }
1164
+
1165
+ //过滤Texture Shape
1166
+ private void DrawFilterTextureImporterShapeGUI()
1167
+ {
1168
+ if (_filterFlag)
1169
+ {
1170
+ GUILayout.Space(3);
1171
+ GUILayout.BeginHorizontal();
1172
+ GUILayout.Label("Texture Shape:", GUILayout.Width(90));
1173
+ if (GUILayout.Button("全选", GUILayout.Width(50)))
1174
+ {
1175
+ SelectAllFilterTextureShape();
1176
+ }
1177
+
1178
+ if (GUILayout.Button("全不选", GUILayout.Width(50)))
1179
+ {
1180
+ ClearAllFilterTextureShape();
1181
+ }
1182
+
1183
+ foreach (var element in FILTER_SHAPE_TYPE)
1184
+ {
1185
+ var isOn = _filterShapeType.Contains(element);
1186
+ var tog = isOn;
1187
+ tog = GUILayout.Toggle(tog, element.ToString(), Styles.ToggleFlex);
1188
+ if (isOn != tog)
1189
+ {
1190
+ if (tog)
1191
+ {
1192
+ AddFilterTextureShape(element);
1193
+ }
1194
+ else
1195
+ {
1196
+ RemoveFilterTextureShape(element);
1197
+ }
1198
+ }
1199
+ }
1200
+
1201
+ GUILayout.EndHorizontal();
1202
+ }
1203
+ }
1204
+
1205
+ private void SelectAllFilterTextureShape()
1206
+ {
1207
+ _filterShapeType = new HashSet<TextureImporterShape>(FILTER_SHAPE_TYPE);
1208
+ ClearSortCache();
1209
+ OnFilterChanged?.Invoke();
1210
+ }
1211
+
1212
+ private void ClearAllFilterTextureShape()
1213
+ {
1214
+ _filterShapeType = new HashSet<TextureImporterShape>();
1215
+ ClearSortCache();
1216
+ OnFilterChanged?.Invoke();
1217
+ }
1218
+
1219
+ private void AddFilterTextureShape(TextureImporterShape shape)
1220
+ {
1221
+ _filterShapeType.Add(shape);
1222
+ ClearSortCache();
1223
+ OnFilterChanged?.Invoke();
1224
+ }
1225
+
1226
+ private void RemoveFilterTextureShape(TextureImporterShape shape)
1227
+ {
1228
+ _filterShapeType.Remove(shape);
1229
+ ClearSortCache();
1230
+ OnFilterChanged?.Invoke();
1231
+ }
1232
+
1233
+ #endregion
1234
+
1235
+ #region 中心GUI
1236
+
1237
+ //过滤器GUI
1238
+ private void DrawFilterGUI(Rect view)
1239
+ {
1240
+ GUILayout.BeginArea(view);
1241
+ DrawFastFilterToolBar();
1242
+ DrawFilterTextureImporterTypeGUI();
1243
+ DrawFilterTextureImporterShapeGUI();
1244
+ GUILayout.EndArea();
1245
+ }
1246
+
1247
+ private void DrawCenterGUI(Rect view)
1248
+ {
1249
+ var rect = new Rect(0, 0, view.width, view.height);
1250
+ var rectFilter = view;
1251
+ rectFilter.height = 100;
1252
+ if (!_filterFlag)
1253
+ {
1254
+ rectFilter.height = 24;
1255
+ }
1256
+
1257
+ DrawFilterGUI(rectFilter);
1258
+
1259
+
1260
+ //搜索框
1261
+ var rectSearchBar = rectFilter;
1262
+ rectSearchBar.height = 22;
1263
+ rectSearchBar.y = rectFilter.yMax;
1264
+ var center = rectSearchBar.center;
1265
+ rectSearchBar.height -= 4;
1266
+ rectSearchBar.width -= 4;
1267
+ rectSearchBar.center = center;
1268
+ DrawSearchBarGUI(rectSearchBar);
1269
+ var rectItemWindowView = rectSearchBar;
1270
+ rectItemWindowView.y = rectSearchBar.yMax;
1271
+ rectItemWindowView.y += 2;
1272
+ rectItemWindowView.height = view.yMax - rectItemWindowView.y;
1273
+ rectItemWindowView.height -= 24;
1274
+ DrawItemWindow(rectItemWindowView);
1275
+
1276
+ var rectCenterBottom = rectItemWindowView;
1277
+ rectCenterBottom.y = rectItemWindowView.yMax;
1278
+ rectCenterBottom.height = 24;
1279
+ DrawInfoGUI(rectCenterBottom);
1280
+ _searchBarArea = rectSearchBar;
1281
+ }
1282
+
1283
+ private void DrawSearchBarGUI(Rect view)
1284
+ {
1285
+ GUI.SetNextControlName(CONTROL_NAME_SEARCH_BAR);
1286
+ var temSearch = _searchTxt;
1287
+
1288
+ _searchTxt = GUI.TextArea(view, _searchTxt);
1289
+ if (GUI.GetNameOfFocusedControl() == CONTROL_NAME_SEARCH_BAR)
1290
+ {
1291
+ EditorGUI.DrawRect(view, Color.blue * 0.4f);
1292
+ }
1293
+
1294
+ if (string.IsNullOrEmpty(_searchTxt) && GUI.GetNameOfFocusedControl() != CONTROL_NAME_SEARCH_BAR)
1295
+ {
1296
+ GUI.Label(view, "搜索...", Styles.SearchTips);
1297
+ }
1298
+
1299
+ if (temSearch != _searchTxt)
1300
+ {
1301
+ OnFilterChanged?.Invoke();
1302
+ }
1303
+ }
1304
+
1305
+ private void DrawItemWindow(Rect view)
1306
+ {
1307
+ var windowWidth = CalculateItemWindowWidth();
1308
+ var windowHeight = CalculateItemWindowHeight();
1309
+ GUILayout.BeginArea(view);
1310
+ var rect = new Rect(0, 0, view.width, view.height);
1311
+ var rectViewPort = rect;
1312
+ var rectScrollView = new Rect(0, 0, windowWidth, windowHeight);
1313
+ //绘制
1314
+ _itemWindowScroll = GUI.BeginScrollView(rectViewPort, _itemWindowScroll, rectScrollView);
1315
+ DrawItems(view, _itemWindowScroll.y, rectViewPort, rectScrollView);
1316
+ DrawPropertyTabBar(_itemWindowScroll.y, rectViewPort, rectScrollView);
1317
+ //绘制属性标题
1318
+ GUI.EndScrollView();
1319
+ GUILayout.EndArea();
1320
+ _itemsArea = view;
1321
+ _itemsArea.y += PROPERTY_TITLE_BAR_HEIGHT;
1322
+ var h = windowHeight - PROPERTY_TITLE_BAR_HEIGHT - 16;
1323
+ var h2 = rectViewPort.height - PROPERTY_TITLE_BAR_HEIGHT - 16;
1324
+ _itemsArea.height = Mathf.Min(h, h2);
1325
+ _itemsArea.width -= 16;
1326
+ }
1327
+
1328
+
1329
+ private void DrawInfoGUI(Rect view)
1330
+ {
1331
+ EditorGUI.DrawRect(view, Color.black);
1332
+ if (!string.IsNullOrEmpty(_lastSelectGuid))
1333
+ {
1334
+ var importer = GetImporter(_lastSelectGuid);
1335
+ GUI.TextArea(view, importer.assetPath, Styles.WhiteTitleLabel);
1336
+ }
1337
+ }
1338
+
1339
+ //修正items视窗
1340
+ private void FitItemWindowScrollPosition(string guid, int offsetIndex)
1341
+ {
1342
+ var index = _matchItems.IndexOf(guid);
1343
+ var finalIndex = index + offsetIndex;
1344
+ if (index >= 0 && index < _matchItems.Count && finalIndex >= 0 && finalIndex <= _matchItems.Count)
1345
+ {
1346
+ if (_itemsRects.TryGetValue(guid, out var rect))
1347
+ {
1348
+ var nextRect = rect;
1349
+ nextRect.y += ITEM_HEIGHT * offsetIndex;
1350
+ if (nextRect.yMin < _itemsArea.yMin)
1351
+ {
1352
+ _itemWindowScroll =
1353
+ new Vector2(_itemWindowScroll.x,
1354
+ _itemWindowScroll.y - ITEM_HEIGHT * Mathf.Abs(offsetIndex));
1355
+ }
1356
+
1357
+ if (nextRect.yMax > _itemsArea.yMax)
1358
+ {
1359
+ _itemWindowScroll =
1360
+ new Vector2(_itemWindowScroll.x,
1361
+ _itemWindowScroll.y + ITEM_HEIGHT * Mathf.Abs(offsetIndex));
1362
+ }
1363
+ }
1364
+ else
1365
+ {
1366
+ //如果不在范围内
1367
+ _itemWindowScroll =
1368
+ new Vector2(_itemWindowScroll.x,
1369
+ finalIndex * ITEM_HEIGHT - ITEM_HEIGHT);
1370
+ }
1371
+ }
1372
+ }
1373
+
1374
+ private void DrawPropertyTabBar(float offsetY, Rect viewPort, Rect scrollView)
1375
+ {
1376
+ var rect = new Rect(0, offsetY, scrollView.width, PROPERTY_TITLE_BAR_HEIGHT);
1377
+ var bottom = rect;
1378
+ bottom.width = Mathf.Max(viewPort.width, scrollView.width);
1379
+ EditorGUI.DrawRect(bottom, new Color(0.22f, 0.22f, 0.22f, 1f));
1380
+ var offsetX = (float)ITEM_PADDING.left;
1381
+ foreach (var pair in PropertyTabMap)
1382
+ {
1383
+ var key = pair.Key;
1384
+ var value = pair.Value;
1385
+ var itemRect = rect;
1386
+ itemRect.width = value.LabelWidth;
1387
+ itemRect.width -= 1;
1388
+ itemRect.x = offsetX;
1389
+ EditorGUI.DrawRect(itemRect, Color.black);
1390
+ GUI.Label(itemRect, key.ToString(), Styles.WhiteTitleLabel);
1391
+ if (value.CanSort)
1392
+ {
1393
+ var rectSortBtn = itemRect;
1394
+ rectSortBtn.height -= 4;
1395
+ rectSortBtn.center = itemRect.center;
1396
+ rectSortBtn.width = rectSortBtn.height;
1397
+ rectSortBtn.x = itemRect.xMax - rectSortBtn.width;
1398
+ rectSortBtn.x -= 2;
1399
+ if (GUI.Button(rectSortBtn, "▼"))
1400
+ {
1401
+ SortBy(key);
1402
+ }
1403
+
1404
+ if (value.EnumType == PropertyTab.Name)
1405
+ {
1406
+ var btnDefaultSort = rectSortBtn;
1407
+ btnDefaultSort.width = 60;
1408
+ btnDefaultSort.x = rectSortBtn.xMin - btnDefaultSort.width;
1409
+ btnDefaultSort.x -= 2;
1410
+ if (GUI.Button(btnDefaultSort, "默认排序"))
1411
+ {
1412
+ SortByDefault();
1413
+ }
1414
+ }
1415
+ }
1416
+
1417
+
1418
+ offsetX += value.LabelWidth;
1419
+ }
1420
+ }
1421
+
1422
+ private void DrawItems(Rect area, float offsetY, Rect viewPort, Rect scrollView)
1423
+ {
1424
+ _itemsRects.Clear();
1425
+ //计算绘制的元素索引范围
1426
+ var startY = offsetY - ITEM_PADDING.top;
1427
+ var endY = startY + viewPort.height;
1428
+ startY -= ITEM_EDGE_RANGE;
1429
+ endY += ITEM_EDGE_RANGE;
1430
+ //元素数量
1431
+ var count = Mathf.CeilToInt((endY - startY) / ITEM_HEIGHT);
1432
+ var startIndex = (int)(startY / ITEM_HEIGHT);
1433
+ var endIndex = startIndex + count;
1434
+ //截取有效范围
1435
+ for (int i = startIndex; i <= endIndex; i++)
1436
+ {
1437
+ var rect = CalculateItemRect(i, scrollView);
1438
+ var dark = i % 2 == 0;
1439
+ EditorGUI.DrawRect(rect, dark ? Color.black * 0.1f : Color.white * 0.1f);
1440
+ if (!(i >= 0 && i < _matchItems.Count))
1441
+ {
1442
+ continue;
1443
+ }
1444
+
1445
+ var no = i + 1;
1446
+ var guid = _matchItems[i];
1447
+ var cacheRect = rect;
1448
+ cacheRect.position += area.position;
1449
+ cacheRect.position -= Vector2.up * offsetY;
1450
+ _itemsRects[guid] = cacheRect;
1451
+
1452
+ var importer = GetImporter(guid);
1453
+ var info = GetInfo(guid);
1454
+ var settings = info.Settings;
1455
+ var source = info.SourceInfo;
1456
+
1457
+ if (_selectGuids.Contains(guid))
1458
+ {
1459
+ EditorGUI.DrawRect(rect, Styles.IsProSKin ? Color.cyan * 0.5f : Color.blue * 0.3f);
1460
+ }
1461
+
1462
+ if (_hoverSelect.Contains(guid))
1463
+ {
1464
+ EditorGUI.DrawRect(rect, Color.green * 0.3f);
1465
+ }
1466
+
1467
+ //信息-序号
1468
+ var rectNo = rect;
1469
+ rectNo.width = GetPropertyWidth(PropertyTab.NO);
1470
+ GUI.Label(rectNo, no.ToString(), Styles.SmallLabel);
1471
+
1472
+ //绘制信息-Name
1473
+ var rectName = rectNo;
1474
+ rectName.x += rectName.width;
1475
+ rectName.width = GetPropertyWidth(PropertyTab.Name);
1476
+ var rectPreviewTex = rectName;
1477
+ rectPreviewTex.width = rectPreviewTex.height;
1478
+ GUI.DrawTexture(rectPreviewTex, info.Texture, ScaleMode.ScaleToFit);
1479
+ rectName.x = rectPreviewTex.xMax;
1480
+ rectName.width -= rectPreviewTex.width;
1481
+ GUI.Label(rectName, info.Name);
1482
+
1483
+ //信息-Override
1484
+ var rectOverride = rectName;
1485
+ rectOverride.x += rectOverride.width;
1486
+ rectOverride.width = GetPropertyWidth(PropertyTab.Override);
1487
+ GUI.Label(rectOverride, settings.overridden ? "开启" : "-", Styles.MiddleLabel);
1488
+
1489
+ //信息-Format
1490
+ var temEnable = GUI.enabled;
1491
+ GUI.enabled = settings.overridden;
1492
+ var rectFormat = rectOverride;
1493
+ rectFormat.x += rectFormat.width;
1494
+ rectFormat.width = GetPropertyWidth(PropertyTab.Format);
1495
+ var formatTxt = settings.overridden
1496
+ ? GetFormatName(settings.format)
1497
+ : GetFormatName(info.DefaultFormat);
1498
+ GUI.Label(rectFormat, formatTxt);
1499
+ GUI.enabled = temEnable;
1500
+
1501
+
1502
+ //信息-MaxSize
1503
+ var rectMaxSize = rectFormat;
1504
+ rectMaxSize.x += rectMaxSize.width;
1505
+ rectMaxSize.width = GetPropertyWidth(PropertyTab.MaxSize);
1506
+ var maxSizeTxt = settings.overridden
1507
+ ? settings.maxTextureSize.ToString()
1508
+ : importer.GetDefaultPlatformTextureSettings().maxTextureSize.ToString();
1509
+ GUI.Label(rectMaxSize, maxSizeTxt, Styles.MiddleLabel);
1510
+
1511
+ //信息-原始大小
1512
+ var rectSourceSize = rectMaxSize;
1513
+ rectSourceSize.x += rectSourceSize.width;
1514
+ rectSourceSize.width = GetPropertyWidth(PropertyTab.SourceSize);
1515
+
1516
+ GUI.Label(rectSourceSize, source != null ? $"{source.width} × {source.height}" : "---",
1517
+ Styles.MiddleLabel);
1518
+
1519
+ //信息-MipMap
1520
+ var rectMipMap = rectSourceSize;
1521
+ rectMipMap.x += rectMipMap.width;
1522
+ rectMipMap.width = GetPropertyWidth(PropertyTab.MipMap);
1523
+ GUI.Label(rectMipMap, importer.mipmapEnabled ? "开启" : "-", Styles.MiddleLabel);
1524
+
1525
+ //信息-npotscale
1526
+ var rectNpot = rectMipMap;
1527
+ rectNpot.x += rectNpot.width;
1528
+ rectNpot.width = GetPropertyWidth(PropertyTab.NpotScale);
1529
+ GUI.Label(rectNpot, importer.npotScale.ToString());
1530
+
1531
+ //信息-type
1532
+ var rectType = rectNpot;
1533
+ rectType.x += rectType.width;
1534
+ rectType.width = GetPropertyWidth(PropertyTab.Type);
1535
+ GUI.Label(rectType, $"{importer.textureType}({importer.textureShape})");
1536
+
1537
+ //信息-path
1538
+ var rectPath = rectType;
1539
+ rectPath.x += rectPath.width;
1540
+ rectPath.width = GetPropertyWidth(PropertyTab.Path);
1541
+ GUI.Label(rectPath, importer.assetPath);
1542
+ }
1543
+ }
1544
+
1545
+ private Rect CalculateItemRect(int index, Rect scrollView)
1546
+ {
1547
+ var x = ITEM_PADDING.left;
1548
+ var y = index * ITEM_HEIGHT + ITEM_PADDING.top;
1549
+ return new Rect(x, y, scrollView.width, ITEM_HEIGHT);
1550
+ }
1551
+
1552
+ private float GetPropertyWidth(PropertyTab propertyTab)
1553
+ {
1554
+ return PropertyTabMap[propertyTab].LabelWidth;
1555
+ }
1556
+
1557
+ //item window width
1558
+ private float CalculateItemWindowWidth()
1559
+ {
1560
+ var result = 0f;
1561
+ result += ITEM_PADDING.horizontal;
1562
+ foreach (var value in PropertyTabMap.Values)
1563
+ {
1564
+ result += value.LabelWidth;
1565
+ }
1566
+
1567
+ return result;
1568
+ }
1569
+
1570
+ //item window height
1571
+ private float CalculateItemWindowHeight()
1572
+ {
1573
+ return ITEM_PADDING.vertical + _matchItems.Count * ITEM_HEIGHT;
1574
+ }
1575
+
1576
+ //图片信息
1577
+ private static TextureInfo GetInfo(string guid)
1578
+ {
1579
+ if (!_infos.ContainsKey(guid))
1580
+ {
1581
+ var importer = GetImporter(guid);
1582
+ var source = GetSourceTextureInformation(importer);
1583
+ _infos[guid] = new TextureInfo()
1584
+ {
1585
+ Guid = guid,
1586
+ SourceInfo = source,
1587
+ };
1588
+ }
1589
+
1590
+ return _infos[guid];
1591
+ }
1592
+
1593
+ private static TextureImporter GetImporter(string guid)
1594
+ {
1595
+ return _importers[guid];
1596
+ }
1597
+
1598
+ private void Select(string[] guids)
1599
+ {
1600
+ _selectGuids = new HashSet<string>(guids);
1601
+ _lastSelectGuid = guids.Last();
1602
+ OnSelectChanged?.Invoke();
1603
+ }
1604
+
1605
+ private void Select(string guid, SelectMode mode)
1606
+ {
1607
+ switch (mode)
1608
+ {
1609
+ case SelectMode.Single:
1610
+ {
1611
+ _selectGuids.Clear();
1612
+ _selectGuids.Add(guid);
1613
+ _lastSelectGuid = guid;
1614
+ OnSelectChanged?.Invoke();
1615
+ }
1616
+
1617
+ break;
1618
+ case SelectMode.Shift:
1619
+ {
1620
+ var startIndex = _matchItems.IndexOf(_lastSelectGuid);
1621
+ var endIndex = _matchItems.IndexOf(guid);
1622
+ if (startIndex >= 0 && endIndex >= 0)
1623
+ {
1624
+ var min = Mathf.Min(startIndex, endIndex);
1625
+ var max = Mathf.Max(startIndex, endIndex);
1626
+ _selectGuids.Clear();
1627
+ for (int i = min; i <= max && i < _matchItems.Count; i++)
1628
+ {
1629
+ _selectGuids.Add(_matchItems[i]);
1630
+ }
1631
+ }
1632
+
1633
+ _lastSelectGuid = guid;
1634
+ OnSelectChanged?.Invoke();
1635
+ }
1636
+ break;
1637
+ case SelectMode.Ctrl:
1638
+ {
1639
+ if (_selectGuids.Contains(guid))
1640
+ {
1641
+ _selectGuids.Remove(guid);
1642
+ }
1643
+ else
1644
+ {
1645
+ _selectGuids.Add(guid);
1646
+ }
1647
+
1648
+ _lastSelectGuid = guid;
1649
+ OnSelectChanged?.Invoke();
1650
+ }
1651
+ break;
1652
+ }
1653
+ }
1654
+
1655
+
1656
+ private bool SelectOffset(int offset)
1657
+ {
1658
+ var index = GetIndexOf(_lastSelectGuid) + offset;
1659
+ if (index >= 0 && index < _matchItems.Count)
1660
+ {
1661
+ var guid = _matchItems[index];
1662
+ FitItemWindowScrollPosition(_lastSelectGuid, offset);
1663
+ Select(guid, SelectMode.Single);
1664
+ return true;
1665
+ }
1666
+ else
1667
+ {
1668
+ if (_selectGuids.Contains(_lastSelectGuid))
1669
+ {
1670
+ FitItemWindowScrollPosition(_lastSelectGuid, 0);
1671
+ }
1672
+ }
1673
+
1674
+ return false;
1675
+ }
1676
+
1677
+ private bool ShiftSelectOffset(int offset)
1678
+ {
1679
+ var cacheSelect = _lastSelectGuid;
1680
+ var index = GetIndexOf(cacheSelect) + offset;
1681
+ if (index >= 0 && index < _matchItems.Count)
1682
+ {
1683
+ var guid = _matchItems[index];
1684
+ if (_selectGuids.Contains(guid))
1685
+ {
1686
+ //存在,判断是否剔除
1687
+ _selectGuids.Remove(cacheSelect);
1688
+ }
1689
+ else
1690
+ {
1691
+ //不存在
1692
+ _selectGuids.Add(guid);
1693
+ }
1694
+
1695
+ _lastSelectGuid = guid;
1696
+ OnSelectChanged?.Invoke();
1697
+ FitItemWindowScrollPosition(cacheSelect, offset);
1698
+ return true;
1699
+ }
1700
+ else
1701
+ {
1702
+ if (_selectGuids.Contains(_lastSelectGuid))
1703
+ {
1704
+ FitItemWindowScrollPosition(_lastSelectGuid, 0);
1705
+ }
1706
+ }
1707
+
1708
+ return false;
1709
+ }
1710
+
1711
+
1712
+ private int GetIndexOf(string guid)
1713
+ {
1714
+ return _matchItems.IndexOf(guid);
1715
+ }
1716
+
1717
+ #endregion
1718
+
1719
+ #region 右侧GUI
1720
+
1721
+ private void DrawRightGUI(Rect view)
1722
+ {
1723
+ var rectTitle = view;
1724
+ rectTitle.height = 22;
1725
+ GUI.Label(rectTitle, "Inspector", Styles.TitleLabel);
1726
+ var rect = new Rect(0, 0, view.width, view.height);
1727
+ var rectInspector = rectTitle;
1728
+ rectInspector.y = rectTitle.yMax;
1729
+ rectInspector.height = rect.yMax - rectInspector.y;
1730
+ var center = rectInspector.center;
1731
+ rectInspector.width -= 8;
1732
+ rectInspector.height -= 8;
1733
+ rectInspector.center = center;
1734
+ rectInspector.height -= PREVIEW_HEIGHT;
1735
+ var hover = false;
1736
+ if (_multipleInspector)
1737
+ {
1738
+ //显示按钮,重复选实例
1739
+ GUILayout.BeginArea(rectInspector);
1740
+ if (_cacheSelectTextures.Count > 0)
1741
+ {
1742
+ var click = GUILayout.Button(new GUIContent($"{_cacheSelectTextures.Count} Texture2D",
1743
+ EditorGUIUtility.IconContent("Texture Icon").image), GUILayout.Height(24));
1744
+ var last = GUILayoutUtility.GetLastRect();
1745
+ if (last.Contains(Event.current.mousePosition))
1746
+ {
1747
+ _hoverSelect = new HashSet<string>(_cacheSelectTextures);
1748
+ Repaint();
1749
+ }
1750
+
1751
+ if (click)
1752
+ {
1753
+ Select(_cacheSelectTextures.ToArray());
1754
+ }
1755
+ }
1756
+
1757
+ if (_cacheSelectCubeMap.Count > 0)
1758
+ {
1759
+ var click = GUILayout.Button(new GUIContent($"{_cacheSelectCubeMap.Count} CubeMap",
1760
+ EditorGUIUtility.IconContent("Cubemap Icon").image), GUILayout.Height(24));
1761
+ var last = GUILayoutUtility.GetLastRect();
1762
+ if (last.Contains(Event.current.mousePosition))
1763
+ {
1764
+ _hoverSelect = new HashSet<string>(_cacheSelectCubeMap);
1765
+ Repaint();
1766
+ }
1767
+
1768
+ if (click)
1769
+ {
1770
+ Select(_cacheSelectCubeMap.ToArray());
1771
+ }
1772
+ }
1773
+
1774
+ GUILayout.EndArea();
1775
+ }
1776
+
1777
+
1778
+ if (!_multipleInspector)
1779
+ {
1780
+ var rectPreview = rectInspector;
1781
+ rectPreview.y = rectInspector.yMax;
1782
+ rectPreview.height = PREVIEW_HEIGHT;
1783
+ if (!_previewGUIFlag)
1784
+ {
1785
+ rectPreview.height = 0;
1786
+ rectPreview.y = view.yMax;
1787
+ }
1788
+
1789
+ var rectGUIView = rectInspector;
1790
+ rectGUIView.height = Mathf.Max(INSPECTOR_VIEW_HEIGHT, rectInspector.height);
1791
+ _scrollInspector = GUI.BeginScrollView(rectInspector, _scrollInspector, rectGUIView, false, false,
1792
+ GUIStyle.none, GUIStyle.none);
1793
+ GUILayout.BeginArea(rectGUIView);
1794
+ var editorError = false;
1795
+
1796
+ if (InspectorEditor != null)
1797
+ {
1798
+ try
1799
+ {
1800
+ InspectorEditor.DrawHeader();
1801
+ InspectorEditor.OnInspectorGUI();
1802
+ }
1803
+ catch (Exception e)
1804
+ {
1805
+ editorError = true;
1806
+ }
1807
+ }
1808
+
1809
+ GUILayout.EndArea();
1810
+
1811
+ GUI.EndScrollView();
1812
+
1813
+ var rectFoldoutPreviewGUI = rectPreview;
1814
+ rectFoldoutPreviewGUI.y -= 22;
1815
+ rectFoldoutPreviewGUI.height += 22;
1816
+ center = rectFoldoutPreviewGUI.center;
1817
+ rectFoldoutPreviewGUI.width += 8;
1818
+ rectFoldoutPreviewGUI.center = center;
1819
+ var rectPreviewGUITitle = rectFoldoutPreviewGUI;
1820
+ rectPreviewGUITitle.height = 22;
1821
+
1822
+
1823
+ var rectBtnClosePreview = rectFoldoutPreviewGUI;
1824
+ rectBtnClosePreview.height = 22;
1825
+ rectBtnClosePreview.height -= 4;
1826
+ rectBtnClosePreview.width = 60;
1827
+ rectBtnClosePreview.x = rectFoldoutPreviewGUI.xMax - rectBtnClosePreview.width;
1828
+ rectBtnClosePreview.y = rectFoldoutPreviewGUI.yMin;
1829
+ rectBtnClosePreview.x -= 2;
1830
+ rectBtnClosePreview.y += 2;
1831
+
1832
+
1833
+ //绘制预览视窗
1834
+ if (InspectorEditor != null)
1835
+ {
1836
+ EditorGUI.DrawRect(rectFoldoutPreviewGUI, Color.black);
1837
+ try
1838
+ {
1839
+ if (_previewGUIFlag)
1840
+ {
1841
+ if (InspectorEditor.HasPreviewGUI())
1842
+ {
1843
+ InspectorEditor.DrawPreview(rectPreview);
1844
+ }
1845
+ }
1846
+ }
1847
+ catch (Exception e)
1848
+ {
1849
+ editorError = true;
1850
+ }
1851
+
1852
+ var txt = _previewGUIFlag ? "收起▼" : "展开▲";
1853
+
1854
+ GUI.Label(rectPreviewGUITitle, "预览视窗", Styles.WhiteTitleLabel);
1855
+ if (GUI.Button(rectBtnClosePreview, txt))
1856
+ {
1857
+ _previewGUIFlag = !_previewGUIFlag;
1858
+ }
1859
+ }
1860
+
1861
+
1862
+ if (editorError)
1863
+ {
1864
+ DestroyImmediate(_inspectorEditor, true);
1865
+ RebuildInspectorEditor();
1866
+ }
1867
+ }
1868
+ }
1869
+
1870
+ #endregion
1871
+
1872
+ #region 排序
1873
+
1874
+ //排序
1875
+ private static void SortBy(PropertyTab propertyTab)
1876
+ {
1877
+ _cacheSortBy = propertyTab;
1878
+ var cache = GetSortState(propertyTab);
1879
+ var state = !cache;
1880
+ SetSortState(propertyTab, state);
1881
+ OnFilterChanged?.Invoke();
1882
+ }
1883
+
1884
+ //按名称排序
1885
+ private static void SortByName(List<string> list, bool state)
1886
+ {
1887
+ list.Sort((a, b) =>
1888
+ {
1889
+ var (ta, tb) = (a, b);
1890
+ if (!state)
1891
+ {
1892
+ (ta, tb) = (b, a);
1893
+ }
1894
+
1895
+ var result = String.Compare(GetInfo(ta).Name, GetInfo(tb).Name, StringComparison.Ordinal);
1896
+ if (result == 0)
1897
+ {
1898
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
1899
+ }
1900
+
1901
+ return result;
1902
+ });
1903
+ }
1904
+
1905
+ //按override排序
1906
+ private static void SortByOverride(List<string> list, bool state)
1907
+ {
1908
+ list.Sort((a, b) =>
1909
+ {
1910
+ var (ta, tb) = (a, b);
1911
+ if (state)
1912
+ {
1913
+ (ta, tb) = (b, a);
1914
+ }
1915
+
1916
+ var infoA = GetInfo(ta);
1917
+ var infoB = GetInfo(tb);
1918
+ var result = infoA.Settings.overridden.CompareTo(infoB.Settings.overridden);
1919
+ if (result == 0)
1920
+ {
1921
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
1922
+ }
1923
+
1924
+ return result;
1925
+ });
1926
+ }
1927
+
1928
+ //按Format排序
1929
+ private static void SortByFormat(List<string> list, bool state)
1930
+ {
1931
+ list.Sort((a, b) =>
1932
+ {
1933
+ var (ta, tb) = (a, b);
1934
+ if (!state)
1935
+ {
1936
+ (ta, tb) = (b, a);
1937
+ }
1938
+
1939
+ var infoA = GetInfo(ta);
1940
+ var infoB = GetInfo(tb);
1941
+ var formatA = infoA.Settings.overridden ? infoA.Settings.format : infoA.DefaultFormat;
1942
+ var formatB = infoB.Settings.overridden ? infoB.Settings.format : infoB.DefaultFormat;
1943
+ var result = formatA.CompareTo(formatB);
1944
+ if (result == 0)
1945
+ {
1946
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
1947
+ }
1948
+
1949
+ return result;
1950
+ });
1951
+ }
1952
+
1953
+ //按MaxSize排序
1954
+ private static void SortByMaxSize(List<string> list, bool state)
1955
+ {
1956
+ list.Sort((a, b) =>
1957
+ {
1958
+ var (ta, tb) = (a, b);
1959
+ if (!state)
1960
+ {
1961
+ (ta, tb) = (b, a);
1962
+ }
1963
+
1964
+ var infoA = GetInfo(ta);
1965
+ var infoB = GetInfo(tb);
1966
+ var importerA = GetImporter(ta);
1967
+ var importerB = GetImporter(tb);
1968
+ var sizeA = infoA.Settings.overridden
1969
+ ? infoA.Settings.maxTextureSize
1970
+ : importerA.GetDefaultPlatformTextureSettings().maxTextureSize;
1971
+ var sizeB = infoB.Settings.overridden
1972
+ ? infoB.Settings.maxTextureSize
1973
+ : importerB.GetDefaultPlatformTextureSettings().maxTextureSize;
1974
+ var result = sizeA.CompareTo(sizeB);
1975
+ if (result == 0)
1976
+ {
1977
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
1978
+ }
1979
+
1980
+ return result;
1981
+ });
1982
+ }
1983
+
1984
+ //按Source排序
1985
+ private static void SortBySourceSize(List<string> list, bool state)
1986
+ {
1987
+ list.Sort((a, b) =>
1988
+ {
1989
+ var (ta, tb) = (a, b);
1990
+ if (!state)
1991
+ {
1992
+ (ta, tb) = (b, a);
1993
+ }
1994
+
1995
+ var infoA = GetInfo(ta);
1996
+ var infoB = GetInfo(tb);
1997
+ var sizeA = infoA.SourceInfo.width * infoA.SourceInfo.height;
1998
+ var sizeB = infoB.SourceInfo.width * infoB.SourceInfo.height;
1999
+ var result = sizeA.CompareTo(sizeB);
2000
+ if (result == 0)
2001
+ {
2002
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
2003
+ }
2004
+
2005
+ return result;
2006
+ });
2007
+ }
2008
+
2009
+ //按mipmap排序
2010
+ private static void SortByMipMap(List<string> list, bool state)
2011
+ {
2012
+ list.Sort((a, b) =>
2013
+ {
2014
+ var (ta, tb) = (a, b);
2015
+ if (state)
2016
+ {
2017
+ (ta, tb) = (b, a);
2018
+ }
2019
+
2020
+ var importerA = GetImporter(ta);
2021
+ var importerB = GetImporter(tb);
2022
+ var result = importerA.mipmapEnabled.CompareTo(importerB.mipmapEnabled);
2023
+ if (result == 0)
2024
+ {
2025
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
2026
+ }
2027
+
2028
+ return result;
2029
+ });
2030
+ }
2031
+
2032
+ //按NpotScale排序
2033
+ private static void SortByNpotScale(List<string> list, bool state)
2034
+ {
2035
+ list.Sort((a, b) =>
2036
+ {
2037
+ var (ta, tb) = (a, b);
2038
+ if (!state)
2039
+ {
2040
+ (ta, tb) = (b, a);
2041
+ }
2042
+
2043
+ var importerA = GetImporter(ta);
2044
+ var importerB = GetImporter(tb);
2045
+ var result = importerA.npotScale.CompareTo(importerB.npotScale);
2046
+ if (result == 0)
2047
+ {
2048
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
2049
+ }
2050
+
2051
+ return result;
2052
+ });
2053
+ }
2054
+
2055
+ //按TextureType排序
2056
+ private static void SortByTextureType(List<string> list, bool state)
2057
+ {
2058
+ list.Sort((a, b) =>
2059
+ {
2060
+ var (ta, tb) = (a, b);
2061
+ if (!state)
2062
+ {
2063
+ (ta, tb) = (b, a);
2064
+ }
2065
+
2066
+ var importerA = GetImporter(ta);
2067
+ var importerB = GetImporter(tb);
2068
+ var result = importerA.textureType.CompareTo(importerB.textureType);
2069
+ if (result == 0)
2070
+ {
2071
+ result = importerA.textureShape.CompareTo(importerB.textureShape);
2072
+ }
2073
+
2074
+ if (result == 0)
2075
+ {
2076
+ result = GetTextureOrder(a).CompareTo(GetTextureOrder(b));
2077
+ }
2078
+
2079
+ return result;
2080
+ });
2081
+ }
2082
+
2083
+ //按Path排序
2084
+ private static void SortByPath(List<string> list, bool state)
2085
+ {
2086
+ list.Sort((a, b) =>
2087
+ {
2088
+ var (ta, tb) = (a, b);
2089
+ if (!state)
2090
+ {
2091
+ (ta, tb) = (b, a);
2092
+ }
2093
+
2094
+ return GetTextureOrder(ta).CompareTo(GetTextureOrder(tb));
2095
+ });
2096
+ }
2097
+
2098
+ //默认排序
2099
+ private void SortByDefault()
2100
+ {
2101
+ _matchItems.Sort((a, b) => { return GetTextureOrder(a).CompareTo(GetTextureOrder(b)); });
2102
+ }
2103
+
2104
+ #endregion
2105
+
2106
+ #region 事件处理
2107
+
2108
+ private void HandleEvent()
2109
+ {
2110
+ //键盘点击
2111
+ if (Event.current.type == EventType.KeyDown)
2112
+ {
2113
+ switch (Event.current.keyCode)
2114
+ {
2115
+ case KeyCode.Escape: //点击ESC
2116
+ if (GUI.GetNameOfFocusedControl() == CONTROL_NAME_SEARCH_BAR)
2117
+ {
2118
+ GUI.FocusControl("");
2119
+ var temSearch = _searchTxt;
2120
+ _searchTxt = "";
2121
+ if (temSearch != _searchTxt)
2122
+ {
2123
+ OnFilterChanged?.Invoke();
2124
+ }
2125
+
2126
+ Event.current.Use();
2127
+ }
2128
+
2129
+ if (GUI.GetNameOfFocusedControl() == CONTROL_FOLDER_SEARCH_BAR)
2130
+ {
2131
+ GUI.FocusControl("");
2132
+ if (_folderTree != null)
2133
+ {
2134
+ _folderTree.searchString = "";
2135
+ }
2136
+
2137
+ Event.current.Use();
2138
+ }
2139
+
2140
+
2141
+ break;
2142
+ case KeyCode.Return:
2143
+ case KeyCode.KeypadEnter:
2144
+ {
2145
+ //点击回车
2146
+ if (GUI.GetNameOfFocusedControl() == CONTROL_NAME_SEARCH_BAR)
2147
+ {
2148
+ GUI.FocusControl("");
2149
+ Event.current.Use();
2150
+ }
2151
+
2152
+
2153
+ if (GUI.GetNameOfFocusedControl() == CONTROL_FOLDER_SEARCH_BAR)
2154
+ {
2155
+ GUI.FocusControl("");
2156
+ Event.current.Use();
2157
+ }
2158
+ }
2159
+ break;
2160
+ case KeyCode.F:
2161
+ {
2162
+ if (Event.current.modifiers == EventModifiers.Control)
2163
+ {
2164
+ switch (_lastLayoutScene)
2165
+ {
2166
+ case LayoutScene.Left:
2167
+ {
2168
+ GUI.FocusControl(CONTROL_FOLDER_SEARCH_BAR);
2169
+
2170
+ if (_folderTree != null && !string.IsNullOrEmpty(_folderTree.searchString) &&
2171
+ _folderTree.searchString.Length > 0)
2172
+ {
2173
+ TextEditor te =
2174
+ (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor),
2175
+ GUIUtility.keyboardControl);
2176
+ te.OnFocus();
2177
+ if (te != null)
2178
+ {
2179
+ te.cursorIndex = 0; //CursorStartPosition;
2180
+ te.selectIndex =
2181
+ _folderTree.searchString.Length; //cursor selected end position…
2182
+ }
2183
+ }
2184
+ }
2185
+ break;
2186
+ case LayoutScene.Center:
2187
+ {
2188
+ GUI.FocusControl(CONTROL_NAME_SEARCH_BAR);
2189
+ if (!string.IsNullOrEmpty(_searchTxt) && _searchTxt.Length > 0)
2190
+ {
2191
+ TextEditor te =
2192
+ (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor),
2193
+ GUIUtility.keyboardControl);
2194
+ te.OnFocus();
2195
+ if (te != null)
2196
+ {
2197
+ te.cursorIndex = 0; //CursorStartPosition;
2198
+ te.selectIndex = _searchTxt.Length; //cursor selected end position…
2199
+ }
2200
+ }
2201
+ }
2202
+ break;
2203
+ }
2204
+
2205
+
2206
+ Event.current.Use();
2207
+ }
2208
+ }
2209
+ break;
2210
+ case KeyCode.UpArrow:
2211
+ {
2212
+ if (_focusScene == FocusScene.ItemView && _selectGuids.Contains(_lastSelectGuid))
2213
+ {
2214
+ if (Event.current.modifiers == (EventModifiers.Shift | EventModifiers.FunctionKey))
2215
+ {
2216
+ //多选
2217
+ ShiftSelectOffset(-1);
2218
+ }
2219
+ else
2220
+ {
2221
+ SelectOffset(-1);
2222
+ }
2223
+
2224
+ Event.current.Use();
2225
+ }
2226
+ }
2227
+ break;
2228
+ case KeyCode.DownArrow:
2229
+ {
2230
+ if (_focusScene == FocusScene.ItemView && _selectGuids.Contains(_lastSelectGuid))
2231
+ {
2232
+ if (Event.current.modifiers == (EventModifiers.Shift | EventModifiers.FunctionKey))
2233
+ {
2234
+ //多选
2235
+ ShiftSelectOffset(1);
2236
+ }
2237
+ else
2238
+ {
2239
+ SelectOffset(1);
2240
+ }
2241
+
2242
+ Event.current.Use();
2243
+ }
2244
+ }
2245
+ break;
2246
+
2247
+ case KeyCode.A:
2248
+ {
2249
+ if (Event.current.modifiers == EventModifiers.Control)
2250
+ {
2251
+ if (_lastLayoutScene == LayoutScene.Center)
2252
+ {
2253
+ //全选
2254
+ Select(_matchItems.ToArray());
2255
+ Event.current.Use();
2256
+ }
2257
+ }
2258
+ }
2259
+ break;
2260
+ }
2261
+ }
2262
+
2263
+ //鼠标点击
2264
+ if (Event.current.type == EventType.MouseDown)
2265
+ {
2266
+ if (Event.current.button == 0)
2267
+ {
2268
+ var mousePosition = Event.current.mousePosition;
2269
+
2270
+ if (GUI.GetNameOfFocusedControl() == CONTROL_NAME_SEARCH_BAR &&
2271
+ !_searchBarArea.Contains(mousePosition))
2272
+ {
2273
+ GUI.FocusControl("");
2274
+ }
2275
+
2276
+ if (GUI.GetNameOfFocusedControl() == CONTROL_FOLDER_SEARCH_BAR &&
2277
+ !_searchFolderArea.Contains(mousePosition))
2278
+ {
2279
+ GUI.FocusControl("");
2280
+ }
2281
+
2282
+ if (_leftArea.Contains(mousePosition))
2283
+ {
2284
+ _lastLayoutScene = LayoutScene.Left;
2285
+ }
2286
+
2287
+ if (_centerArea.Contains(mousePosition))
2288
+ {
2289
+ _lastLayoutScene = LayoutScene.Center;
2290
+ }
2291
+
2292
+ if (_inspectorArea.Contains(mousePosition))
2293
+ {
2294
+ //TODO//点击右侧
2295
+ }
2296
+
2297
+ if (_itemsArea.Contains(mousePosition) && IsInsideItemRect(mousePosition, out var match))
2298
+ {
2299
+ switch (Event.current.modifiers)
2300
+ {
2301
+ case EventModifiers.None:
2302
+ {
2303
+ Select(match, SelectMode.Single);
2304
+ if (Event.current.clickCount >= 2)
2305
+ {
2306
+ Ping(GetInfo(match).Texture);
2307
+ if (_folderTree != null)
2308
+ {
2309
+ _folderTree.PingFolder(GetImporter(match).assetPath, true);
2310
+ }
2311
+ }
2312
+
2313
+ //选择实例
2314
+ Event.current.Use();
2315
+ }
2316
+ return;
2317
+ case EventModifiers.Control:
2318
+ {
2319
+ Select(match, SelectMode.Ctrl);
2320
+ //选择实例
2321
+ Event.current.Use();
2322
+ }
2323
+ return;
2324
+ case EventModifiers.Shift:
2325
+ {
2326
+ Select(match, SelectMode.Shift);
2327
+ //选择实例
2328
+ Event.current.Use();
2329
+ }
2330
+ return;
2331
+ }
2332
+ }
2333
+ }
2334
+ }
2335
+ }
2336
+
2337
+
2338
+ private bool IsInsideItemRect(Vector2 mousePos, out string match)
2339
+ {
2340
+ match = "";
2341
+ foreach (var pair in _itemsRects)
2342
+ {
2343
+ var guid = pair.Key;
2344
+ var rect = pair.Value;
2345
+ if (mousePos.y > rect.yMin && mousePos.y < rect.yMax)
2346
+ {
2347
+ match = guid;
2348
+ return true;
2349
+ }
2350
+ }
2351
+
2352
+ return false;
2353
+ }
2354
+
2355
+ //选择项改变时
2356
+ private void WhenSelectChanged()
2357
+ {
2358
+ if (!_selectGuids.Contains(_lastSelectGuid))
2359
+ {
2360
+ _lastSelectGuid = "";
2361
+ }
2362
+
2363
+ //更新选中实例
2364
+ SelectImporters(_selectGuids);
2365
+
2366
+ //更新inspector
2367
+ if (!string.IsNullOrEmpty(_lastSelectGuid))
2368
+ {
2369
+ var assetTargets = new List<Object>();
2370
+ foreach (var guid in _selectGuids)
2371
+ {
2372
+ assetTargets.Add(AssetDatabase.LoadAssetAtPath<Object>(AssetDatabase.GUIDToAssetPath(guid)));
2373
+ }
2374
+
2375
+ // Selection.objects = assetTargets.ToArray();
2376
+ }
2377
+
2378
+ _focusScene = FocusScene.ItemView;
2379
+ GUIUtility.keyboardControl = -1;
2380
+
2381
+
2382
+ if (_folderTree != null && !string.IsNullOrEmpty(_lastSelectGuid))
2383
+ {
2384
+ _folderTree.PingFolder(GetImporter(_lastSelectGuid).assetPath, false);
2385
+ }
2386
+ else
2387
+ {
2388
+ _folderTree.PingFolder("", false);
2389
+ }
2390
+ }
2391
+
2392
+
2393
+ //过滤项改变时
2394
+ private void WhenFilterChanged()
2395
+ {
2396
+ //更新匹配项
2397
+ UpdateMatchItems();
2398
+ }
2399
+
2400
+ private void SelectImporters(HashSet<string> guids, bool force = false)
2401
+ {
2402
+ if (!SelectImportersIsChanged(guids) && force == false)
2403
+ {
2404
+ return;
2405
+ }
2406
+
2407
+ _cacheSelectTextures.Clear();
2408
+ _cacheSelectCubeMap.Clear();
2409
+ _hoverSelect.Clear();
2410
+ var tex2d = new List<Texture2D>();
2411
+ var cubeMaps = new List<Cubemap>();
2412
+ _selectImportersGuids = new HashSet<string>(guids);
2413
+ var importers = new HashSet<TextureImporter>();
2414
+ foreach (var guid in _selectImportersGuids)
2415
+ {
2416
+ var importer = GetImporter(guid);
2417
+ importers.Add(importer);
2418
+ var tex = GetInfo(guid).Texture as Texture2D;
2419
+ var cubemap = GetInfo(guid).Texture as Cubemap;
2420
+ if (tex != null)
2421
+ {
2422
+ tex2d.Add(tex);
2423
+ _cacheSelectTextures.Add(guid);
2424
+ }
2425
+
2426
+ if (cubemap != null)
2427
+ {
2428
+ cubeMaps.Add(cubemap);
2429
+ _cacheSelectCubeMap.Add(guid);
2430
+ }
2431
+ }
2432
+
2433
+ _selectImporters = importers.ToArray();
2434
+ //加入二选一机制
2435
+ _multipleInspector = (cubeMaps.Count > 0 && tex2d.Count > 0);
2436
+ Object[] targets = tex2d.ToArray();
2437
+ if (tex2d.Count <= 0)
2438
+ {
2439
+ targets = cubeMaps.ToArray();
2440
+ }
2441
+
2442
+ DestroyImmediate(_inspectorEditor, true);
2443
+ DestroyImmediate(_assetEditor, true);
2444
+ _inspectorEditor = Editor.CreateEditor(_selectImporters);
2445
+ _assetEditor = Editor.CreateEditor(targets);
2446
+ var typeName = "UnityEditor.Experimental.AssetImporters.AssetImporterEditor";
2447
+ #if UNITY_2020_1_OR_NEWER
2448
+ typeName = $"UnityEditor.AssetImporters.AssetImporterEditor";
2449
+ #endif
2450
+ var type = GetType(typeName);
2451
+ var method = type.GetMethod("InternalSetAssetImporterTargetEditor",
2452
+ BindingFlags.NonPublic | BindingFlags.Instance);
2453
+ method.Invoke(_inspectorEditor, new object[] { _assetEditor });
2454
+ EditorUserBuildSettings.selectedBuildTargetGroup = BuildPipeline.GetBuildTargetGroup(_filterBuildTarget);
2455
+ }
2456
+
2457
+
2458
+ private void RebuildInspectorEditor()
2459
+ {
2460
+ SelectImporters(_selectGuids, true);
2461
+ }
2462
+
2463
+
2464
+ private bool SelectImportersIsChanged(HashSet<string> guids)
2465
+ {
2466
+ if (guids.Count != _selectImportersGuids.Count)
2467
+ {
2468
+ return true;
2469
+ }
2470
+
2471
+ foreach (var guid in guids)
2472
+ {
2473
+ if (!_selectImportersGuids.Contains(guid))
2474
+ {
2475
+ return true;
2476
+ }
2477
+ }
2478
+
2479
+ return false;
2480
+ }
2481
+
2482
+ private void WhenClickFolderTree()
2483
+ {
2484
+ _focusScene = FocusScene.FolderTree;
2485
+ }
2486
+
2487
+ #endregion
2488
+
2489
+ private static PropertyTabBinding GetPropertyTabBinding(PropertyTab tab)
2490
+ {
2491
+ return PropertyTabMap[tab];
2492
+ }
2493
+
2494
+ private static bool GetSortState(PropertyTab tab)
2495
+ {
2496
+ if (_sortReverseMap.TryGetValue(tab, out var match))
2497
+ {
2498
+ return match;
2499
+ }
2500
+ else
2501
+ {
2502
+ _sortReverseMap[tab] = false;
2503
+ return _sortReverseMap[tab];
2504
+ }
2505
+ }
2506
+
2507
+
2508
+ private static void SetSortState(PropertyTab tab, bool reverse)
2509
+ {
2510
+ _sortReverseMap[tab] = reverse;
2511
+ }
2512
+
2513
+ //清理排序缓存
2514
+ private static void ClearSortCache()
2515
+ {
2516
+ _cacheSortBy = null;
2517
+ _sortReverseMap.Clear();
2518
+ }
2519
+
2520
+ //获取sort order
2521
+ private static int GetTextureOrder(string guid)
2522
+ {
2523
+ if (_defaultOrders.TryGetValue(guid, out var order))
2524
+ {
2525
+ return order;
2526
+ }
2527
+
2528
+ return -1;
2529
+ }
2530
+
2531
+ private static void Ping(Object target)
2532
+ {
2533
+ EditorApplication.ExecuteMenuItem("Window/General/Project");
2534
+ EditorGUIUtility.PingObject(target);
2535
+ }
2536
+
2537
+ private static HashSet<T> CollectionToHashSet<T>(IEnumerable<T> target)
2538
+ {
2539
+ var result = new HashSet<T>();
2540
+ foreach (var element in target)
2541
+ {
2542
+ result.Add(element);
2543
+ }
2544
+
2545
+ return result;
2546
+ }
2547
+
2548
+ private static bool DrawMenuButton(string txt, bool selected, params GUILayoutOption[] options)
2549
+ {
2550
+ var click = GUILayout.Button("", options);
2551
+ var rect = GUILayoutUtility.GetLastRect();
2552
+ if (selected)
2553
+ {
2554
+ EditorGUI.DrawRect(rect, Color.black * 0.7f);
2555
+ }
2556
+
2557
+ GUI.Label(rect, txt, Styles.GetMenuButtonLabel(selected));
2558
+ return click;
2559
+ }
2560
+
2561
+ //反射获取有效的枚举
2562
+ private static T[] GetValidEnumValues<T>() where T : Enum
2563
+ {
2564
+ var type = typeof(T);
2565
+ var match = new HashSet<string>();
2566
+ var names = Enum.GetNames(typeof(T));
2567
+ foreach (var element in names)
2568
+ {
2569
+ var fieldInfo = type.GetField(element);
2570
+ // 检查特性是否废弃
2571
+ if (fieldInfo.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length > 0)
2572
+ {
2573
+ continue;
2574
+ }
2575
+ else
2576
+ {
2577
+ match.Add(fieldInfo.Name);
2578
+ }
2579
+ }
2580
+
2581
+ List<T> result = new List<T>();
2582
+ foreach (var value in match)
2583
+ {
2584
+ result.Add((T)Enum.Parse(typeof(T), value));
2585
+ }
2586
+
2587
+ return result.ToArray();
2588
+ }
2589
+
2590
+ private static Type _type_UnityEditor_TextureImporter = null;
2591
+
2592
+ private static Type Type_UnityEditor_TextureImporter
2593
+ {
2594
+ get
2595
+ {
2596
+ if (_type_UnityEditor_TextureImporter == null)
2597
+ {
2598
+ _type_UnityEditor_TextureImporter = GetType("UnityEditor.TextureImporter");
2599
+ }
2600
+
2601
+ return _type_UnityEditor_TextureImporter;
2602
+ }
2603
+ }
2604
+
2605
+ private static MethodInfo _method_RecommendedFormatsFromTextureTypeAndPlatform = null;
2606
+
2607
+ private static MethodInfo Method_RecommendedFormatsFromTextureTypeAndPlatform
2608
+ {
2609
+ get
2610
+ {
2611
+ if (_method_RecommendedFormatsFromTextureTypeAndPlatform == null)
2612
+ {
2613
+ _method_RecommendedFormatsFromTextureTypeAndPlatform = Type_UnityEditor_TextureImporter.GetMethod(
2614
+ "RecommendedFormatsFromTextureTypeAndPlatform",
2615
+ BindingFlags.Static | BindingFlags.NonPublic);
2616
+ }
2617
+
2618
+ return _method_RecommendedFormatsFromTextureTypeAndPlatform;
2619
+ }
2620
+ }
2621
+
2622
+ private static MethodInfo _method_GetSourceTextureInformation = null;
2623
+
2624
+ private static MethodInfo Method_GetSourceTextureInformation
2625
+ {
2626
+ get
2627
+ {
2628
+ if (_method_GetSourceTextureInformation == null)
2629
+ {
2630
+ _method_GetSourceTextureInformation = Type_UnityEditor_TextureImporter.GetMethod(
2631
+ "GetSourceTextureInformation",
2632
+ BindingFlags.Instance | BindingFlags.NonPublic);
2633
+ }
2634
+
2635
+ return _method_GetSourceTextureInformation;
2636
+ }
2637
+ }
2638
+
2639
+
2640
+ private static Type GetType(string typeName)
2641
+ {
2642
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies();
2643
+ foreach (var assembly in assemblies)
2644
+ {
2645
+ var type = assembly.GetType(typeName);
2646
+ if (type != null)
2647
+ {
2648
+ return type;
2649
+ }
2650
+ }
2651
+
2652
+ return null;
2653
+ }
2654
+
2655
+
2656
+ public static SourceTextureInformation GetSourceTextureInformation(
2657
+ TextureImporter importer)
2658
+ {
2659
+ var info =
2660
+ Method_GetSourceTextureInformation?.Invoke(importer, null) as
2661
+ SourceTextureInformation;
2662
+ return info;
2663
+ }
2664
+
2665
+
2666
+ //推荐格式类型
2667
+ public static TextureImporterFormat[] GetRecommendedFormats(TextureImporter importer, BuildTarget target)
2668
+ {
2669
+ return Method_RecommendedFormatsFromTextureTypeAndPlatform.Invoke(null,
2670
+ new object[] { importer.textureType, target }) as
2671
+ TextureImporterFormat[];
2672
+ }
2673
+
2674
+
2675
+ //绘制标题
2676
+ private static Rect DrawHeader(string title, params GUILayoutOption[] options)
2677
+ {
2678
+ GUILayout.Label("", Styles.WhiteTitleLabel, options);
2679
+ var rect = GUILayoutUtility.GetLastRect();
2680
+ EditorGUI.DrawRect(rect, Color.black);
2681
+ GUI.Label(rect, title, Styles.WhiteTitleLabel);
2682
+ return rect;
2683
+ }
2684
+
2685
+
2686
+ //创建右上角rect
2687
+ public static Rect CreateRightTopRect(Rect rect, float width, float margin)
2688
+ {
2689
+ var rectResult = rect;
2690
+ rectResult.width = width;
2691
+ rectResult.x = rect.xMax - rectResult.width;
2692
+ var center = rectResult.center;
2693
+ rectResult.height -= margin * 2;
2694
+ rectResult.width -= margin * 2;
2695
+ rectResult.center = center;
2696
+ return rectResult;
2697
+ }
2698
+
2699
+ private void OnDisable()
2700
+ {
2701
+ _folderTree?.Release();
2702
+ _folderTree = null;
2703
+ DestroyImmediate(_assetEditor, true);
2704
+ DestroyImmediate(_inspectorEditor, true);
2705
+ }
2706
+
2707
+ #region GUI样式
2708
+
2709
+ public class Styles
2710
+ {
2711
+ public static bool IsProSKin => EditorGUIUtility.isProSkin;
2712
+
2713
+ private static GUIStyle _toggleFlex = null;
2714
+
2715
+ public static GUIStyle ToggleFlex => GetStyle(ref _toggleFlex, "toggle", (style) =>
2716
+ {
2717
+ style.margin = new RectOffset(0, 0, 0, 0);
2718
+ style.padding = new RectOffset(2, 24, 2, 2);
2719
+ style.border = new RectOffset(0, 0, 0, 0);
2720
+ style.alignment = TextAnchor.MiddleLeft;
2721
+ style.contentOffset = Vector2.right * 16;
2722
+ style.fixedWidth = 0;
2723
+ style.stretchWidth = false;
2724
+ });
2725
+
2726
+
2727
+ private static GUIStyle _buttonLeft = null;
2728
+
2729
+ public static GUIStyle ButtonLeft => GetStyle(ref _buttonLeft, "button", (style) =>
2730
+ {
2731
+ style.margin = new RectOffset(0, 0, 0, 0);
2732
+ style.padding = new RectOffset(2, 2, 2, 2);
2733
+ style.border = new RectOffset(0, 0, 0, 0);
2734
+ style.alignment = TextAnchor.MiddleLeft;
2735
+ });
2736
+
2737
+
2738
+ private static GUIStyle _smallLabel = null;
2739
+
2740
+ public static GUIStyle SmallLabel => GetStyle(ref _smallLabel, "label", (style) =>
2741
+ {
2742
+ style.margin = new RectOffset(0, 0, 0, 0);
2743
+ style.padding = new RectOffset(2, 2, 2, 2);
2744
+ style.border = new RectOffset(0, 0, 0, 0);
2745
+ style.alignment = TextAnchor.MiddleLeft;
2746
+ style.fontSize = 10;
2747
+ });
2748
+
2749
+ private static GUIStyle _titleLabel = null;
2750
+
2751
+ public static GUIStyle TitleLabel => GetStyle(ref _titleLabel, "label", (style) =>
2752
+ {
2753
+ style.margin = new RectOffset(0, 0, 0, 0);
2754
+ style.padding = new RectOffset(8, 8, 2, 2);
2755
+ style.border = new RectOffset(0, 0, 0, 0);
2756
+ style.alignment = TextAnchor.MiddleLeft;
2757
+ style.fontStyle = FontStyle.Bold;
2758
+ style.fontSize = 14;
2759
+ });
2760
+
2761
+ private static GUIStyle _boldLabel = null;
2762
+
2763
+ public static GUIStyle BoldLabel => GetStyle(ref _boldLabel, "label", (style) =>
2764
+ {
2765
+ style.margin = new RectOffset(0, 0, 0, 0);
2766
+ style.padding = new RectOffset(8, 8, 2, 2);
2767
+ style.border = new RectOffset(0, 0, 0, 0);
2768
+ style.fontStyle = FontStyle.Bold;
2769
+ });
2770
+
2771
+
2772
+ private static GUIStyle _whiteTitleLabel = null;
2773
+
2774
+ public static GUIStyle WhiteTitleLabel => GetStyle(ref _whiteTitleLabel, "label", (style) =>
2775
+ {
2776
+ style.margin = new RectOffset(0, 0, 0, 0);
2777
+ style.padding = new RectOffset(8, 8, 2, 2);
2778
+ style.border = new RectOffset(0, 0, 0, 0);
2779
+ style.fontStyle = FontStyle.Bold;
2780
+ style.normal.textColor = Color.white;
2781
+ style.alignment = TextAnchor.MiddleLeft;
2782
+ });
2783
+
2784
+
2785
+ private static GUIStyle _middleLabel = null;
2786
+
2787
+ public static GUIStyle MiddleLabel => GetStyle(ref _middleLabel, "label", (style) =>
2788
+ {
2789
+ style.margin = new RectOffset(0, 0, 0, 0);
2790
+ style.padding = new RectOffset(8, 8, 2, 2);
2791
+ style.border = new RectOffset(0, 0, 0, 0);
2792
+ style.alignment = TextAnchor.MiddleCenter;
2793
+ });
2794
+
2795
+
2796
+ private static GUIStyle _menuButtonLabel = null;
2797
+
2798
+ public static GUIStyle MenuButtonLabel => GetStyle(ref _menuButtonLabel, "label", (style) =>
2799
+ {
2800
+ style.margin = new RectOffset(0, 0, 0, 0);
2801
+ style.padding = new RectOffset(8, 8, 2, 2);
2802
+ style.border = new RectOffset(0, 0, 0, 0);
2803
+ style.alignment = TextAnchor.MiddleLeft;
2804
+ });
2805
+
2806
+ public static GUIStyle GetMenuButtonLabel(bool isSelect)
2807
+ {
2808
+ var textColor = IsProSKin ? Color.white : Color.black;
2809
+ if (isSelect)
2810
+ {
2811
+ textColor = IsProSKin ? new Color(0.3f, 0.53f, 1f, 1f) : Color.white;
2812
+ }
2813
+
2814
+ MenuButtonLabel.normal.textColor = textColor;
2815
+ MenuButtonLabel.fontStyle = isSelect ? FontStyle.Bold : FontStyle.Normal;
2816
+ return MenuButtonLabel;
2817
+ }
2818
+
2819
+
2820
+ private static GUIStyle _searchTips = null;
2821
+
2822
+ public static GUIStyle SearchTips => GetStyle(ref _searchTips, "label",
2823
+ (style) =>
2824
+ {
2825
+ var col = style.normal.textColor;
2826
+ style.normal.textColor = new Color(col.r, col.g, col.b, col.a * 0.5f);
2827
+ style.fontStyle = FontStyle.Italic;
2828
+ style.margin = new RectOffset(0, 0, 0, 0);
2829
+ style.padding = new RectOffset(4, 8, 2, 2);
2830
+ style.border = new RectOffset(0, 0, 0, 0);
2831
+ style.alignment = TextAnchor.MiddleLeft;
2832
+ });
2833
+
2834
+
2835
+ private static GUIStyle GetStyle(ref GUIStyle style, string styleName, Action<GUIStyle> onCreate = null)
2836
+ {
2837
+ if (style == null)
2838
+ {
2839
+ style = new GUIStyle(styleName);
2840
+ onCreate?.Invoke(style);
2841
+ }
2842
+
2843
+ return style;
2844
+ }
2845
+ }
2846
+
2847
+ #endregion
2848
+ }
2849
+ }