protected EntityHierarchyItemViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, [NotNull] IEnumerable <EntityDesign> childEntities) : base(editor, asset) { if (childEntities == null) { throw new ArgumentNullException(nameof(childEntities)); } // note: we want to ignore case and diacritics (e.g. accentuation) when sorting the folders Folders = new AutoUpdatingSortedObservableCollection <EntityFolderViewModel>((x, y) => string.Compare(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase)); // Note: we make sure that empty folders and null folders are grouped together // TODO: implement a more robust folder grouping method that trims, etc. // TODO: also ensure that empty folder are serialized as null (or vice-versa) to avoid this kind of issue foreach (var folderGroup in childEntities.GroupBy(x => !string.IsNullOrWhiteSpace(x.Folder) ? x.Folder : null).OrderBy(x => x.Key)) { if (!EntityFolderViewModel.GenerateFolder(this, folderGroup.Key, folderGroup)) { foreach (var child in folderGroup) { var viewModel = (EntityViewModel)Editor.CreatePartViewModel(Asset, child); subEntities.Add(viewModel); } } } AddItems(Folders); AddItems(subEntities); // We register the collection changed handler after having added already-existing children Folders.CollectionChanged += FolderCollectionChanged; subEntities.CollectionChanged += SubEntityCollectionChanged; // Add policies for adding/inserting assets // TODO: make it work with plugins (discovery, registration, override...) addAssetPolicies = new List <IAddAssetPolicy> { new AddModelAssetPolicy <ModelAsset>(), new AddModelAssetPolicy <PrefabModelAsset>(), new AddModelAssetPolicy <ProceduralModelAsset>(), new AddPrefabAssetPolicy(), new AddSceneAssetPolicy(), new AddScriptSourceFileAssetPolicy(), new AddSpriteSheetAssetPolicy(), new AddSpriteStudioModelAssetPolicy(), new AddTextureAssetPolicy(), new AddVideoAssetPolicy(), new AddUIPageAssetPolicy(), }; }
public static bool GenerateFolder([NotNull] EntityHierarchyItemViewModel parent, string path, [NotNull] IEnumerable <EntityDesign> entities) { if (parent == null) { throw new ArgumentNullException(nameof(parent)); } if (parent is EntityFolderViewModel) { return(false); } // Trim separator in malformed path path = path?.Trim(FolderSeparator); if (string.IsNullOrWhiteSpace(path)) { return(false); } var folders = path.Split(new[] { FolderSeparator }, StringSplitOptions.RemoveEmptyEntries); var folderCollection = parent.Folders; EntityFolderViewModel subFolder; foreach (var folder in folders.Take(folders.Length - 1)) { subFolder = folderCollection.FirstOrDefault(x => string.Equals(x.Name, folder, FolderCase)); if (subFolder == null) { subFolder = new EntityFolderViewModel(parent.Editor, parent.Asset, folder, Enumerable.Empty <EntityDesign>()); parent.Folders.Add(subFolder); } folderCollection = subFolder.Folders; parent = subFolder; } subFolder = new EntityFolderViewModel(parent.Editor, parent.Asset, folders[folders.Length - 1], entities); parent.Folders.Add(subFolder); return(true); }