14 protected IEntity m_Entity;
15 protected IEntitySource m_EntitySource;
16 protected float m_fHeightTerrain = -1;
17 protected bool m_bIsOnOrigTransform =
true;
18 protected vector m_vLocalTransform[4];
19 protected vector m_vTerrainTransform[4];
20 protected ref array<SCR_BasePreviewEntity> m_aChildren;
21 protected vector m_vBounds[2];
22 protected bool m_bHasMultipleEditableEntities;
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)
36 if (entries.IsEmpty())
38 Print(
"No entries defined!", LogLevel.WARNING);
45 EntitySpawnParams spawnParamsLocal = spawnParams;
46 if (!spawnParamsLocal)
48 spawnParamsLocal =
new EntitySpawnParams();
49 spawnParamsLocal.Transform[3] = entries[0].m_vPosition;
52 bool applyMesh = !material.IsEmpty();
56 FilePath.StripExtension(previewPrefab, ext);
57 Resource previewResource;
59 bool spawnFromResource;
62 previewResource = Resource.Load(previewPrefab);
63 spawnFromResource = previewResource.IsValid();
67 if (spawnFromResource)
75 previewType = previewPrefab.ToType();
83 Debug.Error2(
"SCR_BasePreviewEntity",
string.Format(
"Unable to create preview entity from prefab/type '%1'!", previewPrefab));
87 vector rootTransform[4];
88 Math3D.MatrixCopy(spawnParamsLocal.Transform, rootTransform);
90 rootEntity.m_Flags = flags;
92 vector rootBoundMin = vector.One *
float.MAX;
93 vector rootBoundMax = -rootBoundMin;
95 int editableEntityCount;
97 array<SCR_BasePreviewEntity> children = {};
104 spawnParamsLocal =
new EntitySpawnParams();
105 entry.LoadTransform(spawnParamsLocal.Transform);
108 Math3D.MatrixScale(spawnParamsLocal.Transform, entry.GetScale());
111 if (entry.m_iParentID == -1)
114 parent = children[entry.m_iParentID];
118 editableEntityCount++;
128 if (spawnFromResource)
133 if (entity && applyMesh)
135 switch (entry.m_Shape)
142 Resource meshResource = Resource.Load(entry.m_Mesh);
145 BaseResourceObject res = meshResource.GetResource();
148 entity.SetPreviewObject(res.ToVObject(), material);
156 int resolution = SCR_BaseAreaMeshComponent.PREVIEW_RESOLUTION;
157 vector dimensions = entry.m_vScale;
159 if (resolution <= 0 || dimensions[0] <= 0 || dimensions[1] <= 0 || dimensions[2] <= 0)
164 array<vector> positions = {};
168 float dirStep = Math.PI2 / resolution;
171 for (
int v = 0; v < resolution; v++)
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);
184 float width = dimensions[0] / 2;
185 float lenght = dimensions[2] / 2;
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)
195 for (
int p = 0; p < resolution; p++)
197 vector start = corners[p];
198 vector end = corners[(p + 1) % resolution];
200 for (
float s = 0; s < 4; s++)
202 vector pos = vector.Lerp(start, end, s / resolution);
203 positions.Insert(pos);
208 Resource res =
SCR_Shape.CreateAreaMesh(positions, dimensions[1] * 2, material,
true);
209 MeshObject meshObject = res.GetResource().ToMeshObject();
211 entity.SetObject(meshObject,
"");
217 children.Insert(entity);
220 vector boundMin, boundMax;
221 entity.GetBounds(boundMin, boundMax);
222 boundMin += entry.m_vPosition;
223 boundMax += entry.m_vPosition;
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]);
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]);
235 if (!entry.m_iPivotID.IsEmpty() && parent.GetAnimation())
236 pivot = parent.GetAnimation().GetBoneIndex(entry.m_iPivotID);
237 parent.AddChild(entity, pivot, EAddChildFlags.AUTO_TRANSFORM);
240 if (!parent.m_aChildren)
241 parent.m_aChildren = {};
242 parent.m_aChildren.Insert(entity);
245 Math3D.AnglesToMatrix(entry.m_vAnglesTerrain, entity.m_vTerrainTransform);
246 entity.m_fHeightTerrain = entry.m_vHeightTerrain;
249 Math3D.MatrixCopy(spawnParamsLocal.Transform, entity.m_vLocalTransform);
252 entity.m_Flags |= entry.m_Flags;
253 entity.m_Entity = entry.m_Entity;
255 entity.EOnPreviewInit(entry, rootEntity);
257 rootEntity.m_vBounds[0] = rootBoundMin;
258 rootEntity.m_vBounds[1] = rootBoundMax;
261 rootEntity.m_bHasMultipleEditableEntities = editableEntityCount > 1;
263 rootEntity.EOnRootPreviewInit(entries);
265 Print(
string.Format(
"Preview entity created from %1 entries, at %2, using '%3' with material '%4'", entries.Count(), rootTransform, previewPrefab, material), LogLevel.VERBOSE);
278 void SetPreviewTransform(vector worldTransform[4],
EEditorTransformVertical verticalMode,
float heightTerrain = 0,
bool isUnderwater =
false, TraceParam trace =
null)
281 if (m_fHeightTerrain == -1)
282 m_fHeightTerrain = heightTerrain;
283 heightTerrain -= m_fHeightTerrain;
285 SetWorldTransform(worldTransform);
286 SetChildTransform(verticalMode, heightTerrain, isUnderwater, trace);
291 DbgUI.Begin(this.ToString(), 0, 0);
292 SCR_DbgUI.Matrix(
"worldTransform", worldTransform);
297 protected void SetChildTransform(
EEditorTransformVertical verticalMode,
float heightTerrain,
bool isUnderwater =
false, TraceParam trace =
null)
302 switch (verticalMode)
308 vector transform[4], surfaceBasis[4];
309 GetParent().GetWorldTransform(transform);
310 Math3D.MatrixMultiply4(transform, m_vLocalTransform, transform);
312 float scale = transform[0].Length();
315 if (!
SCR_TerrainHelper.GetTerrainBasis(transform[3], surfaceBasis, GetWorld(), !isUnderwater, trace))
318 vector angles = Math3D.MatrixToAngles(transform);
324 Math3D.AnglesToMatrix(angles, transform);
330 Math3D.AnglesToMatrix(Vector(angles[0], 0, 0), transform);
333 Math3D.MatrixMultiply3(surfaceBasis, transform, surfaceBasis);
336 Math3D.MatrixMultiply3(surfaceBasis, m_vTerrainTransform, transform);
340 transform[3][1] = surfaceBasis[3][1] + m_fHeightTerrain + heightTerrain;
344 Math3D.MatrixScale(transform, scale);
347 SetWorldTransform(transform);
350 m_bIsOnOrigTransform =
false;
356 if (!m_bIsOnOrigTransform)
358 SetLocalTransform(m_vLocalTransform);
359 m_bIsOnOrigTransform =
true;
368 for (
int i = 0, count =
m_aChildren.Count(); i < count; i++)
370 m_aChildren[i].SetChildTransform(verticalMode, heightTerrain, isUnderwater, trace);
377 GetWorldTransform(matrix);
378 SCR_Global.DrawMatrix(matrix, 1, colorX: Color.CYAN, colorY: Color.MAGENTA, colorZ: 0xffffff00);
381 protected void SetPreviewObject(VObject mesh, ResourceName material)
386 string remap =
string.Empty;
387 string materials[256];
388 int numMats = mesh.GetMaterials(materials);
389 for (
int i = 0; i < numMats; i++)
391 remap +=
string.Format(
"$remap '%1' '%2';", materials[i], material);
393 SetObject(mesh, remap);
400 array<SCR_BasePreviewEntity> GetPreviewChildren()
408 IEntity GetSourceEntity()
417 void GetPreviewBounds(out vector outBoundMin, out vector outBoundMax)
419 outBoundMin = m_vBounds[0];
420 outBoundMax = m_vBounds[1]
425 bool HasMultipleEditableEntities()
427 return m_bHasMultipleEditableEntities;
438 protected void EOnRootPreviewInit(array<ref SCR_BasePreviewEntry> entries);
452 override void _WB_GetBoundBox(inout vector min, inout vector max, IEntitySource src)
456 override void _WB_AfterWorldUpdate(
float timeSlice)
459 if (_WB_GetEditorAPI() && _WB_GetEditorAPI().IsEntitySelectedAsMain(_WB_GetEditorAPI().EntityToSource(
this)))
461 string text =
"<No Mesh>";
463 text = FilePath.StripPath(GetVObject().GetResourceName());
466 DebugTextWorldSpace.Create(GetWorld(), text, DebugTextFlags.ONCE | DebugTextFlags.CENTER, pos[0], pos[1], pos[2], 12, Color.WHITE, Color.BLACK);