Completed conversion of buildings handling to ECS systems

This commit is contained in:
2025-04-29 16:15:37 +03:00
parent dd00a41024
commit bc0dcfaead
20 changed files with 974 additions and 638 deletions

View File

@@ -5,12 +5,14 @@ EDITOR_PLATFORM=x11es
EDITOR2_PLATFORM=x11 EDITOR2_PLATFORM=x11
DEMO_PLATFORMS=x11 x11es DEMO_PLATFORMS=x11 x11es
EDITOR = src/godot/bin/godot.$(EDITOR_PLATFORM).opt.tools.$(ARCH) EDITOR = src/godot/bin/godot.$(EDITOR_PLATFORM).opt.tools.$(ARCH)
EDITOR_DBG = src/godot/bin/godot.$(EDITOR_PLATFORM).tools.$(ARCH)
EDITOR2 = src/godot/bin/godot.$(EDITOR2_PLATFORM).opt.tools.$(ARCH) EDITOR2 = src/godot/bin/godot.$(EDITOR2_PLATFORM).opt.tools.$(ARCH)
EDITOR2_DBG = src/godot/bin/godot.$(EDITOR2_PLATFORM).tools.$(ARCH)
.PHONY: all godot-editor-main export export-models export-clothes \ .PHONY: all godot-editor-main godot-editor-debug export export-models export-clothes \
export-clean export-linux-demo export-windows-demo \ export-clean export-linux-demo export-windows-demo \
export-binaries patch tests import-vrm export-buildings export-binaries patch tests import-vrm export-buildings
all: godot-editor-main godot-main all: godot-editor-main godot-editor-debug godot-main
SCONS_EXTRA=-j16 SCONS_EXTRA=-j16
define build_godot define build_godot
$(4): $(5) $(4): $(5)
@@ -31,12 +33,15 @@ $(foreach pt,$(DEMO_PLATFORMS),$(eval $(call build_godot_platform,$(pt))))
godot-main: $(GODOT_MAIN_TARGETS) godot-editor-main godot-server-main godot-main: $(GODOT_MAIN_TARGETS) godot-editor-main godot-server-main
godot-server-main: $(SERVER) godot-server-main: $(SERVER)
godot-editor-main: $(EDITOR) $(EDITOR2) godot-editor-main: $(EDITOR) $(EDITOR2)
godot-editor-debug: $(EDITOR_DBG) $(EDITOR2_DBG)
#$(SERVER): patch #$(SERVER): patch
# cd src/godot; \ # cd src/godot; \
# scons platform=server arch=$(ARCH) target=release_debug tools=yes custom_modules=../modules -j16 # scons platform=server arch=$(ARCH) target=release_debug tools=yes custom_modules=../modules -j16
$(eval $(call build_godot,server,release_debug,yes,$(SERVER),patch)) $(eval $(call build_godot,server,release_debug,yes,$(SERVER),patch))
$(eval $(call build_godot,x11es,release_debug,yes,$(EDITOR),patch)) $(eval $(call build_godot,x11es,release_debug,yes,$(EDITOR),patch))
$(eval $(call build_godot,x11es,debug,yes,$(EDITOR_DBG),patch))
$(eval $(call build_godot,x11,release_debug,yes,$(EDITOR2),patch)) $(eval $(call build_godot,x11,release_debug,yes,$(EDITOR2),patch))
$(eval $(call build_godot,x11,debug,yes,$(EDITOR2_DBG),patch))
patch: ./src/godot/scene/animation/skeleton_ik.cpp patch: ./src/godot/scene/animation/skeleton_ik.cpp
cd ./src/godot && git reset --hard HEAD && rm -Rf platform/x11es && for p in ../patches/*.patch; do git apply $$p; done cd ./src/godot && git reset --hard HEAD && rm -Rf platform/x11es && for p in ../patches/*.patch; do git apply $$p; done
sed -e 's/ERR_FAIL_COND_V(-1 == p_task->root_bone, false);//g' -i ./src/godot/scene/animation/skeleton_ik.cpp sed -e 's/ERR_FAIL_COND_V(-1 == p_task->root_bone, false);//g' -i ./src/godot/scene/animation/skeleton_ik.cpp

View File

@@ -15,13 +15,7 @@
#include "base_data.h" #include "base_data.h"
#include "buildings_data.h" #include "buildings_data.h"
static ConfigFile config; ConfigFile BuildingsData::config;
static ConfigFile custom_layouts;
struct scene_data {
Ref<PackedScene> packed_scene;
String path;
Ref<ResourceInteractiveLoader> loader;
};
static flecs::world &ecs() static flecs::world &ecs()
{ {
@@ -37,250 +31,12 @@ static flecs::entity lookup(const char *key)
{ {
return ecs().lookup(key); return ecs().lookup(key);
} }
struct CBuildingInstance {
String key;
Node *node;
};
struct CSceneData {
struct scene_data sd;
};
#if 0
void BuildingsData::load_tile(std::tuple<int, int> key)
{
int i;
const std::vector<String> &items = tiles[key];
for (i = 0; i < (int)items.size(); i++) {
print_verbose("load item: " + itos(i) + ": key: " + (items[i]) +
": " /* + data()->get_building(items[i]).id */);
const String &bkey = items[i];
flecs::entity eb = get_building_entity(bkey);
if (eb.is_valid()) {
if (!eb.has<BuildingsData::CBuildingLoaded>())
eb.add<BuildingsData::CBuildingLoad>();
}
}
}
#endif
BuildingsData::BuildingsData()
: undo_log_size(64)
{
flecs::world ecs_ = ecs();
ecs_.component<CBuildingStats>();
ecs_.component<CBuildingData>();
ecs_.component<CBTypeResidental>();
ecs_.component<CBCustomLayout>();
ecs_.component<CBuildingEdited>();
ecs_.component<CBuildingTileData>();
ecs_.component<CBuildingsEye>();
bool deferred = ecs_.is_deferred();
if (deferred)
ecs_.defer_suspend();
ecs_.set<CBuildingStats>({ 0 });
ecs_.set<CBuildingTileData>({});
assert(ecs_.has<CBuildingStats>());
load_data();
ecs_.query_builder<const CBuildingData>().build().each(
[](flecs::entity e, const CBuildingData &bd) {
print_line("created: " + bd.building.key + " / " +
String(e.name()));
});
if (deferred)
ecs_.defer_resume();
print_line("loaded buildings: " +
itos(ecs().get<CBuildingStats>()->created_entities));
assert(ecs().get<CBuildingStats>()->created_entities > 0);
fill_door_locations();
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);
}
});
ecs_.observer<CBuildingEdited>()
.event(flecs::OnAdd)
.with<CBuildingData>()
.run([&](flecs::iter &it) {
flecs::query<const CBuildingData> q =
it.world()
.query_builder<const CBuildingData>()
.with<CBuildingEdited>()
.build();
if (it.next()) {
flecs::entity qe = it.entity(0);
q.each([qe](flecs::entity e,
const CBuildingData &d) {
if (e != qe)
e.remove<CBuildingEdited>();
});
print_line("Selected building " +
String(qe.name()));
// it.fini();
}
});
ecs_.system("UpdateEye").kind(flecs::OnUpdate).run([&](flecs::iter &it) {
Viewport *viewport = SceneTree::get_singleton()
->get_current_scene()
->get_viewport();
int i, j, l;
int tile_size = config.get_value("world", "tile_size");
int view_distance = config.get_value("world", "view_distance");
assert(tile_size > 0);
Transform xform =
viewport->get_camera()->get_global_transform();
Vector3 eye = xform.origin;
int tile_x = int(eye.x / tile_size);
int tile_z = int(eye.z / tile_size);
bool need_update = true;
if (it.world().has<CBuildingsEye>()) {
int old_x = it.world().get<CBuildingsEye>()->tile_x;
int old_z = it.world().get<CBuildingsEye>()->tile_z;
if (old_x == tile_x && old_z == tile_z)
need_update = false;
}
it.world().set<CBuildingsEye>({ xform, tile_x, tile_z });
if (need_update)
return;
if (!it.world().has<CBuildingTileData>())
return;
CBuildingTileData *td = it.world().get_mut<CBuildingTileData>();
it.world()
.query_builder<CBuildingData>()
.without<CBuildingLoaded>()
.without<CBuildingLoad>()
.with<CBuildingTile>()
.build()
.each([&](flecs::entity e, const CBuildingData &bd) {
const CBuildingTile *bt =
e.get<CBuildingTile>();
std::tuple<int, int> tile = bt->tile;
int t_x = std::get<0>(tile);
int t_z = std::get<1>(tile);
if (t_x > tile_x - view_distance &&
t_x < tile_x + view_distance &&
t_z > tile_z - view_distance &&
t_z < tile_z + view_distance) {
if (e.is_valid()) {
e.add<BuildingsData::
CBuildingLoad>();
}
}
});
it.world()
.query_builder<CBuildingData>()
.with<CBuildingLoaded>()
.with<CBuildingTile>()
.without<CBuildingUnload>()
.build()
.each([&](flecs::entity e, const CBuildingData &bd) {
const CBuildingTile *bt =
e.get<CBuildingTile>();
std::tuple<int, int> tile = bt->tile;
int erase_distance = view_distance + 1;
int ed2 = erase_distance * erase_distance;
int t_x = std::get<0>(tile);
int t_z = std::get<1>(tile);
int d1 = t_x - tile_x;
int d2 = t_z - tile_z;
if (d1 * d1 > ed2 || d2 * d2 > ed2)
if (e.is_valid()) {
e.add<BuildingsData::
CBuildingUnload>();
}
});
});
ecs_.system<const CBuildingData>("LoadData")
.kind(flecs::OnUpdate)
.without<CBuildingLoaded>()
.with<CBuildingLoad>()
.write<CBuildingLoaded>()
.each([&](flecs::entity e, const CBuildingData &bd) {
e.world().defer_suspend();
bool debug = false;
// if (bd.building.key.begins_with("road__"))
// debug = true;
String id = bd.building.id;
if (debug)
print_verbose("add to scene id: " + id);
if (!has_scene(id))
create_scene_data(id, bd.building.key);
else
add_scene_item(id, bd.building.key);
if (debug)
print_verbose("added to scene id: " + id);
e.add<CBuildingLoaded>();
e.remove<CBuildingLoad>();
e.world().defer_resume();
});
ecs_.system<const CBuildingData>("UnloadData")
.kind(flecs::OnUpdate)
.with<CBuildingUnload>()
.with<CBuildingLoaded>()
.write<CBuildingLoaded>()
.each([&](flecs::entity e, const CBuildingData &bd) {
bool debug = false;
// if (bd.building.key.begins_with("road__"))
// debug = true;
String id = bd.building.key;
if (debug)
print_verbose("removed from scene id: " + id);
if (has_scene(id))
remove_scene_item(id, bd.building.key);
e.remove<CBuildingLoaded>();
e.remove<CBuildingUnload>();
});
}
BuildingsData::~BuildingsData()
{
}
void BuildingsData::build_building_aabbs() void BuildingsData::build_building_aabbs()
{ {
building_aabbs.clear(); // building_aabbs.clear();
List<String> keys; // List<String> keys;
building_data.get_key_list(&keys); // building_data.get_key_list(&keys);
List<String>::Element *e = keys.front(); // List<String>::Element *e = keys.front();
while (e) {
Error err;
const String &path = building_data[e->get()];
Ref<PackedScene> ps =
ResourceLoader::load(path, "PackedScene", true, &err);
if (err == OK && ps.is_valid()) {
AABB aabb;
Node *scene = ps->instance();
List<Node *> queue;
queue.push_back(scene);
while (!queue.empty()) {
int i;
Node *item = queue.front()->get();
queue.pop_front();
MeshInstance *mi =
Object::cast_to<MeshInstance>(item);
if (mi) {
if (aabb.size.length_squared() < 0.1f)
aabb = mi->get_aabb();
else
aabb.merge_with(mi->get_aabb());
}
for (i = 0; i < item->get_child_count(); i++)
queue.push_back(item->get_child(i));
}
building_aabbs[e->get()] = aabb;
scene->queue_delete();
ps.unref();
} else
print_error("Could not load: " + path);
e = e->next();
}
} }
void BuildingsData::update_building_transform(const String &key, void BuildingsData::update_building_transform(const String &key,
@@ -301,7 +57,7 @@ bool BuildingsData::has_building(const String &key)
return e.is_valid(); return e.is_valid();
} }
String BuildingsData::get_closest_building(const Transform &xform) const String BuildingsData::get_closest_building(const Transform &xform)
{ {
float dst = Math_INF; float dst = Math_INF;
String rkey; String rkey;
@@ -318,8 +74,7 @@ String BuildingsData::get_closest_building(const Transform &xform) const
}); });
return rkey; return rkey;
} }
flecs::entity flecs::entity BuildingsData::get_closest_building_entity(const Transform &xform)
BuildingsData::get_closest_building_entity(const Transform &xform) const
{ {
float dst = Math_INF; float dst = Math_INF;
String rkey; String rkey;
@@ -500,6 +255,7 @@ void BuildingsData::load_data()
assert(ecs().has<CBuildingStats>()); assert(ecs().has<CBuildingStats>());
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");
#if 0
Dictionary buildings_data = Dictionary buildings_data =
config.get_value("buildings", "building_data"); config.get_value("buildings", "building_data");
List<Variant> keys; List<Variant> keys;
@@ -507,7 +263,23 @@ void BuildingsData::load_data()
List<Variant>::Element *e = keys.front(); List<Variant>::Element *e = keys.front();
while (e) { while (e) {
String key = e->get(); String key = e->get();
building_data[key] = buildings_data[key]; // building_data[key] = buildings_data[key];
flecs::entity se = ecs().entity(key.ascii().ptr());
// print_line("scene key: " + key);
assert(buildings_data.has(key));
String path = buildings_data[key];
// print_line("path: " + path);
assert(path.length() > 5);
// print_line("Requesting " + (bkey) + " " + path);
assert(!pending_scene.has(path));
struct scene_data sd;
sd.path = path;
sd.loader = ResourceLoader::load_interactive(
path, "PackedScene", true);
assert(sd.loader.is_valid());
se.set<CSceneData>({ sd });
pending_scene.insert(path);
assert(se.get_mut<CSceneData>());
e = e->next(); e = e->next();
} }
e = keys.front(); e = keys.front();
@@ -516,12 +288,14 @@ void BuildingsData::load_data()
// print_line(key + ": " + buildings_data[key]); // print_line(key + ": " + buildings_data[key]);
e = e->next(); e = e->next();
} }
#endif
String buildings_path = config.get_value("buildings", "buildings_path"); String buildings_path = config.get_value("buildings", "buildings_path");
read_buildings_json(buildings_path); read_buildings_json(buildings_path);
} }
void BuildingsData::checkpoint() void BuildingsData::checkpoint()
{ {
#if 0
struct checkpoint_data cp; struct checkpoint_data cp;
cp.building_data = building_data; cp.building_data = building_data;
cp.buildings.clear(); cp.buildings.clear();
@@ -531,9 +305,11 @@ void BuildingsData::checkpoint()
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());
#endif
} }
void BuildingsData::undo() void BuildingsData::undo()
{ {
#if 0
int i; 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;
@@ -545,98 +321,44 @@ void BuildingsData::undo()
flecs::entity e = ecs().entity(ename.ascii().ptr()); flecs::entity e = ecs().entity(ename.ascii().ptr());
e.set<CBuildingData>({ cp.buildings[i] }); e.set<CBuildingData>({ cp.buildings[i] });
} }
#endif
} }
void BuildingsData::fill_door_locations() void BuildingsData::get_scene_keys_list(List<String> *keys)
{
/*
func fill_door_locations():
for k in building_data.keys():
var bdoors = []
var l = building_data[k].instance()
var queue = [l]
while queue.size() > 0:
var item = queue.pop_front()
if item.name.find("-portal") >= 0:
var xform = item.transform
var tmp = item.get_parent()
while tmp != null:
var parent_xform = tmp.transform
xform = parent_xform * xform
tmp = tmp.get_parent()
bdoors.push_back(var2str(xform))
for c in item.get_children():
queue.push_back(c)
door_locations[k] = bdoors
l.queue_free()
*/
List<String> keys;
building_data.get_key_list(&keys);
List<String>::Element *e = keys.front();
while (e) {
Error err;
const String &path = building_data[e->get()];
Ref<PackedScene> ps =
ResourceLoader::load(path, "PackedScene", true, &err);
if (err == OK && ps.is_valid()) {
Vector<Transform> doors;
Node *scene = ps->instance();
List<Node *> queue;
queue.push_back(scene);
while (!queue.empty()) {
int i;
Node *item = queue.front()->get();
queue.pop_front();
String name = item->get_name();
if (name.find("-portal") >= 0) {
Spatial *sp =
Object::cast_to<Spatial>(item);
if (sp) {
Transform xform =
sp->get_transform();
Node *tmp = item->get_parent();
while (tmp) {
Transform parent_xform;
Spatial *parent_sp =
Object::cast_to<
Spatial>(
tmp);
if (parent_sp)
parent_xform =
parent_sp
->get_transform();
xform = parent_xform *
xform;
tmp = tmp->get_parent();
}
doors.push_back(xform);
}
}
for (i = 0; i < item->get_child_count(); i++)
queue.push_back(item->get_child(i));
}
building_doors[e->get()] = doors;
scene->queue_delete();
ps.unref();
}
e = e->next();
}
}
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)
{ {
flecs::entity e = ecs().lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
return e.is_valid(); return e.is_valid() && e.has<CSceneData>();
} }
flecs::entity BuildingsData::get_building_entity(const String &key) const AABB BuildingsData::get_scene_aabb(const String &key)
{
flecs::entity e = ecs().lookup(key.ascii().ptr());
if (!e.is_valid()) {
uint64_t key_hash = key.hash64();
e = ecs().query_builder<const CSceneData>().build().find(
[key_hash](const CSceneData &sd) {
print_line("scene: " + sd.sd.key);
return sd.sd.key.hash64() == key_hash;
});
if (!e.is_valid())
print_line("scene not found: " + key);
}
assert(e.is_valid());
if (!e.has<CSceneData>() || !e.has<CSceneAABB>())
print_error("not found: " + key);
assert(e.has<CSceneData>());
return e.get<CSceneAABB>()->aabb;
}
flecs::entity BuildingsData::get_building_entity(const String &key)
{ {
flecs::query_builder<const CBuildingData> qb = flecs::query_builder<const CBuildingData> qb =
ecs().query_builder<const CBuildingData>(); ecs().query_builder<const CBuildingData>();
@@ -689,6 +411,11 @@ 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());
assert(e.has<CSceneData>());
flecs::entity be = get_building_entity(bkey);
assert(be.is_valid());
assert(be.has<CBuildingData>());
const CBuildingData *b = be.get<CBuildingData>();
CSceneData *d = e.get_mut<CSceneData>(); CSceneData *d = e.get_mut<CSceneData>();
assert(d); assert(d);
String ename = "bi:" + bkey; String ename = "bi:" + bkey;
@@ -697,54 +424,46 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey)
if (ce.is_valid()) if (ce.is_valid())
ce.destruct(); ce.destruct();
ce = ecs().entity(ename.ascii().ptr()).child_of(e); ce = ecs().entity(ename.ascii().ptr()).child_of(e);
Ref<PackedScene> ps = scene_get_packed_scene(key);
if (!ps.is_valid())
return;
Node *where = SceneTree::get_singleton()->get_current_scene();
assert(where);
if (ps.is_valid()) {
Spatial *scene = Object::cast_to<Spatial>(ps->instance());
assert(scene);
where->call_deferred("add_child", scene);
scene->set_transform(b->building.xform);
ce.set<CBuildingInstance>({ bkey, scene });
} else
ce.set<CBuildingInstance>({ bkey, nullptr }); ce.set<CBuildingInstance>({ bkey, nullptr });
// print_line("child name: " + String(ce.name())); // print_line("child name: " + String(ce.name()));
} }
void BuildingsData::create_scene_data(const String &key, const String &bkey) Ref<PackedScene> BuildingsData::scene_get_packed_scene(const String &key)
{
if (!has_scene(key)) {
flecs::entity e = ecs().entity(key.ascii().ptr());
// print_line("scene key: " + key);
assert(building_data.has(key));
String path = building_data[key];
// print_line("path: " + path);
assert(path.length() > 5);
print_line("Requesting " + (bkey) + " " + path);
assert(!pending_scene.has(path));
struct scene_data sd;
sd.path = path;
sd.loader = ResourceLoader::load_interactive(
path, "PackedScene", true);
assert(sd.loader.is_valid());
e.set<CSceneData>({ sd });
pending_scene.insert(path);
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()));
}
}
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.has<CScenePackLoaded>())
return Ref<PackedScene>();
assert(e.is_valid());
assert(e.has<CSceneData>());
assert(e.has<CScenePack>());
assert(e.get<CScenePack>());
assert(e.get<CScenePack>()->sp.packed_scene.is_valid());
if (!e.is_valid()) if (!e.is_valid())
return Ref<PackedScene>(); return Ref<PackedScene>();
if (!e.get<CSceneData>()) if (!e.get<CSceneData>())
return Ref<PackedScene>(); return Ref<PackedScene>();
if (!e.get<CScenePack>())
return Ref<PackedScene>();
assert(e.is_valid()); assert(e.is_valid());
const CSceneData *d = e.get<CSceneData>(); const CScenePack *d = e.get<CScenePack>();
assert(d); assert(d);
return d->sd.packed_scene; return d->sp.packed_scene;
} }
int BuildingsData::scene_get_item_count(const String &key) const int BuildingsData::scene_get_item_count(const String &key)
{ {
flecs::entity e = ecs().lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
if (!e.is_valid()) if (!e.is_valid())
@@ -769,7 +488,7 @@ int BuildingsData::scene_get_item_count(const String &key) const
// print_line("scene_get_item_count: " + itos(result)); // print_line("scene_get_item_count: " + itos(result));
return result; return result;
} }
List<String> BuildingsData::scene_get_items(const String &key) const List<String> BuildingsData::scene_get_items(const String &key)
{ {
List<String> ret; List<String> ret;
flecs::entity e = ecs().lookup(key.ascii().ptr()); flecs::entity e = ecs().lookup(key.ascii().ptr());
@@ -803,8 +522,9 @@ void BuildingsData::set_scene_item_node(const String &key, const String &bkey,
assert(bi); assert(bi);
assert(bi->key == bkey); assert(bi->key == bkey);
bi->node = node; bi->node = node;
ce.modified<CBuildingInstance>();
} }
bool BuildingsData::has_scene_item(const String &key, const String &bkey) const bool BuildingsData::has_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());
@@ -814,8 +534,7 @@ bool BuildingsData::has_scene_item(const String &key, const String &bkey) const
flecs::entity ce = e.lookup(ename.ascii().ptr()); flecs::entity ce = e.lookup(ename.ascii().ptr());
return ce.is_valid(); return ce.is_valid();
} }
Node *BuildingsData::get_scene_item_node(const String &key, Node *BuildingsData::get_scene_item_node(const String &key, const String &bkey)
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());
@@ -823,6 +542,8 @@ Node *BuildingsData::get_scene_item_node(const String &key,
assert(d); assert(d);
String ename = "bi:" + bkey; String ename = "bi:" + bkey;
flecs::entity ce = e.lookup(ename.ascii().ptr()); flecs::entity ce = e.lookup(ename.ascii().ptr());
if (!ce.is_valid()) /* no instance */
return nullptr;
assert(ce.is_valid()); assert(ce.is_valid());
CBuildingInstance *bi = ce.get_mut<CBuildingInstance>(); CBuildingInstance *bi = ce.get_mut<CBuildingInstance>();
assert(bi); assert(bi);
@@ -836,7 +557,7 @@ void BuildingsData::save_buildings()
save_buildings_json(buildings_path); save_buildings_json(buildings_path);
} }
Node *BuildingsData::item_nodes_get_node(const String &key) const Node *BuildingsData::item_nodes_get_node(const String &key)
{ {
flecs::query_builder<const CBuildingInstance> qb = flecs::query_builder<const CBuildingInstance> qb =
ecs().query_builder<const CBuildingInstance>(); ecs().query_builder<const CBuildingInstance>();
@@ -851,29 +572,6 @@ Node *BuildingsData::item_nodes_get_node(const String &key) const
return nullptr; return nullptr;
} }
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);
assert(d->sd.loader.is_valid());
Error err = d->sd.loader->poll();
if (err == ERR_FILE_EOF || err == OK) {
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() void BuildingsData::scene_update()
{ {
List<String> keys; List<String> keys;
@@ -885,12 +583,11 @@ void BuildingsData::scene_update()
e = e->next(); e = e->next();
continue; continue;
} }
scene_loader_poll(key);
e = e->next(); e = e->next();
} }
} }
int BuildingsData::get_building_count() const int BuildingsData::get_building_count()
{ {
flecs::query<const CBuildingData> q = flecs::query<const CBuildingData> q =
ecs().query<const CBuildingData>(); ecs().query<const CBuildingData>();
@@ -906,20 +603,24 @@ int BuildingsData::get_building_count() const
return result; return result;
} }
const struct BuildingsData::building &
BuildingsData::get_building(const String &building_key) const
{
String ename = "base:" + building_key;
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)
{ {
String ename = "base:" + building_key; String ename = "base:" + building_key;
flecs::entity e = lookup(ename); flecs::entity e = lookup(ename);
if (!e.is_valid()) {
// print_error("bad building: " + ename);
e = ecs().query_builder<const CBuildingData>().build().find(
[&](flecs::entity se, const CBuildingData &bd) {
// print_line(String(se.name() + "#" +
// bd.building.key));
if (bd.building.key == building_key)
return true;
if (String(se.name()) == ename)
return true;
return false;
});
}
assert(e.is_valid()); assert(e.is_valid());
return e.get_mut<CBuildingData>()->building; return e.get_mut<CBuildingData>()->building;
} }

