7class SCR_ObstacleDetector
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;
28 protected float m_fOceanLevel;
29 protected ref TraceSphere m_AvoidObjectTraceSphere;
33 void SetAvoidObjects(
bool avoidObjects)
35 m_bAvoidObjects = avoidObjects;
40 void SetAvoidObjectsDetectionRadius(
float radius)
45 m_fAvoidObjectsDetectionRadius = radius;
46 if (m_AvoidObjectTraceSphere)
47 m_AvoidObjectTraceSphere.Radius = m_fAvoidObjectsDetectionRadius;
52 void SetAvoidObjectsDetectionHeight(
float height)
54 m_fAvoidObjectsDetectionHeight = height;
55 if (m_AvoidObjectTraceSphere)
56 m_AvoidObjectTraceSphere.End[1] = m_AvoidObjectTraceSphere.Start[1] + m_fAvoidObjectsDetectionHeight;
61 void SetAvoidRoads(
bool avoidRoads)
63 m_bAvoidRoads = avoidRoads;
68 void SetAvoidRivers(
bool avoidRivers)
70 m_bAvoidRivers = avoidRivers;
75 void SetAvoidPowerLines(
bool avoidPowerLines)
77 m_bAvoidPowerLines = avoidPowerLines;
82 void SetAvoidTracks(
bool avoidTracks)
84 m_bAvoidTracks = avoidTracks;
89 void SetAvoidForests(
bool avoidForests)
91 m_bAvoidForests = avoidForests;
96 void SetAvoidLakes(
bool avoidLakes)
98 m_bAvoidLakes = avoidLakes;
103 void SetAvoidLand(
bool avoidLand)
105 m_bAvoidLand = avoidLand;
110 void SetAvoidOcean(
bool avoidOcean)
112 m_bAvoidOcean = avoidOcean;
118 void SetAvoidLandOceanOffset(
float offset)
120 m_fAvoidLandOceanOffset = offset;
128 void RefreshObstaclesByAABB(vector worldMin, vector worldMax)
130 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
131 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
134 SetupObstacleArrays(
true,
true);
135 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
136 worldEditorAPI.GetWorld().QueryEntitiesByAABB(worldMin, worldMax, AllSplineQueryFilter);
142 void RefreshObstaclesByWorld()
144 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
145 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
149 worldEditorAPI.GetWorld().GetBoundBox(min, max);
150 RefreshObstaclesByAABB(min, max);
158 void RefreshRoadObstaclesBySphere(vector worldPos,
float radius)
160 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
161 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
164 SetupObstacleArrays(
true,
false);
165 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
166 worldEditorAPI.GetWorld().QueryEntitiesBySphere(worldPos, radius, RoadSplineQueryFilter);
174 void RefreshAreaObstaclesBySphere(vector worldPos,
float radius)
176 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
177 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
180 SetupObstacleArrays(
false,
true);
181 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
182 worldEditorAPI.GetWorld().QueryEntitiesBySphere(worldPos, radius, AreaSplineQueryFilter);
188 void RefreshAreaObstaclesByWorld()
190 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
191 if (!worldEditorAPI || !worldEditorAPI.GetWorld())
194 SetupObstacleArrays(
false,
true);
195 m_fOceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
198 worldEditorAPI.GetWorld().GetBoundBox(min, max);
199 worldEditorAPI.GetWorld().QueryEntitiesByAABB(min, max, AreaSplineQueryFilter);
207 bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
209 if (!m_aAvoidInfoRoads)
211 Print(
"SCR_ObstacleDetector.HasObstacle() method requires obtaining obstacles info through SCR_ObstacleDetector.RefreshObstaclesBy*() method first",
LogLevel.ERROR);
215 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
219 BaseWorld world = worldEditorAPI.GetWorld();
225 if (m_bAvoidLand && m_bAvoidOcean)
228 float terrainY = world.GetSurfaceY(worldPos[0], worldPos[2]);
230 if (m_bAvoidOcean && terrainY < m_fOceanLevel + m_fAvoidLandOceanOffset)
233 if (m_bAvoidLand && terrainY > m_fOceanLevel + m_fAvoidLandOceanOffset)
239 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoForests)
241 if (Math2D.IsPointInPolygon(info.m_a2DPoints, worldPos[0], worldPos[2]))
248 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoLakes)
250 if (worldPos[1] < info.m_fLakeSurfaceY && Math2D.IsPointInPolygon(info.m_a2DPoints, worldPos[0], worldPos[2]))
257 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoRoads)
259 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
266 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoRivers)
268 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
273 if (m_bAvoidPowerLines)
275 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoPowerLines)
277 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
284 foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoTracks)
286 if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
292 if (m_bAvoidObjects && (m_fAvoidObjectsDetectionHeight != 0 || m_fAvoidObjectsDetectionHeight > 0))
294 if (!m_AvoidObjectTraceSphere)
296 m_AvoidObjectTraceSphere =
new TraceSphere();
297 m_AvoidObjectTraceSphere.Radius = m_fAvoidObjectsDetectionRadius;
299 m_AvoidObjectTraceSphere.Flags =
TraceFlags.ENTS;
302 m_AvoidObjectTraceSphere.Start = worldPos;
303 m_AvoidObjectTraceSphere.End = { worldPos[0], worldPos[1] + m_fAvoidObjectsDetectionHeight, worldPos[2] };
306 m_AvoidObjectTraceSphere.ExcludeArray = exclusionList;
307 else if (m_AvoidObjectTraceSphere.ExcludeArray)
308 m_AvoidObjectTraceSphere.ExcludeArray.Clear();
310 world.TraceMove(m_AvoidObjectTraceSphere, null);
312 if (m_AvoidObjectTraceSphere.TraceEnt)
322 bool HasObstaclesList()
324 return m_aAvoidInfoRoads != null;
331 protected void SetupObstacleArrays(
bool setupRoadSplines,
bool setupAreaSplines)
334 if (setupRoadSplines || !m_aAvoidInfoRoads)
335 m_aAvoidInfoRoads = {};
337 if (setupRoadSplines || !m_aAvoidInfoRivers)
338 m_aAvoidInfoRivers = {};
340 if (setupRoadSplines || !m_aAvoidInfoPowerLines)
341 m_aAvoidInfoPowerLines = {};
343 if (setupRoadSplines || !m_aAvoidInfoTracks)
344 m_aAvoidInfoTracks = {};
347 if (setupAreaSplines || !m_aAvoidInfoForests)
348 m_aAvoidInfoForests = {};
350 if (setupAreaSplines || !m_aAvoidInfoLakes)
351 m_aAvoidInfoLakes = {};
358 array<ref SCR_ObstacleDetectorSplineInfo> GetObstacles()
360 if (!m_aAvoidInfoRoads)
363 array<ref SCR_ObstacleDetectorSplineInfo> result = {};
364 array<array<ref SCR_ObstacleDetectorSplineInfo>> arrays = {
367 m_aAvoidInfoPowerLines,
373 foreach (array<ref SCR_ObstacleDetectorSplineInfo> arr : arrays)
375 foreach (SCR_ObstacleDetectorSplineInfo info : arr)
386 void ClearObstacles()
388 m_aAvoidInfoRoads = null;
389 m_aAvoidInfoRivers = null;
390 m_aAvoidInfoPowerLines = null;
391 m_aAvoidInfoTracks = null;
392 m_aAvoidInfoForests = null;
393 m_aAvoidInfoLakes = null;
402 protected bool BaseSplineQueryFilter(
IEntity entity,
bool getRoadSplines,
bool getAreaSplines)
404 if (!getRoadSplines && !getAreaSplines)
407 ShapeEntity shapeEntity = ShapeEntity.Cast(entity);
411 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
415 IEntitySource shapeSource = worldEditorAPI.EntityToSource(shapeEntity);
419 IEntitySource generatorSource;
420 typename generatorTypename;
422 for (
int i, count = shapeSource.GetNumChildren(); i < count; ++i)
424 generatorSource = shapeSource.GetChild(i);
425 generatorTypename = generatorSource.GetClassName().ToType();
426 if (!generatorTypename)
431 if (generatorTypename.IsInherited(RoadGeneratorEntity))
433 m_aAvoidInfoRoads.Insert(
new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
437 if (generatorTypename.IsInherited(RiverEntity))
439 m_aAvoidInfoRivers.Insert(
new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
443 if (generatorTypename.IsInherited(SCR_PowerlineGeneratorEntity))
445 m_aAvoidInfoPowerLines.Insert(
new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
449 if (generatorTypename.IsInherited(SCR_TrackGeneratorEntity))
451 m_aAvoidInfoTracks.Insert(
new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
458 if (generatorTypename.IsInherited(ForestGeneratorEntity))
460 m_aAvoidInfoForests.Insert(
new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
464 if (generatorTypename.IsInherited(LakeGeneratorEntity) && generatorSource.Get(
"m_bIsLake", isLake) && isLake)
466 m_aAvoidInfoLakes.Insert(
new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
477 protected bool AllSplineQueryFilter(
IEntity entity)
479 return BaseSplineQueryFilter(entity,
true,
true);
484 protected bool RoadSplineQueryFilter(
IEntity entity)
486 return BaseSplineQueryFilter(entity,
true,
false);
491 protected bool AreaSplineQueryFilter(
IEntity entity)
493 return BaseSplineQueryFilter(entity,
false,
true);
497class SCR_ObstacleDetectorSplineInfo
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;
511 bool IsNearRoadSplineXZ(vector point)
516 if (x < m_vMinWithClearance[0] || m_vMaxWithClearance[0] < x ||
517 z < m_vMinWithClearance[2] || m_vMaxWithClearance[2] < z)
521 foreach (
int index, vector min : m_aMinsWithClearance)
523 max = m_aMaxsWithClearance[
index];
524 if (min[0] <= x && x <= max[0])
526 if (min[2] <= z && z <= max[2])
540 protected void GetAndSetMinMaxWithClearance(inout notnull array<vector> mins, inout notnull array<vector> maxs, out vector min, out vector max)
542 vector vectorClearance = { m_fClearance, 0, m_fClearance };
543 int minsCount = mins.Count();
544 int maxsCount = maxs.Count();
546 if (minsCount < 1 || maxsCount < 1 || minsCount != maxsCount)
548 min = -vectorClearance;
549 max = vectorClearance;
554 for (
int i; i < minsCount; i++)
556 mins[i] = mins[i] - vectorClearance;
557 for (
int j; j < 3; j++)
559 if (min[j] > mins[i][j])
565 for (
int i; i < maxsCount; i++)
567 maxs[i] = maxs[i] + vectorClearance;
568 for (
int j; j < 3; j++)
570 if (max[j] < maxs[i][j])
582 protected static int GetPoints2D3D(notnull ShapeEntity shapeEntity, out array<float> pos2D, out array<vector> pos3D)
584 if (!pos2D && !pos3D)
587 array<vector> points3D = {};
588 shapeEntity.GetPointsPositions(points3D);
596 foreach (vector point : points3D)
598 point = shapeEntity.CoordToParent(point);
601 pos2D.Insert(point[0]);
602 pos2D.Insert(point[2]);
609 return points3D.Count();
613 protected array<vector> GetTesselatedWorldPoints(notnull ShapeEntity shapeEntity)
615 array<vector> result = {};
617 shapeEntity.GenerateTesselatedShape(result);
618 for (
int i, count = result.Count(); i < count; i++)
620 result[i] = shapeEntity.CoordToParent(result[i]);
631 void SCR_ObstacleDetectorSplineInfo(notnull IEntitySource shapeEntitySource, notnull ShapeEntity shapeEntity, notnull IEntitySource generatorSource)
633 typename generatorTypeName = generatorSource.GetClassName().ToType();
634 if (!generatorTypeName)
637 m_aMinsWithClearance = {};
638 m_aMaxsWithClearance = {};
643 if (generatorTypeName.IsInherited(RoadGeneratorEntity))
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);
656 if (generatorTypeName.IsInherited(RiverEntity) ||
657 generatorTypeName.IsInherited(SCR_PowerlineGeneratorEntity))
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);
669 if (generatorTypeName.IsInherited(SCR_TrackGeneratorEntity))
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);
681 if (generatorTypeName.IsInherited(ForestGeneratorEntity))
684 GetPoints2D3D(shapeEntity, m_a2DPoints, null);
691 if (generatorTypeName.IsInherited(LakeGeneratorEntity))
694 array<vector> a3DPoints = {};
695 GetPoints2D3D(shapeEntity, m_a2DPoints, a3DPoints);
697 bool flattenByBottomPlane;
698 generatorSource.Get(
"m_bFlattenByBottomPlane", flattenByBottomPlane);
700 if (a3DPoints.IsEmpty())
704 float minOrMaxY = a3DPoints[0][1];
705 foreach (vector a3DPoint : a3DPoints)
707 if (flattenByBottomPlane)
709 if (a3DPoint[1] < minOrMaxY)
710 minOrMaxY = a3DPoint[1];
714 if (a3DPoint[1] > minOrMaxY)
715 minOrMaxY = a3DPoint[1];
719 m_fLakeSurfaceY = minOrMaxY;
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
enum EVehicleType IEntity
EPhysicsLayerPresets
Enum is filled by C++ by data in project config PhysicsSettings.LayerPresets.
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.