Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_EntityFlagsManagerPlugin.c
Go to the documentation of this file.
1#ifdef WORKBENCH
5 name: "Entity Flags Manager",
6 description: "Reset all/selected entities' desired flags to Prefab's default",
7 shortcut: "Ctrl+Shift+F",
8 wbModules: { "WorldEditor" })]
9class SCR_EntityFlagsManagerPlugin : WorldEditorPlugin
10{
11 /*
12 Category: Flags
13 */
14
15 [Attribute(defvalue: "0", category: "Flags")]
16 protected bool m_bResetTraceableFlag;
17
18 [Attribute(defvalue: "0", category: "Flags")]
19 protected bool m_bResetVisibleFlag;
20
21 [Attribute(defvalue: "0", category: "Flags")]
22 protected bool m_bResetStaticFlag;
23
24 [Attribute(defvalue: "0", category: "Flags")]
25 protected bool m_bResetFeatureFlag;
26
27 [Attribute(defvalue: "0", category: "Flags")]
28 protected bool m_bResetNoLinkFlag;
29
30 [Attribute(defvalue: "0", category: "Flags")]
31 protected bool m_bResetProxyFlag;
32
33 [Attribute(defvalue: "0", category: "Flags")]
34 protected bool m_bResetEditorOnlyFlag;
35
36 [Attribute(defvalue: "0", category: "Flags")]
37 protected bool m_bResetDisabledFlag;
38
39 [Attribute(defvalue: "0", category: "Flags")]
40 protected bool m_bResetRelativeYFlag;
41
42 [Attribute(defvalue: "0", category: "Flags")]
43 protected bool m_bResetOnFilteredNavmeshFlag;
44
45 /*
46 Category: Entities
47 */
48
49 [Attribute(defvalue: "0", category: "Entities")]
50 protected bool m_bProcessEverythingSelected;
51/*
52 [Attribute(defvalue: "1", category: "Entities")]
53 protected bool m_bCurrentLayerOnly;
54*/
55 [Attribute(defvalue: "1", category: "Entities")]
56 protected bool m_bProcessRocks;
57
58 [Attribute(defvalue: "1", category: "Entities")]
59 protected bool m_bProcessTrees;
60
61 [Attribute(defvalue: "1", category: "Entities")]
62 protected bool m_bProcessBushes;
63
64 [Attribute(defvalue: "1", category: "Entities")]
65 protected bool m_bProcessBuildings;
66/*
67 [Attribute(category: "Entities")]
68 protected array<ResourceName> m_aOtherTopMostPrefabs;
69*/
70 /*
71 Category: Options
72 */
73
74 [Attribute(defvalue: "0", desc: "[COSTY] Process child entities - may be problematic with e.g forest generators", category: "Options")]
75 protected bool m_bUpdateChildEntities;
76
77 [Attribute(defvalue: "0", desc: "Force flags cleaning - slower but sure to remove unneeded flags", category: "Options")]
78 protected bool m_bForceCleaning;
79
80 protected static const int PROGRESSBAR_TIMEOUT = 3000;
81 protected static const int PROGRESSBAR_REFRESH = 1000;
82 protected static const string COORDS = "coords";
83 protected static const string FLAGS = "Flags";
84 protected static const ResourceName ROCK_BASE = "{B94DDC61F0B7F9D7}Prefabs/Rocks/Rock_Base.et";
85 protected static const ResourceName TREE_BASE = "{388AE316D09D0680}Prefabs/Vegetation/Core/Tree_Base.et";
86 protected static const ResourceName BUSH_BASE = "{D7163D1B571F4C0C}Prefabs/Vegetation/Core/Bush_Base.et";
87 protected static const ResourceName BUILDING_BASE = "{A43A100E3C377DB2}Prefabs/Structures/Core/Building_Base.et";
88
89 //------------------------------------------------------------------------------------------------
90 override void Run()
91 {
92 WorldEditorAPI worldEditorAPI = SCR_WorldEditorToolHelper.GetWorldEditorAPI();
93 if (!worldEditorAPI)
94 {
95 Print("World Editor API is not available", LogLevel.ERROR);
96 return;
97 }
98
99 int selectedCount = worldEditorAPI.GetSelectedEntitiesCount();
100 string message = "Entities currently selected: " + selectedCount;
101
102 if (selectedCount < 1)
103 {
104 m_bProcessEverythingSelected = false; // safety
105 message += "\n\n[ WARNING: you are about to process ALL TERRAIN ENTITIES ]";
106 }
107
108 // filter
109 if (!Workbench.ScriptDialog("Entity Flags Manager", message, this))
110 return;
111
112 if (!(
113 m_bResetTraceableFlag ||
114 m_bResetVisibleFlag ||
115 m_bResetStaticFlag ||
116 m_bResetFeatureFlag ||
117 m_bResetNoLinkFlag ||
118 m_bResetProxyFlag ||
119 m_bResetEditorOnlyFlag ||
120 m_bResetDisabledFlag ||
121 m_bResetRelativeYFlag ||
122 m_bResetOnFilteredNavmeshFlag
123 ))
124 {
125 Print("No Flags were selected for reset; leaving", LogLevel.WARNING);
126 return;
127 }
128
129 // prepare
130 array<ResourceName> validTopMostAncestors = {};
131 if (!m_bProcessEverythingSelected)
132 {
133 if (m_bProcessRocks)
134 validTopMostAncestors.Insert(ROCK_BASE);
135
136 if (m_bProcessTrees)
137 validTopMostAncestors.Insert(TREE_BASE);
138
139 if (m_bProcessBushes)
140 validTopMostAncestors.Insert(BUSH_BASE);
141
142 if (m_bProcessBuildings)
143 validTopMostAncestors.Insert(BUILDING_BASE);
144
145 if (validTopMostAncestors.IsEmpty())
146 {
147 Print("No Entity Types have been selected; leaving", LogLevel.WARNING);
148 return;
149 }
150 }
151
152 // get entities
153 array<IEntitySource> entitySources = GetEntitySources(validTopMostAncestors);
154
155 int entitySourcesCount = entitySources.Count();
156 if (entitySourcesCount < 1)
157 {
158 Print("No entities found; exiting", LogLevel.NORMAL);
159 return;
160 }
161
162 // process
163 ProcessEntitySources(entitySources);
164
165 // leave!
166 }
167
168 //------------------------------------------------------------------------------------------------
169 protected void ProcessEntitySources(array<IEntitySource> entitySources)
170 {
171 int entitySourcesCount = entitySources.Count();
172
173 int lastRefresh = System.GetTickCount();
174 WBProgressDialog progress;
175
176 vector entityPos;
177 int clearedFlags, editedFlags, fixed;
178
179 WorldEditorAPI worldEditorAPI = SCR_WorldEditorToolHelper.GetWorldEditorAPI();
180
181 Debug.BeginTimeMeasure();
182 worldEditorAPI.BeginEntityAction();
183
184 foreach (int i, IEntitySource entitySource : entitySources)
185 {
186 if (!entitySource.GetAncestor())
187 continue;
188
189 EntityFlags oldFlags;
190 if (!entitySource.Get(FLAGS, oldFlags))
191 {
192 Print("Could not get flags from entitySource", LogLevel.WARNING);
193 continue;
194 }
195
196 EntityFlags prefabFlags;
197 if (!entitySource.GetAncestor().Get(FLAGS, prefabFlags))
198 {
199 Print("Could not get flags from Prefab", LogLevel.WARNING);
200 continue;
201 }
202
203 EntityFlags newFlags = oldFlags;
204
205 bool useEditSequence = m_bResetRelativeYFlag; // due to flag + pos
206 if (useEditSequence)
207 worldEditorAPI.BeginEditSequence(entitySource);
208
209 /*
210 FLAGS
211 */
212
213 if (m_bResetTraceableFlag)
214 {
215 if (prefabFlags & EntityFlags.TRACEABLE)
216 newFlags |= EntityFlags.TRACEABLE;
217 else
218 newFlags &= ~EntityFlags.TRACEABLE;
219 }
220
221 if (m_bResetVisibleFlag)
222 {
223 if (prefabFlags & EntityFlags.VISIBLE)
224 newFlags |= EntityFlags.VISIBLE;
225 else
226 newFlags &= ~EntityFlags.VISIBLE;
227 }
228
229 if (m_bResetStaticFlag)
230 {
231 if (prefabFlags & EntityFlags.STATIC)
232 newFlags |= EntityFlags.STATIC;
233 else
234 newFlags &= ~EntityFlags.STATIC;
235 }
236
237 if (m_bResetFeatureFlag)
238 {
239 if (prefabFlags & EntityFlags.FEATURE)
240 newFlags |= EntityFlags.FEATURE;
241 else
242 newFlags &= ~EntityFlags.FEATURE;
243 }
244
245 if (m_bResetNoLinkFlag)
246 {
247 if (prefabFlags & EntityFlags.NO_LINK)
248 newFlags |= EntityFlags.NO_LINK;
249 else
250 newFlags &= ~EntityFlags.NO_LINK;
251 }
252
253 if (m_bResetProxyFlag)
254 {
255 if (prefabFlags & EntityFlags.PROXY)
256 newFlags |= EntityFlags.PROXY;
257 else
258 newFlags &= ~EntityFlags.PROXY;
259 }
260
261 if (m_bResetEditorOnlyFlag)
262 {
263 if (prefabFlags & EntityFlags.EDITOR_ONLY)
264 newFlags |= EntityFlags.EDITOR_ONLY;
265 else
266 newFlags &= ~EntityFlags.EDITOR_ONLY;
267 }
268
269 if (m_bResetDisabledFlag)
270 {
271 if (prefabFlags & EntityFlags.DISABLED)
272 newFlags |= EntityFlags.DISABLED;
273 else
274 newFlags &= ~EntityFlags.DISABLED;
275 }
276
277 if (m_bResetRelativeYFlag)
278 {
279 if (prefabFlags & EntityFlags.RELATIVE_Y)
280 newFlags |= EntityFlags.RELATIVE_Y;
281 else
282 newFlags &= ~EntityFlags.RELATIVE_Y;
283
284 if (oldFlags & EntityFlags.RELATIVE_Y) // if currently ATL
285 {
286 if (!(newFlags & EntityFlags.RELATIVE_Y)) // to World
287 {
288 // ATL to World
289 float y;
290 entitySource.Get(COORDS, entityPos);
291 if (worldEditorAPI.TryGetTerrainSurfaceY(entityPos[0], entityPos[2], y))
292 entityPos[1] = entityPos[1] + y;
293 else
294 Print("Entity " + worldEditorAPI.SourceToEntity(entitySource).GetID() + " position cannot be changed (ATL to World)", LogLevel.WARNING);
295 }
296 else
297 {
298 entityPos = vector.Zero;
299 }
300 }
301 else // if currently World
302 {
303 if (newFlags & EntityFlags.RELATIVE_Y) // to ATL
304 {
305 // World to ATL
306 float y;
307 entitySource.Get(COORDS, entityPos);
308 if (worldEditorAPI.TryGetTerrainSurfaceY(entityPos[0], entityPos[2], y))
309 entityPos[1] = entityPos[1] - y;
310 else
311 Print("Entity " + worldEditorAPI.SourceToEntity(entitySource).GetID() + " position cannot be changed (World to ATL)", LogLevel.WARNING);
312 }
313 else
314 {
315 entityPos = vector.Zero;
316 }
317 }
318 }
319
320 if (m_bResetOnFilteredNavmeshFlag)
321 {
322 if (prefabFlags & EntityFlags.USER4) // OnFilteredNavmesh
323 newFlags |= EntityFlags.USER4;
324 else
325 newFlags &= ~EntityFlags.USER4;
326 }
327
328 /*
329 /FLAGS
330 */
331
332 // identical
333 if (!m_bForceCleaning && oldFlags == newFlags && newFlags == prefabFlags)
334 continue;
335
336 if (newFlags == prefabFlags)
337 {
338 worldEditorAPI.ClearVariableValue(entitySource, null, FLAGS);
339 clearedFlags++;
340 }
341 else
342 if (newFlags != oldFlags)
343 {
344 worldEditorAPI.SetVariableValue(entitySource, null, FLAGS, newFlags.ToString());
345 editedFlags++;
346 }
347
348 // relativeY aftermath
349 if (m_bResetRelativeYFlag && entityPos != vector.Zero)
350 worldEditorAPI.SetVariableValue(entitySource, null, COORDS, entityPos.ToString(false));
351
352 if (oldFlags != newFlags)
353 fixed++;
354
355 if (useEditSequence) // due to flag + pos
356 worldEditorAPI.EndEditSequence(entitySource);
357
358 int timeDiff = System.GetTickCount() - lastRefresh;
359 if (!progress)
360 {
361 if (timeDiff > PROGRESSBAR_TIMEOUT)
362 {
363 progress = new WBProgressDialog("Processing " + entitySourcesCount + " entities...", Workbench.GetModule(WorldEditor));
364 progress.SetProgress(i / entitySourcesCount);
365 }
366 }
367 else
368 if (timeDiff > PROGRESSBAR_REFRESH)
369 {
370 progress.SetProgress(i / entitySourcesCount);
371 lastRefresh = System.GetTickCount();
372 }
373 }
374
375 worldEditorAPI.EndEntityAction();
376 Debug.EndTimeMeasure("Entity flag fixing");
377
378 Print("Fixed " + fixed + "/" + entitySourcesCount + " entities (edited: " + editedFlags + " / cleared " + clearedFlags + ")", LogLevel.NORMAL);
379 }
380
381 //------------------------------------------------------------------------------------------------
384 // \param[out] filteredCount - how many entities remain after filter < removed for now
386 protected array<IEntitySource> GetEntitySources(array<ResourceName> validAncestors)
387 {
388 int originalCount;
389 array<IEntitySource> result = {};
390 WorldEditorAPI worldEditorAPI = SCR_WorldEditorToolHelper.GetWorldEditorAPI();
391 int selectedCount = worldEditorAPI.GetSelectedEntitiesCount();
392
393 Debug.BeginTimeMeasure();
394 if (selectedCount > 0)
395 {
396 IEntitySource entitySource;
397 originalCount = selectedCount;
398 result.Reserve(selectedCount);
399 for (int i = 0; i < selectedCount; i++)
400 {
401 entitySource = worldEditorAPI.GetSelectedEntity(i);
402
403 if (!entitySource)
404 continue;
405
406 if (!m_bUpdateChildEntities && entitySource.GetParent())
407 continue;
408
409 if (m_bProcessEverythingSelected || validAncestors.Contains(SCR_BaseContainerTools.GetTopMostAncestor(entitySource).GetResourceName()))
410 result.Insert(entitySource);
411 }
412 }
413 else
414 {
415 int entitiesCount = worldEditorAPI.GetEditorEntityCount(); // maximum possible (almost)
416 originalCount = entitiesCount;
417 result.Reserve(entitiesCount);
418 IEntitySource entitySource;
419 for (int i = 0; i < entitiesCount; i++)
420 {
421 entitySource = worldEditorAPI.GetEditorEntity(i);
422 if (!entitySource)
423 continue;
424
425 if (!m_bUpdateChildEntities && entitySource.GetParent())
426 continue;
427
428 // m_bProcessEverythingSelected must not be introduced here
429 if (validAncestors.Contains(SCR_BaseContainerTools.GetTopMostAncestor(entitySource).GetResourceName()))
430 result.Insert(entitySource);
431 }
432 }
433 Debug.EndTimeMeasure("Filtering " + result.Count() + "/" + originalCount + " entities");
434
435 return result;
436 }
437
438 //------------------------------------------------------------------------------------------------
439 [ButtonAttribute("OK", true)]
440 protected bool BtnOK()
441 {
442 return true;
443 }
444
445 //------------------------------------------------------------------------------------------------
446 [ButtonAttribute("Cancel")]
447 protected bool BtnCancel()
448 {
449 return false;
450 }
451}
452#endif // WORKBENCH
GenerateFlowMaps WorkbenchPlugin WorkbenchPluginAttribute("Regenerate river flow-maps", "Generate and save/overwrite river flow-maps", "", "", {"WorldEditor"}, "", 0xf773)
Definition FlowmapTool.c:59
override void Run()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
Definition Debug.c:13
proto external EntityID GetID()
@ FLAGS
Flag-set type.
Definition DataVarType.c:45
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
EntityFlags
Various entity flags.
Definition EntityFlags.c:14