View File

@@ -3,10 +3,14 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <core/reference.h> #include <core/reference.h>
#include <scene/resources/packed_scene.h>
#include <core/io/config_file.h>
#include <flecs.h> #include <flecs.h>
class PackedScene; class PackedScene;
class ResourceInteractiveLoader; class ResourceInteractiveLoader;
class BuildingsData { class BuildingsData {
static ConfigFile config;
public: public:
/* Per-building information */ /* Per-building information */
struct building { struct building {
@@ -23,6 +27,15 @@ public:
Dictionary to_dict() const; Dictionary to_dict() const;
String line_name; String line_name;
}; };
struct scene_data {
String key;
String path;
};
struct scene_pack {
Ref<PackedScene> packed_scene;
Ref<ResourceInteractiveLoader> loader;
};
Set<String> pending_scene; Set<String> pending_scene;
/* Scene objects data */ /* Scene objects data */
//private: //private:
@@ -31,6 +44,9 @@ public:
struct CBuildingData { struct CBuildingData {
struct BuildingsData::building building; struct BuildingsData::building building;
}; };
struct CBuildingSceneLoaded {};
struct CBuildingSceneLoad {};
struct CBuildingSceneUnload {};
struct CBTypeResidental {}; struct CBTypeResidental {};
struct CBCustomLayout { struct CBCustomLayout {
int size; int size;
@@ -65,39 +81,54 @@ public:
struct CBuildingUnload {}; struct CBuildingUnload {};
struct CBuildingLoaded {}; struct CBuildingLoaded {};
struct CBuildingEdited {}; struct CBuildingEdited {};
struct CSceneData {
struct scene_data sd;
};
struct CScenePack {
struct scene_pack sp;
};
struct CScenePackLoaded {};
struct CSceneDoors {
Vector<Transform> doors;
};
struct CSceneAABB {
AABB aabb;
};
struct CScenesLoaded {}; /* all scenes loaded */
struct CBuildingInstance {
String key;
Node *node;
};
struct CBuildingInstanced {};
public: public:
void get_scene_keys_list(List<String> *keys) const; static void get_scene_keys_list(List<String> *keys);
bool has_scene(const String &key) const; static bool has_scene(const String &key);
void remove_scene_item(const String &key, const String &bkey); static AABB get_scene_aabb(const String &key);
void add_scene_item(const String &key, const String &bkey); static void remove_scene_item(const String &key, const String &bkey);
void create_scene_data(const String &key, const String &bkey); static void add_scene_item(const String &key, const String &bkey);
Ref<PackedScene> scene_get_packed_scene(const String &key) const; static Ref<PackedScene> scene_get_packed_scene(const String &key);
int scene_get_item_count(const String &key) const; static int scene_get_item_count(const String &key);
// 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; static List<String> scene_get_items(const String &key);
void set_scene_item_node(const String &key, const String &bkey, static void set_scene_item_node(const String &key, const String &bkey,
Node *node); Node *node);
bool has_scene_item(const String &key, const String &bkey) const; static bool has_scene_item(const String &key, const String &bkey);
Node *get_scene_item_node(const String &key, const String &bkey) const; static Node *get_scene_item_node(const String &key, const String &bkey);
void save_buildings(); static void save_buildings();
public: public:
Node *item_nodes_get_node(const String &key) const; static Node *item_nodes_get_node(const String &key);
private:
Error scene_loader_poll(const String &key);
public: public:
void scene_update(); static void scene_update();
/* Path for each building type */ /* Path for each building type */
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;
public: public:
struct building &get_building(const String &building_key); static struct building &get_building(const String &building_key);
const struct building &get_building(const String &building_key) const;
struct callme { struct callme {
class H {}; class H {};
H *obj; H *obj;
@@ -126,8 +157,9 @@ public:
void *)>(obj); void *)>(obj);
} }
void for_each_building(struct callme &c); static void for_each_building(struct callme &c);
template <typename Func> void for_each_building(Func &&func, void *data) template <typename Func>
static void for_each_building(Func &&func, void *data)
{ {
List<String> keys; List<String> keys;
get_building_keys_list(&keys); get_building_keys_list(&keys);
@@ -137,40 +169,41 @@ public:
e = e->next(); e = e->next();
} }
} }
void for_each_building(void (*func)(const String &key, void *data), static void for_each_building(void (*func)(const String &key,
void *data),
void *data); void *data);
void get_building_keys_list(List<String> *keys); static void get_building_keys_list(List<String> *keys);
int get_building_count() const; static int get_building_count();
String create_building(const Dictionary &dict); static String create_building(const Dictionary &dict);
String create_building(const struct building &building); static String create_building(const struct building &building);
String create_building(const struct building *building); static String create_building(const struct building *building);
bool destroy_building(const String &key); static bool destroy_building(const String &key);
struct checkpoint_data { struct checkpoint_data {
HashMap<String, String> building_data; HashMap<String, String> building_data;
std::vector<struct building> buildings; std::vector<struct building> buildings;
}; };
std::vector<struct checkpoint_data> undo_log; std::vector<struct checkpoint_data> undo_log;
int undo_log_size; int undo_log_size;
BuildingsData(); BuildingsData(flecs::world &e);
virtual ~BuildingsData(); virtual ~BuildingsData();
public: public:
void read_buildings_json(const String &buildings_path); static void read_buildings_json(const String &buildings_path);
void save_buildings_json(const String &buildings_path); static void save_buildings_json(const String &buildings_path);
void filter_generated_stuff(); static void filter_generated_stuff();
void remove_generated_stuff(); static void remove_generated_stuff();
void load_data(); void load_data();
void checkpoint(); void checkpoint();
void undo(); void undo();
void fill_door_locations(); static void build_building_aabbs();
void build_building_aabbs(); static void update_building_transform(const String &key,
void update_building_transform(const String &key,
const Transform &xform); const Transform &xform);
bool has_building(const String &key); static bool has_building(const String &key);
String get_closest_building(const Transform &xform) const; static String get_closest_building(const Transform &xform);
flecs::entity get_closest_building_entity(const Transform &xform) const; static flecs::entity
flecs::entity get_building_entity(const String &key) const; get_closest_building_entity(const Transform &xform);
static flecs::entity get_building_entity(const String &key);
void load_tile(int x, int z); void load_tile(int x, int z);
}; };
#endif #endif

