Working on interior graph

This commit is contained in:
2024-10-26 02:41:33 +03:00
parent 3b4006e02d
commit 69b807bf22
4 changed files with 271 additions and 28 deletions

View File

@@ -8,20 +8,142 @@
#include <scene/gui/dialogs.h>
#include <scene/gui/menu_button.h>
#include <scene/gui/color_rect.h>
#include <scene/gui/line_edit.h>
#include <scene/gui/item_list.h>
#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<String> *keys)
{
flecs::entity base = get_layout_base();
base.children([keys](flecs::entity e) {
if (e.has<WorldEditor::components::
buildings_layout_graph>())
keys->push_back(String(e.name()));
});
}
void update_layout_item_list()
{
ItemList *item_list =
gui->get_as_node<ItemList>("%building_layout_list");
List<String> items;
get_layout_list(&items);
List<String>::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<WorldEditor::components::buildings_layout_graph>();
}
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<flecs::entity> *keys)
{
layout_e.children(
[keys](flecs::entity e) { keys->push_back(e); });
}
void select_layout(int id)
{
ItemList *item_list =
gui->get_as_node<ItemList>("%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<Variant> &args)
{
int i;
if (event == "button:building_layouts_create_new") {
LineEdit *line_edit = gui->get_as_node<LineEdit>(
"%building_layouts_create_text");
ItemList *item_list = gui->get_as_node<ItemList>(
"%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<Vector2> buttons;
void update_buttons(ColorRect *canvas)
{
assert(current_layout.length() > 0);
flecs::entity e = get_current_layout();
List<flecs::entity> queue;
bool layout_empty = true;
queue.push_back(e);
HashMap<int, int> 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<WorldEditor::components::
buildings_layout_graph_node>()) {
e.set<WorldEditor::components::
buildings_layout_graph_node>(
{ 0, 0 });
}
int depth = e.get<WorldEditor::components::
buildings_layout_graph_node>()
->depth;
int y = e.get<WorldEditor::components::
buildings_layout_graph_node>()
->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<WorldEditor::components::
buildings_layout_graph>()) {
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<WorldEditor::components::
buildings_layout_graph_node>(
{ 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<WorldEditor::components::
buildings_layout_graph_node>(
{ 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<Control>(
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<ScrollContainer>(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<Node *> 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<Variant> 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);
}
};

View File

@@ -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<Variant> 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;

View File

@@ -83,6 +83,7 @@ WorldEditor::WorldEditor()
ecs.component<WorldEditor::components::buildings_editor_node>();
ecs.component<WorldEditor::components::road_lines_editor_node>();
ecs.component<WorldEditor::components::buildings_editor_mode>();
ecs.component<WorldEditor::components::buildings_layout_graph>();
e = ecs.lookup("world_editor");
assert(!e.is_valid());
if (!InputMap::get_singleton()->has_action("left"))

View File

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