Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ObstacleDetector.c
Go to the documentation of this file.
1#ifdef WORKBENCH
2
7class SCR_ObstacleDetector
8{
9 protected bool m_bAvoidObjects;
10 protected float m_fAvoidObjectsDetectionRadius;
11 protected float m_fAvoidObjectsDetectionHeight;
12 protected bool m_bAvoidRoads;
13 protected bool m_bAvoidRivers;
14 protected bool m_bAvoidPowerLines;
15 protected bool m_bAvoidTracks;
16 protected bool m_bAvoidForests;
17 protected bool m_bAvoidLakes;
18 protected bool m_bAvoidLand;
19 protected bool m_bAvoidOcean;
20 protected float m_fAvoidLandOceanOffset;
21 protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoRoads;
22 protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoRivers;
23 protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoPowerLines;
24 protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoTracks;
25 protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoLakes;
26 protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoForests;
27
28 protected float m_fOceanLevel;
29 protected ref TraceSphere m_AvoidObjectTraceSphere;
30
31 //------------------------------------------------------------------------------------------------
33 void SetAvoidObjects(bool avoidObjects)
34 {
35 m_bAvoidObjects = avoidObjects;
36 }
37
38 //------------------------------------------------------------------------------------------------
40 void SetAvoidObjectsDetectionRadius(float radius)
41 {
42 if (radius < 0)
43 radius = 0;
44
45 m_fAvoidObjectsDetectionRadius = radius;
46 if (m_AvoidObjectTraceSphere)
47 m_AvoidObjectTraceSphere.Radius = m_fAvoidObjectsDetectionRadius;
48 }
49
50 //------------------------------------------------------------------------------------------------
52 void SetAvoidObjectsDetectionHeight(float height)
53 {
54 m_fAvoidObjectsDetectionHeight = height;
55 if (m_AvoidObjectTraceSphere)
56 m_AvoidObjectTraceSphere.End[1] = m_AvoidObjectTraceSphere.Start[1] + m_fAvoidObjectsDetectionHeight;
57 }
58
59 //------------------------------------------------------------------------------------------------
61 void SetAvoidRoads(bool avoidRoads)
62 {
63 m_bAvoidRoads = avoidRoads;
64 }
65
66 //------------------------------------------------------------------------------------------------
68 void SetAvoidRivers(bool avoidRivers)
69 {
70 m_bAvoidRivers = avoidRivers;
71 }
72
73 //------------------------------------------------------------------------------------------------
75 void SetAvoidPowerLines(bool avoidPowerLines)
76 {
77 m_bAvoidPowerLines = avoidPowerLines;
78 }
79
80 //------------------------------------------------------------------------------------------------
82 void SetAvoidTracks(bool avoidTracks)
83 {
84 m_bAvoidTracks = avoidTracks;
85 }
86
87 //------------------------------------------------------------------------------------------------
89 void SetAvoidForests(bool avoidForests)
90 {
91 m_bAvoidForests = avoidForests;
92 }
93
94 //------------------------------------------------------------------------------------------------
96 void SetAvoidLakes(bool avoidLakes)
97 {
98 m_bAvoidLakes = avoidLakes;
99 }
100
101 //------------------------------------------------------------------------------------------------
103 void SetAvoidLand(bool avoidLand)
104 {
105 m_bAvoidLand = avoidLand;
106 }
107
108 //------------------------------------------------------------------------------------------------
110 void SetAvoidOcean(bool avoidOcean)
111 {
112 m_bAvoidOcean = avoidOcean;
113 }
114
115 //------------------------------------------------------------------------------------------------
118 void SetAvoidLandOceanOffset(float offset)
119 {
120 m_fAvoidLandOceanOffset = offset;
121 }
122
123 //------------------------------------------------------------------------------------------------
127 // used by SCR_GeneratorBaseEntity.RefreshObstacles() (and RefreshObstaclesByWorld() which is unused)
128 void RefreshObstaclesByAABB(vector worldMin, vector worldMax)
129 {
130 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
131 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
132 return;
133
134 SetupObstacleArrays(true, true);
135 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
136 worldEditorAPI.GetWorld().QueryEntitiesByAABB(worldMin, worldMax, AllSplineQueryFilter);
137 }
138
139 //------------------------------------------------------------------------------------------------
141 // unused
142 void RefreshObstaclesByWorld()
143 {
144 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
145 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
146 return;
147
148 vector min, max;
149 worldEditorAPI.GetWorld().GetBoundBox(min, max);
150 RefreshObstaclesByAABB(min, max);
151 }
152
153 //------------------------------------------------------------------------------------------------
157 // used by ObjectBrushTool.CreateObjects()
158 void RefreshRoadObstaclesBySphere(vector worldPos, float radius)
159 {
160 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
161 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
162 return;
163
164 SetupObstacleArrays(true, false);
165 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
166 worldEditorAPI.GetWorld().QueryEntitiesBySphere(worldPos, radius, RoadSplineQueryFilter);
167 }
168
169 //------------------------------------------------------------------------------------------------
173 // used by ObjectBrushTool.OnMousePressEvent()
174 void RefreshAreaObstaclesBySphere(vector worldPos, float radius)
175 {
176 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
177 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
178 return;
179
180 SetupObstacleArrays(false, true);
181 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
182 worldEditorAPI.GetWorld().QueryEntitiesBySphere(worldPos, radius, AreaSplineQueryFilter);
183 }
184
185 //------------------------------------------------------------------------------------------------
187 // used by ObjectBrushTool.OnMousePressEvent()
188 void RefreshAreaObstaclesByWorld()
189 {
190 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
191 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
192 return;
193
194 SetupObstacleArrays(false, true);
195 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
196
197 vector min, max;
198 worldEditorAPI.GetWorld().GetBoundBox(min, max);
199 worldEditorAPI.GetWorld().QueryEntitiesByAABB(min, max, AreaSplineQueryFilter);
200 }
201
202 //------------------------------------------------------------------------------------------------
207 bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
208 {
209 if (!m_aAvoidInfoRoads) // a null array means obstacles were cleared or never initialised
210 {
211 Print("SCR_ObstacleDetector.HasObstacle() method requires obtaining obstacles info through SCR_ObstacleDetector.RefreshObstaclesBy*() method first", LogLevel.ERROR);
212 return true; // prevent placement by default
213 }
214
215 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
216 if (!worldEditorAPI)
217 return true;
218
219 BaseWorld world = worldEditorAPI.GetWorld();
220 if (!world)
221 return true;
222
223 if (world.IsOcean())
224 {
225 if (m_bAvoidLand && m_bAvoidOcean)
226 return true; // let's save some time
227
228 float terrainY = world.GetSurfaceY(worldPos[0], worldPos[2]);
229
230 if (m_bAvoidOcean && terrainY < m_fOceanLevel + m_fAvoidLandOceanOffset)
231 return true;
232
233 if (m_bAvoidLand && terrainY > m_fOceanLevel + m_fAvoidLandOceanOffset)
234 return true;
235 }
236
237 if (m_bAvoidForests)
238 {
239 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoForests)
240 {
241 if (Math2D.IsPointInPolygon(info.m_a2DPoints, worldPos[0], worldPos[2]))
242 return true;
243 }
244 }
245
246 if (m_bAvoidLakes)
247 {
248 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoLakes)
249 {
250 if (worldPos[1] < info.m_fLakeSurfaceY && Math2D.IsPointInPolygon(info.m_a2DPoints, worldPos[0], worldPos[2]))
251 return true;
252 }
253 }
254
255 if (m_bAvoidRoads)
256 {
257 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoRoads)
258 {
259 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
260 return true;
261 }
262 }
263
264 if (m_bAvoidRivers)
265 {
266 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoRivers)
267 {
268 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
269 return true;
270 }
271 }
272
273 if (m_bAvoidPowerLines)
274 {
275 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoPowerLines)
276 {
277 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
278 return true;
279 }
280 }
281
282 if (m_bAvoidTracks)
283 {
284 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoTracks)
285 {
286 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
287 return true;
288 }
289 }
290
291 // tracing is the expensive part
292 if (m_bAvoidObjects && (m_fAvoidObjectsDetectionHeight != 0 || m_fAvoidObjectsDetectionHeight > 0))
293 {
294 if (!m_AvoidObjectTraceSphere)
295 {
296 m_AvoidObjectTraceSphere = new TraceSphere();
297 m_AvoidObjectTraceSphere.Radius = m_fAvoidObjectsDetectionRadius;
298 m_AvoidObjectTraceSphere.LayerMask = EPhysicsLayerPresets.Main | EPhysicsLayerDefs.Water; // is Water required?
299 m_AvoidObjectTraceSphere.Flags = TraceFlags.ENTS;
300 }
301
302 m_AvoidObjectTraceSphere.Start = worldPos;
303 m_AvoidObjectTraceSphere.End = { worldPos[0], worldPos[1] + m_fAvoidObjectsDetectionHeight, worldPos[2] }; // move up
304
305 if (exclusionList)
306 m_AvoidObjectTraceSphere.ExcludeArray = exclusionList;
307 else if (m_AvoidObjectTraceSphere.ExcludeArray)
308 m_AvoidObjectTraceSphere.ExcludeArray.Clear();
309
310 world.TraceMove(m_AvoidObjectTraceSphere, null);
311
312 if (m_AvoidObjectTraceSphere.TraceEnt) // or TraceMove < 1
313 return true;
314 }
315
316 return false;
317 }
318
319 //------------------------------------------------------------------------------------------------
322 bool HasObstaclesList()
323 {
324 return m_aAvoidInfoRoads != null;
325 }
326
327 //------------------------------------------------------------------------------------------------
331 protected void SetupObstacleArrays(bool setupRoadSplines, bool setupAreaSplines)
332 {
333 // roads
334 if (setupRoadSplines || !m_aAvoidInfoRoads)
335 m_aAvoidInfoRoads = {};
336
337 if (setupRoadSplines || !m_aAvoidInfoRivers)
338 m_aAvoidInfoRivers = {};
339
340 if (setupRoadSplines || !m_aAvoidInfoPowerLines)
341 m_aAvoidInfoPowerLines = {};
342
343 if (setupRoadSplines || !m_aAvoidInfoTracks)
344 m_aAvoidInfoTracks = {};
345
346 // areas
347 if (setupAreaSplines || !m_aAvoidInfoForests)
348 m_aAvoidInfoForests = {};
349
350 if (setupAreaSplines || !m_aAvoidInfoLakes)
351 m_aAvoidInfoLakes = {};
352 }
353
354 //------------------------------------------------------------------------------------------------
356 // TODO: separate areas (Forest for now) vs splines
358 array<ref SCR_ObstacleDetectorSplineInfo> GetObstacles()
359 {
360 if (!m_aAvoidInfoRoads) // a null array means obstacles were cleared or never initialised
361 return null;
362
363 array<ref SCR_ObstacleDetectorSplineInfo> result = {};
364 array<array<ref SCR_ObstacleDetectorSplineInfo>> arrays = {
365 m_aAvoidInfoRoads,
366 m_aAvoidInfoRivers,
367 m_aAvoidInfoPowerLines,
368 m_aAvoidInfoTracks,
369 m_aAvoidInfoForests,
370 m_aAvoidInfoLakes,
371 };
372
373 foreach (array<ref SCR_ObstacleDetectorSplineInfo> arr : arrays)
374 {
375 foreach (SCR_ObstacleDetectorSplineInfo info : arr)
376 {
377 result.Insert(info);
378 }
379 }
380
381 return result;
382 }
383
384 //------------------------------------------------------------------------------------------------
386 void ClearObstacles()
387 {
388 m_aAvoidInfoRoads = null;
389 m_aAvoidInfoRivers = null;
390 m_aAvoidInfoPowerLines = null;
391 m_aAvoidInfoTracks = null;
392 m_aAvoidInfoForests = null;
393 m_aAvoidInfoLakes = null;
394 }
395
396 //------------------------------------------------------------------------------------------------
402 protected bool BaseSplineQueryFilter(IEntity entity, bool getRoadSplines, bool getAreaSplines)
403 {
404 if (!getRoadSplines && !getAreaSplines)
405 return true;
406
407 ShapeEntity shapeEntity = ShapeEntity.Cast(entity);
408 if (!shapeEntity)
409 return true;
410
411 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
412 if (!worldEditorAPI)
413 return true;
414
415 IEntitySource shapeSource = worldEditorAPI.EntityToSource(shapeEntity);
416 if (!shapeSource)
417 return true;
418
419 IEntitySource generatorSource;
420 typename generatorTypename;
421 bool isLake;
422 for (int i, count = shapeSource.GetNumChildren(); i < count; ++i)
423 {
424 generatorSource = shapeSource.GetChild(i);
425 generatorTypename = generatorSource.GetClassName().ToType();
426 if (!generatorTypename)
427 continue;
428
429 if (getRoadSplines)
430 {
431 if (generatorTypename.IsInherited(RoadGeneratorEntity))
432 {
433 m_aAvoidInfoRoads.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
434 break;
435 }
436
437 if (generatorTypename.IsInherited(RiverEntity))
438 {
439 m_aAvoidInfoRivers.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
440 break;
441 }
442
443 if (generatorTypename.IsInherited(SCR_PowerlineGeneratorEntity))
444 {
445 m_aAvoidInfoPowerLines.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
446 break;
447 }
448
449 if (generatorTypename.IsInherited(SCR_TrackGeneratorEntity))
450 {
451 m_aAvoidInfoTracks.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
452 break;
453 }
454 }
455
456 if (getAreaSplines)
457 {
458 if (generatorTypename.IsInherited(ForestGeneratorEntity))
459 {
460 m_aAvoidInfoForests.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
461 break;
462 }
463
464 if (generatorTypename.IsInherited(LakeGeneratorEntity) && generatorSource.Get("m_bIsLake", isLake) && isLake)
465 {
466 m_aAvoidInfoLakes.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
467 break;
468 }
469 }
470 }
471
472 return true;
473 }
474
475 //------------------------------------------------------------------------------------------------
477 protected bool AllSplineQueryFilter(IEntity entity)
478 {
479 return BaseSplineQueryFilter(entity, true, true);
480 }
481
482 //------------------------------------------------------------------------------------------------
484 protected bool RoadSplineQueryFilter(IEntity entity)
485 {
486 return BaseSplineQueryFilter(entity, true, false);
487 }
488
489 //------------------------------------------------------------------------------------------------
491 protected bool AreaSplineQueryFilter(IEntity entity)
492 {
493 return BaseSplineQueryFilter(entity, false, true);
494 }
495}
496
497class SCR_ObstacleDetectorSplineInfo
498{
499 float m_fClearance;
500 float m_fLakeSurfaceY;
501 ref array<float> m_a2DPoints;
502 ref array<vector> m_aTesselatedPoints;
503 ref array<vector> m_aMinsWithClearance;
504 ref array<vector> m_aMaxsWithClearance;
505 vector m_vMinWithClearance;
506 vector m_vMaxWithClearance;
507
508 //------------------------------------------------------------------------------------------------
511 bool IsNearRoadSplineXZ(vector point)
512 {
513 float x = point[0];
514 float z = point[2];
515
516 if (x < m_vMinWithClearance[0] || m_vMaxWithClearance[0] < x ||
517 z < m_vMinWithClearance[2] || m_vMaxWithClearance[2] < z)
518 return false; // nowhere near
519
520 vector max;
521 foreach (int index, vector min : m_aMinsWithClearance)
522 {
523 max = m_aMaxsWithClearance[index];
524 if (min[0] <= x && x <= max[0])
525 {
526 if (min[2] <= z && z <= max[2])
527 return true;
528 }
529 }
530
531 return false;
532 }
533
534 //------------------------------------------------------------------------------------------------
539 // minor performance gains to add clearance to mins/maxs but gains nonetheless (e.g 500ms on 20s calculation so ~= 2.5% on big area)
540 protected void GetAndSetMinMaxWithClearance(inout notnull array<vector> mins, inout notnull array<vector> maxs, out vector min, out vector max)
541 {
542 vector vectorClearance = { m_fClearance, 0, m_fClearance };
543 int minsCount = mins.Count();
544 int maxsCount = maxs.Count();
545
546 if (minsCount < 1 || maxsCount < 1 || minsCount != maxsCount)
547 {
548 min = -vectorClearance;
549 max = vectorClearance;
550 return;
551 }
552
553 min = mins[0];
554 for (int i; i < minsCount; i++)
555 {
556 mins[i] = mins[i] - vectorClearance;
557 for (int j; j < 3; j++)
558 {
559 if (min[j] > mins[i][j])
560 min[j] = mins[i][j];
561 }
562 }
563
564 max = maxs[0];
565 for (int i; i < maxsCount; i++)
566 {
567 maxs[i] = maxs[i] + vectorClearance;
568 for (int j; j < 3; j++)
569 {
570 if (max[j] < maxs[i][j])
571 max[j] = maxs[i][j];
572 }
573 }
574 }
575
576 //------------------------------------------------------------------------------------------------
582 protected static int GetPoints2D3D(notnull ShapeEntity shapeEntity, out array<float> pos2D, out array<vector> pos3D)
583 {
584 if (!pos2D && !pos3D)
585 return -1;
586
587 array<vector> points3D = {};
588 shapeEntity.GetPointsPositions(points3D);
589
590 if (pos2D)
591 pos2D.Clear();
592
593 if (pos3D)
594 pos3D.Clear();
595
596 foreach (vector point : points3D)
597 {
598 point = shapeEntity.CoordToParent(point);
599 if (pos2D)
600 {
601 pos2D.Insert(point[0]);
602 pos2D.Insert(point[2]);
603 }
604
605 if (pos3D)
606 pos3D.Insert(point);
607 }
608
609 return points3D.Count();
610 }
611
612 //------------------------------------------------------------------------------------------------
613 protected array<vector> GetTesselatedWorldPoints(notnull ShapeEntity shapeEntity)
614 {
615 array<vector> result = {};
616
617 shapeEntity.GenerateTesselatedShape(result);
618 for (int i, count = result.Count(); i < count; i++)
619 {
620 result[i] = shapeEntity.CoordToParent(result[i]);
621 }
622
623 return result;
624 }
625
626 //------------------------------------------------------------------------------------------------
627 // constructor
631 void SCR_ObstacleDetectorSplineInfo(notnull IEntitySource shapeEntitySource, notnull ShapeEntity shapeEntity, notnull IEntitySource generatorSource)
632 {
633 typename generatorTypeName = generatorSource.GetClassName().ToType();
634 if (!generatorTypeName)
635 return;
636
637 m_aMinsWithClearance = {};
638 m_aMaxsWithClearance = {};
639
640 /*
641 ROAD
642 */
643 if (generatorTypeName.IsInherited(RoadGeneratorEntity))
644 {
645 generatorSource.Get("RoadClearance", m_fClearance);
646 m_aTesselatedPoints = GetTesselatedWorldPoints(shapeEntity);
647 shapeEntity.GetAllInfluenceBBoxes(shapeEntitySource, m_aMinsWithClearance, m_aMaxsWithClearance);
648 GetAndSetMinMaxWithClearance(m_aMinsWithClearance, m_aMaxsWithClearance, m_vMinWithClearance, m_vMaxWithClearance);
649 return;
650 }
651
652 /*
653 RIVER,
654 POWER LINE
655 */
656 if (generatorTypeName.IsInherited(RiverEntity) ||
657 generatorTypeName.IsInherited(SCR_PowerlineGeneratorEntity))
658 {
659 generatorSource.Get("Clearance", m_fClearance);
660 m_aTesselatedPoints = GetTesselatedWorldPoints(shapeEntity);
661 shapeEntity.GetAllInfluenceBBoxes(shapeEntitySource, m_aMinsWithClearance, m_aMaxsWithClearance);
662 GetAndSetMinMaxWithClearance(m_aMinsWithClearance, m_aMaxsWithClearance, m_vMinWithClearance, m_vMaxWithClearance);
663 return;
664 }
665
666 /*
667 TRACK
668 */
669 if (generatorTypeName.IsInherited(SCR_TrackGeneratorEntity))
670 {
671 generatorSource.Get("m_fClearance", m_fClearance);
672 m_aTesselatedPoints = GetTesselatedWorldPoints(shapeEntity);
673 shapeEntity.GetAllInfluenceBBoxes(shapeEntitySource, m_aMinsWithClearance, m_aMaxsWithClearance);
674 GetAndSetMinMaxWithClearance(m_aMinsWithClearance, m_aMaxsWithClearance, m_vMinWithClearance, m_vMaxWithClearance);
675 return;
676 }
677
678 /*
679 FOREST
680 */
681 if (generatorTypeName.IsInherited(ForestGeneratorEntity))
682 {
683 m_a2DPoints = {};
684 GetPoints2D3D(shapeEntity, m_a2DPoints, null);
685 return;
686 }
687
688 /*
689 LAKE
690 */
691 if (generatorTypeName.IsInherited(LakeGeneratorEntity))
692 {
693 m_a2DPoints = {};
694 array<vector> a3DPoints = {};
695 GetPoints2D3D(shapeEntity, m_a2DPoints, a3DPoints);
696
697 bool flattenByBottomPlane;
698 generatorSource.Get("m_bFlattenByBottomPlane", flattenByBottomPlane);
699
700 if (a3DPoints.IsEmpty())
701 return;
702
703 // all this to be replaced with a later LakeGeneratorEntity method
704 float minOrMaxY = a3DPoints[0][1];
705 foreach (vector a3DPoint : a3DPoints)
706 {
707 if (flattenByBottomPlane)
708 {
709 if (a3DPoint[1] < minOrMaxY)
710 minOrMaxY = a3DPoint[1];
711 }
712 else
713 {
714 if (a3DPoint[1] > minOrMaxY)
715 minOrMaxY = a3DPoint[1];
716 }
717 }
718
719 m_fLakeSurfaceY = minOrMaxY;
720 return;
721 }
722 }
723}
724
725#endif // WORKBENCH
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
enum EVehicleType IEntity
EPhysicsLayerPresets
Enum is filled by C++ by data in project config PhysicsSettings.LayerPresets.
Definition gameLib.c:19
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
TraceFlags
Definition TraceFlags.c:13