diff --git a/godot/astream/building_layout_data.conf b/godot/astream/building_layout_data.conf new file mode 100644 index 0000000..a216a09 --- /dev/null +++ b/godot/astream/building_layout_data.conf @@ -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 +} ] diff --git a/src/modules/stream/ui/building_layout_graph.cpp b/src/modules/stream/ui/building_layout_graph.cpp index af85144..6d98c2c 100644 --- a/src/modules/stream/ui/building_layout_graph.cpp +++ b/src/modules/stream/ui/building_layout_graph.cpp @@ -78,6 +78,12 @@ void BuildingLayoutGraph::create_unit(const String &base_path) new_e.set({ 0 }); } +void BuildingLayoutGraph::create_floor(const String &base_path) +{ + flecs::entity new_e = create_graph_entity(base_path, "unit"); + new_e.set({ 0 }); +} + void BuildingLayoutGraph::create_room(const String &base_path, int id) { Array room; @@ -106,11 +112,15 @@ flecs::entity BuildingLayoutGraph::get_layout_base() const flecs::world ecs = BaseData::get_singleton()->get(); flecs::entity layout_base_e = 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; - else { + } else { layout_base_e = ecs.entity(layout_base_name.ascii().ptr()); assert(layout_base_e.is_valid()); + layout_base_e + .add(); 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 queue; + queue.push_back(layout_e); + while (!queue.empty()) { + flecs::entity e = queue.front()->get(); + queue.pop_front(); + if (!e.has()) { + assert(false); + } + int depth = e.get() + ->depth; + int y = e.get() + ->y_pos; + e.get_mut() + ->y_pos = y; + int count = 0; + int offset = y; + e.children([depth, y, &count, &queue, + &offset](flecs::entity fe) { + int size = fe.get() + ->size; + fe.set( + { depth + 1, offset, size }); + offset += size; + queue.push_back(fe); + count++; + }); + } +} + +void BuildingLayoutGraph::get_menu_entries(flecs::entity e, + List > *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()) { + for (i = 0; i < sizeof(floor_menu) / sizeof(floor_menu[0]); + i++) { + Pair item( + { floor_menu[i].id, floor_menu[i].item }); + list->push_back(item); + } + } + if (e.has()) { + if (!list->empty()) + list->push_back(Pair({ -1, "" })); + for (i = 0; i < sizeof(unit_menu) / sizeof(unit_menu[0]); i++) { + Pair item( + { unit_menu[i].id, unit_menu[i].item }); + list->push_back(item); + } + } + if (e.has()) { + if (!list->empty()) + list->push_back(Pair({ -1, "" })); + int zone_type = + e.get() + ->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 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 item( + { id, "Create " + room_name }); + list->push_back(item); + } + } + } + if (e.has()) { + int room_type = + e.get() + ->room_type; + if (!list->empty()) + list->push_back(Pair({ -1, "" })); + switch (room_type) { + case 305: + case 306: + list->push_back(Pair({ 104, "Floor" })); + break; + default: + break; + } + } + if (!e.has()) { + if (!list->empty()) + list->push_back(Pair({ -1, "" })); + list->push_back(Pair({ 1000, "Delete" })); + } +} + +void BuildingLayoutGraph::save_layouts() +{ + List queue; + flecs::entity base = get_layout_base(); + queue.push_back(base); + int index = 0; + HashMap 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()) + 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()) { + 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()) { + entry["type"] = "layout"; + /* remember it has floor component too */ + } else if (e.has()) { + /* non-root floor */ + entry["type"] = "floor"; + } else if (e.has()) { + entry["type"] = "zone"; + int zone_type = e.get() + ->type; + entry["zone_type"] = zone_type; + } else if (e.has()) { + entry["type"] = "unit"; + } else if (e.has()) { + entry["type"] = "room"; + int room_type = e.get() + ->room_type; + entry["room_type"] = room_type; + bool window = e.get() + ->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"); +} diff --git a/src/modules/stream/ui/building_layout_graph.h b/src/modules/stream/ui/building_layout_graph.h index b1a01ea..8d49a40 100644 --- a/src/modules/stream/ui/building_layout_graph.h +++ b/src/modules/stream/ui/building_layout_graph.h @@ -30,6 +30,7 @@ public: const Array &get_public_rooms() const; void create_zone(const String &base_path, int zone_type); void create_unit(const String &base_path); + void create_floor(const String &base_path); void create_room(const String &base_path, int id); void destroy_graph_entity(const String &path); flecs::entity get_layout_base() const; @@ -39,4 +40,8 @@ public: void get_layout_entity_children(flecs::entity layout_e, List *keys) const; void recalculate_size(const String &layout_name); + void update_button_positions(const String &layout_name); + void get_menu_entries(flecs::entity e, + List > *list) const; + void save_layouts(); }; \ No newline at end of file diff --git a/src/modules/stream/ui/building_layout_graph_ui.h b/src/modules/stream/ui/building_layout_graph_ui.h index 39e4465..e4b831d 100644 --- a/src/modules/stream/ui/building_layout_graph_ui.h +++ b/src/modules/stream/ui/building_layout_graph_ui.h @@ -44,7 +44,8 @@ public: case 100: case 101: case 102: - case 103: { + case 103: + case 104: { int count = 0; switch (id) { case 100: @@ -59,6 +60,10 @@ public: BuildingLayoutGraph::get_singleton() ->create_zone(path, 1); break; + case 104: + BuildingLayoutGraph::get_singleton() + ->create_floor(path); + break; } } break; case 1000: @@ -131,7 +136,9 @@ public: "select_layout")) item_list->connect("item_selected", this, "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(); dlg->update(); } @@ -176,6 +183,8 @@ public: assert(current_layout.length() > 0); BuildingLayoutGraph::get_singleton()->recalculate_size( current_layout); + BuildingLayoutGraph::get_singleton()->update_button_positions( + current_layout); flecs::entity layout_e = get_current_layout(); List queue; bool layout_empty = true; @@ -195,9 +204,11 @@ public: int y = e.get() ->y_pos; +#if 0 e.get_mut() ->y_pos = y; +#endif /* make button here */ Vector2 pt(depth * 120 + 40, y * 110 + 40); { @@ -206,27 +217,33 @@ public: canvas->add_child(button); button->set_size(Vector2(80, 40)); button->set_position(pt); + List > menu_options; + List >::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()) { button->set_text(button->get_text() + "Floor\n" + 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()) { button->set_text(button->get_text() + "Unit\n" + String(e.name())); - button->get_popup()->add_item( - "Create private zone", 101); - button->get_popup()->add_item( - "Create public zone", 102); } if (e.has()) { @@ -239,43 +256,11 @@ public: button->set_text( button->get_text() + "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) { int i; button->set_text( button->get_text() + "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() + String(e.name())); @@ -296,9 +281,10 @@ public: e.get() ->room_type; - button->set_text(button->get_text() + - "Room\n" + - String(e.name())); + button->set_text( + button->get_text() + "Room\n" + + String(e.name() + " " + + itos(room_type))); PopupMenu *mp = memnew(PopupMenu); std::vector args = { "Room Area: ", "area_value" @@ -327,16 +313,18 @@ public: buildings_layout_graph_node>() ->size)); #endif - button->get_popup()->add_separator(); - button->get_popup()->add_item("Delete", 1000); + // button->get_popup()->add_separator(); + // button->get_popup()->add_item("Delete", 1000); button->get_popup()->connect( "id_pressed", this, "menu_pressed", varray(button, String(e.path()))); } +#if 0 int count = 0; int offset = y; - e.children([depth, y, &count, &queue, - &offset](flecs::entity fe) { +#endif + e.children([&queue](flecs::entity fe) { +#if 0 int size = fe.get() @@ -345,8 +333,9 @@ public: buildings_layout_graph_node>( { depth + 1, offset, size }); offset += size; - queue.push_back(fe); count++; +#endif + queue.push_back(fe); }); // if (count > 1) @@ -476,10 +465,12 @@ public: "", "building_layouts_create_text", Control::SIZE_EXPAND_FILL, "Create", "building_layouts_create_button", "building_layouts_create_new", varray(), + "Save", "building_layouts_save_button", + "building_layouts_save", varray(), /* clang-format on */ }; 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()); } static void _bind_methods() diff --git a/src/modules/stream/world_editor.h b/src/modules/stream/world_editor.h index 9fe7854..b00e409 100644 --- a/src/modules/stream/world_editor.h +++ b/src/modules/stream/world_editor.h @@ -67,6 +67,7 @@ public: int mode; String current_type; }; + struct buildings_layout_base {}; struct buildings_layout_graph {}; struct buildings_layout_graph_node { int depth;