diff --git a/Makefile b/Makefile index 6972a4c..52b37d5 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,14 @@ EDITOR_PLATFORM=x11es EDITOR2_PLATFORM=x11 DEMO_PLATFORMS=x11 x11es 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_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-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 define build_godot $(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-server-main: $(SERVER) godot-editor-main: $(EDITOR) $(EDITOR2) +godot-editor-debug: $(EDITOR_DBG) $(EDITOR2_DBG) #$(SERVER): patch # cd src/godot; \ # 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,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,debug,yes,$(EDITOR2_DBG),patch)) 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 sed -e 's/ERR_FAIL_COND_V(-1 == p_task->root_bone, false);//g' -i ./src/godot/scene/animation/skeleton_ik.cpp diff --git a/src/flecs b/src/flecs index fa9bfa0..99c8226 160000 --- a/src/flecs +++ b/src/flecs @@ -1 +1 @@ -Subproject commit fa9bfa08d7074727bad72362a6edf9f7ee5e3dc1 +Subproject commit 99c822674a2ae25e29dc01990f91e34383616096 diff --git a/src/godot b/src/godot index 9fccb6b..bec38d9 160000 --- a/src/godot +++ b/src/godot @@ -1 +1 @@ -Subproject commit 9fccb6b2d7fba4373c7b95e467f1ac44b0ff0cda +Subproject commit bec38d9248b764c60d6e4ca7dc43046450d405c9 diff --git a/src/meshoptimizer b/src/meshoptimizer index 515e92f..5712395 160000 --- a/src/meshoptimizer +++ b/src/meshoptimizer @@ -1 +1 @@ -Subproject commit 515e92fb70e8c187744b84c93095cedebfd662dc +Subproject commit 57123951b57eb38ab219eaa188ed73cc917f728f diff --git a/src/modules/stream/buildings_data.cpp b/src/modules/stream/buildings_data.cpp index 583be85..902a26d 100644 --- a/src/modules/stream/buildings_data.cpp +++ b/src/modules/stream/buildings_data.cpp @@ -15,13 +15,7 @@ #include "base_data.h" #include "buildings_data.h" -static ConfigFile config; -static ConfigFile custom_layouts; -struct scene_data { - Ref packed_scene; - String path; - Ref loader; -}; +ConfigFile BuildingsData::config; static flecs::world &ecs() { @@ -37,250 +31,12 @@ static flecs::entity lookup(const char *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 key) -{ - int i; - const std::vector &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()) - eb.add(); - } - } -} -#endif - -BuildingsData::BuildingsData() - : undo_log_size(64) -{ - flecs::world ecs_ = ecs(); - ecs_.component(); - ecs_.component(); - ecs_.component(); - ecs_.component(); - ecs_.component(); - ecs_.component(); - ecs_.component(); - bool deferred = ecs_.is_deferred(); - if (deferred) - ecs_.defer_suspend(); - ecs_.set({ 0 }); - ecs_.set({}); - assert(ecs_.has()); - load_data(); - ecs_.query_builder().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()->created_entities)); - assert(ecs().get()->created_entities > 0); - fill_door_locations(); - build_building_aabbs(); - ecs_.observer() - .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() - .event(flecs::OnAdd) - .with() - .run([&](flecs::iter &it) { - flecs::query q = - it.world() - .query_builder() - .with() - .build(); - if (it.next()) { - flecs::entity qe = it.entity(0); - q.each([qe](flecs::entity e, - const CBuildingData &d) { - if (e != qe) - e.remove(); - }); - 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()) { - int old_x = it.world().get()->tile_x; - int old_z = it.world().get()->tile_z; - if (old_x == tile_x && old_z == tile_z) - need_update = false; - } - it.world().set({ xform, tile_x, tile_z }); - if (need_update) - return; - if (!it.world().has()) - return; - CBuildingTileData *td = it.world().get_mut(); - it.world() - .query_builder() - .without() - .without() - .with() - .build() - .each([&](flecs::entity e, const CBuildingData &bd) { - const CBuildingTile *bt = - e.get(); - std::tuple 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(); - } - } - }); - it.world() - .query_builder() - .with() - .with() - .without() - .build() - .each([&](flecs::entity e, const CBuildingData &bd) { - const CBuildingTile *bt = - e.get(); - std::tuple 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(); - } - }); - }); - ecs_.system("LoadData") - .kind(flecs::OnUpdate) - .without() - .with() - .write() - .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(); - e.remove(); - e.world().defer_resume(); - }); - ecs_.system("UnloadData") - .kind(flecs::OnUpdate) - .with() - .with() - .write() - .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(); - e.remove(); - }); -} - -BuildingsData::~BuildingsData() -{ -} - void BuildingsData::build_building_aabbs() { - building_aabbs.clear(); - List keys; - building_data.get_key_list(&keys); - List::Element *e = keys.front(); - while (e) { - Error err; - const String &path = building_data[e->get()]; - Ref ps = - ResourceLoader::load(path, "PackedScene", true, &err); - if (err == OK && ps.is_valid()) { - AABB aabb; - Node *scene = ps->instance(); - List queue; - queue.push_back(scene); - while (!queue.empty()) { - int i; - Node *item = queue.front()->get(); - queue.pop_front(); - MeshInstance *mi = - Object::cast_to(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(); - } + // building_aabbs.clear(); + // List keys; + // building_data.get_key_list(&keys); + // List::Element *e = keys.front(); } void BuildingsData::update_building_transform(const String &key, @@ -301,7 +57,7 @@ bool BuildingsData::has_building(const String &key) 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; String rkey; @@ -318,8 +74,7 @@ String BuildingsData::get_closest_building(const Transform &xform) const }); return rkey; } -flecs::entity -BuildingsData::get_closest_building_entity(const Transform &xform) const +flecs::entity BuildingsData::get_closest_building_entity(const Transform &xform) { float dst = Math_INF; String rkey; @@ -500,6 +255,7 @@ void BuildingsData::load_data() assert(ecs().has()); Error result = config.load("res://config/stream.conf"); ERR_FAIL_COND_MSG(result != OK, "Failed to load config"); +#if 0 Dictionary buildings_data = config.get_value("buildings", "building_data"); List keys; @@ -507,7 +263,23 @@ void BuildingsData::load_data() List::Element *e = keys.front(); while (e) { 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({ sd }); + pending_scene.insert(path); + assert(se.get_mut()); e = e->next(); } e = keys.front(); @@ -516,12 +288,14 @@ void BuildingsData::load_data() // print_line(key + ": " + buildings_data[key]); e = e->next(); } +#endif String buildings_path = config.get_value("buildings", "buildings_path"); read_buildings_json(buildings_path); } void BuildingsData::checkpoint() { +#if 0 struct checkpoint_data cp; cp.building_data = building_data; cp.buildings.clear(); @@ -531,9 +305,11 @@ void BuildingsData::checkpoint() undo_log.push_back(cp); while ((int)undo_log.size() > undo_log_size) undo_log.erase(undo_log.begin()); +#endif } void BuildingsData::undo() { +#if 0 int i; struct checkpoint_data cp = *undo_log.end(); building_data = cp.building_data; @@ -545,98 +321,44 @@ void BuildingsData::undo() flecs::entity e = ecs().entity(ename.ascii().ptr()); e.set({ cp.buildings[i] }); } +#endif } -void BuildingsData::fill_door_locations() -{ - /* -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 keys; - building_data.get_key_list(&keys); - List::Element *e = keys.front(); - while (e) { - Error err; - const String &path = building_data[e->get()]; - Ref ps = - ResourceLoader::load(path, "PackedScene", true, &err); - if (err == OK && ps.is_valid()) { - Vector doors; - Node *scene = ps->instance(); - List 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(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 *keys) const +void BuildingsData::get_scene_keys_list(List *keys) { ecs().each([keys](flecs::entity e, const CSceneData &d) { 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()); - return e.is_valid(); + return e.is_valid() && e.has(); } -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().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() || !e.has()) + print_error("not found: " + key); + assert(e.has()); + + return e.get()->aabb; +} + +flecs::entity BuildingsData::get_building_entity(const String &key) { flecs::query_builder qb = ecs().query_builder(); @@ -689,6 +411,11 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey) { flecs::entity e = ecs().lookup(key.ascii().ptr()); assert(e.is_valid()); + assert(e.has()); + flecs::entity be = get_building_entity(bkey); + assert(be.is_valid()); + assert(be.has()); + const CBuildingData *b = be.get(); CSceneData *d = e.get_mut(); assert(d); String ename = "bi:" + bkey; @@ -697,54 +424,46 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey) if (ce.is_valid()) ce.destruct(); ce = ecs().entity(ename.ascii().ptr()).child_of(e); - ce.set({ bkey, nullptr }); + Ref 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(ps->instance()); + assert(scene); + where->call_deferred("add_child", scene); + scene->set_transform(b->building.xform); + ce.set({ bkey, scene }); + } else + ce.set({ bkey, nullptr }); // print_line("child name: " + String(ce.name())); } -void BuildingsData::create_scene_data(const String &key, const String &bkey) -{ - 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({ sd }); - pending_scene.insert(path); - assert(e.get_mut()); - 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({ bkey, nullptr }); - // print_line("child name: " + String(ce.name())); - } -} - -Ref BuildingsData::scene_get_packed_scene(const String &key) const +Ref BuildingsData::scene_get_packed_scene(const String &key) { flecs::entity e = ecs().lookup(key.ascii().ptr()); + if (!e.has()) + return Ref(); + assert(e.is_valid()); + assert(e.has()); + assert(e.has()); + assert(e.get()); + assert(e.get()->sp.packed_scene.is_valid()); + if (!e.is_valid()) return Ref(); if (!e.get()) return Ref(); + if (!e.get()) + return Ref(); assert(e.is_valid()); - const CSceneData *d = e.get(); + const CScenePack *d = e.get(); 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()); 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)); return result; } -List BuildingsData::scene_get_items(const String &key) const +List BuildingsData::scene_get_items(const String &key) { List ret; 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->key == bkey); bi->node = node; + ce.modified(); } -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()); 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()); return ce.is_valid(); } -Node *BuildingsData::get_scene_item_node(const String &key, - const String &bkey) const +Node *BuildingsData::get_scene_item_node(const String &key, const String &bkey) { flecs::entity e = ecs().lookup(key.ascii().ptr()); assert(e.is_valid()); @@ -823,6 +542,8 @@ Node *BuildingsData::get_scene_item_node(const String &key, assert(d); String ename = "bi:" + bkey; flecs::entity ce = e.lookup(ename.ascii().ptr()); + if (!ce.is_valid()) /* no instance */ + return nullptr; assert(ce.is_valid()); CBuildingInstance *bi = ce.get_mut(); assert(bi); @@ -836,7 +557,7 @@ void BuildingsData::save_buildings() 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 qb = ecs().query_builder(); @@ -851,29 +572,6 @@ Node *BuildingsData::item_nodes_get_node(const String &key) const 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(); - assert(d); - assert(d->sd.loader.is_valid()); - Error err = d->sd.loader->poll(); - if (err == ERR_FILE_EOF || err == OK) { - Ref sc = d->sd.loader->get_resource(); - d->sd.packed_scene = sc; - print_line("Loaded scene: " + d->sd.path + " OK"); - return OK; - } else { - print_error("Could not load the resource :( " + - d->sd.path + " " + itos(err)); - return err; - } - } - return FAILED; -} - void BuildingsData::scene_update() { List keys; @@ -885,12 +583,11 @@ void BuildingsData::scene_update() e = e->next(); continue; } - scene_loader_poll(key); e = e->next(); } } -int BuildingsData::get_building_count() const +int BuildingsData::get_building_count() { flecs::query q = ecs().query(); @@ -906,20 +603,24 @@ int BuildingsData::get_building_count() const 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()->building; -} - struct BuildingsData::building & BuildingsData::get_building(const String &building_key) { String ename = "base:" + building_key; flecs::entity e = lookup(ename); + if (!e.is_valid()) { + // print_error("bad building: " + ename); + e = ecs().query_builder().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()); return e.get_mut()->building; } diff --git a/src/modules/stream/buildings_data.h b/src/modules/stream/buildings_data.h index 41433c1..74150cd 100644 --- a/src/modules/stream/buildings_data.h +++ b/src/modules/stream/buildings_data.h @@ -3,10 +3,14 @@ #include #include #include +#include +#include #include class PackedScene; class ResourceInteractiveLoader; class BuildingsData { + static ConfigFile config; + public: /* Per-building information */ struct building { @@ -23,6 +27,15 @@ public: Dictionary to_dict() const; String line_name; }; + struct scene_data { + String key; + String path; + }; + struct scene_pack { + Ref packed_scene; + Ref loader; + }; + Set pending_scene; /* Scene objects data */ //private: @@ -31,6 +44,9 @@ public: struct CBuildingData { struct BuildingsData::building building; }; + struct CBuildingSceneLoaded {}; + struct CBuildingSceneLoad {}; + struct CBuildingSceneUnload {}; struct CBTypeResidental {}; struct CBCustomLayout { int size; @@ -65,39 +81,54 @@ public: struct CBuildingUnload {}; struct CBuildingLoaded {}; struct CBuildingEdited {}; + struct CSceneData { + struct scene_data sd; + }; + struct CScenePack { + struct scene_pack sp; + }; + struct CScenePackLoaded {}; + struct CSceneDoors { + Vector doors; + }; + struct CSceneAABB { + AABB aabb; + }; + struct CScenesLoaded {}; /* all scenes loaded */ + struct CBuildingInstance { + String key; + Node *node; + }; + struct CBuildingInstanced {}; public: - void get_scene_keys_list(List *keys) const; - bool has_scene(const String &key) const; - void remove_scene_item(const String &key, const String &bkey); - void add_scene_item(const String &key, const String &bkey); - void create_scene_data(const String &key, const String &bkey); - Ref scene_get_packed_scene(const String &key) const; - int scene_get_item_count(const String &key) const; + static void get_scene_keys_list(List *keys); + static bool has_scene(const String &key); + static AABB get_scene_aabb(const String &key); + static void remove_scene_item(const String &key, const String &bkey); + static void add_scene_item(const String &key, const String &bkey); + static Ref scene_get_packed_scene(const String &key); + static int scene_get_item_count(const String &key); // String scene_get_item(const String &key, int index) const; - List scene_get_items(const String &key) const; - void set_scene_item_node(const String &key, const String &bkey, - Node *node); - bool has_scene_item(const String &key, const String &bkey) const; - Node *get_scene_item_node(const String &key, const String &bkey) const; - void save_buildings(); + static List scene_get_items(const String &key); + static void set_scene_item_node(const String &key, const String &bkey, + Node *node); + static bool has_scene_item(const String &key, const String &bkey); + static Node *get_scene_item_node(const String &key, const String &bkey); + static void save_buildings(); public: - Node *item_nodes_get_node(const String &key) const; - -private: - Error scene_loader_poll(const String &key); + static Node *item_nodes_get_node(const String &key); public: - void scene_update(); + static void scene_update(); /* Path for each building type */ - HashMap building_data; - HashMap > building_doors; - HashMap building_aabbs; + // HashMap building_data; + // HashMap > building_doors; + // HashMap building_aabbs; public: - struct building &get_building(const String &building_key); - const struct building &get_building(const String &building_key) const; + static struct building &get_building(const String &building_key); struct callme { class H {}; H *obj; @@ -126,8 +157,9 @@ public: void *)>(obj); } - void for_each_building(struct callme &c); - template void for_each_building(Func &&func, void *data) + static void for_each_building(struct callme &c); + template + static void for_each_building(Func &&func, void *data) { List keys; get_building_keys_list(&keys); @@ -137,40 +169,41 @@ public: e = e->next(); } } - void for_each_building(void (*func)(const String &key, void *data), - void *data); - void get_building_keys_list(List *keys); + static void for_each_building(void (*func)(const String &key, + void *data), + void *data); + static void get_building_keys_list(List *keys); - int get_building_count() const; - String create_building(const Dictionary &dict); - String create_building(const struct building &building); - String create_building(const struct building *building); - bool destroy_building(const String &key); + static int get_building_count(); + static String create_building(const Dictionary &dict); + static String create_building(const struct building &building); + static String create_building(const struct building *building); + static bool destroy_building(const String &key); struct checkpoint_data { HashMap building_data; std::vector buildings; }; std::vector undo_log; int undo_log_size; - BuildingsData(); + BuildingsData(flecs::world &e); virtual ~BuildingsData(); public: - void read_buildings_json(const String &buildings_path); - void save_buildings_json(const String &buildings_path); - void filter_generated_stuff(); - void remove_generated_stuff(); + static void read_buildings_json(const String &buildings_path); + static void save_buildings_json(const String &buildings_path); + static void filter_generated_stuff(); + static void remove_generated_stuff(); void load_data(); void checkpoint(); void undo(); - void fill_door_locations(); - void build_building_aabbs(); - void update_building_transform(const String &key, - const Transform &xform); - bool has_building(const String &key); - String get_closest_building(const Transform &xform) const; - flecs::entity get_closest_building_entity(const Transform &xform) const; - flecs::entity get_building_entity(const String &key) const; + static void build_building_aabbs(); + static void update_building_transform(const String &key, + const Transform &xform); + static bool has_building(const String &key); + static String get_closest_building(const Transform &xform); + static flecs::entity + get_closest_building_entity(const Transform &xform); + static flecs::entity get_building_entity(const String &key); void load_tile(int x, int z); }; #endif \ No newline at end of file diff --git a/src/modules/stream/buildings_data_module.cpp b/src/modules/stream/buildings_data_module.cpp new file mode 100644 index 0000000..2906ede --- /dev/null +++ b/src/modules/stream/buildings_data_module.cpp @@ -0,0 +1,400 @@ +#include +#include +#include +#include +#include +#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(); + // print_line("e0"); + // flecs::world ecs_ = ecs(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + ecs_.component(); + // print_line("e1"); + // bool deferred = ecs_.is_deferred(); + // if (deferred) + // ecs_.defer_suspend(); + ecs_.set({ 0 }); + ecs_.set({}); + assert(ecs_.has()); + load_data(); + print_line("=== buildings"); + ecs_.query_builder().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().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()->created_entities)); + assert(ecs().get()->created_entities > 0); + + /* Fill door locations */ + ecs().query_builder().build().each([&](flecs::entity e, + CSceneData &sd) { + Error err; + const String &path = sd.sd.path; + Ref ps = + ResourceLoader::load(path, "PackedScene", true, &err); + if (err == OK && ps.is_valid()) { + Vector doors; + Node *scene = ps->instance(); + List 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(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({ doors }); + scene->queue_delete(); + ps.unref(); + } + }); + // if (deferred) + // ecs_.defer_resume(); + ecs_.system("CreateSceneData") + .kind(flecs::OnUpdate) + .write() + .run([&](flecs::iter &it) { + Dictionary buildings_data = + config.get_value("buildings", "building_data"); + List keys; + buildings_data.get_key_list(&keys); + List::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({ key, path }); + } + e = e->next(); + } + }); + ecs_.system("LoadPackedScene") + .kind(flecs::OnUpdate) + .without() + .write() + .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({ sp }); + }); + ecs_.system("LoadPackedScenePoll") + .kind(flecs::OnUpdate) + .without() + .each([&](flecs::entity e, CScenePack &sp) { + const CSceneData *sd = e.get(); + 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 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(); + assert(sp.sp.packed_scene.is_valid()); + } else { + print_error("Could not load the resource :( " + + sd->sd.path + " " + itos(err)); + } + }); + ecs_.system("CalculateAABBs") + .without() + .each([&](flecs::entity e, CSceneData &sd) { + Error err; + const String &path = sd.sd.path; + Ref ps = ResourceLoader::load( + path, "PackedScene", true, &err); + if (err == OK && ps.is_valid()) { + AABB aabb; + Node *scene = ps->instance(); + List queue; + queue.push_back(scene); + while (!queue.empty()) { + int i; + Node *item = queue.front()->get(); + queue.pop_front(); + MeshInstance *mi = + Object::cast_to( + 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({ 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() + .build() + .count(); + int count_pack = + (int)it.world() + .query_builder() + .build() + .count(); + int count_aabb = (int)it.world() + .query_builder() + .build() + .count(); + if (count_csdata > 0 && count_csdata == count_pack && + count_csdata == count_aabb) + it.world().add(); + else + it.world().remove(); + }); + ecs_.observer() + .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() + .event(flecs::OnAdd) + .with() + .run([&](flecs::iter &it) { + flecs::query q = + it.world() + .query_builder() + .with() + .build(); + if (it.next()) { + flecs::entity qe = it.entity(0); + q.each([qe](flecs::entity e, + const CBuildingData &d) { + if (e != qe) + e.remove(); + }); + 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()) { + int old_x = it.world().get()->tile_x; + int old_z = it.world().get()->tile_z; + if (old_x == tile_x && old_z == tile_z) + need_update = false; + else + print_line("UpdateEye need update"); + } + it.world().set({ xform, tile_x, tile_z }); + if (!need_update) + return; + if (!it.world().has()) + return; + CBuildingTileData *td = it.world().get_mut(); + it.world() + .query_builder() + .without() + .without() + .with() + .build() + .each([&](flecs::entity e, const CBuildingData &bd) { + const CBuildingTile *bt = + e.get(); + std::tuple 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(); + } + } + }); + it.world() + .query_builder() + .with() + .with() + .without() + .build() + .each([&](flecs::entity e, const CBuildingData &bd) { + const CBuildingTile *bt = + e.get(); + std::tuple 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(); + } + }); + }); + ecs_.system("LoadData") + .kind(flecs::OnUpdate) + .without() + .without() + .with() + .write() + .write() + .write() + .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()) { + add_scene_item(id, bd.building.key); + e.add(); + } + } + if (debug) + print_verbose("added to scene id: " + id); + assert(e.is_valid()); + // e.world().defer_suspend(); + e.add(); + e.remove(); + print_line("CBuildingLoaded"); + // e.world().defer_resume(); + print_line("LoadData"); + }); + ecs_.system("UnloadData") + .kind(flecs::OnUpdate) + .read() + .with() + .with() + .write() + .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(); + e.remove(); + e.remove(); + print_line("UnloadData"); + }); + ecs_.system("SpawnNode") + .kind(flecs::OnUpdate) + .without() + .with() + .write() + .each([&](flecs::entity e, const CBuildingData &bd) {}); + print_line("SpawnNode initialized"); +} + +BuildingsData::~BuildingsData() +{ +} diff --git a/src/modules/stream/contours.cpp b/src/modules/stream/contours.cpp index c7a2dda..5728ca7 100644 --- a/src/modules/stream/contours.cpp +++ b/src/modules/stream/contours.cpp @@ -4,28 +4,28 @@ #include #include "wedge.h" #include "base_data.h" +#include "buildings_data.h" #include "contours.h" -Contours *Contours::singleton = nullptr; - -Contours *Contours::get_singleton() -{ - if (!singleton) - singleton = memnew(Contours); - return singleton; -} - -Contours::Contours() +Contours::Contours(flecs::world &ecs) : dbg(nullptr) { - BaseData::get_singleton()->get().component(); + ecs.module(); + ecs.import (); + Lot::import_packer(ecs); + ecs.component(); + 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() { } -bool Contours::is_in_closed_contour(const struct wedge *w) +bool Contours::is_in_closed_contour(const struct wedge *w) const { int i, j; bool found = false; @@ -51,6 +51,7 @@ static Vector3 normal(const Vector3 &v) void Contours::build() { int i, j; + print_line("Contours::build()"); contours.clear(); for (i = 0; i < (int)wedge_contours.size(); i++) { struct main_contour mc; @@ -86,10 +87,6 @@ void Contours::build() } 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 polygon_queue; List polygon_output; Vector check; @@ -141,7 +138,7 @@ void Contours::build() List::Element *e = polygon_queue.front(); while (e) { struct Lot::polygon item = e->get(); - print_line("queue: " + itos(polygon_queue.size())); + // print_line("queue: " + itos(polygon_queue.size())); polygon_queue.pop_front(); float area = item.area(); if (area > 120.0f * 120.0f && @@ -162,12 +159,15 @@ void Contours::build() e = polygon_queue.front(); } e = polygon_output.front(); + assert(base_e.is_valid()); while (e) { + print_line("creating entity"); flecs::entity lot_e = BaseData::get_singleton() ->get() .entity() .child_of(base_e); lot_e.set({ e->get() }); + print_line("created entity: " + String(lot_e.name())); e = e->next(); } } @@ -186,7 +186,6 @@ void Contours::build() } }); }); - Lot::pack(); } void Contours::debug() diff --git a/src/modules/stream/contours.h b/src/modules/stream/contours.h index 61c0f3b..810a21e 100644 --- a/src/modules/stream/contours.h +++ b/src/modules/stream/contours.h @@ -2,6 +2,7 @@ #ifndef CONTOURS_H_ #define CONTOURS_H_ #include +#include #include "road_lot.h" class ImmediateGeometry; @@ -20,12 +21,11 @@ struct Contours { Ref imm_mat; std::vector > wedge_contours; std::vector contours; - static Contours *singleton; - static Contours *get_singleton(); - Contours(); + Contours(flecs::world &ecs); virtual ~Contours(); - bool is_in_closed_contour(const struct wedge *w); + bool is_in_closed_contour(const struct wedge *w) const; void debug(); + flecs::entity base_e; }; #endif // CONTOURS_H_ \ No newline at end of file diff --git a/src/modules/stream/line_metadata_editor.cpp b/src/modules/stream/line_metadata_editor.cpp index e894ac3..a29d684 100644 --- a/src/modules/stream/line_metadata_editor.cpp +++ b/src/modules/stream/line_metadata_editor.cpp @@ -26,6 +26,7 @@ LineMetadataEditor::~LineMetadataEditor() void LineMetadataEditor::_notification(int which) { +#if 0 switch (which) { case NOTIFICATION_ENTER_TREE: { VBoxContainer *box = memnew(VBoxContainer); @@ -64,6 +65,7 @@ void LineMetadataEditor::_notification(int which) } } break; } +#endif } void LineMetadataEditor::_bind_methods() diff --git a/src/modules/stream/road_lines_editor.cpp b/src/modules/stream/road_lines_editor.cpp index 2f44f9e..efabfa9 100644 --- a/src/modules/stream/road_lines_editor.cpp +++ b/src/modules/stream/road_lines_editor.cpp @@ -1125,7 +1125,7 @@ class EdgeEditorHandler { continue; } const AABB &aabb_building = - bd()->building_aabbs[buildings[i].id]; + bd()->get_scene_aabb(buildings[i].id); Transform building_rot( Basis().rotated( Vector3(0, 1, 0), @@ -1306,9 +1306,9 @@ class EdgeEditorHandler { String lot_id = side.lot_type; if (side.buildings.size() > 1) { const AABB &aabb_lot = - bd()->building_aabbs - ["lot-" + - lot_id]; + bd()->get_scene_aabb( + "lot-" + + lot_id); bool pack_result = pack_buildings( aabb_lot, @@ -1375,9 +1375,9 @@ class EdgeEditorHandler { String lot_id = side.lot_type; if (side.buildings.size() > 1) { const AABB &aabb_lot = - bd()->building_aabbs - ["lot-" + - lot_id]; + bd()->get_scene_aabb( + "lot-" + + lot_id); bool pack_result = pack_buildings( aabb_lot, diff --git a/src/modules/stream/road_lot.cpp b/src/modules/stream/road_lot.cpp index 90a0af8..35efdcc 100644 --- a/src/modules/stream/road_lot.cpp +++ b/src/modules/stream/road_lot.cpp @@ -121,9 +121,9 @@ template static Vector get_polygon2(const T &polygon) bool Lot::polygon::intersects(const polygon *other) const { - print_line("intersection_test"); - dump(); - other->dump(); + // print_line("intersection_test"); + // dump(); + // other->dump(); Vector p1 = get_polygon2(points); Vector p2 = get_polygon2(other->points); Vector > intersection = @@ -510,14 +510,16 @@ struct LotPacker { lbs.clear(); Array lb = config.get_value("road", varname, Array()); int i, j; + print_line("start building list"); for (i = 0; i < (int)lb.size(); i++) { struct config_buildings cb; cb.area = 0.0f; Array entries = lb[i]; for (j = 0; j < entries.size(); j++) { String bname = entries[j]; + print_line("building: " + 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; print_line("config building: " + bname); } @@ -525,6 +527,7 @@ struct LotPacker { String::num(cb.area)); lbs.push_back(cb); } + print_line("end building list"); struct lbsort { _FORCE_INLINE_ bool operator()(const struct config_buildings &b1, @@ -536,29 +539,45 @@ struct LotPacker { lbs.sort_custom(); lbs.invert(); } - LotPacker(Vector2 cell_size) - : cell_size(cell_size) + LotPacker(flecs::world &ecs) + : cell_size(Vector2(16, 16)) { - BaseData::get_singleton()->get().component(); - BaseData::get_singleton()->get().component(); - BaseData::get_singleton()->get().component(); - BaseData::get_singleton()->get().component(); - BaseData::get_singleton()->get().component(); - BaseData::get_singleton()->get().component(); + ecs.module(); + ecs.import (); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component(); + struct PackerState { + int state; + }; + ecs.component(); + Error err = config.load("res://config/stream.conf"); assert(err == OK); - get_building_list("lot_buildings_residental", - lot_buildings_residental); - get_building_list("lot_buildings_commercial", - lot_buildings_commercial); - get_building_list("lot_buildings_industrial", - lot_buildings_industrial); - } - static LotPacker *get_singleton() - { - if (!singleton) - singleton = memnew(LotPacker(Vector2(16, 16))); - return singleton; + ecs.system("MakeStuff") + .kind(flecs::OnUpdate) + .run([&](flecs::iter &it) { + if (!it.world().has()) + it.world().set({ 0 }); + if (it.world().has() && + it.world().get()->state == 1) { + get_building_list( + "lot_buildings_residental", + lot_buildings_residental); + get_building_list( + "lot_buildings_commercial", + lot_buildings_commercial); + get_building_list( + "lot_buildings_industrial", + lot_buildings_industrial); + } + if (it.world().has()) + it.world() + .get_mut() + ->state++; + }); } static inline Rect2 aabb2rect(const AABB &aabb) @@ -840,17 +859,17 @@ out_bad: } bool tmp_found = false; int office_count = 0; + // FIXME use components and find instead of direct lookup AABB get_building_aabb(const String &key) const { const struct BuildingsData::building &b = bd()->get_building(key); - const AABB &building_aabb = bd()->building_aabbs[b.id]; - return building_aabb; + return bd()->get_scene_aabb(b.id); } + // FIXME use components and find instead of direct lookup AABB get_building_type_aabb(const String &building) const { - const AABB &building_aabb = bd()->building_aabbs[building]; - return building_aabb; + return bd()->get_scene_aabb(building); } Transform get_building_transform(const String &key) { @@ -872,80 +891,99 @@ out_bad: void create() { int lot_count = 0; + int i, j; + Vector entities; + Vector entities_all; + Vector vrects; + Vector xforms; + List buildings; + Vector vbuildings; + bd()->get_building_keys_list(&buildings); BaseData::get_singleton() ->get() .query_builder() - .write() - .write() + .read() .build() .each([&](flecs::entity e, Lot &lot_) { assert(e.get()->polygon.points.size() > 0); - List buildings; - bd()->get_building_keys_list(&buildings); - List::Element *be = buildings.front(); e.get_mut()->polygon.update_aabb(); - if (e.has()) - return; - while (be) { - const String &key = be->get(); - const struct BuildingsData::building &b = - bd()->get_building(key); - if (key.begins_with("road__")) { - be = be->next(); - continue; - } - if (allowed_building(b.id)) { - be = be->next(); - continue; - } - AABB lot_aabb = - e.get()->polygon.aabb; - Rect2 lot_rect = aabb2rect( - e.get()->polygon.aabb); - Rect2 building_rect = - get_rect_transformed(key); - Transform xform = - get_building_transform(key); - Vector2 building_pos = Vector2( - xform.origin.x, xform.origin.z); - bool intersects = false; - if (e.get()->polygon.is_inside( - building_rect)) - intersects = true; - assert(e.get() - ->polygon.points.size() > - 0); - if (intersects) { - assert(e.get() - ->polygon.points - .size() > 0); - e.add(); - assert(e.get() - ->polygon.points - .size() > 0); - LotBuildings &lb = - e.ensure(); - lb.buildings.push_back( - { building_rect, key }); - Vector pt = - get_polygon2( - e.get() - ->polygon - .points); - assert(pt.size() > 0); - lb.polygons.push_back(pt); - e.modified(); - } - be = be->next(); - } + if (!e.has()) + entities.push_back(e); }); + BaseData::get_singleton() + ->get() + .query_builder() + .build() + .each([&](flecs::entity e, Lot &lot_) { + entities_all.push_back(e); + }); + print_line("entities: " + itos(entities.size())); + List::Element *be = buildings.front(); + while (be) { + const String &key = be->get(); + const struct BuildingsData::building &b = + bd()->get_building(key); + if (key.begins_with("road__")) { + be = be->next(); + continue; + } + if (allowed_building(b.id)) { + be = be->next(); + continue; + } + vbuildings.push_back(b); + Rect2 building_rect = get_rect_transformed(b.key); + vrects.push_back(building_rect); + Transform xform = get_building_transform(b.key); + xforms.push_back(xform); + be = be->next(); + } + print_line("buildings: " + itos(vbuildings.size())); + for (i = 0; i < entities.size(); i++) { + flecs::entity e = entities[i]; + print_line("Lot: " + itos(i) + " " + String(e.name())); + assert(e.is_valid()); + assert(e.get()->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(); + be = buildings.front(); + AABB lot_aabb = e.get()->polygon.aabb; + Rect2 lot_rect = aabb2rect(e.get()->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; + if (e.get()->polygon.is_inside( + building_rect)) + intersects = true; + if (intersects) { + e.add(); + LotBuildings &lb = + e.ensure(); + lb.buildings.push_back( + { building_rect, b.key }); + Vector pt = get_polygon2( + e.get()->polygon.points); + assert(pt.size() > 0); + lb.polygons.push_back(pt); + e.modified(); + } + } + } BaseData::get_singleton() ->get() .query_builder() .with() .build() .each([&](flecs::entity e, Lot &lot, LotBuildings &lb) { - int i; for (i = 0; i < lb.buildings.size(); i++) { const Pair &mp = lb.buildings[i]; @@ -956,6 +994,9 @@ out_bad: get_rect_transformed(key); Rect2 lot_rect = aabb2rect(lot.polygon.aabb); + assert(bd()->has_scene( + "office-exterior")); + print_line("building type: " + b.id); if (b.id == "office-exterior") { print_line("id: " + b.id); print_line("xform: " + @@ -972,6 +1013,19 @@ out_bad: } } }); + for (i = 0; i < entities.size(); i++) { + flecs::entity e = entities[i]; + if (e.has()) + continue; + if ((lot_count % 5) == 0) + e.add(); + else if (lot_count % 3 == 0) + e.add(); + else + e.add(); + lot_count++; + } +#if 0 BaseData::get_singleton() ->get() .query_builder() @@ -1080,14 +1134,12 @@ out_bad: e.add(); lot_count++; }); +#endif assert(tmp_found); print_line("office_count: " + itos(office_count)); // assert(office_count > 1); - BaseData::get_singleton() - ->get() - .query_builder() - .build() - .each([&](flecs::entity e, Lot &lot) { add_lot(e); }); + for (i = 0; i < entities_all.size(); i++) + add_lot(entities_all[i]); BaseData::get_singleton() ->get() .query_builder() @@ -1292,31 +1344,42 @@ out_bad: return lb->polygons; } }; -LotPacker *LotPacker::singleton = nullptr; void Lot::pack() { - LotPacker::get_singleton()->create(); - LotPacker::get_singleton()->pack_lots(); + BaseData::get_singleton()->get().get_mut()->create(); + BaseData::get_singleton()->get().get_mut()->pack_lots(); + BaseData::get_singleton()->get().modified(); } void Lot::get_lot_data(flecs::entity e, List > *lot_data) { - LotPacker::get_singleton()->get_lot_data(e, lot_data); + BaseData::get_singleton()->get().get_mut()->get_lot_data( + e, lot_data); } void Lot::get_lot_rotations(flecs::entity e, List *lot_xform) { - LotPacker::get_singleton()->get_lot_rotations(e, lot_xform); + BaseData::get_singleton()->get().get_mut()->get_lot_rotations( + e, lot_xform); } void Lot::get_lot_buildings(flecs::entity e, Vector > *lot_buildings) { - LotPacker::get_singleton()->get_lot_buildings(e, lot_buildings); + BaseData::get_singleton()->get().get_mut()->get_lot_buildings( + e, lot_buildings); } Vector > Lot::get_lot_polygons(flecs::entity e) { - return LotPacker::get_singleton()->get_lot_polygons(e); + return BaseData::get_singleton() + ->get() + .get_mut() + ->get_lot_polygons(e); +} + +void Lot::import_packer(flecs::world &ecs) +{ + ecs.import (); } diff --git a/src/modules/stream/road_lot.h b/src/modules/stream/road_lot.h index 894a5de..25a716e 100644 --- a/src/modules/stream/road_lot.h +++ b/src/modules/stream/road_lot.h @@ -33,6 +33,7 @@ struct Lot { get_lot_buildings(flecs::entity e, Vector > *lot_buildings); static Vector > get_lot_polygons(flecs::entity e); + static void import_packer(flecs::world &ecs); }; #endif // ROAD_LOT_H_ \ No newline at end of file diff --git a/src/modules/stream/road_processing.cpp b/src/modules/stream/road_processing.cpp index cd0edee..9f4d709 100644 --- a/src/modules/stream/road_processing.cpp +++ b/src/modules/stream/road_processing.cpp @@ -88,9 +88,10 @@ struct RoadLinesProcessing { int debug_flags; DebugGeo *dbg; static ConfigFile config; - RoadLinesProcessing() + RoadLinesProcessing(flecs::world &ecs) : dbg(nullptr) { + ecs.module(); Error err = config.load("res://config/stream.conf"); assert(err == OK); } @@ -158,7 +159,7 @@ struct RoadLinesProcessing { } bd()->create_building(b); if (!bd()->has_scene(b.id)) - bd()->create_scene_data(b.id, b.key); + return; else bd()->add_scene_item(b.id, b.key); print_line("created building: " + b.key + " " + b.id); @@ -919,7 +920,10 @@ out2:; void find_closed_contours() { int i, j; - Contours *contours = Contours::get_singleton(); + print_line("find_closed_contours"); + assert(this); + Contours *contours = + BaseData::get_singleton()->get().get_mut(); // RoadLinesProcessing *r = BaseData::get_singleton() ->get() .get_mut(); RoadLinesProcessing *r = this; if (r->nodes.size() == 0) @@ -985,7 +989,7 @@ out2:; } if (finished) { int k; - print_line("complete contour"); + // print_line("complete contour"); std::vector wedge_contour; Vector polygon; for (k = 0; k < (int)contour.size(); k++) { @@ -993,8 +997,8 @@ out2:; wedges_ref[contour[k]]; wedge_contour.push_back( &wedges[wr.first][wr.second]); - print_line(itos(k) + ": " + - itos(contour[k])); + // print_line(itos(k) + ": " + + // itos(contour[k])); Vector3 p1 = wedges[wr.first][wr.second].p[0]; Vector3 p2 = @@ -1007,9 +1011,8 @@ out2:; used.push_back(contour[k]); } if (Geometry::is_polygon_clockwise(polygon)) - contours->get_singleton() - ->wedge_contours.push_back( - wedge_contour); + contours->wedge_contours.push_back( + wedge_contour); contour.clear(); contour_count++; } else @@ -1018,8 +1021,6 @@ out2:; if (base >= (int)wedges_ref.size()) break; } - contours->build(); - contours->debug(); } ~RoadLinesProcessing() { @@ -1032,27 +1033,10 @@ out2:; { return debug_flags; } - void road_setup() + void road_setup2() { int i, j; RoadLinesData *rld = RoadLinesData::get_singleton(); - std::vector road_lines_nodes; - std::unordered_map > - 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(); ImmediateGeometry *d = rld->get_debug_node(); d->clear(); @@ -1114,7 +1098,6 @@ out2:; } d->end(); } - create_structures(); print_line("ROAD SETUP DONE"); } }; @@ -1703,7 +1686,9 @@ public: out_surfaces[h], 0.0f); } else if (k == params.nlanes + 1 && mside1.lot > 0) { /* lot */ - if (!Contours::get_singleton() + if (!BaseData::get_singleton() + ->get() + .get() ->is_in_closed_contour( &wedge)) build_split_segment( @@ -1779,7 +1764,9 @@ public: "m2: " + String::num( mside2.lot_depth_eff)); - if (!Contours::get_singleton() + if (!BaseData::get_singleton() + ->get() + .get() ->is_in_closed_contour( &wedge)) build_split_segment( @@ -1864,25 +1851,51 @@ public: nodes_mi.push_back(mi); } } - RoadMeshProcessing() + RoadMeshProcessing(flecs::world &ecs) : road_mgroup(nullptr) { - BaseData::get_singleton()->get().ensure(); + ecs.module(); + ecs.import (); } }; void RoadProcessing::road_setup(Node *target, int debug_flags) { - BaseData::get_singleton()->get().ensure(); - BaseData::get_singleton()->get().ensure(); + RoadLinesData *rld = RoadLinesData::get_singleton(); + int i, j; RoadLinesProcessing *r = BaseData::get_singleton()->get().get_mut(); r->set_debug_flags(debug_flags); - r->road_setup(); + std::vector road_lines_nodes; + std::unordered_map > + 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->build(); + Lot::pack(); + contours->debug(); + BaseData::get_singleton()->get().modified(); + r->create_structures(); BaseData::get_singleton() ->get() .get_mut() ->create_road_meshes(target); + r->road_setup2(); } void RoadProcessing::remove_road_meshes(Node *target) @@ -1900,7 +1913,6 @@ void RoadProcessing::load_data() ConfigFile config; Error result = config.load("res://config/stream.conf"); ERR_FAIL_COND_MSG(result != OK, "Failed to load config"); - BaseData::get_singleton()->get().ensure(); RoadMeshProcessing *rmp = BaseData::get_singleton()->get().get_mut(); assert(rmp); @@ -2025,3 +2037,15 @@ void RoadProcessing::cleanup() BaseData::get_singleton()->get().remove(); BaseData::get_singleton()->get().remove(); } + +RoadProcessing::RoadProcessing(flecs::world &ecs) +{ + ecs.module(); + ecs.import (); + ecs.import (); + ecs.import (); +} + +RoadProcessing::~RoadProcessing() +{ +} diff --git a/src/modules/stream/road_processing.h b/src/modules/stream/road_processing.h index 9ef6ca4..f83012c 100644 --- a/src/modules/stream/road_processing.h +++ b/src/modules/stream/road_processing.h @@ -1,5 +1,6 @@ #ifndef ROAD_LINES_PROCESSING_H_ #define ROAD_LINES_PROCESSSING_H_ +#include class Node; class ImmediateGeometry; class RoadProcessing { @@ -8,5 +9,7 @@ public: static void remove_road_meshes(Node *target); static void load_data(); static void cleanup(); + RoadProcessing(flecs::world &ecs); + virtual ~RoadProcessing(); }; #endif diff --git a/src/modules/stream/stream.cpp b/src/modules/stream/stream.cpp index 984726a..37b11cb 100644 --- a/src/modules/stream/stream.cpp +++ b/src/modules/stream/stream.cpp @@ -53,7 +53,7 @@ void StreamWorld::create_tilemap() void StreamWorld::update_view() { - int i, j; + int i; ERR_FAIL_COND_MSG(!initialized, "The Stream object is incorrectly initialized"); if (!viewer || !terrain) { @@ -84,6 +84,12 @@ void StreamWorld::update_view() ERR_FAIL_COND_MSG(!t, "VoxelLodTerrain was not found"); viewer = v; terrain = t; + assert(terrain); + assert(viewer); + BaseData::get_singleton() + ->get() + .set( + { viewer, terrain }); viewer->connect("tree_exiting", this, "viewer_dead"); terrain->connect("tree_exiting", this, "terrain_dead"); current_x = world_extent + 1; @@ -218,7 +224,7 @@ void StreamWorld::unload_building(const String &key) void StreamWorld::update_items() { List keys; - data()->get_scene_keys_list(&keys); + BuildingsData::get_scene_keys_list(&keys); List::Element *e = keys.front(); while (e) { const String &key = e->get(); @@ -260,6 +266,7 @@ void StreamWorld::remove_building(const String &key) VoxelLodTerrain *StreamWorld::get_terrain() { + assert(terrain); return terrain; } @@ -316,7 +323,7 @@ void StreamWorld::run_command(const String &command, String new_type = args[1]; Dictionary buildings_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); return; } @@ -403,7 +410,7 @@ void StreamWorld::run_command(const String &command, create_tilemap(); #endif update_view(); - data()->scene_update(); + BuildingsData::scene_update(); update_items(); #if 0 data()->for_each_building( @@ -453,7 +460,17 @@ void StreamWorld::_notification(int which) if (current_scene) current_scene = get_tree()->get_root(); } +#if 0 + BaseData::get_singleton() + ->get() + .add(); +#endif 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); #if 0 data()->for_each_building( @@ -471,6 +488,7 @@ void StreamWorld::_notification(int which) #if 0 create_tilemap(); #endif + BaseData::get_singleton()->get().defer_resume(); set_process(true); if (Engine::get_singleton()->is_editor_hint()) break; @@ -480,12 +498,14 @@ void StreamWorld::_notification(int which) update_view(); assert(terrain); assert(viewer); +#endif } break; case NOTIFICATION_EXIT_TREE: frame_count = 0; break; case NOTIFICATION_PROCESS: { +#if 0 if (frame_count % 60 == 0) { float fmon = Performance::get_singleton()->get_monitor( Performance::RENDER_DRAW_CALLS_IN_FRAME); @@ -497,6 +517,12 @@ void StreamWorld::_notification(int which) update_view(); data()->scene_update(); update_items(); +#endif + if (road_setup_needed && !road_setup_complete) { + road_setup(); + road_setup_needed = false; + road_setup_complete = true; + } } break; } @@ -525,14 +551,30 @@ StreamWorld::StreamWorld() , view_distance(0) , initialized(false) , frame_count(0) + , road_setup_needed(false) + , road_setup_complete(false) + , count_shit(0) { - BaseData::get_singleton()->get().component(); + BaseData::get_singleton()->get().import (); + BaseData::get_singleton()->get().import (); + BaseData::get_singleton() + ->get() + .component(); + BaseData::get_singleton() + ->get() + .component(); + BaseData::get_singleton() + ->get() + .component(); + BaseData::get_singleton() + ->get() + .component(); Error result = config.load("res://config/stream.conf"); ERR_FAIL_COND_MSG(result != OK, "Failed to load config"); - BaseData::get_singleton()->get().ensure(); RoadProcessing::load_data(); world_extent = config.get_value("world", "world_extent"); 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 || world_extent <= tile_size, "Failed to configure world"); @@ -548,11 +590,40 @@ StreamWorld::StreamWorld() map_it++; } #endif - view_distance = config.get_value("world", "view_distance"); BaseData::get_singleton()->get().import (); flecs::entity npcctrl = BaseData::get_singleton()->get().entity(); npcctrl.set({ NPC::NPCControl::CMD_PRESIM }); 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()) + return; + if (it.world() + .has() && + !it.world() + .has()) { + road_setup_needed = true; + it.world() + .add(); + } else if (it.world() + .has()) + it.world() + .add(); +#endif + }); } void StreamWorld::cleanup() { @@ -592,3 +663,16 @@ void StreamWorld::undo() update_view(); 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); +} diff --git a/src/modules/stream/stream.h b/src/modules/stream/stream.h index c670f49..cd52193 100644 --- a/src/modules/stream/stream.h +++ b/src/modules/stream/stream.h @@ -37,6 +37,9 @@ private: bool initialized; int current_x, current_z; int frame_count; + bool road_setup_needed; + bool road_setup_complete; + int count_shit; void _notification(int which); // void create_tilemap(); void update_view(); @@ -51,10 +54,20 @@ private: void remove_generated_stuff(); void place_zebras(); void undo(); + void road_setup(); static void _bind_methods(); public: + struct components { + struct Initialized {}; + struct WorldData { + VoxelViewer *viewer; + VoxelLodTerrain *terrain; + }; + struct RoadSetupNeeded {}; + struct RoadSetupDone {}; + }; VoxelLodTerrain *get_terrain(); void run_command(const String &command, const Vector &args); StreamWorld(); diff --git a/src/modules/stream/terrain_editor.cpp b/src/modules/stream/terrain_editor.cpp index 29e941d..5fe4093 100644 --- a/src/modules/stream/terrain_editor.cpp +++ b/src/modules/stream/terrain_editor.cpp @@ -34,8 +34,14 @@ void TerrainEditor::exit() void TerrainEditor::update(float delta) { - if (!active) - activate(); + if (!active) { + if (BaseData::get_singleton() + ->get() + .has()) + activate(); + else + return; + } if (!cursor_enabled && get_camera_mode() == 3) { cursor_enabled = true; get_as_node(cursor_name)->show(); @@ -382,7 +388,7 @@ end:; "building elevation: " + String::num(imgmapper->get_height_full( b.xform.origin))); - AABB aabb = bd()->building_aabbs[b.id]; + AABB aabb = bd()->get_scene_aabb(b.id); print_line("building AABB: " + (aabb.operator String())); float max_elevation_c = -Math_INF, diff --git a/src/modules/stream/ui/main_tabs.cpp b/src/modules/stream/ui/main_tabs.cpp index 549fb21..598ed6a 100644 --- a/src/modules/stream/ui/main_tabs.cpp +++ b/src/modules/stream/ui/main_tabs.cpp @@ -614,6 +614,7 @@ void MainTabs::_notification(int which) std::vector args_data = { items[i].header }; + assert(items[i].header.length() > 0); ui_field::ui_field_builder(this, tab, "l_p{v{}}", args_data.data(), diff --git a/src/modules/stream/ui/ui_field_builder.cpp b/src/modules/stream/ui/ui_field_builder.cpp index 6257f8a..eb57ff7 100644 --- a/src/modules/stream/ui/ui_field_builder.cpp +++ b/src/modules/stream/ui/ui_field_builder.cpp @@ -40,9 +40,10 @@ void ui_field::ui_field_builder(Node *owner, Node *parent, const String format, .get() ->node; assert(owner->is_inside_tree()); - for (i = 0; i < format.length(); i++) { - const char *fmt = format.ascii().ptr(); - int c = fmt[i]; + CharString cformat = format.ascii(); + for (i = 0; i < format.ascii().length(); i++) { + assert(i < cformat.length()); + int c = (int)cformat.ptr()[i]; // printf("character: %c : argp: %d\n", (char)c, argp); switch (c) { case '{':