Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_BasePreviewEntity.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameScripted/Preview", description: "", color: "0 0 0 0", dynamicBox: true)]
2class SCR_BasePreviewEntityClass: GenericEntityClass
3{
4};
5
10{
11 [Attribute(uiwidget: UIWidgets.Flags, category: "Preview Entity", enums: ParamEnumArray.FromEnum(EPreviewEntityFlag))]
13
14 protected IEntity m_Entity;
16 protected float m_fHeightTerrain = -1;
17 protected bool m_bIsOnOrigTransform = true;
20 protected ref array<SCR_BasePreviewEntity> m_aChildren;
21 protected vector m_vBounds[2];
23
34 static SCR_BasePreviewEntity SpawnPreview(notnull array<ref SCR_BasePreviewEntry> entries, ResourceName previewPrefab, BaseWorld world = null, EntitySpawnParams spawnParams = null, ResourceName material = ResourceName.Empty, EPreviewEntityFlag flags = 0)
35 {
36 if (entries.IsEmpty())
37 {
38 Print("No entries defined!", LogLevel.WARNING);
39 return null;
40 }
41
42 if (!world)
43 world = GetGame().GetWorld();
44
45 EntitySpawnParams spawnParamsLocal = spawnParams;
46 if (!spawnParamsLocal)
47 {
48 spawnParamsLocal = new EntitySpawnParams();
49 spawnParamsLocal.Transform[3] = entries[0].m_vPosition;
50 }
51
52 bool applyMesh = !material.IsEmpty();
53
54 //--- Create root entity
55 string ext;
56 FilePath.StripExtension(previewPrefab, ext);
57 Resource previewResource;
58 typename previewType;
59 bool spawnFromResource;
60 if (!ext.IsEmpty())
61 {
62 previewResource = Resource.Load(previewPrefab);
63 spawnFromResource = previewResource.IsValid();
64 }
65
66 SCR_BasePreviewEntity rootEntity;
67 if (spawnFromResource)
68 {
69 //--- From prefab
70 rootEntity = SCR_BasePreviewEntity.Cast(GetGame().SpawnEntityPrefab(previewResource, world, spawnParamsLocal));
71 }
72 else
73 {
74 //--- From class name
75 previewType = previewPrefab.ToType();
76 if (!previewType)
77 previewType = SCR_BasePreviewEntity;
78 rootEntity = SCR_BasePreviewEntity.Cast(GetGame().SpawnEntity(previewType, world, spawnParamsLocal));
79 }
80
81 if (!rootEntity)
82 {
83 Debug.Error2("SCR_BasePreviewEntity", string.Format("Unable to create preview entity from prefab/type '%1'!", previewPrefab));
84 return null;
85 }
86
87 vector rootTransform[4];
88 Math3D.MatrixCopy(spawnParamsLocal.Transform, rootTransform);
89
90 rootEntity.m_Flags = flags;
91
92 vector rootBoundMin = vector.One * float.MAX;
93 vector rootBoundMax = -rootBoundMin;
94
95 int editableEntityCount;
96
97 array<SCR_BasePreviewEntity> children = {};
98 SCR_BasePreviewEntity entity, parent;
99 foreach (int i, SCR_BasePreviewEntry entry: entries)
100 {
101 //entry.Log(i);
102
103 //--- Get local transformation matrix
104 spawnParamsLocal = new EntitySpawnParams();
105 entry.LoadTransform(spawnParamsLocal.Transform);
106
107 if (entry.m_Shape != EPreviewEntityShape.ELLIPSE && entry.m_Shape != EPreviewEntityShape.RECTANGLE) //--- Don't scale area meshes; instead, the scale is applied on the actual area
108 Math3D.MatrixScale(spawnParamsLocal.Transform, entry.GetScale()); //--- Apply scale on matrix, SetScale() doesn't work reliably
109
110 //--- Get parent (don't apply it to spawn params, it doesn't create true hierarchy link)
111 if (entry.m_iParentID == -1)
112 parent = rootEntity;
113 else
114 parent = children[entry.m_iParentID];
115
116 //--- Count how manuy editable entities are inside. When more than 1, editing along geometry is disabled.
117 if (entry.m_Flags & EPreviewEntityFlag.EDITABLE)
118 editableEntityCount++;
119
120 if (applyMesh && entry.m_Shape == EPreviewEntityShape.PREFAB && entry.m_Mesh)
121 {
122 //--- Use preview prefab
123 entity = SCR_BasePreviewEntity.Cast(GetGame().SpawnEntityPrefabLocal(Resource.Load(entry.m_Mesh), world, spawnParamsLocal));
124 }
125 else
126 {
127 //--- Create entity
128 if (spawnFromResource)
129 entity = SCR_BasePreviewEntity.Cast(GetGame().SpawnEntityPrefabLocal(previewResource, world, spawnParamsLocal));
130 else
131 entity = SCR_BasePreviewEntity.Cast(GetGame().SpawnEntity(previewType, world, spawnParamsLocal));
132
133 if (entity && applyMesh)
134 {
135 switch (entry.m_Shape)
136 {
137 case EPreviewEntityShape.MESH:
138 {
139 //--- Set mesh from a file
140 if (entry.m_Mesh)
141 {
142 Resource meshResource = Resource.Load(entry.m_Mesh);
143 if (meshResource)
144 {
145 BaseResourceObject res = meshResource.GetResource();
146
147 if (res)
148 entity.SetPreviewObject(res.ToVObject(), material);
149 }
150 }
151 break;
152 }
153 case EPreviewEntityShape.ELLIPSE:
154 case EPreviewEntityShape.RECTANGLE:
155 {
156 int resolution = SCR_BaseAreaMeshComponent.PREVIEW_RESOLUTION;
157 vector dimensions = entry.m_vScale;
158
159 if (resolution <= 0 || dimensions[0] <= 0 || dimensions[1] <= 0 || dimensions[2] <= 0)
160 {
161 break;
162 }
163
164 array<vector> positions = {};
165
166 if (entry.m_Shape == EPreviewEntityShape.ELLIPSE)
167 {
168 float dirStep = Math.PI2 / resolution;
169
170 //--- Get positions
171 for (int v = 0; v < resolution; v++)
172 {
173 float dir = dirStep * v;
174 vector pos = Vector(Math.Sin(dir) * dimensions[0], -dimensions[1], Math.Cos(dir) * dimensions[2]);
175 positions.Insert(pos);
176 }
177 }
178 else if (entry.m_Shape == EPreviewEntityShape.RECTANGLE)
179 {
180 //~ Resulution is always 4 for Rectangles
181 resolution = 4;
182
183 //~ Make sure it uses half of the width and lenght
184 float width = dimensions[0] / 2;
185 float lenght = dimensions[2] / 2;
186
187 array<vector> corners = {
188 Vector(-width, -dimensions[1], -lenght),
189 Vector(width, -dimensions[1], -lenght),
190 Vector(width, -dimensions[1], lenght),
191 Vector(-width, -dimensions[1], lenght)
192 };
193
194 //~ Set positions
195 for (int p = 0; p < resolution; p++)
196 {
197 vector start = corners[p];
198 vector end = corners[(p + 1) % resolution];
199
200 for (float s = 0; s < 4; s++)
201 {
202 vector pos = vector.Lerp(start, end, s / resolution);
203 positions.Insert(pos);
204 }
205 }
206 }
207
208 Resource res = SCR_Shape.CreateAreaMesh(positions, dimensions[1] * 2, material, true);
209 MeshObject meshObject = res.GetResource().ToMeshObject();
210 if (meshObject)
211 entity.SetObject(meshObject, "");
212 }
213
214 }
215 }
216 }
217 children.Insert(entity);
218
219 //--- Update root bounding box
220 vector boundMin, boundMax;
221 entity.GetBounds(boundMin, boundMax);
222 boundMin += entry.m_vPosition;
223 boundMax += entry.m_vPosition;
224
225 rootBoundMin[0] = Math.Min(rootBoundMin[0], boundMin[0]);
226 rootBoundMin[1] = Math.Min(rootBoundMin[1], boundMin[1]);
227 rootBoundMin[2] = Math.Min(rootBoundMin[2], boundMin[2]);
228
229 rootBoundMax[0] = Math.Max(rootBoundMax[0], boundMax[0]);
230 rootBoundMax[1] = Math.Max(rootBoundMax[1], boundMax[1]);
231 rootBoundMax[2] = Math.Max(rootBoundMax[2], boundMax[2]);
232
233 //--- Add to parent (spawn params won't do that on their own)
234 int pivot = -1;
235 if (!entry.m_iPivotID.IsEmpty() && parent.GetAnimation())
236 pivot = parent.GetAnimation().GetBoneIndex(entry.m_iPivotID);
237 parent.AddChild(entity, pivot, EAddChildFlags.AUTO_TRANSFORM);
238
239 //--- Cache the child in parent's array
240 if (!parent.m_aChildren)
241 parent.m_aChildren = {};
242 parent.m_aChildren.Insert(entity);
243
244 //--- Set coordinates local to terrain
245 Math3D.AnglesToMatrix(entry.m_vAnglesTerrain, entity.m_vTerrainTransform);
246 entity.m_fHeightTerrain = entry.m_fHeightTerrain;
247
248 //--- Make a copy of local transform for use in SetPreviewTransform()
249 Math3D.MatrixCopy(spawnParamsLocal.Transform, entity.m_vLocalTransform);
250
251 //--- Initialize
252 entity.m_Flags |= entry.m_Flags;
253 entity.m_Entity = entry.m_Entity;
254
255 entity.EOnPreviewInit(entry, rootEntity);
256 }
257 rootEntity.m_vBounds[0] = rootBoundMin;
258 rootEntity.m_vBounds[1] = rootBoundMax;
259
260 //--- When there is more than one editable entity, mark it. Editing along geometry is disallowed in such case.
261 rootEntity.m_bHasMultipleEditableEntities = editableEntityCount > 1;
262
263 rootEntity.EOnRootPreviewInit(entries);
264
265 Print(string.Format("Preview entity created from %1 entries, at %2, using '%3' with material '%4'", entries.Count(), rootTransform, previewPrefab, material), LogLevel.VERBOSE);
266
267 return rootEntity;
268 }
269
278 void SetPreviewTransform(vector worldTransform[4], EEditorTransformVertical verticalMode, float heightTerrain = 0, bool isUnderwater = false, TraceParam trace = null)
279 {
280 //--- Get height difference
281 if (m_fHeightTerrain == -1)
282 m_fHeightTerrain = heightTerrain;
283
284 heightTerrain -= m_fHeightTerrain;
285
286 SetWorldTransform(worldTransform);
287 SetChildTransform(verticalMode, heightTerrain, isUnderwater, trace);
288 Update();
289
290 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_EDITOR_SHOW_DEBUG))
291 {
292 DbgUI.Begin(this.ToString(), 0, 0);
293 SCR_DbgUI.Matrix("worldTransform", worldTransform);
294 SCR_Global.DrawMatrix(worldTransform, 1);
295 DbgUI.End();
296 }
297 }
298 protected void SetChildTransform(EEditorTransformVertical verticalMode, float heightTerrain, bool isUnderwater = false, TraceParam trace = null)
299 {
300 if (GetParent())
301 {
302 //--- Actual preview entity, not root
303 switch (verticalMode)
304 {
305 case EEditorTransformVertical.GEOMETRY:
306 case EEditorTransformVertical.TERRAIN:
307 {
308 //--- Restore local transformation and convert it to world transformation
309 vector transform[4], surfaceBasis[4];
310 GetParent().GetWorldTransform(transform);
311 Math3D.MatrixMultiply4(transform, m_vLocalTransform, transform);
312
313 float scale = transform[0].Length();
314
315 //--- Get surface basis
316 if (!SCR_TerrainHelper.GetTerrainBasis(transform[3], surfaceBasis, GetWorld(), !isUnderwater, trace))
317 return;
318
319 vector angles = Math3D.MatrixToAngles(transform);
320 if (SCR_Enum.HasFlag(m_Flags, EPreviewEntityFlag.HORIZONTAL))
321 {
322 //--- Orient to horizontal normal
323 angles[1] = 0;
324 angles[2] = 0;
325 Math3D.AnglesToMatrix(angles, transform);
326 }
327 else
328 {
329 //--- Orient to terrain normal
330 //--- Get identity matrix rotated according to the entity
331 Math3D.AnglesToMatrix(Vector(angles[0], 0, 0), transform);
332
333 //--- Rotate surface basis
334 Math3D.MatrixMultiply3(surfaceBasis, transform, surfaceBasis);
335
336 //--- Apply local transformation relative to terrain
337 Math3D.MatrixMultiply3(surfaceBasis, m_vTerrainTransform, transform);
338 }
339
340 //--- Apply height
341 transform[3][1] = surfaceBasis[3][1] + m_fHeightTerrain + heightTerrain;
342
343 //--- Preserve scale
344 if (scale != 1)
345 Math3D.MatrixScale(transform, scale);
346
347 //--- Apply
348 SetWorldTransform(transform);
349 Update();
350
351 m_bIsOnOrigTransform = false;
352 break;
353 }
354 default:
355 {
356 //--- Reset transformation
358 {
361 }
362 break;
363 }
364 }
365 }
366 if (m_aChildren && (!GetParent() || SCR_Enum.HasFlag(m_Flags, EPreviewEntityFlag.ORIENT_CHILDREN)))
367 {
368 //--- Is root, or has children and is allowed to orient them
369 for (int i = 0, count = m_aChildren.Count(); i < count; i++)
370 {
371 m_aChildren[i].SetChildTransform(verticalMode, heightTerrain, isUnderwater, trace);
372 }
373 }
374
375 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_EDITOR_SHOW_DEBUG))
376 {
377 vector matrix[4];
378 GetWorldTransform(matrix);
379 SCR_Global.DrawMatrix(matrix, 1, colorX: Color.CYAN, colorY: Color.MAGENTA, colorZ: 0xffffff00);
380 }
381 }
382 protected void SetPreviewObject(VObject mesh, ResourceName material)
383 {
384 if (!mesh)
385 return;
386
387 string remap = string.Empty;
388 string materials[256];
389 int numMats = mesh.GetMaterials(materials);
390 for (int i = 0; i < numMats; i++)
391 {
392 remap += string.Format("$remap '%1' '%2';", materials[i], material);
393 }
394 SetObject(mesh, remap);
395 }
396
401 array<SCR_BasePreviewEntity> GetPreviewChildren()
402 {
403 return m_aChildren;
404 }
405
410 {
411 return m_Entity;
412 }
413
418 void GetPreviewBounds(out vector outBoundMin, out vector outBoundMax)
419 {
420 outBoundMin = m_vBounds[0];
421 outBoundMax = m_vBounds[1]
422 }
423
430
439 protected void EOnRootPreviewInit(array<ref SCR_BasePreviewEntry> entries);
440
442 {
443 }
445 {
446 while (GetChildren())
447 {
448 delete GetChildren();
449 }
450 }
451
452#ifdef WORKBENCH
453 override void _WB_GetBoundBox(inout vector min, inout vector max, IEntitySource src)
454 {
455 GetBounds(min, max);
456 }
457 override int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
458 {
459 return EEntityFrameUpdateSpecs.CALL_WHEN_ENTITY_VISIBLE;
460 }
461 override void _WB_AfterWorldUpdate(float timeSlice)
462 {
463 //--- Show mesh name for easier World Editor debugging
464 if (_WB_GetEditorAPI() && _WB_GetEditorAPI().IsEntitySelectedAsMain(_WB_GetEditorAPI().EntityToSource(this)))
465 {
466 string text = "<No Mesh>";
467 if (GetVObject())
468 text = FilePath.StripPath(GetVObject().GetResourceName());
469
470 vector pos = GetOrigin();
471 DebugTextWorldSpace.Create(GetWorld(), text, DebugTextFlags.ONCE | DebugTextFlags.CENTER, pos[0], pos[1], pos[2], 12, Color.WHITE, Color.BLACK);
472 }
473 }
474#endif
475};
SCR_EAIThreatSectorFlags flags
vector scale
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
EPreviewEntityFlag
EPreviewEntityShape
ArmaReforgerScripted GetGame()
Definition game.c:1398
ref array< string > angles
IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
Definition Color.c:13
Definition DbgUI.c:66
Definition Debug.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
event void _WB_GetBoundBox(inout vector min, inout vector max, IEntitySource src)
Editor needs to know a bound box of entity (For ray-casting, visualizers etc.). You can return any cu...
event void _WB_AfterWorldUpdate(float timeSlice)
Called after updating world in Workbench. The entity must be visible in frustum, selected or named....
proto external WorldEditorAPI _WB_GetEditorAPI()
This returns world editor API, which is safe to use from editor events bellow.
event int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
Called after _WB_OnInit or also later when editor needs to know whether _WB_AfterWorldUpdate needs to...
void IEntity(IEntitySource src, IEntity parent)
protected script Constructor
proto external vector GetOrigin()
proto external bool SetLocalTransform(vector mat[4])
See IEntity::SetTransform. Returns false, if there is no change in transformation.
proto external void GetBounds(out vector mins, out vector maxs)
proto external IEntity GetChildren()
proto external void GetWorldTransform(out vector mat[])
See IEntity::GetTransform.
proto external int Update()
proto external BaseWorld GetWorld()
proto external bool SetWorldTransform(vector mat[4])
See IEntity::SetTransform. Returns false, if there is no change in transformation.
proto external IEntity GetParent()
proto external VObject GetVObject()
Returns visual object set to this Entity. No reference is added.
Definition Math.c:13
MeshObject.
Definition MeshObject.c:34
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
void SetPreviewTransform(vector worldTransform[4], EEditorTransformVertical verticalMode, float heightTerrain=0, bool isUnderwater=false, TraceParam trace=null)
void SetChildTransform(EEditorTransformVertical verticalMode, float heightTerrain, bool isUnderwater=false, TraceParam trace=null)
void EOnPreviewInit(SCR_BasePreviewEntry entry, SCR_BasePreviewEntity root)
ref array< SCR_BasePreviewEntity > m_aChildren
void SetPreviewObject(VObject mesh, ResourceName material)
void GetPreviewBounds(out vector outBoundMin, out vector outBoundMax)
array< SCR_BasePreviewEntity > GetPreviewChildren()
void SCR_BasePreviewEntity(IEntitySource src, IEntity parent)
void EOnRootPreviewInit(array< ref SCR_BasePreviewEntry > entries)
static SCR_BasePreviewEntity SpawnPreview(notnull array< ref SCR_BasePreviewEntry > entries, ResourceName previewPrefab, BaseWorld world=null, EntitySpawnParams spawnParams=null, ResourceName material=ResourceName.Empty, EPreviewEntityFlag flags=0)
static void DrawMatrix(vector matrix[4], float scale=1, ShapeFlags flags=ShapeFlags.ONCE|ShapeFlags.NOZBUFFER, int colorX=Color.RED, int colorY=Color.GREEN, int colorZ=Color.BLUE)
Definition Functions.c:1747
static bool GetTerrainBasis(vector pos, out vector result[4], BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
Visual object.
Definition VObject.c:14
void EntitySpawnParams()
Definition gameLib.c:130
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
DebugTextFlags
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EEditorTransformVertical
Vertical transformation mode.
EAddChildFlags
proto external string ToString()
Plain C++ pointer, no weak pointers, no memory management.
proto native vector Vector(float x, float y, float z)