Made accessor for lines

This commit is contained in:
2024-10-02 20:49:41 +03:00
parent 521ae37202
commit 794857209d
10 changed files with 417 additions and 308 deletions

View File

@@ -67,7 +67,8 @@
"cinttypes": "cpp", "cinttypes": "cpp",
"typeinfo": "cpp", "typeinfo": "cpp",
"variant": "cpp", "variant": "cpp",
"format": "cpp" "format": "cpp",
"future": "cpp"
}, },
"cmake.ignoreCMakeListsMissing": true "cmake.ignoreCMakeListsMissing": true
} }

View File

@@ -0,0 +1,32 @@
#include <core/os/memory.h>
#include "base_data.h"
static BaseData *base_data = nullptr;
BaseData::BaseData()
{
}
flecs::world &BaseData::get()
{
return ecs;
}
BaseData::~BaseData()
{
}
BaseData *BaseData::get_singleton()
{
if (!base_data)
base_data = memnew(BaseData);
return base_data;
}
void BaseData::cleanup()
{
if (base_data) {
memdelete(base_data);
base_data = nullptr;
}
}

View File

@@ -0,0 +1,13 @@
#include "flecs/flecs.h"
class BaseData {
flecs::world ecs;
protected:
BaseData();
public:
flecs::world &get();
virtual ~BaseData();
static BaseData *get_singleton();
void cleanup();
};

View File

