Now we can generate 3D layouts
This commit is contained in:
37
.vscode/snippets.code-snippets
vendored
Normal file
37
.vscode/snippets.code-snippets
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
// Place your streaming_world workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||||
|
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||||
|
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||||
|
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||||
|
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||||
|
// Placeholders with the same ids are connected.
|
||||||
|
// Example:
|
||||||
|
// "Print to console": {
|
||||||
|
// "scope": "javascript,typescript",
|
||||||
|
// "prefix": "log",
|
||||||
|
// "body": [
|
||||||
|
// "console.log('$1');",
|
||||||
|
// "$2"
|
||||||
|
// ],
|
||||||
|
// "description": "Log output to console"
|
||||||
|
// }
|
||||||
|
"cppHeaderGuard": {
|
||||||
|
"prefix": "hg1",
|
||||||
|
"body": [
|
||||||
|
"#ifndef ${TM_FILEPATH/(?:^.*\\\\src\\\\)?(\\w+)\\W?/${1:/upcase}_/g}",
|
||||||
|
"#define ${TM_FILEPATH/(?:^.*\\\\src\\\\)?(\\w+)\\W?/${1:/upcase}_/g}",
|
||||||
|
"",
|
||||||
|
"#endif // ${TM_FILEPATH/(?:^.*\\\\src\\\\)?(\\w+)\\W?/${1:/upcase}_/g}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"cppHeaderGuard2": {
|
||||||
|
"prefix": "hg2",
|
||||||
|
"body": [
|
||||||
|
"/* ${TM_FILEPATH} */",
|
||||||
|
"#ifndef ${TM_FILENAME/(\\w+)\\W?/${1:/upcase}_/g}",
|
||||||
|
"#define ${TM_FILENAME/(\\w+)\\W?/${1:/upcase}_/g}",
|
||||||
|
"",
|
||||||
|
"#endif // ${TM_FILENAME/(\\w+)\\W?/${1:/upcase}_/g}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/blender/buildings/building-elements-v2.blend
Normal file
BIN
assets/blender/buildings/building-elements-v2.blend
Normal file
Binary file not shown.
BIN
assets/blender/buildings/textures/interior_atlas.png
Normal file
BIN
assets/blender/buildings/textures/interior_atlas.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
godot/astream/building-layouts/building-elements-v2.glb
Normal file
BIN
godot/astream/building-layouts/building-elements-v2.glb
Normal file
Binary file not shown.
1066
godot/astream/building-layouts/building-elements-v2.glb.import
Normal file
1066
godot/astream/building-layouts/building-elements-v2.glb.import
Normal file
File diff suppressed because it is too large
Load Diff
BIN
godot/astream/building-layouts/exterior_atlas.material
Normal file
BIN
godot/astream/building-layouts/exterior_atlas.material
Normal file
Binary file not shown.
BIN
godot/astream/building-layouts/interior_atlas.material
Normal file
BIN
godot/astream/building-layouts/interior_atlas.material
Normal file
Binary file not shown.
@@ -20,6 +20,7 @@ public = [
|
|||||||
[310, "Server Room", { "window": true }],
|
[310, "Server Room", { "window": true }],
|
||||||
[311, "Room", { "window": true }]
|
[311, "Room", { "window": true }]
|
||||||
]
|
]
|
||||||
|
parts_library_path = "res://astream/building-layouts/building-elements-v2.glb"
|
||||||
[commands]
|
[commands]
|
||||||
commands = [
|
commands = [
|
||||||
[-1, "None"],
|
[-1, "None"],
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <scene/gui/spin_box.h>
|
#include <scene/gui/spin_box.h>
|
||||||
#include <scene/gui/option_button.h>
|
#include <scene/gui/option_button.h>
|
||||||
|
#include "setup_3d_viewport.h"
|
||||||
#include "building_layout_graph_ui.h"
|
#include "building_layout_graph_ui.h"
|
||||||
|
|
||||||
void BuildingLayoutGraphUI::menu_pressed(int id, Control *button,
|
void BuildingLayoutGraphUI::menu_pressed(int id, Control *button,
|
||||||
@@ -636,6 +637,30 @@ void BuildingLayoutGraphUI::show_command_editor(Control *item,
|
|||||||
command_editor->popup_centered();
|
command_editor->popup_centered();
|
||||||
}
|
}
|
||||||
static List<Control *> update_controls;
|
static List<Control *> update_controls;
|
||||||
|
flecs::entity BuildingLayoutGraphUI::get_current_grid_floor() const
|
||||||
|
{
|
||||||
|
flecs::entity grid_e = get_current_grid_layout();
|
||||||
|
flecs::query<const WorldEditor::components::buildings_layout_grid_floor>
|
||||||
|
floor_q = grid_e.world()
|
||||||
|
.query_builder<
|
||||||
|
const WorldEditor::components::
|
||||||
|
buildings_layout_grid_floor>()
|
||||||
|
.with(flecs::ChildOf, grid_e)
|
||||||
|
.build();
|
||||||
|
const String &cur_floor = current_grid_floor;
|
||||||
|
flecs::entity grid_floor_e;
|
||||||
|
|
||||||
|
floor_q.each([&grid_floor_e,
|
||||||
|
cur_floor](flecs::entity fe,
|
||||||
|
const WorldEditor::components::
|
||||||
|
buildings_layout_grid_floor) {
|
||||||
|
if (grid_floor_e.is_valid())
|
||||||
|
return;
|
||||||
|
if (fe.name() == cur_floor.ascii().ptr())
|
||||||
|
grid_floor_e = fe;
|
||||||
|
});
|
||||||
|
return grid_floor_e;
|
||||||
|
}
|
||||||
void BuildingLayoutGraphUI::handle_event(const String &event,
|
void BuildingLayoutGraphUI::handle_event(const String &event,
|
||||||
const Vector<Variant> &args)
|
const Vector<Variant> &args)
|
||||||
{
|
{
|
||||||
@@ -698,6 +723,8 @@ void BuildingLayoutGraphUI::tree_entered()
|
|||||||
"Interior", "", 0, "select_grid_level", Control::SIZE_EXPAND_FILL, Color(1, 0, 0, 1),
|
"Interior", "", 0, "select_grid_level", Control::SIZE_EXPAND_FILL, Color(1, 0, 0, 1),
|
||||||
MARGIN_RIGHT, 1.0f, MARGIN_BOTTOM, 1.0f,
|
MARGIN_RIGHT, 1.0f, MARGIN_BOTTOM, 1.0f,
|
||||||
"color_view_grid",
|
"color_view_grid",
|
||||||
|
"Interior 3D",
|
||||||
|
"Exterior scene display", Control::SIZE_EXPAND_FILL, "interior_3d_view",
|
||||||
"Exterior",
|
"Exterior",
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
};
|
};
|
||||||
@@ -705,10 +732,11 @@ void BuildingLayoutGraphUI::tree_entered()
|
|||||||
ui_field::ui_field_builder(
|
ui_field::ui_field_builder(
|
||||||
dlg, dlg,
|
dlg, dlg,
|
||||||
// "p+={t+={v#{s#!+={}}v#{}v#{}}}",
|
// "p+={t+={v#{s#!+={}}v#{}v#{}}}",
|
||||||
"t**{v#{s**{p#!**}}v#{o#$p={c**#$}}v#{}}",
|
"t**{v#{s**{p#!**}}v#{o#$p={c**#$}}v#{lp=#$}v#{}}",
|
||||||
args_data2.data(), args_data2.size(), &save_obj);
|
args_data2.data(), args_data2.size(), &save_obj);
|
||||||
assert(save_obj.has("color_view_grid"));
|
assert(save_obj.has("color_view_grid"));
|
||||||
assert(save_obj.has("select_grid_level"));
|
assert(save_obj.has("select_grid_level"));
|
||||||
|
assert(save_obj.has("interior_3d_view"));
|
||||||
ColorRect *grid_view =
|
ColorRect *grid_view =
|
||||||
Object::cast_to<ColorRect>(save_obj["color_view_grid"]);
|
Object::cast_to<ColorRect>(save_obj["color_view_grid"]);
|
||||||
grid_view->connect("draw", this, "draw_2d_grid_view",
|
grid_view->connect("draw", this, "draw_2d_grid_view",
|
||||||
@@ -729,6 +757,9 @@ void BuildingLayoutGraphUI::tree_entered()
|
|||||||
0)
|
0)
|
||||||
select_layout(0);
|
select_layout(0);
|
||||||
update_graph();
|
update_graph();
|
||||||
|
Control *vc =
|
||||||
|
Object::cast_to<Control>(save_obj["interior_3d_view"]);
|
||||||
|
setup_3dv = memnew(Setup3DViewport(vc, this));
|
||||||
EditorEvent::get_singleton()->event.add_listener(
|
EditorEvent::get_singleton()->event.add_listener(
|
||||||
this, &BuildingLayoutGraphUI::handle_event);
|
this, &BuildingLayoutGraphUI::handle_event);
|
||||||
ItemList *item_list =
|
ItemList *item_list =
|
||||||
@@ -849,6 +880,7 @@ void BuildingLayoutGraphUI::draw_2d_grid_view(Control *draw)
|
|||||||
.with(flecs::ChildOf, fe)
|
.with(flecs::ChildOf, fe)
|
||||||
.build();
|
.build();
|
||||||
HashMap<String, Color> colors;
|
HashMap<String, Color> colors;
|
||||||
|
colors["corridoor"] = Color(0, 0, 0, 1);
|
||||||
q2.each([&draw, grid_size, disp_size,
|
q2.each([&draw, grid_size, disp_size,
|
||||||
&colors](flecs::entity fc,
|
&colors](flecs::entity fc,
|
||||||
const WorldEditor::components::
|
const WorldEditor::components::
|
||||||
@@ -913,6 +945,31 @@ void BuildingLayoutGraphUI::draw_2d_grid_view(Control *draw)
|
|||||||
Color(0, 0, 1, 1),
|
Color(0, 0, 1, 1),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
if (fc.has<WorldEditor::components::
|
||||||
|
internal_wall_west>())
|
||||||
|
draw->draw_rect(
|
||||||
|
Rect2(dx, dy, dsize * 0.2f,
|
||||||
|
dsize),
|
||||||
|
Color(1, 0.3f, 1, 1), true);
|
||||||
|
if (fc.has<WorldEditor::components::
|
||||||
|
internal_wall_east>())
|
||||||
|
draw->draw_rect(
|
||||||
|
Rect2(dx + dsize - dsize * 0.2f,
|
||||||
|
dy, dsize * 0.2f, dsize),
|
||||||
|
Color(1, 0.3f, 1, 1), true);
|
||||||
|
if (fc.has<WorldEditor::components::
|
||||||
|
internal_wall_north>())
|
||||||
|
draw->draw_rect(Rect2(dx, dy, dsize,
|
||||||
|
dsize * 0.2f),
|
||||||
|
Color(1, 0.3f, 1, 1),
|
||||||
|
true);
|
||||||
|
if (fc.has<WorldEditor::components::
|
||||||
|
internal_wall_south>())
|
||||||
|
draw->draw_rect(
|
||||||
|
Rect2(dx,
|
||||||
|
dy + dsize - dsize * 0.2f,
|
||||||
|
dsize, dsize * 0.2f),
|
||||||
|
Color(1, 0.3f, 1, 1), true);
|
||||||
if (fc.has<WorldEditor::components::border>())
|
if (fc.has<WorldEditor::components::border>())
|
||||||
draw->draw_circle(
|
draw->draw_circle(
|
||||||
Vector2(dx + 0.5f * dsize,
|
Vector2(dx + 0.5f * dsize,
|
||||||
@@ -982,6 +1039,8 @@ void BuildingLayoutGraphUI::select_grid_floor_ob(int id, Control *button,
|
|||||||
current_grid_floor = ob->get_item_text(index);
|
current_grid_floor = ob->get_item_text(index);
|
||||||
print_line("selected: " + current_grid_floor);
|
print_line("selected: " + current_grid_floor);
|
||||||
draw->update();
|
draw->update();
|
||||||
|
EditorEvent::get_singleton()->event.emit("update_layout_view",
|
||||||
|
varray());
|
||||||
}
|
}
|
||||||
void BuildingLayoutGraphUI::_bind_methods()
|
void BuildingLayoutGraphUI::_bind_methods()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "world_editor.h"
|
#include "world_editor.h"
|
||||||
#include "building_layout_graph.h"
|
#include "building_layout_graph.h"
|
||||||
|
|
||||||
|
class Setup3DViewport;
|
||||||
class BuildingLayoutGraphUI : public Object {
|
class BuildingLayoutGraphUI : public Object {
|
||||||
GDCLASS(BuildingLayoutGraphUI, Object)
|
GDCLASS(BuildingLayoutGraphUI, Object)
|
||||||
MainTabs *gui;
|
MainTabs *gui;
|
||||||
@@ -25,6 +26,7 @@ class BuildingLayoutGraphUI : public Object {
|
|||||||
Button *button;
|
Button *button;
|
||||||
String current_layout;
|
String current_layout;
|
||||||
String current_grid_floor;
|
String current_grid_floor;
|
||||||
|
Setup3DViewport *setup_3dv;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BuildingLayoutGraphUI(MainTabs *gui, WindowDialog *dlg)
|
BuildingLayoutGraphUI(MainTabs *gui, WindowDialog *dlg)
|
||||||
@@ -51,18 +53,19 @@ public:
|
|||||||
e = e->next();
|
e = e->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flecs::entity get_current_layout()
|
flecs::entity get_current_layout() const
|
||||||
{
|
{
|
||||||
assert(current_layout.length() > 0);
|
assert(current_layout.length() > 0);
|
||||||
return BuildingLayoutGraph::get_singleton()->get_layout(
|
return BuildingLayoutGraph::get_singleton()->get_layout(
|
||||||
current_layout);
|
current_layout);
|
||||||
}
|
}
|
||||||
flecs::entity get_current_grid_layout()
|
flecs::entity get_current_grid_layout() const
|
||||||
{
|
{
|
||||||
assert(current_layout.length() > 0);
|
assert(current_layout.length() > 0);
|
||||||
return BuildingLayoutGraph::get_singleton()->get_grid_layout(
|
return BuildingLayoutGraph::get_singleton()->get_grid_layout(
|
||||||
current_layout);
|
current_layout);
|
||||||
}
|
}
|
||||||
|
flecs::entity get_current_grid_floor() const;
|
||||||
void select_layout(int id)
|
void select_layout(int id)
|
||||||
{
|
{
|
||||||
ItemList *item_list =
|
ItemList *item_list =
|
||||||
|
|||||||
@@ -100,9 +100,6 @@ growth_module::growth_module(flecs::world &ecs)
|
|||||||
west_id, north_id, east_id, south_id
|
west_id, north_id, east_id, south_id
|
||||||
};
|
};
|
||||||
bool outside = false;
|
bool outside = false;
|
||||||
#if 0
|
|
||||||
bool border = false;
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < (int)neighbors.size(); i++) {
|
for (i = 0; i < (int)neighbors.size(); i++) {
|
||||||
int id = neighbors[i];
|
int id = neighbors[i];
|
||||||
print_line("id=" + itos(id));
|
print_line("id=" + itos(id));
|
||||||
@@ -114,31 +111,31 @@ growth_module::growth_module(flecs::world &ecs)
|
|||||||
.ptr());
|
.ptr());
|
||||||
if (!neighbor_e.is_valid()) {
|
if (!neighbor_e.is_valid()) {
|
||||||
outside = true;
|
outside = true;
|
||||||
if (id == west_id)
|
if (id == west_id) {
|
||||||
e.add<WorldEditor::components::
|
e.add<WorldEditor::components::
|
||||||
outside_wall_west>();
|
outside_wall_west>();
|
||||||
else if (id == east_id)
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_west>();
|
||||||
|
} else if (id == east_id) {
|
||||||
e.add<WorldEditor::components::
|
e.add<WorldEditor::components::
|
||||||
outside_wall_east>();
|
outside_wall_east>();
|
||||||
else if (id == north_id)
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_east>();
|
||||||
|
} else if (id == north_id) {
|
||||||
e.add<WorldEditor::components::
|
e.add<WorldEditor::components::
|
||||||
outside_wall_north>();
|
outside_wall_north>();
|
||||||
else if (id == south_id)
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_north>();
|
||||||
|
} else if (id == south_id) {
|
||||||
e.add<WorldEditor::components::
|
e.add<WorldEditor::components::
|
||||||
outside_wall_south>();
|
outside_wall_south>();
|
||||||
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_south>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (!e.parent()
|
|
||||||
.get<WorldEditor::components::
|
|
||||||
buildings_layout_grid_floor>()
|
|
||||||
->cells.has(id)) {
|
|
||||||
outside = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
bool border = false;
|
||||||
flecs::log::dbg("outside: %d", outside);
|
flecs::log::dbg("outside: %d", outside);
|
||||||
#ifdef MAKE_BORDER
|
|
||||||
for (i = 0; i < (int)neighbors.size(); i++) {
|
for (i = 0; i < (int)neighbors.size(); i++) {
|
||||||
int id = neighbors[i];
|
int id = neighbors[i];
|
||||||
print_line("id=" + itos(id));
|
print_line("id=" + itos(id));
|
||||||
@@ -156,10 +153,20 @@ growth_module::growth_module(flecs::world &ecs)
|
|||||||
buildings_layout_grid_cell>();
|
buildings_layout_grid_cell>();
|
||||||
if (cell.type != neighbor_cell->type) {
|
if (cell.type != neighbor_cell->type) {
|
||||||
border = true;
|
border = true;
|
||||||
break;
|
if (id == west_id)
|
||||||
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_west>();
|
||||||
|
else if (id == east_id)
|
||||||
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_east>();
|
||||||
|
else if (id == north_id)
|
||||||
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_north>();
|
||||||
|
else if (id == south_id)
|
||||||
|
e.add<WorldEditor::components::
|
||||||
|
internal_wall_south>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (outside) {
|
if (outside) {
|
||||||
e.add<WorldEditor::components::
|
e.add<WorldEditor::components::
|
||||||
outside_wall>();
|
outside_wall>();
|
||||||
@@ -168,10 +175,8 @@ growth_module::growth_module(flecs::world &ecs)
|
|||||||
} else
|
} else
|
||||||
e.add<WorldEditor::components::
|
e.add<WorldEditor::components::
|
||||||
final_cell>();
|
final_cell>();
|
||||||
#if 0
|
if (border)
|
||||||
if (border)
|
e.add<WorldEditor::components::border>();
|
||||||
e.add<WorldEditor::components::border>();
|
|
||||||
#endif
|
|
||||||
print_line("outside: " + itos(outside));
|
print_line("outside: " + itos(outside));
|
||||||
print_line("position: " +
|
print_line("position: " +
|
||||||
(position.operator String()));
|
(position.operator String()));
|
||||||
|
|||||||
@@ -238,13 +238,6 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
|
|||||||
item->region.can_grow_square = false;
|
item->region.can_grow_square = false;
|
||||||
state[item]++;
|
state[item]++;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if () {
|
|
||||||
item->region.can_grow_square = false;
|
|
||||||
item->region.can_grow = false;
|
|
||||||
item->region.complete = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
grow_count++;
|
grow_count++;
|
||||||
if (item->region.can_grow && state[item] < 7)
|
if (item->region.can_grow && state[item] < 7)
|
||||||
queue.push_back(item);
|
queue.push_back(item);
|
||||||
|
|||||||
340
src/modules/stream/ui/setup_3d_viewport.h
Normal file
340
src/modules/stream/ui/setup_3d_viewport.h
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
/* ~/godot-projects/streaming_world/src/modules/stream/ui/setup_3d_viewport.h */
|
||||||
|
#ifndef SETUP_3D_VIEWPORT_H_
|
||||||
|
#define SETUP_3D_VIEWPORT_H_
|
||||||
|
#undef NDEBUG
|
||||||
|
#include <cassert>
|
||||||
|
#include <scene/gui/control.h>
|
||||||
|
#include <scene/gui/viewport_container.h>
|
||||||
|
#include <scene/main/viewport.h>
|
||||||
|
#include <scene/3d/camera.h>
|
||||||
|
#include <scene/3d/light.h>
|
||||||
|
#include <scene/3d/mesh_instance.h>
|
||||||
|
#include <scene/resources/mesh.h>
|
||||||
|
#include <scene/resources/mesh_library.h>
|
||||||
|
#include <scene/resources/packed_scene.h>
|
||||||
|
#include <scene/resources/primitive_meshes.h>
|
||||||
|
#include <scene/resources/surface_tool.h>
|
||||||
|
#include <editor/editor_file_system.h>
|
||||||
|
#include "building_layout_graph_ui.h"
|
||||||
|
#include "editor_event.h"
|
||||||
|
class BuildingLayoutGraphUI;
|
||||||
|
class Setup3DViewport : public Object {
|
||||||
|
GDCLASS(Setup3DViewport, Object)
|
||||||
|
ViewportContainer *wc;
|
||||||
|
Control *parent;
|
||||||
|
Viewport *view;
|
||||||
|
Camera *camera;
|
||||||
|
DirectionalLight *light;
|
||||||
|
String current_graph;
|
||||||
|
int current_floor;
|
||||||
|
BuildingLayoutGraphUI *base;
|
||||||
|
MeshInstance *display_mi_exterior, *display_mi_interior;
|
||||||
|
Ref<MeshLibrary> layout_parts;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
wc = memnew(ViewportContainer);
|
||||||
|
view = memnew(Viewport);
|
||||||
|
light = memnew(DirectionalLight);
|
||||||
|
view->set_size(parent->get_size() * 0.95f);
|
||||||
|
Ref<World> use_world;
|
||||||
|
Ref<Environment> env;
|
||||||
|
use_world.instance();
|
||||||
|
env.instance();
|
||||||
|
env->set_ambient_light_color(Color(0.8, 0.9, 0.9, 1));
|
||||||
|
env->set_ambient_light_energy(0.6f);
|
||||||
|
use_world->set_environment(env);
|
||||||
|
view->set_world(use_world);
|
||||||
|
view->set_use_own_world(true);
|
||||||
|
view->set_update_mode(Viewport::UPDATE_WHEN_VISIBLE);
|
||||||
|
camera = memnew(Camera);
|
||||||
|
Transform cam_xform =
|
||||||
|
Transform(Basis(), Vector3(30, 20, 30))
|
||||||
|
.looking_at(Vector3(), Vector3(0, 1, 0));
|
||||||
|
camera->set_transform(cam_xform);
|
||||||
|
camera->set_zfar(1000.0f);
|
||||||
|
// camera->call_deferred("set_as_top_level", true);
|
||||||
|
view->call_deferred("add_child", camera);
|
||||||
|
view->call_deferred("add_child", light);
|
||||||
|
light->set_translation(Vector3(0, 50, 0));
|
||||||
|
wc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
wc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
wc->set_custom_minimum_size(view->get_size());
|
||||||
|
wc->call_deferred("add_child", view);
|
||||||
|
parent->call_deferred("add_child", wc);
|
||||||
|
wc->connect("resized", this, "resize");
|
||||||
|
MeshInstance *base_mi = memnew(MeshInstance);
|
||||||
|
Ref<CubeMesh> cube;
|
||||||
|
cube.instance();
|
||||||
|
cube->set_size(Vector3(100, 1, 100));
|
||||||
|
base_mi->set_mesh(cube);
|
||||||
|
base_mi->set_translation(Vector3(0, -0.5, 0));
|
||||||
|
view->call_deferred("add_child", base_mi);
|
||||||
|
display_mi_exterior = memnew(MeshInstance);
|
||||||
|
view->call_deferred("add_child", display_mi_exterior);
|
||||||
|
display_mi_interior = memnew(MeshInstance);
|
||||||
|
view->call_deferred("add_child", display_mi_interior);
|
||||||
|
}
|
||||||
|
void build_mesh_data()
|
||||||
|
{
|
||||||
|
flecs::entity grid_floor_e = base->get_current_grid_floor();
|
||||||
|
if (!grid_floor_e.is_valid())
|
||||||
|
return;
|
||||||
|
flecs::log::dbg("layout is valid");
|
||||||
|
int grid_size =
|
||||||
|
grid_floor_e
|
||||||
|
.get<WorldEditor::components::
|
||||||
|
buildings_layout_grid_floor>()
|
||||||
|
->grid_size;
|
||||||
|
flecs::query<
|
||||||
|
const WorldEditor::components::buildings_layout_grid_cell>
|
||||||
|
cells_query =
|
||||||
|
grid_floor_e.world()
|
||||||
|
.query_builder<
|
||||||
|
const WorldEditor::components::
|
||||||
|
buildings_layout_grid_cell>()
|
||||||
|
.with(flecs::ChildOf, grid_floor_e)
|
||||||
|
.build();
|
||||||
|
Ref<ArrayMesh> layout_mesh_exterior, layout_mesh_interior;
|
||||||
|
layout_mesh_exterior.instance();
|
||||||
|
layout_mesh_interior.instance();
|
||||||
|
SurfaceTool tool_exterior, tool_interior;
|
||||||
|
Ref<Material> mat_exterior, mat_interior;
|
||||||
|
layout_mesh_exterior->set_storage_mode(Mesh::STORAGE_MODE_CPU);
|
||||||
|
layout_mesh_interior->set_storage_mode(Mesh::STORAGE_MODE_CPU);
|
||||||
|
tool_exterior.create_from(layout_mesh_exterior, 0);
|
||||||
|
tool_interior.create_from(layout_mesh_interior, 0);
|
||||||
|
Transform offset(Basis(), Vector3(-grid_size * 4 / 2, 0,
|
||||||
|
-grid_size * 4 / 2));
|
||||||
|
cells_query.each([this, grid_size, offset, &tool_exterior,
|
||||||
|
&tool_interior, &mat_exterior, &mat_interior](
|
||||||
|
flecs::entity e,
|
||||||
|
const WorldEditor::components::
|
||||||
|
buildings_layout_grid_cell
|
||||||
|
&cell) {
|
||||||
|
int i;
|
||||||
|
int x = cell.index % grid_size;
|
||||||
|
int y = 0;
|
||||||
|
int z = cell.index / grid_size;
|
||||||
|
Transform base_transform(Basis(),
|
||||||
|
Vector3(x * 4, 0, z * 4));
|
||||||
|
int matches = 0;
|
||||||
|
Vector<Pair<int, Transform> > items_exterior;
|
||||||
|
Vector<Pair<int, Transform> > items_interior;
|
||||||
|
struct pmatch {
|
||||||
|
int mask;
|
||||||
|
String item;
|
||||||
|
Basis basis;
|
||||||
|
Vector3 offset;
|
||||||
|
bool exterior;
|
||||||
|
};
|
||||||
|
struct pmatch match_data[] = {
|
||||||
|
{ 1, "outside-wall", Basis(), Vector3(0, 0, -2),
|
||||||
|
true },
|
||||||
|
{ 2, "outside-wall",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0), Math_PI),
|
||||||
|
Vector3(0, 0, 2), true },
|
||||||
|
{ 4, "outside-wall",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
Math_PI / 2),
|
||||||
|
Vector3(-2, 0, 0), true },
|
||||||
|
{ 8, "outside-wall",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
-Math_PI / 2),
|
||||||
|
Vector3(2, 0, 0), true },
|
||||||
|
{ 2 | 8, "outside-wall-corner",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0), Math_PI),
|
||||||
|
Vector3(2, 0, 2), true },
|
||||||
|
{ 1 | 4, "outside-wall-corner",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0), 0),
|
||||||
|
Vector3(-2, 0, -2), true },
|
||||||
|
{ 1 | 8, "outside-wall-corner",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
-Math_PI / 2),
|
||||||
|
Vector3(2, 0, -2), true },
|
||||||
|
{ 2 | 4, "outside-wall-corner",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
Math_PI / 2),
|
||||||
|
Vector3(-2, 0, 2), true },
|
||||||
|
{ 16, "internal-wall", Basis(),
|
||||||
|
Vector3(0, 0, -2), false },
|
||||||
|
{ 32, "internal-wall",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0), Math_PI),
|
||||||
|
Vector3(0, 0, 2), false },
|
||||||
|
{ 64, "internal-wall",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
Math_PI / 2),
|
||||||
|
Vector3(-2, 0, 0), false },
|
||||||
|
{ 128, "internal-wall",
|
||||||
|
Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
-Math_PI / 2),
|
||||||
|
Vector3(2, 0, 0), false },
|
||||||
|
};
|
||||||
|
if (e.has<WorldEditor::components::outside_wall_north>())
|
||||||
|
matches |= 1;
|
||||||
|
if (e.has<WorldEditor::components::outside_wall_south>())
|
||||||
|
matches |= 2;
|
||||||
|
if (e.has<WorldEditor::components::outside_wall_west>())
|
||||||
|
matches |= 4;
|
||||||
|
if (e.has<WorldEditor::components::outside_wall_east>())
|
||||||
|
matches |= 8;
|
||||||
|
if (e.has<WorldEditor::components::internal_wall_north>())
|
||||||
|
matches |= 16;
|
||||||
|
if (e.has<WorldEditor::components::internal_wall_south>())
|
||||||
|
matches |= 32;
|
||||||
|
if (e.has<WorldEditor::components::internal_wall_west>())
|
||||||
|
matches |= 64;
|
||||||
|
if (e.has<WorldEditor::components::internal_wall_east>())
|
||||||
|
matches |= 128;
|
||||||
|
for (i = 0; i < (int)sizeof(match_data) /
|
||||||
|
(int)sizeof(match_data[0]);
|
||||||
|
i++) {
|
||||||
|
int mask = match_data[i].mask;
|
||||||
|
if ((matches & mask) == mask) {
|
||||||
|
int id =
|
||||||
|
layout_parts->find_item_by_name(
|
||||||
|
match_data[i].item);
|
||||||
|
assert(id >= 0);
|
||||||
|
Transform item_transform;
|
||||||
|
item_transform.basis =
|
||||||
|
match_data[i].basis;
|
||||||
|
item_transform.origin =
|
||||||
|
match_data[i].offset;
|
||||||
|
if (match_data[i].exterior)
|
||||||
|
items_exterior.push_back(
|
||||||
|
{ id, item_transform });
|
||||||
|
else
|
||||||
|
items_interior.push_back(
|
||||||
|
{ id, item_transform });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < items_exterior.size(); i++) {
|
||||||
|
Ref<Mesh> mesh = layout_parts->get_item_mesh(
|
||||||
|
items_exterior[i].first);
|
||||||
|
assert(mesh.is_valid());
|
||||||
|
if (!mat_exterior.is_valid())
|
||||||
|
mat_exterior =
|
||||||
|
mesh->surface_get_material(0);
|
||||||
|
tool_exterior.append_from(
|
||||||
|
mesh, 0,
|
||||||
|
offset * base_transform *
|
||||||
|
items_exterior[i].second);
|
||||||
|
}
|
||||||
|
for (i = 0; i < items_interior.size(); i++) {
|
||||||
|
Ref<Mesh> mesh = layout_parts->get_item_mesh(
|
||||||
|
items_interior[i].first);
|
||||||
|
assert(mesh.is_valid());
|
||||||
|
if (!mat_interior.is_valid())
|
||||||
|
mat_interior =
|
||||||
|
mesh->surface_get_material(0);
|
||||||
|
tool_interior.append_from(
|
||||||
|
mesh, 0,
|
||||||
|
offset * base_transform *
|
||||||
|
items_interior[i].second);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Array arr_exterior = tool_exterior.commit_to_arrays();
|
||||||
|
layout_mesh_exterior->add_surface_from_arrays(
|
||||||
|
Mesh::PRIMITIVE_TRIANGLES, arr_exterior, Array(),
|
||||||
|
Mesh::ARRAY_COMPRESS_DEFAULT);
|
||||||
|
if (!mat_exterior.is_valid()) {
|
||||||
|
Ref<SpatialMaterial> spmat;
|
||||||
|
spmat.instance();
|
||||||
|
spmat->set_albedo(Color(1.0f, 0.6f, 0.6f));
|
||||||
|
mat_exterior = spmat;
|
||||||
|
}
|
||||||
|
Array arr_interior = tool_interior.commit_to_arrays();
|
||||||
|
layout_mesh_interior->add_surface_from_arrays(
|
||||||
|
Mesh::PRIMITIVE_TRIANGLES, arr_interior, Array(),
|
||||||
|
Mesh::ARRAY_COMPRESS_DEFAULT);
|
||||||
|
if (!mat_interior.is_valid()) {
|
||||||
|
Ref<SpatialMaterial> spmat;
|
||||||
|
spmat.instance();
|
||||||
|
spmat->set_albedo(Color(1.0f, 0.6f, 0.6f));
|
||||||
|
mat_interior = spmat;
|
||||||
|
}
|
||||||
|
layout_mesh_exterior->surface_set_material(0, mat_exterior);
|
||||||
|
display_mi_exterior->hide();
|
||||||
|
display_mi_exterior->set_mesh(layout_mesh_exterior);
|
||||||
|
layout_mesh_exterior->set_storage_mode(
|
||||||
|
Mesh::STORAGE_MODE_CPU_AND_GPU);
|
||||||
|
display_mi_exterior->show();
|
||||||
|
layout_mesh_interior->surface_set_material(0, mat_interior);
|
||||||
|
display_mi_interior->hide();
|
||||||
|
display_mi_interior->set_mesh(layout_mesh_interior);
|
||||||
|
layout_mesh_interior->set_storage_mode(
|
||||||
|
Mesh::STORAGE_MODE_CPU_AND_GPU);
|
||||||
|
display_mi_interior->show();
|
||||||
|
}
|
||||||
|
void resize()
|
||||||
|
{
|
||||||
|
wc->update();
|
||||||
|
view->set_size(wc->get_size());
|
||||||
|
}
|
||||||
|
static void _bind_methods()
|
||||||
|
{
|
||||||
|
ClassDB::bind_method(D_METHOD("setup"),
|
||||||
|
&Setup3DViewport::setup);
|
||||||
|
ClassDB::bind_method(D_METHOD("resize"),
|
||||||
|
&Setup3DViewport::resize);
|
||||||
|
}
|
||||||
|
void update_layout(const String &event, const Vector<Variant> &args)
|
||||||
|
{
|
||||||
|
if (event == "update_layout_view") {
|
||||||
|
build_mesh_data();
|
||||||
|
flecs::log::dbg("mesh updated");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_mesh_library(const Ref<PackedScene> &scene)
|
||||||
|
{
|
||||||
|
Node *sroot = scene->instance();
|
||||||
|
if (!layout_parts.is_valid())
|
||||||
|
layout_parts.instance();
|
||||||
|
List<Node *> queue;
|
||||||
|
queue.push_back(sroot);
|
||||||
|
while (!queue.empty()) {
|
||||||
|
int i;
|
||||||
|
Node *item = queue.front()->get();
|
||||||
|
queue.pop_front();
|
||||||
|
MeshInstance *mi = Object::cast_to<MeshInstance>(item);
|
||||||
|
if (mi) {
|
||||||
|
String mesh_name = mi->get_name();
|
||||||
|
Ref<ArrayMesh> mesh = mi->get_mesh();
|
||||||
|
mesh->set_storage_mode(Mesh::STORAGE_MODE_CPU);
|
||||||
|
int id =
|
||||||
|
layout_parts->get_last_unused_item_id();
|
||||||
|
layout_parts->create_item(id);
|
||||||
|
layout_parts->set_item_name(id, mesh_name);
|
||||||
|
layout_parts->set_item_mesh(id, mesh);
|
||||||
|
}
|
||||||
|
for (i = 0; i < item->get_child_count(); i++)
|
||||||
|
queue.push_back(item->get_child(i));
|
||||||
|
}
|
||||||
|
sroot->queue_delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Setup3DViewport(Control *parent, BuildingLayoutGraphUI *base)
|
||||||
|
: Object()
|
||||||
|
, parent(parent)
|
||||||
|
, base(base)
|
||||||
|
{
|
||||||
|
ConfigFile config;
|
||||||
|
Error err = config.load("res://astream/building_layout.conf");
|
||||||
|
assert(err == OK);
|
||||||
|
String library_scene_path =
|
||||||
|
config.get_value("rooms", "parts_library_path");
|
||||||
|
Ref<PackedScene> library_scene = ResourceLoader::load(
|
||||||
|
library_scene_path, "PackedScene", true);
|
||||||
|
assert(library_scene.is_valid());
|
||||||
|
create_mesh_library(library_scene);
|
||||||
|
parent->connect("ready", this, "setup");
|
||||||
|
if (parent->is_node_ready())
|
||||||
|
setup();
|
||||||
|
EditorEvent::get_singleton()->event.add_listener(
|
||||||
|
this, &Setup3DViewport::update_layout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // SETUP_3D_VIEWPORT_H_
|
||||||
@@ -127,6 +127,10 @@ public:
|
|||||||
struct outside_wall_west {};
|
struct outside_wall_west {};
|
||||||
struct outside_wall_north {};
|
struct outside_wall_north {};
|
||||||
struct outside_wall_south {};
|
struct outside_wall_south {};
|
||||||
|
struct internal_wall_east {};
|
||||||
|
struct internal_wall_west {};
|
||||||
|
struct internal_wall_north {};
|
||||||
|
struct internal_wall_south {};
|
||||||
struct corridoor {};
|
struct corridoor {};
|
||||||
struct buildings_layout_grid_floor {
|
struct buildings_layout_grid_floor {
|
||||||
Set<int> cells;
|
Set<int> cells;
|
||||||
|
|||||||
Reference in New Issue
Block a user