Made layout saving work

This commit is contained in:
2024-10-27 22:36:30 +03:00
parent 7152267937
commit 799ac40a4a
5 changed files with 373 additions and 55 deletions

View File

@@ -0,0 +1,114 @@
[layouts]
entries=[ {
"children": [ 1, 2, 3 ],
"index": 0,
"name": "v1",
"type": "layout"
}, {
"children": [ 4, 5 ],
"index": 1,
"name": "unit_0",
"type": "unit"
}, {
"children": [ 6, 7, 8 ],
"index": 2,
"name": "zone_0",
"type": "zone",
"zone_type": 0
}, {
"children": [ 9, 10, 11 ],
"index": 3,
"name": "zone_1",
"type": "zone",
"zone_type": 1
}, {
"children": [ 12, 13, 14 ],
"index": 4,
"name": "zone_0",
"type": "zone",
"zone_type": 0
}, {
"children": [ 15, 16 ],
"index": 5,
"name": "zone_1",
"type": "zone",
"zone_type": 1
}, {
"children": [ ],
"index": 6,
"name": "wc_0",
"room_type": 200,
"type": "room",
"window": false
}, {
"children": [ ],
"index": 7,
"name": "bathroom_0",
"room_type": 201,
"type": "room",
"window": false
}, {
"children": [ ],
"index": 8,
"name": "bedroom_0",
"room_type": 202,
"type": "room",
"window": true
}, {
"children": [ ],
"index": 9,
"name": "living_room_0",
"room_type": 300,
"type": "room",
"window": true
}, {
"children": [ ],
"index": 10,
"name": "kitchen_0",
"room_type": 302,
"type": "room",
"window": true
}, {
"children": [ ],
"index": 11,
"name": "storage_room_0",
"room_type": 307,
"type": "room",
"window": true
}, {
"children": [ ],
"index": 12,
"name": "wc_0",
"room_type": 200,
"type": "room",
"window": false
}, {
"children": [ ],
"index": 13,
"name": "bathroom_0",
"room_type": 201,
"type": "room",
"window": false
}, {
"children": [ ],
"index": 14,
"name": "bedroom_0",
"room_type": 202,
"type": "room",
"window": true
}, {
"children": [ ],
"index": 15,
"name": "living_room_0",
"room_type": 300,
"type": "room",
"window": true
}, {
"children": [ ],
"index": 16,
"name": "kitchen_0",
"room_type": 302,
"type": "room",
"window": true
} ]

View File

