|
|
|
|
@@ -5,6 +5,8 @@
|
|
|
|
|
#include "../components/Transform.hpp"
|
|
|
|
|
#include "../components/StaticGeometry.hpp"
|
|
|
|
|
#include "../components/StaticGeometryMember.hpp"
|
|
|
|
|
#include "../components/RigidBody.hpp"
|
|
|
|
|
#include "../components/PhysicsCollider.hpp"
|
|
|
|
|
#include <OgreStaticGeometry.h>
|
|
|
|
|
#include "../components/ProceduralMaterial.hpp"
|
|
|
|
|
#include "../components/ProceduralTexture.hpp"
|
|
|
|
|
@@ -46,6 +48,12 @@ void CellGridSystem::initialize()
|
|
|
|
|
m_initialized = true;
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGridSystem initialized");
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* NOTE: Observers removed because flecs observer registration shifts
|
|
|
|
|
* entity IDs, which breaks SceneSerializer's hardcoded ID resolution
|
|
|
|
|
* for proceduralMaterialEntityId in Town/District/Lot components.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::update()
|
|
|
|
|
@@ -83,6 +91,7 @@ void CellGridSystem::update()
|
|
|
|
|
// First check stored texture entity
|
|
|
|
|
auto it = m_entityMeshes.find(entity.id());
|
|
|
|
|
if (it != m_entityMeshes.end() &&
|
|
|
|
|
it->second.textureEntity.is_valid() &&
|
|
|
|
|
it->second.textureEntity.is_alive() &&
|
|
|
|
|
it->second.textureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
currentTextureEntity = it->second.textureEntity;
|
|
|
|
|
@@ -90,9 +99,9 @@ void CellGridSystem::update()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If no stored texture, try to find from parent material
|
|
|
|
|
if (!currentTextureEntity.is_alive()) {
|
|
|
|
|
if (!currentTextureEntity.is_valid()) {
|
|
|
|
|
flecs::entity parent = entity.parent();
|
|
|
|
|
while (parent.is_alive()) {
|
|
|
|
|
while (parent.is_valid() && parent.is_alive()) {
|
|
|
|
|
flecs::entity matEntity = flecs::entity::null();
|
|
|
|
|
if (parent.has<LotComponent>()) {
|
|
|
|
|
matEntity = parent.get<LotComponent>().proceduralMaterialEntity;
|
|
|
|
|
@@ -102,9 +111,11 @@ void CellGridSystem::update()
|
|
|
|
|
matEntity = parent.get<TownComponent>().proceduralMaterialEntity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (matEntity.is_alive() && matEntity.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
if (matEntity.is_valid() && matEntity.is_valid() && matEntity.is_alive() &&
|
|
|
|
|
matEntity.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat = matEntity.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity.is_alive() &&
|
|
|
|
|
if (mat.diffuseTextureEntity.is_valid() &&
|
|
|
|
|
mat.diffuseTextureEntity.is_valid() && mat.diffuseTextureEntity.is_alive() &&
|
|
|
|
|
mat.diffuseTextureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
currentTextureEntity = mat.diffuseTextureEntity;
|
|
|
|
|
const auto &tex = mat.diffuseTextureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -117,7 +128,7 @@ void CellGridSystem::update()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool textureChanged = false;
|
|
|
|
|
if (currentTextureEntity.is_alive()) {
|
|
|
|
|
if (currentTextureEntity.is_valid() && currentTextureEntity.is_alive()) {
|
|
|
|
|
const auto &tex = currentTextureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
if (tex.version != currentTextureVersion) {
|
|
|
|
|
textureChanged = true;
|
|
|
|
|
@@ -171,6 +182,7 @@ void CellGridSystem::update()
|
|
|
|
|
if (!needsRebuild) {
|
|
|
|
|
auto it = m_plazaMeshes.find(entity.id());
|
|
|
|
|
if (it != m_plazaMeshes.end() &&
|
|
|
|
|
it->second.textureEntity.is_valid() &&
|
|
|
|
|
it->second.textureEntity.is_alive() &&
|
|
|
|
|
it->second.textureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
const auto &tex = it->second.textureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -207,6 +219,7 @@ void CellGridSystem::update()
|
|
|
|
|
if (!needsRebuild) {
|
|
|
|
|
auto it = m_lotBaseMeshes.find(entity.id());
|
|
|
|
|
if (it != m_lotBaseMeshes.end() &&
|
|
|
|
|
it->second.textureEntity.is_valid() &&
|
|
|
|
|
it->second.textureEntity.is_alive() &&
|
|
|
|
|
it->second.textureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
const auto &tex = it->second.textureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -221,6 +234,15 @@ void CellGridSystem::update()
|
|
|
|
|
lot.dirty = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Process any pending physics builds outside of query iteration
|
|
|
|
|
for (auto pendingEntity : m_pendingPhysicsBuilds) {
|
|
|
|
|
if (pendingEntity.is_valid() && pendingEntity.is_alive()) {
|
|
|
|
|
destroyPhysicsColliders(pendingEntity);
|
|
|
|
|
buildPhysicsColliders(pendingEntity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_pendingPhysicsBuilds.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
@@ -235,6 +257,23 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
|
|
|
|
|
// Destroy existing meshes
|
|
|
|
|
destroyCellGridMeshes(entity);
|
|
|
|
|
|
|
|
|
|
// Create or recreate StaticGeometry region early (used for frames, furniture, roofs)
|
|
|
|
|
std::string regionName = "FrameRegion_" + std::to_string(entity.id());
|
|
|
|
|
Ogre::StaticGeometry *staticGeom = m_sceneMgr->createStaticGeometry(regionName);
|
|
|
|
|
staticGeom->setCastShadows(true);
|
|
|
|
|
staticGeom->setRegionDimensions(Ogre::Vector3(1000.0f));
|
|
|
|
|
|
|
|
|
|
MeshData &meshData = m_entityMeshes[entity.id()];
|
|
|
|
|
meshData.frameStaticGeometry = staticGeom;
|
|
|
|
|
meshData.framePlacements.clear();
|
|
|
|
|
meshData.furniturePlacements.clear();
|
|
|
|
|
for (auto furnEntity : meshData.isolatedFurnitureEntities) {
|
|
|
|
|
if (furnEntity.is_valid() && furnEntity.is_alive()) {
|
|
|
|
|
furnEntity.destruct();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
meshData.isolatedFurnitureEntities.clear();
|
|
|
|
|
|
|
|
|
|
// Find material - prefer ProceduralMaterial from Town/District/Lot
|
|
|
|
|
std::string materialName = "Ogre/StandardFloor"; // default
|
|
|
|
|
@@ -243,16 +282,16 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
|
|
|
|
|
// Look for ProceduralMaterial in parent hierarchy (Lot -> District -> Town)
|
|
|
|
|
flecs::entity parent = entity.parent();
|
|
|
|
|
while (parent.is_alive()) {
|
|
|
|
|
while (parent.is_valid() && parent.is_alive()) {
|
|
|
|
|
if (parent.has<LotComponent>()) {
|
|
|
|
|
auto &lot = parent.get<LotComponent>();
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_valid() && lot.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
lot.proceduralMaterialEntity
|
|
|
|
|
.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
lot.proceduralMaterialEntity.get<
|
|
|
|
|
ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created && !mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
materialEntity =
|
|
|
|
|
lot.proceduralMaterialEntity;
|
|
|
|
|
@@ -262,13 +301,13 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
}
|
|
|
|
|
if (parent.has<DistrictComponent>()) {
|
|
|
|
|
auto &district = parent.get<DistrictComponent>();
|
|
|
|
|
if (district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (district.proceduralMaterialEntity.is_valid() && district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity
|
|
|
|
|
.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
district.proceduralMaterialEntity.get<
|
|
|
|
|
ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created && !mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
materialEntity =
|
|
|
|
|
district.proceduralMaterialEntity;
|
|
|
|
|
@@ -280,13 +319,13 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
townEntity = parent;
|
|
|
|
|
auto &town = parent.get<TownComponent>();
|
|
|
|
|
// Prefer ProceduralMaterial over generated material
|
|
|
|
|
if (town.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (town.proceduralMaterialEntity.is_valid() && town.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
town.proceduralMaterialEntity
|
|
|
|
|
.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
town.proceduralMaterialEntity.get<
|
|
|
|
|
ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created && !mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
materialEntity =
|
|
|
|
|
town.proceduralMaterialEntity;
|
|
|
|
|
@@ -308,8 +347,6 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
"CellGrid: Using material '" + materialName + "' for entity " +
|
|
|
|
|
std::to_string(entity.id()));
|
|
|
|
|
|
|
|
|
|
MeshData &meshData = m_entityMeshes[entity.id()];
|
|
|
|
|
|
|
|
|
|
// Build geometry parts
|
|
|
|
|
Procedural::TriangleBuffer floorTb, ceilingTb, extWallTb, intWallTb,
|
|
|
|
|
extWindowsTb, intWindowsTb, extDoorsTb, intDoorsTb, roofTopTb, roofSideTb;
|
|
|
|
|
@@ -408,7 +445,7 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
meshData.entities.push_back(entity3d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Roof top pieces
|
|
|
|
|
// Roof top pieces -> attach to SceneNode
|
|
|
|
|
if (roofTopTb.getVertices().size() >= 3) {
|
|
|
|
|
meshData.roofMesh = baseName + "_roofTop";
|
|
|
|
|
auto mesh =
|
|
|
|
|
@@ -418,7 +455,7 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
meshData.entities.push_back(entity3d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Roof side pieces (trim/gable ends)
|
|
|
|
|
// Roof side pieces (trim/gable ends) -> attach to SceneNode
|
|
|
|
|
if (roofSideTb.getVertices().size() >= 3) {
|
|
|
|
|
meshData.roofSideMesh = baseName + "_roofSide";
|
|
|
|
|
auto mesh =
|
|
|
|
|
@@ -512,18 +549,24 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
"CellGrid: Unknown error building furniture");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build combined static geometry (frames + batched furniture)
|
|
|
|
|
// Build combined static geometry (frames + furniture + roofs)
|
|
|
|
|
auto sgIt = m_entityMeshes.find(entity.id());
|
|
|
|
|
if (sgIt != m_entityMeshes.end() && sgIt->second.frameStaticGeometry) {
|
|
|
|
|
sgIt->second.frameStaticGeometry->build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Queue physics build to happen outside query iteration
|
|
|
|
|
if (std::find(m_pendingPhysicsBuilds.begin(), m_pendingPhysicsBuilds.end(), entity) ==
|
|
|
|
|
m_pendingPhysicsBuilds.end()) {
|
|
|
|
|
m_pendingPhysicsBuilds.push_back(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store texture dependency for automatic rebuild when texture changes
|
|
|
|
|
// Get texture entity from material entity
|
|
|
|
|
if (materialEntity.is_alive() &&
|
|
|
|
|
if (materialEntity.is_valid() && materialEntity.is_alive() &&
|
|
|
|
|
materialEntity.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat = materialEntity.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity.is_alive() &&
|
|
|
|
|
if (mat.diffuseTextureEntity.is_valid() && mat.diffuseTextureEntity.is_alive() &&
|
|
|
|
|
mat.diffuseTextureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
auto &meshData = m_entityMeshes[entity.id()];
|
|
|
|
|
meshData.textureEntity = mat.diffuseTextureEntity;
|
|
|
|
|
@@ -2365,6 +2408,8 @@ void CellGridSystem::buildFurniture(flecs::entity entity,
|
|
|
|
|
staticGeom->addEntity(tempEnt, worldPos, worldRot,
|
|
|
|
|
parentScale);
|
|
|
|
|
m_sceneMgr->destroyEntity(tempEnt);
|
|
|
|
|
meshData.furniturePlacements.push_back(
|
|
|
|
|
{def->meshName, worldPos, worldRot});
|
|
|
|
|
batchedCount++;
|
|
|
|
|
} else {
|
|
|
|
|
Ogre::Entity *ent =
|
|
|
|
|
@@ -2385,6 +2430,18 @@ void CellGridSystem::buildFurniture(flecs::entity entity,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meshData.furnitureEntities.push_back(ent);
|
|
|
|
|
|
|
|
|
|
// Create isolated furniture physics body
|
|
|
|
|
flecs::entity furnEntity = m_world.entity();
|
|
|
|
|
furnEntity.child_of(entity);
|
|
|
|
|
furnEntity.set<TransformComponent>(
|
|
|
|
|
{fnode, pos, localRot, Ogre::Vector3::UNIT_SCALE});
|
|
|
|
|
furnEntity.set<RigidBodyComponent>(RigidBodyComponent());
|
|
|
|
|
PhysicsColliderComponent collider;
|
|
|
|
|
collider.shapeType = PhysicsColliderComponent::ShapeType::Mesh;
|
|
|
|
|
collider.meshName = def->meshName;
|
|
|
|
|
furnEntity.set<PhysicsColliderComponent>(collider);
|
|
|
|
|
meshData.isolatedFurnitureEntities.push_back(furnEntity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2416,6 +2473,15 @@ void CellGridSystem::destroyFurniture(flecs::entity entity)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
it->second.furnitureEntities.clear();
|
|
|
|
|
|
|
|
|
|
// Destroy isolated furniture physics entities
|
|
|
|
|
for (auto furnEntity : it->second.isolatedFurnitureEntities) {
|
|
|
|
|
if (furnEntity.is_valid() && furnEntity.is_alive()) {
|
|
|
|
|
furnEntity.destruct();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
it->second.isolatedFurnitureEntities.clear();
|
|
|
|
|
it->second.furniturePlacements.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::generateLodForMesh(Ogre::MeshPtr mesh)
|
|
|
|
|
@@ -2495,6 +2561,9 @@ void CellGridSystem::destroyCellGridMeshes(flecs::entity entity)
|
|
|
|
|
|
|
|
|
|
// Destroy frames
|
|
|
|
|
destroyFrames(entity);
|
|
|
|
|
|
|
|
|
|
// Destroy physics colliders
|
|
|
|
|
destroyPhysicsColliders(entity);
|
|
|
|
|
|
|
|
|
|
m_entityMeshes.erase(it);
|
|
|
|
|
}
|
|
|
|
|
@@ -2544,6 +2613,172 @@ void CellGridSystem::rebuildCellGrid(flecs::entity entity)
|
|
|
|
|
entity.get_mut<CellGridComponent>().markDirty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::addPhysicsCollider(flecs::entity physicsParent,
|
|
|
|
|
const std::string &meshName,
|
|
|
|
|
const Ogre::Vector3 &position,
|
|
|
|
|
const Ogre::Quaternion &rotation)
|
|
|
|
|
{
|
|
|
|
|
flecs::entity colliderEntity = m_world.entity();
|
|
|
|
|
colliderEntity.child_of(physicsParent);
|
|
|
|
|
colliderEntity.set<TransformComponent>({nullptr, position, rotation,
|
|
|
|
|
Ogre::Vector3::UNIT_SCALE});
|
|
|
|
|
PhysicsColliderComponent collider;
|
|
|
|
|
collider.shapeType = PhysicsColliderComponent::ShapeType::Mesh;
|
|
|
|
|
collider.meshName = meshName;
|
|
|
|
|
colliderEntity.set<PhysicsColliderComponent>(collider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::buildPhysicsColliders(flecs::entity entity)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// Helper to get world transform from an entity
|
|
|
|
|
auto getWorldTransform = [&](flecs::entity e,
|
|
|
|
|
Ogre::Vector3 &pos,
|
|
|
|
|
Ogre::Quaternion &rot,
|
|
|
|
|
Ogre::Vector3 &scale) {
|
|
|
|
|
if (e.is_valid() && e.is_alive() && e.has<TransformComponent>()) {
|
|
|
|
|
auto &t = e.get<TransformComponent>();
|
|
|
|
|
if (t.node) {
|
|
|
|
|
pos = t.node->_getDerivedPosition();
|
|
|
|
|
rot = t.node->_getDerivedOrientation();
|
|
|
|
|
scale = t.node->_getDerivedScale();
|
|
|
|
|
} else {
|
|
|
|
|
pos = t.position;
|
|
|
|
|
rot = t.rotation;
|
|
|
|
|
scale = t.scale;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
pos = Ogre::Vector3::ZERO;
|
|
|
|
|
rot = Ogre::Quaternion::IDENTITY;
|
|
|
|
|
scale = Ogre::Vector3::UNIT_SCALE;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Cell grid meshes, frames, and furniture
|
|
|
|
|
auto it = m_entityMeshes.find(entity.id());
|
|
|
|
|
if (it != m_entityMeshes.end()) {
|
|
|
|
|
auto &meshData = it->second;
|
|
|
|
|
|
|
|
|
|
Ogre::Vector3 parentPos;
|
|
|
|
|
Ogre::Quaternion parentRot;
|
|
|
|
|
Ogre::Vector3 parentScale;
|
|
|
|
|
getWorldTransform(entity, parentPos, parentRot, parentScale);
|
|
|
|
|
|
|
|
|
|
// Create a dedicated physics parent entity at world transform
|
|
|
|
|
flecs::entity physicsParent = m_world.entity();
|
|
|
|
|
physicsParent.child_of(entity);
|
|
|
|
|
physicsParent.set<TransformComponent>({nullptr, parentPos, parentRot,
|
|
|
|
|
parentScale});
|
|
|
|
|
physicsParent.set<RigidBodyComponent>(RigidBodyComponent());
|
|
|
|
|
meshData.physicsParentEntity = physicsParent;
|
|
|
|
|
|
|
|
|
|
// Add colliders for main cell grid meshes (local to parent)
|
|
|
|
|
auto addMeshCollider = [&](const std::string &meshName) {
|
|
|
|
|
if (!meshName.empty()) {
|
|
|
|
|
addPhysicsCollider(physicsParent, meshName,
|
|
|
|
|
Ogre::Vector3::ZERO,
|
|
|
|
|
Ogre::Quaternion::IDENTITY);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
addMeshCollider(meshData.floorMesh);
|
|
|
|
|
addMeshCollider(meshData.ceilingMesh);
|
|
|
|
|
addMeshCollider(meshData.extWallMesh);
|
|
|
|
|
addMeshCollider(meshData.intWallMesh);
|
|
|
|
|
addMeshCollider(meshData.intWindowsMesh);
|
|
|
|
|
addMeshCollider(meshData.roofMesh);
|
|
|
|
|
addMeshCollider(meshData.roofSideMesh);
|
|
|
|
|
for (const auto &doorMesh : meshData.doorMeshes)
|
|
|
|
|
addMeshCollider(doorMesh);
|
|
|
|
|
for (const auto &windowMesh : meshData.windowMeshes)
|
|
|
|
|
addMeshCollider(windowMesh);
|
|
|
|
|
|
|
|
|
|
// Add colliders for frame placements (convert world -> local)
|
|
|
|
|
for (const auto &placement : meshData.framePlacements) {
|
|
|
|
|
Ogre::Vector3 localPos =
|
|
|
|
|
parentRot.Inverse() *
|
|
|
|
|
(placement.position - parentPos);
|
|
|
|
|
Ogre::Quaternion localRot =
|
|
|
|
|
parentRot.Inverse() * placement.rotation;
|
|
|
|
|
addPhysicsCollider(physicsParent, placement.meshName,
|
|
|
|
|
localPos, localRot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add colliders for batched furniture placements (convert world -> local)
|
|
|
|
|
for (const auto &placement : meshData.furniturePlacements) {
|
|
|
|
|
Ogre::Vector3 localPos =
|
|
|
|
|
parentRot.Inverse() *
|
|
|
|
|
(placement.position - parentPos);
|
|
|
|
|
Ogre::Quaternion localRot =
|
|
|
|
|
parentRot.Inverse() * placement.rotation;
|
|
|
|
|
addPhysicsCollider(physicsParent, placement.meshName,
|
|
|
|
|
localPos, localRot);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// District plaza
|
|
|
|
|
auto plazaIt = m_plazaMeshes.find(entity.id());
|
|
|
|
|
if (plazaIt != m_plazaMeshes.end() && !plazaIt->second.meshName.empty()) {
|
|
|
|
|
Ogre::Vector3 parentPos;
|
|
|
|
|
Ogre::Quaternion parentRot;
|
|
|
|
|
Ogre::Vector3 parentScale;
|
|
|
|
|
getWorldTransform(entity, parentPos, parentRot, parentScale);
|
|
|
|
|
|
|
|
|
|
flecs::entity physicsParent = m_world.entity();
|
|
|
|
|
physicsParent.child_of(entity);
|
|
|
|
|
physicsParent.set<TransformComponent>({nullptr, parentPos, parentRot,
|
|
|
|
|
parentScale});
|
|
|
|
|
physicsParent.set<RigidBodyComponent>(RigidBodyComponent());
|
|
|
|
|
plazaIt->second.physicsParentEntity = physicsParent;
|
|
|
|
|
addPhysicsCollider(physicsParent, plazaIt->second.meshName,
|
|
|
|
|
Ogre::Vector3::ZERO, Ogre::Quaternion::IDENTITY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lot base
|
|
|
|
|
auto lotIt = m_lotBaseMeshes.find(entity.id());
|
|
|
|
|
if (lotIt != m_lotBaseMeshes.end() && !lotIt->second.meshName.empty()) {
|
|
|
|
|
Ogre::Vector3 parentPos;
|
|
|
|
|
Ogre::Quaternion parentRot;
|
|
|
|
|
Ogre::Vector3 parentScale;
|
|
|
|
|
getWorldTransform(entity, parentPos, parentRot, parentScale);
|
|
|
|
|
|
|
|
|
|
flecs::entity physicsParent = m_world.entity();
|
|
|
|
|
physicsParent.child_of(entity);
|
|
|
|
|
physicsParent.set<TransformComponent>({nullptr, parentPos, parentRot,
|
|
|
|
|
parentScale});
|
|
|
|
|
physicsParent.set<RigidBodyComponent>(RigidBodyComponent());
|
|
|
|
|
lotIt->second.physicsParentEntity = physicsParent;
|
|
|
|
|
addPhysicsCollider(physicsParent, lotIt->second.meshName,
|
|
|
|
|
Ogre::Vector3::ZERO, Ogre::Quaternion::IDENTITY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::destroyPhysicsColliders(flecs::entity entity)
|
|
|
|
|
{
|
|
|
|
|
auto it = m_entityMeshes.find(entity.id());
|
|
|
|
|
if (it != m_entityMeshes.end() &&
|
|
|
|
|
it->second.physicsParentEntity.is_valid() &&
|
|
|
|
|
it->second.physicsParentEntity.is_alive()) {
|
|
|
|
|
it->second.physicsParentEntity.destruct();
|
|
|
|
|
it->second.physicsParentEntity = flecs::entity::null();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto plazaIt = m_plazaMeshes.find(entity.id());
|
|
|
|
|
if (plazaIt != m_plazaMeshes.end() &&
|
|
|
|
|
plazaIt->second.physicsParentEntity.is_valid() &&
|
|
|
|
|
plazaIt->second.physicsParentEntity.is_alive()) {
|
|
|
|
|
plazaIt->second.physicsParentEntity.destruct();
|
|
|
|
|
plazaIt->second.physicsParentEntity = flecs::entity::null();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto lotIt = m_lotBaseMeshes.find(entity.id());
|
|
|
|
|
if (lotIt != m_lotBaseMeshes.end() &&
|
|
|
|
|
lotIt->second.physicsParentEntity.is_valid() &&
|
|
|
|
|
lotIt->second.physicsParentEntity.is_alive()) {
|
|
|
|
|
lotIt->second.physicsParentEntity.destruct();
|
|
|
|
|
lotIt->second.physicsParentEntity = flecs::entity::null();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::buildDistrictPlaza(flecs::entity entity,
|
|
|
|
|
DistrictComponent &district)
|
|
|
|
|
{
|
|
|
|
|
@@ -2563,6 +2798,7 @@ void CellGridSystem::buildDistrictPlaza(flecs::entity entity,
|
|
|
|
|
} catch (...) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
destroyPhysicsColliders(entity);
|
|
|
|
|
m_plazaMeshes.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2586,12 +2822,12 @@ void CellGridSystem::buildDistrictPlaza(flecs::entity entity,
|
|
|
|
|
// Get material from district's procedural material entity
|
|
|
|
|
std::string materialName = "Ogre/StandardFloor"; // fallback
|
|
|
|
|
|
|
|
|
|
if (district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (district.proceduralMaterialEntity.is_valid() && district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity
|
|
|
|
|
.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat = district.proceduralMaterialEntity
|
|
|
|
|
.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created && !mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -2649,19 +2885,19 @@ void CellGridSystem::buildDistrictPlaza(flecs::entity entity,
|
|
|
|
|
if (!district.textureRectName.empty()) {
|
|
|
|
|
// Find the texture entity from the material
|
|
|
|
|
flecs::entity textureEntity = flecs::entity::null();
|
|
|
|
|
if (district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (district.proceduralMaterialEntity.is_valid() && district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity
|
|
|
|
|
.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
district.proceduralMaterialEntity
|
|
|
|
|
.get<ProceduralMaterialComponent>();
|
|
|
|
|
// Search for the texture that is referenced by this material
|
|
|
|
|
if (mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
if (mat.diffuseTextureEntity.is_valid() && mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
textureEntity = mat.diffuseTextureEntity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (textureEntity.is_alive() &&
|
|
|
|
|
if (textureEntity.is_valid() && textureEntity.is_alive() &&
|
|
|
|
|
textureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
const auto &texture =
|
|
|
|
|
textureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -2736,10 +2972,10 @@ void CellGridSystem::buildDistrictPlaza(flecs::entity entity,
|
|
|
|
|
data.meshName = meshName;
|
|
|
|
|
data.entity = plazzaEntity;
|
|
|
|
|
// Store texture dependency for automatic rebuild when texture changes
|
|
|
|
|
if (district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (district.proceduralMaterialEntity.is_valid() && district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat = district.proceduralMaterialEntity.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity.is_alive() &&
|
|
|
|
|
if (mat.diffuseTextureEntity.is_valid() && mat.diffuseTextureEntity.is_alive() &&
|
|
|
|
|
mat.diffuseTextureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
data.textureEntity = mat.diffuseTextureEntity;
|
|
|
|
|
const auto &tex = mat.diffuseTextureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -2748,6 +2984,12 @@ void CellGridSystem::buildDistrictPlaza(flecs::entity entity,
|
|
|
|
|
}
|
|
|
|
|
m_plazaMeshes[entity.id()] = data;
|
|
|
|
|
|
|
|
|
|
// Queue physics rebuild
|
|
|
|
|
if (std::find(m_pendingPhysicsBuilds.begin(), m_pendingPhysicsBuilds.end(), entity) ==
|
|
|
|
|
m_pendingPhysicsBuilds.end()) {
|
|
|
|
|
m_pendingPhysicsBuilds.push_back(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGrid: Created plaza mesh for district " +
|
|
|
|
|
std::to_string(entity.id()) + " attached to node '" +
|
|
|
|
|
@@ -2778,6 +3020,7 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
} catch (...) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
destroyPhysicsColliders(entity);
|
|
|
|
|
m_lotBaseMeshes.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2802,11 +3045,11 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
|
|
|
|
|
// Material hierarchy: Lot -> District -> Town
|
|
|
|
|
// 1. Check Lot's own material first
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_valid() && lot.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
lot.proceduralMaterialEntity.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat = lot.proceduralMaterialEntity
|
|
|
|
|
.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created && !mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGrid: Using Lot's own material: " +
|
|
|
|
|
@@ -2816,20 +3059,20 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
|
|
|
|
|
// 2. Walk up hierarchy for District and Town, and fallback materials
|
|
|
|
|
flecs::entity parent = entity.parent();
|
|
|
|
|
while (parent.is_alive()) {
|
|
|
|
|
while (parent.is_valid() && parent.is_alive()) {
|
|
|
|
|
if (parent.has<DistrictComponent>()) {
|
|
|
|
|
districtEntity = parent;
|
|
|
|
|
auto &district = parent.get<DistrictComponent>();
|
|
|
|
|
districtRadius = district.radius;
|
|
|
|
|
// Use District material if Lot doesn't have one
|
|
|
|
|
if (materialName == "Ogre/StandardFloor" &&
|
|
|
|
|
district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity.is_valid() && district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity
|
|
|
|
|
.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
district.proceduralMaterialEntity.get<
|
|
|
|
|
ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created && !mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGrid: Using District material: " +
|
|
|
|
|
@@ -2842,14 +3085,13 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
// Check Town's ProceduralMaterial first, then generated material
|
|
|
|
|
if (materialName == "Ogre/StandardFloor") {
|
|
|
|
|
auto &town = parent.get<TownComponent>();
|
|
|
|
|
if (town.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
if (town.proceduralMaterialEntity.is_valid() && town.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
town.proceduralMaterialEntity.has<
|
|
|
|
|
ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
town.proceduralMaterialEntity.get<
|
|
|
|
|
ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.created &&
|
|
|
|
|
!mat.materialName.empty()) {
|
|
|
|
|
if (!mat.materialName.empty()) {
|
|
|
|
|
materialName = mat.materialName;
|
|
|
|
|
Ogre::LogManager::getSingleton()
|
|
|
|
|
.logMessage(
|
|
|
|
|
@@ -2871,7 +3113,7 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
parent = parent.parent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!districtEntity.is_alive()) {
|
|
|
|
|
if (!districtEntity.is_valid() || !districtEntity.is_alive()) {
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGrid: Lot has no parent District");
|
|
|
|
|
return;
|
|
|
|
|
@@ -2931,7 +3173,7 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
flecs::entity materialEntityToUse;
|
|
|
|
|
|
|
|
|
|
// If Lot has its own material, use its texture rect
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_valid() && lot.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
textureRectToUse = lot.textureRectName;
|
|
|
|
|
materialEntityToUse = lot.proceduralMaterialEntity;
|
|
|
|
|
if (!textureRectToUse.empty()) {
|
|
|
|
|
@@ -2942,7 +3184,7 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
} else {
|
|
|
|
|
// Lot uses District/Town material - look up hierarchy for texture rect
|
|
|
|
|
flecs::entity parent = entity.parent();
|
|
|
|
|
while (parent.is_alive()) {
|
|
|
|
|
while (parent.is_valid() && parent.is_alive()) {
|
|
|
|
|
if (parent.has<DistrictComponent>()) {
|
|
|
|
|
auto &district =
|
|
|
|
|
parent.get<DistrictComponent>();
|
|
|
|
|
@@ -2978,31 +3220,33 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
|
|
|
|
|
// Apply UV mapping
|
|
|
|
|
if (!textureRectToUse.empty()) {
|
|
|
|
|
if (materialEntityToUse.is_alive() &&
|
|
|
|
|
if (materialEntityToUse.is_valid() && materialEntityToUse.is_alive() &&
|
|
|
|
|
materialEntityToUse.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
materialEntityToUse
|
|
|
|
|
.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
if (mat.diffuseTextureEntity.is_valid() && mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
textureEntity = mat.diffuseTextureEntity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Fallback to District/Town texture
|
|
|
|
|
if (!textureEntity.is_alive()) {
|
|
|
|
|
if (!textureEntity.is_valid()) {
|
|
|
|
|
flecs::entity parent = entity.parent();
|
|
|
|
|
while (parent.is_alive()) {
|
|
|
|
|
while (parent.is_valid() && parent.is_alive()) {
|
|
|
|
|
if (parent.has<DistrictComponent>()) {
|
|
|
|
|
auto &district =
|
|
|
|
|
parent.get<DistrictComponent>();
|
|
|
|
|
if (district.proceduralMaterialEntity
|
|
|
|
|
.is_alive() &&
|
|
|
|
|
.is_valid() &&
|
|
|
|
|
district.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
district.proceduralMaterialEntity.has<
|
|
|
|
|
ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
district.proceduralMaterialEntity
|
|
|
|
|
.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity
|
|
|
|
|
.is_alive()) {
|
|
|
|
|
.is_valid() &&
|
|
|
|
|
mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
textureEntity =
|
|
|
|
|
mat.diffuseTextureEntity;
|
|
|
|
|
break;
|
|
|
|
|
@@ -3013,14 +3257,16 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
auto &town =
|
|
|
|
|
parent.get<TownComponent>();
|
|
|
|
|
if (town.proceduralMaterialEntity
|
|
|
|
|
.is_alive() &&
|
|
|
|
|
.is_valid() &&
|
|
|
|
|
town.proceduralMaterialEntity.is_alive() &&
|
|
|
|
|
town.proceduralMaterialEntity.has<
|
|
|
|
|
ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
town.proceduralMaterialEntity
|
|
|
|
|
.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity
|
|
|
|
|
.is_alive()) {
|
|
|
|
|
.is_valid() &&
|
|
|
|
|
mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
textureEntity =
|
|
|
|
|
mat.diffuseTextureEntity;
|
|
|
|
|
break;
|
|
|
|
|
@@ -3032,7 +3278,7 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (textureEntity.is_alive() &&
|
|
|
|
|
if (textureEntity.is_valid() && textureEntity.is_alive() &&
|
|
|
|
|
textureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
const auto &texture =
|
|
|
|
|
textureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -3133,7 +3379,7 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
data.entity = lotBaseEntity;
|
|
|
|
|
// Store texture dependency for automatic rebuild when texture changes
|
|
|
|
|
// textureEntity was determined earlier in the function
|
|
|
|
|
if (textureEntity.is_alive() &&
|
|
|
|
|
if (textureEntity.is_valid() && textureEntity.is_alive() &&
|
|
|
|
|
textureEntity.has<ProceduralTextureComponent>()) {
|
|
|
|
|
data.textureEntity = textureEntity;
|
|
|
|
|
const auto &tex = textureEntity.get<ProceduralTextureComponent>();
|
|
|
|
|
@@ -3141,6 +3387,12 @@ void CellGridSystem::buildLotBase(flecs::entity entity, LotComponent &lot)
|
|
|
|
|
}
|
|
|
|
|
m_lotBaseMeshes[entity.id()] = data;
|
|
|
|
|
|
|
|
|
|
// Queue physics rebuild
|
|
|
|
|
if (std::find(m_pendingPhysicsBuilds.begin(), m_pendingPhysicsBuilds.end(), entity) ==
|
|
|
|
|
m_pendingPhysicsBuilds.end()) {
|
|
|
|
|
m_pendingPhysicsBuilds.push_back(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGrid: Successfully created lot base mesh for entity " +
|
|
|
|
|
std::to_string(entity.id()) + " with " +
|
|
|
|
|
@@ -3177,16 +3429,16 @@ void CellGridSystem::applyUVMappingToBuffer(Procedural::TriangleBuffer &tb,
|
|
|
|
|
|
|
|
|
|
// Find texture entity from material
|
|
|
|
|
flecs::entity textureEntity = flecs::entity::null();
|
|
|
|
|
if (materialEntity.is_alive() &&
|
|
|
|
|
if (materialEntity.is_valid() && materialEntity.is_alive() &&
|
|
|
|
|
materialEntity.has<ProceduralMaterialComponent>()) {
|
|
|
|
|
const auto &mat =
|
|
|
|
|
materialEntity.get<ProceduralMaterialComponent>();
|
|
|
|
|
if (mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
if (mat.diffuseTextureEntity.is_valid() && mat.diffuseTextureEntity.is_alive()) {
|
|
|
|
|
textureEntity = mat.diffuseTextureEntity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!textureEntity.is_alive()) {
|
|
|
|
|
if (!textureEntity.is_valid() || !textureEntity.is_alive()) {
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
"CellGrid: WARNING - No texture entity for rect: " +
|
|
|
|
|
rectName);
|
|
|
|
|
@@ -3262,17 +3514,17 @@ void CellGridSystem::buildFrames(flecs::entity entity,
|
|
|
|
|
// Get material entity for UV mapping
|
|
|
|
|
flecs::entity materialEntity = flecs::entity::null();
|
|
|
|
|
flecs::entity parent = entity.parent();
|
|
|
|
|
while (parent.is_alive()) {
|
|
|
|
|
while (parent.is_valid() && parent.is_alive()) {
|
|
|
|
|
if (parent.has<LotComponent>()) {
|
|
|
|
|
auto &lot = parent.get<LotComponent>();
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
if (lot.proceduralMaterialEntity.is_valid() && lot.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
materialEntity = lot.proceduralMaterialEntity;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (parent.has<DistrictComponent>()) {
|
|
|
|
|
auto &district = parent.get<DistrictComponent>();
|
|
|
|
|
if (district.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
if (district.proceduralMaterialEntity.is_valid() && district.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
materialEntity =
|
|
|
|
|
district.proceduralMaterialEntity;
|
|
|
|
|
break;
|
|
|
|
|
@@ -3280,7 +3532,7 @@ void CellGridSystem::buildFrames(flecs::entity entity,
|
|
|
|
|
}
|
|
|
|
|
if (parent.has<TownComponent>()) {
|
|
|
|
|
auto &town = parent.get<TownComponent>();
|
|
|
|
|
if (town.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
if (town.proceduralMaterialEntity.is_valid() && town.proceduralMaterialEntity.is_alive()) {
|
|
|
|
|
materialEntity = town.proceduralMaterialEntity;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -3941,6 +4193,7 @@ void CellGridSystem::destroyFrames(flecs::entity entity)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
it->second.frameEntities.clear();
|
|
|
|
|
it->second.framePlacements.clear();
|
|
|
|
|
|
|
|
|
|
// Destroy frame meshes
|
|
|
|
|
auto &meshMgr = Ogre::MeshManager::getSingleton();
|
|
|
|
|
@@ -4009,6 +4262,12 @@ void CellGridSystem::placeWindowFramesInStaticGeometry(
|
|
|
|
|
staticGeom->addEntity(tempEnt, worldPos, worldRot, parentScale);
|
|
|
|
|
m_sceneMgr->destroyEntity(tempEnt); // StaticGeometry copies the data
|
|
|
|
|
frameCount++;
|
|
|
|
|
|
|
|
|
|
auto it = m_entityMeshes.find(entity.id());
|
|
|
|
|
if (it != m_entityMeshes.end()) {
|
|
|
|
|
it->second.framePlacements.push_back(
|
|
|
|
|
{mesh->getName(), worldPos, worldRot});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (extMesh) {
|
|
|
|
|
@@ -4099,6 +4358,12 @@ void CellGridSystem::placeDoorFramesInStaticGeometry(
|
|
|
|
|
staticGeom->addEntity(tempEnt, worldPos, worldRot, parentScale);
|
|
|
|
|
m_sceneMgr->destroyEntity(tempEnt); // StaticGeometry copies the data
|
|
|
|
|
frameCount++;
|
|
|
|
|
|
|
|
|
|
auto it = m_entityMeshes.find(entity.id());
|
|
|
|
|
if (it != m_entityMeshes.end()) {
|
|
|
|
|
it->second.framePlacements.push_back(
|
|
|
|
|
{mesh->getName(), worldPos, worldRot});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const auto &cell : grid.cells) {
|
|
|
|
|
|