Started using ECS

This commit is contained in:
2024-09-28 05:23:24 +03:00
parent dfb24aa4b2
commit e19dbd7a4f
3 changed files with 184 additions and 68 deletions

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <core/os/memory.h>
#include <core/io/json.h>
#include <core/os/time.h>
@@ -7,12 +8,23 @@
#include <scene/3d/spatial.h>
#include <scene/3d/mesh_instance.h>
#include "from_string.h"
#include <flecs/flecs.h>
#include "flecs/flecs.h"
#include "buildings_data.h"
BuildingsData *BuildingsData::singleton;
static ConfigFile config;
static flecs::world ecs;
struct scene_data {
Ref<PackedScene> packed_scene;
String path;
Ref<ResourceInteractiveLoader> loader;
std::vector<int> 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<String> *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<CSceneData>();
assert(d);
std::vector<int>::iterator b = d->sd.buildings.begin();
std::vector<int>::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<CSceneData>();
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<CSceneData>({ sd });
assert(e.get_mut<CSceneData>());
}
}
Ref<PackedScene> BuildingsData::scene_get_packed_scene(const String &key) const
{
flecs::entity e = ecs.lookup(key.ascii().ptr());
if (!e.is_valid())
return Ref<PackedScene>();
if (!e.get<CSceneData>())
return Ref<PackedScene>();
assert(e.is_valid());
const CSceneData *d = e.get<CSceneData>();
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<CSceneData>())
return 0;
assert(e.is_valid());
const CSceneData *d = e.get<CSceneData>();
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<CSceneData>())
return -1;
assert(e.is_valid());
const CSceneData *d = e.get<CSceneData>();
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<CSceneData>();
assert(d);
Error err = d->sd.loader->poll();
if (err == ERR_FILE_EOF) {
Ref<PackedScene> 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<String> keys;
get_scene_keys_list(&keys);
List<String>::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();

View File

@@ -22,13 +22,24 @@ public:
String line_name;
};
/* Scene objects data */
struct scene_data {
Ref<PackedScene> packed_scene;
String path;
Ref<ResourceInteractiveLoader> loader;
std::vector<int> buildings;
};
HashMap<String, struct scene_data> scenes;
//private:
// HashMap<String, struct scene_data> scenes;
public:
void get_scene_keys_list(List<String> *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<PackedScene> 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<String, String> building_data;
HashMap<String, Vector<Transform> > building_doors;

View File

@@ -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<int>::iterator b =
data()->scenes[id].buildings.begin();
std::vector<int>::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<String> keys;
data()->get_scene_keys_list(&keys);
List<String>::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<Spatial>(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<PackedScene> 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;