@@ -10,24 +10,42 @@
#include <scene/3d/spatial.h> #include <scene/3d/spatial.h>
#include <scene/3d/mesh_instance.h> #include <scene/3d/mesh_instance.h>
#include "from_string.h" #include "from_string.h"
#include "flecs/flecs.h" #include "base_data.h"
#include "buildings_data.h" #include "buildings_data.h"
BuildingsData *BuildingsData::singleton; BuildingsData *BuildingsData::singleton;
static ConfigFile config; static ConfigFile config;
static flecs::world ecs;
struct scene_data { struct scene_data {
Ref<PackedScene> packed_scene; Ref<PackedScene> packed_scene;
String path; String path;
Ref<ResourceInteractiveLoader> loader; Ref<ResourceInteractiveLoader> loader;
}; };
static flecs::world &ecs()
{
return BaseData::get_singleton()->get();
}
static flecs::entity lookup(const String &key)
{
return ecs().lookup(key.ascii().ptr());
}
static flecs::entity lookup(const char *key)
{
return ecs().lookup(key);
}
struct CBuildingInstance { struct CBuildingInstance {
String key; String key;
Node *node; Node *node;
}; };
struct CBuildingData {
struct BuildingsData::building building;
};
struct CSceneData { struct CSceneData {
struct scene_data sd; struct scene_data sd;
}; };
@@ -38,6 +56,15 @@ BuildingsData::BuildingsData()
load_data(); load_data();
fill_door_locations(); fill_door_locations();
build_building_aabbs(); build_building_aabbs();
ecs().observer<CBuildingInstance>()
.event(flecs::OnRemove)
.each([](flecs::entity e, CBuildingInstance &bi) {
if (bi.node) {
bi.node->queue_delete();
bi.node = nullptr;
print_line("instance destroyed for " + bi.key);
}
});
} }
BuildingsData::~BuildingsData() BuildingsData::~BuildingsData()
@@ -99,28 +126,27 @@ void BuildingsData::update_building_transform(const String &key,
bool BuildingsData::has_building(const String &key) bool BuildingsData::has_building(const String &key)
{ {
int index = get_building_by_key(key); String ename = "base:" + key;
if (index >= 0) flecs::entity e = lookup(ename.ascii().ptr());
return true; return e.is_valid();
return false;
} }
String BuildingsData::get_closest_building(const Transform &xform) String BuildingsData::get_closest_building(const Transform &xform)
{ {
int i;
float dst = Math_INF; float dst = Math_INF;
String rkey; String rkey;
int id = -1; // int id = -1;
for (i = 0; i < (int)buildings_.size(); i++) { ecs().each(
Vector3 o = xform.origin; [xform, &rkey, &dst](flecs::entity e, const CBuildingData &d) {
Vector3 m = buildings_[i].xform.origin; Vector3 o = xform.origin;
float mdst = o.distance_squared_to(m); Vector3 m = d.building.xform.origin;
if (dst > mdst) { float mdst = o.distance_squared_to(m);
dst = mdst; if (dst > mdst) {
id = i; dst = mdst;
} rkey = d.building.key;
} }
return buildings_[id].key; });
return rkey;
} }
void BuildingsData::cleanup() void BuildingsData::cleanup()
@@ -132,19 +158,6 @@ void BuildingsData::cleanup()
} }
} }
int BuildingsData::get_building_by_key(const String &key) const
{
int i, index = -1;
uint64_t key_hash = key.hash64();
for (i = 0; i < (int)buildings_.size(); i++) {
if (key_hash == buildings_[i].key_hash) {
index = i;
break;
}
}
return index;
}
void BuildingsData::read_buildings_json(const String &buildings_path) void BuildingsData::read_buildings_json(const String &buildings_path)
{ {
String buildings_json = FileAccess::get_file_as_string(buildings_path); String buildings_json = FileAccess::get_file_as_string(buildings_path);
@@ -172,30 +185,17 @@ void BuildingsData::read_buildings_json(const String &buildings_path)
entry["xform"] = key; entry["xform"] = key;
if (!entry.has("key")) // legacy if (!entry.has("key")) // legacy
entry["key"] = key; entry["key"] = key;
building::from_dict(&b, json[key]); create_building(entry);
buildings_.push_back(b); // building::from_dict(&b, json[key]);
// buildings_.push_back(b);
e = e->next(); e = e->next();
} }
#if 0
e = keys.front();
while (e) {
String key = e->get();
/* Transform */
print_line("key: " + key);
String id = json[key].get("id");
print_line("id: " + id);
String aabb = json[key].get("aabb");
print_line("aabb: " + aabb);
e = e->next();
}
#endif
filter_generated_stuff(); filter_generated_stuff();
print_line("entries count: " + itos(buildings_.size())); print_line("entries count: " + itos(get_building_count()));
} }
void BuildingsData::save_buildings_json(const String &buildings_path) void BuildingsData::save_buildings_json(const String &buildings_path)
{ {
int i;
String buildings_json = FileAccess::get_file_as_string(buildings_path); String buildings_json = FileAccess::get_file_as_string(buildings_path);
String backup_path = buildings_path + ".bak"; String backup_path = buildings_path + ".bak";
String store_path = buildings_path; String store_path = buildings_path;
@@ -204,17 +204,19 @@ void BuildingsData::save_buildings_json(const String &buildings_path)
fa->store_string(buildings_json); fa->store_string(buildings_json);
fa->close(); fa->close();
Dictionary json; Dictionary json;
for (i = 0; i < (int)buildings_.size(); i++) { int index = 0;
String key = buildings_[i].key; ecs().each([&index, &json](const CBuildingData &b) {
Dictionary dict = buildings_[i].to_dict(); String key = b.building.key;
dict["index"] = i; Dictionary dict = b.building.to_dict();
dict["index"] = index;
json[key] = dict; json[key] = dict;
} index++;
});
String json_string = JSON::print(json, "\t", false); String json_string = JSON::print(json, "\t", false);
fa = FileAccess::open(store_path, FileAccess::WRITE); fa = FileAccess::open(store_path, FileAccess::WRITE);
fa->store_string(json_string); fa->store_string(json_string);
fa->close(); fa->close();
print_line("entries count: " + itos(buildings_.size())); print_line("entries count: " + itos(get_building_count()));
} }
void BuildingsData::building::from_dict(building *b, const Dictionary &dict) void BuildingsData::building::from_dict(building *b, const Dictionary &dict)
@@ -294,16 +296,16 @@ void BuildingsData::filter_generated_stuff()
Error result = config.load("res://config/stream.conf"); Error result = config.load("res://config/stream.conf");
ERR_FAIL_COND_MSG(result != OK, "Failed to load config"); ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
Array gen_prefixes = config.get_value("lines", "gen_prefixes"); Array gen_prefixes = config.get_value("lines", "gen_prefixes");
int i, j; ecs().each([gen_prefixes](CBuildingData &b) {
for (i = 0; i < (int)buildings_.size(); i++) { int j;
for (j = 0; j < (int)gen_prefixes.size(); j++) { for (j = 0; j < (int)gen_prefixes.size(); j++) {
String prefix = gen_prefixes[j]; String prefix = gen_prefixes[j];
if (buildings_[i].id.begins_with(prefix)) { if (b.building.id.begins_with(prefix)) {
buildings_[i].generated = true; b.building.generated = true;
break; break;
} }
} }
} });
} }
void BuildingsData::load_data() void BuildingsData::load_data()
@@ -334,16 +336,27 @@ void BuildingsData::checkpoint()
{ {
struct checkpoint_data cp; struct checkpoint_data cp;
cp.building_data = building_data; cp.building_data = building_data;
cp.buildings = buildings_; cp.buildings.clear();
ecs().each([&cp](flecs::entity e, const CBuildingData &b) {
cp.buildings.push_back(b.building);
});
undo_log.push_back(cp); undo_log.push_back(cp);
while ((int)undo_log.size() > undo_log_size) while ((int)undo_log.size() > undo_log_size)
undo_log.erase(undo_log.begin()); undo_log.erase(undo_log.begin());
} }
void BuildingsData::undo() void BuildingsData::undo()
{ {
int i;
struct checkpoint_data cp = *undo_log.end(); struct checkpoint_data cp = *undo_log.end();
building_data = cp.building_data; building_data = cp.building_data;
buildings_ = cp.buildings; ecs().each([&cp](flecs::entity e, const CBuildingData &b) {
e.destruct();
});
for (i = 0; i < (int)cp.buildings.size(); i++) {
String ename = "base:" + cp.buildings[i].key;
flecs::entity e = ecs().entity(ename.ascii().ptr());
e.set<CBuildingData>({ cp.buildings[i] });
}
} }
void BuildingsData::fill_door_locations() void BuildingsData::fill_door_locations()
@@ -424,43 +437,38 @@ func fill_door_locations():
void BuildingsData::get_scene_keys_list(List<String> *keys) const void BuildingsData::get_scene_keys_list(List<String> *keys) const
{ {
ecs.each([keys](flecs::entity e, const CSceneData &d) { ecs().each([keys](flecs::entity e, const CSceneData &d) {
keys->push_back(String(e.name())); keys->push_back(String(e.name()));
}); });
} }
bool BuildingsData::has_scene(const String &key) const bool BuildingsData::has_scene(const String &key) const
{ {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
return e.is_valid(); return e.is_valid();
} }
void BuildingsData::remove_scene_item(const String &key, const String &bkey) void BuildingsData::remove_scene_item(const String &key, const String &bkey)
{ {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
flecs::query_builder<const CBuildingInstance> qb = flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>().with( ecs().query_builder<const CBuildingInstance>().with(
flecs::ChildOf, e); flecs::ChildOf, e);
flecs::query<const CBuildingInstance> q = qb.build(); flecs::query<const CBuildingInstance> q = qb.build();
uint64_t key_hash = bkey.hash64(); uint64_t key_hash = bkey.hash64();
flecs::entity em = q.find([key_hash](const CBuildingInstance &bi) { flecs::entity em = q.find([key_hash](const CBuildingInstance &bi) {
return bi.key.hash64() == key_hash; return bi.key.hash64() == key_hash;
}); });
if (em.is_valid()) { if (em.is_valid())
CBuildingInstance *bi = em.get_mut<CBuildingInstance>();
if (bi->node)
bi->node->queue_delete();
bi->node = nullptr;
em.destruct(); em.destruct();
}
} }
void BuildingsData::add_scene_item(const String &key, const String &bkey) void BuildingsData::add_scene_item(const String &key, const String &bkey)
{ {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
@@ -468,7 +476,7 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey)
flecs::entity ce = e.lookup(ename.ascii().ptr()); flecs::entity ce = e.lookup(ename.ascii().ptr());
if (ce.is_valid()) if (ce.is_valid())
ce.destruct(); ce.destruct();
ce = ecs.entity(ename.ascii().ptr()); ce = ecs().entity(ename.ascii().ptr());
ce.child_of(e); ce.child_of(e);
ce.set<CBuildingInstance>({ bkey, nullptr }); ce.set<CBuildingInstance>({ bkey, nullptr });
print_line("child name: " + String(ce.name())); print_line("child name: " + String(ce.name()));
@@ -477,7 +485,7 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey)
void BuildingsData::create_scene_data(const String &key, const String &bkey) void BuildingsData::create_scene_data(const String &key, const String &bkey)
{ {
if (!has_scene(key)) { if (!has_scene(key)) {
flecs::entity e = ecs.entity(key.ascii().ptr()); flecs::entity e = ecs().entity(key.ascii().ptr());
String path = building_data[key]; String path = building_data[key];
print_line("Requesting " + (bkey) + " " + path); print_line("Requesting " + (bkey) + " " + path);
struct scene_data sd; struct scene_data sd;
@@ -490,7 +498,7 @@ void BuildingsData::create_scene_data(const String &key, const String &bkey)
flecs::entity ce = e.lookup(ename.ascii().ptr()); flecs::entity ce = e.lookup(ename.ascii().ptr());
if (ce.is_valid()) if (ce.is_valid())
ce.destruct(); ce.destruct();
ce = ecs.entity(ename.ascii().ptr()); ce = ecs().entity(ename.ascii().ptr());
ce.child_of(e); ce.child_of(e);
ce.set<CBuildingInstance>({ bkey, nullptr }); ce.set<CBuildingInstance>({ bkey, nullptr });
print_line("child name: " + String(ce.name())); print_line("child name: " + String(ce.name()));
@@ -499,7 +507,7 @@ void BuildingsData::create_scene_data(const String &key, const String &bkey)
Ref<PackedScene> BuildingsData::scene_get_packed_scene(const String &key) const Ref<PackedScene> BuildingsData::scene_get_packed_scene(const String &key) const
{ {
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 Ref<PackedScene>(); return Ref<PackedScene>();
if (!e.get<CSceneData>()) if (!e.get<CSceneData>())
@@ -512,7 +520,7 @@ Ref<PackedScene> BuildingsData::scene_get_packed_scene(const String &key) const
int BuildingsData::scene_get_item_count(const String &key) const int BuildingsData::scene_get_item_count(const String &key) const
{ {
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 0; return 0;
if (!e.get<CSceneData>()) if (!e.get<CSceneData>())
@@ -522,7 +530,7 @@ int BuildingsData::scene_get_item_count(const String &key) const
assert(d); assert(d);
// return d->sd.buildings.size(); // return d->sd.buildings.size();
flecs::query_builder<const CBuildingInstance> qb = flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>().with( ecs().query_builder<const CBuildingInstance>().with(
flecs::ChildOf, e); flecs::ChildOf, e);
flecs::query<const CBuildingInstance> q = qb.build(); flecs::query<const CBuildingInstance> q = qb.build();
int result; int result;
@@ -538,7 +546,7 @@ int BuildingsData::scene_get_item_count(const String &key) const
List<String> BuildingsData::scene_get_items(const String &key) const List<String> BuildingsData::scene_get_items(const String &key) const
{ {
List<String> ret; List<String> ret;
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 List<String>(); return List<String>();
if (!e.get<CSceneData>()) if (!e.get<CSceneData>())
@@ -547,7 +555,7 @@ List<String> BuildingsData::scene_get_items(const String &key) const
const CSceneData *d = e.get<CSceneData>(); const CSceneData *d = e.get<CSceneData>();
assert(d); assert(d);
flecs::query_builder<const CBuildingInstance> qb = flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>().with( ecs().query_builder<const CBuildingInstance>().with(
flecs::ChildOf, e); flecs::ChildOf, e);
flecs::query<const CBuildingInstance> q = qb.build(); flecs::query<const CBuildingInstance> q = qb.build();
q.each([&ret](flecs::entity me, const CBuildingInstance &ib) { q.each([&ret](flecs::entity me, const CBuildingInstance &ib) {
@@ -558,7 +566,7 @@ List<String> BuildingsData::scene_get_items(const String &key) const
void BuildingsData::set_scene_item_node(const String &key, const String &bkey, void BuildingsData::set_scene_item_node(const String &key, const String &bkey,
Node *node) Node *node)
{ {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
@@ -572,7 +580,7 @@ void BuildingsData::set_scene_item_node(const String &key, const String &bkey,
} }
bool BuildingsData::has_scene_item(const String &key, const String &bkey) const bool BuildingsData::has_scene_item(const String &key, const String &bkey) const
{ {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
@@ -583,7 +591,7 @@ bool BuildingsData::has_scene_item(const String &key, const String &bkey) const
Node *BuildingsData::get_scene_item_node(const String &key, Node *BuildingsData::get_scene_item_node(const String &key,
const String &bkey) const const String &bkey) const
{ {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
@@ -595,52 +603,11 @@ Node *BuildingsData::get_scene_item_node(const String &key,
assert(bi->key == bkey); assert(bi->key == bkey);
return bi->node; return bi->node;
} }
void BuildingsData::item_nodes_delete_node(const String &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();
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;
}
void BuildingsData::item_nodes_item_removed(const String &key)
{
/* FIXME: pretty sure this is redundant */
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](const CBuildingInstance &bi) {
return bi.key.hash64() == key_hash;
});
if (!e.is_valid())
return;
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
{
return buildings_[item].key;
}
Node *BuildingsData::item_nodes_get_node(const String &key) const Node *BuildingsData::item_nodes_get_node(const String &key) const
{ {
flecs::query_builder<const CBuildingInstance> qb = flecs::query_builder<const CBuildingInstance> qb =
ecs.query_builder<const CBuildingInstance>(); ecs().query_builder<const CBuildingInstance>();
flecs::query<const CBuildingInstance> q = qb.build(); flecs::query<const CBuildingInstance> q = qb.build();
uint64_t key_hash = key.hash64(); uint64_t key_hash = key.hash64();
flecs::entity e = q.find([key_hash](const CBuildingInstance &bi) { flecs::entity e = q.find([key_hash](const CBuildingInstance &bi) {
@@ -655,7 +622,7 @@ Node *BuildingsData::item_nodes_get_node(const String &key) const
Error BuildingsData::scene_loader_poll(const String &key) Error BuildingsData::scene_loader_poll(const String &key)
{ {
if (has_scene(key)) { if (has_scene(key)) {
flecs::entity e = ecs.lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
assert(e.is_valid()); assert(e.is_valid());
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
@@ -692,23 +659,35 @@ void BuildingsData::scene_update()
int BuildingsData::get_building_count() const int BuildingsData::get_building_count() const
{ {
return buildings_.size(); flecs::query<const CBuildingData> q =
ecs().query<const CBuildingData>();
int result;
q.run([&result](flecs::iter &it) {
it.next();
result = it.count();
it.fini();
});
return result;
} }
const struct BuildingsData::building & const struct BuildingsData::building &
BuildingsData::get_building(const String &building_key) const BuildingsData::get_building(const String &building_key) const
{ {
int index = get_building_by_key(building_key); String ename = "base:" + building_key;
assert(index >= 0 && index < get_building_count()); print_line("get_building: " + ename);
return buildings_[index]; flecs::entity e = lookup(ename);
assert(e.is_valid());
return e.get<CBuildingData>()->building;
} }
struct BuildingsData::building & struct BuildingsData::building &
BuildingsData::get_building(const String &building_key) BuildingsData::get_building(const String &building_key)
{ {
int index = get_building_by_key(building_key); String ename = "base:" + building_key;
assert(index >= 0 && index < get_building_count()); print_line("get_building: " + ename);
return buildings_[index]; flecs::entity e = lookup(ename);
assert(e.is_valid());
return e.get_mut<CBuildingData>()->building;
} }
String BuildingsData::create_building(const Dictionary &dict) String BuildingsData::create_building(const Dictionary &dict)
@@ -721,39 +700,37 @@ String BuildingsData::create_building(const Dictionary &dict)
String BuildingsData::create_building(const struct building &building) String BuildingsData::create_building(const struct building &building)
{ {
assert(building.key.length() > 0); assert(building.key.length() > 0);
buildings_.push_back(building); String ename = "base:" + building.key;
print_line("create_building: " + ename);
flecs::entity e = ecs().lookup(ename.ascii().ptr());
assert(!e.is_valid());
e = ecs().entity(ename.ascii().ptr());
e.set<CBuildingData>({ building });
assert(e.is_valid());
print_line("create_building: " + ename + " created");
return building.key; return building.key;
} }
void BuildingsData::for_each_building(callme &c) void BuildingsData::for_each_building(struct callme &c)
{ {
List<String> keys; ecs().each([&c](const CBuildingData &b) { c(b.building.key); });
get_building_keys_list(&keys);
List<String>::Element *e = keys.front();
while (e) {
c(e->get());
e = e->next();
}
} }
void BuildingsData::for_each_building(void (*func)(const String &key, void BuildingsData::for_each_building(void (*func)(const String &key,
void *data), void *data),
void *data) void *data)
{ {
List<String> keys; ecs().each([func, data](const CBuildingData &b) {
get_building_keys_list(&keys); func(b.building.key, data);
List<String>::Element *e = keys.front(); });
while (e) {
func(e->get(), data);
e = e->next();
}
} }
void BuildingsData::get_building_keys_list(List<String> *keys) void BuildingsData::get_building_keys_list(List<String> *keys)
{ {
int i; ecs().each([keys](const CBuildingData &e) {
for (i = 0; i < get_building_count(); i++) keys->push_back(e.building.key);
keys->push_back(buildings_[i].key); });
} }
String BuildingsData::create_building(const building *building) String BuildingsData::create_building(const building *building)
@@ -764,8 +741,12 @@ String BuildingsData::create_building(const building *building)
bool BuildingsData::destroy_building(const String &key) bool BuildingsData::destroy_building(const String &key)
{ {
int index = get_building_by_key(key); assert(key.length() > 0);
assert(index >= 0 && index < get_building_count()); String ename = "base:" + key;
buildings_.erase(buildings_.begin() + index); print_line("destroy_building: " + ename);
flecs::entity e = ecs().lookup(ename.ascii().ptr());
assert(e.is_valid());
e.destruct();
print_line("destroy_building: " + ename + " destroyed");
return true; return true;
} }

View File

@@ -41,14 +41,9 @@ public:
Node *get_scene_item_node(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);
// bool item_nodes_exists(const String &key) const;
// void item_nodes_set_node(const String &key, Node *node);
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;
private: private:
String item_nodes_get_key(int item) const;
Error scene_loader_poll(const String &key); Error scene_loader_poll(const String &key);
public: public:
@@ -57,9 +52,6 @@ public:
HashMap<String, String> building_data; HashMap<String, String> building_data;
HashMap<String, Vector<Transform> > building_doors; HashMap<String, Vector<Transform> > building_doors;
HashMap<String, AABB> building_aabbs; HashMap<String, AABB> building_aabbs;
/* Data for each building in a world */
private:
std::vector<struct building> buildings_;
public: public:
struct building &get_building(const String &building_key); struct building &get_building(const String &building_key);
@@ -138,8 +130,5 @@ public:
String get_closest_building(const Transform &xform); String get_closest_building(const Transform &xform);
static BuildingsData *get_singleton(); static BuildingsData *get_singleton();
static void cleanup(); static void cleanup();
private:
int get_building_by_key(const String &key) const;
}; };
#endif #endif

View File

@@ -15,6 +15,54 @@
#include "editor_event.h" #include "editor_event.h"
#include "road_lines_data.h" #include "road_lines_data.h"
class LinesAccessor {
HashMap<String, struct RoadLinesData::road_line> lines_;
public:
inline const struct RoadLinesData::road_line &
get_line(const String &key) const
{
return lines_[key];
}
inline const struct RoadLinesData::road_line *
get_line_ptr(const String &key) const
{
return &lines_[key];
}
inline struct RoadLinesData::road_line &get_line(const String &key)
{
return lines_[key];
}
inline const struct RoadLinesData::road_line &
operator[](const String &key) const
{
return lines_[key];
}
inline struct RoadLinesData::road_line &operator[](const String &key)
{
return lines_[key];
}
inline bool has(const String &key)
{
return lines_.has(key);
}
void get_key_list(List<String> *keys)
{
lines_.get_key_list(keys);
}
const String &get_next(const String &key)
{
const String *r = lines_.next(&key);
return *r;
}
void erase(const String &key)
{
lines_.erase(key);
}
};
static LinesAccessor lines;
ImmediateGeometry *RoadLinesData::debug_im = nullptr; ImmediateGeometry *RoadLinesData::debug_im = nullptr;
static Ref<Material> debug_material; static Ref<Material> debug_material;
RoadLinesData::RoadLinesData() RoadLinesData::RoadLinesData()
@@ -22,6 +70,27 @@ RoadLinesData::RoadLinesData()
load_data(); load_data();
} }
RoadLinesData *RoadLinesData::singleton = nullptr; RoadLinesData *RoadLinesData::singleton = nullptr;
const struct RoadLinesData::road_line &
RoadLinesData::get_line(const String &key) const
{
return ::lines[key];
}
struct RoadLinesData::road_line &RoadLinesData::get_line(const String &key)
{
return ::lines[key];
}
const RoadLinesData::road_line &RoadLinesData::lines(const String &key) const
{
return ::lines[key];
}
RoadLinesData::road_line &RoadLinesData::lines(const String &key)
{
return ::lines[key];
}
bool RoadLinesData::has_line(const String &key)
{
return ::lines.has(key);
}
RoadLinesData *RoadLinesData::get_singleton() RoadLinesData *RoadLinesData::get_singleton()
{ {
if (!singleton) if (!singleton)
@@ -49,7 +118,7 @@ String RoadLinesData::get_road_lines_path()
void RoadLinesData::get_road_lines_key_list(List<String> *keys) void RoadLinesData::get_road_lines_key_list(List<String> *keys)
{ {
List<String> line_keys; List<String> line_keys;
lines.get_key_list(&line_keys); ::lines.get_key_list(&line_keys);
List<String>::Element *e = line_keys.front(); List<String>::Element *e = line_keys.front();
keys->clear(); keys->clear();
while (e) { while (e) {
@@ -59,6 +128,18 @@ void RoadLinesData::get_road_lines_key_list(List<String> *keys)
e = e->next(); e = e->next();
} }
} }
void RoadLinesData::get_lines_key_list(List<String> *keys)
{
::lines.get_key_list(keys);
}
const String &RoadLinesData::get_next_line(const String &key)
{
return ::lines.get_next(key);
}
void RoadLinesData::erase_line(const String &key)
{
return ::lines.erase(key);
}
void RoadLinesData::load_data() void RoadLinesData::load_data()
{ {
int i; int i;
@@ -109,7 +190,7 @@ void RoadLinesData::load_data()
} }
// TODO: wtf is flags? // TODO: wtf is flags?
rline.lanes = lanes; rline.lanes = lanes;
lines[key] = rline; lines(key) = rline;
e = e->next(); e = e->next();
} }
} }
@@ -124,26 +205,26 @@ void RoadLinesData::save_data()
FileAccess::get_file_as_string(road_lines_path); FileAccess::get_file_as_string(road_lines_path);
Dictionary output; Dictionary output;
List<String> keys; List<String> keys;
lines.get_key_list(&keys); ::lines.get_key_list(&keys);
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
while (e) { while (e) {
Dictionary pvalues; Dictionary pvalues;
Array points, indices; Array points, indices;
points.resize(lines[e->get()].points.size()); points.resize(lines(e->get()).points.size());
for (i = 0; i < (int)lines[e->get()].points.size(); i++) for (i = 0; i < (int)lines(e->get()).points.size(); i++)
points[i] = to_string(lines[e->get()].points[i]); points[i] = to_string(lines(e->get()).points[i]);
indices.resize(lines[e->get()].indices.size()); indices.resize(lines(e->get()).indices.size());
for (i = 0; i < (int)lines[e->get()].indices.size(); i++) for (i = 0; i < (int)lines(e->get()).indices.size(); i++)
indices[i] = lines[e->get()].indices[i]; indices[i] = lines(e->get()).indices[i];
pvalues["points"] = points; pvalues["points"] = points;
// pvalues["indices"] = indices; // pvalues["indices"] = indices;
pvalues["metadata"] = lines[e->get()].metadata; pvalues["metadata"] = lines(e->get()).metadata;
pvalues["lanes"] = lines[e->get()].lanes; pvalues["lanes"] = lines(e->get()).lanes;
pvalues["pattern"] = lines[e->get()].pattern; pvalues["pattern"] = ::lines[e->get()].pattern;
Array buildings; Array buildings;
for (i = 0; i < (int)lines[e->get()].buildings.size(); i++) for (i = 0; i < (int)::lines[e->get()].buildings.size(); i++)
buildings.push_back( buildings.push_back(
lines[e->get()].buildings[i].to_dict()); ::lines[e->get()].buildings[i].to_dict());
pvalues["buildings"] = buildings; pvalues["buildings"] = buildings;
output[e->get()] = pvalues; output[e->get()] = pvalues;
e = e->next(); e = e->next();
@@ -224,14 +305,14 @@ void RoadLinesData::index_lines(
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
while (e) { while (e) {
String rkey = e->get(); String rkey = e->get();
struct RoadLinesData::road_line &pt = lines[rkey]; struct RoadLinesData::road_line &pt = ::lines[rkey];
pt.indices.clear(); pt.indices.clear();
e = e->next(); e = e->next();
} }
e = keys.front(); e = keys.front();
while (e) { while (e) {
String rkey = e->get(); String rkey = e->get();
struct RoadLinesData::road_line &pt = lines[rkey]; struct RoadLinesData::road_line &pt = ::lines[rkey];
road_lines_curve_index(pt, road_lines_nodes_hash, road_lines_curve_index(pt, road_lines_nodes_hash,
road_lines_nodes); road_lines_nodes);
e = e->next(); e = e->next();
@@ -240,14 +321,14 @@ void RoadLinesData::index_lines(
static inline int get_segment_index(const String &road, int pos) static inline int get_segment_index(const String &road, int pos)
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
int idx = rld->lines[road].indices[pos]; int idx = rld->get_line(road).indices[pos];
return idx; return idx;
} }
void RoadLinesData::create_segments(const String &road, void RoadLinesData::create_segments(const String &road,
std::vector<int> &segments) std::vector<int> &segments)
{ {
int i; int i;
for (i = 0; i < (int)lines[road].indices.size() - 1; i++) { for (i = 0; i < (int)::lines[road].indices.size() - 1; i++) {
segments.push_back(i); segments.push_back(i);
segments.push_back(i + 1); segments.push_back(i + 1);
} }
@@ -297,8 +378,8 @@ void RoadLinesData::insert_close_points(std::vector<Vector3> &road_lines_nodes,
distance_squared) { distance_squared) {
/* split segment and replace road /* split segment and replace road
point with a point on segment */ point with a point on segment */
lines[rkey].indices.insert( ::lines[rkey].indices.insert(
lines[rkey].indices.begin() + ::lines[rkey].indices.begin() +
idx, idx,
idx3); idx3);
road_lines_nodes[idx3] = closest; road_lines_nodes[idx3] = closest;
@@ -345,22 +426,23 @@ void RoadLinesData::update_road_lines_nodes(
std::tuple<String, String> data = kcmp[it->first]; std::tuple<String, String> data = kcmp[it->first];
const String &k = std::get<0>(data); const String &k = std::get<0>(data);
const String &r = std::get<1>(data); const String &r = std::get<1>(data);
if (lines[k].indices.size() < 2) if (::lines[k].indices.size() < 2)
continue; continue;
if (lines[r].indices.size() < 2) if (::lines[r].indices.size() < 2)
continue; continue;
for (i = 0; i < (int)lines[k].indices.size() - 1; i++) { for (i = 0; i < (int)::lines[k].indices.size() - 1; i++) {
for (j = 0; j < (int)lines[k].indices.size() - 1; j++) { for (j = 0; j < (int)::lines[k].indices.size() - 1;
j++) {
uint32_t key = k.hash() ^ i ^ r.hash() ^ j ^ uint32_t key = k.hash() ^ i ^ r.hash() ^ j ^
2147483137; 2147483137;
uint32_t key2 = r.hash() ^ j ^ k.hash() ^ i ^ uint32_t key2 = r.hash() ^ j ^ k.hash() ^ i ^
2147463167; 2147463167;
if (checks.find(key) == checks.end() && if (checks.find(key) == checks.end() &&
checks.find(key2) == checks.end()) { checks.find(key2) == checks.end()) {
int idx_a1 = lines[k].indices[i]; int idx_a1 = ::lines[k].indices[i];
int idx_a2 = lines[k].indices[i + 1]; int idx_a2 = ::lines[k].indices[i + 1];
int idx_b1 = lines[k].indices[j]; int idx_b1 = ::lines[k].indices[j];
int idx_b2 = lines[k].indices[j + 1]; int idx_b2 = ::lines[k].indices[j + 1];
std::vector<int> cmp1 = { idx_a1, std::vector<int> cmp1 = { idx_a1,
idx_a2 }; idx_a2 };
if (std::find(cmp1.begin(), cmp1.end(), if (std::find(cmp1.begin(), cmp1.end(),
@@ -426,16 +508,16 @@ void RoadLinesData::update_road_lines_nodes(
int nidx = road_lines_nodes.size(); int nidx = road_lines_nodes.size();
road_lines_nodes.push_back(pxt); road_lines_nodes.push_back(pxt);
// int il = (int)road_lines[k].indices.size(); // int il = (int)road_lines[k].indices.size();
assert(std::find(lines[k].indices.begin(), assert(std::find(::lines[k].indices.begin(),
lines[k].indices.end(), ::lines[k].indices.end(),
nidx) == lines[k].indices.end()); nidx) == ::lines[k].indices.end());
assert(std::find(lines[r].indices.begin(), assert(std::find(::lines[r].indices.begin(),
lines[r].indices.end(), ::lines[r].indices.end(),
nidx) == lines[r].indices.end()); nidx) == ::lines[r].indices.end());
lines[k].indices.insert( ::lines[k].indices.insert(
lines[k].indices.begin() + i + 1, nidx); ::lines[k].indices.begin() + i + 1, nidx);
lines[r].indices.insert( ::lines[r].indices.insert(
lines[k].indices.begin() + j + 1, nidx); ::lines[k].indices.begin() + j + 1, nidx);
} }
} }
} }
@@ -447,7 +529,7 @@ void RoadLinesData::dump_road_lines(const std::vector<Vector3> &road_lines_nodes
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
while (e) { while (e) {
String rkey = e->get(); String rkey = e->get();
struct RoadLinesData::road_line &pt = lines[rkey]; struct RoadLinesData::road_line &pt = ::lines[rkey];
String outline = rkey + ": "; String outline = rkey + ": ";
for (i = 0; i < (int)pt.indices.size(); i++) { for (i = 0; i < (int)pt.indices.size(); i++) {
outline += " " + itos(pt.indices[i]); outline += " " + itos(pt.indices[i]);
@@ -501,20 +583,20 @@ int RoadLinesData::get_debug_flags() const
void RoadLinesData::update_line_segments(const String &line) void RoadLinesData::update_line_segments(const String &line)
{ {
int i; int i;
lines[line].segments.clear(); ::lines[line].segments.clear();
lines[line].segments.resize(lines[line].points.size() - 1); ::lines[line].segments.resize(::lines[line].points.size() - 1);
float offset = 0.0f; float offset = 0.0f;
for (i = 0; i < (int)lines[line].points.size() - 1; i++) { for (i = 0; i < (int)::lines[line].points.size() - 1; i++) {
struct line_segment segment; struct line_segment segment;
segment.p1 = lines[line].points[i].origin; segment.p1 = ::lines[line].points[i].origin;
segment.p2 = lines[line].points[i + 1].origin; segment.p2 = ::lines[line].points[i + 1].origin;
segment.length = segment.p1.distance_to(segment.p2); segment.length = segment.p1.distance_to(segment.p2);
segment.dir = (segment.p2 - segment.p1).normalized(); segment.dir = (segment.p2 - segment.p1).normalized();
Vector3 side = segment.dir.cross(Vector3(0, 1, 0)); Vector3 side = segment.dir.cross(Vector3(0, 1, 0));
side.y = 0; side.y = 0;
segment.tangent = side.normalized(); segment.tangent = side.normalized();
segment.offset = offset; segment.offset = offset;
lines[line].segments[i] = segment; ::lines[line].segments[i] = segment;
offset += segment.length; offset += segment.length;
} }
} }
@@ -529,7 +611,7 @@ void RoadLinesData::line_add_building(const String &line, const String &key,
lb.line_offset = curve_offset; lb.line_offset = curve_offset;
lb.normal_offset = normal_offset; lb.normal_offset = normal_offset;
lb.y_rotation = y_rotation; lb.y_rotation = y_rotation;
lines[line].buildings.push_back(lb); ::lines[line].buildings.push_back(lb);
// TODO: save/load // TODO: save/load
BuildingsData::get_singleton()->get_building(key).line_name = line; BuildingsData::get_singleton()->get_building(key).line_name = line;
} }
@@ -538,14 +620,14 @@ void RoadLinesData::assign_close_buildings(const String &line)
{ {
int j; int j;
print_line("assign_close_buildings: " + line); print_line("assign_close_buildings: " + line);
if (!lines.has(line)) if (!::lines.has(line))
return; return;
if (!line.ends_with("_buildings")) if (!line.ends_with("_buildings"))
return; return;
if (lines[line].points.size() < 2) if (::lines[line].points.size() < 2)
return; return;
update_line_segments(line); update_line_segments(line);
if (lines[line].segments.size() == 0) if (::lines[line].segments.size() == 0)
return; return;
print_line("assign_close_buildings: processing: " + print_line("assign_close_buildings: processing: " +
itos(BuildingsData::get_singleton()->get_building_count()) + itos(BuildingsData::get_singleton()->get_building_count()) +
@@ -577,21 +659,22 @@ void RoadLinesData::assign_close_buildings(const String &line)
Vector3 segment_point; Vector3 segment_point;
int segment_index = -1; int segment_index = -1;
for (j = 0; j < (int)lines[line].segments.size(); j++) { for (j = 0; j < (int)::lines[line].segments.size(); j++) {
Vector3 seg[] = { lines[line].segments[j].p1, Vector3 seg[] = { ::lines[line].segments[j].p1,
lines[line].segments[j].p2 }; ::lines[line].segments[j].p2 };
Vector3 closest = Vector3 closest =
Geometry::get_closest_point_to_segment(p, seg); Geometry::get_closest_point_to_segment(p, seg);
Vector3 xp = p; Vector3 xp = p;
xp.y = p.y; xp.y = p.y;
float tmpdst = xp.distance_squared_to(closest); float tmpdst = xp.distance_squared_to(closest);
if (closest.is_equal_approx( if (closest.is_equal_approx(
lines[line].segments[j].p1) || ::lines[line].segments[j].p1) ||
closest.is_equal_approx( closest.is_equal_approx(
lines[line].segments[j].p2)) { ::lines[line].segments[j].p2)) {
float w = closest.dot( float w = closest.dot(
lines[line].segments[j].dir); ::lines[line].segments[j].dir);
float wt = xp.dot(lines[line].segments[j].dir); float wt =
xp.dot(::lines[line].segments[j].dir);
if (wt - w > 0.1f || wt - w < -0.1f) if (wt - w > 0.1f || wt - w < -0.1f)
continue; continue;
} }
@@ -605,9 +688,9 @@ void RoadLinesData::assign_close_buildings(const String &line)
if (segment_index < 0) if (segment_index < 0)
continue; continue;
const Vector3 &p1 = lines[line].segments[segment_index].p1; const Vector3 &p1 = ::lines[line].segments[segment_index].p1;
const Vector3 &p2 = lines[line].segments[segment_index].p2; const Vector3 &p2 = ::lines[line].segments[segment_index].p2;
const Vector3 &dir = lines[line].segments[segment_index].dir; const Vector3 &dir = ::lines[line].segments[segment_index].dir;
assert(segment_index >= 0); assert(segment_index >= 0);
// assert(!segment_point.is_equal_approx(p1)); // assert(!segment_point.is_equal_approx(p1));
// assert(!segment_point.is_equal_approx(p2)); // assert(!segment_point.is_equal_approx(p2));
@@ -616,8 +699,8 @@ void RoadLinesData::assign_close_buildings(const String &line)
print_line("wdst=" + String::num(wdst)); print_line("wdst=" + String::num(wdst));
assert(wdst >= 0); assert(wdst >= 0);
result_offset = result_offset =
lines[line].segments[segment_index].offset + wdst; ::lines[line].segments[segment_index].offset + wdst;
side = (p - p1).dot(lines[line].segments[j].tangent); side = (p - p1).dot(::lines[line].segments[j].tangent);
assert(result_offset >= 0); assert(result_offset >= 0);
@@ -645,8 +728,8 @@ bool RoadLinesData::line_has_building(const String &line,
uint64_t key_hash = building_key.hash64(); uint64_t key_hash = building_key.hash64();
bool ret = false; bool ret = false;
int i; int i;
for (i = 0; i < (int)lines[line].buildings.size(); i++) for (i = 0; i < (int)::lines[line].buildings.size(); i++)
if (lines[line].buildings[i].building_key_hash == key_hash) { if (::lines[line].buildings[i].building_key_hash == key_hash) {
ret = true; ret = true;
break; break;
} }
@@ -659,14 +742,14 @@ Vector3 RoadLinesData::get_point_by_offsets(const String &line,
{ {
Vector3 ret; Vector3 ret;
int i; int i;
assert(lines.has(line)); assert(::lines.has(line));
print_verbose("line: " + line + print_verbose("line: " + line +
" line_offset: " + String::num(dir_offset) + " line_offset: " + String::num(dir_offset) +
" normal_offset: " + String::num(normal_offset)); " normal_offset: " + String::num(normal_offset));
float n_offset = dir_offset; float n_offset = dir_offset;
int selected_segment = 0; int selected_segment = 0;
for (i = 0; i < (int)lines[line].segments.size(); i++) { for (i = 0; i < (int)::lines[line].segments.size(); i++) {
struct line_segment *segment = &lines[line].segments[i]; struct line_segment *segment = &::lines[line].segments[i];
if (n_offset < segment->length) { if (n_offset < segment->length) {
selected_segment = i; selected_segment = i;
break; break;
@@ -674,9 +757,9 @@ Vector3 RoadLinesData::get_point_by_offsets(const String &line,
n_offset -= segment->length; n_offset -= segment->length;
} }
print_verbose("offset: " + String::num(n_offset)); print_verbose("offset: " + String::num(n_offset));
ret = lines[line].segments[selected_segment].p1 + ret = ::lines[line].segments[selected_segment].p1 +
lines[line].segments[selected_segment].dir * n_offset + ::lines[line].segments[selected_segment].dir * n_offset +
lines[line].segments[selected_segment].tangent * normal_offset; ::lines[line].segments[selected_segment].tangent * normal_offset;
print_verbose("data: " + (ret.operator String())); print_verbose("data: " + (ret.operator String()));
return ret; return ret;
} }
@@ -685,46 +768,50 @@ void RoadLinesData::update_buildings_from_lines()
{ {
BuildingsData *bd = BuildingsData::get_singleton(); BuildingsData *bd = BuildingsData::get_singleton();
List<String> keys; List<String> keys;
lines.get_key_list(&keys); ::lines.get_key_list(&keys);
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
while (e) { while (e) {
int i; int i;
const String &line = e->get(); const String &line = e->get();
for (i = 0; i < (int)lines[line].buildings.size(); i++) { for (i = 0; i < (int)::lines[line].buildings.size(); i++) {
const uint64_t &building_key_hash = const uint64_t &building_key_hash =
lines[line].buildings[i].building_key_hash; ::lines[line].buildings[i].building_key_hash;
bool found = bd->has_building( bool found = bd->has_building(
lines[line].buildings[i].building_key); ::lines[line].buildings[i].building_key);
if (found) { if (found) {
struct BuildingsData::building &b = struct BuildingsData::building &b =
bd->get_building(lines[line] bd->get_building(::lines[line]
.buildings[i] .buildings[i]
.building_key); .building_key);
Vector3 pt = get_point_by_offsets( Vector3 pt = get_point_by_offsets(
line, line,
lines[line].buildings[i].line_offset, ::lines[line].buildings[i].line_offset,
lines[line].buildings[i].normal_offset); ::lines[line]
.buildings[i]
.normal_offset);
Basis basis = Basis().rotated( Basis basis = Basis().rotated(
Vector3(0, 1, 0), Vector3(0, 1, 0),
lines[line].buildings[i].y_rotation); ::lines[line].buildings[i].y_rotation);
b.xform.origin = pt; b.xform.origin = pt;
b.xform.basis = basis; b.xform.basis = basis;
Array args; Array args;
args.push_back( args.push_back(
lines[line].buildings[i].building_key); ::lines[line].buildings[i].building_key);
EditorEvent::get_singleton()->event.emit( EditorEvent::get_singleton()->event.emit(
"building_updated", args); "building_updated", args);
} else { } else {
Vector3 pt = get_point_by_offsets( Vector3 pt = get_point_by_offsets(
line, line,
lines[line].buildings[i].line_offset, ::lines[line].buildings[i].line_offset,
lines[line].buildings[i].normal_offset); ::lines[line]
.buildings[i]
.normal_offset);
Basis basis = Basis().rotated( Basis basis = Basis().rotated(
Vector3(0, 1, 0), Vector3(0, 1, 0),
lines[line].buildings[i].y_rotation); ::lines[line].buildings[i].y_rotation);
struct BuildingsData::building nb; struct BuildingsData::building nb;
Dictionary data; Dictionary data;
data["id"] = lines[line].buildings[i].id; data["id"] = ::lines[line].buildings[i].id;
data["xform"] = Transform(basis, pt); data["xform"] = Transform(basis, pt);
BuildingsData::building::from_dict(&nb, data); BuildingsData::building::from_dict(&nb, data);
String bkey = bd->create_building(nb); String bkey = bd->create_building(nb);

View File

@@ -25,6 +25,8 @@ public:
const Dictionary &from); const Dictionary &from);
Dictionary to_dict() const; Dictionary to_dict() const;
}; };
private:
struct line_segment { struct line_segment {
Vector3 p1; Vector3 p1;
Vector3 p2; Vector3 p2;
@@ -33,6 +35,8 @@ public:
Vector3 tangent; Vector3 tangent;
float offset; float offset;
}; };
public:
struct road_line { struct road_line {
std::vector<Transform> points; std::vector<Transform> points;
std::vector<int> indices; std::vector<int> indices;
@@ -44,14 +48,28 @@ public:
Dictionary metadata; Dictionary metadata;
_Signal<void> line_updated; _Signal<void> line_updated;
}; };
public:
static ImmediateGeometry *get_debug_node(); static ImmediateGeometry *get_debug_node();
HashMap<String, struct road_line> lines;
private:
HashMap<String, Ref<Curve3D> > curves; HashMap<String, Ref<Curve3D> > curves;
public:
const struct road_line &get_line(const String &key) const;
struct road_line &get_line(const String &key);
const struct road_line &lines(const String &key) const;
struct road_line &lines(const String &key);
bool has_line(const String &key);
static RoadLinesData *get_singleton(); static RoadLinesData *get_singleton();
virtual ~RoadLinesData(); virtual ~RoadLinesData();
static void cleanup(); static void cleanup();
String get_road_lines_path(); String get_road_lines_path();
void get_road_lines_key_list(List<String> *keys); void get_road_lines_key_list(List<String> *keys);
void get_lines_key_list(List<String> *keys);
const String &get_next_line(const String &key);
void erase_line(const String &key);
void load_data(); void load_data();
void save_data(); void save_data();
void process_lines(std::unordered_map<uint32_t, std::vector<Vector3> > void process_lines(std::unordered_map<uint32_t, std::vector<Vector3> >

View File

@@ -314,11 +314,11 @@ protected:
editor->get_as_node<ItemList>("%line_buildings_list"); editor->get_as_node<ItemList>("%line_buildings_list");
items->clear(); items->clear();
for (i = 0; i < (int)RoadLinesData::get_singleton() for (i = 0; i < (int)RoadLinesData::get_singleton()
->lines[current_line] ->lines(current_line)
.buildings.size(); .buildings.size();
i++) { i++) {
const String &key = RoadLinesData::get_singleton() const String &key = RoadLinesData::get_singleton()
->lines[current_line] ->lines(current_line)
.buildings[i] .buildings[i]
.building_key; .building_key;
items->add_item(key); items->add_item(key);
@@ -615,7 +615,7 @@ Node *RoadLinesEditor::scene()
void RoadLinesEditor::update_line_geometry() void RoadLinesEditor::update_line_geometry()
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
if (!rld->lines.has(current_line)) { if (!rld->has_line(current_line)) {
if (line_im) if (line_im)
line_im->clear(); line_im->clear();
return; return;
@@ -629,16 +629,16 @@ void RoadLinesEditor::update_line_geometry()
line_im->set_color(Color(1.0f, 0.0f, 0.0f, 1.0f)); line_im->set_color(Color(1.0f, 0.0f, 0.0f, 1.0f));
line_im->add_vertex(Vector3(0.0f, 100.0f, 0.0f)); line_im->add_vertex(Vector3(0.0f, 100.0f, 0.0f));
line_im->end(); line_im->end();
if (rld->lines[current_line].points.size() > 1) { if (rld->lines(current_line).points.size() > 1) {
line_im->begin(Mesh::PRIMITIVE_LINES); line_im->begin(Mesh::PRIMITIVE_LINES);
for (i = 0; for (i = 0;
i < i <
(int)rld->lines[current_line].points.size() - 1; (int)rld->lines(current_line).points.size() - 1;
i++) { i++) {
Vector3 pt1 = rld->lines[current_line] Vector3 pt1 = rld->lines(current_line)
.points[i] .points[i]
.origin; .origin;
Vector3 pt2 = rld->lines[current_line] Vector3 pt2 = rld->lines(current_line)
.points[i + 1] .points[i + 1]
.origin; .origin;
line_im->set_color( line_im->set_color(
@@ -659,14 +659,14 @@ void RoadLinesEditor::update_line_geometry()
} }
// FIXME: update line segments on load and when line is changed // FIXME: update line segments on load and when line is changed
rld->update_line_segments(current_line); rld->update_line_segments(current_line);
if (rld->lines[current_line].buildings.size() > 1) { if (rld->lines(current_line).buildings.size() > 1) {
line_im->begin(Mesh::PRIMITIVE_LINES); line_im->begin(Mesh::PRIMITIVE_LINES);
for (i = 0; for (i = 0;
i < (int)rld->lines[current_line].buildings.size(); i < (int)rld->lines(current_line).buildings.size();
i++) { i++) {
print_line("idx: " + itos(i)); print_line("idx: " + itos(i));
const RoadLinesData::line_building_data &b = const RoadLinesData::line_building_data &b =
rld->lines[current_line].buildings[i]; rld->lines(current_line).buildings[i];
Vector3 pt = rld->get_point_by_offsets( Vector3 pt = rld->get_point_by_offsets(
current_line, b.line_offset, current_line, b.line_offset,
b.normal_offset); b.normal_offset);
@@ -686,14 +686,14 @@ void RoadLinesEditor::update_line_index_ui()
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
SpinBox *sp_line_index = get_as_node<SpinBox>("%line_index"); SpinBox *sp_line_index = get_as_node<SpinBox>("%line_index");
sp_line_index->set_max(rld->lines[current_line].points.size() - 1); sp_line_index->set_max(rld->lines(current_line).points.size() - 1);
sp_line_index->set_min(0); sp_line_index->set_min(0);
} }
void RoadLinesEditor::select_line(const String &line_name) void RoadLinesEditor::select_line(const String &line_name)
{ {
print_line("selected line: " + line_name); print_line("selected line: " + line_name);
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
assert(rld->lines.has(line_name)); assert(rld->has_line(line_name));
if (current_line != line_name) { if (current_line != line_name) {
current_line = line_name; current_line = line_name;
update_line_index_ui(); update_line_index_ui();
@@ -713,7 +713,7 @@ void RoadLinesEditor::select_line(const String &line_name)
bool RoadLinesEditor::line_exists(const String &line_name) bool RoadLinesEditor::line_exists(const String &line_name)
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
return rld->lines.has(line_name); return rld->has_line(line_name);
} }
void RoadLinesEditor::line_create_point() void RoadLinesEditor::line_create_point()
@@ -724,8 +724,10 @@ void RoadLinesEditor::line_create_point()
Vector3 position = get_cursor_position(); Vector3 position = get_cursor_position();
Transform xform(Basis(), position); Transform xform(Basis(), position);
int index = get_line_index(); int index = get_line_index();
rld->lines[current_line].points.insert( rld->lines(current_line)
rld->lines[current_line].points.begin() + index + 1, xform); .points.insert(rld->lines(current_line).points.begin() + index +
1,
xform);
Array args; Array args;
args.push_back(current_line); args.push_back(current_line);
EditorEvent::get_singleton()->event.emit("lines_changed_line", args); EditorEvent::get_singleton()->event.emit("lines_changed_line", args);
@@ -742,10 +744,10 @@ void RoadLinesEditor::line_delete_point()
print_line("line_delete_point"); print_line("line_delete_point");
int index = get_line_index(); int index = get_line_index();
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
if (rld->lines[current_line].points.size() < 2) if (rld->lines(current_line).points.size() < 2)
return; return;
rld->lines[current_line].points.erase( rld->lines(current_line)
rld->lines[current_line].points.begin() + index); .points.erase(rld->lines(current_line).points.begin() + index);
Array args; Array args;
args.push_back(current_line); args.push_back(current_line);
EditorEvent::get_singleton()->event.emit("lines_changed_line", args); EditorEvent::get_singleton()->event.emit("lines_changed_line", args);
@@ -766,12 +768,12 @@ void RoadLinesEditor::set_point_to_cursor()
Spatial *cursor = get_as_node<Spatial>(cursor_name); Spatial *cursor = get_as_node<Spatial>(cursor_name);
Transform xform = cursor->get_global_transform(); Transform xform = cursor->get_global_transform();
int index = get_line_index(); int index = get_line_index();
rld->lines[current_line].points[index].origin = xform.origin; rld->lines(current_line).points[index].origin = xform.origin;
Array args; Array args;
args.push_back(current_line); args.push_back(current_line);
EditorEvent::get_singleton()->event.emit("lines_changed_line", args); EditorEvent::get_singleton()->event.emit("lines_changed_line", args);
update_line_geometry(); update_line_geometry();
set_ui_point_position(rld->lines[current_line].points[index].origin); set_ui_point_position(rld->lines(current_line).points[index].origin);
} }
int RoadLinesEditor::get_line_index() int RoadLinesEditor::get_line_index()
@@ -787,7 +789,7 @@ void RoadLinesEditor::move_cursor_to_point()
print_line("move_cursor_to_point"); print_line("move_cursor_to_point");
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
int index = get_line_index(); int index = get_line_index();
Transform xform(Basis(), rld->lines[current_line].points[index].origin); Transform xform(Basis(), rld->lines(current_line).points[index].origin);
set_cursor_position(xform.origin); set_cursor_position(xform.origin);
set_ui_cursor_position(xform.origin); set_ui_cursor_position(xform.origin);
} }
@@ -899,7 +901,7 @@ void RoadLinesEditor::update_ui()
get_as_node<Control>("%road_lines_buildings")->hide(); get_as_node<Control>("%road_lines_buildings")->hide();
ItemList *lines_list = get_as_node<ItemList>("%lines_list"); ItemList *lines_list = get_as_node<ItemList>("%lines_list");
List<String> line_keys; List<String> line_keys;
rld->lines.get_key_list(&line_keys); rld->get_lines_key_list(&line_keys);
List<String>::Element *e = line_keys.front(); List<String>::Element *e = line_keys.front();
lines_list->clear(); lines_list->clear();
if (!re.is_valid()) if (!re.is_valid())
@@ -942,7 +944,7 @@ void RoadLinesEditor::create_new_line_at_cursor(const String &line_name)
rline.pattern = 0; rline.pattern = 0;
Transform cursor_position(Basis(), get_cursor_position()); Transform cursor_position(Basis(), get_cursor_position());
rline.points.push_back(cursor_position); rline.points.push_back(cursor_position);
rld->lines[line_name] = rline; rld->lines(line_name) = rline;
update_line_index_ui(); update_line_index_ui();
update_ui(); update_ui();
} }
@@ -951,9 +953,8 @@ void RoadLinesEditor::delete_current_line()
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
String delete_line = current_line; String delete_line = current_line;
const String *k = rld->lines.next(&delete_line); current_line = rld->get_next_line(delete_line);
current_line = *k; rld->erase_line(delete_line);
rld->lines.erase(delete_line);
update_line_index_ui(); update_line_index_ui();
update_ui(); update_ui();
} }
@@ -976,7 +977,7 @@ void RoadLinesEditor::set_point_position(const Vector3 &position)
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
int index = get_line_index(); int index = get_line_index();
rld->lines[current_line].points[index].origin = position; rld->lines(current_line).points[index].origin = position;
Array args; Array args;
args.push_back(current_line); args.push_back(current_line);
EditorEvent::get_singleton()->event.emit("lines_changed_line", args); EditorEvent::get_singleton()->event.emit("lines_changed_line", args);
@@ -1004,9 +1005,9 @@ void RoadLinesEditor::set_ui_point_position(const Vector3 &point_position)
void RoadLinesEditor::set_line_index(int index) void RoadLinesEditor::set_line_index(int index)
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
assert(rld->lines.has(current_line)); assert(rld->has_line(current_line));
assert(index < (int)rld->lines[current_line].points.size()); assert(index < (int)rld->lines(current_line).points.size());
Vector3 point_position = rld->lines[current_line].points[index].origin; Vector3 point_position = rld->lines(current_line).points[index].origin;
Vector3 cursor_position = point_position; Vector3 cursor_position = point_position;
set_cursor_position(cursor_position); set_cursor_position(cursor_position);
set_ui_cursor_position(cursor_position); set_ui_cursor_position(cursor_position);
@@ -1227,7 +1228,7 @@ void RoadLinesEditor::save_data()
void RoadLinesEditor::update_current_line_metadata(const String &text) void RoadLinesEditor::update_current_line_metadata(const String &text)
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
assert(rld->lines.has(current_line)); assert(rld->has_line(current_line));
if (!text.begins_with("{")) if (!text.begins_with("{"))
return; return;
String err_s; String err_s;
@@ -1243,13 +1244,13 @@ void RoadLinesEditor::update_current_line_metadata(const String &text)
print_line("Invalid metadata type, should be Dictionary"); print_line("Invalid metadata type, should be Dictionary");
return; return;
} }
rld->lines[current_line].metadata = v; rld->lines(current_line).metadata = v;
} }
String RoadLinesEditor::get_current_line_metadata() const String RoadLinesEditor::get_current_line_metadata() const
{ {
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
assert(rld->lines.has(current_line)); assert(rld->has_line(current_line));
return JSON::print(rld->lines[current_line].metadata, "\t", true); return JSON::print(rld->lines(current_line).metadata, "\t", true);
} }
void RoadLinesEditor::remove_generated_stuff() void RoadLinesEditor::remove_generated_stuff()
{ {

View File

@@ -63,14 +63,14 @@ struct RoadLinesProcessing {
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
while (e) { while (e) {
const String &key = e->get(); const String &key = e->get();
if (rld->lines[key].indices.size() < 2) { if (rld->lines(key).indices.size() < 2) {
e = e->next(); e = e->next();
continue; continue;
} }
for (i = 0; i < (int)rld->lines[key].indices.size() - 1; for (i = 0; i < (int)rld->lines(key).indices.size() - 1;
i++) { i++) {
int idx1 = rld->lines[key].indices[i]; int idx1 = rld->lines(key).indices[i];
int idx2 = rld->lines[key].indices[i + 1]; int idx2 = rld->lines(key).indices[i + 1];
if (edges.find(idx1) == edges.end()) { if (edges.find(idx1) == edges.end()) {
struct edgedata ed; struct edgedata ed;
ed.neighbors.clear(); ed.neighbors.clear();

View File

@@ -18,10 +18,10 @@ void StreamWorld::create_tilemap()
{ {
data()->for_each_building( data()->for_each_building(
[this](const String &key, void *hdata) { [this](const String &key, void *hdata) {
int tile_x = data()->get_building(key).xform.origin.x / const struct BuildingsData::building &b =
tile_size; data()->get_building(key);
int tile_z = data()->get_building(key).xform.origin.z / int tile_x = b.xform.origin.x / tile_size;
tile_size; int tile_z = b.xform.origin.z / tile_size;
std::tuple<int, int> tkey = std::tuple<int, int> tkey =
std::make_tuple(tile_x, tile_z); std::make_tuple(tile_x, tile_z);
if (tiles.find(tkey) != tiles.end()) if (tiles.find(tkey) != tiles.end())
@@ -32,19 +32,6 @@ void StreamWorld::create_tilemap()
} }
}, },
nullptr); nullptr);
#if 0
for (i = 0; i < (int)data()->get_building_count(); i++) {
int tile_x = data()->get_building(i).xform.origin.x / tile_size;
int tile_z = data()->get_building(i).xform.origin.z / tile_size;
std::tuple<int, int> key = std::make_tuple(tile_x, tile_z);
if (tiles.find(key) != tiles.end())
tiles[key].push_back(i);
else {
std::vector<int> data = { i };
tiles[key] = data;
}
}
#endif
print_line("Tile count: " + itos(tiles.size())); print_line("Tile count: " + itos(tiles.size()));
} }
@@ -243,7 +230,7 @@ void StreamWorld::remove_building(const String &key)
// TODO: implement // TODO: implement
unload_building(key); unload_building(key);
data()->destroy_building(key); data()->destroy_building(key);
data()->item_nodes_item_removed(key); assert(!data()->has_building(key));
update_items(); update_items();
} }
@@ -352,7 +339,7 @@ void StreamWorld::run_command(const String &command, const Array &args)
for (i = erased_keys.size() - 1; i >= 0; i--) { for (i = erased_keys.size() - 1; i >= 0; i--) {
unload_building(erased_keys[i]); unload_building(erased_keys[i]);
data()->destroy_building(erased_keys[i]); data()->destroy_building(erased_keys[i]);
data()->item_nodes_item_removed(erased_keys[i]); assert(!data()->has_building(erased_keys[i]));
} }
update_items(); update_items();
} else if (command == "remove_generated_stuff") { } else if (command == "remove_generated_stuff") {
@@ -475,7 +462,7 @@ void StreamWorld::remove_generated_stuff()
const String &key = erased_keys[i]; const String &key = erased_keys[i];
unload_building(key); unload_building(key);
data()->destroy_building(key); data()->destroy_building(key);
data()->item_nodes_item_removed(key); assert(!data()->has_building(key));
} }
update_items(); update_items();
} }