Create records for doors and aabbs, debug events problem, closes #38

This commit is contained in:
2024-09-16 19:06:04 +03:00
parent ccc1555424
commit 49e7b9f970
6 changed files with 162 additions and 43 deletions

View File

@@ -3,6 +3,8 @@
#include <core/os/file_access.h> #include <core/os/file_access.h>
#include <core/io/config_file.h> #include <core/io/config_file.h>
#include <scene/resources/packed_scene.h> #include <scene/resources/packed_scene.h>
#include <scene/3d/spatial.h>
#include <scene/3d/mesh_instance.h>
#include "from_string.h" #include "from_string.h"
#include "buildings_data.h" #include "buildings_data.h"
@@ -14,6 +16,8 @@ BuildingsData::BuildingsData()
: undo_log_size(64) : undo_log_size(64)
{ {
load_data(); load_data();
fill_door_locations();
build_building_aabbs();
} }
BuildingsData::~BuildingsData() BuildingsData::~BuildingsData()
@@ -28,6 +32,45 @@ BuildingsData *BuildingsData::get_singleton()
return singleton; return singleton;
} }
void BuildingsData::build_building_aabbs()
{
building_aabbs.clear();
List<String> keys;
building_data.get_key_list(&keys);
List<String>::Element *e = keys.front();
while (e) {
Error err;
const String &path = building_data[e->get()];
Ref<PackedScene> ps =
ResourceLoader::load(path, "PackedScene", true, &err);
if (err == OK && ps.is_valid()) {
AABB aabb;
Node *scene = ps->instance();
List<Node *> queue;
queue.push_back(scene);
while (!queue.empty()) {
int i;
Node *item = queue.front()->get();
queue.pop_front();
MeshInstance *mi =
Object::cast_to<MeshInstance>(item);
if (mi) {
if (aabb.size.length_squared() < 0.1f)
aabb = mi->get_aabb();
else
aabb.merge_with(mi->get_aabb());
}
for (i = 0; i < item->get_child_count(); i++)
queue.push_back(item->get_child(i));
}
building_aabbs[e->get()] = aabb;
scene->queue_delete();
ps.unref();
}
e = e->next();
}
}
void BuildingsData::cleanup() void BuildingsData::cleanup()
{ {
if (singleton) { if (singleton) {
@@ -127,13 +170,6 @@ void BuildingsData::building::from_dict(building *b, const Dictionary &dict,
b->guests.resize(guests.size()); b->guests.resize(guests.size());
for (i = 0; i < (int)guests.size(); i++) for (i = 0; i < (int)guests.size(); i++)
b->guests.write[i] = guests[i]; b->guests.write[i] = guests[i];
String doors_s = dict.get("doors", "[ ]");
Array doors = from_string<Array>(doors_s);
b->doors.resize(doors.size());
for (i = 0; i < (int)doors.size(); i++)
b->doors.write[i] = from_string<Transform>(doors[i]);
String aabb_s = dict.get("aabb", AABB());
b->aabb = from_string<AABB>(aabb_s);
Array worktime = dict.get("worktime", Array()); Array worktime = dict.get("worktime", Array());
if (worktime.size() == 0) { if (worktime.size() == 0) {
worktime.resize(2); worktime.resize(2);
@@ -154,7 +190,6 @@ template <class T> static inline void v2a(Array &ret, const Vector<T> &data)
Dictionary BuildingsData::building::to_dict() const Dictionary BuildingsData::building::to_dict() const
{ {
int i;
Dictionary ret; Dictionary ret;
ret["id"] = id; ret["id"] = id;
ret["pattern_id"] = pattern_id; ret["pattern_id"] = pattern_id;
@@ -166,21 +201,6 @@ Dictionary BuildingsData::building::to_dict() const
ret["workers"] = w; ret["workers"] = w;
v2a(g, guests); v2a(g, guests);
ret["guests"] = g; ret["guests"] = g;
Array d;
v2a(d, doors);
String doors_s;
Array d2;
d2.resize(d.size());
for (i = 0; i < (int)d.size(); i++) {
String tmp;
VariantWriter::write_to_string(d[i], tmp);
d2[i] = tmp;
}
VariantWriter::write_to_string(d2, doors_s);
ret["doors"] = doors_s;
String aabb_s;
VariantWriter::write_to_string(aabb, aabb_s);
ret["aabb"] = aabb_s;
Array wt; Array wt;
wt.resize(2); wt.resize(2);
wt[0] = worktime[0]; wt[0] = worktime[0];
@@ -246,3 +266,79 @@ void BuildingsData::undo()
building_data = cp.building_data; building_data = cp.building_data;
buildings = cp.buildings; buildings = cp.buildings;
} }
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<String> keys;
building_data.get_key_list(&keys);
List<String>::Element *e = keys.front();
while (e) {
Error err;
const String &path = building_data[e->get()];
Ref<PackedScene> ps =
ResourceLoader::load(path, "PackedScene", true, &err);
if (err == OK && ps.is_valid()) {
Vector<Transform> doors;
Node *scene = ps->instance();
List<Node *> queue;
queue.push_back(scene);
while (!queue.empty()) {
int i;
Node *item = queue.front()->get();
queue.pop_front();
String name = item->get_name();
if (name.find("-portal") >= 0) {
Spatial *sp =
Object::cast_to<Spatial>(item);
if (sp) {
Transform xform =
sp->get_transform();
Node *tmp = item->get_parent();
while (tmp) {
Transform parent_xform;
Spatial *parent_sp =
Object::cast_to<
Spatial>(
tmp);
if (parent_sp)
parent_xform =
parent_sp
->get_transform();
xform = parent_xform *
xform;
tmp = tmp->get_parent();
}
doors.push_back(xform);
}
}
for (i = 0; i < item->get_child_count(); i++)
queue.push_back(item->get_child(i));
}
building_doors[e->get()] = doors;
scene->queue_delete();
ps.unref();
}
e = e->next();
}
}

View File

@@ -11,10 +11,8 @@ public:
String id; String id;
int pattern_id; int pattern_id;
Vector<int> residents, workers, guests; Vector<int> residents, workers, guests;
Vector<Transform> doors;
String key; String key;
Transform xform; Transform xform;
AABB aabb;
int worktime[2]; int worktime[2];
bool generated; bool generated;
static void from_dict(struct building *b, static void from_dict(struct building *b,
@@ -30,8 +28,10 @@ public:
std::vector<int> buildings; std::vector<int> buildings;
}; };
HashMap<String, struct scene_data> scenes; HashMap<String, struct scene_data> scenes;
/* Data for each building type */ /* Path for each building type */
HashMap<String, String> building_data; HashMap<String, String> building_data;
HashMap<String, Vector<Transform> > building_doors;
HashMap<String, AABB> building_aabbs;
/* Data for each building in a world */ /* Data for each building in a world */
std::vector<struct building> buildings; std::vector<struct building> buildings;
struct checkpoint_data { struct checkpoint_data {
@@ -52,6 +52,8 @@ public:
void load_data(); void load_data();
void checkpoint(); void checkpoint();
void undo(); void undo();
void fill_door_locations();
void build_building_aabbs();
static BuildingsData *get_singleton(); static BuildingsData *get_singleton();
static void cleanup(); static void cleanup();
}; };

View File

@@ -138,7 +138,6 @@ public:
&HandleDeleteButton::delete_building_handler); &HandleDeleteButton::delete_building_handler);
} }
}; };
static HandleDeleteButton *delete_button_handler = nullptr;
static std::vector<Object *> ui_handlers; static std::vector<Object *> ui_handlers;
BuildingsEditor::BuildingsEditor(WorldEditor *editor) BuildingsEditor::BuildingsEditor(WorldEditor *editor)
@@ -156,37 +155,35 @@ void BuildingsEditor::exit()
void BuildingsEditor::activate() void BuildingsEditor::activate()
{ {
assert(!active); assert(!active);
editor->event.add_listener(this, &BuildingsEditor::event_handler); print_line("BuildingsEditor ACTIVE");
Array args; Array args;
ui_handlers.push_back(memnew(HandleButton( ui_handlers.push_back(memnew(HandleButton(
this, "%buildings_create_building", "create_building", args))); this, "%buildings_create_building", "create_building", args)));
ui_handlers.push_back(memnew(HandleChangeBuildingType(this))); ui_handlers.push_back(memnew(HandleChangeBuildingType(this)));
ui_handlers.push_back(memnew(HandleDeleteButton(this)));
int i; int i;
for (i = 0; i < (int)ui_handlers.size(); i++) for (i = 0; i < (int)ui_handlers.size(); i++)
assert(ui_handlers[i]); assert(ui_handlers[i]);
if (!delete_button_handler)
delete_button_handler = memnew(HandleDeleteButton(this));
assert(delete_button_handler);
active = true; active = true;
editor->event.add_listener(this, &BuildingsEditor::event_handler);
} }
void BuildingsEditor::deactivate() void BuildingsEditor::deactivate()
{ {
assert(active); assert(active);
if (delete_button_handler) { editor->event.remove_listener(this, &BuildingsEditor::event_handler);
memdelete(delete_button_handler); print_line("BuildingsEditor DEACTIVE");
delete_button_handler = nullptr;
}
int i; int i;
for (i = 0; i < (int)ui_handlers.size(); i++) for (i = 0; i < (int)ui_handlers.size(); i++)
memdelete(ui_handlers[i]); memdelete(ui_handlers[i]);
ui_handlers.clear(); ui_handlers.clear();
editor->event.remove_listener(this, &BuildingsEditor::event_handler);
active = false; active = false;
} }
void BuildingsEditor::event_handler(const String &event, const Array &args) void BuildingsEditor::event_handler(const String &event, const Array &args)
{ {
assert(active);
print_line("E::" + event);
if (event == "mouse_drag") if (event == "mouse_drag")
mouse_drag(args[0]); mouse_drag(args[0]);
else if (event == "mouse_press") else if (event == "mouse_press")
@@ -242,6 +239,12 @@ inline void BuildingsEditor::mode_visibility(int mode, const String &path)
void BuildingsEditor::update(float delta) void BuildingsEditor::update(float delta)
{ {
#ifdef _VERBOSE_DEBUG
if (active)
print_line("update: " + String::num(delta) + " " +
itos(editor->get_current_mode()) + " " +
itos(editor->get_camera_mode()));
#endif
if (!active) if (!active)
activate(); activate();
int mode = get_buildings_editor_mode(); int mode = get_buildings_editor_mode();
@@ -259,10 +262,16 @@ void BuildingsEditor::update(float delta)
void BuildingsEditor::mouse_drag(const Vector2 &position) void BuildingsEditor::mouse_drag(const Vector2 &position)
{ {
if (editor->get_current_mode() != WorldEditor::MODE_BUILDINGS) if (editor->get_current_mode() != WorldEditor::MODE_BUILDINGS) {
print_verbose("bad editor mode: " +
itos(editor->get_current_mode()));
return; return;
if (editor->get_camera_mode() != 3) }
if (editor->get_camera_mode() != 3) {
print_verbose("bad camera mode: " +
itos(editor->get_camera_mode()));
return; return;
}
print_line("in mouse_drag"); print_line("in mouse_drag");
Camera *camera = editor->get_viewport()->get_camera(); Camera *camera = editor->get_viewport()->get_camera();
Vector3 start = camera->project_ray_origin(position); Vector3 start = camera->project_ray_origin(position);
@@ -337,10 +346,16 @@ void BuildingsEditor::mouse_drag(const Vector2 &position)
void BuildingsEditor::mouse_press(const Vector2 &position) void BuildingsEditor::mouse_press(const Vector2 &position)
{ {
if (editor->get_current_mode() != WorldEditor::MODE_BUILDINGS) if (editor->get_current_mode() != WorldEditor::MODE_BUILDINGS) {
print_verbose("bad editor mode: " +
itos(editor->get_current_mode()));
return; return;
if (editor->get_camera_mode() != 3) }
if (editor->get_camera_mode() != 3) {
print_verbose("bad camera mode: " +
itos(editor->get_camera_mode()));
return; return;
}
print_line("in mouse_press"); print_line("in mouse_press");
Camera *camera = editor->get_viewport()->get_camera(); Camera *camera = editor->get_viewport()->get_camera();
Vector3 start = camera->project_ray_origin(position); Vector3 start = camera->project_ray_origin(position);

View File

@@ -351,7 +351,6 @@ void StreamWorld::run_command(const String &command, const Array &args)
print_line("changed building: " + itos(id) + print_line("changed building: " + itos(id) +
" from: " + old_type + " to: " + new_type); " from: " + old_type + " to: " + new_type);
} else if (command == "create_building") { } else if (command == "create_building") {
int i;
if (args.size() == 0) { if (args.size() == 0) {
print_error("bad command: not enough args: " + command); print_error("bad command: not enough args: " + command);
return; return;
@@ -363,7 +362,6 @@ void StreamWorld::run_command(const String &command, const Array &args)
BuildingsData::building::from_dict(&b, building_dict, key); BuildingsData::building::from_dict(&b, building_dict, key);
data()->buildings.push_back(b); data()->buildings.push_back(b);
load_building(data()->buildings.size() - 1); load_building(data()->buildings.size() - 1);
// TODO: check it is enmough
} else if (command == "remove_building") { } else if (command == "remove_building") {
if (args.size() == 0) { if (args.size() == 0) {
print_error("bad command: not enough args: " + command); print_error("bad command: not enough args: " + command);

View File

@@ -172,6 +172,9 @@ void WorldEditor::tools_button(const String &button)
case MODE_ROAD_LINES: case MODE_ROAD_LINES:
road_lines_editor->exit(); road_lines_editor->exit();
break; break;
case MODE_BUILDINGS:
buildings_editor->exit();
break;
} }
switch (modes[button]) { switch (modes[button]) {
case MODE_BUILDINGS: case MODE_BUILDINGS:

View File

@@ -1,5 +1,7 @@
#ifndef WORLD_EDITOR_H #ifndef WORLD_EDITOR_H
#define WORLD_EDITOR_H #define WORLD_EDITOR_H
#undef NDEBUG
#include <cassert>
#include <list> #include <list>
#include <scene/3d/spatial.h> #include <scene/3d/spatial.h>
#include "stream.h" #include "stream.h"
@@ -71,6 +73,7 @@ public:
void add_listener(T *obj, void (T::*method)(const String &event, void add_listener(T *obj, void (T::*method)(const String &event,
const Array &args)) const Array &args))
{ {
int size = listeners.size();
auto evl = listeners.begin(); auto evl = listeners.begin();
bool bad = false; bool bad = false;
while (evl != listeners.end()) { while (evl != listeners.end()) {
@@ -83,12 +86,14 @@ public:
} }
evl++; evl++;
} }
assert(!bad);
if (bad) if (bad)
return; return;
event_listener_ptrs ev; event_listener_ptrs ev;
ev.obj = reinterpret_cast<obj_t>(obj); ev.obj = reinterpret_cast<obj_t>(obj);
ev.method = reinterpret_cast<method_t>(method); ev.method = reinterpret_cast<method_t>(method);
listeners.push_back(ev); listeners.push_back(ev);
assert((int)listeners.size() == size + 1);
} }
template <class T> template <class T>
void remove_listener(T *obj, void remove_listener(T *obj,