Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_WorldEditorToolHelper.c
Go to the documentation of this file.
1#ifdef WORKBENCH
2class SCR_WorldEditorToolHelper
3{
4 protected static ref array<IEntity> s_aTempEntities;
5
6 protected static const string WEB_PREFIX = "https://enfusionengine.com/api/redirect?to=";
7
8 //------------------------------------------------------------------------------------------------
11 static ResourceManager GetResourceManager()
12 {
13 return Workbench.GetModule(ResourceManager);
14 }
15
16 //------------------------------------------------------------------------------------------------
19 static WorldEditor GetWorldEditor()
20 {
21 return Workbench.GetModule(WorldEditor);
22 }
23
24 //------------------------------------------------------------------------------------------------
27 static WorldEditorAPI GetWorldEditorAPI()
28 {
29 WorldEditor worldEditor = GetWorldEditor();
30 if (!worldEditor)
31 return null;
32
33 return worldEditor.GetApi();
34 }
35
36 //------------------------------------------------------------------------------------------------
39 static IEntitySource GetPrefabEditModeEntitySource()
40 {
41 WorldEditor worldEditor = GetWorldEditor();
42 if (!worldEditor)
43 return null;
44
45 if (!worldEditor.IsPrefabEditMode())
46 return null;
47
48 WorldEditorAPI worldEditorAPI = worldEditor.GetApi();
49 if (worldEditorAPI.GetEditorEntityCount() != 2) // world and Entity
50 return null;
51
52 return worldEditorAPI.GetEditorEntity(1);
53 }
54
55 //------------------------------------------------------------------------------------------------
58 static ResourceName GetPrefabEditModeResourceName()
59 {
60 IEntitySource entitySource = GetPrefabEditModeEntitySource();
61 if (!entitySource)
62 return string.Empty;
63
64 BaseContainer ancestor = entitySource.GetAncestor();
65 if (!ancestor)
66 return string.Empty;
67
68 return ancestor.GetResourceName();
69 }
70
71 //------------------------------------------------------------------------------------------------
75 static string GetCurrentWorldEditorLink(bool useWebPrefix = false)
76 {
77 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
78 if (!worldEditorAPI)
79 return string.Empty;
80
81 BaseWorld world = worldEditorAPI.GetWorld();
82 if (!world)
83 return string.Empty;
84
85 vector transform[4];
86 world.GetCurrentCamera(transform);
87
88 return SCR_WorldEditorToolHelper.GetCurrentWorldEditorLink(transform[3], Math3D.MatrixToAngles(transform), useWebPrefix);
89 }
90
91 //------------------------------------------------------------------------------------------------
98 static string GetCurrentWorldEditorLink(vector position, vector angles, bool useWebPrefix = false)
99 {
100 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
101 if (!worldEditorAPI)
102 return string.Empty;
103
104 string fullLink;
105 worldEditorAPI.GetWorldPath(fullLink);
106
107 if (fullLink.IsEmpty())
108 return string.Empty;
109
110 string worldPath = fullLink;
111 if (worldPath[0] == "$")
112 worldPath = "~" + worldPath.Substring(1, worldPath.Length() - 1);
113 else
114 if (worldPath[0] != "~")
115 {
116 // if we don't have an exact path (should not happen),
117 // fallback to the original solution:
118
119 // we want to substring only /worlds/(...)
120 // to prevent exposing local folders, etc.
121 string fullLinkLC = fullLink;
122 fullLinkLC.ToLower();
123
124 int begin = fullLinkLC.IndexOf("worlds\\");
125 if (begin == -1)
126 begin = fullLinkLC.IndexOf("worlds/");
127
128 if (begin == -1)
129 return string.Empty;
130
131 worldPath = fullLink.Substring(begin, fullLink.Length() - begin);
132 }
133
134 // Have consistent link
135 worldPath.Replace("\\", "/");
136
137 if (position == vector.Zero && angles == vector.Zero)
138 return "enfusion://WorldEditor/" + worldPath;
139
140 string result = string.Format(
141 "enfusion://WorldEditor/%1;%2,%3,%4;%5,%6,%7",
142 worldPath,
143 position[0],
144 position[1],
145 position[2],
146 angles[1],
147 angles[0],
148 angles[2]);
149
150 if (useWebPrefix)
151 return WEB_PREFIX + result;
152 else
153 return result;
154 }
155
156 //------------------------------------------------------------------------------------------------
158 static string GetWorldName()
159 {
160 string result = FilePath.StripExtension(FilePath.StripPath(GetWorldPath()));
161 if (!result) // .IsEmpty()
162 return "Unknown";
163
164 return result;
165 }
166
167 //------------------------------------------------------------------------------------------------
169 static string GetWorldPath()
170 {
171 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
172 if (!worldEditorAPI)
173 return string.Empty;
174
175 string result;
176 worldEditorAPI.GetWorldPath(result);
177 return result;
178 }
179
180 //------------------------------------------------------------------------------------------------
182 static bool IsWorldLoaded()
183 {
184 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
185 if (!worldEditor)
186 return false;
187
188 if (worldEditor.IsPrefabEditMode())
189 return false;
190
191 WorldEditorAPI worldEditorAPI = worldEditor.GetApi();
192 if (!worldEditorAPI)
193 return false;
194
195 string worldPath;
196 worldEditorAPI.GetWorldPath(worldPath);
197 return worldPath && worldEditorAPI.GetWorld() != null; // !.IsEmpty()
198 }
199
200 //------------------------------------------------------------------------------------------------
202 static bool HasTerrainMesh()
203 {
204 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
205 if (!worldEditor)
206 return false;
207
208 vector min, max;
209 worldEditor.GetTerrainBounds(min, max);
210 return max != vector.Zero || min != vector.Zero;
211 }
212
213 //------------------------------------------------------------------------------------------------
215 static IEntitySource GetTerrainEntitySource()
216 {
217 WorldEditor worldEditor = GetWorldEditor();
218 if (!worldEditor)
219 return null;
220
221 if (worldEditor.IsPrefabEditMode())
222 return null;
223
224 WorldEditorAPI worldEditorAPI = worldEditor.GetApi();
225 if (worldEditorAPI.GetEditorEntityCount() < 2) // world and Entity
226 return null;
227
228 IEntitySource entitySource;
229 for (int i, entitiesCount = worldEditorAPI.GetEditorEntityCount(); i < entitiesCount; ++i)
230 {
231 entitySource = worldEditorAPI.GetEditorEntity(i);
232 if (entitySource && entitySource.GetClassName().ToType() && entitySource.GetClassName().ToType().IsInherited(GenericTerrainEntity))
233 return entitySource;
234 }
235
236 return null;
237 }
238
239 //------------------------------------------------------------------------------------------------
241 static vector GetTerrainDimensions()
242 {
243 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
244 vector min, max;
245 worldEditor.GetTerrainBounds(min, max);
246 return max - min;
247 }
248
249 //------------------------------------------------------------------------------------------------
252 static void GetTerrainMinMaxY(out float minY, out float maxY)
253 {
254 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
255 vector min, max;
256 worldEditor.GetTerrainBounds(min, max);
257
258 minY = min[1];
259 maxY = max[1];
260 }
261
262 //------------------------------------------------------------------------------------------------
266 static bool GetTerrainMinMaxElevationPositions(out vector min, out vector max)
267 {
268 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
269 if (!HasTerrainMesh())
270 return false;
271
272 float minY, maxY;
273 GetTerrainMinMaxY(minY, maxY);
274
275 vector terrainPosition = GetTerrainPosition();
276 float minX = terrainPosition[0];
277 float minZ = terrainPosition[2];
278
279 vector terrainDimensions = GetTerrainDimensions();
280 float maxX = minX + terrainDimensions[0];
281 float maxZ = minZ + terrainDimensions[2];
282
283 float step = worldEditorAPI.GetTerrainUnitScale();
284
285 bool hasMinY, hasMaxY;
286
287 float y;
288 for (float z = minZ, limitZ = maxZ; z <= limitZ; z += step)
289 {
290 for (float x = minX, limitX = maxX; x <= limitX; x += step)
291 {
292 if (!worldEditorAPI.TryGetTerrainSurfaceY(x, z, y))
293 continue;
294
295 if (!hasMaxY && y == maxY)
296 {
297 max = { x, y, z };
298 hasMaxY = true;
299 }
300 else
301 if (!hasMinY && y == minY)
302 {
303 min = { x, y, z };
304 hasMinY = true;
305 }
306
307 if (hasMinY && hasMaxY)
308 return true;
309 }
310 }
311
312 return hasMinY && hasMaxY;
313 }
314
315 //------------------------------------------------------------------------------------------------
319 static float GetTerrainLandArea(int terrainIndex = 0)
320 {
321 if (terrainIndex < 0)
322 return -1;
323
324 WorldEditorAPI worldEditorAPI = SCR_WorldEditorToolHelper.GetWorldEditorAPI();
325
326 BaseWorld world = worldEditorAPI.GetWorld();
327 if (!world)
328 return -1;
329
330 const float cellSideSize = worldEditorAPI.GetTerrainUnitScale(terrainIndex);
331 if (cellSideSize <= 0)
332 return -1; // wrong terrain index or no terrain loaded
333
334 const float cellSideSizeSq = cellSideSize * cellSideSize;
335
336 if (!world.IsOcean()) // no ocean = everything is land
337 {
338 return cellSideSizeSq
339 * (worldEditorAPI.GetTerrainResolutionX(terrainIndex) - 1)
340 * (worldEditorAPI.GetTerrainResolutionY(terrainIndex) - 1);
341 }
342
343 const float oceanLevel = worldEditorAPI.GetWorld().GetOceanBaseHeight();
344 if (oceanLevel == -float.MAX) // just some safety, most likely not needed
345 {
346 return cellSideSizeSq
347 * (worldEditorAPI.GetTerrainResolutionX(terrainIndex) - 1)
348 * (worldEditorAPI.GetTerrainResolutionY(terrainIndex) - 1);
349 }
350
351 const int tileXCount = worldEditorAPI.GetTerrainTilesX(terrainIndex);
352 const int tileYCount = worldEditorAPI.GetTerrainTilesY(terrainIndex);
353
354 const int tileSideSizeX = (worldEditorAPI.GetTerrainResolutionX(terrainIndex) - 1) / tileXCount;
355 const int tileSideSizeY = (worldEditorAPI.GetTerrainResolutionY(terrainIndex) - 1) / tileYCount;
356
357 const int tileArea = tileSideSizeX * tileSideSizeY;
358 const int tileValuesCount = (tileSideSizeX + 1) * (tileSideSizeY + 1); // +1 - e.g 32×32 cells = 33×33 vertices
359 array<float> tileYs = {};
360 tileYs.Resize(tileValuesCount);
361
362 float result;
363
364 int bottomLeftIndex, bottomRightIndex;
365 float topLeftY, bottomLeftY, topRightY, bottomRightY;
366 bool aboveZeroTL, aboveZeroTR, aboveZeroBL, aboveZeroBR;
367 bool tileHasAboveZeroArea, tileHasBelowZeroArea;
368 for (int tileY; tileY < tileYCount; ++tileY)
369 {
370 for (int tileX; tileX < tileXCount; ++tileX)
371 {
372 if (!worldEditorAPI.GetTerrainSurfaceTile(terrainIndex, tileX, tileY, tileYs))
373 {
374 PrintFormat("Invalid tile %1:%2", tileX, tileY, level: LogLevel.ERROR);
375 return -1;
376 }
377
378 tileHasAboveZeroArea = false;
379 tileHasBelowZeroArea = false;
380 foreach (float yValue : tileYs)
381 {
382 if (yValue >= oceanLevel)
383 {
384 tileHasAboveZeroArea = true;
385 if (tileHasBelowZeroArea)
386 break;
387 }
388 else
389 {
390 tileHasBelowZeroArea = true;
391 if (tileHasAboveZeroArea)
392 break;
393 }
394 }
395
396 if (!tileHasAboveZeroArea) // full underwater
397 continue;
398
399 if (!tileHasBelowZeroArea) // full above water
400 {
401 result += tileArea * cellSideSizeSq;
402 continue;
403 }
404
405 float tileSurface; // intermediate variable needed for big terrains (e.g Balta) due to float precision
406 for (int tileValueY = 1; tileValueY <= tileSideSizeY; ++tileValueY)
407 {
408 for (int tileValueX = 1; tileValueX <= tileSideSizeX; ++tileValueX)
409 {
410 if (tileValueX == 1)
411 {
412 bottomLeftIndex = tileValueX - 1 + tileSideSizeY * (tileValueY - 1);
413 topLeftY = tileYs[bottomLeftIndex + tileSideSizeY];
414 bottomLeftY = tileYs[bottomLeftIndex];
415 }
416 else
417 {
418 bottomLeftIndex = bottomRightIndex;
419 topLeftY = topRightY;
420 bottomLeftY = bottomRightY;
421 }
422
423 bottomRightIndex = bottomLeftIndex + 1;
424 topRightY = tileYs[bottomLeftIndex + tileSideSizeY + 1];
425 bottomRightY = tileYs[bottomRightIndex];
426
427 aboveZeroTL = topLeftY >= 0;
428 aboveZeroTR = topRightY >= 0;
429 aboveZeroBL = bottomLeftY >= 0;
430 aboveZeroBR = bottomRightY >= 0;
431 if (aboveZeroTL == aboveZeroTR && aboveZeroTL == aboveZeroBL && aboveZeroTL == aboveZeroBR) // everything equal
432 {
433 if (aboveZeroTL) // all points are >= 0
434 tileSurface += 1; // one full cell
435
436 continue;
437 }
438
439 // top-right triangle
440 if (aboveZeroTL == aboveZeroTR && aboveZeroTL == aboveZeroBR)
441 {
442 if (aboveZeroTL)
443 tileSurface += 0.5;
444 }
445 else
446 {
447 tileSurface += GetTriangle2DAreaAboveOceanLevel(topLeftY, topRightY, bottomRightY, oceanLevel);
448 }
449
450 // bottom-left triangle
451 if (aboveZeroTL == aboveZeroBL && aboveZeroTL == aboveZeroBR)
452 {
453 if (aboveZeroTL)
454 tileSurface += 0.5;
455 }
456 else
457 {
458 tileSurface += GetTriangle2DAreaAboveOceanLevel(topLeftY, bottomLeftY, bottomRightY, oceanLevel);
459 }
460 }
461 }
462
463 result += tileSurface * cellSideSizeSq;
464 }
465 }
466
467 return result;
468 }
469
470 //------------------------------------------------------------------------------------------------
477 protected static float GetTriangle2DAreaAboveOceanLevel(float a, float b, float c, float oceanLevel = 0)
478 {
479 array<float> heights = { a - oceanLevel, b - oceanLevel, c - oceanLevel };
480 heights.Sort();
481
482 if (heights[2] < 0)
483 return 0;
484
485 const float area = 0.5;
486
487 // all above zero
488 if (heights[0] >= 0)
489 return area;
490
491 // only heights[2] is above zero → small positive triangle near heights[2]
492 if (heights[1] < 0)
493 {
494 float r1 = heights[2] / (heights[2] - heights[0]);
495 float r2 = heights[2] / (heights[2] - heights[1]);
496 return area * r1 * r2 * heights[2] / 3;
497 }
498
499 // heights[0] < 0, heights[1] >= 0, heights[2] > 0 → cut away negative triangle near heights[0]
500 float s1 = -heights[0] / (heights[1] - heights[0]);
501 float s2 = -heights[0] / (heights[2] - heights[0]);
502 float negSubArea = area * s1 * s2;
503 // negative sub-triangle has heights (heights[0], 0, 0), volume = negSubArea * heights[0] / 3
504 // total = full volume - negative sub volume
505 return area * (heights[0] + heights[1] + heights[2]) / 3 - negSubArea * heights[0] / 3;
506 }
507
508 //------------------------------------------------------------------------------------------------
510 static vector GetTerrainPosition()
511 {
512 IEntitySource terrainEntitySource = GetTerrainEntitySource();
513 if (!terrainEntitySource)
514 return vector.Zero;
515
516 vector result;
517 terrainEntitySource.Get("coords", result);
518 return result;
519 }
520
521 //------------------------------------------------------------------------------------------------
523 static IEntitySource GetTimeAndWeatherManagerEntitySource()
524 {
525 WorldEditor worldEditor = GetWorldEditor();
526 if (!worldEditor)
527 return null;
528
529 if (worldEditor.IsPrefabEditMode())
530 return null;
531
532 WorldEditorAPI worldEditorAPI = worldEditor.GetApi();
533 if (worldEditorAPI.GetEditorEntityCount() < 2) // world and Entity
534 return null;
535
536 IEntitySource entitySource;
537 for (int i, entitiesCount = worldEditorAPI.GetEditorEntityCount(); i < entitiesCount; ++i)
538 {
539 entitySource = worldEditorAPI.GetEditorEntity(i);
540 if (entitySource && entitySource.GetClassName().ToType() && entitySource.GetClassName().ToType().IsInherited(TimeAndWeatherManagerEntity))
541 return entitySource;
542 }
543
544 return null;
545 }
546
547 //------------------------------------------------------------------------------------------------
550 static vector GetWorldEditorCameraPosition(out vector direction = vector.Zero)
551 {
552 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
553 if (!worldEditorAPI)
554 return vector.Zero;
555
556 vector result, traceEnd;
557 worldEditorAPI.TraceWorldPos(0, 0, 0, result, traceEnd, direction);
558
559 return result;
560 }
561
562 //------------------------------------------------------------------------------------------------
565 static ResourceName GetResourceNameFromFile(string absoluteFilePath)
566 {
567 MetaFile metaFile = GetResourceManager().GetMetaFile(absoluteFilePath);
568 if (!metaFile)
569 return string.Empty;
570
571 return metaFile.GetResourceID();
572 }
573
574 //------------------------------------------------------------------------------------------------
577 static array<ResourceName> GetSelectedDirectories()
578 {
579 array<ResourceName> result = GetSelectedResources(true);
580 if (!result)
581 return null;
582
583 for (int i = result.Count() - 1; i >= 0; i--)
584 {
585 ResourceName selectedResource = result[i];
586 if (FilePath.StripExtension(selectedResource) != selectedResource)
587 result.RemoveOrdered(i);
588 }
589
590 return result;
591 }
592
593 //------------------------------------------------------------------------------------------------
598 static array<ResourceName> GetSelectedOrOpenedResources(string wantedExtension, array<string> keywords = null)
599 {
600 return GetSelectedOrOpenedResources({ wantedExtension }, keywords);
601 }
602
603 //------------------------------------------------------------------------------------------------
605 static array<IEntitySource> GetSelectedWorldEntitySources()
606 {
607 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
608 if (!worldEditorAPI)
609 return null;
610
611 array<IEntitySource> result = {};
612 IEntitySource entitySource;
613 for (int i, count = worldEditorAPI.GetSelectedEntitiesCount(); i < count; ++i)
614 {
615 entitySource = worldEditorAPI.GetSelectedEntity(i);
616 if (entitySource)
617 result.Insert(entitySource);
618 }
619
620 return result;
621 }
622
623 //------------------------------------------------------------------------------------------------
628 static array<ResourceName> GetSelectedOrOpenedResources(array<string> acceptedExtensions = null, array<string> keywords = null)
629 {
630 array<ResourceName> tempResult = GetSelectedResources(true);
631 if (tempResult.IsEmpty())
632 {
633 ResourceName openedResource = GetPrefabEditModeResourceName();
634 if (!openedResource.IsEmpty())
635 tempResult.Insert(openedResource);
636 }
637
638 if (tempResult.IsEmpty())
639 return tempResult;
640
641 if (acceptedExtensions && acceptedExtensions.IsEmpty())
642 acceptedExtensions = null;
643
644 if (acceptedExtensions)
645 {
646 foreach (int i, string wantedExtension : acceptedExtensions)
647 {
648 wantedExtension.ToLower();
649 acceptedExtensions[i] = wantedExtension;
650 }
651 }
652
653 array<string> keywordsLC;
654 if (keywords && !keywords.IsEmpty())
655 {
656 keywordsLC = {};
657 foreach (string keyword : keywords)
658 {
659 if (keyword.IsEmpty())
660 continue;
661
662 keyword.ToLower();
663 keywordsLC.Insert(keyword);
664 }
665 }
666
667 array<ResourceName> result = {};
668
669 foreach (ResourceName resourceName : tempResult)
670 {
671 string resourceNameLC = resourceName;
672 resourceNameLC.ToLower();
673
674 string extensionLC;
675 resourceNameLC = FilePath.StripExtension(resourceName, extensionLC);
676 extensionLC.ToLower();
677
678 if (acceptedExtensions && !acceptedExtensions.Contains(extensionLC))
679 continue;
680
681 resourceNameLC = FilePath.StripPath(resourceNameLC);
682
683 if (!keywordsLC || SCR_StringHelper.ContainsEvery(resourceNameLC, keywordsLC))
684 result.Insert(resourceName);
685 }
686
687 return result;
688 }
689
690 //------------------------------------------------------------------------------------------------
694 static array<ResourceName> GetSelectedResources(bool recursive = true)
695 {
696 WorldEditor worldEditor = GetWorldEditor();
697 if (!worldEditor)
698 return null;
699
700 array<ResourceName> result = {};
701 worldEditor.GetResourceBrowserSelection(result.Insert, recursive);
702 return result;
703 }
704
705 //------------------------------------------------------------------------------------------------
706 [Obsolete("Use SCR_WorkbenchHelper.SearchWorkbenchResources instead")] // obsolete since 2025-03-03
707 static array<ResourceName> SearchWorkbenchResources(array<string> fileExtensions = null, array<string> searchStrArray = null, string rootPath = "", bool recursive = true)
708 {
709 return SCR_WorkbenchHelper.SearchWorkbenchResources(fileExtensions, searchStrArray, rootPath, recursive);
710 }
711
712 //------------------------------------------------------------------------------------------------
715 static void DeleteEntityFromSource(IEntitySource entitySource)
716 {
717 if (!entitySource)
718 return;
719
720 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
721 if (!worldEditorAPI)
722 {
723 Print("WorldEditorAPI is not available", LogLevel.ERROR);
724 return;
725 }
726
727 bool manageEditAction = BeginEntityAction();
728
729 worldEditorAPI.DeleteEntity(entitySource);
730
731 EndEntityAction(manageEditAction);
732 }
733
734 //------------------------------------------------------------------------------------------------
737 static bool BeginEntityAction()
738 {
739 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
740 if (!worldEditorAPI)
741 {
742 Print("WorldEditorAPI is not available", LogLevel.ERROR);
743 return false;
744 }
745
746 if (worldEditorAPI.IsDoingEditAction())
747 return false;
748
749 return worldEditorAPI.BeginEntityAction();
750 }
751
752 //------------------------------------------------------------------------------------------------
755 static void EndEntityAction(bool manageEditAction)
756 {
757 WorldEditorAPI worldEditorAPI = GetWorldEditorAPI();
758 if (!worldEditorAPI)
759 {
760 Print("WorldEditorAPI is not available", LogLevel.ERROR);
761 return;
762 }
763
764 if (manageEditAction)
765 worldEditorAPI.EndEntityAction();
766 }
767
768 //------------------------------------------------------------------------------------------------
775 static array<IEntity> QueryEntitiesByAABB(notnull World world, vector mins, vector maxs, EQueryEntitiesFlags queryFlags = EQueryEntitiesFlags.ALL)
776 {
777 s_aTempEntities = {};
778 if (!world.QueryEntitiesByAABB(mins, maxs, QueryEntitiesCallbackMethod, null, queryFlags))
779 return null;
780
781 array<IEntity> result = {};
782 result.Copy(s_aTempEntities);
783 s_aTempEntities = null;
784 return result;
785 }
786
787 //------------------------------------------------------------------------------------------------
794 static array<IEntity> QueryEntitiesBySphere(notnull World world, vector worldPos, float radius, EQueryEntitiesFlags queryFlags = EQueryEntitiesFlags.ALL)
795 {
796 array<IEntity> result = {};
797 s_aTempEntities = {};
798 world.QueryEntitiesBySphere(worldPos, radius, QueryEntitiesCallbackMethod, null, queryFlags);
799 result.Copy(s_aTempEntities);
800 s_aTempEntities = null;
801 return result;
802 }
803
804 //------------------------------------------------------------------------------------------------
809 static array<IEntity> TraceMoveEntitiesBySphere(notnull World world, notnull TraceSphere traceSphere)
810 {
811 array<IEntity> result = {};
812
813 s_aTempEntities = {};
814 world.TraceMove(traceSphere, TraceCallbackMethod);
815
816 result.Copy(s_aTempEntities);
817 s_aTempEntities = null;
818
819 return result;
820 }
821
822 //------------------------------------------------------------------------------------------------
827 static array<IEntity> TracePositionEntitiesBySphere(notnull World world, notnull TraceSphere traceSphere)
828 {
829 array<IEntity> result = {};
830
831 s_aTempEntities = {};
832 world.TracePosition(traceSphere, TraceCallbackMethod);
833
834 result.Copy(s_aTempEntities);
835 s_aTempEntities = null;
836
837 return result;
838 }
839
840 //
841 // Callbacks
842 //
843
844 //------------------------------------------------------------------------------------------------
846 protected static bool QueryEntitiesCallbackMethod(IEntity e)
847 {
848 s_aTempEntities.Insert(e);
849 return true;
850 }
851
852 //------------------------------------------------------------------------------------------------
854 protected static bool TraceCallbackMethod(notnull IEntity e, vector start = "0 0 0", vector dir = "0 0 0")
855 {
856 s_aTempEntities.Insert(e);
857 return true;
858 }
859}
860#endif // WORKBENCH
ref array< string > angles
ResourceName resourceName
Definition SCR_AIGroup.c:66
vector direction
vector position
enum EVehicleType IEntity
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
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
@ MAX
EQueryEntitiesFlags