@@ -78,6 +78,12 @@ void BuildingLayoutGraph::create_unit(const String &base_path)
new_e.set<WorldEditor::components::buildings_layout_unit>({ 0 }); new_e.set<WorldEditor::components::buildings_layout_unit>({ 0 });
} }
void BuildingLayoutGraph::create_floor(const String &base_path)
{
flecs::entity new_e = create_graph_entity(base_path, "unit");
new_e.set<WorldEditor::components::buildings_layout_floor>({ 0 });
}
void BuildingLayoutGraph::create_room(const String &base_path, int id) void BuildingLayoutGraph::create_room(const String &base_path, int id)
{ {
Array room; Array room;
@@ -106,11 +112,15 @@ flecs::entity BuildingLayoutGraph::get_layout_base() const
flecs::world ecs = BaseData::get_singleton()->get(); flecs::world ecs = BaseData::get_singleton()->get();
flecs::entity layout_base_e = flecs::entity layout_base_e =
ecs.lookup(layout_base_name.ascii().ptr()); ecs.lookup(layout_base_name.ascii().ptr());
if (layout_base_e.is_valid()) if (layout_base_e.is_valid()) {
assert(layout_base_e.has<
WorldEditor::components::buildings_layout_base>());
return layout_base_e; return layout_base_e;
else { } else {
layout_base_e = ecs.entity(layout_base_name.ascii().ptr()); layout_base_e = ecs.entity(layout_base_name.ascii().ptr());
assert(layout_base_e.is_valid()); assert(layout_base_e.is_valid());
layout_base_e
.add<WorldEditor::components::buildings_layout_base>();
return layout_base_e; return layout_base_e;
} }
} }
@@ -196,3 +206,200 @@ void BuildingLayoutGraph::recalculate_size(const String &layout_name)
} }
} }
} }
void BuildingLayoutGraph::update_button_positions(const String &layout_name)
{
assert(layout_name.length() > 0);
flecs::entity layout_e = get_layout(layout_name);
assert(layout_e.is_valid());
List<flecs::entity> queue;
queue.push_back(layout_e);
while (!queue.empty()) {
flecs::entity e = queue.front()->get();
queue.pop_front();
if (!e.has<WorldEditor::components::
buildings_layout_graph_node>()) {
assert(false);
}
int depth = e.get<WorldEditor::components::
buildings_layout_graph_node>()
->depth;
int y = e.get<WorldEditor::components::
buildings_layout_graph_node>()
->y_pos;
e.get_mut<WorldEditor::components::buildings_layout_graph_node>()
->y_pos = y;
int count = 0;
int offset = y;
e.children([depth, y, &count, &queue,
&offset](flecs::entity fe) {
int size = fe.get<WorldEditor::components::
buildings_layout_graph_node>()
->size;
fe.set<WorldEditor::components::
buildings_layout_graph_node>(
{ depth + 1, offset, size });
offset += size;
queue.push_back(fe);
count++;
});
}
}
void BuildingLayoutGraph::get_menu_entries(flecs::entity e,
List<Pair<int, String> > *list) const
{
struct menu_entry {
int id;
String item;
};
int i;
menu_entry floor_menu[] = { { 100, "Create block unit" },
{ 101, "Create private zone" },
{ 102, "Create public zone" } };
menu_entry unit_menu[] = { { 101, "Create private zone" },
{ 102, "Create public zone" } };
list->clear();
if (e.has<WorldEditor::components::buildings_layout_floor>()) {
for (i = 0; i < sizeof(floor_menu) / sizeof(floor_menu[0]);
i++) {
Pair<int, String> item(
{ floor_menu[i].id, floor_menu[i].item });
list->push_back(item);
}
}
if (e.has<WorldEditor::components::buildings_layout_unit>()) {
if (!list->empty())
list->push_back(Pair<int, String>({ -1, "" }));
for (i = 0; i < sizeof(unit_menu) / sizeof(unit_menu[0]); i++) {
Pair<int, String> item(
{ unit_menu[i].id, unit_menu[i].item });
list->push_back(item);
}
}
if (e.has<WorldEditor::components::buildings_layout_zone>()) {
if (!list->empty())
list->push_back(Pair<int, String>({ -1, "" }));
int zone_type =
e.get<WorldEditor::components::buildings_layout_zone>()
->type;
if (zone_type == 0) {
const Array &private_rooms = get_private_rooms();
for (i = 0; i < private_rooms.size(); i++) {
Array room_data = private_rooms[i];
int id = room_data[0];
String room_name = room_data[1];
Pair<int, String> item(
{ id, "Create " + room_name });
list->push_back(item);
}
} else if (zone_type == 1) {
const Array &public_rooms = get_public_rooms();
for (i = 0; i < public_rooms.size(); i++) {
Array room_data = public_rooms[i];
int id = room_data[0];
String room_name = room_data[1];
Pair<int, String> item(
{ id, "Create " + room_name });
list->push_back(item);
}
}
}
if (e.has<WorldEditor::components::buildings_layout_room>()) {
int room_type =
e.get<WorldEditor::components::buildings_layout_room>()
->room_type;
if (!list->empty())
list->push_back(Pair<int, String>({ -1, "" }));
switch (room_type) {
case 305:
case 306:
list->push_back(Pair<int, String>({ 104, "Floor" }));
break;
default:
break;
}
}
if (!e.has<WorldEditor::components::buildings_layout_graph>()) {
if (!list->empty())
list->push_back(Pair<int, String>({ -1, "" }));
list->push_back(Pair<int, String>({ 1000, "Delete" }));
}
}
void BuildingLayoutGraph::save_layouts()
{
List<flecs::entity> queue;
flecs::entity base = get_layout_base();
queue.push_back(base);
int index = 0;
HashMap<String, int> indices;
while (!queue.empty()) {
flecs::entity e = queue.front()->get();
queue.pop_front();
e.children([&queue](flecs::entity ce) { queue.push_back(ce); });
if (e.has<WorldEditor::components::buildings_layout_base>())
continue;
print_line("store: " + String(String(e.path())));
indices[String(e.path())] = index++;
}
queue.clear();
queue.push_back(base);
Array entries;
entries.resize(index);
while (!queue.empty()) {
flecs::entity e = queue.front()->get();
queue.pop_front();
if (e.has<WorldEditor::components::buildings_layout_base>()) {
e.children([&queue](flecs::entity ce) {
queue.push_back(ce);
});
continue;
}
print_line("getting: " + String(String(e.path())));
int index = indices[String(e.path())];
Array children;
e.children([&queue, indices, &children](flecs::entity ce) {
int cindex = indices[String(ce.path())];
children.push_back(cindex);
queue.push_back(ce);
});
Dictionary entry;
entry["name"] = String(e.name());
entry["index"] = index;
entry["children"] = children;
if (e.has<WorldEditor::components::buildings_layout_graph>()) {
entry["type"] = "layout";
/* remember it has floor component too */
} else if (e.has<WorldEditor::components::
buildings_layout_floor>()) {
/* non-root floor */
entry["type"] = "floor";
} else if (e.has<WorldEditor::components::
buildings_layout_zone>()) {
entry["type"] = "zone";
int zone_type = e.get<WorldEditor::components::
buildings_layout_zone>()
->type;
entry["zone_type"] = zone_type;
} else if (e.has<WorldEditor::components::
buildings_layout_unit>()) {
entry["type"] = "unit";
} else if (e.has<WorldEditor::components::
buildings_layout_room>()) {
entry["type"] = "room";
int room_type = e.get<WorldEditor::components::
buildings_layout_room>()
->room_type;
entry["room_type"] = room_type;
bool window = e.get<WorldEditor::components::
buildings_layout_room>()
->window;
entry["window"] = window;
}
entries[index] = entry;
}
ConfigFile config_layouts;
config_layouts.set_value("layouts", "entries", entries);
config_layouts.save("res://astream/building_layout_data.conf");
}

