예제 #1
0
        /// <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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        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);
        }
예제 #5
0
            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);
            }
예제 #6
0
        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();
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
            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);
            }
예제 #10
0
        /// <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);
        }
예제 #11
0
        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);
        }