View File

@@ -0,0 +1,400 @@
#include <scene/resources/packed_scene.h>
#include <scene/3d/spatial.h>
#include <scene/3d/mesh_instance.h>
#include <scene/3d/camera.h>
#include <scene/main/viewport.h>
#include "base_data.h"
#include "buildings_data.h"
static flecs::world &ecs()
{
return BaseData::get_singleton()->get();
}
BuildingsData::BuildingsData(flecs::world &ecs_)
: undo_log_size(64)
{
ecs_.module<BuildingsData>();
// print_line("e0");
// flecs::world ecs_ = ecs();
ecs_.component<CBuildingStats>();
ecs_.component<CBuildingData>();
ecs_.component<CBTypeResidental>();
ecs_.component<CBCustomLayout>();
ecs_.component<CBuildingEdited>();
ecs_.component<CBuildingTileData>();
ecs_.component<CBuildingLoaded>();
ecs_.component<CBuildingsEye>();
ecs_.component<CSceneData>();
ecs_.component<CScenePack>();
ecs_.component<CScenesLoaded>();
ecs_.component<CSceneAABB>();
// print_line("e1");
// bool deferred = ecs_.is_deferred();
// if (deferred)
// ecs_.defer_suspend();
ecs_.set<CBuildingStats>({ 0 });
ecs_.set<CBuildingTileData>({});
assert(ecs_.has<CBuildingStats>());
load_data();
print_line("=== buildings");
ecs_.query_builder<const CBuildingData>().build().each(
[](flecs::entity e, const CBuildingData &bd) {
print_line("created: building: " + bd.building.key +
" / " + String(e.name()));
});
/* no scene data loaded yet */
print_line("=== scenes");
ecs_.query_builder<const CSceneData>().build().each(
[](flecs::entity e, const CSceneData &sd) {
print_line("created: scene: " + sd.sd.path + " / " +
String(e.name()));
});
print_line("loaded buildings: " +
itos(ecs().get<CBuildingStats>()->created_entities));
assert(ecs().get<CBuildingStats>()->created_entities > 0);
/* Fill door locations */
ecs().query_builder<CSceneData>().build().each([&](flecs::entity e,
CSceneData &sd) {
Error err;
const String &path = sd.sd.path;
Ref<PackedScene> ps =
ResourceLoader::load(path, "PackedScene", true, &err);
if (err == OK && ps.is_valid()) {
Vector<Transform> doors;
Node *scene = ps->instance();
List<Node *> queue;
queue.push_back(scene);
while (!queue.empty()) {
int i;
Node *item = queue.front()->get();
queue.pop_front();
String name = item->get_name();
if (name.find("-portal") >= 0) {
Spatial *sp =
Object::cast_to<Spatial>(item);
if (sp) {
Transform xform =
sp->get_transform();
Node *tmp = item->get_parent();
while (tmp) {
Transform parent_xform;
Spatial *parent_sp =
Object::cast_to<
Spatial>(
tmp);
if (parent_sp)
parent_xform =
parent_sp
->get_transform();
xform = parent_xform *
xform;
tmp = tmp->get_parent();
}
doors.push_back(xform);
}
}
for (i = 0; i < item->get_child_count(); i++)
queue.push_back(item->get_child(i));
}
e.set<CSceneDoors>({ doors });
scene->queue_delete();
ps.unref();
}
});
// if (deferred)
// ecs_.defer_resume();
ecs_.system("CreateSceneData")
.kind(flecs::OnUpdate)
.write<CSceneData>()
.run([&](flecs::iter &it) {
Dictionary buildings_data =
config.get_value("buildings", "building_data");
List<Variant> keys;
buildings_data.get_key_list(&keys);
List<Variant>::Element *e = keys.front();
while (e) {
String key = e->get();
if (!has_scene(key)) {
// building_data[key] = buildings_data[key];
String path = buildings_data[key];
flecs::entity se =
ecs().entity(key.ascii().ptr());
se.set<CSceneData>({ key, path });
}
e = e->next();
}
});
ecs_.system<const CSceneData>("LoadPackedScene")
.kind(flecs::OnUpdate)
.without<CScenePack>()
.write<CScenePack>()
.each([&](flecs::entity e, const CSceneData &sd) {
struct scene_pack sp;
sp.loader = ResourceLoader::load_interactive(
sd.sd.path, "PackedScene", true);
assert(sp.loader.is_valid());
e.set<CScenePack>({ sp });
});
ecs_.system<CScenePack>("LoadPackedScenePoll")
.kind(flecs::OnUpdate)
.without<CScenePackLoaded>()
.each([&](flecs::entity e, CScenePack &sp) {
const CSceneData *sd = e.get<CSceneData>();
assert(sd);
assert(sp.sp.loader.is_valid());
Error err = sp.sp.loader->poll();
if (err == OK) {
return;
} else if (err == ERR_FILE_EOF) {
Ref<PackedScene> sc =
sp.sp.loader->get_resource();
sp.sp.packed_scene = sc;
uint64_t m_id = (uint64_t)&sp.sp.loader;
print_line("Loaded scene: " + sd->sd.path +
" OK " +
String::num_int64(m_id, 16));
e.add<CScenePackLoaded>();
assert(sp.sp.packed_scene.is_valid());
} else {
print_error("Could not load the resource :( " +
sd->sd.path + " " + itos(err));
}
});
ecs_.system<CSceneData>("CalculateAABBs")
.without<CSceneAABB>()
.each([&](flecs::entity e, CSceneData &sd) {
Error err;
const String &path = sd.sd.path;
Ref<PackedScene> ps = ResourceLoader::load(
path, "PackedScene", true, &err);
if (err == OK && ps.is_valid()) {
AABB aabb;
Node *scene = ps->instance();
List<Node *> queue;
queue.push_back(scene);
while (!queue.empty()) {
int i;
Node *item = queue.front()->get();
queue.pop_front();
MeshInstance *mi =
Object::cast_to<MeshInstance>(
item);
if (mi) {
if (aabb.size.length_squared() <
0.1f)
aabb = mi->get_aabb();
else
aabb.merge_with(
mi->get_aabb());
}
for (i = 0; i < item->get_child_count();
i++)
queue.push_back(
item->get_child(i));
}
scene->queue_delete();
ps.unref();
e.set<CSceneAABB>({ aabb });
} else
print_error("Could not load: " + path);
});
ecs_.system("CheckScenesLoaded")
.kind(flecs::OnUpdate)
.run([&](flecs::iter &it) {
int count_csdata = (int)it.world()
.query_builder<CSceneData>()
.build()
.count();
int count_pack =
(int)it.world()
.query_builder<CScenePackLoaded>()
.build()
.count();
int count_aabb = (int)it.world()
.query_builder<CSceneAABB>()
.build()
.count();
if (count_csdata > 0 && count_csdata == count_pack &&
count_csdata == count_aabb)
it.world().add<CScenesLoaded>();
else
it.world().remove<CScenesLoaded>();
});
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);
}
});
ecs_.observer<CBuildingEdited>()
.event(flecs::OnAdd)
.with<CBuildingData>()
.run([&](flecs::iter &it) {
flecs::query<const CBuildingData> q =
it.world()
.query_builder<const CBuildingData>()
.with<CBuildingEdited>()
.build();
if (it.next()) {
flecs::entity qe = it.entity(0);
q.each([qe](flecs::entity e,
const CBuildingData &d) {
if (e != qe)
e.remove<CBuildingEdited>();
});
print_line("Selected building " +
String(qe.name()));
// it.fini();
}
});
ecs_.system("UpdateEye").kind(flecs::OnUpdate).run([&](flecs::iter &it) {
Viewport *viewport = SceneTree::get_singleton()
->get_current_scene()
->get_viewport();
int i, j, l;
int tile_size = config.get_value("world", "tile_size");
int view_distance = config.get_value("world", "view_distance");
assert(tile_size > 0);
Transform xform =
viewport->get_camera()->get_global_transform();
Vector3 eye = xform.origin;
int tile_x = int(eye.x / tile_size);
int tile_z = int(eye.z / tile_size);
bool need_update = true;
if (it.world().has<CBuildingsEye>()) {
int old_x = it.world().get<CBuildingsEye>()->tile_x;
int old_z = it.world().get<CBuildingsEye>()->tile_z;
if (old_x == tile_x && old_z == tile_z)
need_update = false;
else
print_line("UpdateEye need update");
}
it.world().set<CBuildingsEye>({ xform, tile_x, tile_z });
if (!need_update)
return;
if (!it.world().has<CBuildingTileData>())
return;
CBuildingTileData *td = it.world().get_mut<CBuildingTileData>();
it.world()
.query_builder<CBuildingData>()
.without<CBuildingLoaded>()
.without<CBuildingLoad>()
.with<CBuildingTile>()
.build()
.each([&](flecs::entity e, const CBuildingData &bd) {
const CBuildingTile *bt =
e.get<CBuildingTile>();
std::tuple<int, int> tile = bt->tile;
int t_x = std::get<0>(tile);
int t_z = std::get<1>(tile);
if (t_x > tile_x - view_distance &&
t_x < tile_x + view_distance &&
t_z > tile_z - view_distance &&
t_z < tile_z + view_distance) {
if (e.is_valid()) {
print_line("CBuildingLoad");
e.add<BuildingsData::
CBuildingLoad>();
}
}
});
it.world()
.query_builder<CBuildingData>()
.with<CBuildingLoaded>()
.with<CBuildingTile>()
.without<CBuildingUnload>()
.build()
.each([&](flecs::entity e, const CBuildingData &bd) {
const CBuildingTile *bt =
e.get<CBuildingTile>();
std::tuple<int, int> tile = bt->tile;
int erase_distance = view_distance + 1;
int ed2 = erase_distance * erase_distance;
int t_x = std::get<0>(tile);
int t_z = std::get<1>(tile);
int d1 = t_x - tile_x;
int d2 = t_z - tile_z;
if (d1 * d1 > ed2 || d2 * d2 > ed2)
if (e.is_valid()) {
print_line("CBuildingUnload");
e.add<BuildingsData::
CBuildingUnload>();
}
});
});
ecs_.system<const CBuildingData>("LoadData")
.kind(flecs::OnUpdate)
.without<CBuildingLoaded>()
.without<CBuildingUnload>()
.with<CBuildingLoad>()
.write<CBuildingLoaded>()
.write<CBuildingLoad>()
.write<CBuildingInstanced>()
.each([&](flecs::entity e, const CBuildingData &bd) {
bool debug = false;
// if (bd.building.key.begins_with("road__"))
// debug = true;
String id = bd.building.id;
if (debug)
print_verbose("add to scene id: " + id);
if (!SceneTree::get_singleton()->get_current_scene())
return;
if (!scene_get_packed_scene(id).is_valid())
return;
if (!has_scene(id))
return;
else {
if (!e.has<CBuildingInstanced>()) {
add_scene_item(id, bd.building.key);
e.add<CBuildingInstanced>();
}
}
if (debug)
print_verbose("added to scene id: " + id);
assert(e.is_valid());
// e.world().defer_suspend();
e.add<CBuildingLoaded>();
e.remove<CBuildingLoad>();
print_line("CBuildingLoaded");
// e.world().defer_resume();
print_line("LoadData");
});
ecs_.system<const CBuildingData>("UnloadData")
.kind(flecs::OnUpdate)
.read<CBuildingInstanced>()
.with<CBuildingUnload>()
.with<CBuildingLoaded>()
.write<CBuildingLoaded>()
.each([&](flecs::entity e, const CBuildingData &bd) {
bool debug = false;
// if (bd.building.key.begins_with("road__"))
// debug = true;
String id = bd.building.key;
if (debug)
print_verbose("removed from scene id: " + id);
if (has_scene(id))
remove_scene_item(id, bd.building.key);
e.remove<CBuildingLoaded>();
e.remove<CBuildingUnload>();
e.remove<CBuildingInstanced>();
print_line("UnloadData");
});
ecs_.system<const CBuildingData>("SpawnNode")
.kind(flecs::OnUpdate)
.without<CBuildingUnload>()
.with<CBuildingLoaded>()
.write<CBuildingLoaded>()
.each([&](flecs::entity e, const CBuildingData &bd) {});
print_line("SpawnNode initialized");
}
BuildingsData::~BuildingsData()
{
}

