Converted buildings loading to flecs
This commit is contained in:
11
Makefile
11
Makefile
@@ -2,8 +2,10 @@ ARCH=$(patsubst aarch64,arm64,$(shell uname -m))
|
||||
BLENDER = ../../blender-3.6.20-linux-x64/blender
|
||||
SERVER = src/godot/bin/godot_server.x11.opt.tools.$(ARCH)
|
||||
EDITOR_PLATFORM=x11es
|
||||
EDITOR2_PLATFORM=x11
|
||||
DEMO_PLATFORMS=x11 x11es
|
||||
EDITOR = src/godot/bin/godot.$(EDITOR_PLATFORM).opt.tools.$(ARCH)
|
||||
EDITOR2 = src/godot/bin/godot.$(EDITOR2_PLATFORM).opt.tools.$(ARCH)
|
||||
|
||||
.PHONY: all godot-editor-main export export-models export-clothes \
|
||||
export-clean export-linux-demo export-windows-demo \
|
||||
@@ -28,12 +30,13 @@ $(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)
|
||||
$(SERVER): patch
|
||||
cd src/godot; \
|
||||
scons platform=server arch=$(ARCH) target=release_debug tools=yes custom_modules=../modules -j16
|
||||
godot-editor-main: $(EDITOR) $(EDITOR2)
|
||||
#$(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,x11,release_debug,yes,$(EDITOR2),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
|
||||
|
||||
@@ -27,7 +27,7 @@ flags/repeat=true
|
||||
flags/filter=true
|
||||
flags/mipmaps=true
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
flags/srgb=1
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
|
||||
@@ -54,3 +54,6 @@ transform = Transform( 1.7, 0, 0, 0, 1, 0, 0, 0, 1.2, 0, 0, 2.03699 )
|
||||
|
||||
[node name="2" type="Spatial" parent="LOD"]
|
||||
visible = false
|
||||
|
||||
[node name="BuildingLayoutInstance" type="BuildingLayoutInstance" parent="."]
|
||||
size = 8
|
||||
|
||||
@@ -17,6 +17,10 @@ boot_splash/minimum_display_time=4
|
||||
|
||||
settings/fps/force_fps=60
|
||||
|
||||
[display]
|
||||
|
||||
window/vsync/use_vsync=false
|
||||
|
||||
[input]
|
||||
|
||||
forward={
|
||||
@@ -87,5 +91,5 @@ portals/optimize/remove_danglers=false
|
||||
gles3/shaders/shader_compilation_mode=2
|
||||
gles3/shaders/shader_compilation_mode.mobile=2
|
||||
gles3/shaders/max_simultaneous_compiles=4
|
||||
limits/buffers/immediate_buffer_size_kb=4096
|
||||
limits/buffers/blend_shape_max_buffer_size_kb=8192
|
||||
limits/buffers/immediate_buffer_size_kb=4096
|
||||
|
||||
20
src/modules/stream/building_grid_instance.cpp
Normal file
20
src/modules/stream/building_grid_instance.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "building_grid_instance.h"
|
||||
#include "buildings_data.h"
|
||||
|
||||
AABB BuildingGridInstance::get_aabb() const
|
||||
{
|
||||
return AABB();
|
||||
}
|
||||
|
||||
PoolVector<Face3> BuildingGridInstance::get_faces(uint32_t p_usage_flags) const
|
||||
{
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
BuildingGridInstance::BuildingGridInstance()
|
||||
{
|
||||
}
|
||||
|
||||
BuildingGridInstance::~BuildingGridInstance()
|
||||
{
|
||||
}
|
||||
17
src/modules/stream/building_grid_instance.h
Normal file
17
src/modules/stream/building_grid_instance.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* ~/godot-projects/streaming_world/src/modules/stream/building_grid_instance.h */
|
||||
#ifndef BUILDING_GRID_INSTANCE_H_
|
||||
#define BUILDING_GRID_INSTANCE_H_
|
||||
#include <flecs.h>
|
||||
#include <scene/3d/visual_instance.h>
|
||||
class BuildingGridInstance : public GeometryInstance {
|
||||
GDCLASS(BuildingGridInstance, GeometryInstance)
|
||||
flecs::entity e;
|
||||
|
||||
public:
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
BuildingGridInstance();
|
||||
~BuildingGridInstance();
|
||||
};
|
||||
|
||||
#endif // BUILDING_GRID_INSTANCE_H_
|
||||
97
src/modules/stream/buildings/building_layout_instance.cpp
Normal file
97
src/modules/stream/buildings/building_layout_instance.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <scene/3d/area.h>
|
||||
#include <scene/3d/collision_shape.h>
|
||||
#include "building_layout_instance.h"
|
||||
|
||||
BuildingLayoutInstance::BuildingLayoutInstance()
|
||||
: GeometryInstance()
|
||||
, size(0)
|
||||
, level(0)
|
||||
{
|
||||
}
|
||||
|
||||
BuildingLayoutInstance::~BuildingLayoutInstance()
|
||||
{
|
||||
}
|
||||
|
||||
void BuildingLayoutInstance::_notification(int which)
|
||||
{
|
||||
switch (which) {
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
break;
|
||||
case NOTIFICATION_EXIT_TREE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BuildingLayoutInstance::_get_property_list(List<PropertyInfo> *p_list) const
|
||||
{
|
||||
int i, j;
|
||||
p_list->push_back(PropertyInfo(Variant::INT, "size", PROPERTY_HINT_NONE,
|
||||
"", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "walls",
|
||||
PROPERTY_HINT_NONE, "",
|
||||
PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
|
||||
bool BuildingLayoutInstance::_get(const StringName &name, Variant &val) const
|
||||
{
|
||||
int i;
|
||||
if (name == "size") {
|
||||
val = size;
|
||||
return true;
|
||||
} else if (name == "walls") {
|
||||
PoolVector<int> mfloors;
|
||||
mfloors.resize(size);
|
||||
mfloors.fill(0);
|
||||
if (floors.size() < 2) {
|
||||
val = mfloors;
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < floors.size(); i += 2) {
|
||||
int cell_index = floors[i];
|
||||
int cell_data = floors[i + 1];
|
||||
if (cell_index >= 0 && cell_index < mfloors.size())
|
||||
continue;
|
||||
if (cell_data & (1 << 0))
|
||||
mfloors.write()[cell_index] = 1;
|
||||
else
|
||||
mfloors.write()[cell_index] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BuildingLayoutInstance::_set(const StringName &name, const Variant &val)
|
||||
{
|
||||
int i;
|
||||
if (name == "size") {
|
||||
size = val;
|
||||
property_list_changed_notify();
|
||||
return true;
|
||||
#if 0
|
||||
} else if (name == "walls") {
|
||||
PoolVector<int> mfloors = val;
|
||||
floors.resize(mfloors.size());
|
||||
for (i = 0; i < mfloors.size(); i++) {
|
||||
if (mfloors[i] > 0)
|
||||
floors.ptrw()[i] |= (1 << 0);
|
||||
else
|
||||
floors.ptrw()[i] &= ~(1 << 0);
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AABB BuildingLayoutInstance::get_aabb() const
|
||||
{
|
||||
return AABB();
|
||||
}
|
||||
|
||||
PoolVector<Face3>
|
||||
BuildingLayoutInstance::get_faces(uint32_t p_usage_flags) const
|
||||
{
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
21
src/modules/stream/buildings/building_layout_instance.h
Normal file
21
src/modules/stream/buildings/building_layout_instance.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <scene/3d/visual_instance.h>
|
||||
|
||||
class BuildingLayoutInstance : public GeometryInstance {
|
||||
GDCLASS(BuildingLayoutInstance, GeometryInstance)
|
||||
public:
|
||||
BuildingLayoutInstance();
|
||||
~BuildingLayoutInstance();
|
||||
|
||||
protected:
|
||||
void _notification(int which);
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
bool _get(const StringName &name, Variant &val) const;
|
||||
bool _set(const StringName &name, const Variant &val);
|
||||
Vector<int> floors;
|
||||
int size;
|
||||
int level;
|
||||
|
||||
public:
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
};
|
||||
@@ -9,13 +9,14 @@
|
||||
#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 "from_string.h"
|
||||
#include "base_data.h"
|
||||
#include "buildings_data.h"
|
||||
|
||||
BuildingsData *BuildingsData::singleton;
|
||||
|
||||
static ConfigFile config;
|
||||
static ConfigFile custom_layouts;
|
||||
struct scene_data {
|
||||
Ref<PackedScene> packed_scene;
|
||||
String path;
|
||||
@@ -42,43 +43,206 @@ struct CBuildingInstance {
|
||||
Node *node;
|
||||
};
|
||||
|
||||
struct CBuildingData {
|
||||
struct BuildingsData::building building;
|
||||
};
|
||||
|
||||
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>()
|
||||
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);
|
||||
// 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()
|
||||
{
|
||||
}
|
||||
|
||||
BuildingsData *BuildingsData::get_singleton()
|
||||
{
|
||||
if (!singleton)
|
||||
singleton = memnew(BuildingsData);
|
||||
|
||||
return singleton;
|
||||
}
|
||||
|
||||
void BuildingsData::build_building_aabbs()
|
||||
{
|
||||
building_aabbs.clear();
|
||||
@@ -130,14 +294,14 @@ bool BuildingsData::has_building(const String &key)
|
||||
String ename = "base:" + key;
|
||||
flecs::entity e = lookup(ename.ascii().ptr());
|
||||
if (!e.is_valid())
|
||||
print_line("no key: " + key);
|
||||
print_verbose("no key: " + key);
|
||||
else
|
||||
print_line("has building with parent: " +
|
||||
print_verbose("has building with parent: " +
|
||||
String(e.parent().name()));
|
||||
return e.is_valid();
|
||||
}
|
||||
|
||||
String BuildingsData::get_closest_building(const Transform &xform)
|
||||
String BuildingsData::get_closest_building(const Transform &xform) const
|
||||
{
|
||||
float dst = Math_INF;
|
||||
String rkey;
|
||||
@@ -154,18 +318,30 @@ String BuildingsData::get_closest_building(const Transform &xform)
|
||||
});
|
||||
return rkey;
|
||||
}
|
||||
|
||||
void BuildingsData::cleanup()
|
||||
flecs::entity
|
||||
BuildingsData::get_closest_building_entity(const Transform &xform) const
|
||||
{
|
||||
if (singleton) {
|
||||
singleton->~BuildingsData();
|
||||
Memory::free_static(singleton, false);
|
||||
singleton = nullptr;
|
||||
float dst = Math_INF;
|
||||
String rkey;
|
||||
flecs::entity qe;
|
||||
// int id = -1;
|
||||
ecs().each([xform, &rkey, &dst, &qe](flecs::entity e,
|
||||
const CBuildingData &d) {
|
||||
Vector3 o = xform.origin;
|
||||
Vector3 m = d.building.xform.origin;
|
||||
float mdst = o.distance_squared_to(m);
|
||||
if (dst > mdst && !d.building.key.begins_with("road__")) {
|
||||
dst = mdst;
|
||||
rkey = d.building.key;
|
||||
qe = e;
|
||||
}
|
||||
});
|
||||
return qe;
|
||||
}
|
||||
|
||||
void BuildingsData::read_buildings_json(const String &buildings_path)
|
||||
{
|
||||
assert(ecs().has<CBuildingStats>());
|
||||
String buildings_json = FileAccess::get_file_as_string(buildings_path);
|
||||
Variant json_v;
|
||||
String es;
|
||||
@@ -213,7 +389,7 @@ void BuildingsData::save_buildings_json(const String &buildings_path)
|
||||
fa->close();
|
||||
Dictionary json;
|
||||
int index = 0;
|
||||
ecs().each([&index, &json](const CBuildingData &b) {
|
||||
ecs().each([&index, &json](flecs::entity e, const CBuildingData &b) {
|
||||
String key = b.building.key;
|
||||
/* do not save roadside generated stuff */
|
||||
if (!key.begins_with("road::") && !key.begins_with("road__")) {
|
||||
@@ -321,6 +497,7 @@ void BuildingsData::filter_generated_stuff()
|
||||
|
||||
void BuildingsData::load_data()
|
||||
{
|
||||
assert(ecs().has<CBuildingStats>());
|
||||
Error result = config.load("res://config/stream.conf");
|
||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||
Dictionary buildings_data =
|
||||
@@ -336,7 +513,7 @@ void BuildingsData::load_data()
|
||||
e = keys.front();
|
||||
while (e) {
|
||||
String key = e->get();
|
||||
print_line(key + ": " + buildings_data[key]);
|
||||
// print_line(key + ": " + buildings_data[key]);
|
||||
e = e->next();
|
||||
}
|
||||
String buildings_path = config.get_value("buildings", "buildings_path");
|
||||
@@ -459,6 +636,19 @@ bool BuildingsData::has_scene(const String &key) const
|
||||
return e.is_valid();
|
||||
}
|
||||
|
||||
flecs::entity BuildingsData::get_building_entity(const String &key) const
|
||||
{
|
||||
flecs::query_builder<const CBuildingData> qb =
|
||||
ecs().query_builder<const CBuildingData>();
|
||||
flecs::query<const CBuildingData> q = qb.build();
|
||||
uint64_t key_hash = key.hash64();
|
||||
flecs::entity em = q.find([key_hash](const CBuildingData &bd) {
|
||||
// print_line("search: " + bd.building.key);
|
||||
return bd.building.key.hash64() == key_hash;
|
||||
});
|
||||
return em;
|
||||
}
|
||||
|
||||
void BuildingsData::remove_scene_item(const String &key, const String &bkey)
|
||||
{
|
||||
flecs::entity e = ecs().lookup(key.ascii().ptr());
|
||||
@@ -502,28 +692,33 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey)
|
||||
CSceneData *d = e.get_mut<CSceneData>();
|
||||
assert(d);
|
||||
String ename = "bi:" + bkey;
|
||||
print_line("creating entity: " + ename + " on top of: " + key);
|
||||
// print_line("creating entity: " + ename + " on top of: " + key);
|
||||
flecs::entity ce = e.lookup(ename.ascii().ptr());
|
||||
if (ce.is_valid())
|
||||
ce.destruct();
|
||||
ce = ecs().entity(ename.ascii().ptr()).child_of(e);
|
||||
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)
|
||||
{
|
||||
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());
|
||||
@@ -532,7 +727,7 @@ void BuildingsData::create_scene_data(const String &key, const String &bkey)
|
||||
ce = ecs().entity(ename.ascii().ptr());
|
||||
ce.child_of(e);
|
||||
ce.set<CBuildingInstance>({ bkey, nullptr });
|
||||
print_line("child name: " + String(ce.name()));
|
||||
// print_line("child name: " + String(ce.name()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,7 +766,7 @@ int BuildingsData::scene_get_item_count(const String &key) const
|
||||
it.fini();
|
||||
});
|
||||
// assert(result == d->sd.buildings.size());
|
||||
print_line("scene_get_item_count: " + itos(result));
|
||||
// print_line("scene_get_item_count: " + itos(result));
|
||||
return result;
|
||||
}
|
||||
List<String> BuildingsData::scene_get_items(const String &key) const
|
||||
@@ -700,11 +895,14 @@ int BuildingsData::get_building_count() const
|
||||
flecs::query<const CBuildingData> q =
|
||||
ecs().query<const CBuildingData>();
|
||||
int result;
|
||||
result = q.count();
|
||||
#if 0
|
||||
q.run([&result](flecs::iter &it) {
|
||||
it.next();
|
||||
result = it.count();
|
||||
it.fini();
|
||||
});
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -728,6 +926,7 @@ BuildingsData::get_building(const String &building_key)
|
||||
|
||||
String BuildingsData::create_building(const Dictionary &dict)
|
||||
{
|
||||
assert(ecs().has<CBuildingStats>());
|
||||
struct building b;
|
||||
building::from_dict(&b, dict);
|
||||
return create_building(b);
|
||||
@@ -736,13 +935,29 @@ String BuildingsData::create_building(const Dictionary &dict)
|
||||
String BuildingsData::create_building(const struct building &building)
|
||||
{
|
||||
assert(building.key.length() > 0);
|
||||
assert(ecs().has<CBuildingStats>());
|
||||
String ename = "base:" + building.key;
|
||||
print_line("create_building: " + ename);
|
||||
// print_line("create_building: " + ename);
|
||||
flecs::entity e = ecs().lookup(ename.ascii().ptr());
|
||||
assert(!e.is_valid());
|
||||
e = ecs().entity(ename.ascii().ptr());
|
||||
e.set<CBuildingData>({ building });
|
||||
assert(e.is_valid());
|
||||
int tile_size = config.get_value("world", "tile_size");
|
||||
assert(tile_size > 0);
|
||||
e.set<CBuildingData>({ building });
|
||||
int tile_x = building.xform.origin.x / tile_size;
|
||||
int tile_z = building.xform.origin.z / tile_size;
|
||||
std::tuple<int, int> tile = { tile_x, tile_z };
|
||||
e.set<CBuildingTile>({ tile });
|
||||
CBuildingTileData *td = ecs().get_mut<CBuildingTileData>();
|
||||
if (td->tiles.find(tile) != td->tiles.end())
|
||||
td->tiles[tile].push_back(e);
|
||||
else
|
||||
td->tiles[tile] = { e };
|
||||
ecs().get_mut<CBuildingStats>()->created_entities++;
|
||||
ecs().modified<CBuildingStats>();
|
||||
if (building.id.begins_with("residental-"))
|
||||
e.add<CBTypeResidental>();
|
||||
print_line("create_building: " + ename + " created");
|
||||
|
||||
return building.key;
|
||||
@@ -779,7 +994,7 @@ bool BuildingsData::destroy_building(const String &key)
|
||||
{
|
||||
assert(key.length() > 0);
|
||||
String ename = "base:" + key;
|
||||
print_line("destroy_building: " + ename);
|
||||
// print_line("destroy_building: " + ename);
|
||||
flecs::entity e = ecs().lookup(ename.ascii().ptr());
|
||||
assert(e.is_valid());
|
||||
e.destruct();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef BUILDINGS_DATA_H
|
||||
#define BUILFINGS_DATA_H
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <core/reference.h>
|
||||
#include <flecs.h>
|
||||
class PackedScene;
|
||||
class ResourceInteractiveLoader;
|
||||
class BuildingsData {
|
||||
@@ -21,10 +23,49 @@ public:
|
||||
Dictionary to_dict() const;
|
||||
String line_name;
|
||||
};
|
||||
Set<String> pending_scene;
|
||||
/* Scene objects data */
|
||||
//private:
|
||||
// HashMap<String, struct scene_data> scenes;
|
||||
|
||||
struct CBuildingData {
|
||||
struct BuildingsData::building building;
|
||||
};
|
||||
struct CBTypeResidental {};
|
||||
struct CBCustomLayout {
|
||||
int size;
|
||||
Vector<int> floors;
|
||||
};
|
||||
struct CBuildingStats {
|
||||
int created_entities;
|
||||
};
|
||||
struct CBuildingsEye {
|
||||
Transform cam_xform;
|
||||
int tile_x;
|
||||
int tile_z;
|
||||
};
|
||||
struct CBuildingTileData {
|
||||
using tile_key_t = std::tuple<int, int>;
|
||||
struct tile_hash
|
||||
: public std::unary_function<key_t, std::size_t> {
|
||||
std::size_t operator()(const tile_key_t &k) const
|
||||
{
|
||||
return std::get<0>(k) ^ std::get<1>(k);
|
||||
}
|
||||
};
|
||||
using tile_map_t = std::unordered_map<
|
||||
const tile_key_t, std::vector<flecs::entity>, tile_hash>;
|
||||
tile_map_t tiles;
|
||||
tile_map_t loaded_tiles;
|
||||
};
|
||||
struct CBuildingTile {
|
||||
std::tuple<int, int> tile;
|
||||
};
|
||||
struct CBuildingLoad {};
|
||||
struct CBuildingUnload {};
|
||||
struct CBuildingLoaded {};
|
||||
struct CBuildingEdited {};
|
||||
|
||||
public:
|
||||
void get_scene_keys_list(List<String> *keys) const;
|
||||
bool has_scene(const String &key) const;
|
||||
@@ -113,7 +154,6 @@ public:
|
||||
int undo_log_size;
|
||||
BuildingsData();
|
||||
virtual ~BuildingsData();
|
||||
static BuildingsData *singleton;
|
||||
|
||||
public:
|
||||
void read_buildings_json(const String &buildings_path);
|
||||
@@ -128,8 +168,9 @@ public:
|
||||
void update_building_transform(const String &key,
|
||||
const Transform &xform);
|
||||
bool has_building(const String &key);
|
||||
String get_closest_building(const Transform &xform);
|
||||
static BuildingsData *get_singleton();
|
||||
static void cleanup();
|
||||
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;
|
||||
void load_tile(int x, int z);
|
||||
};
|
||||
#endif
|
||||
@@ -67,6 +67,8 @@ void BuildingsEditor::event_handler(const String &event,
|
||||
handle_create_building();
|
||||
else if (event == "button:delete_building")
|
||||
delete_building_handler();
|
||||
else if (event == "button:edit_layout")
|
||||
create_layout_editor();
|
||||
else if (event == "result:get_closest_building") {
|
||||
select_building(args[0], args[3], args[4]);
|
||||
if (get_buildings_editor_mode() == 2 /* rotate */) {
|
||||
@@ -249,8 +251,26 @@ void BuildingsEditor::mouse_press(const Vector2 &position)
|
||||
case 0: {
|
||||
/* select */
|
||||
Transform xform(Basis(), proj);
|
||||
editor->editor_command("get_closest_building",
|
||||
varray(xform));
|
||||
flecs::entity e =
|
||||
BaseData::get_singleton()
|
||||
->get()
|
||||
.get_mut<BuildingsData>()
|
||||
->get_closest_building_entity(xform);
|
||||
assert(e.is_valid());
|
||||
e.add<BuildingsData::CBuildingEdited>();
|
||||
const BuildingsData::CBuildingData *b =
|
||||
e.get<BuildingsData::CBuildingData>();
|
||||
print_line("selected: " + b->building.id);
|
||||
select_building(b->building.xform, b->building.key,
|
||||
b->building.id);
|
||||
if (get_buildings_editor_mode() == 2 /* rotate */) {
|
||||
/* move rot cursor too */
|
||||
get_as_node<Spatial>("%building_rot_cursor")
|
||||
->set_global_transform(
|
||||
selected_building_xform);
|
||||
}
|
||||
// editor->editor_command("get_closest_building",
|
||||
// varray(xform));
|
||||
} break;
|
||||
case 1: {
|
||||
/* move */
|
||||
@@ -417,3 +437,8 @@ const Node *BuildingsEditor::scene() const
|
||||
const Node *ret = editor->get_tree()->get_current_scene();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BuildingsEditor::create_layout_editor()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -37,5 +37,6 @@ public:
|
||||
template <class T> const T *get_as_node(const String &path) const;
|
||||
Node *scene();
|
||||
const Node *scene() const;
|
||||
void create_layout_editor();
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#undef NDEBUG
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <core/os/memory.h>
|
||||
@@ -14,8 +16,61 @@
|
||||
#include "editor_event.h"
|
||||
#include "game_event.h"
|
||||
#include "persistent_data.h"
|
||||
#include "buildings_data.h"
|
||||
#include "npc.h"
|
||||
|
||||
static ConfigFile npcconf;
|
||||
NPC::NPC(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<NPC>();
|
||||
ecs.component<struct NPCBase>();
|
||||
ecs.observer<NPCControl>()
|
||||
.event(flecs::OnSet)
|
||||
.each([&](flecs::iter &it, size_t i,
|
||||
struct NPCControl &control) {
|
||||
if (control.command_id == NPCControl::CMD_PRESIM) {
|
||||
generate_random_npcs(it.world());
|
||||
simulate_past(it.world());
|
||||
}
|
||||
it.entity(i).destruct();
|
||||
});
|
||||
}
|
||||
/* should be run on new game */
|
||||
void NPC::simulate_past(flecs::world ecs)
|
||||
{
|
||||
int i;
|
||||
Error err = npcconf.load("res://config/npc.conf");
|
||||
assert(err == OK);
|
||||
#if 0
|
||||
for (i = 0; i < 100000; i++) {
|
||||
if (npcconf.has_section("npc/" + itos(i))) {
|
||||
String name = npcconf.get_value("npc/" + itos(i),
|
||||
"name", "Nobody");
|
||||
int age =
|
||||
npcconf.get_value("npc/" + itos(i), "age", 18);
|
||||
String sex = npcconf.get_value("npc/" + itos(i), "name",
|
||||
"male");
|
||||
flecs::entity e =
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// assert(false);
|
||||
}
|
||||
|
||||
void NPC::generate_random_npcs(flecs::world ecs)
|
||||
{
|
||||
flecs::query<const BuildingsData::CBuildingData> query =
|
||||
ecs.query_builder<const BuildingsData::CBuildingData>()
|
||||
.with<BuildingsData::CBTypeResidental>()
|
||||
.build();
|
||||
query.each([](flecs::entity e, const BuildingsData::CBuildingData &bd) {
|
||||
print_line(String(e.name()));
|
||||
print_line("id: " + bd.building.id);
|
||||
});
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
class NPCSaveData : public PersistentData::SaveHandler {
|
||||
public:
|
||||
NPC *npc;
|
||||
@@ -39,58 +94,6 @@ struct NPCBase {
|
||||
int id;
|
||||
};
|
||||
|
||||
struct NPCSkeleton {
|
||||
String skeleton_path;
|
||||
};
|
||||
|
||||
struct NPCNode {
|
||||
Skeleton *skeleton;
|
||||
};
|
||||
|
||||
struct NPCLocation {
|
||||
Transform global_location, local_position;
|
||||
};
|
||||
struct NPCTarget {
|
||||
Transform target;
|
||||
};
|
||||
struct NPCTargetKey {
|
||||
String location_key;
|
||||
};
|
||||
struct NPCBackgroundMotion {
|
||||
float speed;
|
||||
};
|
||||
|
||||
struct NPCBody {
|
||||
/* TODO: implement */
|
||||
void *nothing;
|
||||
};
|
||||
|
||||
struct NPCAnimation {
|
||||
/* TODO: implement */
|
||||
void *nothing;
|
||||
};
|
||||
|
||||
struct NPCResidence {
|
||||
String residence_key;
|
||||
};
|
||||
|
||||
struct NPCOccupation {
|
||||
/* building key */
|
||||
String occupation_key;
|
||||
// index in building's job list
|
||||
int job_type;
|
||||
int start_hour;
|
||||
int end_hour;
|
||||
// bit field from mon to sun
|
||||
int week_days;
|
||||
};
|
||||
|
||||
/* Assign leisure on the go depending on
|
||||
character mood and stats */
|
||||
struct NPCLeisure {
|
||||
String leisure_key;
|
||||
};
|
||||
|
||||
struct module {
|
||||
module(flecs::world &ecs)
|
||||
{
|
||||
@@ -105,70 +108,12 @@ struct module {
|
||||
ecs.component<struct NPCResidence>();
|
||||
ecs.component<struct NPCOccupation>();
|
||||
ecs.component<struct NPCLeisure>();
|
||||
ecs.observer<struct NPCSkeleton>()
|
||||
.event(flecs::OnSet)
|
||||
.with<struct NPCBase>()
|
||||
.with<struct NPCLocation>()
|
||||
.write<struct NPCNode>()
|
||||
.each([](flecs::entity e, const NPCSkeleton &s) {
|
||||
Ref<SkeletonData> skeleton_data;
|
||||
String path = s.skeleton_path;
|
||||
if (e.has<NPCNode>()) {
|
||||
if (e.get<NPCNode>()->skeleton) {
|
||||
e.get_mut<NPCNode>()
|
||||
->skeleton
|
||||
->queue_delete();
|
||||
e.get_mut<NPCNode>()->skeleton =
|
||||
nullptr;
|
||||
e.remove<NPCNode>();
|
||||
}
|
||||
}
|
||||
Node *root = SceneTree::get_singleton()
|
||||
->get_current_scene();
|
||||
if (!root) {
|
||||
print_error("No scene");
|
||||
return;
|
||||
}
|
||||
skeleton_data = ResourceLoader::load(
|
||||
path, "SkeletonData");
|
||||
if (skeleton_data.is_valid()) {
|
||||
Skeleton *skeleton = memnew(Skeleton);
|
||||
|
||||
skeleton_data->load_skeleton(skeleton);
|
||||
e.set<NPCNode>({ skeleton });
|
||||
root->call_deferred("add_child",
|
||||
skeleton);
|
||||
} else
|
||||
print_error(
|
||||
"ERROR: Could not load skeleton: " +
|
||||
path);
|
||||
});
|
||||
ecs.observer<struct NPCSkeleton>()
|
||||
.event(flecs::OnRemove)
|
||||
.write<struct NPCNode>()
|
||||
.each([](flecs::entity e, const NPCSkeleton &s) {
|
||||
if (e.has<NPCNode>()) {
|
||||
if (e.get<NPCNode>()->skeleton) {
|
||||
e.get_mut<NPCNode>()
|
||||
->skeleton
|
||||
->queue_delete();
|
||||
e.get_mut<NPCNode>()->skeleton =
|
||||
nullptr;
|
||||
e.remove<NPCNode>();
|
||||
}
|
||||
}
|
||||
});
|
||||
/* moving NPC despawned NPC */
|
||||
ecs.system<NPCBase>("Update").each(
|
||||
[](flecs::entity e, NPCBase &b) {
|
||||
// TODO: implement;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
NPC::NPC()
|
||||
void NPC::create()
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
ecs.import <NPCModule::module>();
|
||||
@@ -176,10 +121,12 @@ NPC::NPC()
|
||||
if (base.is_valid()) {
|
||||
/* create components for top level */
|
||||
}
|
||||
#if 0
|
||||
EditorEvent::get_singleton()->event.add_listener(
|
||||
this, &NPC::editor_event_handler);
|
||||
GameEvent::get_singleton()->event.add_listener(
|
||||
this, &NPC::game_event_handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
NPC *NPC::get_singleton()
|
||||
@@ -202,70 +149,13 @@ void NPC::update(float delta)
|
||||
{
|
||||
}
|
||||
|
||||
flecs::entity NPC::foreground_character(int id)
|
||||
{
|
||||
String ch_name = "ch_" + itos(id);
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity base = ecs.lookup("characters");
|
||||
flecs::entity ch = base.lookup(ch_name.ascii().ptr());
|
||||
if (!ch.is_valid())
|
||||
ch = ecs.entity(ch_name.ascii().ptr()).child_of(base);
|
||||
assert(ch.is_valid());
|
||||
if (!ch.has<NPCModule::NPCBase>())
|
||||
ch.set<NPCModule::NPCBase>({ id });
|
||||
return ch;
|
||||
}
|
||||
|
||||
void NPC::background_character(int id)
|
||||
{
|
||||
String ch_name = "ch_" + itos(id);
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity base = ecs.lookup("characters");
|
||||
flecs::entity ch = base.lookup(ch_name.ascii().ptr());
|
||||
assert(ch.is_valid());
|
||||
/* remove all components */
|
||||
std::vector<flecs::entity_t> keep_components = {
|
||||
ecs.component<NPCModule::NPCBase>()
|
||||
};
|
||||
ch.each([&ch, keep_components](flecs::entity_t c) {
|
||||
if (std::find(keep_components.begin(), keep_components.end(),
|
||||
c) == keep_components.end())
|
||||
ch.remove(c);
|
||||
});
|
||||
}
|
||||
|
||||
void NPC::get_character_list(List<int> *character_list)
|
||||
{
|
||||
Error err;
|
||||
DirAccess *d = DirAccess::open("res://character/config", &err);
|
||||
d->list_dir_begin();
|
||||
String conf_path;
|
||||
while ((conf_path = d->get_next()) != "") {
|
||||
ConfigFile config;
|
||||
config.load(conf_path);
|
||||
int id = config.get_value("base", "id");
|
||||
}
|
||||
d->list_dir_end();
|
||||
}
|
||||
|
||||
void NPC::editor_event_handler(const String &event, const Vector<Variant> &args)
|
||||
{
|
||||
if (event == "npc_foreground") {
|
||||
int npc_id = args[0];
|
||||
foreground_character(npc_id);
|
||||
} else if (event == "npc_background") {
|
||||
int npc_id = args[0];
|
||||
background_character(npc_id);
|
||||
}
|
||||
/* not implemented */
|
||||
}
|
||||
|
||||
void NPC::game_event_handler(const String &event, const Vector<Variant> &args)
|
||||
{
|
||||
if (event == "npc_foreground") {
|
||||
int npc_id = args[0];
|
||||
foreground_character(npc_id);
|
||||
} else if (event == "npc_background") {
|
||||
int npc_id = args[0];
|
||||
background_character(npc_id);
|
||||
}
|
||||
/* not implemented */
|
||||
}
|
||||
#endif
|
||||
@@ -1,23 +1,37 @@
|
||||
#ifndef NPC_H_
|
||||
#define NPC_H_
|
||||
class ConfigFile;
|
||||
class NPC {
|
||||
static NPC *singleton;
|
||||
NPC();
|
||||
|
||||
#include <flecs.h>
|
||||
struct NPC {
|
||||
NPC(flecs::world &ecs);
|
||||
struct NPCBase {
|
||||
int id;
|
||||
int age; // days
|
||||
};
|
||||
struct NPCSexMale {};
|
||||
struct NPCSexFemale {};
|
||||
struct NPCControl {
|
||||
enum {
|
||||
CMD_IDLE = 0,
|
||||
CMD_PRESIM = 1,
|
||||
CMD_LOAD = 2,
|
||||
CMD_SAVE = 3,
|
||||
CMD_SIM = 4,
|
||||
};
|
||||
int command_id;
|
||||
};
|
||||
void simulate_past(flecs::world ecs);
|
||||
void generate_random_npcs(flecs::world ecs);
|
||||
#if 0
|
||||
public:
|
||||
static NPC *get_singleton();
|
||||
static void create();
|
||||
static void cleanup();
|
||||
virtual ~NPC();
|
||||
void update(float delta);
|
||||
flecs::entity foreground_character(int id);
|
||||
void background_character(int id);
|
||||
static void get_character_list(List<int> *character_list);
|
||||
|
||||
private:
|
||||
void editor_event_handler(const String &event,
|
||||
const Vector<Variant> &args);
|
||||
void game_event_handler(const String &event,
|
||||
const Vector<Variant> &args);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "npc/importer.h"
|
||||
#include "npc/skeleton_data.h"
|
||||
#include "base_data.h"
|
||||
#include "building_grid_instance.h"
|
||||
#include "buildings/building_layout_instance.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
static void _editor_init()
|
||||
@@ -30,6 +32,8 @@ void register_stream_types()
|
||||
ClassDB::register_class<BuildingLayoutEditor>();
|
||||
ClassDB::register_class<MainTabs>();
|
||||
ClassDB::register_class<SkeletonData>();
|
||||
ClassDB::register_class<BuildingGridInstance>();
|
||||
ClassDB::register_class<BuildingLayoutInstance>();
|
||||
#ifdef TOOLS_ENABLED
|
||||
ClassDB::APIType prev_api = ClassDB::get_current_api();
|
||||
ClassDB::set_current_api(ClassDB::API_EDITOR);
|
||||
|
||||
@@ -431,15 +431,20 @@ void RoadLinesEditor::move_cursor_to_point()
|
||||
set_ui_cursor_position(xform.origin);
|
||||
}
|
||||
|
||||
static inline BuildingsData *bd()
|
||||
{
|
||||
BuildingsData *ret =
|
||||
BaseData::get_singleton()->get().get_mut<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RoadLinesEditor::move_cursor_to_closest_building()
|
||||
{
|
||||
print_line("move_cursor_to_closest_building");
|
||||
Vector3 pt = get_cursor_position();
|
||||
const String &key =
|
||||
BuildingsData::get_singleton()->get_closest_building(
|
||||
Transform(Basis(), pt));
|
||||
const Transform &xform =
|
||||
BuildingsData::get_singleton()->get_building(key).xform;
|
||||
const String &key = bd()->get_closest_building(Transform(Basis(), pt));
|
||||
const Transform &xform = bd()->get_building(key).xform;
|
||||
set_cursor_position(xform.origin);
|
||||
Spatial *cursor = get_as_node<Spatial>(cursor_name);
|
||||
if (!cursor->is_visible())
|
||||
@@ -1120,8 +1125,7 @@ class EdgeEditorHandler {
|
||||
continue;
|
||||
}
|
||||
const AABB &aabb_building =
|
||||
BuildingsData::get_singleton()
|
||||
->building_aabbs[buildings[i].id];
|
||||
bd()->building_aabbs[buildings[i].id];
|
||||
Transform building_rot(
|
||||
Basis().rotated(
|
||||
Vector3(0, 1, 0),
|
||||
@@ -1302,8 +1306,7 @@ class EdgeEditorHandler {
|
||||
String lot_id = side.lot_type;
|
||||
if (side.buildings.size() > 1) {
|
||||
const AABB &aabb_lot =
|
||||
BuildingsData::get_singleton()
|
||||
->building_aabbs
|
||||
bd()->building_aabbs
|
||||
["lot-" +
|
||||
lot_id];
|
||||
bool pack_result =
|
||||
@@ -1372,8 +1375,7 @@ class EdgeEditorHandler {
|
||||
String lot_id = side.lot_type;
|
||||
if (side.buildings.size() > 1) {
|
||||
const AABB &aabb_lot =
|
||||
BuildingsData::get_singleton()
|
||||
->building_aabbs
|
||||
bd()->building_aabbs
|
||||
["lot-" +
|
||||
lot_id];
|
||||
bool pack_result =
|
||||
|
||||
@@ -487,6 +487,21 @@ struct LotPacker {
|
||||
Vector<String> buildings;
|
||||
float area;
|
||||
};
|
||||
inline BuildingsData *bd()
|
||||
{
|
||||
BuildingsData *ret = BaseData::get_singleton()
|
||||
->get()
|
||||
.get_mut<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
const inline BuildingsData *bd() const
|
||||
{
|
||||
const BuildingsData *ret =
|
||||
BaseData::get_singleton()->get().get<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
Vector<struct config_buildings> lot_buildings_residental,
|
||||
lot_buildings_commercial, lot_buildings_industrial;
|
||||
void get_building_list(const String &varname,
|
||||
@@ -502,8 +517,7 @@ struct LotPacker {
|
||||
for (j = 0; j < entries.size(); j++) {
|
||||
String bname = entries[j];
|
||||
cb.buildings.push_back(bname);
|
||||
AABB aabb = BuildingsData::get_singleton()
|
||||
->building_aabbs[bname];
|
||||
AABB aabb = get_building_type_aabb(bname);
|
||||
cb.area += aabb.size.x * aabb.size.z;
|
||||
print_line("config building: " + bname);
|
||||
}
|
||||
@@ -826,18 +840,22 @@ out_bad:
|
||||
}
|
||||
bool tmp_found = false;
|
||||
int office_count = 0;
|
||||
AABB get_building_aabb(const String &key)
|
||||
AABB get_building_aabb(const String &key) const
|
||||
{
|
||||
const struct BuildingsData::building &b =
|
||||
BuildingsData::get_singleton()->get_building(key);
|
||||
const AABB &building_aabb =
|
||||
BuildingsData::get_singleton()->building_aabbs[b.id];
|
||||
bd()->get_building(key);
|
||||
const AABB &building_aabb = bd()->building_aabbs[b.id];
|
||||
return building_aabb;
|
||||
}
|
||||
AABB get_building_type_aabb(const String &building) const
|
||||
{
|
||||
const AABB &building_aabb = bd()->building_aabbs[building];
|
||||
return building_aabb;
|
||||
}
|
||||
Transform get_building_transform(const String &key)
|
||||
{
|
||||
const struct BuildingsData::building &b =
|
||||
BuildingsData::get_singleton()->get_building(key);
|
||||
bd()->get_building(key);
|
||||
return b.xform;
|
||||
}
|
||||
AABB get_aabb_transformed(const String &key)
|
||||
@@ -863,8 +881,7 @@ out_bad:
|
||||
.each([&](flecs::entity e, Lot &lot_) {
|
||||
assert(e.get<Lot>()->polygon.points.size() > 0);
|
||||
List<String> buildings;
|
||||
BuildingsData::get_singleton()
|
||||
->get_building_keys_list(&buildings);
|
||||
bd()->get_building_keys_list(&buildings);
|
||||
List<String>::Element *be = buildings.front();
|
||||
e.get_mut<Lot>()->polygon.update_aabb();
|
||||
if (e.has<PreOccupied>())
|
||||
@@ -872,8 +889,7 @@ out_bad:
|
||||
while (be) {
|
||||
const String &key = be->get();
|
||||
const struct BuildingsData::building &b =
|
||||
BuildingsData::get_singleton()
|
||||
->get_building(key);
|
||||
bd()->get_building(key);
|
||||
if (key.begins_with("road__")) {
|
||||
be = be->next();
|
||||
continue;
|
||||
@@ -935,8 +951,7 @@ out_bad:
|
||||
lb.buildings[i];
|
||||
const String &key = mp.second;
|
||||
const struct BuildingsData::building &b =
|
||||
BuildingsData::get_singleton()
|
||||
->get_building(key);
|
||||
bd()->get_building(key);
|
||||
Rect2 building_rect =
|
||||
get_rect_transformed(key);
|
||||
Rect2 lot_rect =
|
||||
@@ -1096,19 +1111,19 @@ out_bad:
|
||||
lot.polygon.update_aabb();
|
||||
});
|
||||
}
|
||||
#if 0
|
||||
float get_required_area(const Vector<String> &buildings) const
|
||||
{
|
||||
float ret = 0.0f;
|
||||
int i;
|
||||
for (i = 0; i < (int)buildings.size(); i++) {
|
||||
const String &building = buildings[i];
|
||||
const AABB &building_aabb =
|
||||
BuildingsData::get_singleton()
|
||||
->building_aabbs[building];
|
||||
const AABB &building_aabb = get_building_aabb(building);
|
||||
ret += building_aabb.size.x * building_aabb.size.z;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
int get_selected_building(const Lot &lot,
|
||||
Vector<struct config_buildings> &lbs)
|
||||
{
|
||||
@@ -1200,9 +1215,8 @@ out_bad:
|
||||
const String &building =
|
||||
buildings[i];
|
||||
const AABB &building_aabb =
|
||||
BuildingsData::get_singleton()
|
||||
->building_aabbs
|
||||
[building];
|
||||
get_building_type_aabb(
|
||||
building);
|
||||
AABB result = pack_item(
|
||||
e,
|
||||
building_aabb,
|
||||
|
||||
@@ -86,22 +86,27 @@ struct RoadLinesProcessing {
|
||||
String road_center_mesh_path, road_mid_mesh_path,
|
||||
road_sidewalk_mesh_path;
|
||||
int debug_flags;
|
||||
static struct RoadLinesProcessing *singleton;
|
||||
static RoadLinesProcessing *get_singleton()
|
||||
{
|
||||
if (!singleton)
|
||||
singleton = memnew(RoadLinesProcessing);
|
||||
return singleton;
|
||||
}
|
||||
DebugGeo *dbg;
|
||||
ConfigFile config;
|
||||
static ConfigFile config;
|
||||
RoadLinesProcessing()
|
||||
: dbg(nullptr)
|
||||
{
|
||||
singleton = this;
|
||||
Error err = config.load("res://config/stream.conf");
|
||||
assert(err == OK);
|
||||
}
|
||||
RoadLinesProcessing &operator=(const RoadLinesProcessing &other)
|
||||
{
|
||||
dbg = other.dbg;
|
||||
debug_flags = other.debug_flags;
|
||||
edges = other.edges;
|
||||
nodes = other.nodes;
|
||||
road_center_mesh_path = other.road_center_mesh_path;
|
||||
road_mid_mesh_path = other.road_mid_mesh_path;
|
||||
road_sidewalk_mesh_path = other.road_sidewalk_mesh_path;
|
||||
side_refs = other.side_refs;
|
||||
wedges = other.wedges;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void create_nodes(const std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
@@ -125,23 +130,37 @@ struct RoadLinesProcessing {
|
||||
xform = xform * rot;
|
||||
return xform;
|
||||
}
|
||||
inline BuildingsData *bd()
|
||||
{
|
||||
BuildingsData *ret = BaseData::get_singleton()
|
||||
->get()
|
||||
.get_mut<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline const BuildingsData *bd() const
|
||||
{
|
||||
const BuildingsData *ret =
|
||||
BaseData::get_singleton()->get().get<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void create_building_structure(const BuildingsData::building &b)
|
||||
{
|
||||
assert(b.key.begins_with("road__"));
|
||||
assert(b.id.length() > 0);
|
||||
assert(b.key.length() > 0);
|
||||
if (BuildingsData::get_singleton()->has_building(b.key)) {
|
||||
BuildingsData::get_singleton()->remove_scene_item(
|
||||
b.id, b.key);
|
||||
BuildingsData::get_singleton()->destroy_building(b.key);
|
||||
if (bd()->has_building(b.key)) {
|
||||
bd()->remove_scene_item(b.id, b.key);
|
||||
bd()->destroy_building(b.key);
|
||||
}
|
||||
BuildingsData::get_singleton()->create_building(b);
|
||||
if (!BuildingsData::get_singleton()->has_scene(b.id))
|
||||
BuildingsData::get_singleton()->create_scene_data(
|
||||
b.id, b.key);
|
||||
bd()->create_building(b);
|
||||
if (!bd()->has_scene(b.id))
|
||||
bd()->create_scene_data(b.id, b.key);
|
||||
else
|
||||
BuildingsData::get_singleton()->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("at: " + (b.xform.origin.operator String()));
|
||||
print_line("created ok");
|
||||
@@ -414,394 +433,6 @@ out2:;
|
||||
/* FIXME: need to generate lots from wedges, not lines (because intersections)
|
||||
and join lots on the same line segment if they are adjacent and of similar depth
|
||||
and not too narrow */
|
||||
void update_lot_depths()
|
||||
{
|
||||
#if 0
|
||||
int i, j, k;
|
||||
struct line_check {
|
||||
struct side_ref side;
|
||||
Vector3 normal;
|
||||
float depth;
|
||||
Vector3 startp;
|
||||
AABB rect;
|
||||
};
|
||||
|
||||
LocalVector<struct line_check> check_lines;
|
||||
RoadLinesProcessing *r = RoadLinesProcessing::get_singleton();
|
||||
if (r->nodes.size() == 0)
|
||||
return;
|
||||
if (r->nodes.empty())
|
||||
goto out_skip_end;
|
||||
// dbg->set_material_override(dbg_mat);
|
||||
if (!dbg &&
|
||||
VisualServer::get_singleton()->is_render_loop_enabled()) {
|
||||
dbg = memnew(DebugGeo);
|
||||
SceneTree::get_singleton()
|
||||
->get_current_scene()
|
||||
->call_deferred("add_child", dbg);
|
||||
}
|
||||
print_line("wedges size:" + itos(r->nodes.size()));
|
||||
dbg->clear();
|
||||
dbg->begin(Mesh::PRIMITIVE_LINES);
|
||||
dbg->set_color(Color(1, 0, 0, 1));
|
||||
dbg->set_color(Color(1, 0, 0, 1));
|
||||
for (i = 0; i < (int)r->nodes.size(); i++) {
|
||||
const std::vector<struct wedge> &ws = wedges[i];
|
||||
int wsize = ws.size();
|
||||
for (j = 0; j < wsize; j++) {
|
||||
const struct wedge &w = wedges[i][j];
|
||||
struct RoadLinesData::road_edge_side mside1 =
|
||||
RoadLinesData::get_singleton()
|
||||
->get_line_edge_side(
|
||||
w.side1_ref.line_key,
|
||||
w.side1_ref.edge,
|
||||
w.side1_ref.side);
|
||||
struct RoadLinesData::road_edge_side mside2 =
|
||||
RoadLinesData::get_singleton()
|
||||
->get_line_edge_side(
|
||||
w.side2_ref.line_key,
|
||||
w.side2_ref.edge,
|
||||
w.side2_ref.side);
|
||||
Vector3 d1 = (w.p[1] - w.p[0]).normalized();
|
||||
Vector3 d2 = (w.p[2] - w.p[1]).normalized();
|
||||
Vector3 n1 = (w.p[0] - w.y[0]).normalized();
|
||||
Vector3 n2 = (w.p[1] - w.y[1]).normalized();
|
||||
Vector3 n3 = (w.p[2] - w.y[2]).normalized();
|
||||
mside1.lot_depth_eff =
|
||||
MAX(mside1.lot_depth_eff, 200.0f);
|
||||
mside2.lot_depth_eff =
|
||||
MAX(mside2.lot_depth_eff, 200.0f);
|
||||
assert(mside1.lot_depth_eff > 0.001);
|
||||
assert(mside2.lot_depth_eff > 0.001);
|
||||
struct line_check lc1, lc2;
|
||||
int nlanes1 = w.width1 / 5.0f;
|
||||
int nlanes2 = w.width2 / 5.0f;
|
||||
float m = (w.p[1] - w.y[1]).length() /
|
||||
(w.p[0] - w.y[0]).length();
|
||||
lc1.side = w.side1_ref;
|
||||
lc1.depth = mside1.lot_depth_eff;
|
||||
lc1.normal = n1;
|
||||
lc1.startp = w.p[0] + (w.width1 - 4.0f) * n1;
|
||||
lc1.rect.position = lc1.startp;
|
||||
lc1.rect.size = Vector3();
|
||||
lc1.rect.expand_to(lc1.startp + n1 * lc1.depth);
|
||||
lc2.side = w.side2_ref;
|
||||
lc2.depth = MIN(mside1.lot_depth_eff,
|
||||
mside2.lot_depth_eff);
|
||||
lc2.normal = n2;
|
||||
Vector3 x = n2 * (w.width2 - 4.0f) * m;
|
||||
|
||||
lc2.startp = w.p[1] + x;
|
||||
lc2.rect.position = lc2.startp;
|
||||
lc2.rect.size = Vector3();
|
||||
lc2.rect.expand_to(lc2.startp + n2 * lc2.depth);
|
||||
check_lines.push_back(lc1);
|
||||
check_lines.push_back(lc2);
|
||||
}
|
||||
}
|
||||
assert(check_lines.size() > 0);
|
||||
for (i = 0; i < (int)check_lines.size(); i++) {
|
||||
for (j = 0; j < (int)r->nodes.size(); j++) {
|
||||
const std::vector<struct wedge> &ws = wedges[j];
|
||||
int wsize = ws.size();
|
||||
for (k = 0; k < wsize; k++) {
|
||||
const struct wedge &w = ws[k];
|
||||
Vector3 p0 = check_lines[i].startp;
|
||||
Vector3 p1 =
|
||||
p0 +
|
||||
check_lines[i].normal *
|
||||
check_lines[i].depth;
|
||||
Vector3 p2 = w.p[0];
|
||||
Vector3 p3 = w.p[1];
|
||||
Vector3 s, t;
|
||||
/* samey segments do not intersect */
|
||||
if (p0.is_equal_approx(p2) &&
|
||||
p1.is_equal_approx(p3))
|
||||
continue;
|
||||
if (p0.is_equal_approx(p3) &&
|
||||
p1.is_equal_approx(p2))
|
||||
continue;
|
||||
/* segments which share a point do not intersect */
|
||||
if (p0.is_equal_approx(p2))
|
||||
continue;
|
||||
if (p0.is_equal_approx(p3))
|
||||
continue;
|
||||
if (p1.is_equal_approx(p3))
|
||||
continue;
|
||||
if (p1.is_equal_approx(p2))
|
||||
continue;
|
||||
assert(!p0.is_equal_approx(p1) &&
|
||||
!p2.is_equal_approx(p3));
|
||||
Geometry::get_closest_points_between_segments(
|
||||
p0, p1, p2, p3, s, t);
|
||||
if (s.is_equal_approx(p0))
|
||||
continue;
|
||||
if (s.is_equal_approx(p1))
|
||||
continue;
|
||||
if (t.is_equal_approx(p2))
|
||||
continue;
|
||||
if (t.is_equal_approx(p3))
|
||||
continue;
|
||||
assert(!s.is_equal_approx(p0));
|
||||
assert(!s.is_equal_approx(p1));
|
||||
assert(!t.is_equal_approx(p2));
|
||||
assert(!t.is_equal_approx(p3));
|
||||
Vector3 mx(t.x, s.y, t.z);
|
||||
if (!s.is_equal_approx(mx))
|
||||
continue;
|
||||
if (Math::abs(s.y - t.y) < 5.0f) {
|
||||
if (s.is_equal_approx(mx)) {
|
||||
float l1 =
|
||||
p0.distance_to(
|
||||
s);
|
||||
check_lines[i]
|
||||
.depth = MIN(
|
||||
check_lines[i]
|
||||
.depth,
|
||||
l1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (int)check_lines.size(); i++) {
|
||||
Vector3 p0 = check_lines[i].startp;
|
||||
Vector3 p1 = p0 + check_lines[i].normal *
|
||||
check_lines[i].depth;
|
||||
assert(p0.distance_squared_to(p1) > 0.001f);
|
||||
dbg->set_color(Color(1, 0, 0, 1));
|
||||
dbg->add_vertex(p0);
|
||||
dbg->add_vertex(p0 + Vector3(0, 100, 0));
|
||||
dbg->add_vertex(p1);
|
||||
dbg->add_vertex(p1 + Vector3(0, 100, 0));
|
||||
dbg->set_color(Color(0, 0, 1, 1));
|
||||
dbg->add_vertex(p0);
|
||||
dbg->add_vertex(p1);
|
||||
for (j = 0; j < (int)check_lines.size(); j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
Vector3 p2 = check_lines[j].startp;
|
||||
Vector3 p3 = p2 + check_lines[j].normal *
|
||||
check_lines[j].depth;
|
||||
Vector3 s, t;
|
||||
/* samey segments do not intersect */
|
||||
if (p0.is_equal_approx(p2) &&
|
||||
p1.is_equal_approx(p3))
|
||||
continue;
|
||||
if (p0.is_equal_approx(p3) &&
|
||||
p1.is_equal_approx(p2))
|
||||
continue;
|
||||
/* segments which share a point do not intersect */
|
||||
if (p0.is_equal_approx(p2))
|
||||
continue;
|
||||
if (p0.is_equal_approx(p3))
|
||||
continue;
|
||||
if (p1.is_equal_approx(p3))
|
||||
continue;
|
||||
if (p1.is_equal_approx(p2))
|
||||
continue;
|
||||
assert(!p0.is_equal_approx(p1) &&
|
||||
!p2.is_equal_approx(p3));
|
||||
Geometry::get_closest_points_between_segments(
|
||||
p0, p1, p2, p3, s, t);
|
||||
if (s.is_equal_approx(p0))
|
||||
continue;
|
||||
if (s.is_equal_approx(p1))
|
||||
continue;
|
||||
if (t.is_equal_approx(p2))
|
||||
continue;
|
||||
if (t.is_equal_approx(p3))
|
||||
continue;
|
||||
assert(!s.is_equal_approx(p0));
|
||||
assert(!s.is_equal_approx(p1));
|
||||
assert(!t.is_equal_approx(p2));
|
||||
assert(!t.is_equal_approx(p3));
|
||||
Vector3 mx(t.x, s.y, t.z);
|
||||
if (!s.is_equal_approx(mx))
|
||||
continue;
|
||||
if (Math::abs(s.y - t.y) < 5.0f) {
|
||||
if (s.is_equal_approx(mx)) {
|
||||
dbg->set_color(
|
||||
Color(0, 1, 0, 1));
|
||||
dbg->add_vertex(
|
||||
s +
|
||||
Vector3(-0.5, 15, 0));
|
||||
dbg->add_vertex(s + Vector3(0.5,
|
||||
100,
|
||||
0));
|
||||
float l1 = p0.distance_to(s);
|
||||
float l2 = p2.distance_to(t);
|
||||
check_lines[i].depth = MIN(
|
||||
check_lines[i].depth,
|
||||
l1);
|
||||
check_lines[j].depth = MIN(
|
||||
check_lines[j].depth,
|
||||
l2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dbg->end();
|
||||
dbg->clear();
|
||||
dbg->begin(Mesh::PRIMITIVE_LINES);
|
||||
dbg->set_color(Color(1, 0, 0, 1));
|
||||
for (i = 0; i < (int)check_lines.size(); i++) {
|
||||
Vector3 p0 = check_lines[i].startp;
|
||||
Vector3 p1 = p0 + check_lines[i].normal *
|
||||
check_lines[i].depth;
|
||||
assert(p0.distance_squared_to(p1) > 0.001f);
|
||||
dbg->set_color(Color(1, 0, 0, 1));
|
||||
dbg->add_vertex(p0);
|
||||
dbg->add_vertex(p0 + Vector3(0, 100, 0));
|
||||
dbg->add_vertex(p1);
|
||||
dbg->add_vertex(p1 + Vector3(0, 100, 0));
|
||||
dbg->set_color(Color(0, 0, 1, 1));
|
||||
dbg->add_vertex(p0);
|
||||
dbg->add_vertex(p1);
|
||||
struct side_ref &side1 = check_lines[i].side;
|
||||
struct RoadLinesData::road_edge_side mside1 =
|
||||
RoadLinesData::get_singleton()
|
||||
->get_line_edge_side(side1.line_key,
|
||||
side1.edge,
|
||||
side1.side);
|
||||
mside1.lot_depth_eff = check_lines[i].depth;
|
||||
mside1.lot_depth = mside1.lot_depth_eff;
|
||||
int bad_count = 0;
|
||||
int lot_points = mside1.lot_points.size();
|
||||
assert(lot_points == 0 || lot_points == 2);
|
||||
for (j = 0; j < mside1.lot_points.size(); j++) {
|
||||
if (!mside1.lot_points[j].is_equal_approx(p0))
|
||||
bad_count++;
|
||||
if (!mside1.lot_points[j].is_equal_approx(p1))
|
||||
bad_count++;
|
||||
}
|
||||
if (bad_count < 2) {
|
||||
mside1.lot_points.push_back(p0);
|
||||
mside1.lot_points.push_back(p1);
|
||||
}
|
||||
if (side1.side == 0)
|
||||
RoadLinesData::get_singleton()
|
||||
->set_line_edge_left(side1.line_key,
|
||||
side1.edge,
|
||||
mside1);
|
||||
else
|
||||
RoadLinesData::get_singleton()
|
||||
->set_line_edge_right(side1.line_key,
|
||||
side1.edge,
|
||||
mside1);
|
||||
}
|
||||
dbg->end();
|
||||
dbg->begin(Mesh::PRIMITIVE_LINES);
|
||||
dbg->set_color(Color(0, 1, 1, 1));
|
||||
{
|
||||
List<String> line_keys;
|
||||
List<String>::Element *line_e;
|
||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||
rld->get_road_lines_key_list(&line_keys);
|
||||
line_e = line_keys.front();
|
||||
while (line_e) {
|
||||
const String &key = line_e->get();
|
||||
print_line("line: " + key);
|
||||
int edges = rld->get_line_edge_count(key);
|
||||
for (i = 0; i < edges; i++) {
|
||||
RoadLinesData::road_edge_side left =
|
||||
rld->get_line_edge_left(key, i);
|
||||
RoadLinesData::road_edge_side right =
|
||||
rld->get_line_edge_right(key,
|
||||
i);
|
||||
print_line("edge: " + itos(i) +
|
||||
" left: lot: " +
|
||||
itos(left.lot));
|
||||
print_line("edge: " + itos(i) +
|
||||
" right: lot: " +
|
||||
itos(right.lot));
|
||||
print_line(
|
||||
"lot_points: left: " +
|
||||
itos(left.lot_points.size()));
|
||||
print_line(
|
||||
"lot_points: right: " +
|
||||
itos(right.lot_points.size()));
|
||||
for (j = 0;
|
||||
j < (int)left.lot_points.size();
|
||||
j++) {
|
||||
dbg->add_vertex(
|
||||
left.lot_points[j] +
|
||||
Vector3(0, 20, 0));
|
||||
dbg->add_vertex(
|
||||
left.lot_points[j] +
|
||||
Vector3(0, 200, 0));
|
||||
}
|
||||
if (left.lot_points.size() == 6) {
|
||||
int index[] = { 0, 1, 1, 3,
|
||||
3, 5, 5, 4 };
|
||||
for (j = 0; j < 8; j++) {
|
||||
dbg->add_vertex(
|
||||
left.lot_points
|
||||
[index[j]] +
|
||||
Vector3(0, 25,
|
||||
0));
|
||||
print_line(
|
||||
itos(j) + ": " +
|
||||
left.lot_points[index[j]]
|
||||
.
|
||||
operator String());
|
||||
}
|
||||
assert(false);
|
||||
} else if (left.lot_points.size() ==
|
||||
4) {
|
||||
int index[] = { 0, 1, 1, 3,
|
||||
3, 2, 2, 0 };
|
||||
for (j = 0; j < 8; j++)
|
||||
dbg->add_vertex(
|
||||
left.lot_points
|
||||
[index[j]] +
|
||||
Vector3(0, 25,
|
||||
0));
|
||||
}
|
||||
for (j = 0;
|
||||
j < (int)right.lot_points.size();
|
||||
j++) {
|
||||
dbg->add_vertex(
|
||||
right.lot_points[j] +
|
||||
Vector3(0, 20, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[j] +
|
||||
Vector3(0, 200, 0));
|
||||
}
|
||||
if (right.lot_points.size() == 6) {
|
||||
dbg->add_vertex(
|
||||
right.lot_points[0] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[1] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[1] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[3] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[3] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[2] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[2] +
|
||||
Vector3(0, 25, 0));
|
||||
dbg->add_vertex(
|
||||
right.lot_points[0] +
|
||||
Vector3(0, 25, 0));
|
||||
}
|
||||
}
|
||||
line_e = line_e->next();
|
||||
}
|
||||
}
|
||||
dbg->end();
|
||||
out_skip_end:;
|
||||
#endif
|
||||
}
|
||||
void create_structures()
|
||||
{
|
||||
List<String> keys;
|
||||
@@ -852,13 +483,13 @@ out_skip_end:;
|
||||
->get()
|
||||
.query_builder<Lot>()
|
||||
.build()
|
||||
.each([&](flecs::entity e, Lot &lot) {
|
||||
.each([&](flecs::entity ev, Lot &lot) {
|
||||
BaseData::get_singleton()
|
||||
->get()
|
||||
.query_builder<Lot>()
|
||||
.build()
|
||||
.each([&](flecs::entity we, Lot &wlot) {
|
||||
if (e != we) {
|
||||
if (ev != we) {
|
||||
lot.polygon
|
||||
.update_aabb();
|
||||
wlot.polygon
|
||||
@@ -868,7 +499,7 @@ out_skip_end:;
|
||||
.length() >
|
||||
100000.0f *
|
||||
1000000.0f)
|
||||
e.destruct();
|
||||
ev.destruct();
|
||||
else if (wlot.polygon
|
||||
.aabb
|
||||
.size
|
||||
@@ -890,7 +521,7 @@ out_skip_end:;
|
||||
.area())
|
||||
we.destruct();
|
||||
else
|
||||
e.destruct();
|
||||
ev.destruct();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -899,12 +530,11 @@ out_skip_end:;
|
||||
->get()
|
||||
.query_builder<Lot>()
|
||||
.build()
|
||||
.each([&](flecs::entity e, const Lot &lot) {
|
||||
.each([&](flecs::entity em, const Lot &lot) {
|
||||
List<Pair<AABB, String> > lot_data;
|
||||
Lot::get_lot_data(e, &lot_data);
|
||||
Lot::get_lot_data(em, &lot_data);
|
||||
List<Pair<AABB, String> >::Element *lot_e =
|
||||
lot_data.front();
|
||||
int ccount = 0;
|
||||
while (lot_e) {
|
||||
Pair<AABB, String> data = lot_e->get();
|
||||
Vector3 center = data.first.position;
|
||||
@@ -924,8 +554,8 @@ out_skip_end:;
|
||||
data.first.
|
||||
operator String());
|
||||
for (j = 0;
|
||||
j <
|
||||
lot.polygon.points.size();
|
||||
j < (int)lot.polygon.points
|
||||
.size();
|
||||
j++)
|
||||
print_line(
|
||||
"polygon: " +
|
||||
@@ -942,11 +572,11 @@ out_skip_end:;
|
||||
->get()
|
||||
.query_builder<Lot>()
|
||||
.build()
|
||||
.each([&](flecs::entity e, const Lot &lot) {
|
||||
.each([&](flecs::entity ev, const Lot &lot) {
|
||||
List<Pair<AABB, String> > lot_data;
|
||||
List<Transform> lot_xform;
|
||||
Lot::get_lot_data(e, &lot_data);
|
||||
Lot::get_lot_rotations(e, &lot_xform);
|
||||
Lot::get_lot_data(ev, &lot_data);
|
||||
Lot::get_lot_rotations(ev, &lot_xform);
|
||||
List<Pair<AABB, String> >::Element *lot_e =
|
||||
lot_data.front();
|
||||
List<Transform>::Element *lotx_e =
|
||||
@@ -955,7 +585,7 @@ out_skip_end:;
|
||||
while (lot_e) {
|
||||
Pair<AABB, String> data = lot_e->get();
|
||||
String key = "road__lot__" +
|
||||
String(e.path()) + "_" +
|
||||
String(ev.path()) + "_" +
|
||||
itos(ccount);
|
||||
key = key.replace("#", "_");
|
||||
BuildingsData::building b;
|
||||
@@ -1290,7 +920,8 @@ out_skip_end:;
|
||||
{
|
||||
int i, j;
|
||||
Contours *contours = Contours::get_singleton();
|
||||
RoadLinesProcessing *r = RoadLinesProcessing::get_singleton();
|
||||
// RoadLinesProcessing *r = BaseData::get_singleton() ->get() .get_mut<RoadLinesProcessing>();
|
||||
RoadLinesProcessing *r = this;
|
||||
if (r->nodes.size() == 0)
|
||||
return;
|
||||
struct wedge_data {
|
||||
@@ -1393,13 +1024,6 @@ out_skip_end:;
|
||||
~RoadLinesProcessing()
|
||||
{
|
||||
}
|
||||
static void cleanup()
|
||||
{
|
||||
if (singleton) {
|
||||
memfree(singleton);
|
||||
singleton = nullptr;
|
||||
}
|
||||
}
|
||||
void set_debug_flags(int debug_flags)
|
||||
{
|
||||
this->debug_flags = debug_flags;
|
||||
@@ -1490,11 +1114,11 @@ out_skip_end:;
|
||||
}
|
||||
d->end();
|
||||
}
|
||||
RoadLinesProcessing::get_singleton()->create_structures();
|
||||
create_structures();
|
||||
print_line("ROAD SETUP DONE");
|
||||
}
|
||||
};
|
||||
RoadLinesProcessing *RoadLinesProcessing::singleton;
|
||||
ConfigFile RoadLinesProcessing::config;
|
||||
|
||||
class RoadMeshProcessing {
|
||||
struct mesh_data {
|
||||
@@ -1513,11 +1137,41 @@ class RoadMeshProcessing {
|
||||
}
|
||||
}
|
||||
};
|
||||
struct wedge_paths {
|
||||
Vector3 path1[3];
|
||||
Vector3 path2[3];
|
||||
};
|
||||
struct lane {
|
||||
Vector3 p[3];
|
||||
String use_mesh; /** use mesh namefor this lane */
|
||||
Transform xform1, xform2; /** rotations for ends
|
||||
of this wedge start and end */
|
||||
Transform xform_m1, xform_m2; /** rotations for middle point of
|
||||
wedge for end and start of segment */
|
||||
float l_seg1[3]; /** start segment scale */
|
||||
float l_seg2[3]; /** end segment scale */
|
||||
};
|
||||
HashMap<String, struct mesh_data> road_meshes;
|
||||
MergeGroup *road_mgroup;
|
||||
std::vector<MeshInstance *> nodes_mi;
|
||||
|
||||
public:
|
||||
RoadMeshProcessing &operator=(const RoadMeshProcessing &other)
|
||||
{
|
||||
road_meshes = other.road_meshes;
|
||||
road_mgroup = other.road_mgroup;
|
||||
nodes_mi = other.nodes_mi;
|
||||
return *this;
|
||||
}
|
||||
#if 0
|
||||
RoadMeshProcessing &operator=(const RoadMeshProcessing &&other)
|
||||
{
|
||||
road_meshes = std::move(other.road_meshes);
|
||||
road_mgroup = std::move(other.road_mgroup);
|
||||
nodes_mi = std::move(other.nodes_mi);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
void load_road_mesh(const String &category, const String &name,
|
||||
const String &path)
|
||||
{
|
||||
@@ -1542,10 +1196,6 @@ public:
|
||||
}
|
||||
road_meshes[category + "/" + name] = md;
|
||||
}
|
||||
struct wedge_paths {
|
||||
Vector3 path1[3];
|
||||
Vector3 path2[3];
|
||||
};
|
||||
void get_paths(struct wedge_paths &paths, const struct wedge &w)
|
||||
{
|
||||
Vector3 p1 = w.y[0] - w.y[1];
|
||||
@@ -1561,16 +1211,6 @@ public:
|
||||
paths.path2[1] = p2a;
|
||||
paths.path2[2] = p3a;
|
||||
}
|
||||
struct lane {
|
||||
Vector3 p[3];
|
||||
String use_mesh; /** use mesh namefor this lane */
|
||||
Transform xform1, xform2; /** rotations for ends
|
||||
of this wedge start and end */
|
||||
Transform xform_m1, xform_m2; /** rotations for middle point of
|
||||
wedge for end and start of segment */
|
||||
float l_seg1[3]; /** start segment scale */
|
||||
float l_seg2[3]; /** end segment scale */
|
||||
};
|
||||
/**
|
||||
* @brief transform mesh segment using start rotation @xform1
|
||||
* ane end rotation @xform2
|
||||
@@ -1599,9 +1239,11 @@ public:
|
||||
assert(vertices.size() > 0);
|
||||
assert(indices.size() > 0);
|
||||
float dlen = xform1.origin.distance_to(xform2.origin);
|
||||
#if 0
|
||||
float offt = 0.0f;
|
||||
if (dlen > start_offset)
|
||||
offt = start_offset;
|
||||
#endif
|
||||
int id;
|
||||
Vector3 dir = xform2.origin - xform1.origin;
|
||||
dir = dir.normalized();
|
||||
@@ -2004,7 +1646,9 @@ public:
|
||||
assert(out_surfaces[h].size() >=
|
||||
ArrayMesh::ARRAY_MAX);
|
||||
float sideroad_l = 3.0f;
|
||||
#if 0
|
||||
float lot_depth1 = mside1.lot_depth;
|
||||
#endif
|
||||
if (k == params.nlanes &&
|
||||
mside1.lot > 0) { /* sidewalk */
|
||||
Vector3 dir = lanes[k].xform_m1.origin -
|
||||
@@ -2197,7 +1841,10 @@ public:
|
||||
void create_road_meshes(Node *base)
|
||||
{
|
||||
int i;
|
||||
RoadLinesProcessing *r = RoadLinesProcessing::get_singleton();
|
||||
RoadLinesProcessing *r =
|
||||
BaseData::get_singleton()
|
||||
->get()
|
||||
.get_mut<RoadLinesProcessing>();
|
||||
clear_road_meshes();
|
||||
road_mgroup = memnew(MergeGroup);
|
||||
road_mgroup->set_param(MergeGroup::PARAM_GROUP_SIZE, 16);
|
||||
@@ -2217,38 +1864,33 @@ public:
|
||||
nodes_mi.push_back(mi);
|
||||
}
|
||||
}
|
||||
static RoadMeshProcessing *singleton;
|
||||
static RoadMeshProcessing *get_singleton()
|
||||
{
|
||||
if (!singleton)
|
||||
singleton = memnew(RoadMeshProcessing);
|
||||
return singleton;
|
||||
}
|
||||
RoadMeshProcessing()
|
||||
: road_mgroup(nullptr)
|
||||
{
|
||||
singleton = this;
|
||||
}
|
||||
static void cleanup()
|
||||
{
|
||||
if (singleton) {
|
||||
memdelete(singleton);
|
||||
singleton = nullptr;
|
||||
}
|
||||
BaseData::get_singleton()->get().ensure<RoadLinesProcessing>();
|
||||
}
|
||||
};
|
||||
RoadMeshProcessing *RoadMeshProcessing::singleton;
|
||||
|
||||
void RoadProcessing::road_setup(Node *target, int debug_flags)
|
||||
{
|
||||
RoadLinesProcessing::get_singleton()->set_debug_flags(debug_flags);
|
||||
RoadLinesProcessing::get_singleton()->road_setup();
|
||||
RoadMeshProcessing::get_singleton()->create_road_meshes(target);
|
||||
BaseData::get_singleton()->get().ensure<RoadLinesProcessing>();
|
||||
BaseData::get_singleton()->get().ensure<RoadMeshProcessing>();
|
||||
RoadLinesProcessing *r =
|
||||
BaseData::get_singleton()->get().get_mut<RoadLinesProcessing>();
|
||||
r->set_debug_flags(debug_flags);
|
||||
r->road_setup();
|
||||
BaseData::get_singleton()
|
||||
->get()
|
||||
.get_mut<RoadMeshProcessing>()
|
||||
->create_road_meshes(target);
|
||||
}
|
||||
|
||||
void RoadProcessing::remove_road_meshes(Node *target)
|
||||
{
|
||||
RoadMeshProcessing::get_singleton()->clear_road_meshes();
|
||||
BaseData::get_singleton()
|
||||
->get()
|
||||
.get_mut<RoadMeshProcessing>()
|
||||
->clear_road_meshes();
|
||||
}
|
||||
|
||||
void RoadProcessing::load_data()
|
||||
@@ -2258,30 +1900,31 @@ void RoadProcessing::load_data()
|
||||
ConfigFile config;
|
||||
Error result = config.load("res://config/stream.conf");
|
||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "center", config.get_value("road", "center_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "mid", config.get_value("road", "mid_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "sidewalk",
|
||||
BaseData::get_singleton()->get().ensure<RoadMeshProcessing>();
|
||||
RoadMeshProcessing *rmp =
|
||||
BaseData::get_singleton()->get().get_mut<RoadMeshProcessing>();
|
||||
assert(rmp);
|
||||
rmp->load_road_mesh("common", "center",
|
||||
config.get_value("road", "center_mesh"));
|
||||
rmp->load_road_mesh("common", "mid",
|
||||
config.get_value("road", "mid_mesh"));
|
||||
rmp->load_road_mesh("common", "sidewalk",
|
||||
config.get_value("road", "sidewalk_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "sidewalk_start",
|
||||
rmp->load_road_mesh("common", "sidewalk_start",
|
||||
config.get_value("road", "sidewalk_start_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "sidewalk_end",
|
||||
rmp->load_road_mesh("common", "sidewalk_end",
|
||||
config.get_value("road", "sidewalk_end_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "sidewalk_sideroad",
|
||||
rmp->load_road_mesh("common", "sidewalk_sideroad",
|
||||
config.get_value("road", "sidewalk_sideroad_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "lot", config.get_value("road", "lot_mesh"));
|
||||
rmp->load_road_mesh("common", "lot",
|
||||
config.get_value("road", "lot_mesh"));
|
||||
}
|
||||
|
||||
void RoadDebug::_notification(int which)
|
||||
{
|
||||
int i, j;
|
||||
RoadLinesProcessing *r = RoadLinesProcessing::get_singleton();
|
||||
RoadLinesProcessing *r =
|
||||
BaseData::get_singleton()->get().get_mut<RoadLinesProcessing>();
|
||||
std::unordered_map<int, RoadLinesProcessing::edgedata>::iterator it;
|
||||
switch (which) {
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
@@ -2379,6 +2022,6 @@ void RoadDebug::_notification(int which)
|
||||
}
|
||||
void RoadProcessing::cleanup()
|
||||
{
|
||||
RoadLinesProcessing::cleanup();
|
||||
RoadMeshProcessing::cleanup();
|
||||
BaseData::get_singleton()->get().remove<RoadLinesProcessing>();
|
||||
BaseData::get_singleton()->get().remove<RoadMeshProcessing>();
|
||||
}
|
||||
|
||||
@@ -17,9 +17,17 @@
|
||||
#include "base_data.h"
|
||||
#include "npc/npc.h"
|
||||
#include "stream.h"
|
||||
static inline BuildingsData *bd()
|
||||
{
|
||||
BuildingsData *ret =
|
||||
BaseData::get_singleton()->get().get_mut<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define data() (BuildingsData::get_singleton())
|
||||
#define data() (bd())
|
||||
|
||||
#if 0
|
||||
void StreamWorld::create_tilemap()
|
||||
{
|
||||
tiles.clear();
|
||||
@@ -41,6 +49,7 @@ void StreamWorld::create_tilemap()
|
||||
nullptr);
|
||||
print_verbose("Tile count: " + itos(tiles.size()));
|
||||
}
|
||||
#endif
|
||||
|
||||
void StreamWorld::update_view()
|
||||
{
|
||||
@@ -80,6 +89,7 @@ void StreamWorld::update_view()
|
||||
current_x = world_extent + 1;
|
||||
current_z = world_extent + 1;
|
||||
}
|
||||
#if 0
|
||||
eye = viewer->get_global_transform().origin;
|
||||
int tile_x = int(eye.x / tile_size);
|
||||
int tile_z = int(eye.z / tile_size);
|
||||
@@ -124,7 +134,8 @@ void StreamWorld::update_view()
|
||||
|
||||
current_x = tile_x;
|
||||
current_z = tile_z;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StreamWorld::viewer_dead()
|
||||
@@ -141,6 +152,7 @@ void StreamWorld::terrain_dead()
|
||||
set_process(false);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void StreamWorld::load_tile(int tx, int ty)
|
||||
{
|
||||
int i;
|
||||
@@ -151,6 +163,11 @@ void StreamWorld::load_tile(int tx, int ty)
|
||||
": " /* + data()->get_building(items[i]).id */);
|
||||
const String &bkey = items[i];
|
||||
load_building(bkey);
|
||||
flecs::entity eb = data()->get_building_entity(bkey);
|
||||
if (eb.is_valid()) {
|
||||
if (!eb.has<BuildingsData::CBuildingLoaded>())
|
||||
eb.add<BuildingsData::CBuildingLoad>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,52 +180,39 @@ void StreamWorld::erase_tile(int tx, int ty)
|
||||
print_verbose("unload item: " + itos(i) + ": key: " + items[i] +
|
||||
": " /* + data()->get_building(items[i]).id */);
|
||||
const String &bkey = items[i];
|
||||
unload_building(bkey);
|
||||
flecs::entity eb = data()->get_building_entity(bkey);
|
||||
if (eb.is_valid()) {
|
||||
if (eb.has<BuildingsData::CBuildingLoaded>())
|
||||
eb.add<BuildingsData::CBuildingUnload>();
|
||||
print_verbose("Removing key:" + bkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void StreamWorld::load_building(const String &key)
|
||||
{
|
||||
request_item(0, key);
|
||||
flecs::entity eb = data()->get_building_entity(key);
|
||||
// print_line("key: " + bkey);
|
||||
if (!eb.is_valid()) {
|
||||
print_error("ERROR: Entity does not exist: " + key);
|
||||
return;
|
||||
}
|
||||
if (!eb.has<BuildingsData::CBuildingLoaded>())
|
||||
eb.add<BuildingsData::CBuildingLoad>();
|
||||
}
|
||||
|
||||
void StreamWorld::unload_building(const String &key)
|
||||
{
|
||||
request_item(1, key);
|
||||
}
|
||||
|
||||
void StreamWorld::request_item(int type, const String &bkey)
|
||||
{
|
||||
bool debug = false;
|
||||
/* bkey can contain "::"'s so need to replae them with underscores */
|
||||
String ekey = bkey;
|
||||
if (bkey.begins_with("road__")) {
|
||||
print_verbose("loading building: " + ekey);
|
||||
debug = true;
|
||||
}
|
||||
String id = data()->get_building(ekey).id;
|
||||
if (debug)
|
||||
print_verbose("building id: " + id);
|
||||
if (id == "empty")
|
||||
flecs::entity eb = data()->get_building_entity(key);
|
||||
// print_line("key: " + bkey);
|
||||
if (!eb.is_valid()) {
|
||||
print_error("ERROR: Entity does not exist: " + key);
|
||||
return;
|
||||
switch (type) {
|
||||
case 0:
|
||||
if (debug)
|
||||
print_verbose("add to scene id: " + id);
|
||||
if (!data()->has_scene(id))
|
||||
data()->create_scene_data(id, ekey);
|
||||
else
|
||||
data()->add_scene_item(id, ekey);
|
||||
if (debug)
|
||||
print_verbose("added to scene id: " + id);
|
||||
break;
|
||||
case 1: {
|
||||
print_verbose("Removing key:" + ekey);
|
||||
if (data()->has_scene(id)) {
|
||||
data()->remove_scene_item(id, ekey);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
if (eb.has<BuildingsData::CBuildingLoaded>())
|
||||
eb.add<BuildingsData::CBuildingUnload>();
|
||||
print_verbose("Removing key:" + key);
|
||||
}
|
||||
|
||||
void StreamWorld::update_items()
|
||||
@@ -395,7 +399,9 @@ void StreamWorld::run_command(const String &command,
|
||||
RoadProcessing::road_setup(this, args[0]);
|
||||
else
|
||||
RoadProcessing::road_setup(this, 0);
|
||||
#if 0
|
||||
create_tilemap();
|
||||
#endif
|
||||
update_view();
|
||||
data()->scene_update();
|
||||
update_items();
|
||||
@@ -419,7 +425,9 @@ void StreamWorld::run_command(const String &command,
|
||||
terrain->set_generator(gen);
|
||||
update_items();
|
||||
RoadProcessing::road_setup(this, 0);
|
||||
#if 0
|
||||
create_tilemap();
|
||||
#endif
|
||||
update_view();
|
||||
update_items();
|
||||
assert(false);
|
||||
@@ -460,7 +468,9 @@ void StreamWorld::_notification(int which)
|
||||
nullptr);
|
||||
assert(false);
|
||||
#endif
|
||||
#if 0
|
||||
create_tilemap();
|
||||
#endif
|
||||
set_process(true);
|
||||
if (Engine::get_singleton()->is_editor_hint())
|
||||
break;
|
||||
@@ -516,14 +526,17 @@ StreamWorld::StreamWorld()
|
||||
, initialized(false)
|
||||
, frame_count(0)
|
||||
{
|
||||
BaseData::get_singleton()->get().component<BuildingsData>();
|
||||
Error result = config.load("res://config/stream.conf");
|
||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||
BaseData::get_singleton()->get().ensure<BuildingsData>();
|
||||
RoadProcessing::load_data();
|
||||
world_extent = config.get_value("world", "world_extent");
|
||||
tile_size = config.get_value("world", "tile_size");
|
||||
ERR_FAIL_COND_MSG(tile_size <= 0 || world_extent <= 0 ||
|
||||
world_extent <= tile_size,
|
||||
"Failed to configure world");
|
||||
#if 0
|
||||
create_tilemap();
|
||||
tile_map_t::iterator map_it = tiles.begin();
|
||||
while (map_it != tiles.end()) {
|
||||
@@ -534,11 +547,11 @@ StreamWorld::StreamWorld()
|
||||
itos(tile_buildings.size()));
|
||||
map_it++;
|
||||
}
|
||||
#endif
|
||||
view_distance = config.get_value("world", "view_distance");
|
||||
NPC *npc = NPC::get_singleton();
|
||||
if (!npc) {
|
||||
assert(false);
|
||||
}
|
||||
BaseData::get_singleton()->get().import <NPC>();
|
||||
flecs::entity npcctrl = BaseData::get_singleton()->get().entity();
|
||||
npcctrl.set<NPC::NPCControl>({ NPC::NPCControl::CMD_PRESIM });
|
||||
initialized = true;
|
||||
}
|
||||
void StreamWorld::cleanup()
|
||||
|
||||
@@ -16,6 +16,7 @@ private:
|
||||
VoxelLodTerrain *terrain;
|
||||
Node *current_scene;
|
||||
ConfigFile config;
|
||||
#if 0
|
||||
using tile_key_t = std::tuple<int, int>;
|
||||
struct tile_hash : public std::unary_function<key_t, std::size_t> {
|
||||
std::size_t operator()(const tile_key_t &k) const
|
||||
@@ -28,6 +29,7 @@ private:
|
||||
Vector3 eye;
|
||||
tile_map_t tiles;
|
||||
tile_map_t loaded_tiles;
|
||||
#endif
|
||||
|
||||
int world_extent;
|
||||
int tile_size;
|
||||
@@ -36,15 +38,14 @@ private:
|
||||
int current_x, current_z;
|
||||
int frame_count;
|
||||
void _notification(int which);
|
||||
void create_tilemap();
|
||||
// void create_tilemap();
|
||||
void update_view();
|
||||
void viewer_dead();
|
||||
void terrain_dead();
|
||||
void load_tile(int tx, int ty);
|
||||
void erase_tile(int tx, int ty);
|
||||
// void load_tile(int tx, int ty);
|
||||
// void erase_tile(int tx, int ty);
|
||||
void load_building(const String &key);
|
||||
void unload_building(const String &key);
|
||||
void request_item(int type, const String &key);
|
||||
void update_items();
|
||||
void remove_building(const String &key);
|
||||
void remove_generated_stuff();
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
#include "signal_handler.h"
|
||||
#include "terrain_editor.h"
|
||||
|
||||
static inline BuildingsData *bd()
|
||||
{
|
||||
BuildingsData *ret =
|
||||
BaseData::get_singleton()->get().get_mut<BuildingsData>();
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TerrainEditor::exit()
|
||||
{
|
||||
if (active)
|
||||
@@ -358,15 +366,13 @@ end:;
|
||||
case 2001: {
|
||||
List<String> building_keys;
|
||||
List<String>::Element *e;
|
||||
BuildingsData::get_singleton()->get_building_keys_list(
|
||||
&building_keys);
|
||||
BuildingsData::get_singleton()->build_building_aabbs();
|
||||
bd()->get_building_keys_list(&building_keys);
|
||||
bd()->build_building_aabbs();
|
||||
e = building_keys.front();
|
||||
while (e) {
|
||||
const String &key = e->get();
|
||||
const BuildingsData::building &b =
|
||||
BuildingsData::get_singleton()
|
||||
->get_building(key);
|
||||
bd()->get_building(key);
|
||||
float i, j;
|
||||
print_line("building type: " + b.id);
|
||||
print_line("building key: " + b.key);
|
||||
@@ -376,8 +382,7 @@ end:;
|
||||
"building elevation: " +
|
||||
String::num(imgmapper->get_height_full(
|
||||
b.xform.origin)));
|
||||
AABB aabb = BuildingsData::get_singleton()
|
||||
->building_aabbs[b.id];
|
||||
AABB aabb = bd()->building_aabbs[b.id];
|
||||
print_line("building AABB: " +
|
||||
(aabb.operator String()));
|
||||
float max_elevation_c = -Math_INF,
|
||||
@@ -458,9 +463,7 @@ end:;
|
||||
// assert(Math::abs(max_elevation2 -
|
||||
// max_elevation) < 1.0f);
|
||||
#endif
|
||||
Transform xform = BuildingsData::get_singleton()
|
||||
->get_building(key)
|
||||
.xform;
|
||||
Transform xform = bd()->get_building(key).xform;
|
||||
xform.origin.y = max_elevation * 1.4998f - 0.5f;
|
||||
editor->editor_command(
|
||||
"update_building_transform",
|
||||
@@ -474,7 +477,7 @@ end:;
|
||||
e = e->next();
|
||||
}
|
||||
imgmapper->save_dirty_tiles();
|
||||
BuildingsData::get_singleton()->save_buildings();
|
||||
bd()->save_buildings();
|
||||
editor->editor_command("nudge_generator", varray());
|
||||
} break;
|
||||
default:
|
||||
|
||||
@@ -426,19 +426,21 @@ void MainTabs::_notification(int which)
|
||||
/* 43 */
|
||||
"Delete Building", "buildings_delete_building", "delete_building", varray(),
|
||||
/* 47 */
|
||||
"Create Building", "buildings_create_building", "create_building", varray(),
|
||||
"Layout", "buildings_edit_layout", "edit_layout", varray(),
|
||||
/* 51 */
|
||||
"Save Buildings", "buildings_save", "buildings_save", varray(),
|
||||
"Create Building", "buildings_create_building", "create_building", varray(),
|
||||
/* 55 */
|
||||
"Save Buildings", "buildings_save", "buildings_save", varray(),
|
||||
/* 59 */
|
||||
0, Vector2(0, 80), "lines_list_building",
|
||||
/* 58 */
|
||||
/* 62 */
|
||||
"Assign To Line", "buildings_assign_to_line"
|
||||
/* 60 */
|
||||
/* 64 */
|
||||
};
|
||||
/* clang-format on */
|
||||
ui_field::ui_field_builder(
|
||||
this, tab,
|
||||
"l_p{v{lh{e#!+e#!+e#!+b#!}lh{e#!+e#!+e#!+}h{le#!b#!}_lo#!Mlo#!T_b#!Qb#!QB#!qi.#!b#!}}",
|
||||
"l_p{v{lh{e#!+e#!+e#!+b#!}lh{e#!+e#!+e#!+}h{le#!b#!}_lo#!Mlo#!T_b#!Qb#!Qb#!QB#!qi.#!b#!}}",
|
||||
args_data.data(),
|
||||
args_data.size());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user