From e19dbd7a4f6f603f687f470929f109dc6593d8e7 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Sat, 28 Sep 2024 05:23:24 +0300 Subject: [PATCH] Started using ECS --- src/modules/stream/buildings_data.cpp | 146 +++++++++++++++++++++++++- src/modules/stream/buildings_data.h | 25 +++-- src/modules/stream/stream.cpp | 81 ++++---------- 3 files changed, 184 insertions(+), 68 deletions(-) diff --git a/src/modules/stream/buildings_data.cpp b/src/modules/stream/buildings_data.cpp index 00a8a48..4cb0b1f 100644 --- a/src/modules/stream/buildings_data.cpp +++ b/src/modules/stream/buildings_data.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,12 +8,23 @@ #include #include #include "from_string.h" -#include +#include "flecs/flecs.h" #include "buildings_data.h" BuildingsData *BuildingsData::singleton; static ConfigFile config; +static flecs::world ecs; +struct scene_data { + Ref packed_scene; + String path; + Ref loader; + std::vector buildings; +}; + +struct CSceneData { + struct scene_data sd; +}; BuildingsData::BuildingsData() : undo_log_size(64) @@ -395,6 +407,138 @@ func fill_door_locations(): } } +void BuildingsData::get_scene_keys_list(List *keys) const +{ + ecs.each([keys](flecs::entity e, const CSceneData &d) { + keys->push_back(String(e.name())); + }); +} + +bool BuildingsData::has_scene(const String &key) const +{ + flecs::entity e = ecs.lookup(key.ascii().ptr()); + return e.is_valid(); +} + +void BuildingsData::remove_scene_item(const String &key, int item) +{ + flecs::entity e = ecs.lookup(key.ascii().ptr()); + assert(e.is_valid()); + CSceneData *d = e.get_mut(); + assert(d); + std::vector::iterator b = d->sd.buildings.begin(); + std::vector::iterator h = d->sd.buildings.end(); + // if (item_nodes.has(item)) + // item_nodes[item]->queue_delete(); + d->sd.buildings.erase(std::remove(b, h, item), d->sd.buildings.end()); +} + +void BuildingsData::add_scene_item(const String &key, int item) +{ + flecs::entity e = ecs.lookup(key.ascii().ptr()); + assert(e.is_valid()); + CSceneData *d = e.get_mut(); + assert(d); + if (std::find(d->sd.buildings.begin(), d->sd.buildings.end(), item) == + d->sd.buildings.end()) + d->sd.buildings.push_back(item); +} + +void BuildingsData::create_scene_data(const String &key, int item) +{ + if (!has_scene(key)) { + flecs::entity e = ecs.entity(key.ascii().ptr()); + String path = building_data[key]; + print_line("Requesting " + itos(item) + " " + path); + struct scene_data sd; + sd.path = path; + sd.loader = ResourceLoader::load_interactive( + path, "PackedScene", true); + if (std::find(sd.buildings.begin(), sd.buildings.end(), item) == + sd.buildings.end()) + sd.buildings.push_back(item); + e.set({ sd }); + assert(e.get_mut()); + } +} + +Ref BuildingsData::scene_get_packed_scene(const String &key) const +{ + flecs::entity e = ecs.lookup(key.ascii().ptr()); + if (!e.is_valid()) + return Ref(); + if (!e.get()) + return Ref(); + assert(e.is_valid()); + const CSceneData *d = e.get(); + assert(d); + return d->sd.packed_scene; +} + +int BuildingsData::scene_get_item_count(const String &key) const +{ + flecs::entity e = ecs.lookup(key.ascii().ptr()); + if (!e.is_valid()) + return 0; + if (!e.get()) + return 0; + assert(e.is_valid()); + const CSceneData *d = e.get(); + assert(d); + return d->sd.buildings.size(); +} + +int BuildingsData::scene_get_item(const String &key, int index) const +{ + flecs::entity e = ecs.lookup(key.ascii().ptr()); + if (!e.is_valid()) + return -1; + if (!e.get()) + return -1; + assert(e.is_valid()); + const CSceneData *d = e.get(); + assert(d); + return d->sd.buildings[index]; +} + +Error BuildingsData::scene_loader_poll(const String &key) +{ + if (has_scene(key)) { + flecs::entity e = ecs.lookup(key.ascii().ptr()); + assert(e.is_valid()); + CSceneData *d = e.get_mut(); + assert(d); + Error err = d->sd.loader->poll(); + if (err == ERR_FILE_EOF) { + Ref sc = d->sd.loader->get_resource(); + d->sd.packed_scene = sc; + print_line("Loaded scene: " + d->sd.path + " OK"); + return OK; + } else { + print_error("Could not load the resource :( " + + d->sd.path + " " + itos(err)); + return err; + } + } + return FAILED; +} + +void BuildingsData::scene_update() +{ + List keys; + get_scene_keys_list(&keys); + List::Element *e = keys.front(); + while (e) { + const String &key = e->get(); + if (scene_get_packed_scene(key).is_valid()) { + e = e->next(); + continue; + } + scene_loader_poll(key); + e = e->next(); + } +} + int BuildingsData::get_building_count() const { return buildings.size(); diff --git a/src/modules/stream/buildings_data.h b/src/modules/stream/buildings_data.h index 5a2f7cf..8394227 100644 --- a/src/modules/stream/buildings_data.h +++ b/src/modules/stream/buildings_data.h @@ -22,13 +22,24 @@ public: String line_name; }; /* Scene objects data */ - struct scene_data { - Ref packed_scene; - String path; - Ref loader; - std::vector buildings; - }; - HashMap scenes; + //private: + // HashMap scenes; + +public: + void get_scene_keys_list(List *keys) const; + bool has_scene(const String &key) const; + void remove_scene_item(const String &key, int item); + void add_scene_item(const String &key, int item); + void create_scene_data(const String &key, int item); + Ref scene_get_packed_scene(const String &key) const; + int scene_get_item_count(const String &key) const; + int scene_get_item(const String &key, int index) const; + +private: + Error scene_loader_poll(const String &key); + +public: + void scene_update(); /* Path for each building type */ HashMap building_data; HashMap > building_doors; diff --git a/src/modules/stream/stream.cpp b/src/modules/stream/stream.cpp index dab59c3..380eda4 100644 --- a/src/modules/stream/stream.cpp +++ b/src/modules/stream/stream.cpp @@ -169,39 +169,17 @@ void StreamWorld::request_item(int type, int item) String id = data()->get_building(item).id; if (id == "empty") return; - String path = data()->building_data[id]; switch (type) { case 0: - if (!data()->scenes.has(id)) { - print_line("Requesting " + itos(item) + " " + path); - struct BuildingsData::scene_data sd; - sd.path = path; - sd.loader = ResourceLoader::load_interactive( - path, "PackedScene", true); - if (std::find(sd.buildings.begin(), sd.buildings.end(), - item) == sd.buildings.end()) - sd.buildings.push_back(item); - data()->scenes[id] = sd; - } else { - struct BuildingsData::scene_data &sd = - data()->scenes[id]; - if (std::find(sd.buildings.begin(), sd.buildings.end(), - item) == sd.buildings.end()) - sd.buildings.push_back(item); - } + if (!data()->has_scene(id)) + data()->create_scene_data(id, item); + else + data()->add_scene_item(id, item); break; case 1: - print_line("Removing " + itos(item) + " " + path); - if (data()->scenes.has(id)) { - std::vector::iterator b = - data()->scenes[id].buildings.begin(); - std::vector::iterator e = - data()->scenes[id].buildings.end(); - // if (item_nodes.has(item)) - // item_nodes[item]->queue_delete(); - data()->scenes[id].buildings.erase( - std::remove(b, e, item), - data()->scenes[id].buildings.end()); + print_line("Removing " + itos(item)); + if (data()->has_scene(id)) { + data()->remove_scene_item(id, item); if (item_nodes.has(item)) { item_nodes[item]->queue_delete(); item_nodes.erase(item); @@ -214,27 +192,29 @@ void StreamWorld::request_item(int type, int item) void StreamWorld::update_items() { int i; - const String *key = data()->scenes.next(nullptr); - while (key) { - if (!data()->scenes[*key].packed_scene.is_valid()) { - key = data()->scenes.next(key); + List keys; + data()->get_scene_keys_list(&keys); + List::Element *e = keys.front(); + while (e) { + const String &key = e->get(); + if (!data()->scene_get_packed_scene(key).is_valid()) { + e = e->next(); continue; } - for (i = 0; i < (int)data()->scenes[*key].buildings.size(); - i++) { - if (item_nodes.has(data()->scenes[*key].buildings[i])) + for (i = 0; i < (int)data()->scene_get_item_count(key); i++) { + if (item_nodes.has(data()->scene_get_item(key, i))) continue; Node *psc = - data()->scenes[*key].packed_scene->instance(); + data()->scene_get_packed_scene(key)->instance(); Spatial *psp = Object::cast_to(psc); - item_nodes[data()->scenes[*key].buildings[i]] = psc; + item_nodes[data()->scene_get_item(key, i)] = psc; current_scene->add_child(psp); psp->set_global_transform( data()->get_building( - data()->scenes[*key].buildings[i]) + data()->scene_get_item(key, i)) .xform); } - key = data()->scenes.next(key); + e = e->next(); } } @@ -422,26 +402,7 @@ void StreamWorld::_notification(int which) if (Engine::get_singleton()->is_editor_hint()) break; update_view(); - const String *key = data()->scenes.next(nullptr); - while (key) { - if (data()->scenes[*key].packed_scene.is_valid()) { - key = data()->scenes.next(key); - continue; - } - Error result = data()->scenes[*key].loader->poll(); - if (result == ERR_FILE_EOF) { - Ref sc = - data()->scenes[*key] - .loader->get_resource(); - data()->scenes[*key].packed_scene = sc; - print_line("Loaded scene: " + - data()->scenes[*key].path + " OK"); - } else if (result != OK) - print_error("Could not load the resource :( " + - data()->scenes[*key].path + " " + - itos(result)); - key = data()->scenes.next(key); - } + data()->scene_update(); update_items(); } break;