View File

@@ -4,28 +4,28 @@
#include <scene/3d/immediate_geometry.h> #include <scene/3d/immediate_geometry.h>
#include "wedge.h" #include "wedge.h"
#include "base_data.h" #include "base_data.h"
#include "buildings_data.h"
#include "contours.h" #include "contours.h"
Contours *Contours::singleton = nullptr; Contours::Contours(flecs::world &ecs)
Contours *Contours::get_singleton()
{
if (!singleton)
singleton = memnew(Contours);
return singleton;
}
Contours::Contours()
: dbg(nullptr) : dbg(nullptr)
{ {
BaseData::get_singleton()->get().component<Lot>(); ecs.module<Contours>();
ecs.import <BuildingsData>();
Lot::import_packer(ecs);
ecs.component<Lot>();
base_e = BaseData::get_singleton()->get().lookup("lots");
if (base_e.is_valid())
base_e.destruct();
base_e = BaseData::get_singleton()->get().entity("lots");
assert(base_e.is_valid());
} }
Contours::~Contours() Contours::~Contours()
{ {
} }
bool Contours::is_in_closed_contour(const struct wedge *w) bool Contours::is_in_closed_contour(const struct wedge *w) const
{ {
int i, j; int i, j;
bool found = false; bool found = false;
@@ -51,6 +51,7 @@ static Vector3 normal(const Vector3 &v)
void Contours::build() void Contours::build()
{ {
int i, j; int i, j;
print_line("Contours::build()");
contours.clear(); contours.clear();
for (i = 0; i < (int)wedge_contours.size(); i++) { for (i = 0; i < (int)wedge_contours.size(); i++) {
struct main_contour mc; struct main_contour mc;
@@ -86,10 +87,6 @@ void Contours::build()
} }
contours.push_back(mc); contours.push_back(mc);
} }
flecs::entity base_e = BaseData::get_singleton()->get().lookup("lots");
if (base_e.is_valid())
base_e.destruct();
base_e = BaseData::get_singleton()->get().entity("lots");
List<struct Lot::polygon> polygon_queue; List<struct Lot::polygon> polygon_queue;
List<struct Lot::polygon> polygon_output; List<struct Lot::polygon> polygon_output;
Vector<struct Lot::polygon> check; Vector<struct Lot::polygon> check;
@@ -141,7 +138,7 @@ void Contours::build()
List<struct Lot::polygon>::Element *e = polygon_queue.front(); List<struct Lot::polygon>::Element *e = polygon_queue.front();
while (e) { while (e) {
struct Lot::polygon item = e->get(); struct Lot::polygon item = e->get();
print_line("queue: " + itos(polygon_queue.size())); // print_line("queue: " + itos(polygon_queue.size()));
polygon_queue.pop_front(); polygon_queue.pop_front();
float area = item.area(); float area = item.area();
if (area > 120.0f * 120.0f && if (area > 120.0f * 120.0f &&
@@ -162,12 +159,15 @@ void Contours::build()
e = polygon_queue.front(); e = polygon_queue.front();
} }
e = polygon_output.front(); e = polygon_output.front();
assert(base_e.is_valid());
while (e) { while (e) {
print_line("creating entity");
flecs::entity lot_e = BaseData::get_singleton() flecs::entity lot_e = BaseData::get_singleton()
->get() ->get()
.entity() .entity()
.child_of(base_e); .child_of(base_e);
lot_e.set<Lot>({ e->get() }); lot_e.set<Lot>({ e->get() });
print_line("created entity: " + String(lot_e.name()));
e = e->next(); e = e->next();
} }
} }
@@ -186,7 +186,6 @@ void Contours::build()
} }
}); });
}); });
Lot::pack();
} }
void Contours::debug() void Contours::debug()

