ECS redesign for buildings layout editor
This commit is contained in:
@@ -64,249 +64,336 @@ elements={
|
||||
"type": "e1"
|
||||
}
|
||||
}
|
||||
exterior_grid={
|
||||
"default": [ {
|
||||
grid_layouts={
|
||||
"default": {
|
||||
"exterior": {
|
||||
"floor_0": [ {
|
||||
"element": "empty",
|
||||
"index": 0,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 1,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 2,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 3,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 4,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 5,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 6,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 7,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 8,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 9,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 10,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 11,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 12,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 13,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 14,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 15,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 16,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 17,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 18,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 19,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 20,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 21,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 22,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 23,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 24,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 25,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 26,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 27,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 28,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 29,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 30,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 31,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 32,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 33,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 34,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 35,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 36,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 37,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 38,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 39,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 40,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 41,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 42,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 43,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 44,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 45,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 46,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 47,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 48,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 49,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 50,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 51,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 52,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 53,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 54,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 55,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 56,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 57,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 58,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 59,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 60,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 61,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 62,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 63,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 64,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 65,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 66,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 67,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 68,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 69,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 70,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 71,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "corner",
|
||||
"index": 72,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "side_window",
|
||||
"index": 73,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "side_window",
|
||||
"index": 74,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "side_door",
|
||||
"index": 75,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "side_window",
|
||||
"index": 76,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "side_window",
|
||||
"index": 77,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"element": "side_wall",
|
||||
"index": 78,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 79,
|
||||
"rotation": 0
|
||||
}, {
|
||||
"element": "empty",
|
||||
"index": 80,
|
||||
"rotation": 0
|
||||
} ]
|
||||
},
|
||||
"interior": {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <scene/gui/button.h>
|
||||
#include <scene/gui/menu_button.h>
|
||||
#include <editor/editor_node.h>
|
||||
#include <flecs/flecs.h>
|
||||
#include "editor_event.h"
|
||||
#include "building_layout_editor.h"
|
||||
|
||||
@@ -36,10 +37,43 @@ template <class T> T *get_as_node(const String &path)
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void select_control_item(const String &path, const String &item)
|
||||
{
|
||||
int i;
|
||||
T *ctl = get_as_node<T>(path);
|
||||
int selected = -1;
|
||||
for (i = 0; i < ctl->get_item_count(); i++)
|
||||
if (ctl->get_item_text(i) == item) {
|
||||
selected = i;
|
||||
break;
|
||||
}
|
||||
if (selected >= 0) {
|
||||
ctl->select(selected);
|
||||
print_line("selected: " + item);
|
||||
}
|
||||
}
|
||||
template <class T> void select_control_item(T *ctl, const String &item)
|
||||
{
|
||||
int i;
|
||||
int selected = -1;
|
||||
for (i = 0; i < ctl->get_item_count(); i++)
|
||||
if (ctl->get_item_text(i) == item) {
|
||||
selected = i;
|
||||
break;
|
||||
}
|
||||
if (selected >= 0) {
|
||||
ctl->select(selected);
|
||||
print_line("selected: " + item);
|
||||
}
|
||||
}
|
||||
|
||||
#define ELEMENT_SOCKETS 16
|
||||
class ElementData {
|
||||
public:
|
||||
flecs::world ecs;
|
||||
static ElementData *singleton;
|
||||
|
||||
public:
|
||||
static ElementData *get_singleton()
|
||||
{
|
||||
if (!singleton)
|
||||
@@ -66,13 +100,37 @@ public:
|
||||
String element;
|
||||
int rotation;
|
||||
};
|
||||
Vector<struct grid_cell> grid;
|
||||
struct grid_layouts {};
|
||||
struct grid_layout {
|
||||
int floor_count;
|
||||
};
|
||||
struct grid_layout_exterior {};
|
||||
struct grid_layout_interior {};
|
||||
struct grid_floor {};
|
||||
struct grid_floor_item {
|
||||
int index;
|
||||
String element;
|
||||
int rotation;
|
||||
};
|
||||
struct grid_floor_item_node {
|
||||
Spatial *node;
|
||||
};
|
||||
|
||||
protected:
|
||||
ElementData()
|
||||
{
|
||||
grid.resize(grid_size * grid_size);
|
||||
grid.fill({ "empty", 0 });
|
||||
ecs.component<struct grid_layouts>();
|
||||
ecs.component<struct grid_layout>();
|
||||
ecs.component<struct grid_layout_exterior>();
|
||||
ecs.component<struct grid_layout_interior>();
|
||||
ecs.component<struct grid_floor>();
|
||||
ecs.component<struct grid_floor_item>();
|
||||
ecs.component<struct grid_floor_item_node>();
|
||||
flecs::entity e = ecs.entity("grid_layouts");
|
||||
e.add<grid_layouts>();
|
||||
create_new_layout("default");
|
||||
create_new_exterior_floor("default");
|
||||
create_new_interior_floor("default");
|
||||
load_data();
|
||||
struct grid_element_type t_empty;
|
||||
struct grid_element e_empty;
|
||||
@@ -81,34 +139,370 @@ protected:
|
||||
e_empty.type = "empty";
|
||||
element_type["empty"] = t_empty;
|
||||
elements["empty"] = e_empty;
|
||||
ecs.observer<struct grid_floor_item_node>()
|
||||
.event(flecs::OnRemove)
|
||||
.each([](flecs::entity em,
|
||||
struct grid_floor_item_node &s) {
|
||||
if (s.node)
|
||||
s.node->queue_delete();
|
||||
s.node = nullptr;
|
||||
});
|
||||
}
|
||||
HashMap<String, struct grid_element_type> element_type;
|
||||
HashMap<String, struct grid_element> elements;
|
||||
|
||||
public:
|
||||
void create_new_layout(const String &key)
|
||||
{
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::entity layout =
|
||||
ecs.entity(key.ascii().ptr()).child_of(top);
|
||||
// one floor by default
|
||||
layout.set<grid_layout>({ 0 });
|
||||
flecs::entity extr = ecs.entity("exterior").child_of(layout);
|
||||
extr.add<grid_layout_exterior>();
|
||||
flecs::entity intr = ecs.entity("interior").child_of(layout);
|
||||
intr.add<grid_layout_interior>();
|
||||
}
|
||||
void create_new_exterior_floor(const String &key)
|
||||
{
|
||||
int i;
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::entity layout = top.lookup(key.ascii().ptr());
|
||||
assert(layout.is_valid());
|
||||
struct grid_layout *l = layout.get_mut<grid_layout>();
|
||||
int floor = l->floor_count;
|
||||
flecs::entity ext = layout.lookup("exterior");
|
||||
assert(ext.is_valid());
|
||||
flecs::entity fl =
|
||||
ecs.entity(("floor_" + itos(floor)).ascii().ptr())
|
||||
.child_of(ext);
|
||||
assert(fl.is_valid());
|
||||
|
||||
for (i = 0; i < grid_size * grid_size; i++) {
|
||||
flecs::entity item =
|
||||
ecs.entity(("item_" + itos(i)).ascii().ptr())
|
||||
.child_of(fl);
|
||||
item.set<grid_floor_item>({ i, "empty", 0 });
|
||||
}
|
||||
l->floor_count++;
|
||||
}
|
||||
void create_new_interior_floor(const String &key)
|
||||
{
|
||||
int i;
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::entity layout = top.lookup(key.ascii().ptr());
|
||||
assert(layout.is_valid());
|
||||
struct grid_layout *l = layout.get_mut<grid_layout>();
|
||||
int floor = l->floor_count;
|
||||
flecs::entity intr = layout.lookup("interior");
|
||||
assert(intr.is_valid());
|
||||
flecs::entity fl =
|
||||
ecs.entity(("floor_" + itos(floor)).ascii().ptr())
|
||||
.child_of(intr);
|
||||
assert(fl.is_valid());
|
||||
|
||||
for (i = 0; i < grid_size * grid_size; i++) {
|
||||
flecs::entity item =
|
||||
ecs.entity(("item_" + itos(i)).ascii().ptr())
|
||||
.child_of(fl);
|
||||
item.set<grid_floor_item>({ i, "empty", 0 });
|
||||
}
|
||||
l->floor_count++;
|
||||
}
|
||||
inline int constexpr get_grid_size()
|
||||
{
|
||||
return grid_size;
|
||||
}
|
||||
inline const String &get_grid_element(int i) const
|
||||
inline flecs::entity get_grid_entity(const String &key, bool exterior,
|
||||
int fl, int i) const
|
||||
{
|
||||
assert(i >= 0 && i < grid_size * grid_size);
|
||||
return grid[i].element;
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::entity layout = top.lookup(key.ascii().ptr());
|
||||
assert(layout.is_valid());
|
||||
struct grid_layout *l = layout.get_mut<grid_layout>();
|
||||
int floor_count = l->floor_count;
|
||||
assert(fl >= 0 && fl < floor_count);
|
||||
flecs::entity base;
|
||||
if (exterior)
|
||||
base = layout.lookup("exterior");
|
||||
else
|
||||
base = layout.lookup("interior");
|
||||
assert(base.is_valid());
|
||||
String floor_key = "floor_" + itos(fl);
|
||||
String item_key = "item_" + itos(i);
|
||||
flecs::entity item_data = base.lookup(
|
||||
(floor_key + "::" + item_key).ascii().ptr());
|
||||
if (!item_data.is_valid())
|
||||
print_error("lookup failed: " + floor_key +
|
||||
"::" + item_key);
|
||||
assert(item_data.is_valid());
|
||||
return item_data;
|
||||
}
|
||||
inline int get_grid_rotation(int i) const
|
||||
inline const String &get_grid_element(const String &key, bool exterior,
|
||||
int fl, int i) const
|
||||
{
|
||||
assert(i >= 0 && i < grid_size * grid_size);
|
||||
return grid[i].rotation;
|
||||
flecs::entity item_data = get_grid_entity(key, exterior, fl, i);
|
||||
const String &element =
|
||||
item_data.get<grid_floor_item>()->element;
|
||||
return element;
|
||||
}
|
||||
void set_grid_element(int i, const String &element)
|
||||
inline int get_grid_rotation(const String &key, bool exterior, int fl,
|
||||
int i) const
|
||||
{
|
||||
assert(i >= 0 && i < grid_size * grid_size);
|
||||
grid.write[i].element = element;
|
||||
flecs::entity item_data = get_grid_entity(key, exterior, fl, i);
|
||||
int rotation = item_data.get<grid_floor_item>()->rotation;
|
||||
return rotation;
|
||||
}
|
||||
void set_grid_rotation(int i, int rotation)
|
||||
void set_grid_element(const String &key, bool exterior, int fl, int i,
|
||||
const String &element)
|
||||
{
|
||||
assert(i >= 0 && i < grid_size * grid_size);
|
||||
grid.write[i].rotation = rotation;
|
||||
flecs::entity item_data = get_grid_entity(key, exterior, fl, i);
|
||||
item_data.get_mut<grid_floor_item>()->element = element;
|
||||
}
|
||||
void set_grid_rotation(const String &key, bool exterior, int fl, int i,
|
||||
int rotation)
|
||||
{
|
||||
flecs::entity item_data = get_grid_entity(key, exterior, fl, i);
|
||||
item_data.get_mut<grid_floor_item>()->rotation = rotation;
|
||||
}
|
||||
Spatial *get_grid_node(const String &key, bool exterior, int fl, int i)
|
||||
{
|
||||
flecs::entity item_data = get_grid_entity(key, exterior, fl, i);
|
||||
if (!item_data.has<struct grid_floor_item_node>()) {
|
||||
Spatial *sp = memnew(Spatial);
|
||||
get_as_node<Spatial>("%bg_floor")
|
||||
->call_deferred("add_child", sp);
|
||||
item_data.set<struct grid_floor_item_node>({ sp });
|
||||
int x = i % grid_size;
|
||||
int z = i / grid_size;
|
||||
int rotation = get_grid_rotation(key, exterior, fl, i);
|
||||
sp->set_transform(Transform(
|
||||
Basis().rotated(Vector3(0, 1, 0),
|
||||
Math_PI * rotation / 2.0f),
|
||||
Vector3((x - 4) * 4, 0, (z - 4) * 4) -
|
||||
get_as_node<Spatial>("%bg_floor")
|
||||
->get_transform()
|
||||
.origin));
|
||||
}
|
||||
return item_data.get<struct grid_floor_item_node>()->node;
|
||||
}
|
||||
int get_closest_node_on_floor(const String &key, bool exterior, int fl,
|
||||
const Vector3 &position)
|
||||
{
|
||||
int i;
|
||||
String full_key = "grid_layouts::" + key;
|
||||
if (exterior)
|
||||
full_key += "::exterior";
|
||||
else
|
||||
full_key += "::interior";
|
||||
String floor_key = "floor_" + itos(fl);
|
||||
full_key += "::" + floor_key;
|
||||
flecs::entity floor_e = ecs.lookup(full_key.ascii().ptr());
|
||||
assert(floor_e.is_valid());
|
||||
int selected = -1;
|
||||
float dst = Math_INF;
|
||||
for (i = 0; i < grid_size * grid_size; i++) {
|
||||
Spatial *node = get_grid_node(key, exterior, fl, i);
|
||||
Vector3 pos = node->get_transform().origin;
|
||||
float mdst = position.distance_squared_to(pos);
|
||||
if (dst > mdst) {
|
||||
dst = mdst;
|
||||
selected = i;
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
void get_grid_layouts_key_list(List<String> *keys)
|
||||
{
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::query_builder<const struct grid_layout> qb =
|
||||
ecs.query_builder<const struct grid_layout>().with(
|
||||
flecs::ChildOf, top);
|
||||
flecs::query<const struct grid_layout> q = qb.build();
|
||||
q.each([keys](flecs::entity e, const struct grid_layout &data) {
|
||||
keys->push_back(String(e.name()));
|
||||
});
|
||||
}
|
||||
void serialize_layouts(Dictionary &store)
|
||||
{
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
top.children([this, &store](flecs::entity l) {
|
||||
Dictionary layout, exterior_layout, interior_layout;
|
||||
if (l.has<struct grid_layout>()) {
|
||||
flecs::entity intr = l.lookup("interior");
|
||||
assert(intr.is_valid());
|
||||
flecs::entity extr = l.lookup("exterior");
|
||||
assert(extr.is_valid());
|
||||
intr.children([this, &interior_layout](
|
||||
flecs::entity intr_fl) {
|
||||
if (intr_fl.has<struct grid_floor>()) {
|
||||
Array items;
|
||||
intr_fl.children([&items](
|
||||
flecs::entity
|
||||
floor_item) {
|
||||
if (floor_item.has<
|
||||
struct grid_floor_item>()) {
|
||||
const struct grid_floor_item *item =
|
||||
floor_item
|
||||
.get<struct grid_floor_item>();
|
||||
Dictionary sitem;
|
||||
sitem["index"] =
|
||||
item->index;
|
||||
sitem["element"] =
|
||||
item->element;
|
||||
sitem["rotation"] =
|
||||
item->rotation;
|
||||
items.push_back(
|
||||
sitem);
|
||||
}
|
||||
});
|
||||
String floor_key(
|
||||
intr_fl.name());
|
||||
interior_layout[floor_key] =
|
||||
items;
|
||||
}
|
||||
});
|
||||
extr.children([this, &exterior_layout](
|
||||
flecs::entity extr_fl) {
|
||||
Array items;
|
||||
extr_fl.children([&items](
|
||||
flecs::entity
|
||||
floor_item) {
|
||||
if (floor_item.has<
|
||||
struct grid_floor_item>()) {
|
||||
const struct grid_floor_item *item =
|
||||
floor_item.get<
|
||||
struct grid_floor_item>();
|
||||
Dictionary sitem;
|
||||
sitem["index"] =
|
||||
item->index;
|
||||
sitem["element"] =
|
||||
item->element;
|
||||
sitem["rotation"] =
|
||||
item->rotation;
|
||||
items.push_back(sitem);
|
||||
}
|
||||
});
|
||||
String floor_key(extr_fl.name());
|
||||
exterior_layout[floor_key] = items;
|
||||
});
|
||||
layout["interior"] = interior_layout;
|
||||
layout["exterior"] = exterior_layout;
|
||||
}
|
||||
String layout_name(l.name());
|
||||
store[layout_name] = layout;
|
||||
});
|
||||
}
|
||||
void unserialize_layouts(const Dictionary &store)
|
||||
{
|
||||
int i;
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
// delete all layouts
|
||||
top.children([this](flecs::entity l) { l.destruct(); });
|
||||
List<Variant> layout_keys;
|
||||
store.get_key_list(&layout_keys);
|
||||
List<Variant>::Element *e;
|
||||
e = layout_keys.front();
|
||||
while (e) {
|
||||
String layout_name = e->get();
|
||||
flecs::entity layout =
|
||||
ecs.entity(layout_name.ascii().ptr())
|
||||
.child_of(top);
|
||||
layout.set<grid_layout>({ 0 });
|
||||
flecs::entity extr =
|
||||
ecs.entity("exterior").child_of(layout);
|
||||
extr.add<grid_layout_exterior>();
|
||||
flecs::entity intr =
|
||||
ecs.entity("interior").child_of(layout);
|
||||
intr.add<grid_layout_interior>();
|
||||
Dictionary store_layout = store[e->get()];
|
||||
Dictionary store_interior = store_layout["interior"];
|
||||
Dictionary store_exterior = store_layout["exterior"];
|
||||
List<Variant>::Element *ve;
|
||||
List<Variant> interior_keys;
|
||||
List<Variant> exterior_keys;
|
||||
store_interior.get_key_list(&interior_keys);
|
||||
store_exterior.get_key_list(&exterior_keys);
|
||||
for (ve = interior_keys.front(); ve; ve = ve->next()) {
|
||||
String floor_key = ve->get();
|
||||
if (floor_key.begins_with("floor_")) {
|
||||
flecs::entity floor_e =
|
||||
ecs.entity(floor_key.ascii()
|
||||
.ptr())
|
||||
.child_of(intr);
|
||||
assert(floor_e.is_valid());
|
||||
floor_e.add<struct grid_floor>();
|
||||
const Array &floor_interior =
|
||||
store_interior[floor_key];
|
||||
for (i = 0; i < floor_interior.size();
|
||||
i++) {
|
||||
const Dictionary &item =
|
||||
floor_interior[i];
|
||||
int index = item["index"];
|
||||
String element =
|
||||
item["element"];
|
||||
int rotation = item["rotation"];
|
||||
String item_key =
|
||||
"item_" + itos(index);
|
||||
flecs::entity item_e =
|
||||
ecs.entity(item_key.ascii()
|
||||
.ptr())
|
||||
.child_of(
|
||||
floor_e);
|
||||
item_e.set<grid_floor_item>(
|
||||
{ index, element,
|
||||
rotation });
|
||||
}
|
||||
struct grid_layout *l = layout.get_mut<
|
||||
struct grid_layout>();
|
||||
l->floor_count++;
|
||||
}
|
||||
}
|
||||
for (ve = exterior_keys.front(); ve; ve = ve->next()) {
|
||||
String floor_key = ve->get();
|
||||
if (floor_key.begins_with("floor_")) {
|
||||
flecs::entity floor_e =
|
||||
ecs.entity(floor_key.ascii()
|
||||
.ptr())
|
||||
.child_of(extr);
|
||||
assert(floor_e.is_valid());
|
||||
floor_e.add<struct grid_floor>();
|
||||
const Array &floor_exterior =
|
||||
store_exterior[floor_key];
|
||||
for (i = 0; i < floor_exterior.size();
|
||||
i++) {
|
||||
const Dictionary &item =
|
||||
floor_exterior[i];
|
||||
int index = item["index"];
|
||||
String element =
|
||||
item["element"];
|
||||
int rotation = item["rotation"];
|
||||
String item_key =
|
||||
"item_" + itos(index);
|
||||
flecs::entity item_e =
|
||||
ecs.entity(item_key.ascii()
|
||||
.ptr())
|
||||
.child_of(
|
||||
floor_e);
|
||||
item_e.set<grid_floor_item>(
|
||||
{ index, element,
|
||||
rotation });
|
||||
}
|
||||
struct grid_layout *l = layout.get_mut<
|
||||
struct grid_layout>();
|
||||
l->floor_count++;
|
||||
}
|
||||
}
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
void get_element_type_key_list(List<String> *keys)
|
||||
{
|
||||
@@ -243,20 +637,12 @@ public:
|
||||
e = e->next();
|
||||
}
|
||||
// TODO: support multiple layouts;
|
||||
Array default_grid;
|
||||
default_grid.resize(grid_size * grid_size);
|
||||
for (i = 0; i < grid_size * grid_size; i++) {
|
||||
Dictionary item;
|
||||
item["element"] = grid[i].element;
|
||||
item["rotation"] = grid[i].rotation;
|
||||
default_grid[i] = item;
|
||||
}
|
||||
conf_exterior_grid["default"] = default_grid;
|
||||
serialize_layouts(conf_exterior_grid);
|
||||
|
||||
config.set_value("buildings_layout", "element_types",
|
||||
conf_element_types);
|
||||
config.set_value("buildings_layout", "elements", conf_elements);
|
||||
config.set_value("buildings_layout", "exterior_grid",
|
||||
config.set_value("buildings_layout", "grid_layouts",
|
||||
conf_exterior_grid);
|
||||
config.save("res://astream/blayout.conf");
|
||||
}
|
||||
@@ -266,7 +652,7 @@ public:
|
||||
ConfigFile config;
|
||||
Dictionary conf_element_types;
|
||||
Dictionary conf_elements;
|
||||
Dictionary conf_exterior_grid;
|
||||
Dictionary conf_grid_layouts;
|
||||
List<Variant> keys;
|
||||
List<Variant>::Element *e;
|
||||
elements.clear();
|
||||
@@ -276,8 +662,8 @@ public:
|
||||
"buildings_layout", "element_types", Dictionary());
|
||||
conf_elements = config.get_value("buildings_layout", "elements",
|
||||
Dictionary());
|
||||
conf_exterior_grid = config.get_value(
|
||||
"buildings_layout", "exterior_grid", Dictionary());
|
||||
conf_grid_layouts = config.get_value(
|
||||
"buildings_layout", "grid_layouts", Dictionary());
|
||||
conf_element_types.get_key_list(&keys);
|
||||
e = keys.front();
|
||||
while (e) {
|
||||
@@ -311,6 +697,8 @@ public:
|
||||
set_element_mesh_name(key, i, mesh_names[i]);
|
||||
e = e->next();
|
||||
}
|
||||
unserialize_layouts(conf_grid_layouts);
|
||||
#if 0
|
||||
if (conf_exterior_grid.has("default")) {
|
||||
Array default_grid = conf_exterior_grid["default"];
|
||||
if (default_grid.size() == grid_size * grid_size) {
|
||||
@@ -323,6 +711,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
ElementData *ElementData::singleton = nullptr;
|
||||
@@ -331,7 +720,6 @@ class LayoutEditor : public Object {
|
||||
GDCLASS(LayoutEditor, Object)
|
||||
BuildingLayoutEditor *editor;
|
||||
String grid_elements;
|
||||
Vector<Spatial *> grid_nodes;
|
||||
int current_cell;
|
||||
|
||||
public:
|
||||
@@ -364,37 +752,30 @@ public:
|
||||
int grid_size =
|
||||
ElementData::get_singleton()->get_grid_size();
|
||||
assert(grid_size > 0);
|
||||
grid_nodes.resize(grid_size * grid_size);
|
||||
const String layout_key = "default";
|
||||
bool exterior = true;
|
||||
int floor = 0;
|
||||
for (i = 0; i < grid_size * grid_size; i++) {
|
||||
int x = i % grid_size;
|
||||
int z = i / grid_size;
|
||||
Spatial *node = memnew(Spatial);
|
||||
int rotation = ElementData::get_singleton()
|
||||
->get_grid_rotation(i);
|
||||
get_as_node<Spatial>("%bg_floor")
|
||||
->call_deferred("add_child", node);
|
||||
node->set_transform(Transform(
|
||||
Basis().rotated(Vector3(0, 1, 0),
|
||||
Math_PI * rotation /
|
||||
2.0f),
|
||||
Vector3((x - 4) * 4, 0, (z - 4) * 4) -
|
||||
get_as_node<Spatial>("%bg_floor")
|
||||
->get_transform()
|
||||
.origin));
|
||||
String element = ElementData::get_singleton()
|
||||
->get_grid_element(i);
|
||||
Spatial *node =
|
||||
ElementData::get_singleton()
|
||||
->get_grid_node(layout_key,
|
||||
exterior, floor,
|
||||
i);
|
||||
String element =
|
||||
ElementData::get_singleton()
|
||||
->get_grid_element(layout_key,
|
||||
exterior,
|
||||
floor, i);
|
||||
editor->visualize_element_at(element, node);
|
||||
|
||||
grid_nodes.write[i] = node;
|
||||
print_line("element: " + element);
|
||||
}
|
||||
assert(grid_nodes.size() > 0);
|
||||
}
|
||||
editor->get_viewport()->get_camera()->set_global_translation(
|
||||
Vector3(-14, 23, 32));
|
||||
List<String> element_keys;
|
||||
List<String>::Element *e;
|
||||
ElementData::get_singleton()->get_element_type_key_list(
|
||||
ElementData::get_singleton()->get_element_key_list(
|
||||
&element_keys);
|
||||
e = element_keys.front();
|
||||
get_as_node<OptionButton>(grid_elements)->clear();
|
||||
@@ -415,7 +796,6 @@ public:
|
||||
}
|
||||
void event_signal_handler(const String &event, const Array &args)
|
||||
{
|
||||
int i;
|
||||
print_line("event: " + event);
|
||||
if (event == "mouse_press") {
|
||||
Vector2 position = args[0];
|
||||
@@ -441,40 +821,71 @@ public:
|
||||
Math::stepify(proj.z, 4.0f)));
|
||||
get_as_node<Spatial>("%refcube")
|
||||
->set_global_transform(xf);
|
||||
float dst = Math_INF;
|
||||
int selected = -1;
|
||||
for (i = 0; i < grid_nodes.size(); i++) {
|
||||
assert(grid_nodes[i]->is_inside_tree());
|
||||
Vector3 o =
|
||||
grid_nodes[i]
|
||||
->get_global_transform()
|
||||
.origin;
|
||||
float mdst = o.distance_squared_to(
|
||||
xf.origin);
|
||||
if (dst > mdst) {
|
||||
selected = i;
|
||||
dst = mdst;
|
||||
}
|
||||
}
|
||||
String layout_key = "default";
|
||||
bool exterior = true;
|
||||
int floor = 0;
|
||||
int selected =
|
||||
ElementData::get_singleton()
|
||||
->get_closest_node_on_floor(
|
||||
layout_key, exterior,
|
||||
floor, xf.origin);
|
||||
if (selected >= 0) {
|
||||
current_cell = selected;
|
||||
get_as_node<Spatial>("%refcube")
|
||||
->set_global_transform(
|
||||
grid_nodes[current_cell]
|
||||
ElementData::get_singleton()
|
||||
->get_grid_node(
|
||||
layout_key,
|
||||
exterior,
|
||||
floor,
|
||||
current_cell)
|
||||
->get_global_transform());
|
||||
print_line(
|
||||
"cell: " + itos(current_cell) +
|
||||
"pos: " +
|
||||
(grid_nodes[current_cell]
|
||||
(ElementData::get_singleton()
|
||||
->get_grid_node(
|
||||
layout_key,
|
||||
exterior,
|
||||
floor,
|
||||
current_cell)
|
||||
->get_global_transform()
|
||||
.origin
|
||||
.operator String()));
|
||||
String element =
|
||||
ElementData::get_singleton()
|
||||
->get_grid_element(
|
||||
layout_key,
|
||||
exterior, floor,
|
||||
current_cell);
|
||||
select_control_item<OptionButton>(
|
||||
"%grid_elements", element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void select_grid_element(int index)
|
||||
{
|
||||
String layout_key = "default";
|
||||
bool exterior = true;
|
||||
int floor = 0;
|
||||
|
||||
print_line("selected: " + itos(current_cell) + " " +
|
||||
itos(index));
|
||||
const String &element =
|
||||
get_as_node<OptionButton>("%grid_elements")
|
||||
->get_item_text(index);
|
||||
ElementData::get_singleton()->set_grid_element(
|
||||
layout_key, exterior, floor, current_cell, element);
|
||||
editor->visualize_element_at(
|
||||
element,
|
||||
ElementData::get_singleton()->get_grid_node(
|
||||
layout_key, exterior, floor, current_cell));
|
||||
}
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("select_grid_element", "index"),
|
||||
&LayoutEditor::select_grid_element);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -588,7 +999,7 @@ public:
|
||||
}
|
||||
void select_element(int element)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
print_line("selected element: " + itos(element));
|
||||
String item = get_as_node<ItemList>("%element_list")
|
||||
->get_item_text(element);
|
||||
@@ -614,27 +1025,13 @@ public:
|
||||
ElementData::get_singleton()->set_element_type(
|
||||
current_element, b->get_item_text(0));
|
||||
}
|
||||
int selected = 0;
|
||||
for (i = 0; i < used_socket_count; i++) {
|
||||
String selected_mesh =
|
||||
ElementData::get_singleton()
|
||||
->get_element_mesh_name(current_element,
|
||||
i);
|
||||
selected = 0;
|
||||
for (j = 0;
|
||||
j < mesh_select_buttons[i]->get_item_count();
|
||||
j++) {
|
||||
String mesh_item =
|
||||
mesh_select_buttons[i]->get_item_text(
|
||||
j);
|
||||
if (mesh_item == selected_mesh) {
|
||||
selected = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_line(itos(i) +
|
||||
": selecting mesh: " + itos(selected));
|
||||
mesh_select_buttons[i]->select(selected);
|
||||
select_control_item<OptionButton>(
|
||||
mesh_select_buttons[i], selected_mesh);
|
||||
}
|
||||
editor->visualize_element_type(type, current_element);
|
||||
}
|
||||
@@ -1186,6 +1583,8 @@ void BuildingLayoutEditor::visualize_element_at(const String &element,
|
||||
return;
|
||||
const String &element_type =
|
||||
ElementData::get_singleton()->get_element_type(element);
|
||||
for (i = 0; i < node->get_child_count(); i++)
|
||||
node->get_child(i)->queue_delete();
|
||||
for (i = 0; i < ELEMENT_SOCKETS; i++) {
|
||||
Transform xform =
|
||||
ElementData::get_singleton()->get_element_type_socket(
|
||||
|
||||
Reference in New Issue
Block a user