UnityEssentials
Small but useful tools and features for Unity
Assets.cs
Go to the documentation of this file.
1 #if UNITY_EDITOR
2 using System;
3 using System.IO;
4 using System.Text.RegularExpressions;
5 using UnityEditor;
6 using UnityEngine;
7 
8 namespace Essentials.EditorTweaks
9 {
13  public class Assets
14  {
15 
16  #region ClassRenaming
17 
18  // Original author of the code: Pellegrino ~thp~ Principe (https://github.com/thp1972)
19  // Original code: https://github.com/thp1972/MyUnityScripts/blob/master/FixClassName/Editor/com.pellegrinoprincipe/FixClassName.cs
20  // The code has been modified to increase consistency, usability and to reduce possible errors.
21 
25  [MenuItem("Assets/Update class name to match file name", false, 19)]
26  private static void UpdateClassNameToMatchFile()
27  {
28 
29  MonoScript[] scripts = Selection.GetFiltered<MonoScript>(SelectionMode.Assets);
30 
31  if (scripts.IsNullOrEmpty() || scripts.Length != 1)
32  {
33  Debug.LogError("One script file must be selected to update the class contained in it.");
34  return;
35  }
36 
37  MonoScript script = scripts[0];
38  int selectedScriptID = script.GetInstanceID();
39 
40  string newClassName = script.name;
41 
42  ReplaceClassName(newClassName, AssetDatabase.GetAssetPath(selectedScriptID));
43  }
44 
49  [MenuItem("Assets/Update class name to match file name", true, 19)]
50  private static bool IsSingleScriptSelected()
51  {
52  // enable the menu item only if a script file is selected
53  MonoScript[] scripts = Selection.GetFiltered<MonoScript>(SelectionMode.Assets);
54 
55  // Only one selected
56  return !scripts.IsNullOrEmpty() && scripts.Length == 1;
57  }
58 
64  private static void ReplaceClassName(string newClassName, string scriptPath)
65  {
66  try
67  {
68  string[] fileText = File.ReadAllLines(scriptPath);
69 
70  for (int i = 0; i < fileText.Length; i++)
71  {
72  // make the refactoring only if the class name is different
73  if (!Regex.IsMatch(fileText[i], @"\bclass\b"))
74  continue;
75 
76  if (Regex.IsMatch(fileText[i], "\\b" + newClassName + "\\b"))
77  {
78  Debug.Log($"Class in file '{scriptPath}' already has the same name as the file ('{newClassName}').");
79  return; // skip if the name is the same
80  }
81 
82  // match the identifier of a class so it can be replaced by 'className'
83  // we use a Positive Lookbehind...
84  const string regexPattern = @"(?<=class )\w+";
85  fileText[i] = Regex.Replace(fileText[i], regexPattern, newClassName);
86  File.WriteAllLines(scriptPath, fileText);
87 
88  AssetDatabase.Refresh(ImportAssetOptions.Default);
89  Debug.Log($"Class in file '{scriptPath}' has been successfully renamed to '{newClassName}'.");
90  }
91  }
92  catch (Exception exception)
93  {
94  Debug.Log($"Something went wrong: {exception.Message}");
95  }
96  }
97 
98  #endregion
99 
100  #region DuplicateAsset
101 
105  [MenuItem("Assets/Duplicate", false, 19)] // No shortcut is set because the functionality calls the Command "Edit/Duplicate" that already has cone signed
106  private static void DuplicateAsset()
107  {
108  EditorWindow.focusedWindow.SendEvent (EditorGUIUtility.CommandEvent ("Duplicate"));
109  }
110 
115  [MenuItem("Assets/Duplicate", true, 19)] // No shortcut is set because the functionality calls the Command "Edit/Duplicate" that already has cone signed
116  private static bool AreAssetsSelected()
117  {
118  return Selection.assetGUIDs.Length > 0;
119  }
120 
121  #endregion
122 
123  }
124 }
125 #endif