View File

@@ -2,6 +2,7 @@
#ifndef CONTOURS_H_ #ifndef CONTOURS_H_
#define CONTOURS_H_ #define CONTOURS_H_
#include <vector> #include <vector>
#include <flecs.h>
#include "road_lot.h" #include "road_lot.h"
class ImmediateGeometry; class ImmediateGeometry;
@@ -20,12 +21,11 @@ struct Contours {
Ref<SpatialMaterial> imm_mat; Ref<SpatialMaterial> imm_mat;
std::vector<std::vector<struct wedge *> > wedge_contours; std::vector<std::vector<struct wedge *> > wedge_contours;
std::vector<struct main_contour> contours; std::vector<struct main_contour> contours;
static Contours *singleton; Contours(flecs::world &ecs);
static Contours *get_singleton();
Contours();
virtual ~Contours(); virtual ~Contours();
bool is_in_closed_contour(const struct wedge *w); bool is_in_closed_contour(const struct wedge *w) const;
void debug(); void debug();
flecs::entity base_e;
}; };
#endif // CONTOURS_H_ #endif // CONTOURS_H_

View File

@@ -26,6 +26,7 @@ LineMetadataEditor::~LineMetadataEditor()
void LineMetadataEditor::_notification(int which) void LineMetadataEditor::_notification(int which)
{ {
#if 0
switch (which) { switch (which) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
VBoxContainer *box = memnew(VBoxContainer); VBoxContainer *box = memnew(VBoxContainer);
@@ -64,6 +65,7 @@ void LineMetadataEditor::_notification(int which)
} }
} break; } break;
} }
#endif
} }
void LineMetadataEditor::_bind_methods() void LineMetadataEditor::_bind_methods()

View File

