Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ClassRenamingPlugin.c
Go to the documentation of this file.
1#ifdef WORKBENCH
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
8{
9 /*
10 Renaming
11 */
12
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;
15
16 [Attribute(defvalue: "1", desc: "Only rename words/classes that begin with a capital letter [A-Z]", category: "Renaming")]
17 protected bool m_bClassMustStartWithACapitalLetter;
18
19 [Attribute(defvalue: "1", desc: "Process .c files in the provided directories", category: "Renaming")]
20 protected bool m_bProcessScriptFiles;
21
22 [Attribute(defvalue: "1", desc: "Process .conf files in the provided directories", category: "Renaming")]
23 protected bool m_bProcessConfigFiles;
24
25 [Attribute(defvalue: "1", desc: "Process .et files in the provided directories", category: "Renaming")]
26 protected bool m_bProcessPrefabFiles;
27
28 [Attribute(defvalue: "1", desc: "Process .layer files in the provided directories", category: "Renaming")]
29 protected bool m_bProcessLayerFiles;
30
31 [Attribute(defvalue: "1", desc: "Go through all the steps without overwriting files", category: "Renaming")]
32 protected bool m_bDemoMode;
33
34 [Attribute(desc: "Replacement parameters - the first matching rule applies", category: "Renaming")]
35 protected ref array<ref SCR_ClassRenamingParam> m_aParameters;
36
37 /*
38 Directories
39 */
40
41 [Attribute(defvalue: "scripts/", category: "Directories")]
42 protected ref array<string> m_aScriptDirectories;
43
44 [Attribute(defvalue: "Configs/", category: "Directories")]
45 protected ref array<string> m_aConfigDirectories;
46
47 [Attribute(defvalue: "Prefabs/", category: "Directories")]
48 protected ref array<string> m_aPrefabDirectories;
49
50 [Attribute(defvalue: "worlds/", category: "Directories")]
51 protected ref array<string> m_aLayerDirectories;
52
53 protected int m_iMode = -1;
54 protected ref map<string, string> m_mClassesLocation;
55
56 // modes
57 protected static const int THIS_FILE = 0;
58 protected static const int ALL_FILES = 1;
59
60 // replacement modes
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;
65
66 // but still cannot start with number
67 protected static const string CLASS_CHARS = SCR_StringHelper.LETTERS + SCR_StringHelper.DIGITS + SCR_StringHelper.UNDERSCORE;
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",
77 };
78
79 //------------------------------------------------------------------------------------------------
80 override void Run()
81 {
82 CheckAndSetParameters();
83
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)
90 return;
91
92 if (!CheckAndSetParameters())
93 {
94 Print("Not running due to incorrect parameters - are there rules, and are they enabled?", LogLevel.WARNING);
95 return;
96 }
97
98 if (!m_bProcessScriptFiles && !m_bProcessConfigFiles && !m_bProcessPrefabFiles && !m_bProcessLayerFiles)
99 {
100 Print("Not running - please select at least one type of files to process", LogLevel.NORMAL);
101 return;
102 }
103
104 ScriptEditor scriptEditor = Workbench.GetModule(ScriptEditor);
105 if (!scriptEditor) // ...?
106 {
107 Print("Script Editor is not available", LogLevel.ERROR);
108 return;
109 }
110
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)
117 {
118 // always grab script files
119 foreach (string path : m_aScriptDirectories)
120 {
121 scriptDirectories.Insert(addonFileSystem + path);
122 }
123
124 if (m_bProcessConfigFiles)
125 {
126 foreach (string path : m_aConfigDirectories)
127 {
128 configDirectories.Insert(addonFileSystem + path);
129 }
130 }
131
132 if (m_bProcessPrefabFiles)
133 {
134 foreach (string path : m_aPrefabDirectories)
135 {
136 prefabDirectories.Insert(addonFileSystem + path);
137 }
138 }
139
140 if (m_bProcessLayerFiles)
141 {
142 foreach (string path : m_aLayerDirectories)
143 {
144 layerDirectories.Insert(addonFileSystem + path);
145 }
146 }
147 }
148
149 array<string> allScriptFilesAbsolutePaths;
150 map<string, string> classNames;
151 if (m_iMode == THIS_FILE)
152 {
153 string filePath;
154 if (!scriptEditor.GetCurrentFile(filePath))
155 {
156 Print("No file opened", LogLevel.WARNING);
157 return;
158 }
159
160 if (filePath == __FILE__)
161 {
162 Print("Cannot edit the plugin file itself", LogLevel.NORMAL);
163 return;
164 }
165
166 if (!Workbench.GetAbsolutePath(filePath, filePath, true))
167 {
168 Print("This file is not accessible", LogLevel.WARNING);
169 return;
170 }
171
172 if (m_bOnlyRenameExistingEditableClasses)
173 classNames = GetClassesFromFiles({ filePath });
174 }
175 else
176 if (m_iMode == ALL_FILES)
177 {
178 if (m_bOnlyRenameExistingEditableClasses)
179 {
180 allScriptFilesAbsolutePaths = GetAllEditableScriptFilesAbsolutePaths(scriptDirectories);
181 if (allScriptFilesAbsolutePaths.IsEmpty())
182 {
183 Print("Cannot find any editable script file", LogLevel.NORMAL);
184 return;
185 }
186
187 classNames = GetClassesFromFiles(allScriptFilesAbsolutePaths);
188 }
189 }
190 else // should obviously not happen
191 {
192 Print("Wrong Mode: " + m_iMode, LogLevel.ERROR);
193 return;
194 }
195
196 array<ref SCR_ClassRenamingParam> fromToParams = GetFromToParams();
197
198 if (fromToParams.IsEmpty())
199 {
200 Print("No renaming rules provided - quitting", LogLevel.NORMAL);
201 return;
202 }
203
204 int scriptFilesEdited;
205 int configFilesEdited;
206 int prefabFilesEdited;
207 int layerFilesEdited;
208 if (m_bOnlyRenameExistingEditableClasses)
209 {
210 map<string, string> fromToMap = GetFromToMap(classNames);
211 int fromToMapCount = fromToMap.Count();
212 if (fromToMapCount < 1)
213 {
214 Print("No classes found to replace", LogLevel.NORMAL);
215 return;
216 }
217
218 if (fromToMapCount < 11)
219 {
220 Print("A total of " + fromToMapCount + " classes were found:", LogLevel.NORMAL);
221 foreach (string key, string value : fromToMap)
222 {
223 Print(key + " => " + value, LogLevel.NORMAL);
224 }
225 }
226 else
227 {
228 Print("A total of " + fromToMapCount + " classes were found", LogLevel.NORMAL);
229 }
230
231 if (m_bProcessScriptFiles)
232 {
233 if (!allScriptFilesAbsolutePaths) // saves a potential double call
234 allScriptFilesAbsolutePaths = GetAllEditableScriptFilesAbsolutePaths(scriptDirectories);
235
236 scriptFilesEdited = RenameInFiles(allScriptFilesAbsolutePaths, null, fromToMap, "Processing %1 Script Files");
237 }
238
239 if (m_bProcessConfigFiles)
240 configFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(configDirectories, "conf"), null, fromToMap, "Processing %1 Config Files");
241
242 if (m_bProcessPrefabFiles)
243 prefabFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(prefabDirectories, "et"), null, fromToMap, "Processing %1 Prefab Files");
244
245 if (m_bProcessLayerFiles)
246 layerFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(layerDirectories, "layer"), null, fromToMap, "Processing %1 Layer Files");
247 }
248 else // rename every word that matches criteria
249 {
250 if (m_bProcessScriptFiles)
251 {
252 if (!allScriptFilesAbsolutePaths) // saves a potential double call
253 allScriptFilesAbsolutePaths = GetAllEditableScriptFilesAbsolutePaths(scriptDirectories);
254
255 if (allScriptFilesAbsolutePaths.IsEmpty())
256 {
257 Print("Cannot find any editable script file", LogLevel.NORMAL);
258 return;
259 }
260
261 scriptFilesEdited = RenameInFiles(allScriptFilesAbsolutePaths, fromToParams, null, "Processing %1 Script Files");
262 }
263
264 if (m_bProcessConfigFiles)
265 configFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(configDirectories, "conf"), fromToParams, null, "Processing %1 Config Files");
266
267 if (m_bProcessPrefabFiles)
268 prefabFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(prefabDirectories, "et"), fromToParams, null, "Processing %1 Prefab Files");
269
270 if (m_bProcessLayerFiles)
271 layerFilesEdited = RenameInFiles(GetAllEditableFilesAbsolutePaths(layerDirectories, "layer"), fromToParams, null, "Processing %1 Layer Files");
272 }
273
274 string demoPrefix;
275 if (m_bDemoMode)
276 {
277 Print("No changes were done (Demo Mode)", LogLevel.NORMAL);
278 demoPrefix = "[DEMO] ";
279 }
280 else
281 if (scriptFilesEdited + configFilesEdited + prefabFilesEdited + layerFilesEdited < 1)
282 {
283 Print("No changes were done", LogLevel.NORMAL);
284 return;
285 }
286
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);
291
292 Workbench.Dialog(
293 demoPrefix + "Renaming completed",
294 string.Format(
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.",
296 demoPrefix,
297 scriptFilesEdited,
298 configFilesEdited,
299 prefabFilesEdited,
300 layerFilesEdited));
301 }
302
303 //------------------------------------------------------------------------------------------------
305 protected bool CheckAndSetParameters()
306 {
307 bool result = true;
308
309 if (!m_aParameters)
310 m_aParameters = {};
311
312 if (m_aParameters.IsEmpty())
313 {
314 SCR_ClassRenamingParam param = new SCR_ClassRenamingParam();
315 param.m_bEnabled = false; // on purpose
316 param.m_sFrom = "BIS_*";
317 param.m_sTo = "SCR_";
318 m_aParameters.Insert(param);
319 result = false;
320 }
321 else
322 {
323 bool goodParams = false;
324 foreach (SCR_ClassRenamingParam param : m_aParameters)
325 {
326 param.m_sFrom.TrimInPlace();
327 param.m_sTo.TrimInPlace();
328 if (param.m_bEnabled && param.m_sFrom) // !.IsEmpty()
329 goodParams = true;
330 }
331
332 if (!goodParams)
333 result = false;
334 }
335
336 if (!m_aScriptDirectories)
337 m_aScriptDirectories = {};
338
339 for (int i = m_aScriptDirectories.Count() - 1; i >= 0; --i)
340 {
341 if (SCR_StringHelper.IsEmptyOrWhiteSpace(m_aScriptDirectories[i]))
342 m_aScriptDirectories.Remove(i);
343 }
344
345 if (m_aScriptDirectories.IsEmpty())
346 m_aScriptDirectories.Insert("scripts/");
347
348 for (int i = m_aPrefabDirectories.Count() - 1; i >= 0; --i)
349 {
350 if (SCR_StringHelper.IsEmptyOrWhiteSpace(m_aPrefabDirectories[i]))
351 m_aPrefabDirectories.Remove(i);
352 }
353
354 if (!m_aPrefabDirectories || m_aPrefabDirectories.IsEmpty())
355 m_aPrefabDirectories = { "PrefabLibrary/", "Prefabs/", "PrefabsEditable/" };
356
357 return result;
358 }
359
360 //------------------------------------------------------------------------------------------------
363 array<string> GetAllEditableScriptFilesAbsolutePaths(notnull array<string> scriptDirectories)
364 {
365 array<string> result = {};
366 string absolutePath;
367 foreach (string scriptDir : scriptDirectories)
368 {
369 foreach (ResourceName resourceName : SCR_WorkbenchHelper.SearchWorkbenchResources({ "c" }, null, scriptDir, true))
370 {
371
372 if (resourceName.GetPath() != __FILE__ && Workbench.GetAbsolutePath(resourceName.GetPath(), absolutePath, true))
373 result.Insert(absolutePath);
374 }
375 }
376
377 return result;
378 }
379
380 //------------------------------------------------------------------------------------------------
384 protected array<string> GetAllEditableFilesAbsolutePaths(notnull array<string> directories, string extension)
385 {
386 array<string> result = {};
387 string absolutePath;
388 foreach (string directory : directories)
389 {
390 foreach (ResourceName resourceName : SCR_WorkbenchHelper.SearchWorkbenchResources({ extension }, null, directory, true))
391 {
392 if (Workbench.GetAbsolutePath(resourceName.GetPath(), absolutePath, true))
393 result.Insert(absolutePath);
394 }
395 }
396
397 return result;
398 }
399
400 //------------------------------------------------------------------------------------------------
404 protected map<string, string> GetClassesFromFiles(notnull array<string> absoluteScriptFilePaths)
405 {
407 foreach (ResourceName absoluteScriptFilePath : absoluteScriptFilePaths)
408 {
409 foreach (string fileClass : GetClassesFromFile(absoluteScriptFilePath))
410 {
411 result.Insert(fileClass, absoluteScriptFilePath);
412 }
413 }
414
415 return result;
416 }
417
418 //------------------------------------------------------------------------------------------------
421 protected array<string> GetClassesFromFile(string absoluteFilePath)
422 {
423 array<string> lines = SCR_FileIOHelper.ReadFileContent(absoluteFilePath);
424 if (!lines)
425 return null;
426
427 array<string> result = {};
428 foreach (string line : lines)
429 {
430 int length = line.Length();
431 if (length < 7) // "class " + 1, "class A" is valid
432 continue;
433
434 if (!line.StartsWith("class ") && !line.StartsWith("class\t"))
435 continue;
436
437 string c;
438 string className;
439 for (int i = 6; i < length; i++)
440 {
441 c = line[i];
442 if (c == " " || c == "\t" || c == ":" || c == "/") // a bit raw but it will work
443 break;
444
445 className += c;
446 }
447
448 if (className) // !.IsEmpty()
449 {
450 if (!m_bClassMustStartWithACapitalLetter || SCR_StringHelper.UPPERCASE.Contains(className[0]))
451 result.Insert(className);
452 }
453 }
454
455 return result;
456 }
457
458 //------------------------------------------------------------------------------------------------
461 array<ref SCR_ClassRenamingParam> GetFromToParams()
462 {
463 array<ref SCR_ClassRenamingParam> result = {};
464
465 SCR_ClassRenamingParam newParam;
466 foreach (SCR_ClassRenamingParam param : m_aParameters)
467 {
468 if (!param.m_bEnabled)
469 continue;
470
471 newParam = new SCR_ClassRenamingParam();
472 // newParam.m_bEnabled = true; // not needed
473
474 bool startsWithStar = param.m_sFrom.StartsWith(SCR_StringHelper.STAR);
475 bool endsWithStar = param.m_sFrom.EndsWith(SCR_StringHelper.STAR);
476
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;
483 else
484 newParam.m_iMode = MODE_PMATCH;
485
486 newParam.m_sFrom = param.m_sFrom;
487 //newParam.m_sFrom.Replace(SCR_StringHelper.STAR, string.Empty); // bug for object properties, using temp var to circumvent it
488 string tmp = param.m_sFrom;
489 tmp.Replace(SCR_StringHelper.STAR, string.Empty);
490 newParam.m_sFrom = tmp;
491 newParam.m_sFrom.TrimInPlace();
492
493 if (newParam.m_sFrom) // !.IsEmpty()
494 {
495 newParam.m_sTo = param.m_sTo;
496 newParam.m_sTo.TrimInPlace();
497 if (newParam.m_sTo || newParam.m_iMode != MODE_PMATCH) // prevent exact match to erase the class
498 result.Insert(newParam);
499 }
500 }
501
502 return result;
503 }
504
505 //------------------------------------------------------------------------------------------------
508 map<string, string> GetFromToMap(notnull map<string, string> classFiles)
509 {
510 array<ref SCR_ClassRenamingParam> newParams = GetFromToParams();
511
512 if (newParams.IsEmpty())
513 return new map<string, string>();
514
516
517 foreach (string className, string fp : classFiles)
518 {
519 foreach (SCR_ClassRenamingParam param : newParams)
520 {
521 if (param.m_iMode == MODE_PMATCH)
522 {
523 if (className == param.m_sFrom)
524 {
525 result.Insert(className, param.m_sTo);
526 break;
527 }
528 }
529 else
530 if (param.m_iMode == MODE_PREFIX)
531 {
532 if (className.StartsWith(param.m_sFrom) && !className.EndsWith(param.m_sFrom))
533 {
534 string newClassName = param.m_sTo + className.Substring(param.m_sFrom.Length(), className.Length() - param.m_sFrom.Length());
535 result.Insert(className, newClassName);
536 break;
537 }
538 }
539 else
540 if (param.m_iMode == MODE_SUFFIX)
541 {
542 if (className.EndsWith(param.m_sFrom) && !className.StartsWith(param.m_sFrom))
543 {
544 string newClassName = className.Substring(0, className.LastIndexOf(param.m_sFrom)) + param.m_sTo;
545 result.Insert(className, newClassName);
546 break;
547 }
548 }
549 else
550 if (param.m_iMode == MODE_MIDDLE)
551 {
552 if (className.Contains(param.m_sFrom) &&
553 !className.StartsWith(param.m_sFrom) &&
554 !className.EndsWith(param.m_sFrom))
555 {
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);
559 break;
560 }
561 }
562 }
563 }
564
565 return result;
566 }
567
568 //------------------------------------------------------------------------------------------------
575 int RenameInFiles(notnull array<string> absolutePaths, array<ref SCR_ClassRenamingParam> fromToParams, map<string, string> fromToMap, string progressBarText = "Processing %1 files")
576 {
577 bool isParams = fromToParams != null;
578 if (!isParams && !fromToMap)
579 {
580 Print("RenameInFiles scripting error - provide fromTo info", LogLevel.ERROR);
581 return 0;
582 }
583
584 float countF = absolutePaths.Count();
585 if (countF < 1)
586 return 0;
587
588 int result;
589 array<string> lines;
590 WBModuleDef workbenchModule = Workbench.GetModule(ScriptEditor);
591 progressBarText = string.Format(progressBarText, countF);
592
593 Print("" + progressBarText, LogLevel.NORMAL);
594 WBProgressDialog progressDialog = new WBProgressDialog(progressBarText, workbenchModule);
595 progressDialog.SetProgress(0);
596 float currProgress, prevProgress;
597 foreach (int i, string scriptFile : absolutePaths)
598 {
599 currProgress = i / countF;
600 if (currProgress - prevProgress >= 0.01) // min 1%
601 {
602 progressDialog.SetProgress(currProgress); // expensive
603 Sleep(1);
604 prevProgress = currProgress;
605 }
606
607 lines = SCR_FileIOHelper.ReadFileContent(scriptFile, false);
608 if (!lines)
609 {
610 Print("Cannot read " + scriptFile, LogLevel.WARNING);
611 continue;
612 }
613
614 int fileResult;
615 if (isParams)
616 fileResult = RenameInLines(lines, fromToParams, null);
617 else
618 fileResult = RenameInLines(lines, null, fromToMap);
619
620 if (fileResult > 0)
621 {
622 if (lines[lines.Count() - 1].Trim() != string.Empty)
623 lines.Insert(string.Empty); // ensure the last line return
624
625 if (m_bDemoMode || SCR_FileIOHelper.WriteFileContent(scriptFile, lines))
626 result++;
627 else
628 Print("Cannot write " + scriptFile, LogLevel.WARNING);
629 }
630 }
631
632 return result;
633 }
634
635 //------------------------------------------------------------------------------------------------
640 protected int RenameInLines(out notnull array<string> lines, array<ref SCR_ClassRenamingParam> fromToParams, map<string, string> fromToMap)
641 {
642 bool isParams = fromToParams != null;
643 if (!isParams && !fromToMap)
644 {
645 Print("RenameInLines scripting error - provide fromTo info", LogLevel.ERROR);
646 return 0;
647 }
648
649 int result;
650
651 foreach (int i, string line : lines)
652 {
653 string word;
654 string newLine;
655 for (int j, countJ = line.Length(); j < countJ; ++j)
656 {
657 string c = line[j];
658 bool isClassChar = CLASS_CHARS.Contains(c);
659 bool isLastChar = j == countJ - 1;
660 if (word)
661 {
662 if (CLASS_CHARS.Contains(c))
663 {
664 word += c;
665 }
666 else // word end - let's deal with it
667 {
668 if (KEYWORDS.Contains(word))
669 {
670 newLine += word + c;
671 word = string.Empty;
672 continue;
673 }
674
675 string newClassName;
676 if (isParams)
677 newClassName = GetNewClassNameIfMatch(word, fromToParams);
678 else
679 newClassName = fromToMap.Get(word);
680
681 if (newClassName)
682 {
683 newLine += newClassName + c;
684 result++;
685 }
686 else
687 {
688 newLine += word + c;
689 }
690
691 word = string.Empty;
692 }
693 }
694 else // not in a word
695 {
696 if (isClassChar && !SCR_StringHelper.DIGITS.Contains(c)) // class start
697 word = c;
698 else
699 newLine += c;
700 }
701 }
702
703 // I have the final word
704 if (word)
705 {
706 string newClassName;
707 if (isParams)
708 newClassName = GetNewClassNameIfMatch(word, fromToParams);
709 else
710 newClassName = fromToMap.Get(word);
711
712 if (newClassName)
713 newLine += newClassName;
714 else
715 newLine += word;
716 }
717
718 if (line != newLine)
719 lines[i] = newLine;
720 }
721
722 return result;
723 }
724
725 //------------------------------------------------------------------------------------------------
729 string GetNewClassNameIfMatch(string className, notnull array<ref SCR_ClassRenamingParam> fromToParams)
730 {
731 string result;
732 foreach (SCR_ClassRenamingParam param : fromToParams)
733 {
734 if (param.m_iMode == MODE_PMATCH)
735 {
736 if (className == param.m_sFrom)
737 {
738 result = param.m_sTo;
739 break;
740 }
741 }
742 else
743 if (param.m_iMode == MODE_PREFIX)
744 {
745 if (className.StartsWith(param.m_sFrom) && !className.EndsWith(param.m_sFrom))
746 {
747 result = param.m_sTo + className.Substring(param.m_sFrom.Length(), className.Length() - param.m_sFrom.Length());
748 break;
749 }
750 }
751 else
752 if (param.m_iMode == MODE_SUFFIX)
753 {
754 if (className.EndsWith(param.m_sFrom) && !className.StartsWith(param.m_sFrom))
755 {
756 result = className.Substring(0, className.LastIndexOf(param.m_sFrom)) + param.m_sTo;
757 break;
758 }
759 }
760 else
761 if (param.m_iMode == MODE_MIDDLE)
762 {
763 if (className.Contains(param.m_sFrom) &&
764 !className.StartsWith(param.m_sFrom) &&
765 !className.EndsWith(param.m_sFrom))
766 {
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());
769 break;
770 }
771 }
772 }
773
774 return result;
775 }
776
777 //------------------------------------------------------------------------------------------------
779 [ButtonAttribute("All classes")]
780 int ButtonRunAll()
781 {
782 m_iMode = ALL_FILES;
783 return 1;
784 }
785
786 //------------------------------------------------------------------------------------------------
788 [ButtonAttribute("Curr. file classes", true)]
789 int ButtonRun()
790 {
791 m_iMode = THIS_FILE;
792 return 1;
793 }
794
795 //------------------------------------------------------------------------------------------------
797 [ButtonAttribute("Cancel")]
798 int ButtonCancel()
799 {
800 return 0;
801 }
802}
803
804[BaseContainerProps(), SCR_BaseContainerCustomTitleFields({ "m_sFrom", "m_sTo" }, "%1 to %2")]
805class SCR_ClassRenamingParam
806{
807 [Attribute(defvalue: "1", desc: "Allow this replacement to happen")]
808 bool m_bEnabled;
809
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)")]
811 string m_sFrom;
812
813 [Attribute(desc: "With what to replace")]
814 string m_sTo;
815
816 int m_iMode; // shh, it's a sikrit variable
817}
818#endif
string path
GenerateFlowMaps WorkbenchPlugin WorkbenchPluginAttribute("Regenerate river flow-maps", "Generate and save/overwrite river flow-maps", "", "", {"WorldEditor"}, "", 0xf773)
Definition FlowmapTool.c:59
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
ResourceName resourceName
Definition SCR_AIGroup.c:66
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
override void Run()
bool ButtonCancel()
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
Definition Attributes.c:74
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)
Definition Types.c:486
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute