Working on interior graph
This commit is contained in:
@@ -8,20 +8,142 @@
|
|||||||
#include <scene/gui/dialogs.h>
|
#include <scene/gui/dialogs.h>
|
||||||
#include <scene/gui/menu_button.h>
|
#include <scene/gui/menu_button.h>
|
||||||
#include <scene/gui/color_rect.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 "ui_field_builder.h"
|
||||||
|
#include "main_tabs.h"
|
||||||
|
#include "base_data.h"
|
||||||
|
#include "editor_event.h"
|
||||||
|
#include "world_editor.h"
|
||||||
|
|
||||||
class BuildingLayoutGraphUI : public Object {
|
class BuildingLayoutGraphUI : public Object {
|
||||||
GDCLASS(BuildingLayoutGraphUI, Object)
|
GDCLASS(BuildingLayoutGraphUI, Object)
|
||||||
|
MainTabs *gui;
|
||||||
WindowDialog *dlg;
|
WindowDialog *dlg;
|
||||||
Control *canvas_item;
|
Control *canvas_item;
|
||||||
|
Button *button;
|
||||||
|
String current_layout;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BuildingLayoutGraphUI(WindowDialog *dlg)
|
BuildingLayoutGraphUI(MainTabs *gui, WindowDialog *dlg)
|
||||||
: Object()
|
: Object()
|
||||||
|
, gui(gui)
|
||||||
, dlg(dlg)
|
, dlg(dlg)
|
||||||
|
, canvas_item(nullptr)
|
||||||
|
, button(nullptr)
|
||||||
{
|
{
|
||||||
dlg->connect("tree_entered", this, "tree_entered");
|
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()
|
void tree_entered()
|
||||||
{
|
{
|
||||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
@@ -47,21 +169,123 @@ public:
|
|||||||
args_data2.data(), args_data2.size());
|
args_data2.data(), args_data2.size());
|
||||||
dlg->update();
|
dlg->update();
|
||||||
update_graph();
|
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()
|
void update_graph()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
assert(dlg->get_node(NodePath("%buildings_layout_graph")));
|
assert(dlg->get_node(NodePath("%buildings_layout_graph")));
|
||||||
Control *base = Object::cast_to<Control>(
|
Control *base = Object::cast_to<Control>(
|
||||||
dlg->get_node(NodePath("%buildings_layout_graph")));
|
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 =
|
ScrollContainer *p =
|
||||||
Object::cast_to<ScrollContainer>(base->get_parent());
|
Object::cast_to<ScrollContainer>(base->get_parent());
|
||||||
p->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
p->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
p->set_h_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_RIGHT, 1.0f);
|
||||||
p->set_anchor(MARGIN_BOTTOM, 1.0f);
|
// p->set_anchor(MARGIN_BOTTOM, 1.0f);
|
||||||
base->set_custom_minimum_size(Vector2(2048, 1600));
|
|
||||||
LocalVector<Node *> data;
|
LocalVector<Node *> data;
|
||||||
for (i = 0; i < base->get_child_count(); i++)
|
for (i = 0; i < base->get_child_count(); i++)
|
||||||
data.push_back(base->get_child(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->set_frame_color(Color(0.2, 0.2, 0.25, 1.0));
|
||||||
canvas_item = canvas;
|
canvas_item = canvas;
|
||||||
canvas->connect("draw", this, "draw_graph");
|
canvas->connect("draw", this, "draw_graph");
|
||||||
|
if (current_layout.length() > 0)
|
||||||
|
update_buttons(canvas);
|
||||||
|
|
||||||
MenuButton *button = memnew(MenuButton);
|
dlg->update();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
void draw_graph()
|
void draw_graph()
|
||||||
{
|
{
|
||||||
@@ -95,12 +313,35 @@ public:
|
|||||||
canvas_item->draw_circle(Vector2(40, 45) + Vector2(40, 20),
|
canvas_item->draw_circle(Vector2(40, 45) + Vector2(40, 20),
|
||||||
40.0f, Color(0.4, 0.4, 0.55, 1.0));
|
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()
|
static void _bind_methods()
|
||||||
{
|
{
|
||||||
|
ClassDB::bind_method(D_METHOD("menu_pressed", "id", "button"),
|
||||||
|
&BuildingLayoutGraphUI::menu_pressed);
|
||||||
ClassDB::bind_method(D_METHOD("tree_entered"),
|
ClassDB::bind_method(D_METHOD("tree_entered"),
|
||||||
&BuildingLayoutGraphUI::tree_entered);
|
&BuildingLayoutGraphUI::tree_entered);
|
||||||
ClassDB::bind_method(D_METHOD("draw_graph"),
|
ClassDB::bind_method(D_METHOD("draw_graph"),
|
||||||
&BuildingLayoutGraphUI::draw_graph);
|
&BuildingLayoutGraphUI::draw_graph);
|
||||||
|
ClassDB::bind_method(D_METHOD("select_layout", "id"),
|
||||||
|
&BuildingLayoutGraphUI::select_layout);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,12 @@ void MainTabs::_notification(int which)
|
|||||||
SceneTree::get_singleton()->get_current_scene());
|
SceneTree::get_singleton()->get_current_scene());
|
||||||
} else
|
} else
|
||||||
building_layouts_editor = nullptr;
|
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++) {
|
for (i = 0; i < (int)(sizeof(items) / sizeof(items[0])); i++) {
|
||||||
VBoxContainer *tab = memnew(VBoxContainer);
|
VBoxContainer *tab = memnew(VBoxContainer);
|
||||||
tab->set_name(items[i].title);
|
tab->set_name(items[i].title);
|
||||||
@@ -324,19 +330,11 @@ void MainTabs::_notification(int which)
|
|||||||
args_data.size());
|
args_data.size());
|
||||||
} break;
|
} break;
|
||||||
case 5: {
|
case 5: {
|
||||||
std::vector<Variant> args_data = {
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
/* clang-format off */
|
assert(pv);
|
||||||
items[i].header,
|
pv->setup_layout_tab(tab,
|
||||||
"Layouts:",
|
items[i].header);
|
||||||
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());
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,8 +344,6 @@ void MainTabs::_notification(int which)
|
|||||||
handlers.push_back(memnew(MenuHandler(rleditor, this)));
|
handlers.push_back(memnew(MenuHandler(rleditor, this)));
|
||||||
handlers.push_back(
|
handlers.push_back(
|
||||||
memnew(HandleLinesList(rleditor, this)));
|
memnew(HandleLinesList(rleditor, this)));
|
||||||
handlers.push_back(memnew(BuildingLayoutGraphUI(
|
|
||||||
building_layouts_editor)));
|
|
||||||
set_process(true);
|
set_process(true);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ WorldEditor::WorldEditor()
|
|||||||
ecs.component<WorldEditor::components::buildings_editor_node>();
|
ecs.component<WorldEditor::components::buildings_editor_node>();
|
||||||
ecs.component<WorldEditor::components::road_lines_editor_node>();
|
ecs.component<WorldEditor::components::road_lines_editor_node>();
|
||||||
ecs.component<WorldEditor::components::buildings_editor_mode>();
|
ecs.component<WorldEditor::components::buildings_editor_mode>();
|
||||||
|
ecs.component<WorldEditor::components::buildings_layout_graph>();
|
||||||
e = ecs.lookup("world_editor");
|
e = ecs.lookup("world_editor");
|
||||||
assert(!e.is_valid());
|
assert(!e.is_valid());
|
||||||
if (!InputMap::get_singleton()->has_action("left"))
|
if (!InputMap::get_singleton()->has_action("left"))
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ public:
|
|||||||
int mode;
|
int mode;
|
||||||
String current_type;
|
String current_type;
|
||||||
};
|
};
|
||||||
|
struct buildings_layout_graph {};
|
||||||
|
struct buildings_layout_graph_node {
|
||||||
|
int depth;
|
||||||
|
int y_pos;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user