Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
EditablePrefabsComponent_EditableEntity.c
Go to the documentation of this file.
1#ifdef WORKBENCH
3class EditablePrefabsComponent_EditableEntity : EditablePrefabsComponent_Base
4{
5 [Attribute(defvalue: "(%1)", desc: "Format of autogenerated placeholder name.\n%1 is the prefab file name (without extension).")]
6 protected string m_sNameFormat;
7
8 [Attribute(defvalue: "#AR-EditableEntity_%1_Name", desc: "Format of localized name.\nWhen found in the database, it will be applied instead of the placeholder name.\n%1 is the prefab file name (without extension).")]
9 protected string m_sLocKeyFormat;
10
11 [Attribute(defvalue: "UI/Textures/EditorPreviews", desc: "Directory where placeholder image will be auto-generated.\nHierarchy inside the folder mimics prefab folder hierarchy.", params: "folders")]
12 protected ResourceName m_ImagesDirectory;
13
14 [Attribute(defvalue: "", desc: "Placeholder image used when adding new editable entity", uiwidget: UIWidgets.ResourcePickerThumbnail, params: "edds")]
15 protected ResourceName m_ImagePlaceholder;
16
17 [Attribute(defvalue: "1", desc: "Enable budget update during autoconfiguration, costly procedure so can be disabled if budgets don't need to be updated")]
18 protected bool m_bUpdateBudgets;
19
20 [Attribute(desc: "Label Rules")]
21 protected ref array<ref EditablePrefabsLabel_Base> m_EntityLabelRules;
22
23 [Attribute(desc: "Editor entity core config file", uiwidget: UIWidgets.ResourcePickerThumbnail, params: "conf")]
24 protected ResourceName m_EntityCoreConfigPrefab;
25
26 protected string m_sImagesPath;
27 protected string m_sImagePlaceholderPath;
28 protected string m_sImagePlaceholderSource;
29 protected string m_sImagePlaceholderExt;
30 protected ref SCR_EditableEntityCore m_EntityCoreConfig;
31
32 protected ref map<EEditableEntityBudget, int> m_MinBudgetCost = new map<EEditableEntityBudget, int>();
33
34 protected const string IMG_EXTENSION = "edds";
35 protected const string META_EXTENSION = ".meta";
36
37 //------------------------------------------------------------------------------------------------
38 protected bool SetUIInfo(EditablePrefabsConfig config, WorldEditorAPI api, ResourceName prefab, string targetPath, IEntitySource entitySource, IEntitySource instanceEntitySource, IEntityComponentSource componentSource, IEntityComponentSource componentCurrent)
39 {
40 BaseContainer info = componentSource.GetObject("m_UIInfo");
41 if (!info)
42 return false;
43
44 typename infoType = info.GetClassName().ToType();
45
46 array<ref ContainerIdPathEntry> path = { ContainerIdPathEntry(componentSource.GetClassName()), ContainerIdPathEntry("m_UIInfo") };
47
48 //--- Get existing UI info
49 BaseContainer infoCurrent;
50 if (componentCurrent)
51 infoCurrent = componentCurrent.GetObject("m_UIInfo");
52
53 //--- Name
54 if (!m_sNameFormat.IsEmpty())
55 {
56 string name;
57
58 //--- Preserve existing localized name
59 if (infoCurrent)
60 infoCurrent.Get("Name", name);
61
62 if (!name.StartsWith("#"))
63 {
64 string prefabName = FilePath.StripExtension(FilePath.StripPath(prefab));
65
66 string locKey = string.Format(m_sLocKeyFormat, prefabName);
67 string locText = WidgetManager.Translate(locKey);
68 if (locText != locKey)
69 name = locKey; //--- Apply existing, but not assigned localized name
70 else
71 name = string.Format(m_sNameFormat, prefabName); //--- No localized name defined yet, generate the name based on prefab name
72 }
73
74 api.SetVariableValue(entitySource, path, "Name", name);
75 }
76
77 //--- Preserve existing localized description
78 if (infoCurrent)
79 {
80 string description;
81 if (infoCurrent.IsVariableSetDirectly("Description") && infoCurrent.Get("Description", description) && !description.IsEmpty())
82 api.SetVariableValue(entitySource, path, "Description", description);
83
84 //--- Preserve existing entity icon set name
85 string entityIconSetName;
86 if (infoCurrent.IsVariableSetDirectly("IconSetName") && infoCurrent.Get("IconSetName", entityIconSetName) && !entityIconSetName.IsEmpty())
87 api.SetVariableValue(entitySource, path, "IconSetName", entityIconSetName);
88
89 //--- Preserve existing entity icon
90 ResourceName entityIcon;
91 if (infoCurrent.IsVariableSetDirectly("Icon") && infoCurrent.Get("Icon", entityIcon) && !entityIcon.IsEmpty())
92 api.SetVariableValue(entitySource, path, "Icon", entityIcon);
93 }
94
95 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
96
97 //--- Image
98 string imagePath = targetPath;
99 if (GetImagePath(config, imagePath))
100 {
101 //--- Create placeholder preview image
102 string addonName = SCR_AddonTool.GetResourceLastAddon(prefab);
103 addonName = SCR_AddonTool.ToFileSystem(addonName);
104 CreatePreviewImage(resourceManager, config, api, imagePath, entitySource, addonName);
105
106 api.SetVariableValue(entitySource, path, "m_Image", imagePath);
107 }
108
109 IEntityComponentSource horizontalAlignComponent = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_HorizontalAlignComponent);
110 if (horizontalAlignComponent)
111 {
112 bool isHorizontalAlign;
113 horizontalAlignComponent.Get("Enabled", isHorizontalAlign);
114
115 if (isHorizontalAlign)
116 {
117 int flags;
118 componentSource.Get("m_Flags", flags);
119 flags = flags | EEditableEntityFlag.HORIZONTAL;
120
121 api.SetVariableValue(entitySource, {ContainerIdPathEntry(componentSource.GetClassName())}, "m_Flags", flags.ToString());
122 }
123 }
124
125 //--- Labels
126
127 /* Print label indices for debugging
128 for (int i = 0; i<50; i++)
129 {
130 string labelName = Type().EnumToString(EEditableEntityLabel, i);
131
132 if (labelName != string.Empty)
133 Print(string.Format("Label %1: %2", i, labelName), LogLevel.NORMAL);
134 }
135 */
136
137 // Read source entity
138 array<EEditableEntityLabel> autoLabels = {};
139 array<EEditableEntityLabel> authoredLabels = {};
140 if (GetLabelsFromSource(api, config, prefab, targetPath, instanceEntitySource, componentSource, componentCurrent, autoLabels, authoredLabels))
141 {
142 api.SetVariableValue(entitySource, path, "m_aAutoLabels", SCR_BaseContainerTools.GetArrayValue(autoLabels));
143 api.SetVariableValue(entitySource, path, "m_aAuthoredLabels", SCR_BaseContainerTools.GetArrayValue(authoredLabels));
144 }
145
146 if (m_bUpdateBudgets)
147 {
148 BaseContainer infoAncestor;
149 IEntityComponentSource componentAncestor;
150 if (componentCurrent)
151 {
152 componentAncestor = componentCurrent.GetAncestor();
153 if (componentAncestor)
154 infoAncestor = componentAncestor.GetObject("m_UIInfo");
155 }
156
157 //--- Update vehicle occupant budgets
158 if (infoType.IsInherited(SCR_EditableVehicleUIInfo))
159 {
160 array<ref SCR_EntityBudgetValue> crewBudgetCosts = {};
161 array<ref SCR_EntityBudgetValue> passengerBudgetCosts = {};
162 array<ECompartmentType> vehicleCompartmentTypes = {};
163
164 GetEntityBudgetCostsFromVehicle(entitySource, crewBudgetCosts, passengerBudgetCosts, vehicleCompartmentTypes);
165
166 string vehicleCompartmentTypesValue = SCR_BaseContainerTools.GetArrayValue(vehicleCompartmentTypes);
167 api.SetVariableValue(entitySource, path, "m_aOccupantFillCompartmentTypes", vehicleCompartmentTypesValue);
168
169 SetBudgets(api, entitySource, infoAncestor, infoCurrent, path, "m_aCrewEntityBudgetCost", crewBudgetCosts);
170 SetBudgets(api, entitySource, infoAncestor, infoCurrent, path, "m_aPassengerEntityBudgetCost", passengerBudgetCosts);
171 }
172
173 //=== Calculate combined children budget costs
174 array<ref SCR_EntityBudgetValue> entityChildrenBudgetCosts = {};
175 GetEntityChildrenBudgetCostsFromSource(entitySource, entityChildrenBudgetCosts);
176
177 SetBudgets(api, entitySource, infoAncestor, infoCurrent, path, "m_EntityChildrenBudgetCost", entityChildrenBudgetCosts);
178
179 //--- Preserve existing values of the entity budget
180 if (infoAncestor)
181 {
182 const string varName = "m_EntityBudgetCost";
183 array<ref SCR_EntityBudgetValue> entityBudgetCosts = {};
184 PreserveBudgets(api, infoCurrent, varName, entityBudgetCosts);
185
186 int budgetListCount;
187 BaseContainerList budgetList = infoAncestor.GetObjectArray(varName);
188 if (budgetList)
189 budgetListCount = budgetList.Count();
190
191 array<ref ContainerIdPathEntry> budgetPath = {ContainerIdPathEntry(componentSource.GetClassName()), ContainerIdPathEntry("m_UIInfo"), null};
192 foreach (SCR_EntityBudgetValue budget : entityBudgetCosts)
193 {
194 api.CreateObjectArrayVariableMember(entitySource, path, varName, "SCR_EntityBudgetValue", budgetListCount);
195
196 budgetPath.Set(budgetPath.Count() - 1, ContainerIdPathEntry(varName, budgetListCount));
197 api.SetVariableValue(entitySource, budgetPath, "m_BudgetType", typename.EnumToString(EEditableEntityBudget, budget.GetBudgetType()));
198 api.SetVariableValue(entitySource, budgetPath, "m_Value", budget.GetBudgetValue().ToString());
199 budgetListCount++;
200 }
201 }
202 }
203
204 //--- Custom slot prefab
205 IEntityComponentSource slotCompositionComponent = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_SlotCompositionComponent);
206 if (slotCompositionComponent)
207 {
208 ResourceName slotPrefab = SCR_SlotCompositionComponentClass.GetSlotPrefab(slotCompositionComponent);
209 if (!slotPrefab.IsEmpty())
210 api.SetVariableValue(entitySource, path, "m_SlotPrefab", slotPrefab);
211 }
212
213 //--- Copy group identity
214 if (infoType.IsInherited(SCR_EditableGroupUIInfo))
215 {
216 IEntityComponentSource groupIdentitySource = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_GroupIdentityComponent);
217 if (groupIdentitySource)
218 {
219 BaseContainer symbolSource = groupIdentitySource.GetObject("m_MilitarySymbol");
220 if (symbolSource)
221 {
222 SCR_MilitarySymbol symbol = SCR_MilitarySymbol.Cast(BaseContainerTools.CreateInstanceFromContainer(symbolSource));
223 Resource symbolResource = BaseContainerTools.CreateContainerFromInstance(symbol);
224 info.SetObject("m_MilitarySymbol", symbolResource.GetResource().ToBaseContainer());
225 }
226 }
227 }
228 return true;
229 }
230
231 //------------------------------------------------------------------------------------------------
232 protected void SetBudgets(WorldEditorAPI api, IEntitySource entitySource, BaseContainer info, BaseContainer infoCurrent, array<ref ContainerIdPathEntry> path, string varName, array<ref SCR_EntityBudgetValue> budgets)
233 {
234 PreserveBudgets(api, infoCurrent, varName, budgets);
235
236 api.ClearVariableValue(entitySource, path, varName);
237
238 //--- Copy path and add an entry to be set in the loop
239 array<ref ContainerIdPathEntry> budgetPath = {};
240 foreach (ContainerIdPathEntry entry : path)
241 {
242 budgetPath.Insert(ContainerIdPathEntry(entry.PropertyName, entry.Index));
243 }
244
245 budgetPath.Insert(null);
246
247 BaseContainerList budgetList;
248 int budgetListCount;
249 if (info)
250 {
251 budgetList = info.GetObjectArray(varName);
252 if (budgetList)
253 budgetListCount = budgetList.Count();
254 }
255
256 EEditableEntityBudget listBudgetType;
257 int listBudgetValue;
258
259 foreach (SCR_EntityBudgetValue entry : budgets)
260 {
261 EEditableEntityBudget budgetType = entry.GetBudgetType();
262 int budgetValue = entry.GetBudgetValue();
263
264 //--- Scan existing array to determine whether to override existing entry or create a new one
265 int index = -1;
266 for (int l = 0; l < budgetListCount; l++)
267 {
268 if (budgetList.Get(l).Get("m_BudgetType", listBudgetType) && listBudgetType == budgetType)
269 {
270 if (budgetList.Get(l).Get("m_Value", listBudgetValue) && listBudgetValue == budgetValue)
271 index = -2; //--- Value found and is the same - don't save new value
272 else
273 index = l; //--- Value found and is different - override the existing one
274
275 break;
276 }
277 }
278
279 if (index == -2)
280 {
281 continue;
282 }
283 if (index == -1)
284 {
285 //--- Value not found, add a new one
286 index = budgetListCount;
287 //budgetListCount++;
288 api.CreateObjectArrayVariableMember(entitySource, path, varName, "SCR_EntityBudgetValue", index);
289 }
290
291 //--- Set values
292 budgetPath.Set(budgetPath.Count() - 1, ContainerIdPathEntry(varName, index));
293 api.SetVariableValue(entitySource, budgetPath, "m_BudgetType", typename.EnumToString(EEditableEntityBudget, budgetType));
294 api.SetVariableValue(entitySource, budgetPath, "m_Value", budgetValue.ToString());
295 }
296 }
297
298 //------------------------------------------------------------------------------------------------
299 protected void PreserveBudgets(WorldEditorAPI api, BaseContainer infoCurrent, string varName, array<ref SCR_EntityBudgetValue> budgets)
300 {
301 BaseContainerList budgetList = infoCurrent.GetObjectArray(varName);
302 int budgetListCount = budgetList.Count();
303 EEditableEntityBudget listBudgetType;
304 for (int l = 0; l < budgetListCount; l++)
305 {
306 budgetList.Get(l).Get("m_BudgetType", listBudgetType);
307
308 bool isFound;
309 foreach (int i, SCR_EntityBudgetValue entry : budgets)
310 {
311 if (entry.GetBudgetType() == listBudgetType)
312 {
313 isFound = true;
314 break;
315 }
316 }
317
318 if (!isFound)
319 {
320 //--- Add only budgets that are not defined anew
321 EEditableEntityBudget budgetType;
322 budgetList.Get(l).Get("m_BudgetType", budgetType);
323
324 int budgetValue;
325 budgetList.Get(l).Get("m_Value", budgetValue);
326
327 budgets.Insert(new SCR_EntityBudgetValue(budgetType, budgetValue));
328 }
329 }
330 }
331
332 //------------------------------------------------------------------------------------------------
333 protected void CreatePreviewImage(
334 notnull ResourceManager resourceManager,
335 EditablePrefabsConfig config,
336 WorldEditorAPI api,
337 out string targetPath,
338 IEntitySource entitySource,
339 string addonName)
340 {
341 //--- Cannot find image path
342 //if (!GetImagePath(config, targetPath)) return;
343
344 //--- Already exists, don't create placeholder, but get GUID of the file
345 if (FileIO.FileExists(targetPath))
346 {
347 string absolutePath;
348 Workbench.GetAbsolutePath(targetPath, absolutePath);
349 MetaFile metaContainer = resourceManager.GetMetaFile(absolutePath);
350 targetPath = metaContainer.GetResourceID();
351 return;
352 }
353
354 // Clear missing texture
355 if (!targetPath.IsEmpty())
356 {
357 Print(string.Format("Clearing missing preview image: '%1' for entity: '%2'", targetPath, entitySource.GetResourceName().GetPath()), LogLevel.WARNING);
358 targetPath = "";
359 return;
360 }
361
362 // Generate new placeholder image - TODO: Move this part into SCR_EditorImageGeneratorEntity
363 string sourceFile = FilePath.ReplaceExtension(FilePath.StripPath(targetPath), m_sImagePlaceholderExt);
364 if (sourceFile.IsEmpty() || m_sImagePlaceholderSource.IsEmpty())
365 return;
366
367 //--- Read source meta file
368 string placeholderPath = m_ImagePlaceholder.GetPath();
369 string absolutePath;
370 Workbench.GetAbsolutePath(placeholderPath, absolutePath);
371
372 //--- Create directory
373 string imageDirectoryPath = FilePath.StripFileName(targetPath);
374 if (!config.CreateDirectoryFor(imageDirectoryPath, addonName))
375 return;
376
377 //--- Copy texture source
378 FileIO.CopyFile(m_sImagePlaceholderPath + m_sImagePlaceholderSource, addonName + FilePath.StripFileName(targetPath) + sourceFile);
379
380 //--- Register the file
381 Workbench.GetAbsolutePath(addonName + FilePath.StripFileName(targetPath) + sourceFile, absolutePath, false);
382 if (resourceManager.RegisterResourceFile(absolutePath, false))
383 {
384 MetaFile metaContainer = resourceManager.GetMetaFile(absolutePath);
385 if (metaContainer)
386 {
387 //--- Update meta file
388 targetPath = metaContainer.GetResourceID();
389 BaseContainerList configurations = metaContainer.GetObjectArray("Configurations");
390 if (configurations)
391 {
392 configurations.Get(0).Set("ColorSpace", "ToSRGB"); //--- Assume PC is the first
393 metaContainer.Save();
394 Print(string.Format("Editable entity preview image ADDED: @\"%1\"", targetPath), LogLevel.DEBUG);
395 return;
396 }
397 }
398 }
399
400 Print(string.Format("Editable entity preview image creation FAILED: from @\"%1\"", entitySource.GetResourceName().GetPath()), LogLevel.WARNING);
401 }
402
403 //------------------------------------------------------------------------------------------------
404 protected void DeletePreviewImage(EditablePrefabsConfig config, string prefabPath)
405 {
406 //--- Delete the texture and its meta file
407 if (!GetImagePath(config, prefabPath))
408 return;
409
410 FileIO.DeleteFile(prefabPath);
411 FileIO.DeleteFile(prefabPath + META_EXTENSION);
412
413 //--- Delete the source file
414 prefabPath.Replace(IMG_EXTENSION, m_sImagePlaceholderExt);
415 FileIO.DeleteFile(prefabPath);
416 }
417
418 //------------------------------------------------------------------------------------------------
419 protected void MovePreviewImage(EditablePrefabsConfig config, string currentPath, string newPath)
420 {
421 //--- Move texture
422 if (!GetImagePath(config, currentPath))
423 return;
424
425 if (!GetImagePath(config, newPath))
426 return;
427
428 string currentSourcePath = currentPath;
429 string newSourcePath = newPath;
430 currentSourcePath.Replace(IMG_EXTENSION, m_sImagePlaceholderExt);
431 newSourcePath.Replace(IMG_EXTENSION, m_sImagePlaceholderExt);
432
433 FileIO.CopyFile(currentSourcePath, newSourcePath);
434 config.MoveFile(currentPath, newPath); //--- Move the texture
435 FileIO.DeleteFile(currentSourcePath); //--- Delete the old source file only after the texture was renamed, otherwise registration will complain
436 }
437
438 //------------------------------------------------------------------------------------------------
439 protected bool GetImagePath(EditablePrefabsConfig config, out string prefabPath)
440 {
441 if (m_sImagesPath.IsEmpty())
442 return false;
443
444 prefabPath = FilePath.ReplaceExtension(prefabPath, IMG_EXTENSION);
445 if (prefabPath.Replace(config.GetTargetPath(), m_sImagesPath) != 0)
446 return true;
447
448 if (prefabPath.Replace(config.GetSourcePath(), m_sImagesPath) != 0)
449 return true;
450
451 return false;
452 }
453
454 //------------------------------------------------------------------------------------------------
455 protected void SetEntityFlags(EditablePrefabsConfig config, WorldEditorAPI api, ResourceName prefab, string targetPath, IEntitySource entitySource, IEntityComponentSource componentSource, IEntityComponentSource componentCurrent)
456 {
457 EEditableEntityFlag flags, flagsOrig;
458 componentSource.Get("m_Flags", flagsOrig);
459 flags = flagsOrig;
460
461 //--- Composition
462 IEntityComponentSource compositionComponent = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_SlotCompositionComponent);
463 if (compositionComponent)
464 {
465 bool orientChildren;
466 compositionComponent.Get("m_bOrientChildrenToTerrain", orientChildren);
467 if (orientChildren)
468 flags = flags | EEditableEntityFlag.ORIENT_CHILDREN;
469 else
470 flags = flags & ~EEditableEntityFlag.ORIENT_CHILDREN;
471 }
472
473 if (flags != flagsOrig)
474 componentSource.Set("m_Flags", flags);
475 }
476
477 //------------------------------------------------------------------------------------------------
478 protected bool GetLabelsFromSource(WorldEditorAPI api, EditablePrefabsConfig config, ResourceName prefab, string targetPath, IEntitySource entitySource, IEntityComponentSource componentSource, IEntityComponentSource componentSourceCurrent, notnull array<EEditableEntityLabel> autoLabels, notnull array<EEditableEntityLabel> authoredLabels)
479 {
480 EEditableEntityType entityType = EEditableEntityType.GENERIC;
481
482 // Read data from existing editable component first, or fall back on new editable component
483 if (componentSourceCurrent)
484 ReadEditableEntityComponent(componentSourceCurrent, entityType, authoredLabels);
485 else
486 ReadEditableEntityComponent(componentSource, entityType, authoredLabels);
487
488 // Validate label rules, add label if unique
489 foreach (EditablePrefabsLabel_Base labelRule : m_EntityLabelRules)
490 {
492 if (labelRule.GetLabelValid(api, entitySource, componentSource, targetPath, entityType, authoredLabels, label))
493 {
494 //PrintFormat("Autoconfig Label added: %1", typename.EnumToString(EEditableEntityLabel, label));
495 if (!autoLabels.Contains(label) && !authoredLabels.Contains(label))
496 autoLabels.Insert(label);
497 }
498 }
499
500 return true;
501 }
502
503 //------------------------------------------------------------------------------------------------
504 protected void ReadEditableEntityComponent(IEntityComponentSource componentSource, out EEditableEntityType entityType, notnull array<EEditableEntityLabel> authoredLabels)
505 {
506 // Read data from existing editable entity
507 if (!componentSource)
508 return;
509
510 BaseContainer componentUIInfoCurrent = componentSource.GetObject("m_UIInfo");
511 if (componentUIInfoCurrent)
512 componentUIInfoCurrent.Get("m_aAuthoredLabels", authoredLabels);
513
514 // Read editable entity type
515 componentSource.Get("m_EntityType", entityType);
516 }
517
518 //------------------------------------------------------------------------------------------------
519 protected void GetEntityChildrenBudgetCostsFromSource(IEntitySource entitySource, out notnull array<ref SCR_EntityBudgetValue> entityBudgetCosts)
520 {
521 IEntityComponentSource compositionLinkComponent = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_EditorLinkComponent);
522
523 if (entitySource.GetClassName().ToType().IsInherited(SCR_AIGroup))
524 GetEntityBudgetCostsFromGroup(entitySource, entityBudgetCosts);
525 else if (compositionLinkComponent)
526 GetEntityBudgetCostsFromLinkComponent(entitySource, compositionLinkComponent, entityBudgetCosts);
527 }
528
529 //------------------------------------------------------------------------------------------------
530 protected void GetEntityBudgetCostsFromVehicle(IEntitySource entitySource, out notnull array<ref SCR_EntityBudgetValue> crewBudgetCosts, out notnull array<ref SCR_EntityBudgetValue> passengerBudgetCosts, out notnull array<ECompartmentType> vehicleCompartmentTypes)
531 {
532 IEntityComponentSource componentSource;
533 typename componentType;
534 BaseContainerList slots;
535 BaseContainer slot, occupantData;
536 ResourceName prefab;
537 Resource resource;
538 IEntitySource slotEntity;
539
540 array<IEntitySource> queue = {entitySource};
541 while (!queue.IsEmpty())
542 {
543 IEntitySource source = queue[0];
544 queue.Remove(0);
545
546 for (int c = 0, componentCount = source.GetComponentCount(); c < componentCount; c++)
547 {
548 componentSource = source.GetComponent(c);
549 componentType = componentSource.GetClassName().ToType();
550
551 if (componentType.IsInherited(BaseCompartmentManagerComponent))
552 {
553 //--- Find compartments and get budgets of their default occupants
554 slots = componentSource.GetObjectArray("CompartmentSlots");
555 for (int s = 0, slotCount = slots.Count(); s < slotCount; s++)
556 {
557 slot = slots[s];
558
559 occupantData = slot.GetObject("m_DefaultOccupantData");
560 if (!occupantData)
561 continue;
562
563 if (!occupantData.Get("m_sDefaultOccupantPrefab", prefab))
564 continue;
565
566 resource = Resource.Load(prefab);
567 if (!resource.IsValid())
568 continue;
569
570 slotEntity = SCR_BaseContainerTools.FindEntitySource(resource);
571 if (!slotEntity)
572 continue;
573
574 //--- Check for slot type (any type apart from cargo counts as crew)
575 typename slotType = slot.GetClassName().ToType();
576 ECompartmentType compartmentType;
577 if (slotType.IsInherited(CargoCompartmentSlot))
578 {
579 AddBudgetCostsFromEntity(slotEntity, passengerBudgetCosts);
580 compartmentType = ECompartmentType.CARGO;
581 }
582 else
583 {
584 AddBudgetCostsFromEntity(slotEntity, crewBudgetCosts);
585
586 if (slotType.IsInherited(PilotCompartmentSlot))
587 compartmentType = ECompartmentType.PILOT;
588 else
589 compartmentType = ECompartmentType.TURRET;
590 }
591
592 if (!vehicleCompartmentTypes.Contains(compartmentType))
593 vehicleCompartmentTypes.Insert(compartmentType);
594 }
595 }
596 else if (componentType.IsInherited(SlotManagerComponent))
597 {
598 //--- Go deeper into base slots
599 slots = componentSource.GetObjectArray("Slots");
600 for (int s = 0, slotCount = slots.Count(); s < slotCount; s++)
601 {
602 if (!slots[s].Get("Prefab", prefab))
603 continue;
604
605 resource = Resource.Load(prefab);
606 if (!resource.IsValid())
607 continue;
608
609 slotEntity = SCR_BaseContainerTools.FindEntitySource(resource);
610 if (slotEntity)
611 queue.Insert(slotEntity);
612 }
613 }
614 }
615 }
616 }
617
618 //------------------------------------------------------------------------------------------------
619 protected void GetEntityBudgetCostsFromGroup(IEntitySource entitySource, out notnull array<ref SCR_EntityBudgetValue> entityBudgetCosts)
620 {
621 array<ResourceName> memberPrefabs = {};
622
623 entitySource.Get("m_aUnitPrefabSlots", memberPrefabs);
624
625 AddBudgetCostsFromEntities(memberPrefabs, entityBudgetCosts);
626 }
627
628 //------------------------------------------------------------------------------------------------
629 protected void GetEntityBudgetCostsFromLinkComponent(IEntitySource entitySource, IEntityComponentSource compositionLinkComponent, out notnull array<ref SCR_EntityBudgetValue> entityBudgetCosts)
630 {
631 array<ResourceName> childPrefabs = {};
632
633 if (compositionLinkComponent)
634 {
635 Resource resource;
636 BaseContainerList entries = compositionLinkComponent.GetObjectArray("m_aEntries");
637 for (int e = 0, count = entries.Count(); e < count; e++)
638 {
639 SCR_EditorLinkEntry compositionChild = SCR_EditorLinkEntry.Cast(BaseContainerTools.CreateInstanceFromContainer(entries.Get(e)));
640 if (!compositionChild)
641 continue;
642
643 resource = Resource.Load(compositionChild.m_Prefab);
644 if (!resource.IsValid())
645 continue;
646
647 IEntitySource childEntitySource = SCR_BaseContainerTools.FindEntitySource(resource);
648 if (!childEntitySource)
649 continue;
650
651 IEntityComponentSource childEditableEntity = SCR_BaseContainerTools.FindComponentSource(childEntitySource, SCR_EditableEntityComponent);
652 if (!childEditableEntity)
653 continue;
654
655 SCR_EditableEntityUIInfo childUiInfo = SCR_EditableEntityComponentClass.GetInfo(childEditableEntity);
656 if (!childUiInfo)
657 continue;
658
659 array<ref SCR_EntityBudgetValue> entityPreviewBudgetCost = {};
660 childUiInfo.GetEntityChildrenBudgetCost(entityPreviewBudgetCost);
661
662 SCR_EntityBudgetValue.MergeBudgetCosts(entityBudgetCosts, entityPreviewBudgetCost);
663
664 childPrefabs.Insert(compositionChild.m_Prefab);
665 }
666 }
667
668 AddBudgetCostsFromEntities(childPrefabs, entityBudgetCosts);
669 }
670
671 //------------------------------------------------------------------------------------------------
672 protected void AddBudgetCostsFromEntities(array<ResourceName> childPrefabs, out notnull array<ref SCR_EntityBudgetValue> entityBudgetCosts)
673 {
674 int childCount = childPrefabs.Count();
675 Resource resource;
676 foreach (ResourceName childPrefab : childPrefabs)
677 {
678 resource = Resource.Load(childPrefab);
679 if (!resource.IsValid())
680 continue;
681
682 IEntitySource memberEntitySource = SCR_BaseContainerTools.FindEntitySource(resource);
683 if (memberEntitySource)
684 AddBudgetCostsFromEntity(memberEntitySource, entityBudgetCosts);
685 }
686 }
687
688 //------------------------------------------------------------------------------------------------
689 protected void AddBudgetCostsFromEntity(IEntitySource entitySource, out notnull array<ref SCR_EntityBudgetValue> entityBudgetCosts)
690 {
691 IEntityComponentSource editableEntitySource = SCR_EditableEntityComponentClass.GetEditableEntitySource(entitySource);
692 if (!editableEntitySource)
693 return;
694
695 array<ref SCR_EntityBudgetValue> budgetCosts = {};
696 if (SCR_EditableEntityComponentClass.GetEntitySourceBudgetCost(editableEntitySource, budgetCosts))
697 {
698 SCR_EntityBudgetValue.MergeBudgetCosts(entityBudgetCosts, budgetCosts);
699 }
700 else
701 {
702 EEditableEntityBudget entityBudgetType = m_EntityCoreConfig.GetBudgetForEntityType(SCR_EditableEntityComponentClass.GetEntityType(editableEntitySource));
703 int minimumBudgetCost = m_MinBudgetCost.Get(entityBudgetType);
704
705 SCR_EntityBudgetValue.MergeBudgetCosts(entityBudgetCosts, { new SCR_EntityBudgetValue(entityBudgetType, minimumBudgetCost) });
706 }
707 }
708
709 //------------------------------------------------------------------------------------------------
710 override void EOnCreate(EditablePrefabsConfig config, WorldEditorAPI api, ResourceName prefab, string targetPath, IEntitySource entitySource, IEntitySource instanceEntitySource, IEntityComponentSource componentSource, IEntityComponentSource componentCurrent)
711 {
712 SetEntityFlags(config, api, prefab, targetPath, entitySource, componentSource, componentCurrent);
713 SetUIInfo(config, api, prefab, targetPath, entitySource, instanceEntitySource, componentSource, componentCurrent);
714
715 //--- Preserve custom icon pos
716 if (componentCurrent && componentCurrent.IsVariableSetDirectly("m_vIconPos"))
717 {
718 vector iconPos;
719 componentCurrent.Get("m_vIconPos", iconPos);
720 componentSource.Set("m_vIconPos", iconPos.ToString(false));
721 }
722 }
723
724 //------------------------------------------------------------------------------------------------
725 override void EOnDelete(EditablePrefabsConfig config, WorldEditorAPI api, string prefabPath)
726 {
727 DeletePreviewImage(config, prefabPath);
728 }
729
730 //------------------------------------------------------------------------------------------------
731 override void EOnMove(EditablePrefabsConfig config, WorldEditorAPI api, string currentPath, string newPath)
732 {
733 MovePreviewImage(config, currentPath, newPath);
734 }
735
736 //------------------------------------------------------------------------------------------------
737 // constructor
738 void EditablePrefabsComponent_EditableEntity()
739 {
740 if (m_ImagePlaceholder.IsEmpty())
741 {
742 Print("m_ImagePlaceholder not defined!", LogLevel.WARNING);
743 return;
744 }
745
746 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
747 if (!resourceManager)
748 return;
749
750 Resource resource = BaseContainerTools.LoadContainer(m_EntityCoreConfigPrefab);
751 BaseContainer configContainer = resource.GetResource().ToBaseContainer();
752 // Combining two lines below will return null
753 Managed configInstance = BaseContainerTools.CreateInstanceFromContainer(configContainer);
754 m_EntityCoreConfig = SCR_EditableEntityCore.Cast(configInstance);
755 if (!m_EntityCoreConfig)
756 {
757 Print("Editable entity core instance could not be created", LogLevel.ERROR);
758 return;
759 }
760
761 array<ref SCR_EditableEntityCoreBudgetSetting> budgetSettings = {};
762 m_EntityCoreConfig.GetBudgets(budgetSettings);
763
764 foreach (SCR_EditableEntityCoreBudgetSetting budget : budgetSettings)
765 {
766 m_MinBudgetCost.Set(budget.GetBudgetType(), budget.GetMinBudgetCost());
767 }
768
769 string absolutePath;
770 Workbench.GetAbsolutePath(m_ImagePlaceholder.GetPath(), absolutePath);
771
772 m_sImagesPath = m_ImagesDirectory.GetPath();
773 m_sImagePlaceholderPath = FilePath.StripFileName(m_ImagePlaceholder.GetPath());
774
775 MetaFile metaContainer = resourceManager.GetMetaFile(absolutePath);
776 if (!metaContainer)
777 return;
778
779 //--- Get source file and extension
780 BaseContainerList configurations = metaContainer.GetObjectArray("Configurations");
781 for (int i = 0, count = configurations.Count(); i < count; i++)
782 {
783 BaseContainer configuration = configurations.Get(i);
784
785 //--- Read extension from source file - obsolete method
786 configuration.Get("SourceFile", m_sImagePlaceholderSource);
787 if (!m_sImagePlaceholderSource.IsEmpty())
788 {
789 FilePath.StripExtension(m_sImagePlaceholderSource, m_sImagePlaceholderExt);
790 continue;
791 }
792
793 //--- Get extension from configuration class - only PNG is allowed
794 if (configuration.GetClassName() == "PNGResourceClass")
795 {
796 m_sImagePlaceholderExt = "png";
797 m_sImagePlaceholderSource = FilePath.ReplaceExtension(m_ImagePlaceholder, m_sImagePlaceholderExt);
798 m_sImagePlaceholderSource = FilePath.StripPath(m_sImagePlaceholderSource);
799 continue;
800 }
801 else
802 {
803 Print(string.Format("Placeholder file configuration is of type %1, must be PNGResourceClass!", configuration.GetClassName()), LogLevel.ERROR);
804 }
805 }
806 }
807}
808#endif // WORKBENCH
SCR_EAIThreatSectorFlags flags
string path
void ContainerIdPathEntry(string propertyName, int index=-1)
Definition worldEditor.c:30
ECompartmentType
EEditableEntityBudget
EEditableEntityLabel
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
void SCR_AIGroup(IEntitySource src, IEntity parent)
SCR_CampaignMilitaryBaseComponent SCR_MilitaryBaseComponent SCR_BaseContainerCustomTitleResourceName("m_sBaseName", true)
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
void GetEntityChildrenBudgetCost(out notnull array< ref SCR_EntityBudgetValue > outBudgets)
Get only Entity's children budget costs, i.e. cost of entities inside a composition entitiy.
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
EEditableEntityType
Defines type of SCR_EditableEntityComponent. Assigned automatically based on IEntity inheritance.
EEditableEntityFlag
Unique flags of the entity.
SCR_FieldOfViewSettings Attribute
proto T Get(int n)