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/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];
|
||||||
@@ -245,4 +265,80 @@ void BuildingsData::undo()
|
|||||||
struct checkpoint_data cp = *undo_log.end();
|
struct checkpoint_data cp = *undo_log.end();
|
||||||
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user