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/io/config_file.h>
#include <scene/resources/packed_scene.h>
#include <scene/3d/spatial.h>
#include <scene/3d/mesh_instance.h>
#include "from_string.h"
#include "buildings_data.h"
@@ -14,6 +16,8 @@ BuildingsData::BuildingsData()
: undo_log_size(64)
{
load_data();
fill_door_locations();
build_building_aabbs();
}
BuildingsData::~BuildingsData()
@@ -28,6 +32,45 @@ BuildingsData *BuildingsData::get_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()
{
if (singleton) {
@@ -127,13 +170,6 @@ void BuildingsData::building::from_dict(building *b, const Dictionary &dict,
b->guests.resize(guests.size());
for (i = 0; i < (int)guests.size(); 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());
if (worktime.size() == 0) {
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
{
int i;
Dictionary ret;
ret["id"] = id;
ret["pattern_id"] = pattern_id;
@@ -166,21 +201,6 @@ Dictionary BuildingsData::building::to_dict() const
ret["workers"] = w;
v2a(g, guests);
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;
wt.resize(2);
wt[0] = worktime[0];
@@ -245,4 +265,80 @@ void BuildingsData::undo()
struct checkpoint_data cp = *undo_log.end();
building_data = cp.building_data;
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;
int pattern_id;
Vector<int> residents, workers, guests;
Vector<Transform> doors;
String key;
Transform xform;
AABB aabb;
int worktime[2];
bool generated;
static void from_dict(struct building *b,
@@ -30,8 +28,10 @@ public:
std::vector<int> buildings;
};
HashMap<String, struct scene_data> scenes;
/* Data for each building type */
/* Path for each building type */
HashMap<String, String> building_data;
HashMap<String, Vector<Transform> > building_doors;
HashMap<String, AABB> building_aabbs;
/* Data for each building in a world */
std::vector<struct building> buildings;
struct checkpoint_data {
@@ -52,6 +52,8 @@ public:
void load_data();
void checkpoint();
void undo();
void fill_door_locations();
void build_building_aabbs();
static BuildingsData *get_singleton();
static void cleanup();
};

View File

@@ -138,7 +138,6 @@ public:
&HandleDeleteButton::delete_building_handler);
}
};
static HandleDeleteButton *delete_button_handler = nullptr;
static std::vector<Object *> ui_handlers;
BuildingsEditor::BuildingsEditor(WorldEditor *editor)
@@ -156,37 +155,35 @@ void BuildingsEditor::exit()
void BuildingsEditor::activate()
{
assert(!active);
editor->event.add_listener(this, &BuildingsEditor::event_handler);
print_line("BuildingsEditor ACTIVE");
Array args;
ui_handlers.push_back(memnew(HandleButton(
this, "%buildings_create_building", "create_building", args)));
ui_handlers.push_back(memnew(HandleChangeBuildingType(this)));
ui_handlers.push_back(memnew(HandleDeleteButton(this)));
int i;
for (i = 0; i < (int)ui_handlers.size(); i++)
assert(ui_handlers[i]);
if (!delete_button_handler)
delete_button_handler = memnew(HandleDeleteButton(this));
assert(delete_button_handler);
active = true;
editor->event.add_listener(this, &BuildingsEditor::event_handler);
}
void BuildingsEditor::deactivate()
{
assert(active);
if (delete_button_handler) {
memdelete(delete_button_handler);
delete_button_handler = nullptr;
}
editor->event.remove_listener(this, &BuildingsEditor::event_handler);
print_line("BuildingsEditor DEACTIVE");
int i;
for (i = 0; i < (int)ui_handlers.size(); i++)
memdelete(ui_handlers[i]);
ui_handlers.clear();
editor->event.remove_listener(this, &BuildingsEditor::event_handler);
active = false;
}
void BuildingsEditor::event_handler(const String &event, const Array &args)
{
assert(active);
print_line("E::" + event);
if (event == "mouse_drag")
mouse_drag(args[0]);
else if (event == "mouse_press")
@@ -242,6 +239,12 @@ inline void BuildingsEditor::mode_visibility(int mode, const String &path)
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)
activate();
int mode = get_buildings_editor_mode();
@@ -259,10 +262,16 @@ void BuildingsEditor::update(float delta)
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;
if (editor->get_camera_mode() != 3)
}
if (editor->get_camera_mode() != 3) {
print_verbose("bad camera mode: " +
itos(editor->get_camera_mode()));
return;
}
print_line("in mouse_drag");
Camera *camera = editor->get_viewport()->get_camera();
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)
{
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;
if (editor->get_camera_mode() != 3)
}
if (editor->get_camera_mode() != 3) {
print_verbose("bad camera mode: " +
itos(editor->get_camera_mode()));
return;
}
print_line("in mouse_press");
Camera *camera = editor->get_viewport()->get_camera();
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) +
" from: " + old_type + " to: " + new_type);
} else if (command == "create_building") {
int i;
if (args.size() == 0) {
print_error("bad command: not enough args: " + command);
return;
@@ -363,7 +362,6 @@ void StreamWorld::run_command(const String &command, const Array &args)
BuildingsData::building::from_dict(&b, building_dict, key);
data()->buildings.push_back(b);
load_building(data()->buildings.size() - 1);
// TODO: check it is enmough
} else if (command == "remove_building") {
if (args.size() == 0) {
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:
road_lines_editor->exit();
break;
case MODE_BUILDINGS:
buildings_editor->exit();
break;
}
switch (modes[button]) {
case MODE_BUILDINGS:

View File

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