3 name:
"Class Renaming Plugin",
4 description:
"Rename one or multiple classes in scripts and Prefabs\n[WARNING] will also rename Prefab/Component properties that match criteria",
5 wbModules: {
"ScriptEditor" },
6 awesomeFontCode: 0xF0EC)]
7class SCR_ClassRenamingPlugin : WorkbenchPlugin
13 [
Attribute(defvalue:
"1",
desc:
"Only rename classes that exist in script files and that can be modified\nIf unchecked, replace all words that match criteria",
category:
"Renaming")]
14 protected bool m_bOnlyRenameExistingEditableClasses;
16 [
Attribute(defvalue:
"1",
desc:
"Only rename words/classes that begin with a capital letter [A-Z]",
category:
"Renaming")]
17 protected bool m_bClassMustStartWithACapitalLetter;
19 [
Attribute(defvalue:
"1",
desc:
"Process .c files in the provided directories",
category:
"Renaming")]
20 protected bool m_bProcessScriptFiles;
22 [
Attribute(defvalue:
"1",
desc:
"Process .conf files in the provided directories",
category:
"Renaming")]
23 protected bool m_bProcessConfigFiles;
25 [
Attribute(defvalue:
"1",
desc:
"Process .et files in the provided directories",
category:
"Renaming")]
26 protected bool m_bProcessPrefabFiles;
28 [
Attribute(defvalue:
"1",
desc:
"Process .layer files in the provided directories",
category:
"Renaming")]
29 protected bool m_bProcessLayerFiles;
31 [
Attribute(defvalue:
"1",
desc:
"Go through all the steps without overwriting files",
category:
"Renaming")]
32 protected bool m_bDemoMode;
35 protected ref array<ref SCR_ClassRenamingParam> m_aParameters;
42 protected ref array<string> m_aScriptDirectories;
45 protected ref array<string> m_aConfigDirectories;
48 protected ref array<string> m_aPrefabDirectories;
51 protected ref array<string> m_aLayerDirectories;
53 protected int m_iMode = -1;
57 protected static const int THIS_FILE = 0;
58 protected static const int ALL_FILES = 1;
61 protected static const int MODE_PMATCH = 0;
62 protected static const int MODE_PREFIX = 1;
63 protected static const int MODE_SUFFIX = 2;
64 protected static const int MODE_MIDDLE = 3;
68 protected static const ref array<string> KEYWORDS = {
69 "auto",
"autoptr",
"class",
"const",
"continue",
70 "delete",
"else",
"event",
"extends",
"external",
71 "for",
"foreach",
"if",
"inout",
"modded",
72 "native",
"new",
"notnull",
"null",
"out",
73 "override",
"owned",
"private",
"protected",
"proto",
74 "ref",
"reference",
"return",
"sealed",
"static",
75 "super",
"switch",
"this",
"thread",
"typedef",
76 "vanilla",
"volatile",
"while",
82 CheckAndSetParameters();
84 if (Workbench.ScriptDialog(
85 "Class Renaming Plugin",
86 "[ PLEASE READ CAREFULLY ]\n\n" +
87 "This plugin renames classes in ALL LOADED ADDONS' scripts, config, Prefabs and terrain layers.\n\n" +
88 "It will also rename Prefab/Component properties that match criteria,\n" +
89 "so beware of same-name properties (e.g \"Damage\" could be both a class and a property).",
this) != 1)
92 if (!CheckAndSetParameters())
94 Print(
"Not running due to incorrect parameters - are there rules, and are they enabled?",
LogLevel.WARNING);
98 if (!m_bProcessScriptFiles && !m_bProcessConfigFiles && !m_bProcessPrefabFiles && !m_bProcessLayerFiles)
100 Print(
"Not running - please select at least one type of files to process",
LogLevel.NORMAL);
104 ScriptEditor scriptEditor = Workbench.GetModule(ScriptEditor);
111 array<string> addonFileSystems = SCR_AddonTool.GetAllAddonFileSystems();
112 array<string> scriptDirectories = {};
113 array<string> configDirectories = {};
114 array<string> prefabDirectories = {};
115 array<string> layerDirectories = {};
116 foreach (
string addonFileSystem : addonFileSystems)
119 foreach (
string path : m_aScriptDirectories)
121 scriptDirectories.Insert(addonFileSystem +
path);
124 if (m_bProcessConfigFiles)
126 foreach (
string path : m_aConfigDirectories)
128 configDirectories.Insert(addonFileSystem +
path);
132 if (m_bProcessPrefabFiles)
134 foreach (
string path : m_aPrefabDirectories)
136 prefabDirectories.Insert(addonFileSystem +
path);
140 if (m_bProcessLayerFiles)
142 foreach (
string path : m_aLayerDirectories)
144 layerDirectories.Insert(addonFileSystem +
path);
149 array<string> allScriptFilesAbsolutePaths;
151 if (m_iMode == THIS_FILE)
154 if (!scriptEditor.GetCurrentFile(filePath))
160 if (filePath == __FILE__)
162 Print(
"Cannot edit the plugin file itself",
LogLevel.NORMAL);
166 if (!Workbench.GetAbsolutePath(filePath, filePath,
true))
172 if (m_bOnlyRenameExistingEditableClasses)
173 classNames = GetClassesFromFiles({ filePath });
176 if (m_iMode == ALL_FILES)
178 if (m_bOnlyRenameExistingEditableClasses)
180 allScriptFilesAbsolutePaths = GetAllEditableScriptFilesAbsolutePaths(scriptDirectories);
181 if (allScriptFilesAbsolutePaths.IsEmpty())
183 Print(
"Cannot find any editable script file",
LogLevel.NORMAL);
187 classNames = GetClassesFromFiles(allScriptFilesAbsolutePaths);
196 array<ref SCR_ClassRenamingParam> fromToParams = GetFromToParams();
198 if (fromToParams.IsEmpty())
200 Print(
"No renaming rules provided - quitting",
LogLevel.NORMAL);
204 int scriptFilesEdited;
205 int configFilesEdited;
206 int prefabFilesEdited;
207 int layerFilesEdited;
208 if (m_bOnlyRenameExistingEditableClasses)
211 int fromToMapCount = fromToMap.Count();
212 if (fromToMapCount < 1)
218 if (fromToMapCount < 11)
220 Print(
"A total of " + fromToMapCount +
" classes were found:",
LogLevel.NORMAL);
221 foreach (
string key,
string value : fromToMap)
228 Print(
"A total of " + fromToMapCount +
" classes were found",
LogLevel.NORMAL);
231 if (m_bProcessScriptFiles)
233 if (!allScriptFilesAbsolutePaths)
234 allScriptFilesAbsolutePaths = GetAllEditableScriptFilesAbsolutePaths(scriptDirectories);
236 scriptFilesEdited = RenameInFiles(allScriptFilesAbsolutePaths, null, fromToMap,
"Processing %1 Script Files");
239 if (m_bProcessConfigFiles)
240 configFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(configDirectories,
"conf"), null, fromToMap,
"Processing %1 Config Files");
242 if (m_bProcessPrefabFiles)
243 prefabFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(prefabDirectories,
"et"), null, fromToMap,
"Processing %1 Prefab Files");
245 if (m_bProcessLayerFiles)
246 layerFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(layerDirectories,
"layer"), null, fromToMap,
"Processing %1 Layer Files");
250 if (m_bProcessScriptFiles)
252 if (!allScriptFilesAbsolutePaths)
253 allScriptFilesAbsolutePaths = GetAllEditableScriptFilesAbsolutePaths(scriptDirectories);
255 if (allScriptFilesAbsolutePaths.IsEmpty())
257 Print(
"Cannot find any editable script file",
LogLevel.NORMAL);
261 scriptFilesEdited = RenameInFiles(allScriptFilesAbsolutePaths, fromToParams, null,
"Processing %1 Script Files");
264 if (m_bProcessConfigFiles)
265 configFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(configDirectories,
"conf"), fromToParams, null,
"Processing %1 Config Files");
267 if (m_bProcessPrefabFiles)
268 prefabFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(prefabDirectories,
"et"), fromToParams, null,
"Processing %1 Prefab Files");
270 if (m_bProcessLayerFiles)
271 layerFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(layerDirectories,
"layer"), fromToParams, null,
"Processing %1 Layer Files");
278 demoPrefix =
"[DEMO] ";
281 if (scriptFilesEdited + configFilesEdited + prefabFilesEdited + layerFilesEdited < 1)
287 Print(scriptFilesEdited.ToString() +
" script files edited",
LogLevel.NORMAL);
288 Print(configFilesEdited.ToString() +
" config files edited",
LogLevel.NORMAL);
289 Print(prefabFilesEdited.ToString() +
" Prefab files edited",
LogLevel.NORMAL);
290 Print(layerFilesEdited.ToString() +
" layer files edited",
LogLevel.NORMAL);
293 demoPrefix +
"Renaming completed",
295 "%1Renamed all classes:\n%2 in script files.\n%3 in config files.\n%4 in Prefab files.\n%5 in layer files.\n\nYou may have to reopen Workbench to see the changes or to process another Prefab class rename.",
305 protected bool CheckAndSetParameters()
312 if (m_aParameters.IsEmpty())
314 SCR_ClassRenamingParam param =
new SCR_ClassRenamingParam();
315 param.m_bEnabled =
false;
316 param.m_sFrom =
"BIS_*";
317 param.m_sTo =
"SCR_";
318 m_aParameters.Insert(param);
323 bool goodParams =
false;
324 foreach (SCR_ClassRenamingParam param : m_aParameters)
326 param.m_sFrom.TrimInPlace();
327 param.m_sTo.TrimInPlace();
328 if (param.m_bEnabled && param.m_sFrom)
336 if (!m_aScriptDirectories)
337 m_aScriptDirectories = {};
339 for (
int i = m_aScriptDirectories.Count() - 1; i >= 0; --i)
342 m_aScriptDirectories.Remove(i);
345 if (m_aScriptDirectories.IsEmpty())
346 m_aScriptDirectories.Insert(
"scripts/");
348 for (
int i = m_aPrefabDirectories.Count() - 1; i >= 0; --i)
351 m_aPrefabDirectories.Remove(i);
354 if (!m_aPrefabDirectories || m_aPrefabDirectories.IsEmpty())
355 m_aPrefabDirectories = {
"PrefabLibrary/",
"Prefabs/",
"PrefabsEditable/" };
363 array<string> GetAllEditableScriptFilesAbsolutePaths(notnull array<string> scriptDirectories)
365 array<string> result = {};
367 foreach (
string scriptDir : scriptDirectories)
373 result.Insert(absolutePath);
384 protected array<string> GetAllEditableFilesAbsolutePaths(notnull array<string> directories,
string extension)
386 array<string> result = {};
388 foreach (
string directory : directories)
392 if (Workbench.GetAbsolutePath(
resourceName.GetPath(), absolutePath,
true))
393 result.Insert(absolutePath);
404 protected map<string, string> GetClassesFromFiles(notnull array<string> absoluteScriptFilePaths)
407 foreach (
ResourceName absoluteScriptFilePath : absoluteScriptFilePaths)
409 foreach (
string fileClass : GetClassesFromFile(absoluteScriptFilePath))
411 result.Insert(fileClass, absoluteScriptFilePath);
421 protected array<string> GetClassesFromFile(
string absoluteFilePath)
427 array<string> result = {};
428 foreach (
string line : lines)
430 int length = line.Length();
434 if (!line.StartsWith(
"class ") && !line.StartsWith(
"class\t"))
439 for (
int i = 6; i < length; i++)
442 if (c ==
" " || c ==
"\t" || c ==
":" || c ==
"/")
450 if (!m_bClassMustStartWithACapitalLetter ||
SCR_StringHelper.UPPERCASE.Contains(className[0]))
451 result.Insert(className);
461 array<ref SCR_ClassRenamingParam> GetFromToParams()
463 array<ref SCR_ClassRenamingParam> result = {};
465 SCR_ClassRenamingParam newParam;
466 foreach (SCR_ClassRenamingParam param : m_aParameters)
468 if (!param.m_bEnabled)
471 newParam =
new SCR_ClassRenamingParam();
477 if (startsWithStar && endsWithStar)
478 newParam.m_iMode = MODE_MIDDLE;
479 else if (startsWithStar)
480 newParam.m_iMode = MODE_SUFFIX;
481 else if (endsWithStar)
482 newParam.m_iMode = MODE_PREFIX;
484 newParam.m_iMode = MODE_PMATCH;
486 newParam.m_sFrom = param.m_sFrom;
488 string tmp = param.m_sFrom;
490 newParam.m_sFrom = tmp;
491 newParam.m_sFrom.TrimInPlace();
493 if (newParam.m_sFrom)
495 newParam.m_sTo = param.m_sTo;
496 newParam.m_sTo.TrimInPlace();
497 if (newParam.m_sTo || newParam.m_iMode != MODE_PMATCH)
498 result.Insert(newParam);
510 array<ref SCR_ClassRenamingParam> newParams = GetFromToParams();
512 if (newParams.IsEmpty())
517 foreach (
string className,
string fp : classFiles)
519 foreach (SCR_ClassRenamingParam param : newParams)
521 if (param.m_iMode == MODE_PMATCH)
523 if (className == param.m_sFrom)
525 result.Insert(className, param.m_sTo);
530 if (param.m_iMode == MODE_PREFIX)
532 if (className.StartsWith(param.m_sFrom) && !className.EndsWith(param.m_sFrom))
534 string newClassName = param.m_sTo + className.Substring(param.m_sFrom.Length(), className.Length() - param.m_sFrom.Length());
535 result.Insert(className, newClassName);
540 if (param.m_iMode == MODE_SUFFIX)
542 if (className.EndsWith(param.m_sFrom) && !className.StartsWith(param.m_sFrom))
544 string newClassName = className.Substring(0, className.LastIndexOf(param.m_sFrom)) + param.m_sTo;
545 result.Insert(className, newClassName);
550 if (param.m_iMode == MODE_MIDDLE)
552 if (className.Contains(param.m_sFrom) &&
553 !className.StartsWith(param.m_sFrom) &&
554 !className.EndsWith(param.m_sFrom))
556 int index = className.IndexOf(param.m_sFrom);
557 string newClassName = className.Substring(0,
index) + param.m_sTo + className.Substring(
index + param.m_sFrom.Length(), className.Length() -
index + param.m_sFrom.Length());
558 result.Insert(className, newClassName);
575 int RenameInFiles(notnull array<string> absolutePaths, array<ref SCR_ClassRenamingParam> fromToParams,
map<string, string> fromToMap,
string progressBarText =
"Processing %1 files")
577 bool isParams = fromToParams != null;
578 if (!isParams && !fromToMap)
580 Print(
"RenameInFiles scripting error - provide fromTo info",
LogLevel.ERROR);
584 float countF = absolutePaths.Count();
590 WBModuleDef workbenchModule = Workbench.GetModule(ScriptEditor);
591 progressBarText =
string.Format(progressBarText, countF);
594 WBProgressDialog progressDialog =
new WBProgressDialog(progressBarText, workbenchModule);
595 progressDialog.SetProgress(0);
596 float currProgress, prevProgress;
597 foreach (
int i,
string scriptFile : absolutePaths)
599 currProgress = i / countF;
600 if (currProgress - prevProgress >= 0.01)
602 progressDialog.SetProgress(currProgress);
604 prevProgress = currProgress;
616 fileResult = RenameInLines(lines, fromToParams, null);
618 fileResult = RenameInLines(lines, null, fromToMap);
622 if (lines[lines.Count() - 1].Trim() !=
string.Empty)
623 lines.Insert(
string.Empty);
640 protected int RenameInLines(out notnull array<string> lines, array<ref SCR_ClassRenamingParam> fromToParams,
map<string, string> fromToMap)
642 bool isParams = fromToParams != null;
643 if (!isParams && !fromToMap)
645 Print(
"RenameInLines scripting error - provide fromTo info",
LogLevel.ERROR);
651 foreach (
int i,
string line : lines)
655 for (
int j, countJ = line.Length(); j < countJ; ++j)
658 bool isClassChar = CLASS_CHARS.Contains(c);
659 bool isLastChar = j == countJ - 1;
662 if (CLASS_CHARS.Contains(c))
668 if (KEYWORDS.Contains(word))
677 newClassName = GetNewClassNameIfMatch(word, fromToParams);
679 newClassName = fromToMap.Get(word);
683 newLine += newClassName + c;
708 newClassName = GetNewClassNameIfMatch(word, fromToParams);
710 newClassName = fromToMap.Get(word);
713 newLine += newClassName;
729 string GetNewClassNameIfMatch(
string className, notnull array<ref SCR_ClassRenamingParam> fromToParams)
732 foreach (SCR_ClassRenamingParam param : fromToParams)
734 if (param.m_iMode == MODE_PMATCH)
736 if (className == param.m_sFrom)
738 result = param.m_sTo;
743 if (param.m_iMode == MODE_PREFIX)
745 if (className.StartsWith(param.m_sFrom) && !className.EndsWith(param.m_sFrom))
747 result = param.m_sTo + className.Substring(param.m_sFrom.Length(), className.Length() - param.m_sFrom.Length());
752 if (param.m_iMode == MODE_SUFFIX)
754 if (className.EndsWith(param.m_sFrom) && !className.StartsWith(param.m_sFrom))
756 result = className.Substring(0, className.LastIndexOf(param.m_sFrom)) + param.m_sTo;
761 if (param.m_iMode == MODE_MIDDLE)
763 if (className.Contains(param.m_sFrom) &&
764 !className.StartsWith(param.m_sFrom) &&
765 !className.EndsWith(param.m_sFrom))
767 int index = className.IndexOf(param.m_sFrom);
768 result = className.Substring(0,
index) + param.m_sTo + className.Substring(
index + param.m_sFrom.Length(), className.Length() -
index + param.m_sFrom.Length());
805class SCR_ClassRenamingParam
807 [
Attribute(defvalue:
"1",
desc:
"Allow this replacement to happen")]
810 [
Attribute(
desc:
"What class name part to rename (case-sensitive). '*' works as a (limited) wildcard:\n- abc = exact match\n- abc* = prefix\n- *abc = suffix\n- *abc* = middle (needs a before AND an after)")]
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
ResourceName resourceName
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
allow to define multiple fields (string or ResourceName) - up to 5 elements
static bool WriteFileContent(string filePath, notnull array< string > lines)
static array< string > ReadFileContent(string filePath, bool printWarning=true)
static bool IsEmptyOrWhiteSpace(string input)
static array< ResourceName > SearchWorkbenchResources(array< string > fileExtensions=null, array< string > searchStrArray=null, string rootPath="", bool recursive=true)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
SCR_FieldOfViewSettings Attribute