Action nodes support and lots of other updates

This commit is contained in:
2026-01-19 00:07:03 +03:00
parent f86e7fd96c
commit 4b24d85123
34 changed files with 7810 additions and 3488 deletions

View File

@@ -6,6 +6,7 @@
#include <OgreRTShaderSystem.h>
#include <OgreStaticGeometry.h>
#include <OgreMeshLodGenerator.h>
#include <OgreWorkQueue.h>
#include <Procedural.h>
#include "Components.h"
#include "GameData.h"
@@ -20,6 +21,7 @@ namespace ECS
static bool itemsLoaded = false;
static bool furnitureLoaded = false;
static bool templatesLoaded = false;
static std::list<std::pair<long, long> > addQueue;
StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
{
@@ -27,6 +29,32 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
ecs.component<TerrainSlotParent>();
ecs.component<TerrainItem>();
ecs.component<FurnitureItem>();
ecs.component<FurnitureInstance>()
.on_remove([](flecs::entity e, FurnitureInstance &instance) {
if (instance.furniture) {
instance.furniture
->destroyAllChildrenAndObjects();
instance.furniture->getCreator()
->destroySceneNode(instance.furniture);
instance.furniture = nullptr;
}
})
.on_set([](flecs::entity e, FurnitureInstance &instance) {
if (instance.furniture !=
e.get<FurnitureInstance>().furniture) {
FurnitureInstance &f =
e.get_mut<FurnitureInstance>();
if (f.furniture) {
f.furniture
->destroyAllChildrenAndObjects();
f.furniture->getCreator()
->destroySceneNode(f.furniture);
}
}
})
.on_add([](flecs::entity e, FurnitureInstance &instance) {
instance.furniture = nullptr;
});
ecs.component<TerrainItemNode>().on_remove([](flecs::entity e,
TerrainItemNode &item) {
if (item.itemNode) {
@@ -42,6 +70,7 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
}
});
ecs.component<TerrainItemMeshNode>();
ecs.component<GeometryUpdateItem>();
ecs.import <TerrainModule>();
ecs.observer<const Terrain>("LoadTerrainItems")
.event(flecs::OnSet)
@@ -65,6 +94,10 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
if (!furnitureLoaded) {
loadFurniture();
furnitureLoaded = true;
}
if (!templatesLoaded) {
loadTemplates();
templatesLoaded = true;
}
std::list<std::pair<long, long> > output;
while (!addQueue.empty()) {
@@ -163,8 +196,48 @@ void StaticGeometryModule::setItemProperties(flecs::entity id,
const Ogre::String &StaticGeometryModule::getItemProperties(flecs::entity id)
{
OgreAssert(id.is_valid(), "bad id");
return id.get<TerrainItem>().properties;
return id.get<TerrainItem>().properties;
}
nlohmann::json templates;
void StaticGeometryModule::loadTemplates()
{
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"templates.list"))
return;
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("templates.list");
Ogre::DataStreamPtr stream =
Ogre::ResourceGroupManager::getSingleton().openResource(
"templates.list", group);
Ogre::String json = stream->getAsString();
nlohmann::json jtemplates = nlohmann::json::parse(json);
templates = jtemplates;
}
void StaticGeometryModule::saveTemplates()
{
Ogre::String path = "resources/buildings/templates.list";
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"templates.list")) {
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("templates.list");
Ogre::FileInfoListPtr fileInfoList(
Ogre::ResourceGroupManager::getSingleton()
.findResourceFileInfo(group, "templates.list"));
OgreAssert(fileInfoList->size() == 1,
"templates.list should be there and only once");
path = fileInfoList->at(0).archive->getName() + "/" +
"templates.list";
Ogre::FileSystemLayer::removeFile(path);
}
std::fstream fout(path.c_str(), std::ios::out);
fout << templates.dump();
fout.close();
}
void StaticGeometryModule::saveItems()
{
Ogre::String path = "resources/buildings/items.list";
@@ -378,6 +451,58 @@ void StaticGeometryModule::destroyItemGeometry(flecs::entity e)
{
Geometry::destroyItemGeometry(e);
}
nlohmann::json &StaticGeometryModule::getTemplates()
{
return templates;
}
void StaticGeometryModule::updateItemGeometry(flecs::entity e)
{
if (e.has<GeometryUpdateItem>())
return;
e.add<GeometryUpdateItem>();
Ogre::Root::getSingleton().getWorkQueue()->addTask([e]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask(
[e]() {
Geometry::updateItemGeometry(e);
e.remove<GeometryUpdateItem>();
});
});
}
void StaticGeometryModule::addTriangleBufferWork(
const Ogre::String &meshName, Ogre::StaticGeometry *geo,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
const Procedural::TriangleBuffer &tb)
{
struct WorkData {
Ogre::String meshName;
Ogre::StaticGeometry *geo;
Ogre::Vector3 position;
Ogre::Quaternion rotation;
Procedural::TriangleBuffer tb;
};
WorkData data = { meshName, geo, position, rotation, tb };
Ogre::Root::getSingleton().getWorkQueue()->addTask([captData = std::move(
data)]() {
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask(
[captData]() {
Ogre::MeshPtr mesh =
captData.tb.transformToMesh(
captData.meshName);
Ogre::Entity *ent =
ECS::get<EngineData>()
.mScnMgr->createEntity(mesh);
captData.geo->addEntity(ent, captData.position,
captData.rotation);
ECS::get<EngineData>().mScnMgr->destroyEntity(
ent);
});
});
}
struct TiledMeshes {
struct Tile {
Ogre::String materialName;
@@ -412,13 +537,6 @@ struct TiledMeshes {
if (tiles.find(name) == tiles.end())
return;
tiles[name].positions.erase(packKey(position));
#if 0
auto pos = std::find(tiles[name].positions.begin(),
tiles[name].positions.end(),
packKey(position));
if (pos != tiles[name].positions.end())
tiles[name].positions.erase(pos);
#endif
}
void addTile(const Ogre::String &name, Ogre::MeshPtr mesh)
{
@@ -435,102 +553,6 @@ struct TiledMeshes {
std::shared_ptr<Ogre::IndexData>(
submesh->indexData->clone()),
{} };
#if 0
std::vector<Ogre::Vector3> vertices;
std::vector<uint32_t> indices;
int count = mesh->getNumSubMeshes();
int i, j;
int indexCount = 0;
int vertexCount = 0;
int sharedVertexOffset = 0;
for (i = 0; i < count; i++) {
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
indexCount += submesh->indexData->indexCount;
if (submesh->useSharedVertices)
vertexCount +=
mesh->sharedVertexData->vertexCount;
else
vertexCount += submesh->vertexData->vertexCount;
}
indices.reserve(indexCount);
vertices.reserve(vertexCount);
size_t currentVertexOffset = 0;
bool added_shared = false;
for (i = 0; i < count; i++) {
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
Ogre::VertexData *vertex_data =
submesh->useSharedVertices ?
mesh->sharedVertexData :
submesh->vertexData;
bool add_vertices =
(submesh->useSharedVertices && !added_shared) ||
!submesh->useSharedVertices;
if (add_vertices) {
if (submesh->useSharedVertices)
sharedVertexOffset = vertices.size();
const Ogre::VertexDeclaration *decl =
vertex_data->vertexDeclaration;
const Ogre::VertexBufferBinding *bind =
vertex_data->vertexBufferBinding;
const Ogre::VertexElement *position_element =
decl->findElementBySemantic(
Ogre::VES_POSITION);
if (!position_element)
continue;
Ogre::HardwareVertexBufferSharedPtr vbuf =
bind->getBuffer(
position_element->getSource());
unsigned char *vertex_buffer = static_cast<
unsigned char *>(vbuf->lock(
Ogre::HardwareBuffer::HBL_READ_ONLY));
int vertexSize = vbuf->getVertexSize();
for (j = 0; j < vertex_data->vertexCount; j++) {
float *position_data;
position_element
->baseVertexPointerToElement(
vertex_buffer,
&position_data);
vertices.push_back(
{ position_data[0],
position_data[1],
position_data[2] });
vertex_buffer += vertexSize;
}
if (submesh->useSharedVertices)
added_shared = true;
vbuf->unlock();
}
Ogre::HardwareIndexBufferSharedPtr ibuf =
submesh->indexData->indexBuffer;
size_t numIndices = submesh->indexData->indexCount;
size_t vertexOffset = submesh->useSharedVertices ?
sharedVertexOffset :
currentVertexOffset;
if (ibuf->getType() ==
Ogre::HardwareIndexBuffer::IT_32BIT) {
unsigned int *pIndices = static_cast<
unsigned int *>(ibuf->lock(
Ogre::HardwareBuffer::HBL_READ_ONLY));
for (j = 0; j < numIndices; j++) {
indices.push_back(
(uint32_t)pIndices[j] +
vertexOffset);
}
ibuf->unlock();
} else {
unsigned short *pIndices = static_cast<
unsigned short *>(ibuf->lock(
Ogre::HardwareBuffer::HBL_READ_ONLY));
for (j = 0; j < numIndices; j++) {
indices.push_back(
(uint32_t)pIndices[j] +
vertexOffset);
}
ibuf->unlock();
}
currentVertexOffset = vertices.size();
}
#endif
}
struct buildSettings {
Ogre::String meshName;
@@ -766,10 +788,8 @@ out:;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(2, 0.15f);
config.createGeneratedLodLevel(20, 0.49f);
#if 0
config.createGeneratedLodLevel(15, 0.49f);
config.createGeneratedLodLevel(150, 0.75f);
#endif
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
config);