View File

@@ -30,6 +30,7 @@ public:
const Array &get_public_rooms() const; const Array &get_public_rooms() const;
void create_zone(const String &base_path, int zone_type); void create_zone(const String &base_path, int zone_type);
void create_unit(const String &base_path); void create_unit(const String &base_path);
void create_floor(const String &base_path);
void create_room(const String &base_path, int id); void create_room(const String &base_path, int id);
void destroy_graph_entity(const String &path); void destroy_graph_entity(const String &path);
flecs::entity get_layout_base() const; flecs::entity get_layout_base() const;
@@ -39,4 +40,8 @@ public:
void get_layout_entity_children(flecs::entity layout_e, void get_layout_entity_children(flecs::entity layout_e,
List<flecs::entity> *keys) const; List<flecs::entity> *keys) const;
void recalculate_size(const String &layout_name); void recalculate_size(const String &layout_name);
void update_button_positions(const String &layout_name);
void get_menu_entries(flecs::entity e,
List<Pair<int, String> > *list) const;
void save_layouts();
}; };

View File

@@ -44,7 +44,8 @@ public:
case 100: case 100:
case 101: case 101:
case 102: case 102:
case 103: { case 103:
case 104: {
int count = 0; int count = 0;
switch (id) { switch (id) {
case 100: case 100:
@@ -59,6 +60,10 @@ public:
BuildingLayoutGraph::get_singleton() BuildingLayoutGraph::get_singleton()
->create_zone(path, 1); ->create_zone(path, 1);
break; break;
case 104:
BuildingLayoutGraph::get_singleton()
->create_floor(path);
break;
} }
} break; } break;
case 1000: case 1000:
@@ -131,7 +136,9 @@ public:
"select_layout")) "select_layout"))
item_list->connect("item_selected", this, item_list->connect("item_selected", this,
"select_layout"); "select_layout");
} else if (event == "building_layouts_layout_selected") { } else if (event == "button:building_layouts_save")
BuildingLayoutGraph::get_singleton()->save_layouts();
else if (event == "building_layouts_layout_selected") {
update_graph(); update_graph();
dlg->update(); dlg->update();
} }
@@ -176,6 +183,8 @@ public:
assert(current_layout.length() > 0); assert(current_layout.length() > 0);
BuildingLayoutGraph::get_singleton()->recalculate_size( BuildingLayoutGraph::get_singleton()->recalculate_size(
current_layout); current_layout);
BuildingLayoutGraph::get_singleton()->update_button_positions(
current_layout);
flecs::entity layout_e = get_current_layout(); flecs::entity layout_e = get_current_layout();
List<flecs::entity> queue; List<flecs::entity> queue;
bool layout_empty = true; bool layout_empty = true;
@@ -195,9 +204,11 @@ public:
int y = e.get<WorldEditor::components:: int y = e.get<WorldEditor::components::
buildings_layout_graph_node>() buildings_layout_graph_node>()
->y_pos; ->y_pos;
#if 0
e.get_mut<WorldEditor::components:: e.get_mut<WorldEditor::components::
buildings_layout_graph_node>() buildings_layout_graph_node>()
->y_pos = y; ->y_pos = y;
#endif
/* make button here */ /* make button here */
Vector2 pt(depth * 120 + 40, y * 110 + 40); Vector2 pt(depth * 120 + 40, y * 110 + 40);
{ {
@@ -206,27 +217,33 @@ public:
canvas->add_child(button); canvas->add_child(button);
button->set_size(Vector2(80, 40)); button->set_size(Vector2(80, 40));
button->set_position(pt); button->set_position(pt);
List<Pair<int, String> > menu_options;
List<Pair<int, String> >::Element *pe;
BuildingLayoutGraph::get_singleton()
->get_menu_entries(e, &menu_options);
pe = menu_options.front();
while (pe) {
if (pe->get().first < 0)
button->get_popup()
->add_separator();
else
button->get_popup()->add_item(
pe->get().second,
pe->get().first);
pe = pe->next();
}
if (e.has<WorldEditor::components:: if (e.has<WorldEditor::components::
buildings_layout_floor>()) { buildings_layout_floor>()) {
button->set_text(button->get_text() + button->set_text(button->get_text() +
"Floor\n" + "Floor\n" +
String(e.name())); String(e.name()));
button->get_popup()->add_item(
"Create block unit", 100);
button->get_popup()->add_item(
"Create private zone", 101);
button->get_popup()->add_item(
"Create public zone", 102);
} }
if (e.has<WorldEditor::components:: if (e.has<WorldEditor::components::
buildings_layout_unit>()) { buildings_layout_unit>()) {
button->set_text(button->get_text() + button->set_text(button->get_text() +
"Unit\n" + "Unit\n" +
String(e.name())); String(e.name()));
button->get_popup()->add_item(
"Create private zone", 101);
button->get_popup()->add_item(
"Create public zone", 102);
} }
if (e.has<WorldEditor::components:: if (e.has<WorldEditor::components::
buildings_layout_zone>()) { buildings_layout_zone>()) {
@@ -239,43 +256,11 @@ public:
button->set_text( button->set_text(
button->get_text() + button->get_text() +
"Private Zone\n"); "Private Zone\n");
const Array &private_rooms =
BuildingLayoutGraph::get_singleton()
->get_private_rooms();
for (i = 0;
i < private_rooms.size();
i++) {
Array room_data =
private_rooms[i];
int id = room_data[0];
String room_name =
room_data[1];
button->get_popup()->add_item(
"Create " +
room_name,
id);
}
} else if (zone_type == 1) { } else if (zone_type == 1) {
int i; int i;
button->set_text( button->set_text(
button->get_text() + button->get_text() +
"Public Zone\n"); "Public Zone\n");
const Array &public_rooms =
BuildingLayoutGraph::get_singleton()
->get_public_rooms();
for (i = 0;
i < public_rooms.size();
i++) {
Array room_data =
public_rooms[i];
int id = room_data[0];
String room_name =
room_data[1];
button->get_popup()->add_item(
"Create " +
room_name,
id);
}
} }
button->set_text(button->get_text() + button->set_text(button->get_text() +
String(e.name())); String(e.name()));
@@ -296,9 +281,10 @@ public:
e.get<WorldEditor::components:: e.get<WorldEditor::components::
buildings_layout_room>() buildings_layout_room>()
->room_type; ->room_type;
button->set_text(button->get_text() + button->set_text(
"Room\n" + button->get_text() + "Room\n" +
String(e.name())); String(e.name() + " " +
itos(room_type)));
PopupMenu *mp = memnew(PopupMenu); PopupMenu *mp = memnew(PopupMenu);
std::vector<Variant> args = { std::vector<Variant> args = {
"Room Area: ", "area_value" "Room Area: ", "area_value"
@@ -327,16 +313,18 @@ public:
buildings_layout_graph_node>() buildings_layout_graph_node>()
->size)); ->size));
#endif #endif
button->get_popup()->add_separator(); // button->get_popup()->add_separator();
button->get_popup()->add_item("Delete", 1000); // button->get_popup()->add_item("Delete", 1000);
button->get_popup()->connect( button->get_popup()->connect(
"id_pressed", this, "menu_pressed", "id_pressed", this, "menu_pressed",
varray(button, String(e.path()))); varray(button, String(e.path())));
} }
#if 0
int count = 0; int count = 0;
int offset = y; int offset = y;
e.children([depth, y, &count, &queue, #endif
&offset](flecs::entity fe) { e.children([&queue](flecs::entity fe) {
#if 0
int size = int size =
fe.get<WorldEditor::components:: fe.get<WorldEditor::components::
buildings_layout_graph_node>() buildings_layout_graph_node>()
@@ -345,8 +333,9 @@ public:
buildings_layout_graph_node>( buildings_layout_graph_node>(
{ depth + 1, offset, size }); { depth + 1, offset, size });
offset += size; offset += size;
queue.push_back(fe);
count++; count++;
#endif
queue.push_back(fe);
}); });
// if (count > 1) // if (count > 1)
@@ -476,10 +465,12 @@ public:
"", "building_layouts_create_text", Control::SIZE_EXPAND_FILL, "", "building_layouts_create_text", Control::SIZE_EXPAND_FILL,
"Create", "building_layouts_create_button", "Create", "building_layouts_create_button",
"building_layouts_create_new", varray(), "building_layouts_create_new", varray(),
"Save", "building_layouts_save_button",
"building_layouts_save", varray(),
/* clang-format on */ /* clang-format on */
}; };
ui_field::ui_field_builder(gui, tab, ui_field::ui_field_builder(gui, tab,
"l_p{v{li.#!lh{e#+!b#!Q}}}", "l_p{v{li.#!lh{e#+!b#!Q}b#!Q}}",
args_data.data(), args_data.size()); args_data.data(), args_data.size());
} }
static void _bind_methods() static void _bind_methods()

View File

@@ -67,6 +67,7 @@ public:
int mode; int mode;
String current_type; String current_type;
}; };
struct buildings_layout_base {};
struct buildings_layout_graph {}; struct buildings_layout_graph {};
struct buildings_layout_graph_node { struct buildings_layout_graph_node {
int depth; int depth;