@@ -1125,7 +1125,7 @@ class EdgeEditorHandler {
continue; continue;
} }
const AABB &aabb_building = const AABB &aabb_building =
bd()->building_aabbs[buildings[i].id]; bd()->get_scene_aabb(buildings[i].id);
Transform building_rot( Transform building_rot(
Basis().rotated( Basis().rotated(
Vector3(0, 1, 0), Vector3(0, 1, 0),
@@ -1306,9 +1306,9 @@ class EdgeEditorHandler {
String lot_id = side.lot_type; String lot_id = side.lot_type;
if (side.buildings.size() > 1) { if (side.buildings.size() > 1) {
const AABB &aabb_lot = const AABB &aabb_lot =
bd()->building_aabbs bd()->get_scene_aabb(
["lot-" + "lot-" +
lot_id]; lot_id);
bool pack_result = bool pack_result =
pack_buildings( pack_buildings(
aabb_lot, aabb_lot,
@@ -1375,9 +1375,9 @@ class EdgeEditorHandler {
String lot_id = side.lot_type; String lot_id = side.lot_type;
if (side.buildings.size() > 1) { if (side.buildings.size() > 1) {
const AABB &aabb_lot = const AABB &aabb_lot =
bd()->building_aabbs bd()->get_scene_aabb(
["lot-" + "lot-" +
lot_id]; lot_id);
bool pack_result = bool pack_result =
pack_buildings( pack_buildings(
aabb_lot, aabb_lot,

View File

@@ -121,9 +121,9 @@ template <typename T> static Vector<Vector2> get_polygon2(const T &polygon)
bool Lot::polygon::intersects(const polygon *other) const bool Lot::polygon::intersects(const polygon *other) const
{ {
print_line("intersection_test"); // print_line("intersection_test");
dump(); // dump();
other->dump(); // other->dump();
Vector<Vector2> p1 = get_polygon2(points); Vector<Vector2> p1 = get_polygon2(points);
Vector<Vector2> p2 = get_polygon2(other->points); Vector<Vector2> p2 = get_polygon2(other->points);
Vector<Vector<Vector2> > intersection = Vector<Vector<Vector2> > intersection =
@@ -510,14 +510,16 @@ struct LotPacker {
lbs.clear(); lbs.clear();
Array lb = config.get_value("road", varname, Array()); Array lb = config.get_value("road", varname, Array());
int i, j; int i, j;
print_line("start building list");
for (i = 0; i < (int)lb.size(); i++) { for (i = 0; i < (int)lb.size(); i++) {
struct config_buildings cb; struct config_buildings cb;
cb.area = 0.0f; cb.area = 0.0f;
Array entries = lb[i]; Array entries = lb[i];
for (j = 0; j < entries.size(); j++) { for (j = 0; j < entries.size(); j++) {
String bname = entries[j]; String bname = entries[j];
print_line("building: " + bname);
cb.buildings.push_back(bname); cb.buildings.push_back(bname);
AABB aabb = get_building_type_aabb(bname); AABB aabb = bd()->get_scene_aabb(bname);
cb.area += aabb.size.x * aabb.size.z; cb.area += aabb.size.x * aabb.size.z;
print_line("config building: " + bname); print_line("config building: " + bname);
} }
@@ -525,6 +527,7 @@ struct LotPacker {
String::num(cb.area)); String::num(cb.area));
lbs.push_back(cb); lbs.push_back(cb);
} }
print_line("end building list");
struct lbsort { struct lbsort {
_FORCE_INLINE_ bool _FORCE_INLINE_ bool
operator()(const struct config_buildings &b1, operator()(const struct config_buildings &b1,
@@ -536,29 +539,45 @@ struct LotPacker {
lbs.sort_custom<struct lbsort>(); lbs.sort_custom<struct lbsort>();
lbs.invert(); lbs.invert();
} }
LotPacker(Vector2 cell_size) LotPacker(flecs::world &ecs)
: cell_size(cell_size) : cell_size(Vector2(16, 16))
{ {
BaseData::get_singleton()->get().component<LotGrid>(); ecs.module<LotPacker>();
BaseData::get_singleton()->get().component<LotBuildings>(); ecs.import <BuildingsData>();
BaseData::get_singleton()->get().component<PreOccupied>(); ecs.component<LotGrid>();
BaseData::get_singleton()->get().component<Industrial>(); ecs.component<PreOccupied>();
BaseData::get_singleton()->get().component<Commercial>(); ecs.component<Industrial>();
BaseData::get_singleton()->get().component<Residental>(); ecs.component<Commercial>();
ecs.component<Residental>();
struct PackerState {
int state;
};
ecs.component<PackerState>();
Error err = config.load("res://config/stream.conf"); Error err = config.load("res://config/stream.conf");
assert(err == OK); assert(err == OK);
get_building_list("lot_buildings_residental", ecs.system("MakeStuff")
.kind(flecs::OnUpdate)
.run([&](flecs::iter &it) {
if (!it.world().has<PackerState>())
it.world().set<PackerState>({ 0 });
if (it.world().has<PackerState>() &&
it.world().get<PackerState>()->state == 1) {
get_building_list(
"lot_buildings_residental",
lot_buildings_residental); lot_buildings_residental);
get_building_list("lot_buildings_commercial", get_building_list(
"lot_buildings_commercial",
lot_buildings_commercial); lot_buildings_commercial);
get_building_list("lot_buildings_industrial", get_building_list(
"lot_buildings_industrial",
lot_buildings_industrial); lot_buildings_industrial);
} }
static LotPacker *get_singleton() if (it.world().has<PackerState>())
{ it.world()
if (!singleton) .get_mut<PackerState>()
singleton = memnew(LotPacker(Vector2(16, 16))); ->state++;
return singleton; });
} }
static inline Rect2 aabb2rect(const AABB &aabb) static inline Rect2 aabb2rect(const AABB &aabb)
@@ -840,17 +859,17 @@ out_bad:
} }
bool tmp_found = false; bool tmp_found = false;
int office_count = 0; int office_count = 0;
// FIXME use components and find instead of direct lookup
AABB get_building_aabb(const String &key) const AABB get_building_aabb(const String &key) const
{ {
const struct BuildingsData::building &b = const struct BuildingsData::building &b =
bd()->get_building(key); bd()->get_building(key);
const AABB &building_aabb = bd()->building_aabbs[b.id]; return bd()->get_scene_aabb(b.id);
return building_aabb;
} }
// FIXME use components and find instead of direct lookup
AABB get_building_type_aabb(const String &building) const AABB get_building_type_aabb(const String &building) const
{ {
const AABB &building_aabb = bd()->building_aabbs[building]; return bd()->get_scene_aabb(building);
return building_aabb;
} }
Transform get_building_transform(const String &key) Transform get_building_transform(const String &key)
{ {
@@ -872,20 +891,34 @@ out_bad:
void create() void create()
{ {
int lot_count = 0; int lot_count = 0;
int i, j;
Vector<flecs::entity> entities;
Vector<flecs::entity> entities_all;
Vector<Rect2> vrects;
Vector<Transform> xforms;
List<String> buildings;
Vector<BuildingsData::building> vbuildings;
bd()->get_building_keys_list(&buildings);
BaseData::get_singleton() BaseData::get_singleton()
->get() ->get()
.query_builder<Lot>() .query_builder<Lot>()
.write<LotBuildings>() .read<PreOccupied>()
.write<PreOccupied>()
.build() .build()
.each([&](flecs::entity e, Lot &lot_) { .each([&](flecs::entity e, Lot &lot_) {
assert(e.get<Lot>()->polygon.points.size() > 0); assert(e.get<Lot>()->polygon.points.size() > 0);
List<String> buildings;
bd()->get_building_keys_list(&buildings);
List<String>::Element *be = buildings.front();
e.get_mut<Lot>()->polygon.update_aabb(); e.get_mut<Lot>()->polygon.update_aabb();
if (e.has<PreOccupied>()) if (!e.has<PreOccupied>())
return; entities.push_back(e);
});
BaseData::get_singleton()
->get()
.query_builder<Lot>()
.build()
.each([&](flecs::entity e, Lot &lot_) {
entities_all.push_back(e);
});
print_line("entities: " + itos(entities.size()));
List<String>::Element *be = buildings.front();
while (be) { while (be) {
const String &key = be->get(); const String &key = be->get();
const struct BuildingsData::building &b = const struct BuildingsData::building &b =
@@ -898,54 +931,59 @@ out_bad:
be = be->next(); be = be->next();
continue; continue;
} }
AABB lot_aabb = vbuildings.push_back(b);
e.get<Lot>()->polygon.aabb; Rect2 building_rect = get_rect_transformed(b.key);
Rect2 lot_rect = aabb2rect( vrects.push_back(building_rect);
e.get<Lot>()->polygon.aabb); Transform xform = get_building_transform(b.key);
Rect2 building_rect = xforms.push_back(xform);
get_rect_transformed(key); be = be->next();
Transform xform = }
get_building_transform(key); print_line("buildings: " + itos(vbuildings.size()));
Vector2 building_pos = Vector2( for (i = 0; i < entities.size(); i++) {
xform.origin.x, xform.origin.z); flecs::entity e = entities[i];
print_line("Lot: " + itos(i) + " " + String(e.name()));
assert(e.is_valid());
assert(e.get<Lot>()->polygon.points.size() > 0);
}
// assert(false);
for (i = 0; i < entities.size(); i++) {
flecs::entity e = entities[i];
print_line("Lot: " + itos(i) + " " + String(e.name()));
Lot *lot_ = e.get_mut<Lot>();
be = buildings.front();
AABB lot_aabb = e.get<Lot>()->polygon.aabb;
Rect2 lot_rect = aabb2rect(e.get<Lot>()->polygon.aabb);
for (j = 0; j < vbuildings.size(); j++) {
const struct BuildingsData::building &b =
vbuildings[j];
Rect2 building_rect = vrects[j];
Transform xform = xforms[j];
Vector2 building_pos =
Vector2(xform.origin.x, xform.origin.z);
bool intersects = false; bool intersects = false;
if (e.get<Lot>()->polygon.is_inside( if (e.get<Lot>()->polygon.is_inside(
building_rect)) building_rect))
intersects = true; intersects = true;
assert(e.get<Lot>()
->polygon.points.size() >
0);
if (intersects) { if (intersects) {
assert(e.get<Lot>()
->polygon.points
.size() > 0);
e.add<PreOccupied>(); e.add<PreOccupied>();
assert(e.get<Lot>()
->polygon.points
.size() > 0);
LotBuildings &lb = LotBuildings &lb =
e.ensure<LotBuildings>(); e.ensure<LotBuildings>();
lb.buildings.push_back( lb.buildings.push_back(
{ building_rect, key }); { building_rect, b.key });
Vector<Vector2> pt = Vector<Vector2> pt = get_polygon2(
get_polygon2( e.get<Lot>()->polygon.points);
e.get<Lot>()
->polygon
.points);
assert(pt.size() > 0); assert(pt.size() > 0);
lb.polygons.push_back(pt); lb.polygons.push_back(pt);
e.modified<LotBuildings>(); e.modified<LotBuildings>();
} }
be = be->next();
} }
}); }
BaseData::get_singleton() BaseData::get_singleton()
->get() ->get()
.query_builder<Lot, LotBuildings>() .query_builder<Lot, LotBuildings>()
.with<PreOccupied>() .with<PreOccupied>()
.build() .build()
.each([&](flecs::entity e, Lot &lot, LotBuildings &lb) { .each([&](flecs::entity e, Lot &lot, LotBuildings &lb) {
int i;
for (i = 0; i < lb.buildings.size(); i++) { for (i = 0; i < lb.buildings.size(); i++) {
const Pair<Rect2, String> &mp = const Pair<Rect2, String> &mp =
lb.buildings[i]; lb.buildings[i];
@@ -956,6 +994,9 @@ out_bad:
get_rect_transformed(key); get_rect_transformed(key);
Rect2 lot_rect = Rect2 lot_rect =
aabb2rect(lot.polygon.aabb); aabb2rect(lot.polygon.aabb);
assert(bd()->has_scene(
"office-exterior"));
print_line("building type: " + b.id);
if (b.id == "office-exterior") { if (b.id == "office-exterior") {
print_line("id: " + b.id); print_line("id: " + b.id);
print_line("xform: " + print_line("xform: " +
@@ -972,6 +1013,19 @@ out_bad:
} }
} }
}); });
for (i = 0; i < entities.size(); i++) {
flecs::entity e = entities[i];
if (e.has<PreOccupied>())
continue;
if ((lot_count % 5) == 0)
e.add<Industrial>();
else if (lot_count % 3 == 0)
e.add<Commercial>();
else
e.add<Residental>();
lot_count++;
}
#if 0
BaseData::get_singleton() BaseData::get_singleton()
->get() ->get()
.query_builder<Lot>() .query_builder<Lot>()
@@ -1080,14 +1134,12 @@ out_bad:
e.add<Residental>(); e.add<Residental>();
lot_count++; lot_count++;
}); });
#endif
assert(tmp_found); assert(tmp_found);
print_line("office_count: " + itos(office_count)); print_line("office_count: " + itos(office_count));
// assert(office_count > 1); // assert(office_count > 1);
BaseData::get_singleton() for (i = 0; i < entities_all.size(); i++)
->get() add_lot(entities_all[i]);
.query_builder<Lot>()
.build()
.each([&](flecs::entity e, Lot &lot) { add_lot(e); });
BaseData::get_singleton() BaseData::get_singleton()
->get() ->get()
.query_builder<Lot>() .query_builder<Lot>()
@@ -1292,31 +1344,42 @@ out_bad:
return lb->polygons; return lb->polygons;
} }
}; };
LotPacker *LotPacker::singleton = nullptr;
void Lot::pack() void Lot::pack()
{ {
LotPacker::get_singleton()->create(); BaseData::get_singleton()->get().get_mut<LotPacker>()->create();
LotPacker::get_singleton()->pack_lots(); BaseData::get_singleton()->get().get_mut<LotPacker>()->pack_lots();
BaseData::get_singleton()->get().modified<LotPacker>();
} }
void Lot::get_lot_data(flecs::entity e, List<Pair<AABB, String> > *lot_data) void Lot::get_lot_data(flecs::entity e, List<Pair<AABB, String> > *lot_data)
{ {
LotPacker::get_singleton()->get_lot_data(e, lot_data); BaseData::get_singleton()->get().get_mut<LotPacker>()->get_lot_data(
e, lot_data);
} }
void Lot::get_lot_rotations(flecs::entity e, List<Transform> *lot_xform) void Lot::get_lot_rotations(flecs::entity e, List<Transform> *lot_xform)
{ {
LotPacker::get_singleton()->get_lot_rotations(e, lot_xform); BaseData::get_singleton()->get().get_mut<LotPacker>()->get_lot_rotations(
e, lot_xform);
} }
void Lot::get_lot_buildings(flecs::entity e, void Lot::get_lot_buildings(flecs::entity e,
Vector<Pair<Rect2, String> > *lot_buildings) Vector<Pair<Rect2, String> > *lot_buildings)
{ {
LotPacker::get_singleton()->get_lot_buildings(e, lot_buildings); BaseData::get_singleton()->get().get_mut<LotPacker>()->get_lot_buildings(
e, lot_buildings);
} }
Vector<Vector<Vector2> > Lot::get_lot_polygons(flecs::entity e) Vector<Vector<Vector2> > Lot::get_lot_polygons(flecs::entity e)
{ {
return LotPacker::get_singleton()->get_lot_polygons(e); return BaseData::get_singleton()
->get()
.get_mut<LotPacker>()
->get_lot_polygons(e);
}
void Lot::import_packer(flecs::world &ecs)
{
ecs.import <LotPacker>();
} }

View File

@@ -33,6 +33,7 @@ struct Lot {
get_lot_buildings(flecs::entity e, get_lot_buildings(flecs::entity e,
Vector<Pair<Rect2, String> > *lot_buildings); Vector<Pair<Rect2, String> > *lot_buildings);
static Vector<Vector<Vector2> > get_lot_polygons(flecs::entity e); static Vector<Vector<Vector2> > get_lot_polygons(flecs::entity e);
static void import_packer(flecs::world &ecs);
}; };
#endif // ROAD_LOT_H_ #endif // ROAD_LOT_H_

View File

@@ -88,9 +88,10 @@ struct RoadLinesProcessing {
int debug_flags; int debug_flags;
DebugGeo *dbg; DebugGeo *dbg;
static ConfigFile config; static ConfigFile config;
RoadLinesProcessing() RoadLinesProcessing(flecs::world &ecs)
: dbg(nullptr) : dbg(nullptr)
{ {
ecs.module<RoadLinesProcessing>();
Error err = config.load("res://config/stream.conf"); Error err = config.load("res://config/stream.conf");
assert(err == OK); assert(err == OK);
} }
@@ -158,7 +159,7 @@ struct RoadLinesProcessing {
} }
bd()->create_building(b); bd()->create_building(b);
if (!bd()->has_scene(b.id)) if (!bd()->has_scene(b.id))
bd()->create_scene_data(b.id, b.key); return;
else else
bd()->add_scene_item(b.id, b.key); bd()->add_scene_item(b.id, b.key);
print_line("created building: " + b.key + " " + b.id); print_line("created building: " + b.key + " " + b.id);
@@ -919,7 +920,10 @@ out2:;
void find_closed_contours() void find_closed_contours()
{ {
int i, j; int i, j;
Contours *contours = Contours::get_singleton(); print_line("find_closed_contours");
assert(this);
Contours *contours =
BaseData::get_singleton()->get().get_mut<Contours>();
// RoadLinesProcessing *r = BaseData::get_singleton() ->get() .get_mut<RoadLinesProcessing>(); // RoadLinesProcessing *r = BaseData::get_singleton() ->get() .get_mut<RoadLinesProcessing>();
RoadLinesProcessing *r = this; RoadLinesProcessing *r = this;
if (r->nodes.size() == 0) if (r->nodes.size() == 0)
@@ -985,7 +989,7 @@ out2:;
} }
if (finished) { if (finished) {
int k; int k;
print_line("complete contour"); // print_line("complete contour");
std::vector<struct wedge *> wedge_contour; std::vector<struct wedge *> wedge_contour;
Vector<Vector2> polygon; Vector<Vector2> polygon;
for (k = 0; k < (int)contour.size(); k++) { for (k = 0; k < (int)contour.size(); k++) {
@@ -993,8 +997,8 @@ out2:;
wedges_ref[contour[k]]; wedges_ref[contour[k]];
wedge_contour.push_back( wedge_contour.push_back(
&wedges[wr.first][wr.second]); &wedges[wr.first][wr.second]);
print_line(itos(k) + ": " + // print_line(itos(k) + ": " +
itos(contour[k])); // itos(contour[k]));
Vector3 p1 = Vector3 p1 =
wedges[wr.first][wr.second].p[0]; wedges[wr.first][wr.second].p[0];
Vector3 p2 = Vector3 p2 =
@@ -1007,8 +1011,7 @@ out2:;
used.push_back(contour[k]); used.push_back(contour[k]);
} }
if (Geometry::is_polygon_clockwise(polygon)) if (Geometry::is_polygon_clockwise(polygon))
contours->get_singleton() contours->wedge_contours.push_back(
->wedge_contours.push_back(
wedge_contour); wedge_contour);
contour.clear(); contour.clear();
contour_count++; contour_count++;
@@ -1018,8 +1021,6 @@ out2:;
if (base >= (int)wedges_ref.size()) if (base >= (int)wedges_ref.size())
break; break;
} }
contours->build();
contours->debug();
} }
~RoadLinesProcessing() ~RoadLinesProcessing()
{ {
@@ -1032,27 +1033,10 @@ out2:;
{ {
return debug_flags; return debug_flags;
} }
void road_setup() void road_setup2()
{ {
int i, j; int i, j;
RoadLinesData *rld = RoadLinesData::get_singleton(); RoadLinesData *rld = RoadLinesData::get_singleton();
std::vector<Vector3> road_lines_nodes;
std::unordered_map<uint32_t, std::vector<Vector3> >
road_lines_nodes_hash;
road_lines_nodes.clear();
road_lines_nodes_hash.clear();
rld->update_line_edges();
test_lines();
calculate_lot_depths();
rld->set_debug_flags(debug_flags);
rld->process_lines(road_lines_nodes_hash, road_lines_nodes);
create_nodes(road_lines_nodes);
create_edges();
optimize_nodes(16.0f);
sort_neighbors();
wedges.clear();
build_wedges(wedges);
find_closed_contours();
// update_lot_depths(); // update_lot_depths();
ImmediateGeometry *d = rld->get_debug_node(); ImmediateGeometry *d = rld->get_debug_node();
d->clear(); d->clear();
@@ -1114,7 +1098,6 @@ out2:;
} }
d->end(); d->end();
} }
create_structures();
print_line("ROAD SETUP DONE"); print_line("ROAD SETUP DONE");
} }
}; };
@@ -1703,7 +1686,9 @@ public:
out_surfaces[h], 0.0f); out_surfaces[h], 0.0f);
} else if (k == params.nlanes + 1 && } else if (k == params.nlanes + 1 &&
mside1.lot > 0) { /* lot */ mside1.lot > 0) { /* lot */
if (!Contours::get_singleton() if (!BaseData::get_singleton()
->get()
.get<Contours>()
->is_in_closed_contour( ->is_in_closed_contour(
&wedge)) &wedge))
build_split_segment( build_split_segment(
@@ -1779,7 +1764,9 @@ public:
"m2: " + "m2: " +
String::num( String::num(
mside2.lot_depth_eff)); mside2.lot_depth_eff));
if (!Contours::get_singleton() if (!BaseData::get_singleton()
->get()
.get<Contours>()
->is_in_closed_contour( ->is_in_closed_contour(
&wedge)) &wedge))
build_split_segment( build_split_segment(
@@ -1864,25 +1851,51 @@ public:
nodes_mi.push_back(mi); nodes_mi.push_back(mi);
} }
} }
RoadMeshProcessing() RoadMeshProcessing(flecs::world &ecs)
: road_mgroup(nullptr) : road_mgroup(nullptr)
{ {
BaseData::get_singleton()->get().ensure<RoadLinesProcessing>(); ecs.module<RoadMeshProcessing>();
ecs.import <RoadLinesProcessing>();
} }
}; };
void RoadProcessing::road_setup(Node *target, int debug_flags) void RoadProcessing::road_setup(Node *target, int debug_flags)
{ {
BaseData::get_singleton()->get().ensure<RoadLinesProcessing>(); RoadLinesData *rld = RoadLinesData::get_singleton();
BaseData::get_singleton()->get().ensure<RoadMeshProcessing>(); int i, j;
RoadLinesProcessing *r = RoadLinesProcessing *r =
BaseData::get_singleton()->get().get_mut<RoadLinesProcessing>(); BaseData::get_singleton()->get().get_mut<RoadLinesProcessing>();
r->set_debug_flags(debug_flags); r->set_debug_flags(debug_flags);
r->road_setup(); std::vector<Vector3> road_lines_nodes;
std::unordered_map<uint32_t, std::vector<Vector3> >
road_lines_nodes_hash;
road_lines_nodes.clear();
road_lines_nodes_hash.clear();
rld->update_line_edges();
r->test_lines();
r->calculate_lot_depths();
rld->set_debug_flags(debug_flags);
rld->process_lines(road_lines_nodes_hash, road_lines_nodes);
r->create_nodes(road_lines_nodes);
r->create_edges();
r->optimize_nodes(16.0f);
r->sort_neighbors();
r->wedges.clear();
r->build_wedges(r->wedges);
print_line("find_closed_contours");
r->find_closed_contours();
Contours *contours =
BaseData::get_singleton()->get().get_mut<Contours>();
contours->build();
Lot::pack();
contours->debug();
BaseData::get_singleton()->get().modified<Contours>();
r->create_structures();
BaseData::get_singleton() BaseData::get_singleton()
->get() ->get()
.get_mut<RoadMeshProcessing>() .get_mut<RoadMeshProcessing>()
->create_road_meshes(target); ->create_road_meshes(target);
r->road_setup2();
} }
void RoadProcessing::remove_road_meshes(Node *target) void RoadProcessing::remove_road_meshes(Node *target)
@@ -1900,7 +1913,6 @@ void RoadProcessing::load_data()
ConfigFile config; ConfigFile config;
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");
BaseData::get_singleton()->get().ensure<RoadMeshProcessing>();
RoadMeshProcessing *rmp = RoadMeshProcessing *rmp =
BaseData::get_singleton()->get().get_mut<RoadMeshProcessing>(); BaseData::get_singleton()->get().get_mut<RoadMeshProcessing>();
assert(rmp); assert(rmp);
@@ -2025,3 +2037,15 @@ void RoadProcessing::cleanup()
BaseData::get_singleton()->get().remove<RoadLinesProcessing>(); BaseData::get_singleton()->get().remove<RoadLinesProcessing>();
BaseData::get_singleton()->get().remove<RoadMeshProcessing>(); BaseData::get_singleton()->get().remove<RoadMeshProcessing>();
} }
RoadProcessing::RoadProcessing(flecs::world &ecs)
{
ecs.module<RoadProcessing>();
ecs.import <Contours>();
ecs.import <RoadLinesProcessing>();
ecs.import <RoadMeshProcessing>();
}
RoadProcessing::~RoadProcessing()
{
}

