Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_GeneratorBaseEntity.c
Go to the documentation of this file.
2{
3 [Attribute()]
4 ref Color m_Color;
5}
6
17class SCR_GeneratorBaseEntity : GeneratorBaseEntity
18{
19 /*
20 Generation
21 */
22
23 [Attribute(defvalue: "1", category: "Generation", desc: "Allow entities generation by this generator - useful in order to adjust shape and settings without generating unwanted entities\nKeep it ticked before saving!\nNote: does not prevent terrain shaping and other generator features")]
24 protected bool m_bEnableGeneration;
26 [Attribute(defvalue: DEFAULT_SEED.ToString(), category: "Generation", desc: "Randomisation Seed used by this generator", params: string.Format("%1 %2", MIN_RANDOM_SEED, MAX_RANDOM_SEED))]
27 protected int m_iSeed;
28
29 [Attribute(defvalue: "1", category: "Generation", desc: "Randomise the above seed every change")]
30 protected bool m_bRandomiseSeedOnUse;
31
32 // these consts must be above ifdef as they are used in attributes
33 protected static const int DEFAULT_SEED = 42;
34 protected static const int MIN_RANDOM_SEED = 0;
35 protected static const int MAX_RANDOM_SEED = 0x7FFF; // 32767
36
37#ifdef WORKBENCH
38
39 protected IEntitySource m_Source;
40 protected IEntitySource m_ParentShapeSource;
41 protected int m_iSourceLayerID;
42
44
45 protected bool m_bIsChangingWorkbenchKey;
46
47 protected static const int BASE_GENERATOR_COLOUR = Color.WHITE;
48
49 //------------------------------------------------------------------------------------------------
50 override void _WB_OnParentChange(IEntitySource src, IEntitySource prevParentSrc)
51 {
52 super._WB_OnParentChange(src, prevParentSrc);
53
54 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
55 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
56 return;
57
58 m_Source = src;
59 m_ParentShapeSource = m_Source.GetParent();
60 if (!m_ParentShapeSource
61 || !m_ParentShapeSource.GetClassName().ToType()
62 || !m_ParentShapeSource.GetClassName().ToType().IsInherited(ShapeEntity))
63 DeleteAllChildren();
64 }
65
66 //------------------------------------------------------------------------------------------------
67 override bool _WB_OnKeyChanged(BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
68 {
69 super._WB_OnKeyChanged(src, key, ownerContainers, parent); // true or false does not matter here
70
71 if (m_bIsChangingWorkbenchKey)
72 return false;
73
74 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
75 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
76 return true;
77
78 m_ParentShapeSource = GetShapeSource();
79 bool sameParentChange = parent && worldEditorAPI.EntityToSource(parent) == m_ParentShapeSource;
80
81 // keep the scale at 1
82 if (key == "scale")
83 {
84 bool isSetDirectly = src.IsVariableSetDirectly("scale");
85
86 if (sameParentChange)
87 Print("Do not modify a generator entity itself! Change its parent shape instead", LogLevel.WARNING);
88
89 m_bIsChangingWorkbenchKey = true;
90 if (isSetDirectly)
91 {
92 worldEditorAPI.ClearVariableValue(src, null, "scale");
93 }
94 else
95 {
96 worldEditorAPI.SetVariableValue(src, null, "scale", "1");
97 Print("Generator has scale set in Prefab! " + src.GetResourceName(), LogLevel.WARNING);
98 }
99
100 m_bIsChangingWorkbenchKey = false;
101 }
102
103 // keep the angles at 0
104 if (key == "angles")
105 {
106 bool isSetDirectly = src.IsVariableSetDirectly("angles");
107
108 if (sameParentChange)
109 Print("Do not modify a generator entity itself! Change its parent shape instead", LogLevel.WARNING);
110
111 m_bIsChangingWorkbenchKey = true;
112 if (isSetDirectly)
113 {
114 worldEditorAPI.ClearVariableValue(src, null, "angles");
115 }
116 else // angleValue != 0
117 {
118 worldEditorAPI.SetVariableValue(src, null, "angles", "0 0 0");
119 Print("Generator has angles set in Prefab! " + src.GetResourceName(), LogLevel.WARNING);
120 }
121
122 m_bIsChangingWorkbenchKey = false;
123 }
124
125 // keep the generator at (relative) 0 0 0 as long as it has a parent
126 // if no parent, do not set to 0 0 0
127 // do not warn about no parent here as the constructor does it
128 if (parent && key == "coords")
129 {
130 vector coords;
131 src.Get("coords", coords);
132 bool isSetDirectly = src.IsVariableSetDirectly("coords");
133 if (isSetDirectly || coords != vector.Zero) // because this can trigger when changing parent shape's points
134 {
135 if (sameParentChange)
136 Print("Do not modify a generator entity itself! Change its parent shape instead", LogLevel.WARNING);
137
138 m_bIsChangingWorkbenchKey = true;
139 if (isSetDirectly)
140 {
141 worldEditorAPI.ClearVariableValue(src, null, "coords");
142 }
143 else
144 {
145 worldEditorAPI.SetVariableValue(src, null, "coords", "0 0 0");
146 Print("Generator has coords set in Prefab! " + src.GetResourceName(), LogLevel.WARNING);
147 }
148
149 m_bIsChangingWorkbenchKey = false;
150 }
151 }
152
153 ShapeEntity parentShape = ShapeEntity.Cast(parent);
154 if (parentShape)
155 m_ParentShapeSource = worldEditorAPI.EntityToSource(parentShape);
156 else
157 m_ParentShapeSource = null;
158
159 // let's not save here for now
160 // BaseContainerTools.WriteToInstance(this, worldEditorAPI.EntityToSource(this));
161
162 return true;
163 }
164
165 //------------------------------------------------------------------------------------------------
166 override bool _WB_CanSelect(IEntitySource src)
167 {
168 return false;
169 }
170
171 //------------------------------------------------------------------------------------------------
172 protected override void OnIntersectingShapeChangedXZInternal(IEntitySource shapeEntitySrc, IEntitySource other, array<vector> mins, array<vector> maxes)
173 {
174 super.OnIntersectingShapeChangedXZInternal(shapeEntitySrc, other, mins, maxes);
175 m_ParentShapeSource = shapeEntitySrc;
176 }
177
178 //------------------------------------------------------------------------------------------------
179 override void OnShapeChangedInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity, array<vector> mins, array<vector> maxes)
180 {
181 super.OnShapeChangedInternal(shapeEntitySrc, shapeEntity, mins, maxes);
182 m_ParentShapeSource = shapeEntitySrc;
183 ResetGeneratorPosition(shapeEntity);
184 }
185
186 //------------------------------------------------------------------------------------------------
187 override void OnShapeInitInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity)
188 {
189 super.OnShapeInitInternal(shapeEntitySrc, shapeEntity);
190 m_ParentShapeSource = shapeEntitySrc;
191 // no WorldEditorAPI operations here!
192 }
193
194 //------------------------------------------------------------------------------------------------
195 protected void ResetGeneratorPosition(ShapeEntity shapeEntity = null)
196 {
197 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
198 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
199 return;
200
201 bool manageEditAction = !worldEditorAPI.IsDoingEditAction();
202 if (manageEditAction)
203 worldEditorAPI.BeginEntityAction();
204
205 vector coords;
206 if (m_Source.IsVariableSetDirectly("coords"))
207 worldEditorAPI.ClearVariableValue(m_Source, null, "coords");
208
209 if (m_Source.Get("coords", coords) && coords != vector.Zero)
210 Print("Generator has coords set in Prefab! " + m_Source.GetResourceName(), LogLevel.WARNING);
211
212 if (manageEditAction)
213 worldEditorAPI.EndEntityAction();
214 }
215
216 //------------------------------------------------------------------------------------------------
218 protected void DeleteAllChildren()
219 {
220 int count = m_Source.GetNumChildren();
221 if (count < 1)
222 return;
223
224 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
225 if (!worldEditorAPI)
226 return;
227
228 array<IEntitySource> entities = {};
229 for (int i = m_Source.GetNumChildren() - 1; i >= 0; --i)
230 {
231 entities.Insert(m_Source.GetChild(i));
232 }
233
234 worldEditorAPI.DeleteEntities(entities);
235 }
236
237 //------------------------------------------------------------------------------------------------
239 protected static WorldEditorAPI GetWorldEditorAPI()
240 {
241 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
242 if (!worldEditor)
243 return null;
244
245 return worldEditor.GetApi();
246 }
247
248 //------------------------------------------------------------------------------------------------
249 [Obsolete("Use GetAnchorPoints instead")]
250 protected static array<vector> GetPoints(notnull IEntitySource shapeEntitySrc)
251 {
252 return GetAnchorPoints(shapeEntitySrc);
253 }
254
255 //------------------------------------------------------------------------------------------------
261 protected static array<vector> GetAnchorPoints(notnull IEntitySource shapeEntitySrc, float offset = 0, bool isShapeClosed = false)
262 {
263 BaseContainerList points = shapeEntitySrc.GetObjectArray("Points");
264 if (!points)
265 return {};
266
267 array<vector> result = {};
268 vector pos;
269 for (int i, count = points.Count(); i < count; ++i)
270 {
271 points.Get(i).Get("Position", pos);
272 result.Insert(pos);
273 }
274
275 if (offset == 0)
276 return result;
277 else
278 return SCR_ParallelShapeHelper.GetOffsetPointsFromPoints(result, offset, isShapeClosed);
279 }
280
281 //------------------------------------------------------------------------------------------------
285 protected static array<vector> GetWorldAnchorPoints(notnull IEntitySource shapeEntitySrc)
286 {
287 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
288 if (!worldEditorAPI)
289 return null;
290
291 ShapeEntity shapeEntity = ShapeEntity.Cast(worldEditorAPI.SourceToEntity(shapeEntitySrc));
292 if (!shapeEntity)
293 return null;
294
295 array<vector> result = {};
296 shapeEntity.GetPointsPositions(result);
297
298 foreach (int i, vector point : result)
299 {
300 result[i] = shapeEntity.CoordToParent(point);
301 }
302
303 return result;
304 }
305
306 //------------------------------------------------------------------------------------------------
311 protected static array<vector> GetTesselatedShapePoints(notnull IEntitySource shapeEntitySrc, float offset = 0, bool isShapeClosed = false)
312 {
313 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
314 if (!worldEditorAPI)
315 return null;
316
317 ShapeEntity shapeEntity = ShapeEntity.Cast(worldEditorAPI.SourceToEntity(shapeEntitySrc));
318 if (!shapeEntity)
319 return null;
320
321 array<vector> result = {};
322 shapeEntity.GenerateTesselatedShape(result);
323 if (offset == 0)
324 return result;
325 else
326 return SCR_ParallelShapeHelper.GetOffsetPointsFromPoints(result, offset, isShapeClosed);
327 }
328
329 //------------------------------------------------------------------------------------------------
332 protected static array<vector> GetWorldTesselatedShapePoints(notnull IEntitySource shapeEntitySrc)
333 {
334 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
335 if (!worldEditorAPI)
336 return null;
337
338 ShapeEntity shapeEntity = ShapeEntity.Cast(worldEditorAPI.SourceToEntity(shapeEntitySrc));
339 if (!shapeEntity)
340 return null;
341
342 array<vector> result = {};
343 shapeEntity.GenerateTesselatedShape(result);
344
345 foreach (int i, vector point : result)
346 {
347 result[i] = shapeEntity.CoordToParent(point);
348 }
349
350 return result;
351 }
352
353 //------------------------------------------------------------------------------------------------
356 map<int, ref ShapePointDataScriptBase> GetFirstPointDataMap(typename wantedType = ShapePointDataScriptBase)
357 {
358 if (!m_ParentShapeSource)
359 return null;
360
361 BaseContainerList points = m_ParentShapeSource.GetObjectArray("Points");
362 if (!points)
363 return null;
364
365 map<int, ref ShapePointDataScriptBase> result = new map<int, ref ShapePointDataScriptBase>();
366
367 array<ref ShapePointDataScriptBase> pointDataArray;
368 ShapePointDataScriptBase pointData;
369 for (int i, pointsCount = points.Count(); i < pointsCount; ++i)
370 {
371 if (!points.Get(i).Get("Data", pointDataArray))
372 continue;
373
374 if (wantedType && wantedType != ShapePointDataScriptBase)
375 {
376 for (int j = 0, countJ = pointDataArray.Count(); j < countJ; ++j)
377 {
378 pointData = pointDataArray[j];
379 if (pointData.IsInherited(wantedType))
380 {
381 result.Insert(i, pointData);
382 break;
383 }
384 }
385 }
386 }
387
388 return result;
389 }
390
391 //------------------------------------------------------------------------------------------------
394 map<int, ref array<ref ShapePointDataScriptBase>> GetPointDataMap(typename wantedType = ShapePointDataScriptBase)
395 {
396 if (!m_ParentShapeSource)
397 return null;
398
399 BaseContainerList points = m_ParentShapeSource.GetObjectArray("Points");
400 if (!points)
401 return null;
402
403 map<int, ref array<ref ShapePointDataScriptBase>> result = new map<int, ref array<ref ShapePointDataScriptBase>>();
404
405 array<ref ShapePointDataScriptBase> pointDataArray;
406 for (int i, pointsCount = points.Count(); i < pointsCount; ++i)
407 {
408 if (!points.Get(i).Get("Data", pointDataArray))
409 continue;
410
411 if (wantedType && wantedType != ShapePointDataScriptBase)
412 {
413 for (int j = pointDataArray.Count() - 1; j >= 0; --j)
414 {
415 if (!pointDataArray[j].IsInherited(wantedType))
416 pointDataArray.RemoveOrdered(j);
417 }
418 }
419
420 if (!pointDataArray.IsEmpty())
421 result.Insert(i, pointDataArray);
422
423 pointDataArray = null; // required to generate a new array every Get("Data")
424 }
425
426 return result;
427 }
428
429 //------------------------------------------------------------------------------------------------
430 // (Re)set the random generator's seed
431 protected void SetSeed()
432 {
433 int wantedSeed;
434 if (m_bRandomiseSeedOnUse)
435 wantedSeed = Math.RandomInt(MIN_RANDOM_SEED, MAX_RANDOM_SEED);
436 else
437 wantedSeed = m_iSeed;
438
439 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
440 if (!worldEditorAPI)
441 return;
442
443 IEntitySource source = worldEditorAPI.EntityToSource(this);
444 IEntitySource ancestor = source.GetAncestor();
445 int ancestorSeed;
446 if (!ancestor || !ancestor.Get("m_iSeed", ancestorSeed))
447 ancestorSeed = DEFAULT_SEED;
448
449 m_bIsChangingWorkbenchKey = true;
450
451 if (wantedSeed == ancestorSeed)
452 worldEditorAPI.ClearVariableValue(source, null, "m_iSeed");
453 else
454 worldEditorAPI.SetVariableValue(source, null, "m_iSeed", wantedSeed.ToString());
455
456 m_bIsChangingWorkbenchKey = false;
457
458 m_RandomGenerator.SetSeed(wantedSeed);
459 m_iSeed = wantedSeed;
460 }
461
462 //------------------------------------------------------------------------------------------------
463 protected Color GetColor()
464 {
465 SCR_GeneratorBaseEntityClass prefabData = SCR_GeneratorBaseEntityClass.Cast(GetPrefabData());
466 if (!prefabData)
467 return Color.FromInt(BASE_GENERATOR_COLOUR);
468
469 return Color.FromInt(prefabData.m_Color.PackToInt());
470 }
471
472 //------------------------------------------------------------------------------------------------
473 override void _WB_OnCreate(IEntitySource src) // TODO: change event (_WB_OnInit?) beware of stack overflow by action edit
474 {
475 super._WB_OnCreate(src);
476
477 ColorShape();
478
479 // when generator entity gets created by any edit activity (given by _WB_OnCreate event) then re-generate its generated content
480 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
481 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
482 return;
483
484 // re-generate content only if it's created with a parent
485 IEntitySource shapeEntitySrc = src.GetParent();
486 if (shapeEntitySrc)
487 {
488 ShapeEntity shapeEntity = ShapeEntity.Cast(worldEditorAPI.SourceToEntity(shapeEntitySrc));
489 if (shapeEntity)
490 OnShapeInit(shapeEntitySrc, shapeEntity);
491 }
492
494 src.Get("Flags", flags);
495 bool manageEditAction = !worldEditorAPI.IsDoingEditAction();
496 if (manageEditAction)
497 worldEditorAPI.BeginEntityAction();
498
499 worldEditorAPI.SetVariableValue(src, null, "Flags", (flags | EntityFlags.EDITOR_ONLY).ToString());
500
501 if (manageEditAction)
502 worldEditorAPI.EndEntityAction();
503 }
504
505 //------------------------------------------------------------------------------------------------
507 protected void ColorShape()
508 {
509 if (!m_Source)
510 return;
511
512 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
513 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
514 return;
515
516 IEntitySource parentSource = m_Source.GetParent();
517 if (!parentSource)
518 return;
519
520 array<ref ContainerIdPathEntry> containerPath = {};
521
522 Color color = GetColor();
523 string colorString = string.Format("%1 %2 %3 %4", color.R(), color.G(), color.B(), color.A());
524
525 bool manageEditAction = !worldEditorAPI.IsDoingEditAction();
526 if (manageEditAction)
527 worldEditorAPI.BeginEntityAction();
528
529 worldEditorAPI.SetVariableValue(parentSource, containerPath, "LineColor", colorString);
530
531 if (manageEditAction)
532 worldEditorAPI.EndEntityAction();
533 }
534
535 //------------------------------------------------------------------------------------------------
537 protected IEntitySource GetShapeSource()
538 {
539 if (!m_Source)
540 {
541 Print("[SCR_GeneratorBaseEntity.GetShapeSource] no generator source available (" + __FILE__ + " L" + __LINE__ + ")", LogLevel.ERROR);
542 return null;
543 }
544
545 IEntitySource parentSource = m_Source.GetParent();
546 if (!parentSource)
547 return null;
548
549 if (!parentSource.GetClassName().ToType() || !parentSource.GetClassName().ToType().IsInherited(ShapeEntity))
550 return null;
551
552 return parentSource;
553
554// while (parentSource)
555// {
556// if (parentSource.GetClassName().ToType() && parentSource.GetClassName().ToType().IsInherited(ShapeEntity))
557// return parentSource;
558//
559// parentSource = parentSource.GetParent();
560// }
561//
562// return null;
563 }
564
565#endif // WORKBENCH
566
567 //------------------------------------------------------------------------------------------------
568 // constructor
569 protected void SCR_GeneratorBaseEntity(IEntitySource src, IEntity parent)
570 {
571
572#ifdef WORKBENCH
573
574 if (!_WB_GetEditorAPI()) // thumbnail generation
575 return;
576
577 m_Source = src;
578 m_iSourceLayerID = m_Source.GetLayerID();
579
580 m_RandomGenerator = new RandomGenerator();
581
582 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
583 if (worldEditor && !ShapeEntity.Cast(parent) && !worldEditor.IsPrefabEditMode())
584 {
585 Print("A Generator is not a direct child of a shape - " + Debug.GetEntityLinkString(this), LogLevel.WARNING);
586 return;
587 }
588
589 m_ParentShapeSource = m_Source.GetParent();
590
591#endif // WORKBENCH
592
593 }
594}
SCR_EAIThreatSectorFlags flags
ref array< string > coords
ref RandomGenerator m_RandomGenerator
override bool _WB_OnKeyChanged(IEntity owner, BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
Any property value has been changed. You can use editor API here and do some additional edit actions ...
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
SCR_VehicleDamageManagerComponentClass GetPrefabData()
proto native external bool IsInherited(typename type)
enum EVehicleType IEntity
Definition Color.c:13
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
void OnIntersectingShapeChangedXZInternal(IEntitySource shapeEntitySrc, IEntitySource other, array< vector > mins, array< vector > maxes)
void OnShapeInitInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity)
void OnShapeChangedInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity, array< vector > mins, array< vector > maxes)
EntityFlags
Various entity flags.
Definition EntityFlags.c:14
GeneratorBaseEntityClass GenericEntityClass OnShapeInit(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity)
void Debug()
Definition Types.c:327