Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_DataToSpreadsheet.c
Go to the documentation of this file.
1#ifdef WORKBENCH
2
3[WorkbenchPluginAttribute(name: "Data To Spreadsheet plugin", category: "", shortcut: "Alt+Shift+E", wbModules: { "ResourceManager" }, awesomeFontCode: 0xF6DD)]
4class SCR_DataToSpreadsheetPlugin : ResourceManagerPlugin
5{
6 [Attribute("", UIWidgets.ResourceNamePicker, "Pick a config with Spreadsheet parser configuration.", "conf", null, "Settings")]
7 protected ResourceName m_sPrefabConfig;
8
9 [Attribute("1", desc: "Use comma as delimiter, otherwise use dot.", category: "Settings")]
10 protected bool m_bCommaAsDelimiter;
11
12 [Attribute("1", desc: "Use Prefab Array from config instead of the current Resource Browser selection.", category: "Settings")]
13 protected bool m_bUseSelectionFromConfig;
14
15 [Attribute("0", desc: "Check this option to enable additional debug.", category: "Debug")]
16 bool m_bPrintToConsole;
17
18 protected string m_sExportString;
19 protected string m_sHeaderString;
20 protected bool m_bGenerateHeader;
21 protected bool m_bRunExport;
22 protected bool m_bReadData;
23 protected bool m_bSaveRequired;
24
26
27 protected static const string DESCRIPTION = "This plugin allows to transfer data between Workbench and spreadsheets\nExport button grabs data from Workbench to clipboard\nImport button grabs data from clipboard to Workbench";
28
29 //------------------------------------------------------------------------------------------------
30 [ButtonAttribute("Import")]
31 protected void ImportButton()
32 {
33 //m_bRunExport = false;
34 m_bReadData = false;
35 m_mImportData.Clear();
36
37 // Get content of user clipboard
38 string input = System.ImportFromClipboard();
39
40 // Verify input
41 if (input.IsEmpty())
42 return;
43
44 // Parse input
45 array<string> parsedText = {};
46 input.Split("\n", parsedText, false);
47
48 // Parse header
49 array<string> parsedHeader = {};
50 parsedText[0].Split("\t", parsedHeader, false);
51 if (m_bPrintToConsole)
52 PrintFormat("Header: %1", parsedHeader, LogLevel.NORMAL);
53
54 // Parse lines
55 for (int i = 1, count = parsedText.Count(); i < count; ++i)
56 {
57 array<string> parsedLine = {};
59 parsedText[i].Split("\t", parsedLine, false);
60
61 // Empty new line for instance
62 if (parsedLine.Count() == 1)
63 continue;
64
65 if (parsedHeader.Count() != parsedLine.Count())
66 {
67 Print("Invalid data - number of columns in one of the line doesn't match the amount of columns in header", LogLevel.ERROR);
68 m_bRunExport = false;
69 return;
70 }
71
72 for (int i2 = 1, count2 = parsedLine.Count(); i2 < count2; ++i2)
73 {
74 data.Insert(parsedHeader[i2].Trim(), parsedLine[i2].Trim());
75 if (m_bPrintToConsole)
76 PrintFormat("'%1': '%2'", parsedHeader[i2], parsedLine[i2], level: LogLevel.NORMAL);
77 }
78
79 m_mImportData.Insert(parsedLine[0], new SCR_DataToSpreadsheetElement(data));
80 }
81 // Verify parse input
82 if (parsedText.Count() == 1)
83 {
84 Print("No data to import was detected - check content of clipboard", LogLevel.WARNING);
85 m_bRunExport = false;
86 }
87 }
88
89 //------------------------------------------------------------------------------------------------
90 [ButtonAttribute("Export")]
91 protected void ExportButton()
92 {
93 ExportToExcel(true);
94 }
95
96 //------------------------------------------------------------------------------------------------
97 [ButtonAttribute("Cancel")]
98 protected bool CancelButton()
99 {
100 return false;
101 }
102
103 //------------------------------------------------------------------------------------------------
104 protected override void Configure()
105 {
106 Workbench.ScriptDialog("Data To Spreadsheets", DESCRIPTION, this);
107 }
108
109 //------------------------------------------------------------------------------------------------
112 protected void ProcessData(IEntitySource entSrc, ResourceName prefabName, SCR_DataToSpreadsheetTemplates prefabConfig)
113 {
114 array<ref ContainerIdPathEntry> containerPath = {};
115 ProcessAttributes(entSrc, containerPath, prefabName, prefabConfig.m_aAttributesArray);
116 }
117
118 //------------------------------------------------------------------------------------------------
120 protected void ProcessAttributes(IEntitySource entSrc, array<ref ContainerIdPathEntry> containerPath, ResourceName prefabName, array<ref SCR_DataToSpreadsheetTemplatesBase> TemplateData)
121 {
122 IEntityComponentSource component;
123 foreach (SCR_DataToSpreadsheetTemplatesBase currentEntry : TemplateData)
124 {
125 switch (currentEntry.ReturnType())
126 {
127 case "Component" :
128 {
129 SCR_DataToSpreadsheetTemplatesComponent entry = SCR_DataToSpreadsheetTemplatesComponent.Cast(currentEntry);
130 component = SCR_BaseContainerTools.FindComponentSource(entSrc, entry.m_sComponentName);
131 if (!component)
132 continue;
133
134 array<ref ContainerIdPathEntry> containerPathSub = {};
135 foreach (ContainerIdPathEntry obj : containerPath)
136 {
137 containerPathSub.Insert(obj);
138 }
139
140 containerPathSub.Insert(new ContainerIdPathEntry(entry.m_sComponentName));
141 ProcessAttributes(component, containerPathSub, prefabName, entry.GetAttributes());
142 }
143 break;
144
145 case "Attribute" :
146 {
147 SCR_DataToSpreadsheetTemplatesAttribute entry = SCR_DataToSpreadsheetTemplatesAttribute.Cast(currentEntry);
148 ProcessAttribute(entSrc, containerPath, prefabName, entry);
149 }
150 break;
151
152 case "Object" :
153 {
154 SCR_DataToSpreadsheetTemplatesObject entry = SCR_DataToSpreadsheetTemplatesObject.Cast(currentEntry);
155 BaseContainer container = entSrc.GetObject(entry.m_sObjectName);
156 if (!container)
157 continue;
158
159 array<ref ContainerIdPathEntry> containerPathSub = {};
160 foreach (ContainerIdPathEntry obj : containerPath)
161 {
162 containerPathSub.Insert(obj);
163 }
164
165 containerPathSub.Insert(ContainerIdPathEntry(entry.m_sObjectName));
166 ProcessAttributes(container, containerPathSub, prefabName, entry.GetAttributes());
167 }
168 break;
169
170 case "ObjectArray" :
171 {
172 SCR_DataToSpreadsheetTemplatesObjectArray entry = SCR_DataToSpreadsheetTemplatesObjectArray.Cast(currentEntry);
173 BaseContainerList containerList = entSrc.GetObjectArray(entry.m_ObjectName);
174 array<ref ContainerIdPathEntry> containerPathSub = new array<ref ContainerIdPathEntry>;
175 foreach (ContainerIdPathEntry obj : containerPath)
176 {
177 containerPathSub.Insert(obj);
178 }
179 containerPathSub.Insert(ContainerIdPathEntry(entry.m_ObjectName));
180 ProcessAttributesList(containerList, containerPathSub, prefabName, entry.GetAttributes());
181 }
182 break;
183 }
184 }
185 }
186
187 protected static BaseContainer GetChildFromList(notnull BaseContainerList containerList, string childName)
188 {
189 if (childName.IsEmpty())
190 return null;
191
192 string arrayItemName;
193 BaseContainer containerListElement;
194 for (int i, cnt = containerList.Count(); i < cnt; i++)
195 {
196 containerListElement = containerList[i];
197 arrayItemName = containerListElement.GetName();
198
199 if (arrayItemName.IsEmpty())
200 arrayItemName = containerListElement.GetClassName(); // if .et
201
202 if (arrayItemName.IsEmpty())
203 continue;
204
205 arrayItemName.ToLower();
206 childName.ToLower();
207 if (arrayItemName == childName)
208 return containerListElement;
209 }
210
211 return null;
212 }
213
214 void ProcessAttributesList(BaseContainerList containerList, array<ref ContainerIdPathEntry> containerPath, ResourceName prefabName, array<ref SCR_DataToSpreadsheetTemplatesBase> TemplateData)
215 {
216
217 foreach (SCR_DataToSpreadsheetTemplatesBase currentEntry : TemplateData)
218 {
219 switch (currentEntry.ReturnType())
220 {
221 case "Object" :
222 {
223 SCR_DataToSpreadsheetTemplatesObject entry = SCR_DataToSpreadsheetTemplatesObject.Cast(currentEntry);
224 BaseContainer container = GetChildFromList(containerList, entry.m_sObjectName);
225 array<ref ContainerIdPathEntry> containerPathSub = new array<ref ContainerIdPathEntry>;
226 foreach (ContainerIdPathEntry obj : containerPath)
227 {
228 containerPathSub.Insert(obj);
229 }
230 containerPathSub.Insert(ContainerIdPathEntry(entry.m_sObjectName));
231 ProcessAttributes(container, containerPathSub, prefabName, entry.GetAttributes());
232 }
233 break;
234
235 case "ObjectIndex" :
236 {
237 SCR_DataToSpreadsheetTemplatesObjectIndex entry = SCR_DataToSpreadsheetTemplatesObjectIndex.Cast(currentEntry);
238 BaseContainer container = containerList.Get(entry.m_iObjectIndex);
239 array<ref ContainerIdPathEntry> containerPathSub = new array<ref ContainerIdPathEntry>;
240 foreach (ContainerIdPathEntry obj : containerPath)
241 {
242 containerPathSub.Insert(obj);
243 }
244 containerPathSub.Insert(ContainerIdPathEntry(entry.m_iObjectIndex.ToString()));
245 ProcessAttributes(container, containerPathSub, prefabName, entry.GetAttributes());
246 }
247 break;
248
249 default:
250 {
251 Print("Incorrect element");
252 }
253 }
254 }
255 }
256
257
258 //------------------------------------------------------------------------------------------------
261 void ProcessAttribute(IEntitySource entSrcAttribute, array<ref ContainerIdPathEntry> containerPath, ResourceName prefabName, SCR_DataToSpreadsheetTemplatesAttribute currentAttribute)
262 {
263 // Read or write
264 string attributeName = currentAttribute.m_sAttributeName;
265 int attributeType = currentAttribute.m_eAttributeType;
266 string value;
267 if (attributeType == SCR_EDataToSpreadsheetDataType.INT)
268 {
269 string currentValue;
270 entSrcAttribute.Get(attributeName, currentValue);
271 if (currentValue.IsEmpty())
272 entSrcAttribute.GetDefaultAsString(attributeName, currentValue);
273
274 value = currentValue;
275 }
276 else
277 if (attributeType == SCR_EDataToSpreadsheetDataType.FLOAT)
278 {
279 string currentValue;
280 entSrcAttribute.Get(attributeName, currentValue);
281 if (currentValue.IsEmpty())
282 entSrcAttribute.GetDefaultAsString(attributeName, currentValue);
283
284 if (m_bCommaAsDelimiter)
285 currentValue.Replace(".", ",");
286
287 value = currentValue;
288 }
289 else
290 if (attributeType == SCR_EDataToSpreadsheetDataType.STRING)
291 {
292 string currentValue;
293 entSrcAttribute.Get(attributeName, currentValue);
294 if (currentValue.IsEmpty())
295 entSrcAttribute.GetDefaultAsString(attributeName, currentValue);
296
297 value = currentValue;
298 }
299 else
300 if (attributeType == SCR_EDataToSpreadsheetDataType.RESOURCE)
301 {
302 ResourceName currentValue;
303 entSrcAttribute.Get(attributeName, currentValue);
304 if (currentValue.IsEmpty())
305 entSrcAttribute.GetDefaultAsString(attributeName, currentValue);
306
307 value = currentValue;
308 }
309
310 if (m_bPrintToConsole)
311 PrintFormat("%1: %2", attributeName, value, level: LogLevel.NORMAL);
312
313 if (m_bReadData)
314 {
315 m_sExportString += value + "\t";
316 if (m_bGenerateHeader)
317 m_sHeaderString += attributeName + "\t";
318 }
319 else
320 {
321 SCR_DataToSpreadsheetElement data;
322 if (!m_mImportData.Find(prefabName, data))
323 return;
324
325 string importedData = data.GetData(attributeName);
326 if (importedData.IsEmpty())
327 return;
328
329 // Check if there is some change between imported data and what is in the prefab/config
330 // If there is a change detected, we are marking that this object need to be resaved by changing m_bSaveRequired flag
331 if (!importedData.Compare(value))
332 return;
333
334 if (m_bCommaAsDelimiter && (attributeType == SCR_EDataToSpreadsheetDataType.INT || attributeType == SCR_EDataToSpreadsheetDataType.FLOAT))
335 {
336 importedData.Replace(",", ".");
337 value.Replace(",", ".");
338 }
339 if(attributeType == SCR_EDataToSpreadsheetDataType.FLOAT)
340 {
341 if(importedData.ToFloat() == value.ToFloat())
342 return;
343 }
344
345 entSrcAttribute.Set(attributeName, importedData);
346 m_bSaveRequired = true;
347 PrintFormat("Detected difference in data '%1' '%2' '%3'", importedData, value, attributeName, level: LogLevel.NORMAL);
348 }
349 }
350
351 //------------------------------------------------------------------------------------------------
352 protected void ExportToExcel(bool useListFromConfig)
353 {
354 if (!m_sPrefabConfig)
355 {
356 Print("Missing Prefab Config file", LogLevel.ERROR);
357 return;
358 }
359
360 Resource holder = BaseContainerTools.LoadContainer(m_sPrefabConfig);
361 if (!holder)
362 {
363 Print("Invalid Prefab Config file - either its not correct type or its missing", LogLevel.ERROR);
364 return;
365 }
366
367 SCR_DataToSpreadsheetTemplates prefabConfig = SCR_DataToSpreadsheetTemplates.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
368 array<ref ResourceName> selection = {};
369 if (useListFromConfig)
370 {
371 selection = prefabConfig.m_aPrefabsArray;
372 }
373 else
374 {
375 // Grab reference to ResourceManager
376 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
377 if (!resourceManager)
378 return;
379
380 // Get list of currently selected resources
381 resourceManager.GetResourceBrowserSelection(selection.Insert, true);
382 }
383
384 // Verify if something is selected - if no, exit method & print error message
385 if (selection.IsEmpty())
386 {
387 Print("No elements are selected in Resource Browser", LogLevel.WARNING);
388 return;
389 }
390
391 if (m_bPrintToConsole)
392 {
393 // Print ResourceManager selection directly to the console
394 Print(selection, LogLevel.NORMAL);
395 }
396
397 m_sExportString = "";
398 m_sHeaderString = "Name\t";
399 m_bGenerateHeader = true;
400
401 // Copy file name to clipboard - each element will be written on new line
402 BaseContainerList baseContainerList;
403 foreach (ResourceName prefabName : selection)
404 {
405 if (m_bPrintToConsole)
406 Print(prefabName, LogLevel.NORMAL);
407
408 m_sExportString += prefabName + "\t";
409 Resource prefab = Resource.Load(prefabName);
410 BaseContainer prefabSource;
411 MetaFile meta;
412 if (prefabName.EndsWith(".et"))
413 {
414 prefabSource = SCR_BaseContainerTools.FindEntitySource(prefab);
415 }
416 else if (prefabName.EndsWith(".xob") || prefabName.EndsWith(".edds"))
417 {
418 // For .xob, .emat, and .edds files, use their meta file and convert to base container
419 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
420 meta = resourceManager.GetMetaFile(prefabName.GetPath());
421 if (meta)
422 {
423 prefabSource = meta.ToBaseContainer();
424 }
425 else
426 {
427 Print(string.Format("Failed to get meta file for: %1", prefabName), LogLevel.ERROR);
428 continue;
429 }
430 }
431 else
432 {
433 prefabSource = prefab.GetResource().ToBaseContainer();
434 }
435
436 ProcessData(prefabSource, prefabName, prefabConfig);
437
438 m_sExportString += "\n";
439 m_bGenerateHeader = false;
440 if (m_bSaveRequired)
441 {
442 if (meta)
443 meta.Save();
444 BaseContainerTools.SaveContainer(prefabSource, prefabName);
445 m_bSaveRequired = false;
446 }
447 }
448
449 if (m_bReadData)
450 {
451 m_sHeaderString += "\n";
452 m_sExportString.Replace("\t\n","\n");
453
454 System.ExportToClipboard(m_sHeaderString + m_sExportString);
455 }
456 }
457
458 //------------------------------------------------------------------------------------------------
459 protected override void Run()
460 {
461 m_bRunExport = true;
462 m_bReadData = true;
463
464 if (Workbench.ScriptDialog("Data To Spreadsheets", DESCRIPTION, this) == 0)
465 return;
466
467 if (m_bRunExport)
468 ExportToExcel(m_bUseSelectionFromConfig);
469 }
470}
471
473enum SCR_EDataToSpreadsheetDataType
474{
475 INT = 1 << 0,
476 FLOAT = 1 << 1,
477 STRING = 4 << 2,
478 RESOURCE = 8 << 3,
479}
480
481class SCR_DataToSpreadsheetElement
482{
483 protected ref map<string, string> m_mElements;
484
485 //------------------------------------------------------------------------------------------------
488 string GetData(string attribute)
489 {
490 return m_mElements.Get(attribute);
491 }
492
493 //------------------------------------------------------------------------------------------------
494 // constructor
496 void SCR_DataToSpreadsheetElement(notnull map<string, string> data)
497 {
498 m_mElements = data;
499 }
500}
501
502[BaseContainerProps(configRoot: true)]
503class SCR_DataToSpreadsheetTemplates
504{
505 [Attribute(desc: "Array of prefabs which will be processed")]
506 ref array<ref ResourceName> m_aPrefabsArray;
507
508 [Attribute(desc: "Array of attributes which will be processed")]
509 ref array<ref SCR_DataToSpreadsheetTemplatesBase> m_aAttributesArray;
510}
511
512[BaseContainerProps(configRoot: false), SCR_BatchPrefabTitle("Template Base - Has no function")]
513class SCR_DataToSpreadsheetTemplatesBase
514{
515 //------------------------------------------------------------------------------------------------
518 string ReturnType()
519 {
520 return "Base";
521 }
522
523 //------------------------------------------------------------------------------------------------
525 array<ref SCR_DataToSpreadsheetTemplatesBase> GetAttributes();
526}
527
528[BaseContainerProps(configRoot: false), SCR_BatchPrefabTitle("Component: ", "m_sComponentName")]
529class SCR_DataToSpreadsheetTemplatesComponent : SCR_DataToSpreadsheetTemplatesBase
530{
531 [Attribute(desc: "Name of component to modify or add")]
532 string m_sComponentName;
533
534 [Attribute(desc: "Sub array of attributes")]
535 ref array<ref SCR_DataToSpreadsheetTemplatesBase> m_aAttributesArray;
536
537 //------------------------------------------------------------------------------------------------
538 override string ReturnType()
539 {
540 return "Component";
541 }
542
543 //------------------------------------------------------------------------------------------------
544 override ref array<ref SCR_DataToSpreadsheetTemplatesBase> GetAttributes()
545 {
546 return m_aAttributesArray;
547 }
548}
549
550[BaseContainerProps(configRoot: false), SCR_BatchPrefabTitle("m_sAttributeName")]
551class SCR_DataToSpreadsheetTemplatesAttribute : SCR_DataToSpreadsheetTemplatesBase
552{
553 [Attribute(desc: "Name of attribute to modify")]
554 string m_sAttributeName;
555
556 [Attribute("2", UIWidgets.ComboBox, desc: "Specifies type of parameter", enums: ParamEnumArray.FromEnum(SCR_EDataToSpreadsheetDataType))]
557 SCR_EDataToSpreadsheetDataType m_eAttributeType;
558
559 //------------------------------------------------------------------------------------------------
560 override string ReturnType()
561 {
562 return "Attribute";
563 }
564}
565
566[BaseContainerProps(configRoot: false), SCR_BatchPrefabTitle("Object: ", "m_sObjectName")]
567class SCR_DataToSpreadsheetTemplatesObject : SCR_DataToSpreadsheetTemplatesBase
568{
569 [Attribute(desc: "Name of container to modify or add")]
570 string m_sObjectName;
571
572 [Attribute(desc: "Array of attributes which will be exported or modified inside container belonging to prefab")]
573 ref array<ref SCR_DataToSpreadsheetTemplatesBase> m_aAttributesArray;
574
575 //------------------------------------------------------------------------------------------------
576 override string ReturnType()
577 {
578 return "Object";
579 }
580
581 //------------------------------------------------------------------------------------------------
582 override array<ref SCR_DataToSpreadsheetTemplatesBase> GetAttributes()
583 {
584 return m_aAttributesArray;
585 }
586}
587
588[BaseContainerProps(configRoot: false), SCR_BatchPrefabTitle("Object Array: ", "m_ObjectName")]
589class SCR_DataToSpreadsheetTemplatesObjectArray: SCR_DataToSpreadsheetTemplatesBase
590{
591 [Attribute(desc: "Name of component to modify or add")]
592 string m_ObjectName;
593
594 [Attribute(desc: "Array of attributes which will be modified inside component belonging to prefab. If component is not present, new one will be created")]
595 ref array<ref SCR_DataToSpreadsheetTemplatesBase> m_AttributesArray;
596
597 override string ReturnType()
598 {
599 return "ObjectArray";
600 }
601 override ref array<ref SCR_DataToSpreadsheetTemplatesBase> GetAttributes()
602 {
603 return m_AttributesArray;
604 }
605}
606
607[BaseContainerProps(configRoot: false), SCR_BatchPrefabTitle("Object Index: ", "m_iObjectIndex")]
608class SCR_DataToSpreadsheetTemplatesObjectIndex : SCR_DataToSpreadsheetTemplatesBase
609{
610 [Attribute(desc: "Name of container to modify or add")]
611 int m_iObjectIndex;
612
613 [Attribute(desc: "Array of attributes which will be exported or modified inside container belonging to prefab")]
614 ref array<ref SCR_DataToSpreadsheetTemplatesBase> m_aAttributesArray;
615
616 //------------------------------------------------------------------------------------------------
617 override string ReturnType()
618 {
619 return "ObjectIndex";
620 }
621
622 //------------------------------------------------------------------------------------------------
623 override array<ref SCR_DataToSpreadsheetTemplatesBase> GetAttributes()
624 {
625 return m_aAttributesArray;
626 }
627}
628
629#endif // WORKBENCH
void ContainerIdPathEntry(string propertyName, int index=-1)
Definition worldEditor.c:30
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.
override string GetData()
Get all prefabs that have the spawner data
override void Run()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
override void Configure()
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
Definition Types.c:486
@ STRING
String type.
Definition DataVarType.c:41
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
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
SCR_FieldOfViewSettings Attribute