diff --git a/godot/main/building_layout_editor.tscn b/godot/main/building_layout_editor.tscn index 12705fa..b9b32b2 100644 --- a/godot/main/building_layout_editor.tscn +++ b/godot/main/building_layout_editor.tscn @@ -1,16 +1,8 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=8 format=2] [ext_resource path="res://main/building_layout_editor.gd" type="Script" id=1] [ext_resource path="res://astream/building-layouts/building-elements.glb" type="PackedScene" id=2] -[sub_resource type="SpatialMaterial" id=4] -flags_transparent = true -albedo_color = Color( 1, 1, 1, 0.654902 ) - -[sub_resource type="CubeMesh" id=1] -material = SubResource( 4 ) -size = Vector3( 40, 1, 40 ) - [sub_resource type="SpatialMaterial" id=2] flags_transparent = true flags_unshaded = true @@ -20,6 +12,17 @@ albedo_color = Color( 0.745098, 0.105882, 0.105882, 0.192157 ) material = SubResource( 2 ) size = Vector3( 4, 8, 4 ) +[sub_resource type="SpatialMaterial" id=4] +flags_transparent = true +albedo_color = Color( 1, 1, 1, 0.654902 ) + +[sub_resource type="CubeMesh" id=1] +material = SubResource( 4 ) +size = Vector3( 40, 1, 40 ) + +[sub_resource type="BoxShape" id=5] +extents = Vector3( 20, 1, 20 ) + [node name="building_layout_editor" type="Spatial"] script = ExtResource( 1 ) @@ -60,16 +63,14 @@ focus_mode = 2 text = "Interior" switch_on_hover = true -[node name="bg_floor" type="MeshInstance" parent="."] +[node name="bg_floor" type="Spatial" parent="."] unique_name_in_owner = true -transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0 ) -mesh = SubResource( 1 ) [node name="DirectionalLight" type="DirectionalLight" parent="."] transform = Transform( 1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 100, 0 ) [node name="Camera" type="Camera" parent="."] -transform = Transform( 0.707107, 0.5, -0.5, 0, 0.707107, 0.707107, 0.707107, -0.5, 0.5, -25, 25, 25 ) +transform = Transform( 0.707107, 0.5, -0.5, 0, 0.707107, 0.707107, 0.707107, -0.5, 0.5, -16, 23, 30 ) [node name="VBoxContainer" type="VBoxContainer" parent="."] anchor_left = 1.0 @@ -323,6 +324,48 @@ size_flags_horizontal = 3 size_flags_vertical = 3 columns = 2 +[node name="layout_editor" type="PanelContainer" parent="VBoxContainer"] +unique_name_in_owner = true +margin_top = 719.0 +margin_right = 314.0 +margin_bottom = 847.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/layout_editor"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 307.0 +margin_bottom = 121.0 + +[node name="grid_elements" type="OptionButton" parent="VBoxContainer/layout_editor/VBoxContainer"] +unique_name_in_owner = true +margin_right = 300.0 +margin_bottom = 20.0 + +[node name="clear_grid_cell" type="Button" parent="VBoxContainer/layout_editor/VBoxContainer"] +unique_name_in_owner = true +margin_top = 24.0 +margin_right = 300.0 +margin_bottom = 44.0 +text = "Clear cell" + +[node name="Label" type="Label" parent="VBoxContainer/layout_editor/VBoxContainer"] +margin_top = 48.0 +margin_right = 300.0 +margin_bottom = 62.0 +text = "Level" + +[node name="level_value" type="SpinBox" parent="VBoxContainer/layout_editor/VBoxContainer"] +unique_name_in_owner = true +margin_top = 66.0 +margin_right = 300.0 +margin_bottom = 90.0 + +[node name="layout_selector" type="OptionButton" parent="VBoxContainer/layout_editor/VBoxContainer"] +unique_name_in_owner = true +margin_top = 94.0 +margin_right = 300.0 +margin_bottom = 114.0 + [node name="BuildingLayoutEditor" type="BuildingLayoutEditor" parent="."] source = ExtResource( 2 ) @@ -333,3 +376,23 @@ unique_name_in_owner = true transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 4, -2 ) mesh = SubResource( 3 ) skeleton = NodePath("../..") + +[node name="RemoteTransform" type="RemoteTransform" parent="."] +remote_path = NodePath("../bg_floor") +update_rotation = false +update_scale = false + +[node name="bg_floor_base" type="MeshInstance" parent="RemoteTransform"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, -0.5, -2 ) +mesh = SubResource( 1 ) +skeleton = NodePath("../..") + +[node name="Area" type="Area" parent="RemoteTransform/bg_floor_base"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0 ) +collision_layer = 49152 +collision_mask = 49152 +monitoring = false + +[node name="CollisionShape" type="CollisionShape" parent="RemoteTransform/bg_floor_base/Area"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 ) +shape = SubResource( 5 ) diff --git a/src/modules/stream/buildings/SCsub b/src/modules/stream/buildings/SCsub index d0136a3..66085fc 100644 --- a/src/modules/stream/buildings/SCsub +++ b/src/modules/stream/buildings/SCsub @@ -14,3 +14,4 @@ env.add_source_files(env.stream_building_sources, "*.cpp") lib = env.add_library("buildings", env.stream_building_sources) env.Prepend(LIBS=[lib]) +env.Prepend(CPPPATH=[".."]) diff --git a/src/modules/stream/buildings/building_layout_editor.cpp b/src/modules/stream/buildings/building_layout_editor.cpp index 373a33a..1fc006c 100644 --- a/src/modules/stream/buildings/building_layout_editor.cpp +++ b/src/modules/stream/buildings/building_layout_editor.cpp @@ -14,6 +14,7 @@ #include #include #include +#include "editor_event.h" #include "building_layout_editor.h" template T *get_as_node(const String &path) @@ -85,6 +86,30 @@ protected: HashMap elements; public: + inline int constexpr get_grid_size() + { + return grid_size; + } + inline const String &get_grid_element(int i) const + { + assert(i >= 0 && i < grid_size * grid_size); + return grid[i].element; + } + inline int get_grid_rotation(int i) const + { + assert(i >= 0 && i < grid_size * grid_size); + return grid[i].rotation; + } + void set_grid_element(int i, const String &element) + { + assert(i >= 0 && i < grid_size * grid_size); + grid.write[i].element = element; + } + void set_grid_rotation(int i, int rotation) + { + assert(i >= 0 && i < grid_size * grid_size); + grid.write[i].rotation = rotation; + } void get_element_type_key_list(List *keys) { element_type.get_key_list(keys); @@ -302,6 +327,157 @@ public: }; ElementData *ElementData::singleton = nullptr; +class LayoutEditor : public Object { + GDCLASS(LayoutEditor, Object) + BuildingLayoutEditor *editor; + String grid_elements; + Vector grid_nodes; + int current_cell; + +public: + LayoutEditor(BuildingLayoutEditor *editor) + : Object() + , editor(editor) + , grid_elements("%grid_elements") + , current_cell(-1) + { + get_as_node(grid_elements) + ->connect("item_selected", this, "select_grid_element"); + } + virtual ~LayoutEditor() + { + } + void activate() + { + get_as_node("%layout_editor")->show(); + get_as_node("%bg_floor")->show(); + { + // delete children of bg_floor + int i; + for (i = 0; i < get_as_node("%bg_floor") + ->get_child_count(); + i++) { + get_as_node("%bg_floor") + ->get_child(i) + ->queue_delete(); + } + int grid_size = + ElementData::get_singleton()->get_grid_size(); + assert(grid_size > 0); + grid_nodes.resize(grid_size * grid_size); + for (i = 0; i < grid_size * grid_size; i++) { + int x = i % grid_size; + int z = i / grid_size; + Spatial *node = memnew(Spatial); + int rotation = ElementData::get_singleton() + ->get_grid_rotation(i); + get_as_node("%bg_floor") + ->call_deferred("add_child", node); + node->set_transform(Transform( + Basis().rotated(Vector3(0, 1, 0), + Math_PI * rotation / + 2.0f), + Vector3((x - 4) * 4, 0, (z - 4) * 4) - + get_as_node("%bg_floor") + ->get_transform() + .origin)); + String element = ElementData::get_singleton() + ->get_grid_element(i); + editor->visualize_element_at(element, node); + + grid_nodes.write[i] = node; + print_line("element: " + element); + } + assert(grid_nodes.size() > 0); + } + editor->get_viewport()->get_camera()->set_global_translation( + Vector3(-14, 23, 32)); + List element_keys; + List::Element *e; + ElementData::get_singleton()->get_element_type_key_list( + &element_keys); + e = element_keys.front(); + get_as_node(grid_elements)->clear(); + while (e) { + get_as_node(grid_elements) + ->add_item(e->get()); + print_line("Added item: " + e->get()); + e = e->next(); + } + EditorEvent::get_singleton()->event.add_listener( + this, &LayoutEditor::event_signal_handler); + } + void deactivate() + { + get_as_node("%layout_editor")->hide(); + EditorEvent::get_singleton()->event.remove_listener( + this, &LayoutEditor::event_signal_handler); + } + void event_signal_handler(const String &event, const Array &args) + { + int i; + print_line("event: " + event); + if (event == "mouse_press") { + Vector2 position = args[0]; + Camera *camera = editor->get_viewport()->get_camera(); + Vector3 start = camera->project_ray_origin(position); + Vector3 normal = camera->project_ray_normal(position); + Vector3 end = start + normal * camera->get_zfar(); + PhysicsDirectSpaceState *space_state = + SceneTree::get_singleton() + ->get_root() + ->get_world() + ->get_direct_space_state(); + PhysicsDirectSpaceState::RayResult result; + Set excludes; + bool r = space_state->intersect_ray(start, end, result, + excludes, 1 << 15, + false, true, false); + if (r && result.rid != RID()) { + Vector3 proj = result.position; + Transform xf( + Basis(), + Vector3(Math::stepify(proj.x, 4.0f), 0, + Math::stepify(proj.z, 4.0f))); + get_as_node("%refcube") + ->set_global_transform(xf); + float dst = Math_INF; + int selected = -1; + for (i = 0; i < grid_nodes.size(); i++) { + assert(grid_nodes[i]->is_inside_tree()); + Vector3 o = + grid_nodes[i] + ->get_global_transform() + .origin; + float mdst = o.distance_squared_to( + xf.origin); + if (dst > mdst) { + selected = i; + dst = mdst; + } + } + if (selected >= 0) { + current_cell = selected; + get_as_node("%refcube") + ->set_global_transform( + grid_nodes[current_cell] + ->get_global_transform()); + print_line( + "cell: " + itos(current_cell) + + "pos: " + + (grid_nodes[current_cell] + ->get_global_transform() + .origin + .operator String())); + } + } + } + } + static void _bind_methods() + { + } +}; + class ElementEditor : public Object { GDCLASS(ElementEditor, Object) BuildingLayoutEditor *editor; @@ -961,9 +1137,8 @@ void BuildingLayoutEditor::visualize_element_type(const String &key, } base = Object::cast_to(get_node(NodePath("%vis_base"))); assert(base); - for (i = 0; i < base->get_child_count(); i++) { + for (i = 0; i < base->get_child_count(); i++) base->get_child(i)->queue_delete(); - } print_line("visualizing: " + key + " with " + test_element); if (!ElementData::get_singleton()->has_element(test_element)) print_line("element " + test_element + " does not exist"); @@ -1003,8 +1178,35 @@ void BuildingLayoutEditor::visualize_element_type(const String &key, } } +void BuildingLayoutEditor::visualize_element_at(const String &element, + Spatial *node) +{ + int i; + if (!ElementData::get_singleton()->has_element(element)) + return; + const String &element_type = + ElementData::get_singleton()->get_element_type(element); + for (i = 0; i < ELEMENT_SOCKETS; i++) { + Transform xform = + ElementData::get_singleton()->get_element_type_socket( + element_type, i); + String mesh_name = ""; + mesh_name = ElementData::get_singleton()->get_element_mesh_name( + element, i); + if (mesh_name.length() == 0) + continue; + assert(meshes.has(mesh_name)); + MeshInstance *mi = memnew(MeshInstance); + mi->set_mesh(meshes[mesh_name].mesh); + mi->set_transform(xform); + node->call_deferred("add_child", mi); + print_line("displaying: " + mesh_name); + } +} + static ElementTypeEditor *etype_editor; static ElementEditor *element_editor; +static LayoutEditor *layout_editor; void BuildingLayoutEditor::_notification(int which) { @@ -1015,14 +1217,17 @@ void BuildingLayoutEditor::_notification(int which) return; etype_editor = memnew(ElementTypeEditor(this)); element_editor = memnew(ElementEditor(this)); + layout_editor = memnew(LayoutEditor(this)); editors.push_back(etype_editor); editors.push_back(element_editor); + editors.push_back(layout_editor); connect_signals(); if (!meshes_ready) { prepare_meshes(); update_mesh_buttons(); } select_mode(0); + set_process_unhandled_input(true); } break; case NOTIFICATION_EXIT_TREE: for (i = 0; i < (int)editors.size(); i++) @@ -1030,6 +1235,7 @@ void BuildingLayoutEditor::_notification(int which) Node *vis = get_node(NodePath("%vis_base")); if (vis) vis->queue_delete(); + set_process_unhandled_input(false); } } @@ -1109,6 +1315,8 @@ void BuildingLayoutEditor::_bind_methods() &BuildingLayoutEditor::select_mode); ClassDB::bind_method(D_METHOD("menu_control"), &BuildingLayoutEditor::menu_control); + ClassDB::bind_method(D_METHOD("_unhandled_input", "event"), + &BuildingLayoutEditor::_unhandled_input); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "source", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"), "set_source", "get_source"); @@ -1148,21 +1356,7 @@ void BuildingLayoutEditor::select_mode(int mode) case 0: etype_editor->deactivate(); element_editor->deactivate(); - get_as_node("%bg_floor")->show(); - { - // delete children of bg_floor - int i; - for (i = 0; - i < get_as_node("%bg_floor") - ->get_child_count(); - i++) { - get_as_node("%bg_floor") - ->get_child(i) - ->queue_delete(); - } - } - get_viewport()->get_camera()->set_global_translation( - Vector3(-25, 25, 25)); + layout_editor->activate(); if (ElementData::get_singleton()->get_element_size() == 0) print_error("No elements"); @@ -1174,6 +1368,7 @@ void BuildingLayoutEditor::select_mode(int mode) get_viewport()->get_camera()->set_global_translation( Vector3(-10, 10, 10)); element_editor->deactivate(); + layout_editor->deactivate(); etype_editor->activate(); element_keys.clear(); break; @@ -1184,6 +1379,7 @@ void BuildingLayoutEditor::select_mode(int mode) get_viewport()->get_camera()->set_global_translation( Vector3(-10, 10, 10)); etype_editor->deactivate(); + layout_editor->deactivate(); element_editor->activate(); } } @@ -1216,3 +1412,22 @@ void BuildingLayoutEditor::save_data() print_line("save_data"); ElementData::get_singleton()->save_data(); } + +void BuildingLayoutEditor::_unhandled_input(const Ref &event) +{ + Ref mm = event; + Ref mb = event; + Ref kb = event; + bool input_handled = false; + if (event->is_action_pressed("mouse1")) { + // if (Input::get_singleton()->is_action_just_pressed("mouse1")) { + Array args; + Vector2 position = get_viewport()->get_mouse_position(); + args.push_back(position); + EditorEvent::get_singleton()->event.emit("mouse_press", args); + // } + input_handled = true; + } + if (input_handled) + get_viewport()->set_input_as_handled(); +} diff --git a/src/modules/stream/buildings/building_layout_editor.h b/src/modules/stream/buildings/building_layout_editor.h index 01b5cc2..7b527e8 100644 --- a/src/modules/stream/buildings/building_layout_editor.h +++ b/src/modules/stream/buildings/building_layout_editor.h @@ -27,6 +27,7 @@ public: Ref get_mesh_preview(const String &key); void visualize_element_type(const String &key, const String &test_element); + void visualize_element_at(const String &element, Spatial *node); protected: void _notification(int which); @@ -37,4 +38,5 @@ protected: void select_mode(int mode); void menu_control(int id); void save_data(); + void _unhandled_input(const Ref &event); };