Can now select grid node with mouse click

This commit is contained in:
2024-10-06 18:17:45 +03:00
parent 0e5a2e7f9b
commit 64a66d1c50
4 changed files with 311 additions and 30 deletions

View File

@@ -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=[".."])

View File

@@ -14,6 +14,7 @@
#include <scene/gui/button.h>
#include <scene/gui/menu_button.h>
#include <editor/editor_node.h>
#include "editor_event.h"
#include "building_layout_editor.h"
template <class T> T *get_as_node(const String &path)
@@ -85,6 +86,30 @@ protected:
HashMap<String, struct grid_element> 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<String> *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<Spatial *> grid_nodes;
int current_cell;
public:
LayoutEditor(BuildingLayoutEditor *editor)
: Object()
, editor(editor)
, grid_elements("%grid_elements")
, current_cell(-1)
{
get_as_node<OptionButton>(grid_elements)
->connect("item_selected", this, "select_grid_element");
}
virtual ~LayoutEditor()
{
}
void activate()
{
get_as_node<Control>("%layout_editor")->show();
get_as_node<Spatial>("%bg_floor")->show();
{
// delete children of bg_floor
int i;
for (i = 0; i < get_as_node<Spatial>("%bg_floor")
->get_child_count();
i++) {
get_as_node<Spatial>("%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<Spatial>("%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<Spatial>("%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<String> element_keys;
List<String>::Element *e;
ElementData::get_singleton()->get_element_type_key_list(
&element_keys);
e = element_keys.front();
get_as_node<OptionButton>(grid_elements)->clear();
while (e) {
get_as_node<OptionButton>(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<Control>("%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<RID> 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<Spatial>("%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<Spatial>("%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<Spatial>(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<Spatial>("%bg_floor")->show();
{
// delete children of bg_floor
int i;
for (i = 0;
i < get_as_node<Spatial>("%bg_floor")
->get_child_count();
i++) {
get_as_node<Spatial>("%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<InputEvent> &event)
{
Ref<InputEventMouseMotion> mm = event;
Ref<InputEventMouseButton> mb = event;
Ref<InputEventKey> 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();
}

View File

@@ -27,6 +27,7 @@ public:
Ref<Texture> 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<InputEvent> &event);
};