/// <summary> /// Gets a preview of the Bulk Rename that shows the rename steps that will be applied /// to each object, if this renamer is used to rename the objects. /// </summary> /// <returns>The results preview.</returns> /// <param name="objectsToRename">Objects to rename.</param> public BulkRenamePreview GetBulkRenamePreview(List <UnityEngine.Object> objectsToRename) { var previews = new RenamePreview[objectsToRename.Count]; for (int i = 0; i < objectsToRename.Count; ++i) { var singlePreview = new RenamePreview( objectsToRename[i], this.operationSequence.GetRenamePreview(objectsToRename[i].name, i)); previews[i] = singlePreview; } // First collect all assets in directories of preview objects into the assetCache. for (int i = 0; i < objectsToRename.Count; ++i) { var obj = objectsToRename[i]; if (obj.IsAsset()) { CacheAsestsInSameDirectoryAsAsset(obj, ref this.assetCache); } } var renameResultPreviews = new BulkRenamePreview(previews, this.assetCache); return(renameResultPreviews); }
private void DrawPreviewPanel(Rect previewPanelRect, BulkRenamePreview bulkRenamePreview) { // PreviewPanel goes null when we recompile while the window is open if (this.previewPanel == null) { this.InitializePreviewPanel(); } this.previewPanel.NumPreviouslyRenamedObjects = this.NumPreviouslyRenamedObjects; // If we aren't doing stepwise preview, send an invalid prefix so that the panel only renders before and after var previewIndex = this.IsShowingPreviewSteps ? this.FocusedRenameOpIndex : -1; this.previewPanel.PreviewStepIndexToShow = previewIndex; MulliganRenamerPreviewPanel.ColumnStyle columnStyle = MulliganRenamerPreviewPanel.ColumnStyle.OriginalAndFinalOnly; if (this.NumRenameOperations <= 1) { columnStyle = MulliganRenamerPreviewPanel.ColumnStyle.StepwiseHideFinal; } else if (this.IsShowingPreviewSteps) { columnStyle = MulliganRenamerPreviewPanel.ColumnStyle.Stepwise; } else { columnStyle = MulliganRenamerPreviewPanel.ColumnStyle.OriginalAndFinalOnly; } this.previewPanel.ColumnsToShow = columnStyle; this.previewPanel.DisableAddSelectedObjectsButton = this.GetValidSelectedObjects().Count == 0; this.previewPanelScrollPosition = this.previewPanel.Draw(previewPanelRect, this.previewPanelScrollPosition, bulkRenamePreview); }
/// <summary> /// Gets a preview of the Bulk Rename that shows the rename steps that will be applied /// to each object, if this renamer is used to rename the objects. /// </summary> /// <returns>The results preview.</returns> /// <param name="objectsToRename">Objects to rename.</param> public BulkRenamePreview GetBulkRenamePreview(List <UnityEngine.Object> objectsToRename) { var renameResultPreviews = new BulkRenamePreview(); for (int i = 0; i < objectsToRename.Count; ++i) { var singlePreview = new RenamePreview( objectsToRename[i], this.operationSequence.GetRenamePreview(objectsToRename[i].name, i)); renameResultPreviews.AddEntry(singlePreview); } var previewsWithDuplicateNames = GetPreviewsWithDuplicateNames(renameResultPreviews, ref this.assetCache); foreach (var preview in previewsWithDuplicateNames) { preview.WarningMessage = "New name matches an existing file or another renamed object."; } var previewsWithInvalidCharacters = GetPreviewsWithInvalidCharacters(renameResultPreviews); foreach (var preview in previewsWithInvalidCharacters) { preview.WarningMessage = "Name includes invalid characters (usually symbols such as ?.,)."; } var previewsEmptyNames = GetPreviewsWithEmptyNames(renameResultPreviews); foreach (var preview in previewsEmptyNames) { preview.WarningMessage = "Asset has blank name."; } return(renameResultPreviews); }
private static List <RenamePreview> GetPreviewsWithInvalidCharacters(BulkRenamePreview preview) { var invalidCharacters = new char[] { '?', '.', '/', '<', '>', '\\', '|', '*', ':', '"' }; var problemPreviews = new List <RenamePreview>(); for (int i = 0; i < preview.NumObjects; ++i) { var previewForObject = preview.GetPreviewAtIndex(i); var thisObject = previewForObject.ObjectToRename; if (!AssetDatabase.Contains(thisObject)) { // Scene objects can have symbols continue; } var thisResult = previewForObject.RenameResultSequence; foreach (var invalidCharacter in invalidCharacters) { if (thisResult.NewName.Contains(invalidCharacter)) { problemPreviews.Add(previewForObject); break; } } } return(problemPreviews); }
public static PreviewPanelContents CreatePreviewContentsForObjects(BulkRenamePreview preview) { var previewPanelContents = new PreviewPanelContents(); previewPanelContents.PreviewRowInfos = new PreviewRowModel[preview.NumObjects]; for (int i = 0; i < preview.NumObjects; ++i) { var info = new PreviewRowModel(); var previewForIndex = preview.GetPreviewAtIndex(i); info.RenameResultSequence = previewForIndex.RenameResultSequence; info.Icon = previewForIndex.ObjectToRename.GetEditorIcon(); if (previewForIndex.HasWarnings) { info.WarningIcon = (Texture2D)EditorGUIUtility.Load("icons/console.warnicon.sml.png"); info.WarningMessage = previewForIndex.WarningMessage; } else { info.WarningIcon = null; info.WarningMessage = string.Empty; } previewPanelContents.PreviewRowInfos[i] = info; } float paddingScaleForBold = 1.11f; previewPanelContents.LongestOriginalNameWidth = 0.0f; previewPanelContents.LongestNewNameWidth = 0.0f; foreach (var previewRowInfo in previewPanelContents.PreviewRowInfos) { float originalNameWidth = GUI.skin.label.CalcSize( new GUIContent(previewRowInfo.RenameResultSequence.OriginalName)).x *paddingScaleForBold; if (originalNameWidth > previewPanelContents.LongestOriginalNameWidth) { previewPanelContents.LongestOriginalNameWidth = originalNameWidth; } float newNameWidth = GUI.skin.label.CalcSize( new GUIContent(previewRowInfo.RenameResultSequence.NewName)).x *paddingScaleForBold; if (newNameWidth > previewPanelContents.LongestNewNameWidth) { previewPanelContents.LongestNewNameWidth = newNameWidth; } } previewPanelContents.LongestOriginalNameWidth = Mathf.Max(MinColumnWidth, previewPanelContents.LongestOriginalNameWidth); previewPanelContents.LongestNewNameWidth = Mathf.Max(MinColumnWidth, previewPanelContents.LongestNewNameWidth); previewPanelContents.LongestFinalNameWidth = previewPanelContents.LongestNewNameWidth; return(previewPanelContents); }
private void DrawPreviewPanel(BulkRenamePreview preview) { EditorGUILayout.BeginVertical(); this.previewPanelScrollPosition = EditorGUILayout.BeginScrollView(this.previewPanelScrollPosition, this.guiStyles.PreviewScroll); bool panelIsEmpty = this.ObjectsToRename.Count == 0; if (panelIsEmpty) { this.DrawPreviewPanelContentsEmpty(); } else { var previewContents = PreviewPanelContents.CreatePreviewContentsForObjects(preview); this.DrawPreviewPanelContentsWithItems(previewContents); } EditorGUILayout.EndScrollView(); // GetLastRect only works during Repaint, so we cache it off during Repaint and use the cached value. if (Event.current.type == EventType.Repaint) { this.scrollViewClippingRect = GUILayoutUtility.GetLastRect(); } var draggedObjects = this.GetDraggedObjectsOverRect(this.scrollViewClippingRect); if (draggedObjects.Count > 0) { this.AddObjectsToRename(draggedObjects); this.ScrollPreviewPanelToBottom(); } if (!panelIsEmpty) { EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Remove All")) { this.ObjectsToRename.Clear(); } this.DrawAddSelectedObjectsButton(); EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); }
private static void CacheAssetsInSameDirectories(BulkRenamePreview preview, ref AssetCache assetCache) { for (int i = 0; i < preview.NumObjects; ++i) { var previewForObject = preview.GetPreviewAtIndex(i); var thisObject = previewForObject.ObjectToRename; if (!thisObject.IsAsset()) { // Scene objects can be named the same thing, so skip these continue; } var assetDirectory = AssetDatabaseUtility.GetAssetPathDirectory(thisObject); assetCache.LoadAssetsInAssetDirectory(assetDirectory); } }
private static List <RenamePreview> GetPreviewsWithEmptyNames(BulkRenamePreview preview) { var problemPreviews = new List <RenamePreview>(); for (int i = 0; i < preview.NumObjects; ++i) { var previewForObject = preview.GetPreviewAtIndex(i); var thisObject = previewForObject.ObjectToRename; if (!AssetDatabase.Contains(thisObject)) { // Scene objects can be empty names... even though that's a terrible idea. But still, skip them. continue; } var thisResult = previewForObject.RenameResultSequence; if (string.IsNullOrEmpty(thisResult.NewName)) { problemPreviews.Add(previewForObject); } } return(problemPreviews); }
public static PreviewPanelContents CreatePreviewContentsForObjects( BulkRenamePreview preview, int firstPreviewIndex, int numObjectsToShow, int stepIndex, Color deletionColor, Color insertionColor) { var previewPanelContents = new PreviewPanelContents(); var numVisibleObjects = Mathf.Min(numObjectsToShow, preview.NumObjects); previewPanelContents.PreviewRowInfos = new PreviewRowModel[numVisibleObjects]; for (int j = 0; j < numVisibleObjects && j < preview.NumObjects - firstPreviewIndex; ++j) { var info = new PreviewRowModel(); var indexOfVisibleObject = firstPreviewIndex + j; var previewForIndex = preview.GetPreviewAtIndex(indexOfVisibleObject); var originalName = stepIndex >= 0 && stepIndex < preview.NumSteps ? previewForIndex.RenameResultSequence.GetNameBeforeAtStep(stepIndex, deletionColor) : previewForIndex.RenameResultSequence.OriginalName; info.NameBeforeStep = originalName; var nameAtStep = stepIndex >= 0 && stepIndex < preview.NumSteps ? previewForIndex.RenameResultSequence.GetNewNameAtStep(stepIndex, insertionColor) : previewForIndex.RenameResultSequence.NewName; info.NameAtStep = nameAtStep; info.FinalName = previewForIndex.RenameResultSequence.NewName; info.Icon = previewForIndex.ObjectToRename.GetEditorIcon(); if (previewForIndex.HasWarnings || preview.WillRenameCollideWithExistingAsset(previewForIndex)) { info.WarningIcon = (Texture2D)EditorGUIUtility.Load("icons/console.warnicon.sml.png"); if (previewForIndex.HasWarnings) { info.WarningMessage = GetWarningMessageForRenamePreview(previewForIndex); } else { info.WarningMessage = "New name matches an existing file or another renamed object."; } } else { info.WarningIcon = null; info.WarningMessage = string.Empty; } info.IndexInPreview = indexOfVisibleObject; previewPanelContents.PreviewRowInfos[j] = info; } // Note that CalcSize is very slow, so it is a problem to do it to the entire list of objects... // For now we only measure the ones that are visible. It causes the columns to resize as you scroll, // but that's not the worst. float paddingScaleForBold = 1.11f; previewPanelContents.LongestOriginalNameWidth = 0.0f; previewPanelContents.LongestNewNameWidth = 0.0f; foreach (var previewRowInfo in previewPanelContents.PreviewRowInfos) { var labelStyle = GUI.skin.label; labelStyle.richText = true; float originalNameWidth = labelStyle.CalcSize( new GUIContent(previewRowInfo.NameBeforeStep)).x *paddingScaleForBold; if (originalNameWidth > previewPanelContents.LongestOriginalNameWidth) { previewPanelContents.LongestOriginalNameWidth = originalNameWidth; } float newNameWidth = labelStyle.CalcSize( new GUIContent(previewRowInfo.NameAtStep)).x *paddingScaleForBold; if (newNameWidth > previewPanelContents.LongestNewNameWidth) { previewPanelContents.LongestNewNameWidth = newNameWidth; } } previewPanelContents.LongestOriginalNameWidth = Mathf.Max(MinColumnWidth, previewPanelContents.LongestOriginalNameWidth); previewPanelContents.LongestNewNameWidth = Mathf.Max(MinColumnWidth, previewPanelContents.LongestNewNameWidth); previewPanelContents.LongestFinalNameWidth = previewPanelContents.LongestNewNameWidth; previewPanelContents.TotalNumRows = preview.NumObjects; return(previewPanelContents); }
/// <summary> /// Draw the specified BulkRenamePreview in the given rect, and returns the new scroll position. /// </summary> /// <returns>The new scroll position.</returns> /// <param name="previewPanelRect">Preview panel rect.</param> /// <param name="previewPanelScrollPosition">Preview panel scroll position.</param> /// <param name="preview">Preview to draw.</param> public Vector2 Draw(Rect previewPanelRect, Vector2 previewPanelScrollPosition, BulkRenamePreview preview) { var spaceBetweenFooterAndScrollview = 2.0f; var panelFooterToolbar = new Rect(previewPanelRect); panelFooterToolbar.height = EditorGUIUtility.singleLineHeight; panelFooterToolbar.y += (previewPanelRect.height + spaceBetweenFooterAndScrollview) - panelFooterToolbar.height; var scrollViewRect = new Rect(previewPanelRect); scrollViewRect.height -= (panelFooterToolbar.height + spaceBetweenFooterAndScrollview); GUI.Box(scrollViewRect, "", this.guiStyles.PreviewScroll); var newScrollPosition = previewPanelScrollPosition; if (preview.NumObjects == 0) { this.DrawPreviewPanelContentsEmpty(scrollViewRect); } else { var scrollLayout = new PreviewPanelLayout(scrollViewRect); // Show the one that doesn't quite fit by subtracting one var firstItemIndex = Mathf.Max(Mathf.FloorToInt(previewPanelScrollPosition.y / PreviewRowHeight) - 1, 0); // Add one for the one that's off screen above, and one for the one below. I think? var numItems = Mathf.CeilToInt(scrollLayout.ScrollRect.height / PreviewRowHeight) + 2; var previewContents = PreviewPanelContents.CreatePreviewContentsForObjects( preview, firstItemIndex, numItems, this.PreviewStepIndexToShow, this.guiStyles.DeletionTextColor, this.guiStyles.InsertionTextColor); bool shouldShowSecondColumn = this.ColumnsToShow != ColumnStyle.OriginalAndFinalOnly; bool shouldShowThirdColumn = this.ColumnsToShow != ColumnStyle.StepwiseHideFinal; var contentsLayout = new PreviewPanelContentsLayout( scrollLayout.ScrollRect, previewContents, shouldShowSecondColumn, shouldShowThirdColumn); newScrollPosition = this.DrawPreviewPanelContentsWithItems( scrollLayout, contentsLayout, previewPanelScrollPosition, previewContents, this.PreviewStepIndexToShow, shouldShowSecondColumn, shouldShowThirdColumn); var buttonSpacing = 2.0f; var rightPadding = 2.0f; var addSelectedObjectsButtonRect = new Rect(panelFooterToolbar); addSelectedObjectsButtonRect.width = 150.0f; addSelectedObjectsButtonRect.x = panelFooterToolbar.xMax - rightPadding - addSelectedObjectsButtonRect.width; var removeAllButtonRect = new Rect(addSelectedObjectsButtonRect); removeAllButtonRect.width = 100.0f; removeAllButtonRect.x -= (removeAllButtonRect.width + buttonSpacing); if (GUI.Button(removeAllButtonRect, "Remove All")) { if (this.RemoveAllClicked != null) { this.RemoveAllClicked.Invoke(); } } this.DrawAddSelectedObjectsButton(addSelectedObjectsButtonRect); if (!scrollLayout.ContentsFitWithoutAnyScrolling(contentsLayout)) { var hintRect = new Rect(scrollViewRect); hintRect.height = EditorGUIUtility.singleLineHeight * 2.0f; hintRect.y += scrollViewRect.height; hintRect.width = scrollViewRect.width - addSelectedObjectsButtonRect.width - removeAllButtonRect.width - buttonSpacing; EditorGUI.LabelField(hintRect, this.guiContents.DropPromptHint, this.guiStyles.DropPromptHint); } } var draggedObjects = this.GetDraggedObjectsOverRect(scrollViewRect); if (draggedObjects.Count > 0) { if (this.ObjectsDropped != null) { this.ObjectsDropped.Invoke(draggedObjects.ToArray()); } } return(newScrollPosition); }
private static List <RenamePreview> GetPreviewsWithDuplicateNames(BulkRenamePreview preview, ref AssetCache assetCache) { // First collect all assets in directories of preview objects into the assetCache. CacheAssetsInSameDirectories(preview, ref assetCache); var assetPreviews = new List <RenamePreview>(); for (int i = 0; i < preview.NumObjects; ++i) { var previewForObject = preview.GetPreviewAtIndex(i); if (previewForObject.ObjectToRename.IsAsset()) { assetPreviews.Add(previewForObject); } } // Get all the cached file paths, but remove any that are in the preview // because those names could be different. We want to test that NEW names // don't collide with existing assets. HashSet <string> allFinalFilePaths = assetCache.GetAllPathsHashed(); foreach (var assetPreview in assetPreviews) { var thisObject = assetPreview.ObjectToRename; var assetPath = AssetDatabaseUtility.GetAssetPathWithSubAsset(thisObject); allFinalFilePaths.Remove(assetPath); } // Now hash the new names and check if they collide with the existing assets var problemPreviews = new List <RenamePreview>(); var unchangedAssetPreviews = new List <RenamePreview>(); var changedAssetPreviews = new List <RenamePreview>(); // Separate unchangedAssets from changedAsests foreach (var assetPreview in assetPreviews) { var thisObject = assetPreview.ObjectToRename; var thisResult = assetPreview.RenameResultSequence; if (thisResult.NewName == thisResult.OriginalName) { unchangedAssetPreviews.Add(assetPreview); } else { changedAssetPreviews.Add(assetPreview); } } // First add all the unchanged results, so that we collide on the // first time adding new names. This fixes an issue where // you'd rename one object which now matches a second, but the second gets // the warning instead of the first. var previewsSorted = new List <RenamePreview>(); previewsSorted.AddRange(unchangedAssetPreviews); previewsSorted.AddRange(changedAssetPreviews); foreach (var renamePreview in previewsSorted) { var resultingPath = renamePreview.GetResultingPath(); if (allFinalFilePaths.Contains(resultingPath)) { problemPreviews.Add(renamePreview); } else { allFinalFilePaths.Add(resultingPath); } } return(problemPreviews); }