Create records for doors and aabbs, debug events problem, closes #38
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user