View File

@@ -1,5 +1,6 @@
#ifndef ROAD_LINES_PROCESSING_H_ #ifndef ROAD_LINES_PROCESSING_H_
#define ROAD_LINES_PROCESSSING_H_ #define ROAD_LINES_PROCESSSING_H_
#include <flecs.h>
class Node; class Node;
class ImmediateGeometry; class ImmediateGeometry;
class RoadProcessing { class RoadProcessing {
@@ -8,5 +9,7 @@ public:
static void remove_road_meshes(Node *target); static void remove_road_meshes(Node *target);
static void load_data(); static void load_data();
static void cleanup(); static void cleanup();
RoadProcessing(flecs::world &ecs);
virtual ~RoadProcessing();
}; };
#endif #endif

View File

@@ -53,7 +53,7 @@ void StreamWorld::create_tilemap()
void StreamWorld::update_view() void StreamWorld::update_view()
{ {
int i, j; int i;
ERR_FAIL_COND_MSG(!initialized, ERR_FAIL_COND_MSG(!initialized,
"The Stream object is incorrectly initialized"); "The Stream object is incorrectly initialized");
if (!viewer || !terrain) { if (!viewer || !terrain) {
@@ -84,6 +84,12 @@ void StreamWorld::update_view()
ERR_FAIL_COND_MSG(!t, "VoxelLodTerrain was not found"); ERR_FAIL_COND_MSG(!t, "VoxelLodTerrain was not found");
viewer = v; viewer = v;
terrain = t; terrain = t;
assert(terrain);
assert(viewer);
BaseData::get_singleton()
->get()
.set<StreamWorld::components::WorldData>(
{ viewer, terrain });
viewer->connect("tree_exiting", this, "viewer_dead"); viewer->connect("tree_exiting", this, "viewer_dead");
terrain->connect("tree_exiting", this, "terrain_dead"); terrain->connect("tree_exiting", this, "terrain_dead");
current_x = world_extent + 1; current_x = world_extent + 1;
@@ -218,7 +224,7 @@ void StreamWorld::unload_building(const String &key)
void StreamWorld::update_items() void StreamWorld::update_items()
{ {
List<String> keys; List<String> keys;
data()->get_scene_keys_list(&keys); BuildingsData::get_scene_keys_list(&keys);
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();
@@ -260,6 +266,7 @@ void StreamWorld::remove_building(const String &key)
VoxelLodTerrain *StreamWorld::get_terrain() VoxelLodTerrain *StreamWorld::get_terrain()
{ {
assert(terrain);
return terrain; return terrain;
} }
@@ -316,7 +323,7 @@ void StreamWorld::run_command(const String &command,
String new_type = args[1]; String new_type = args[1];
Dictionary buildings_data = Dictionary buildings_data =
config.get_value("buildings", "building_data"); config.get_value("buildings", "building_data");
if (!data()->building_data.has(new_type)) { if (!data()->has_scene(new_type)) {
print_error("unknown building type: " + new_type); print_error("unknown building type: " + new_type);
return; return;
} }
@@ -403,7 +410,7 @@ void StreamWorld::run_command(const String &command,
create_tilemap(); create_tilemap();
#endif #endif
update_view(); update_view();
data()->scene_update(); BuildingsData::scene_update();
update_items(); update_items();
#if 0 #if 0
data()->for_each_building( data()->for_each_building(
@@ -453,7 +460,17 @@ void StreamWorld::_notification(int which)
if (current_scene) if (current_scene)
current_scene = get_tree()->get_root(); current_scene = get_tree()->get_root();
} }
#if 0
BaseData::get_singleton()
->get()
.add<StreamWorld::components::Initialized>();
#endif
ERR_FAIL_COND_MSG(!current_scene, "No current scene"); ERR_FAIL_COND_MSG(!current_scene, "No current scene");
if (Engine::get_singleton()->is_editor_hint())
break;
set_process(true);
#if 0
BaseData::get_singleton()->get().defer_suspend();
RoadProcessing::road_setup(this, 0); RoadProcessing::road_setup(this, 0);
#if 0 #if 0
data()->for_each_building( data()->for_each_building(
@@ -471,6 +488,7 @@ void StreamWorld::_notification(int which)
#if 0 #if 0
create_tilemap(); create_tilemap();
#endif #endif
BaseData::get_singleton()->get().defer_resume();
set_process(true); set_process(true);
if (Engine::get_singleton()->is_editor_hint()) if (Engine::get_singleton()->is_editor_hint())
break; break;
@@ -480,12 +498,14 @@ void StreamWorld::_notification(int which)
update_view(); update_view();
assert(terrain); assert(terrain);
assert(viewer); assert(viewer);
#endif
} }
break; break;
case NOTIFICATION_EXIT_TREE: case NOTIFICATION_EXIT_TREE:
frame_count = 0; frame_count = 0;
break; break;
case NOTIFICATION_PROCESS: { case NOTIFICATION_PROCESS: {
#if 0
if (frame_count % 60 == 0) { if (frame_count % 60 == 0) {
float fmon = Performance::get_singleton()->get_monitor( float fmon = Performance::get_singleton()->get_monitor(
Performance::RENDER_DRAW_CALLS_IN_FRAME); Performance::RENDER_DRAW_CALLS_IN_FRAME);
@@ -497,6 +517,12 @@ void StreamWorld::_notification(int which)
update_view(); update_view();
data()->scene_update(); data()->scene_update();
update_items(); update_items();
#endif
if (road_setup_needed && !road_setup_complete) {
road_setup();
road_setup_needed = false;
road_setup_complete = true;
}
} break; } break;
} }
@@ -525,14 +551,30 @@ StreamWorld::StreamWorld()
, view_distance(0) , view_distance(0)
, initialized(false) , initialized(false)
, frame_count(0) , frame_count(0)
, road_setup_needed(false)
, road_setup_complete(false)
, count_shit(0)
{ {
BaseData::get_singleton()->get().component<BuildingsData>(); BaseData::get_singleton()->get().import <BuildingsData>();
BaseData::get_singleton()->get().import <RoadProcessing>();
BaseData::get_singleton()
->get()
.component<StreamWorld::components::RoadSetupDone>();
BaseData::get_singleton()
->get()
.component<StreamWorld::components::RoadSetupNeeded>();
BaseData::get_singleton()
->get()
.component<StreamWorld::components::Initialized>();
BaseData::get_singleton()
->get()
.component<StreamWorld::components::WorldData>();
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");
BaseData::get_singleton()->get().ensure<BuildingsData>();
RoadProcessing::load_data(); RoadProcessing::load_data();
world_extent = config.get_value("world", "world_extent"); world_extent = config.get_value("world", "world_extent");
tile_size = config.get_value("world", "tile_size"); tile_size = config.get_value("world", "tile_size");
view_distance = config.get_value("world", "view_distance");
ERR_FAIL_COND_MSG(tile_size <= 0 || world_extent <= 0 || ERR_FAIL_COND_MSG(tile_size <= 0 || world_extent <= 0 ||
world_extent <= tile_size, world_extent <= tile_size,
"Failed to configure world"); "Failed to configure world");
@@ -548,11 +590,40 @@ StreamWorld::StreamWorld()
map_it++; map_it++;
} }
#endif #endif
view_distance = config.get_value("world", "view_distance");
BaseData::get_singleton()->get().import <NPC>(); BaseData::get_singleton()->get().import <NPC>();
flecs::entity npcctrl = BaseData::get_singleton()->get().entity(); flecs::entity npcctrl = BaseData::get_singleton()->get().entity();
npcctrl.set<NPC::NPCControl>({ NPC::NPCControl::CMD_PRESIM }); npcctrl.set<NPC::NPCControl>({ NPC::NPCControl::CMD_PRESIM });
initialized = true; initialized = true;
flecs::log::set_level(-3);
BaseData::get_singleton()
->get()
.system("WaitForUpdate")
.kind(flecs::OnUpdate)
.run([&](flecs::iter &it) {
if (road_setup_complete)
return;
if (!road_setup_needed && !road_setup_complete)
road_setup_needed = true;
#if 0
if (it.world()
.has<StreamWorld::components::RoadSetupDone>())
return;
if (it.world()
.has<StreamWorld::components::Initialized>() &&
!it.world()
.has<StreamWorld::components::
RoadSetupNeeded>()) {
road_setup_needed = true;
it.world()
.add<StreamWorld::components::
RoadSetupNeeded>();
} else if (it.world()
.has<BuildingsData::CScenesLoaded>())
it.world()
.add<StreamWorld::components::
Initialized>();
#endif
});
} }
void StreamWorld::cleanup() void StreamWorld::cleanup()
{ {
@@ -592,3 +663,16 @@ void StreamWorld::undo()
update_view(); update_view();
update_items(); update_items();
} }
void StreamWorld::road_setup()
{
assert(count_shit == 0);
RoadProcessing::road_setup(this, 0);
update_view();
data()->scene_update();
update_items();
update_view();
count_shit++;
assert(terrain);
assert(viewer);
}

View File

@@ -37,6 +37,9 @@ private:
bool initialized; bool initialized;
int current_x, current_z; int current_x, current_z;
int frame_count; int frame_count;
bool road_setup_needed;
bool road_setup_complete;
int count_shit;
void _notification(int which); void _notification(int which);
// void create_tilemap(); // void create_tilemap();
void update_view(); void update_view();
@@ -51,10 +54,20 @@ private:
void remove_generated_stuff(); void remove_generated_stuff();
void place_zebras(); void place_zebras();
void undo(); void undo();
void road_setup();
static void _bind_methods(); static void _bind_methods();
public: public:
struct components {
struct Initialized {};
struct WorldData {
VoxelViewer *viewer;
VoxelLodTerrain *terrain;
};
struct RoadSetupNeeded {};
struct RoadSetupDone {};
};
VoxelLodTerrain *get_terrain(); VoxelLodTerrain *get_terrain();
void run_command(const String &command, const Vector<Variant> &args); void run_command(const String &command, const Vector<Variant> &args);
StreamWorld(); StreamWorld();

View File

@@ -34,8 +34,14 @@ void TerrainEditor::exit()
void TerrainEditor::update(float delta) void TerrainEditor::update(float delta)
{ {
if (!active) if (!active) {
if (BaseData::get_singleton()
->get()
.has<StreamWorld::components::WorldData>())
activate(); activate();
else
return;
}
if (!cursor_enabled && get_camera_mode() == 3) { if (!cursor_enabled && get_camera_mode() == 3) {
cursor_enabled = true; cursor_enabled = true;
get_as_node<Spatial>(cursor_name)->show(); get_as_node<Spatial>(cursor_name)->show();
@@ -382,7 +388,7 @@ end:;
"building elevation: " + "building elevation: " +
String::num(imgmapper->get_height_full( String::num(imgmapper->get_height_full(
b.xform.origin))); b.xform.origin)));
AABB aabb = bd()->building_aabbs[b.id]; AABB aabb = bd()->get_scene_aabb(b.id);
print_line("building AABB: " + print_line("building AABB: " +
(aabb.operator String())); (aabb.operator String()));
float max_elevation_c = -Math_INF, float max_elevation_c = -Math_INF,

View File

@@ -614,6 +614,7 @@ void MainTabs::_notification(int which)
std::vector<Variant> args_data = { std::vector<Variant> args_data = {
items[i].header items[i].header
}; };
assert(items[i].header.length() > 0);
ui_field::ui_field_builder(this, tab, ui_field::ui_field_builder(this, tab,
"l_p{v{}}", "l_p{v{}}",
args_data.data(), args_data.data(),

View File

@@ -40,9 +40,10 @@ void ui_field::ui_field_builder(Node *owner, Node *parent, const String format,
.get<WorldEditor::components::buildings_editor_node>() .get<WorldEditor::components::buildings_editor_node>()
->node; ->node;
assert(owner->is_inside_tree()); assert(owner->is_inside_tree());
for (i = 0; i < format.length(); i++) { CharString cformat = format.ascii();
const char *fmt = format.ascii().ptr(); for (i = 0; i < format.ascii().length(); i++) {
int c = fmt[i]; assert(i < cformat.length());
int c = (int)cformat.ptr()[i];
// printf("character: %c : argp: %d\n", (char)c, argp); // printf("character: %c : argp: %d\n", (char)c, argp);
switch (c) { switch (c) {
case '{': case '{':