Adapted ECS for building instances

This commit is contained in:
2024-09-29 18:36:11 +03:00
parent 0d425391ce
commit 20807366d1
3 changed files with 236 additions and 24 deletions

View File

@@ -1,3 +1,5 @@
#undef NDEBUG
#include <cassert>
#include <algorithm> #include <algorithm>
#include <core/os/memory.h> #include <core/os/memory.h>
#include <core/io/json.h> #include <core/io/json.h>
@@ -19,7 +21,12 @@ struct scene_data {
Ref<PackedScene> packed_scene; Ref<PackedScene> packed_scene;
String path; String path;
Ref<ResourceInteractiveLoader> loader; Ref<ResourceInteractiveLoader> loader;
std::vector<String> buildings; // std::vector<String> buildings;
};
struct CBuildingInstance {
String key;
Node *node;
}; };
struct CSceneData { struct CSceneData {
@@ -426,11 +433,28 @@ void BuildingsData::remove_scene_item(const String &key, const String &bkey)
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
#if 0
std::vector<String>::iterator b = d->sd.buildings.begin(); std::vector<String>::iterator b = d->sd.buildings.begin();
std::vector<String>::iterator h = d->sd.buildings.end(); std::vector<String>::iterator h = d->sd.buildings.end();
// if (item_nodes.has(item)) // if (item_nodes.has(item))
// item_nodes[item]->queue_delete(); // item_nodes[item]->queue_delete();
d->sd.buildings.erase(std::remove(b, h, bkey), d->sd.buildings.end()); d->sd.buildings.erase(std::remove(b, h, bkey), d->sd.buildings.end());
#endif
flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>().with(
flecs::ChildOf, e);
flecs::query<const CBuildingInstance> q = qb.build();
uint64_t key_hash = bkey.hash64();
flecs::entity em = q.find([key_hash](const CBuildingInstance &bi) {
return bi.key.hash64() == key_hash;
});
if (em.is_valid()) {
CBuildingInstance *bi = em.get_mut<CBuildingInstance>();
if (bi->node)
bi->node->queue_delete();
bi->node = nullptr;
em.destruct();
}
} }
void BuildingsData::add_scene_item(const String &key, const String &bkey) void BuildingsData::add_scene_item(const String &key, const String &bkey)
@@ -439,9 +463,19 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey)
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
#if 0
if (std::find(d->sd.buildings.begin(), d->sd.buildings.end(), bkey) == if (std::find(d->sd.buildings.begin(), d->sd.buildings.end(), bkey) ==
d->sd.buildings.end()) d->sd.buildings.end())
d->sd.buildings.push_back(bkey); d->sd.buildings.push_back(bkey);
#endif
String ename = "bi:" + bkey;
flecs::entity ce = e.lookup(ename.ascii().ptr());
if (ce.is_valid())
ce.destruct();
ce = ecs.entity(ename.ascii().ptr());
ce.child_of(e);
ce.set<CBuildingInstance>({ bkey, nullptr });
print_line("child name: " + String(ce.name()));
} }
void BuildingsData::create_scene_data(const String &key, const String &bkey) void BuildingsData::create_scene_data(const String &key, const String &bkey)
@@ -454,11 +488,21 @@ void BuildingsData::create_scene_data(const String &key, const String &bkey)
sd.path = path; sd.path = path;
sd.loader = ResourceLoader::load_interactive( sd.loader = ResourceLoader::load_interactive(
path, "PackedScene", true); path, "PackedScene", true);
#if 0
if (std::find(sd.buildings.begin(), sd.buildings.end(), bkey) == if (std::find(sd.buildings.begin(), sd.buildings.end(), bkey) ==
sd.buildings.end()) sd.buildings.end())
sd.buildings.push_back(bkey); sd.buildings.push_back(bkey);
#endif
e.set<CSceneData>({ sd }); e.set<CSceneData>({ sd });
assert(e.get_mut<CSceneData>()); assert(e.get_mut<CSceneData>());
String ename = "bi:" + bkey;
flecs::entity ce = e.lookup(ename.ascii().ptr());
if (ce.is_valid())
ce.destruct();
ce = ecs.entity(ename.ascii().ptr());
ce.child_of(e);
ce.set<CBuildingInstance>({ bkey, nullptr });
print_line("child name: " + String(ce.name()));
} }
} }
@@ -485,46 +529,183 @@ int BuildingsData::scene_get_item_count(const String &key) const
assert(e.is_valid()); assert(e.is_valid());
const CSceneData *d = e.get<CSceneData>(); const CSceneData *d = e.get<CSceneData>();
assert(d); assert(d);
return d->sd.buildings.size(); // return d->sd.buildings.size();
flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>().with(
flecs::ChildOf, e);
flecs::query<const CBuildingInstance> q = qb.build();
int result;
q.run([&result](flecs::iter &it) {
it.next();
result = it.count();
it.fini();
});
// assert(result == d->sd.buildings.size());
print_line("scene_get_item_count: " + itos(result));
return result;
} }
List<String> BuildingsData::scene_get_items(const String &key) const
String BuildingsData::scene_get_item(const String &key, int index) const
{ {
List<String> ret;
int i;
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs.lookup(key.ascii().ptr());
if (!e.is_valid()) if (!e.is_valid())
return ""; return List<String>();
if (!e.get<CSceneData>()) if (!e.get<CSceneData>())
return ""; return List<String>();
assert(e.is_valid()); assert(e.is_valid());
const CSceneData *d = e.get<CSceneData>(); const CSceneData *d = e.get<CSceneData>();
assert(d); assert(d);
return d->sd.buildings[index]; flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>().with(
flecs::ChildOf, e);
flecs::query<const CBuildingInstance> q = qb.build();
q.each([&ret](flecs::entity me, const CBuildingInstance &ib) {
ret.push_back(ib.key);
});
return ret;
}
void BuildingsData::set_scene_item_node(const String &key, const String &bkey,
Node *node)
{
flecs::entity e = ecs.lookup(key.ascii().ptr());
assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>();
assert(d);
#if 0
if (std::find(d->sd.buildings.begin(), d->sd.buildings.end(), bkey) ==
d->sd.buildings.end())
d->sd.buildings.push_back(bkey);
#endif
String ename = "bi:" + bkey;
flecs::entity ce = e.lookup(ename.ascii().ptr());
assert(ce.is_valid());
CBuildingInstance *bi = ce.get_mut<CBuildingInstance>();
assert(bi);
assert(bi->key == bkey);
bi->node = node;
}
bool BuildingsData::has_scene_item(const String &key, const String &bkey) const
{
flecs::entity e = ecs.lookup(key.ascii().ptr());
assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>();
assert(d);
String ename = "bi:" + bkey;
flecs::entity ce = e.lookup(ename.ascii().ptr());
return ce.is_valid();
}
Node *BuildingsData::get_scene_item_node(const String &key,
const String &bkey) const
{
flecs::entity e = ecs.lookup(key.ascii().ptr());
assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>();
assert(d);
String ename = "bi:" + bkey;
flecs::entity ce = e.lookup(ename.ascii().ptr());
assert(ce.is_valid());
CBuildingInstance *bi = ce.get_mut<CBuildingInstance>();
assert(bi);
assert(bi->key == bkey);
return bi->node;
} }
void BuildingsData::item_nodes_delete_node(const String &key) void BuildingsData::item_nodes_delete_node(const String &key)
{ {
#if 0
if (item_nodes.has(key)) { if (item_nodes.has(key)) {
item_nodes[key]->queue_delete(); item_nodes[key]->queue_delete();
item_nodes.erase(key); item_nodes.erase(key);
} }
#endif
flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>();
flecs::query<const CBuildingInstance> q = qb.build();
uint64_t key_hash = key.hash64();
flecs::entity e = q.find(
[key_hash](flecs::entity me, const CBuildingInstance &ib) {
return ib.key.hash64() == key_hash;
});
assert(e.is_valid());
CBuildingInstance *ib = e.get_mut<CBuildingInstance>();
if (ib->node)
ib->node->queue_delete();
ib->node = nullptr;
} }
#if 0
bool BuildingsData::item_nodes_exists(const String &key) const bool BuildingsData::item_nodes_exists(const String &key) const
{ {
#if 0
bool result = false;
return item_nodes.has(key); return item_nodes.has(key);
flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>();
flecs::query<const CBuildingInstance> q = qb.build();
uint64_t key_hash = key.hash64();
q.run([key_hash, &result](flecs::iter &it) {
while (it.next()) {
auto em = it.field<flecs::entity>(0);
auto ib = it.field<const CBuildingInstance>(1);
if (ib->key.hash64() == key_hash) {
result = true;
it.fini();
break;
}
}
});
return result;
#endif
String ename = "bi:" + key;
flecs::entity ce = ecs.lookup(ename.ascii().ptr());
bool result = ce.is_valid();
if (!result)
return result;
const CBuildingInstance *bi = ce.get<CBuildingInstance>();
if (!bi)
return false;
if (bi->node)
return true;
return false;
} }
void BuildingsData::item_nodes_set_node(const String &key, Node *node) void BuildingsData::item_nodes_set_node(const String &key, Node *node)
{ {
item_nodes[key] = node; item_nodes[key] = node;
String ename = "bi:" + key;
print_line(ename);
flecs::entity ce = ecs.lookup(ename.ascii().ptr());
assert(ce.is_valid());
CBuildingInstance *bi = ce.get_mut<CBuildingInstance>();
assert(bi);
bi->node = node;
} }
#endif
void BuildingsData::item_nodes_item_removed(const String &key) void BuildingsData::item_nodes_item_removed(const String &key)
{ {
int i; int i;
#if 0
if (item_nodes[key]) if (item_nodes[key])
item_nodes[key]->queue_delete(); item_nodes[key]->queue_delete();
item_nodes.erase(key); item_nodes.erase(key);
#endif
flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>();
flecs::query<const CBuildingInstance> q = qb.build();
Node *ret;
uint64_t key_hash = key.hash64();
flecs::entity e = q.find([key_hash](const CBuildingInstance &bi) {
return bi.key.hash64() == key_hash;
});
assert(e.is_valid());
CBuildingInstance *bi = e.get_mut<CBuildingInstance>();
assert(bi);
if (bi->node) {
bi->node->queue_delete();
}
bi->node = nullptr;
} }
String BuildingsData::item_nodes_get_key(int item) const String BuildingsData::item_nodes_get_key(int item) const
@@ -532,11 +713,34 @@ String BuildingsData::item_nodes_get_key(int item) const
return buildings[item].key; return buildings[item].key;
} }
#if 0
Node *BuildingsData::item_nodes_get_node(const String &key) const Node *BuildingsData::item_nodes_get_node(const String &key) const
{ {
if (!item_nodes_exists(key)) if (!item_nodes_exists(key))
return nullptr; return nullptr;
return item_nodes[key]; // return item_nodes[key];
String ename = "bi:" + key;
flecs::entity ce = ecs.lookup(ename.ascii().ptr());
assert(ce.is_valid());
CBuildingInstance *bi = ce.get_mut<CBuildingInstance>();
assert(bi);
return bi->node;
}
#endif
Node *BuildingsData::item_nodes_get_node(const String &key) const
{
flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>();
flecs::query<const CBuildingInstance> q = qb.build();
Node *ret;
uint64_t key_hash = key.hash64();
flecs::entity e = q.find([key_hash](const CBuildingInstance &bi) {
return bi.key.hash64() == key_hash;
});
if (e.is_valid())
return e.get<CBuildingInstance>()->node;
else
return nullptr;
} }
Error BuildingsData::scene_loader_poll(const String &key) Error BuildingsData::scene_loader_poll(const String &key)

