diff --git a/src/modules/stream/ui/building_layout_graph_ui.h b/src/modules/stream/ui/building_layout_graph_ui.h index 183f60e..afff1cd 100644 --- a/src/modules/stream/ui/building_layout_graph_ui.h +++ b/src/modules/stream/ui/building_layout_graph_ui.h @@ -8,20 +8,142 @@ #include #include #include +#include +#include #include "ui_field_builder.h" +#include "main_tabs.h" +#include "base_data.h" +#include "editor_event.h" +#include "world_editor.h" class BuildingLayoutGraphUI : public Object { GDCLASS(BuildingLayoutGraphUI, Object) + MainTabs *gui; WindowDialog *dlg; Control *canvas_item; + Button *button; + String current_layout; public: - BuildingLayoutGraphUI(WindowDialog *dlg) + BuildingLayoutGraphUI(MainTabs *gui, WindowDialog *dlg) : Object() + , gui(gui) , dlg(dlg) + , canvas_item(nullptr) + , button(nullptr) { dlg->connect("tree_entered", this, "tree_entered"); } + void menu_pressed(int id, Control *button) + { + assert(button); + print_line(itos(id)); + } + flecs::entity get_layout_base() + { + const String &layout_base_name = "buildings_layout_graph"; + 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()) + return layout_base_e; + else { + layout_base_e = + ecs.entity(layout_base_name.ascii().ptr()); + assert(layout_base_e.is_valid()); + return layout_base_e; + } + } + void get_layout_list(List *keys) + { + flecs::entity base = get_layout_base(); + base.children([keys](flecs::entity e) { + if (e.has()) + keys->push_back(String(e.name())); + }); + } + void update_layout_item_list() + { + ItemList *item_list = + gui->get_as_node("%building_layout_list"); + List items; + get_layout_list(&items); + List::Element *e = items.front(); + item_list->clear(); + while (e) { + item_list->add_item(e->get()); + e = e->next(); + } + } + void create_new_layout(const String &layout_name) + { + flecs::world ecs = BaseData::get_singleton()->get(); + flecs::entity base = get_layout_base(); + flecs::entity e = base.lookup(layout_name.ascii().ptr()); + if (e.is_valid()) + return; + e = ecs.entity(layout_name.ascii().ptr()).child_of(base); + if (e.is_valid()) + e.add(); + } + flecs::entity get_current_layout() + { + assert(current_layout.length() > 0); + flecs::entity base = get_layout_base(); + flecs::entity layout_e = + base.lookup(current_layout.ascii().ptr()); + assert(layout_e.has< + WorldEditor::components::buildings_layout_graph>()); + return layout_e; + } + void get_layout_entity_children(flecs::entity layout_e, + List *keys) + { + layout_e.children( + [keys](flecs::entity e) { keys->push_back(e); }); + } + void select_layout(int id) + { + ItemList *item_list = + gui->get_as_node("%building_layout_list"); + current_layout = item_list->get_item_text(id); + EditorEvent::get_singleton()->event.emit( + "building_layouts_layout_selected", + varray(current_layout)); + } + void handle_event(const String &event, const Vector &args) + { + int i; + if (event == "button:building_layouts_create_new") { + LineEdit *line_edit = gui->get_as_node( + "%building_layouts_create_text"); + ItemList *item_list = gui->get_as_node( + "%building_layout_list"); + if (item_list->is_connected("item_selected", this, + "select_layout")) + item_list->disconnect("item_selected", this, + "select_layout"); + String new_name = line_edit->get_text().strip_edges(); + create_new_layout(new_name); + update_layout_item_list(); + int selected = -1; + for (i = 0; i < item_list->get_item_count(); i++) + if (item_list->get_item_text(i) == new_name) { + selected = i; + break; + } + if (selected >= 0) + item_list->select(selected); + if (!item_list->is_connected("item_selected", this, + "select_layout")) + item_list->connect("item_selected", this, + "select_layout"); + } else if (event == "building_layouts_layout_selected") { + update_graph(); + dlg->update(); + } + } void tree_entered() { if (!Engine::get_singleton()->is_editor_hint()) { @@ -47,21 +169,123 @@ public: args_data2.data(), args_data2.size()); dlg->update(); update_graph(); + update_layout_item_list(); + EditorEvent::get_singleton()->event.add_listener( + this, &BuildingLayoutGraphUI::handle_event); } } + Vector buttons; + void update_buttons(ColorRect *canvas) + { + assert(current_layout.length() > 0); + flecs::entity e = get_current_layout(); + List queue; + bool layout_empty = true; + queue.push_back(e); + HashMap depth_height; + depth_height[0] = 0; + buttons.clear(); + while (!queue.empty()) { + layout_empty = false; + flecs::entity e = queue.front()->get(); + queue.pop_front(); + if (!e.has()) { + e.set( + { 0, 0 }); + } + int depth = e.get() + ->depth; + int y = e.get() + ->y_pos; + /* make button here */ + Vector2 pt(depth * 100 + 40, y * 60 + 40); + buttons.push_back(pt); + { + MenuButton *button = memnew(MenuButton); + button->set_text("XXX"); + canvas->add_child(button); + button->set_size(Vector2(80, 40)); + button->set_position(pt); + if (e.has()) { + button->set_text("Entry"); + 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); + button->get_popup()->add_item( + "Create hallway", 103); + button->get_popup()->connect( + "id_pressed", this, + "menu_pressed", varray(button)); + } + } + int count = 0; + e.children([depth, y, &count, &queue, + &depth_height](flecs::entity e) { + e.set( + { depth + 1, y + count }); + queue.push_back(e); + if (!depth_height.has(depth + 1)) + depth_height[depth + 1] = 0; + depth_height[depth + 1] = + MAX(depth_height[depth + 1], + y + count) + + 1; + }); + if (!depth_height.has(depth)) + depth_height[depth] = y + count + 1; + else { + y = MAX(depth_height[depth], y); + e.set( + { depth, y }); + depth_height[depth] = y + count + 1; + } + } +#if 0 + if (layout_empty) { + MenuButton *button = memnew(MenuButton); + button->set_text("Entry"); + canvas->add_child(button); + button->set_size(Vector2(80, 40)); + button->set_position(Vector2(40, 45)); + 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); + button->get_popup()->add_item("Create hallway", 103); + button->get_popup()->connect("id_pressed", this, + "menu_pressed", + varray(button)); + } +#endif + } void update_graph() { int i; assert(dlg->get_node(NodePath("%buildings_layout_graph"))); Control *base = Object::cast_to( dlg->get_node(NodePath("%buildings_layout_graph"))); + base->set_custom_minimum_size(Vector2(2048, 1600)); + base->set_anchor(MARGIN_RIGHT, 1.0f); + base->set_anchor(MARGIN_BOTTOM, 1.0f); + base->set_v_size_flags(Control::SIZE_EXPAND_FILL); + base->set_h_size_flags(Control::SIZE_EXPAND_FILL); ScrollContainer *p = Object::cast_to(base->get_parent()); p->set_v_size_flags(Control::SIZE_EXPAND_FILL); p->set_h_size_flags(Control::SIZE_EXPAND_FILL); - p->set_anchor(MARGIN_RIGHT, 1.0f); - p->set_anchor(MARGIN_BOTTOM, 1.0f); - base->set_custom_minimum_size(Vector2(2048, 1600)); + // p->set_anchor(MARGIN_RIGHT, 1.0f); + // p->set_anchor(MARGIN_BOTTOM, 1.0f); LocalVector data; for (i = 0; i < base->get_child_count(); i++) data.push_back(base->get_child(i)); @@ -76,16 +300,10 @@ public: canvas->set_frame_color(Color(0.2, 0.2, 0.25, 1.0)); canvas_item = canvas; canvas->connect("draw", this, "draw_graph"); + if (current_layout.length() > 0) + update_buttons(canvas); - MenuButton *button = memnew(MenuButton); - button->set_text("Entry"); - canvas->add_child(button); - button->set_size(Vector2(80, 40)); - button->set_position(Vector2(40, 45)); - 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); - button->get_popup()->add_item("Create hallway", 103); + dlg->update(); } void draw_graph() { @@ -95,12 +313,35 @@ public: canvas_item->draw_circle(Vector2(40, 45) + Vector2(40, 20), 40.0f, Color(0.4, 0.4, 0.55, 1.0)); } + void setup_layout_tab(Control *tab, const String &header) + { + assert(gui); + assert(tab); + std::vector args_data = { + /* clang-format off */ + header, + "Layouts:", + 0, Vector2(0, 80), "building_layout_list", + "Create new layout", + "", "building_layouts_create_text", Control::SIZE_EXPAND_FILL, + "Create", "building_layouts_create_button", + "building_layouts_create_new", varray(), + /* clang-format on */ + }; + ui_field::ui_field_builder(gui, tab, + "l_p{v{li.#!lh{e#+!b#!Q}}}", + args_data.data(), args_data.size()); + } static void _bind_methods() { + ClassDB::bind_method(D_METHOD("menu_pressed", "id", "button"), + &BuildingLayoutGraphUI::menu_pressed); ClassDB::bind_method(D_METHOD("tree_entered"), &BuildingLayoutGraphUI::tree_entered); ClassDB::bind_method(D_METHOD("draw_graph"), &BuildingLayoutGraphUI::draw_graph); + ClassDB::bind_method(D_METHOD("select_layout", "id"), + &BuildingLayoutGraphUI::select_layout); } }; diff --git a/src/modules/stream/ui/main_tabs.cpp b/src/modules/stream/ui/main_tabs.cpp index f547649..76f0367 100644 --- a/src/modules/stream/ui/main_tabs.cpp +++ b/src/modules/stream/ui/main_tabs.cpp @@ -161,6 +161,12 @@ void MainTabs::_notification(int which) SceneTree::get_singleton()->get_current_scene()); } else building_layouts_editor = nullptr; + BuildingLayoutGraphUI *pv = nullptr; + if (!Engine::get_singleton()->is_editor_hint()) { + pv = memnew(BuildingLayoutGraphUI( + this, building_layouts_editor)); + handlers.push_back(pv); + } for (i = 0; i < (int)(sizeof(items) / sizeof(items[0])); i++) { VBoxContainer *tab = memnew(VBoxContainer); tab->set_name(items[i].title); @@ -324,19 +330,11 @@ void MainTabs::_notification(int which) args_data.size()); } break; case 5: { - std::vector args_data = { - /* clang-format off */ - items[i].header, - "Layouts:", - 0, Vector2(0, 80), "building_layout_list", - "Create new layout", - "", "building_layouts_create_text", Control::SIZE_EXPAND_FILL, - "Create", "building_layouts_create_button", - /* clang-format on */ - }; - ui_field::ui_field_builder( - this, tab, "l_p{v{li.#!lh{e#+!b#!}}}", - args_data.data(), args_data.size()); + if (!Engine::get_singleton()->is_editor_hint()) { + assert(pv); + pv->setup_layout_tab(tab, + items[i].header); + } } break; } } @@ -346,8 +344,6 @@ void MainTabs::_notification(int which) handlers.push_back(memnew(MenuHandler(rleditor, this))); handlers.push_back( memnew(HandleLinesList(rleditor, this))); - handlers.push_back(memnew(BuildingLayoutGraphUI( - building_layouts_editor))); set_process(true); } } break; diff --git a/src/modules/stream/world_editor.cpp b/src/modules/stream/world_editor.cpp index 458a298..df844a2 100644 --- a/src/modules/stream/world_editor.cpp +++ b/src/modules/stream/world_editor.cpp @@ -83,6 +83,7 @@ WorldEditor::WorldEditor() ecs.component(); ecs.component(); ecs.component(); + ecs.component(); e = ecs.lookup("world_editor"); assert(!e.is_valid()); if (!InputMap::get_singleton()->has_action("left")) diff --git a/src/modules/stream/world_editor.h b/src/modules/stream/world_editor.h index d9133d7..f408dbb 100644 --- a/src/modules/stream/world_editor.h +++ b/src/modules/stream/world_editor.h @@ -67,6 +67,11 @@ public: int mode; String current_type; }; + struct buildings_layout_graph {}; + struct buildings_layout_graph_node { + int depth; + int y_pos; + }; }; };