A game about forced loneliness, made by TACStudios
at master 816 lines 28 kB view raw
1using System; 2using System.Collections.Generic; 3using System.IO; 4using UnityEngine; 5using UnityEngine.U2D.Animation; 6 7namespace UnityEditor.U2D.Animation.SpriteLibraryEditor 8{ 9 internal enum ActionType 10 { 11 SelectCategory, 12 SelectLabels, 13 RenameCategory, 14 RenameLabel, 15 CreateCategory, 16 CreateLabel, 17 DeleteCategories, 18 DeleteLabels, 19 ReorderCategories, 20 ReorderLabels, 21 ModifiedCategories, 22 ModifiedLabels, 23 24 SetMainLibrary, 25 SetLabelSprite, 26 27 None 28 } 29 30 internal enum ViewType 31 { 32 List, 33 Grid 34 } 35 36 internal struct ViewData 37 { 38 /// <summary> 39 /// View type (List / Grid). 40 /// </summary> 41 public ViewType viewType; 42 43 /// <summary> 44 /// Relative size for selected View Type in range 0-1. 45 /// </summary> 46 public float relativeSize; 47 48 /// <summary> 49 /// Absolute size based on the slider position in range 0-1. 50 /// </summary> 51 public float absoluteSize; 52 } 53 54 internal enum SearchType 55 { 56 CategoryAndLabel, 57 Category, 58 Label 59 } 60 61 internal class WindowController 62 { 63 ISpriteLibraryEditorWindow m_Window; 64 SpriteLibraryEditorModel m_Model; 65 66 List<string> selectedCategories => m_Model.GetSelectedCategories(); 67 List<string> selectedLabels => m_Model.GetSelectedLabels(); 68 69 public SpriteLibraryAsset GetSelectedAsset() => m_Model.selectedAsset; 70 71 ControllerEvents m_ControllerEvents; 72 ViewEvents m_ViewEvents; 73 74 bool hasSelectedLibrary => m_Model.selectedAsset != null; 75 76 const float k_ViewSizeDivision = 0.1f; 77 float m_ViewSize; 78 ViewType m_ViewType = ViewType.List; 79 80 string m_FilterString = ""; 81 SearchType m_FilterType = SearchType.CategoryAndLabel; 82 83 string m_SelectedAssetPath; 84 85 const string k_DefaultLabelName = "New Label"; 86 const string k_DefaultCategoryName = "New Category"; 87 88 bool m_AutoSave; 89 bool m_SelectionLocked; 90 91 public WindowController(ISpriteLibraryEditorWindow window, SpriteLibraryEditorModel model, ControllerEvents controllerEvents, ViewEvents viewEvents) 92 { 93 m_Window = window; 94 m_ControllerEvents = controllerEvents; 95 m_ViewEvents = viewEvents; 96 97 m_Model = model; 98 99 AddAssetPostprocessorListeners(); 100 AddViewEventListeners(); 101 102 Selection.selectionChanged += SelectionChanged; 103 Undo.undoRedoPerformed += PropagateLastAction; 104 105 m_AutoSave = SpriteLibraryEditorWindow.Settings.autoSave; 106 } 107 108 public void Destroy() 109 { 110 RemoveAssetPostprocessorListeners(); 111 112 Selection.selectionChanged -= SelectionChanged; 113 Undo.undoRedoPerformed -= PropagateLastAction; 114 115 if (m_Model != null) 116 m_Model.Destroy(); 117 } 118 119 public void SaveChanges() 120 { 121 m_Model.SaveLibrary(m_SelectedAssetPath); 122 123 m_ControllerEvents.onSelectedLibrary?.Invoke(m_Model.selectedAsset); 124 } 125 126 public void RevertChanges() 127 { 128 m_Model.SelectLabels(new List<string>()); 129 m_Model.SelectCategories(new List<string>()); 130 m_Model.SelectAsset(m_Model.selectedAsset); 131 132 m_ControllerEvents.onSelectedLibrary?.Invoke(m_Model.selectedAsset); 133 RefreshView(); 134 RefreshSelection(); 135 } 136 137 public void SelectAsset(SpriteLibraryAsset asset, bool modifiedExternally = false) 138 { 139 // Only allow .spriteLib files to be used in the editor. 140 // This is to prevent the user from opening the editor with .psd or .psb containing spriteLibs. 141 if (!AssetDatabase.GetAssetPath(asset).EndsWith(".spriteLib")) 142 return; 143 144 if (!modifiedExternally) 145 { 146 if (asset == null || asset == m_Model.selectedAsset) 147 return; 148 149 if (m_Window.hasUnsavedChanges) 150 m_Window.HandleUnsavedChanges(); 151 } 152 153 m_SelectedAssetPath = asset != null ? AssetDatabase.GetAssetPath(asset) : null; 154 155 m_Model.SelectAsset(asset); 156 157 m_ControllerEvents.onSelectedLibrary?.Invoke(asset); 158 159 RefreshView(); 160 RefreshSelection(); 161 } 162 163 void AddViewEventListeners() 164 { 165 m_ViewEvents.onCreateNewSpriteLibraryAsset.AddListener(CreateNewSpriteLibraryAsset); 166 m_ViewEvents.onSave.AddListener(OnSave); 167 m_ViewEvents.onRevert.AddListener(OnRevert); 168 m_ViewEvents.onToggleAutoSave.AddListener(ToggleAutoSave); 169 m_ViewEvents.onToggleSelectionLock.AddListener(ToggleSelectionLock); 170 171 m_ViewEvents.onViewSizeUpdate.AddListener(ChangeViewSize); 172 m_ViewEvents.onViewTypeUpdate.AddListener(ChangeViewType); 173 174 m_ViewEvents.onSelectedFilter.AddListener(SelectedFilter); 175 m_ViewEvents.onSelectedFilterType.AddListener(SelectedFilterType); 176 177 m_ViewEvents.onSetMainAsset.AddListener(SetMainAsset); 178 m_ViewEvents.onSelectCategories.AddListener(SelectCategories); 179 m_ViewEvents.onSelectLabels.AddListener(SelectLabels); 180 181 m_ViewEvents.onCreateNewCategory.AddListener(CreateNewCategory); 182 m_ViewEvents.onRenameCategory.AddListener(RenameSelectedCategory); 183 m_ViewEvents.onReorderCategories.AddListener(ReorderCategories); 184 m_ViewEvents.onDeleteCategories.AddListener(DeleteSelectedCategories); 185 186 m_ViewEvents.onCreateNewLabel.AddListener(CreateNewLabel); 187 m_ViewEvents.onRenameLabel.AddListener(RenameSelectedLabel); 188 m_ViewEvents.onReorderLabels.AddListener(ReorderLabels); 189 m_ViewEvents.onDeleteLabels.AddListener(DeleteSelectedLabels); 190 m_ViewEvents.onSetLabelSprite.AddListener(SetLabelSprite); 191 192 m_ViewEvents.onAddDataToCategories.AddListener(AddDataToCategories); 193 m_ViewEvents.onAddDataToLabels.AddListener(AddDataToLabels); 194 m_ViewEvents.onRevertOverridenLabels.AddListener(RevertOverridenLabels); 195 } 196 197 void AddAssetPostprocessorListeners() 198 { 199 SpriteLibraryAssetPostprocessor.OnImported += OnAssetModified; 200 SpriteLibraryAssetPostprocessor.OnDeleted += OnAssetModified; 201 SpriteLibraryAssetPostprocessor.OnMovedAssetFromTo += OnAssetMoved; 202 } 203 204 void RemoveAssetPostprocessorListeners() 205 { 206 SpriteLibraryAssetPostprocessor.OnImported -= OnAssetModified; 207 SpriteLibraryAssetPostprocessor.OnDeleted -= OnAssetModified; 208 SpriteLibraryAssetPostprocessor.OnMovedAssetFromTo -= OnAssetMoved; 209 } 210 211 static void CreateNewSpriteLibraryAsset(string newAssetPath) 212 { 213 if (string.IsNullOrEmpty(newAssetPath) || !string.Equals(Path.GetExtension(newAssetPath), SpriteLibrarySourceAsset.extension, StringComparison.OrdinalIgnoreCase)) 214 return; 215 216 // Make sure that the extension is exactly the same 217 if (Path.GetExtension(newAssetPath) != SpriteLibrarySourceAsset.extension) 218 newAssetPath = newAssetPath.Replace(Path.GetExtension(newAssetPath), SpriteLibrarySourceAsset.extension); 219 220 var assetToSave = ScriptableObject.CreateInstance<SpriteLibrarySourceAsset>(); 221 SpriteLibrarySourceAssetImporter.SaveSpriteLibrarySourceAsset(assetToSave, newAssetPath); 222 AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); 223 224 var newAsset = AssetDatabase.LoadAssetAtPath<SpriteLibraryAsset>(newAssetPath); 225 Selection.objects = new UnityEngine.Object[] { newAsset }; 226 } 227 228 void ChangeViewSize(float newSize) 229 { 230 m_ViewSize = newSize; 231 if (m_ViewSize > k_ViewSizeDivision && m_ViewType == ViewType.List) 232 m_ViewType = ViewType.Grid; 233 if (m_ViewSize < k_ViewSizeDivision && m_ViewType == ViewType.Grid) 234 m_ViewType = ViewType.List; 235 236 m_ControllerEvents.onViewChanged?.Invoke(new ViewData { viewType = m_ViewType, relativeSize = GetAdjustedViewSize(m_ViewSize, m_ViewType), absoluteSize = m_ViewSize }); 237 } 238 239 void ChangeViewType(ViewType viewType) 240 { 241 if (m_ViewType == viewType) 242 return; 243 244 m_ViewType = viewType; 245 m_ViewSize = m_ViewType == ViewType.List ? 0.0f : k_ViewSizeDivision; 246 247 m_ControllerEvents.onViewChanged?.Invoke(new ViewData { viewType = m_ViewType, relativeSize = GetAdjustedViewSize(m_ViewSize, m_ViewType), absoluteSize = m_ViewSize }); 248 } 249 250 static float GetAdjustedViewSize(float size, ViewType viewType) 251 { 252 if (viewType == ViewType.List) 253 return size / k_ViewSizeDivision; 254 return (size - k_ViewSizeDivision) / (1 - k_ViewSizeDivision); 255 } 256 257 void SelectedFilterType(SearchType newFilterType) 258 { 259 if (m_FilterType == newFilterType) 260 return; 261 262 m_FilterType = newFilterType; 263 264 RefreshView(); 265 } 266 267 void SelectedFilter(string newFilterString) 268 { 269 if (string.Equals(m_FilterString, newFilterString, StringComparison.OrdinalIgnoreCase)) 270 return; 271 272 m_FilterString = newFilterString; 273 274 RefreshView(); 275 } 276 277 void OnAssetModified(string modifiedAssetPath) 278 { 279 var isModifiedExternally = !(m_SelectedAssetPath != modifiedAssetPath || m_Model.isSaving); 280 if (!isModifiedExternally) 281 return; 282 283 SelectAsset(AssetDatabase.LoadAssetAtPath<SpriteLibraryAsset>(m_SelectedAssetPath), true); 284 } 285 286 void OnAssetMoved(string sourcePath, string destinationPath) 287 { 288 if (sourcePath == m_SelectedAssetPath) 289 { 290 if (string.IsNullOrEmpty(destinationPath)) 291 { 292 SelectAsset(null, true); 293 } 294 else 295 { 296 m_Model.SetAssetPath(destinationPath); 297 m_SelectedAssetPath = destinationPath; 298 } 299 } 300 } 301 302 void SelectionChanged() 303 { 304 if (!m_SelectionLocked) 305 SelectAsset(SpriteLibrarySourceAssetImporter.GetAssetFromSelection()); 306 } 307 308 void RefreshView() 309 { 310 var areCategoriesFiltered = m_FilterType is SearchType.CategoryAndLabel or SearchType.Category && !string.IsNullOrEmpty(m_FilterString); 311 var filteredCategories = m_Model.GetFilteredCategories(m_FilterString, m_FilterType); 312 m_ControllerEvents.onModifiedCategories?.Invoke(filteredCategories, areCategoriesFiltered); 313 314 var areLabelsFiltered = m_FilterType is SearchType.CategoryAndLabel or SearchType.Label && !string.IsNullOrEmpty(m_FilterString); 315 var filteredLabels = m_Model.GetFilteredLabels(m_FilterString, m_FilterType); 316 m_ControllerEvents.onModifiedLabels?.Invoke(filteredLabels, areLabelsFiltered); 317 318 m_ControllerEvents.onLibraryDataChanged?.Invoke(m_Model.isModified); 319 } 320 321 void RefreshSelection() 322 { 323 m_ControllerEvents.onSelectedCategories?.Invoke(selectedCategories); 324 m_ControllerEvents.onSelectedLabels?.Invoke(selectedLabels); 325 } 326 327 void PropagateLastAction() 328 { 329 if (SpriteLibraryEditorModel.IsActionModifyingAssets(m_Model.lastActionType)) 330 AutoSave(); 331 332 if (m_Model.lastActionType == ActionType.SetMainLibrary) 333 m_ControllerEvents.onMainLibraryChanged?.Invoke(m_Model.GetMainLibrary()); 334 335 RefreshView(); 336 RefreshSelection(); 337 338 m_Model.lastActionType = ActionType.None; 339 } 340 341 void SetMainAsset(SpriteLibraryAsset libraryAsset) 342 { 343 if (!hasSelectedLibrary) 344 return; 345 346 var validAsset = true; 347 if (libraryAsset != null) 348 { 349 if (libraryAsset == m_Model.selectedAsset || SpriteLibrarySourceAssetImporter.GetAssetParentChain(libraryAsset).Contains(GetSelectedAsset())) 350 { 351 Debug.LogWarning(TextContent.spriteLibraryCircularDependency); 352 validAsset = false; 353 } 354 } 355 356 if (validAsset) 357 { 358 m_Model.BeginUndo(ActionType.SetMainLibrary, TextContent.spriteLibrarySetMainLibrary); 359 m_Model.SetMainLibrary(libraryAsset); 360 m_Model.SelectCategories(new List<string>()); 361 m_Model.SelectLabels(new List<string>()); 362 m_Model.EndUndo(); 363 364 AutoSave(); 365 m_ControllerEvents.onMainLibraryChanged?.Invoke(libraryAsset); 366 RefreshView(); 367 RefreshSelection(); 368 } 369 else 370 { 371 m_ControllerEvents.onMainLibraryChanged?.Invoke(m_Model.GetMainLibrary()); 372 } 373 } 374 375 void SelectCategories(IList<string> newSelection) 376 { 377 if (!hasSelectedLibrary) 378 return; 379 380 newSelection ??= new List<string>(); 381 382 if (Equals(m_Model.GetSelectedCategories(), newSelection)) 383 return; 384 385 m_Model.BeginUndo(ActionType.SelectCategory, TextContent.spriteLibrarySelectCategories); 386 m_Model.SelectCategories(newSelection); 387 m_Model.SelectLabels(new List<string>()); 388 m_Model.EndUndo(); 389 390 RefreshView(); 391 RefreshSelection(); 392 } 393 394 void SelectLabels(IList<string> newSelection) 395 { 396 newSelection ??= new List<string>(); 397 398 if (AreSequencesEqual(m_Model.GetSelectedLabels(), newSelection)) 399 return; 400 401 m_Model.BeginUndo(ActionType.SelectLabels, TextContent.spriteLibrarySelectLabels); 402 m_Model.SelectLabels(newSelection); 403 m_Model.EndUndo(); 404 405 RefreshSelection(); 406 } 407 408 void CreateNewCategory(string categoryName = null, IList<Sprite> sprites = null) 409 { 410 if (!hasSelectedLibrary) 411 return; 412 413 if (string.IsNullOrEmpty(categoryName)) 414 categoryName = k_DefaultCategoryName; 415 416 m_Model.BeginUndo(ActionType.CreateCategory, TextContent.spriteLibraryCreateCategory); 417 m_Model.CreateNewCategory(categoryName, sprites); 418 m_Model.SelectCategories(new List<string> { m_Model.GetAllCategories()[^1].name }); 419 m_Model.SelectLabels(new List<string>()); 420 m_Model.EndUndo(); 421 422 AutoSave(); 423 RefreshView(); 424 RefreshSelection(); 425 } 426 427 void RenameSelectedCategory(string newName) 428 { 429 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 430 return; 431 432 newName = newName?.Trim(); 433 if (string.IsNullOrEmpty(newName)) 434 return; 435 436 var categoryData = GetCategoryData(selectedCategories[0]); 437 if (categoryData == null || categoryData.fromMain) 438 return; 439 440 m_Model.BeginUndo(ActionType.RenameCategory, TextContent.spriteLibraryRenameCategory); 441 m_Model.RenameSelectedCategory(newName); 442 m_Model.EndUndo(); 443 444 AutoSave(); 445 RefreshView(); 446 RefreshSelection(); 447 } 448 449 void ReorderCategories(IList<string> reorderedCategories) 450 { 451 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 452 return; 453 454 if (m_Model.CompareCategories(reorderedCategories)) 455 return; 456 457 var categoriesToReorder = selectedCategories; 458 m_Model.BeginUndo(ActionType.ReorderCategories, TextContent.spriteLibraryReorderCategories); 459 m_Model.ReorderCategories(reorderedCategories); 460 m_Model.SelectCategories(categoriesToReorder); 461 m_Model.EndUndo(); 462 463 AutoSave(); 464 RefreshView(); 465 RefreshSelection(); 466 } 467 468 void DeleteSelectedCategories() 469 { 470 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 471 return; 472 473 var validCategories = false; 474 foreach (var category in selectedCategories) 475 { 476 var categoryData = GetCategoryData(category); 477 if (categoryData != null && !categoryData.fromMain) 478 { 479 validCategories = true; 480 break; 481 } 482 } 483 484 if (!validCategories) 485 return; 486 487 m_Model.BeginUndo(ActionType.DeleteCategories, TextContent.spriteLibraryDeleteCategories); 488 m_Model.DeleteSelectedCategories(); 489 m_Model.SelectCategories(new List<string>()); 490 m_Model.SelectLabels(new List<string>()); 491 m_Model.EndUndo(); 492 493 AutoSave(); 494 RefreshView(); 495 RefreshSelection(); 496 } 497 498 void CreateNewLabel(string labelName = null) 499 { 500 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 501 return; 502 503 if (string.IsNullOrEmpty(labelName)) 504 labelName = k_DefaultLabelName; 505 506 m_Model.BeginUndo(ActionType.CreateLabel, TextContent.spriteLibraryCreateLabel); 507 m_Model.CreateNewLabel(labelName); 508 m_Model.SelectLabels(new List<string> { m_Model.GetAllLabels()[^1].name }); 509 m_Model.EndUndo(); 510 511 AutoSave(); 512 RefreshView(); 513 RefreshSelection(); 514 } 515 516 void RenameSelectedLabel(string newName) 517 { 518 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories || !m_Model.hasSelectedLabels) 519 return; 520 521 var labelData = GetLabelData(selectedLabels[0]); 522 if (labelData == null || labelData.fromMain) 523 return; 524 525 newName = newName?.Trim(); 526 if (newName == string.Empty) 527 return; 528 529 m_Model.BeginUndo(ActionType.RenameLabel, TextContent.spriteLibraryRenameLabel); 530 m_Model.RenameSelectedLabel(newName); 531 m_Model.EndUndo(); 532 533 AutoSave(); 534 RefreshView(); 535 RefreshSelection(); 536 } 537 538 void ReorderLabels(IList<string> reorderedLabels) 539 { 540 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 541 return; 542 543 if (m_Model.CompareLabels(reorderedLabels)) 544 return; 545 546 var labelsToReorder = selectedLabels; 547 m_Model.BeginUndo(ActionType.ReorderLabels, TextContent.spriteLibraryReorderLabels); 548 m_Model.ReorderLabels(reorderedLabels); 549 m_Model.SelectLabels(labelsToReorder); 550 m_Model.EndUndo(); 551 552 AutoSave(); 553 RefreshView(); 554 } 555 556 void DeleteSelectedLabels() 557 { 558 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories || !m_Model.hasSelectedLabels) 559 return; 560 561 var canAnyLabelBeDeleted = false; 562 foreach (var label in selectedLabels) 563 { 564 if (!GetLabelData(label).fromMain) 565 { 566 canAnyLabelBeDeleted = true; 567 break; 568 } 569 } 570 571 if (!canAnyLabelBeDeleted) 572 return; 573 574 m_Model.BeginUndo(ActionType.DeleteLabels, TextContent.spriteLibraryDeleteLabels); 575 m_Model.DeleteSelectedLabels(); 576 m_Model.SelectLabels(new List<string>()); 577 m_Model.EndUndo(); 578 579 AutoSave(); 580 RefreshView(); 581 RefreshSelection(); 582 } 583 584 void SetLabelSprite(string labelName, Sprite newSprite) 585 { 586 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 587 return; 588 589 var labelData = GetLabelData(labelName); 590 if (labelData == null || labelData.sprite == newSprite) 591 return; 592 593 m_Model.BeginUndo(ActionType.SetLabelSprite, TextContent.spriteLibrarySetLabelSprite); 594 m_Model.SetLabelSprite(labelName, newSprite); 595 m_Model.EndUndo(); 596 597 AutoSave(); 598 RefreshView(); 599 RefreshSelection(); 600 } 601 602 void ToggleAutoSave(bool newAutoSaveValue) 603 { 604 m_AutoSave = newAutoSaveValue; 605 if (m_AutoSave) 606 OnSave(); 607 } 608 609 void OnSave() 610 { 611 m_Window.SaveChanges(); 612 } 613 614 void OnRevert() 615 { 616 if (m_Window.hasUnsavedChanges) 617 m_Window.HandleRevertChanges(); 618 } 619 620 void AutoSave() 621 { 622 if (m_AutoSave) 623 m_Window.SaveChanges(); 624 } 625 626 void ToggleSelectionLock(bool isSelectionLocked) 627 { 628 m_SelectionLocked = isSelectionLocked; 629 630 SelectionChanged(); 631 } 632 633 void AddDataToCategories(IList<DragAndDropData> spritesData, bool alt, string category) 634 { 635 if (!hasSelectedLibrary) 636 return; 637 638 if (spritesData == null || spritesData.Count == 0) 639 return; 640 641 m_Model.BeginUndo(ActionType.ModifiedCategories, TextContent.spriteLibraryAddDataToCategories); 642 643 foreach (var data in spritesData) 644 { 645 var isDroppedIntoEmptyArea = string.IsNullOrEmpty(category); 646 if (isDroppedIntoEmptyArea) 647 { 648 if (data.spriteSourceType == SpriteSourceType.Psb) 649 HandlePsdData(data); 650 else if (data.spriteSourceType == SpriteSourceType.Sprite) 651 m_Model.CreateNewCategory(data.name, data.sprites); 652 } 653 else 654 m_Model.AddLabelsToCategory(category, data.sprites, true); 655 } 656 657 m_Model.EndUndo(); 658 659 AutoSave(); 660 RefreshView(); 661 RefreshSelection(); 662 } 663 664 void AddDataToLabels(IList<DragAndDropData> spritesData, bool alt, string label) 665 { 666 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 667 return; 668 669 var sprites = new List<Sprite>(); 670 foreach (var data in spritesData) 671 sprites.AddRange(data.sprites); 672 673 if (sprites.Count == 0) 674 return; 675 676 m_Model.BeginUndo(ActionType.ModifiedLabels, TextContent.spriteLibraryAddDataToLabels); 677 if (!string.IsNullOrEmpty(label)) 678 m_Model.SetLabelSprite(label, sprites[0]); 679 else // empty area 680 m_Model.AddLabelsToCategory(selectedCategories[0], sprites, false); 681 m_Model.EndUndo(); 682 683 AutoSave(); 684 RefreshView(); 685 RefreshSelection(); 686 } 687 688 void HandlePsdData(DragAndDropData data) 689 { 690 var psdFilePath = AssetDatabase.GetAssetPath(data.sprites[0]); 691 var characterObj = AssetDatabase.LoadAssetAtPath<GameObject>(psdFilePath); 692 var categoryDictionary = new Dictionary<string, List<Sprite>>(); 693 var objectList = new Queue<Transform>(); 694 objectList.Enqueue(characterObj.transform); 695 while (objectList.Count > 0) 696 { 697 var goTransform = objectList.Dequeue(); 698 var spriteList = new List<Sprite>(); 699 for (var i = 0; i < goTransform.childCount; i++) 700 { 701 var childTransform = goTransform.GetChild(i); 702 703 var spriteRenderer = childTransform.GetComponent<SpriteRenderer>(); 704 if (spriteRenderer != null) 705 spriteList.Add(spriteRenderer.sprite); 706 else 707 objectList.Enqueue(childTransform); 708 } 709 710 if (spriteList.Count > 0) 711 { 712 if (goTransform == characterObj.transform) 713 { 714 foreach (var sprite in spriteList) 715 categoryDictionary[sprite.name] = new List<Sprite> { sprite }; 716 } 717 else 718 { 719 categoryDictionary[goTransform.name] = spriteList; 720 } 721 } 722 } 723 724 foreach (var (categoryName, sprites) in categoryDictionary) 725 { 726 var addedToCategory = false; 727 foreach (var cat in m_Model.GetAllCategories()) 728 { 729 if (cat.name == categoryName) 730 { 731 m_Model.AddLabelsToCategory(categoryName, sprites, true); 732 addedToCategory = true; 733 break; 734 } 735 } 736 737 if (!addedToCategory) 738 m_Model.CreateNewCategory(categoryName, sprites); 739 } 740 } 741 742 void RevertOverridenLabels(IList<string> labels) 743 { 744 if (!hasSelectedLibrary || !m_Model.hasSelectedCategories) 745 return; 746 747 var canRevertChanges = false; 748 foreach (var label in labels) 749 { 750 if (string.IsNullOrEmpty(label)) 751 continue; 752 753 var data = GetLabelData(label); 754 if (data != null && (data.spriteOverride || data.categoryFromMain && !data.fromMain)) 755 { 756 canRevertChanges = true; 757 break; 758 } 759 } 760 761 if (!canRevertChanges) 762 return; 763 764 m_Model.BeginUndo(ActionType.SetLabelSprite, TextContent.spriteLibrarySetLabelSprite); 765 m_Model.RevertLabels(labels); 766 m_Model.SelectLabels(new List<string>()); 767 m_Model.EndUndo(); 768 769 AutoSave(); 770 RefreshView(); 771 RefreshSelection(); 772 } 773 774 CategoryData GetCategoryData(string categoryName) 775 { 776 if (string.IsNullOrEmpty(categoryName)) 777 return null; 778 779 foreach (var category in m_Model.GetAllCategories()) 780 { 781 if (category.name == categoryName) 782 return category; 783 } 784 785 return null; 786 } 787 788 LabelData GetLabelData(string labelName) 789 { 790 if (string.IsNullOrEmpty(labelName)) 791 return null; 792 793 foreach (var label in m_Model.GetAllLabels()) 794 { 795 if (label.name == labelName) 796 return label; 797 } 798 799 return null; 800 } 801 802 static bool AreSequencesEqual(IList<string> first, IList<string> second) 803 { 804 if (first == null || second == null || first.Count != second.Count) 805 return false; 806 807 for (var i = 0; i < first.Count; i++) 808 { 809 if (first[i] != second[i]) 810 return false; 811 } 812 813 return true; 814 } 815 } 816}