View File

@@ -33,12 +33,17 @@ public:
void create_scene_data(const String &key, const String &bkey); void create_scene_data(const String &key, const String &bkey);
Ref<PackedScene> scene_get_packed_scene(const String &key) const; Ref<PackedScene> scene_get_packed_scene(const String &key) const;
int scene_get_item_count(const String &key) const; int scene_get_item_count(const String &key) const;
String scene_get_item(const String &key, int index) const; // String scene_get_item(const String &key, int index) const;
List<String> scene_get_items(const String &key) const;
void set_scene_item_node(const String &key, const String &bkey,
Node *node);
bool has_scene_item(const String &key, const String &bkey) const;
Node *get_scene_item_node(const String &key, const String &bkey) const;
public: public:
void item_nodes_delete_node(const String &key); void item_nodes_delete_node(const String &key);
bool item_nodes_exists(const String &key) const; // bool item_nodes_exists(const String &key) const;
void item_nodes_set_node(const String &key, Node *node); // void item_nodes_set_node(const String &key, Node *node);
void item_nodes_item_removed(const String &key); void item_nodes_item_removed(const String &key);
Node *item_nodes_get_node(const String &key) const; Node *item_nodes_get_node(const String &key) const;
String item_nodes_get_key(int item) const; String item_nodes_get_key(int item) const;
@@ -55,7 +60,7 @@ public:
/* Data for each building in a world */ /* Data for each building in a world */
private: private:
std::vector<struct building> buildings; std::vector<struct building> buildings;
HashMap<String, Node *> item_nodes; // HashMap<String, Node *> item_nodes;
public: public:
int get_building_count() const; int get_building_count() const;

View File

@@ -181,7 +181,6 @@ void StreamWorld::request_item(int type, int item)
print_line("Removing " + itos(item)); print_line("Removing " + itos(item));
if (data()->has_scene(id)) { if (data()->has_scene(id)) {
data()->remove_scene_item(id, bkey); data()->remove_scene_item(id, bkey);
data()->item_nodes_delete_node(bkey);
} }
} break; } break;
} }
@@ -189,7 +188,6 @@ void StreamWorld::request_item(int type, int item)
void StreamWorld::update_items() void StreamWorld::update_items()
{ {
int i;
List<String> keys; List<String> keys;
data()->get_scene_keys_list(&keys); data()->get_scene_keys_list(&keys);
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
@@ -199,19 +197,24 @@ void StreamWorld::update_items()
e = e->next(); e = e->next();
continue; continue;
} }
for (i = 0; i < (int)data()->scene_get_item_count(key); i++) { const List<String> &items = data()->scene_get_items(key);
const String &bkey = data()->scene_get_item(key, i); const List<String>::Element *be = items.front();
if (data()->item_nodes_exists(bkey)) while (be) {
const String &bkey = be->get();
if (data()->has_scene_item(key, bkey) &&
data()->get_scene_item_node(key, bkey)) {
be = be->next();
continue; continue;
}
Node *psc = Node *psc =
data()->scene_get_packed_scene(key)->instance(); data()->scene_get_packed_scene(key)->instance();
Spatial *psp = Object::cast_to<Spatial>(psc); Spatial *psp = Object::cast_to<Spatial>(psc);
data()->item_nodes_set_node(bkey, psc); // data()->item_nodes_set_node(bkey, psc);
current_scene->add_child(psp); data()->set_scene_item_node(key, bkey, psc);
psp->set_global_transform( current_scene->call_deferred("add_child", psp);
data()->get_building( psp->call_deferred("set_global_transform",
data()->scene_get_item(key, i)) data()->get_building(bkey).xform);
.xform); be = be->next();
} }
e = e->next(); e = e->next();
} }