mirror of
https://github.com/Relintai/pandemonium_engine_minimal.git
synced 2025-02-09 07:20:04 +01:00
Removed 3d navigation nodes and geometry parsers.
This commit is contained in:
parent
8adb27eb0f
commit
f944578178
@ -37,7 +37,6 @@
|
||||
#include "nav_obstacle.h"
|
||||
#include "nav_region.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
|
||||
#include <Obstacle2d.h>
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "nav_base.h"
|
||||
|
||||
#include "nav_utils.h"
|
||||
#include "scene/3d/navigation.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
|
||||
class NavRegion : public NavBase {
|
||||
|
@ -1,52 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* meshinstance3d_navigation_geometry_parser_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "meshinstance3d_navigation_geometry_parser_3d.h"
|
||||
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
|
||||
bool MeshInstance3DNavigationGeometryParser3D::parses_node(Node *p_node) {
|
||||
return (Object::cast_to<MeshInstance>(p_node) != nullptr);
|
||||
}
|
||||
|
||||
void MeshInstance3DNavigationGeometryParser3D::parse_geometry(Node *p_node, Ref<NavigationMesh> p_navigationmesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry) {
|
||||
NavigationMesh::ParsedGeometryType parsed_geometry_type = p_navigationmesh->get_parsed_geometry_type();
|
||||
|
||||
if (Object::cast_to<MeshInstance>(p_node) && parsed_geometry_type != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
|
||||
MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(p_node);
|
||||
Ref<Mesh> mesh = mesh_instance->get_mesh();
|
||||
if (mesh.is_valid()) {
|
||||
p_source_geometry->add_mesh(mesh, mesh_instance->get_global_transform());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* meshinstance3d_navigation_geometry_parser_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MESHINSTANCE3D_NAVIGATION_GEOMETRY_PARSER_3D_H
|
||||
#define MESHINSTANCE3D_NAVIGATION_GEOMETRY_PARSER_3D_H
|
||||
|
||||
#include "scene/3d/navigation_geometry_parser_3d.h"
|
||||
|
||||
class MeshInstance3DNavigationGeometryParser3D : public NavigationGeometryParser3D {
|
||||
public:
|
||||
virtual bool parses_node(Node *p_node);
|
||||
|
||||
virtual void parse_geometry(Node *p_node, Ref<NavigationMesh> p_navigationmesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry);
|
||||
};
|
||||
|
||||
#endif // MESHINSTANCE3D_NAVIGATION_GEOMETRY_PARSER_3D_H
|
@ -1,62 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* multimeshinstance3d_navigation_geometry_parser_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "multimeshinstance3d_navigation_geometry_parser_3d.h"
|
||||
|
||||
#include "scene/3d/multimesh_instance.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/mesh/multimesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
|
||||
bool MultiMeshInstance3DNavigationGeometryParser3D::parses_node(Node *p_node) {
|
||||
return (Object::cast_to<MultiMeshInstance>(p_node) != nullptr);
|
||||
}
|
||||
|
||||
void MultiMeshInstance3DNavigationGeometryParser3D::parse_geometry(Node *p_node, Ref<NavigationMesh> p_navigationmesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry) {
|
||||
NavigationMesh::ParsedGeometryType parsed_geometry_type = p_navigationmesh->get_parsed_geometry_type();
|
||||
|
||||
if (Object::cast_to<MultiMeshInstance>(p_node) && parsed_geometry_type != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
|
||||
MultiMeshInstance *multimesh_instance = Object::cast_to<MultiMeshInstance>(p_node);
|
||||
Ref<MultiMesh> multimesh = multimesh_instance->get_multimesh();
|
||||
if (multimesh.is_valid()) {
|
||||
Ref<Mesh> mesh = multimesh->get_mesh();
|
||||
if (mesh.is_valid()) {
|
||||
int n = multimesh->get_visible_instance_count();
|
||||
if (n == -1) {
|
||||
n = multimesh->get_instance_count();
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
p_source_geometry->add_mesh(mesh, multimesh_instance->get_global_transform() * multimesh->get_instance_transform(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* multimeshinstance3d_navigation_geometry_parser_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MULTIMESHINSTANCE3D_NAVIGATION_GEOMETRY_PARSER_3D_H
|
||||
#define MULTIMESHINSTANCE3D_NAVIGATION_GEOMETRY_PARSER_3D_H
|
||||
|
||||
#include "scene/3d/navigation_geometry_parser_3d.h"
|
||||
|
||||
class MultiMeshInstance3DNavigationGeometryParser3D : public NavigationGeometryParser3D {
|
||||
public:
|
||||
virtual bool parses_node(Node *p_node);
|
||||
|
||||
virtual void parse_geometry(Node *p_node, Ref<NavigationMesh> p_navigationmesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry);
|
||||
};
|
||||
|
||||
#endif // MULTIMESHINSTANCE3D_NAVIGATION_GEOMETRY_PARSER_3D_H
|
@ -39,10 +39,6 @@
|
||||
#include "geometry_parser_2d/polygon2d_navigation_geometry_parser_2d.h"
|
||||
#include "geometry_parser_2d/staticbody2d_navigation_geometry_parser_2d.h"
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
#include "geometry_parser_3d/meshinstance3d_navigation_geometry_parser_3d.h"
|
||||
#include "geometry_parser_3d/multimeshinstance3d_navigation_geometry_parser_3d.h"
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
void register_navigation_geometry_parsers_types(ModuleRegistrationLevel p_level) {
|
||||
if (p_level == MODULE_REGISTRATION_LEVEL_SCENE) {
|
||||
@ -50,10 +46,6 @@ void register_navigation_geometry_parsers_types(ModuleRegistrationLevel p_level)
|
||||
NavigationMeshGenerator::get_singleton()->register_geometry_parser_2d(memnew(MultiMeshInstance2DNavigationGeometryParser2D));
|
||||
NavigationMeshGenerator::get_singleton()->register_geometry_parser_2d(memnew(Polygon2DNavigationGeometryParser2D));
|
||||
NavigationMeshGenerator::get_singleton()->register_geometry_parser_2d(memnew(StaticBody2DNavigationGeometryParser2D));
|
||||
#ifndef _3D_DISABLED
|
||||
NavigationMeshGenerator::get_singleton()->register_geometry_parser_3d(memnew(MeshInstance3DNavigationGeometryParser3D));
|
||||
NavigationMeshGenerator::get_singleton()->register_geometry_parser_3d(memnew(MultiMeshInstance3DNavigationGeometryParser3D));
|
||||
#endif // _3D_DISABLED
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,202 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_mesh_editor_plugin.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "navigation_mesh_editor_plugin.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "scene/3d/navigation_mesh_instance.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
#include "servers/navigation/navigation_mesh_generator.h"
|
||||
#include "scene/gui/separator.h"
|
||||
|
||||
void NavigationMeshEditor::_node_removed(Node *p_node) {
|
||||
if (p_node == node) {
|
||||
node = nullptr;
|
||||
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshEditor::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
button_bake->set_icon(get_theme_icon("Bake", "EditorIcons"));
|
||||
button_reset->set_icon(get_theme_icon("Reload", "EditorIcons"));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshEditor::_bake_pressed() {
|
||||
button_bake->set_pressed(false);
|
||||
|
||||
ERR_FAIL_COND(!node);
|
||||
Ref<NavigationMesh> navigation_mesh = node->get_navigation_mesh();
|
||||
if (!navigation_mesh.is_valid()) {
|
||||
err_dialog->set_text(TTR("A NavigationMesh resource must be set or created for this node to work."));
|
||||
err_dialog->popup_centered();
|
||||
return;
|
||||
}
|
||||
|
||||
String path = navigation_mesh->get_path();
|
||||
if (!path.is_resource_file()) {
|
||||
int srpos = path.find("::");
|
||||
if (srpos != -1) {
|
||||
String base = path.substr(0, srpos);
|
||||
if (ResourceLoader::get_resource_type(base) == "PackedScene") {
|
||||
if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_filename() != base) {
|
||||
err_dialog->set_text(TTR("Cannot generate navigation mesh because it does not belong to the edited scene. Make it unique first."));
|
||||
err_dialog->popup_centered();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (FileAccess::exists(base + ".import")) {
|
||||
err_dialog->set_text(TTR("Cannot generate navigation mesh because it belongs to a resource which was imported."));
|
||||
err_dialog->popup_centered();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (FileAccess::exists(path + ".import")) {
|
||||
err_dialog->set_text(TTR("Cannot generate navigation mesh because the resource was imported from another type."));
|
||||
err_dialog->popup_centered();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
node->bake_navigation_mesh(false);
|
||||
|
||||
node->update_gizmos();
|
||||
}
|
||||
|
||||
void NavigationMeshEditor::_clear_pressed() {
|
||||
if (node) {
|
||||
if (node->get_navigation_mesh().is_valid()) {
|
||||
node->get_navigation_mesh()->clear();
|
||||
}
|
||||
}
|
||||
|
||||
button_bake->set_pressed(false);
|
||||
//bake_info->set_text("");
|
||||
|
||||
if (node) {
|
||||
node->update_gizmos();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshEditor::edit(NavigationMeshInstance *p_nav_region) {
|
||||
if (p_nav_region == nullptr || node == p_nav_region) {
|
||||
return;
|
||||
}
|
||||
|
||||
node = p_nav_region;
|
||||
}
|
||||
|
||||
void NavigationMeshEditor::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_bake_pressed"), &NavigationMeshEditor::_bake_pressed);
|
||||
ClassDB::bind_method(D_METHOD("_clear_pressed"), &NavigationMeshEditor::_clear_pressed);
|
||||
}
|
||||
|
||||
NavigationMeshEditor::NavigationMeshEditor() {
|
||||
bake_hbox = memnew(HBoxContainer);
|
||||
|
||||
bake_hbox->add_child(memnew(VSeparator));
|
||||
|
||||
button_bake = memnew(Button);
|
||||
button_bake->set_flat(true);
|
||||
bake_hbox->add_child(button_bake);
|
||||
button_bake->set_toggle_mode(true);
|
||||
//button_bake->set_text(TTR("Bake NavigationMesh"));
|
||||
button_bake->set_tooltip(TTR("Bake NavigationMesh") + "\n" + TTR("Bakes the NavigationMesh by first parsing the scene for source geometry and then creating the navigation mesh vertices and indices."));
|
||||
button_bake->connect("pressed", this, "_bake_pressed");
|
||||
|
||||
button_reset = memnew(Button);
|
||||
button_reset->set_flat(true);
|
||||
bake_hbox->add_child(button_reset);
|
||||
//button_reset->set_text(TTR("Clear NavigationMesh"));
|
||||
button_reset->set_tooltip(TTR("Clear NavigationMesh") + "\n" + TTR("Clears the internal NavigationMesh vertices and indices."));
|
||||
button_reset->connect("pressed", this, "_clear_pressed");
|
||||
|
||||
//bake_info = memnew(Label);
|
||||
//bake_hbox->add_child(bake_info);
|
||||
|
||||
err_dialog = memnew(AcceptDialog);
|
||||
add_child(err_dialog);
|
||||
node = nullptr;
|
||||
}
|
||||
|
||||
NavigationMeshEditor::~NavigationMeshEditor() {
|
||||
}
|
||||
|
||||
void NavigationMeshEditorPlugin::edit(Object *p_object) {
|
||||
navigation_mesh_editor->edit(Object::cast_to<NavigationMeshInstance>(p_object));
|
||||
}
|
||||
|
||||
bool NavigationMeshEditorPlugin::handles(Object *p_object) const {
|
||||
return p_object->is_class("NavigationMeshInstance");
|
||||
}
|
||||
|
||||
void NavigationMeshEditorPlugin::make_visible(bool p_visible) {
|
||||
if (p_visible) {
|
||||
navigation_mesh_editor->show();
|
||||
navigation_mesh_editor->bake_hbox->show();
|
||||
} else {
|
||||
navigation_mesh_editor->hide();
|
||||
navigation_mesh_editor->bake_hbox->hide();
|
||||
navigation_mesh_editor->edit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
NavigationMeshEditorPlugin::NavigationMeshEditorPlugin(EditorNode *p_node) {
|
||||
navigation_mesh_editor = memnew(NavigationMeshEditor);
|
||||
|
||||
EditorNode::get_singleton()->get_viewport()->add_child(navigation_mesh_editor);
|
||||
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, navigation_mesh_editor->bake_hbox);
|
||||
navigation_mesh_editor->hide();
|
||||
navigation_mesh_editor->bake_hbox->hide();
|
||||
}
|
||||
|
||||
NavigationMeshEditorPlugin::~NavigationMeshEditorPlugin() {
|
||||
}
|
||||
|
||||
void NavigationMeshEditorPlugin::_bind_methods() {
|
||||
}
|
||||
|
||||
#endif // TOOLS_ENABLED
|
@ -1,93 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_mesh_editor_plugin.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NAVIGATION_MESH_EDITOR_PLUGIN_H
|
||||
#define NAVIGATION_MESH_EDITOR_PLUGIN_H
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "editor/editor_plugin.h"
|
||||
|
||||
class AcceptDialog;
|
||||
class Button;
|
||||
class HBoxContainer;
|
||||
class Label;
|
||||
class NavigationMeshInstance;
|
||||
|
||||
class NavigationMeshEditor : public Control {
|
||||
friend class NavigationMeshEditorPlugin;
|
||||
|
||||
GDCLASS(NavigationMeshEditor, Control);
|
||||
|
||||
AcceptDialog *err_dialog = nullptr;
|
||||
|
||||
HBoxContainer *bake_hbox = nullptr;
|
||||
Button *button_bake = nullptr;
|
||||
Button *button_reset = nullptr;
|
||||
//Label *bake_info = nullptr;
|
||||
|
||||
NavigationMeshInstance *node = nullptr;
|
||||
|
||||
void _bake_pressed();
|
||||
void _clear_pressed();
|
||||
|
||||
protected:
|
||||
void _node_removed(Node *p_node);
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
void edit(NavigationMeshInstance *p_nav_region);
|
||||
NavigationMeshEditor();
|
||||
~NavigationMeshEditor();
|
||||
};
|
||||
|
||||
class NavigationMeshEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(NavigationMeshEditorPlugin, EditorPlugin);
|
||||
|
||||
NavigationMeshEditor *navigation_mesh_editor = nullptr;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "NavigationMesh"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
NavigationMeshEditorPlugin(EditorNode *p_node);
|
||||
~NavigationMeshEditorPlugin();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
};
|
||||
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
#endif // NAVIGATION_MESH_EDITOR_PLUGIN_H
|
@ -1,238 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_polygon_editor_plugin.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "navigation_polygon_editor_plugin.h"
|
||||
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/object/undo_redo.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "scene/2d/mesh_instance_2d.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "scene/resources/navigation_2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/navigation_2d/navigation_polygon.h"
|
||||
#include "servers/navigation/navigation_mesh_generator.h"
|
||||
#include "scene/gui/separator.h"
|
||||
|
||||
Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navigation_polygon() const {
|
||||
Ref<NavigationPolygon> navigation_polygon = node->get_navigation_polygon();
|
||||
if (!navigation_polygon.is_valid()) {
|
||||
navigation_polygon = Ref<NavigationPolygon>(memnew(NavigationPolygon));
|
||||
node->set_navigation_polygon(navigation_polygon);
|
||||
}
|
||||
return navigation_polygon;
|
||||
}
|
||||
|
||||
Node2D *NavigationPolygonEditor::_get_node() const {
|
||||
return node;
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_set_node(Node *p_polygon) {
|
||||
node = Object::cast_to<NavigationPolygonInstance>(p_polygon);
|
||||
}
|
||||
|
||||
int NavigationPolygonEditor::_get_polygon_count() const {
|
||||
Ref<NavigationPolygon> navigation_polygon = node->get_navigation_polygon();
|
||||
if (navigation_polygon.is_valid()) {
|
||||
return navigation_polygon->get_outline_count();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Variant NavigationPolygonEditor::_get_polygon(int p_idx) const {
|
||||
Ref<NavigationPolygon> navigation_polygon = node->get_navigation_polygon();
|
||||
if (navigation_polygon.is_valid()) {
|
||||
return navigation_polygon->get_outline(p_idx);
|
||||
} else {
|
||||
return Variant(Vector<Vector2>());
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
|
||||
Ref<NavigationPolygon> navigation_polygon = _ensure_navigation_polygon();
|
||||
navigation_polygon->set_outline(p_idx, p_polygon);
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) {
|
||||
Ref<NavigationPolygon> navigation_polygon = _ensure_navigation_polygon();
|
||||
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
undo_redo->create_action("Add Navigation Polygon");
|
||||
undo_redo->add_do_method(navigation_polygon.ptr(), "add_outline", p_polygon);
|
||||
undo_redo->add_undo_method(navigation_polygon.ptr(), "remove_outline", navigation_polygon->get_outline_count());
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_action_remove_polygon(int p_idx) {
|
||||
Ref<NavigationPolygon> navigation_polygon = _ensure_navigation_polygon();
|
||||
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
undo_redo->create_action("Remove Navigation Polygon");
|
||||
undo_redo->add_do_method(navigation_polygon.ptr(), "remove_outline", p_idx);
|
||||
undo_redo->add_undo_method(navigation_polygon.ptr(), "add_outline_at_index", navigation_polygon->get_outline(p_idx), p_idx);
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
|
||||
Ref<NavigationPolygon> navigation_polygon = _ensure_navigation_polygon();
|
||||
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
undo_redo->create_action("Set Navigation Polygon");
|
||||
undo_redo->add_do_method(navigation_polygon.ptr(), "set_outline", p_idx, p_polygon);
|
||||
undo_redo->add_undo_method(navigation_polygon.ptr(), "set_outline", p_idx, p_previous);
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
bool NavigationPolygonEditor::_has_resource() const {
|
||||
return node && node->get_navigation_polygon().is_valid();
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_create_resource() {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
undo_redo->create_action(TTR("Create Navigation Polygon"));
|
||||
undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon)));
|
||||
undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(Ref<NavigationPolygon>()));
|
||||
undo_redo->commit_action();
|
||||
|
||||
_menu_option(MODE_CREATE);
|
||||
}
|
||||
|
||||
NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor, bool p_wip_destructive) :
|
||||
AbstractPolygon2DEditor(p_editor, p_wip_destructive) {
|
||||
|
||||
bake_hbox = memnew(HBoxContainer);
|
||||
add_child(bake_hbox);
|
||||
|
||||
bake_hbox->add_child(memnew(VSeparator));
|
||||
|
||||
button_bake = memnew(Button);
|
||||
button_bake->set_flat(true);
|
||||
bake_hbox->add_child(button_bake);
|
||||
button_bake->set_toggle_mode(true);
|
||||
//button_bake->set_text(TTR("Bake NavigationPolygon"));
|
||||
button_bake->set_tooltip(TTR("Bake NavigationPolygon") + "\n" + TTR("Bakes the NavigationPolygon by first parsing the scene for source geometry and then creating the navigation polygon vertices and polygons."));
|
||||
button_bake->connect("pressed", this, "_bake_pressed");
|
||||
|
||||
button_reset = memnew(Button);
|
||||
button_reset->set_flat(true);
|
||||
bake_hbox->add_child(button_reset);
|
||||
//button_reset->set_text(TTR("Clear NavigationPolygon"));
|
||||
button_reset->set_tooltip(TTR("Clear NavigationPolygon") + "\n" + TTR("Clears the internal NavigationPolygon outlines, vertices and polygons."));
|
||||
button_reset->connect("pressed", this, "_clear_pressed");
|
||||
|
||||
//bake_info = memnew(Label);
|
||||
//bake_hbox->add_child(bake_info);
|
||||
|
||||
err_dialog = memnew(AcceptDialog);
|
||||
add_child(err_dialog);
|
||||
node = nullptr;
|
||||
}
|
||||
|
||||
NavigationPolygonEditor::~NavigationPolygonEditor() {
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
button_bake->set_icon(get_theme_icon("Bake", "EditorIcons"));
|
||||
button_reset->set_icon(get_theme_icon("Reload", "EditorIcons"));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_bake_pressed"), &NavigationPolygonEditor::_bake_pressed);
|
||||
ClassDB::bind_method(D_METHOD("_clear_pressed"), &NavigationPolygonEditor::_clear_pressed);
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_bake_pressed() {
|
||||
button_bake->set_pressed(false);
|
||||
|
||||
ERR_FAIL_COND(!node);
|
||||
Ref<NavigationPolygon> navigation_polygon = node->get_navigation_polygon();
|
||||
if (!navigation_polygon.is_valid()) {
|
||||
err_dialog->set_text(TTR("A NavigationPolygon resource must be set or created for this node to work."));
|
||||
err_dialog->popup_centered();
|
||||
return;
|
||||
}
|
||||
|
||||
navigation_polygon->clear_polygons();
|
||||
navigation_polygon->set_vertices(PoolVector<Vector2>());
|
||||
|
||||
Ref<NavigationMeshSourceGeometryData2D> source_geometry_data = NavigationMeshGenerator::get_singleton()->parse_2d_source_geometry_data(navigation_polygon, node);
|
||||
NavigationMeshGenerator::get_singleton()->bake_2d_from_source_geometry_data(navigation_polygon, source_geometry_data);
|
||||
|
||||
node->update();
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_clear_pressed() {
|
||||
ERR_FAIL_COND(!node);
|
||||
if (!node->get_navigation_polygon().is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
node->get_navigation_polygon()->clear();
|
||||
|
||||
button_bake->set_pressed(false);
|
||||
//bake_info->set_text("");
|
||||
|
||||
if (node) {
|
||||
node->update();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationPolygonEditor::_update_polygon_editing_state() {
|
||||
if (!_get_node()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node != nullptr && node->get_navigation_polygon().is_valid()) {
|
||||
bake_hbox->show();
|
||||
} else {
|
||||
bake_hbox->hide();
|
||||
}
|
||||
}
|
||||
|
||||
NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) :
|
||||
AbstractPolygon2DEditorPlugin(p_node, memnew(NavigationPolygonEditor(p_node)), "NavigationPolygonInstance") {
|
||||
}
|
||||
|
||||
NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin() {
|
||||
}
|
||||
|
||||
void NavigationPolygonEditorPlugin::_bind_methods() {
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_polygon_editor_plugin.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NAVIGATION_POLYGON_EDITOR_PLUGIN_H
|
||||
#define NAVIGATION_POLYGON_EDITOR_PLUGIN_H
|
||||
|
||||
#include "editor/plugins/abstract_polygon_2d_editor.h"
|
||||
#include "scene/2d/navigation_polygon_instance.h"
|
||||
|
||||
#include "editor/editor_plugin.h"
|
||||
|
||||
class AcceptDialog;
|
||||
class OptionButton;
|
||||
class HBoxContainer;
|
||||
|
||||
class NavigationPolygonEditor : public AbstractPolygon2DEditor {
|
||||
friend class NavigationPolygonEditorPlugin;
|
||||
|
||||
GDCLASS(NavigationPolygonEditor, AbstractPolygon2DEditor);
|
||||
|
||||
NavigationPolygonInstance *node = nullptr;
|
||||
|
||||
Ref<NavigationPolygon> _ensure_navigation_polygon() const;
|
||||
|
||||
AcceptDialog *err_dialog = nullptr;
|
||||
|
||||
HBoxContainer *bake_hbox = nullptr;
|
||||
Button *button_bake = nullptr;
|
||||
Button *button_reset = nullptr;
|
||||
//Label *bake_info = nullptr;
|
||||
|
||||
void _bake_pressed();
|
||||
void _clear_pressed();
|
||||
|
||||
void _update_polygon_editing_state();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
virtual Node2D *_get_node() const;
|
||||
virtual void _set_node(Node *p_polygon);
|
||||
|
||||
virtual int _get_polygon_count() const;
|
||||
virtual Variant _get_polygon(int p_idx) const;
|
||||
virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
|
||||
|
||||
virtual void _action_add_polygon(const Variant &p_polygon);
|
||||
virtual void _action_remove_polygon(int p_idx);
|
||||
virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon);
|
||||
|
||||
virtual bool _has_resource() const;
|
||||
virtual void _create_resource();
|
||||
|
||||
public:
|
||||
NavigationPolygonEditor(EditorNode *p_editor, bool p_wip_destructive = true);
|
||||
~NavigationPolygonEditor();
|
||||
};
|
||||
|
||||
class NavigationPolygonEditorPlugin : public AbstractPolygon2DEditorPlugin {
|
||||
GDCLASS(NavigationPolygonEditorPlugin, AbstractPolygon2DEditorPlugin);
|
||||
|
||||
public:
|
||||
NavigationPolygonEditorPlugin(EditorNode *p_node);
|
||||
~NavigationPolygonEditorPlugin();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_POLYGON_EDITOR_PLUGIN_H
|
@ -35,10 +35,8 @@
|
||||
#include "core/core_string_names.h"
|
||||
|
||||
#include "scene/2d/navigation_geometry_parser_2d.h"
|
||||
#include "scene/3d/navigation_geometry_parser_3d.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation_2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
@ -72,37 +70,10 @@ void PandemoniumNavigationMeshGenerator::NavigationGeneratorTask2D::_execute() {
|
||||
void PandemoniumNavigationMeshGenerator::NavigationGeneratorTask2D::_bind_methods() {
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
void PandemoniumNavigationMeshGenerator::NavigationGeneratorTask3D::call_callback() {
|
||||
if (callback.is_valid() && callback->is_valid()) {
|
||||
Array arr;
|
||||
arr.push_back(navigation_mesh);
|
||||
callback->call_funcv(arr);
|
||||
}
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::NavigationGeneratorTask3D::_execute() {
|
||||
if (navigation_mesh.is_null() || source_geometry_data.is_null() || !source_geometry_data->has_data()) {
|
||||
set_complete(true);
|
||||
return;
|
||||
}
|
||||
|
||||
_static_bake_3d_from_source_geometry_data(navigation_mesh, source_geometry_data);
|
||||
|
||||
set_complete(true);
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::NavigationGeneratorTask3D::_bind_methods() {
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::process() {
|
||||
_generator_mutex.lock();
|
||||
|
||||
_process_2d_tasks();
|
||||
#ifndef _3D_DISABLED
|
||||
_process_3d_tasks();
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
_generator_mutex.unlock();
|
||||
}
|
||||
@ -110,10 +81,6 @@ void PandemoniumNavigationMeshGenerator::process() {
|
||||
void PandemoniumNavigationMeshGenerator::cleanup() {
|
||||
_baking_navigation_polygons.clear();
|
||||
_geometry_2d_parsers.clear();
|
||||
#ifndef _3D_DISABLED
|
||||
_baking_navigation_meshes.clear();
|
||||
_geometry_3d_parsers.clear();
|
||||
#endif // _3D_DISABLED
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_process_2d_tasks() {
|
||||
@ -211,7 +178,7 @@ void PandemoniumNavigationMeshGenerator::unregister_geometry_parser_2d(Ref<Navig
|
||||
}
|
||||
|
||||
Ref<NavigationMeshSourceGeometryData2D> PandemoniumNavigationMeshGenerator::parse_2d_source_geometry_data(Ref<NavigationPolygon> p_navigation_polygon, Node *p_root_node, Ref<FuncRef> p_callback) {
|
||||
ERR_FAIL_COND_V_MSG(!p_navigation_polygon.is_valid(), Ref<NavigationMeshSourceGeometryData3D>(), "Invalid navigation mesh.");
|
||||
ERR_FAIL_COND_V_MSG(!p_navigation_polygon.is_valid(), Ref<NavigationMeshSourceGeometryData2D>(), "Invalid navigation mesh.");
|
||||
ERR_FAIL_COND_V_MSG(p_root_node == nullptr, Ref<NavigationMeshSourceGeometryData2D>(), "No parsing root node specified.");
|
||||
|
||||
ObjectID root_node_object_id = p_root_node->get_instance_id();
|
||||
@ -469,414 +436,6 @@ bool PandemoniumNavigationMeshGenerator::is_navigation_polygon_baking(Ref<Naviga
|
||||
return _baking_navigation_polygons.find(p_navigation_polygon) >= 0;
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
void PandemoniumNavigationMeshGenerator::_process_3d_tasks() {
|
||||
if (_3d_parse_jobs.size() == 0 && _3d_running_jobs.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_process_3d_parse_tasks();
|
||||
_process_3d_bake_cleanup_tasks();
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_process_3d_parse_tasks() {
|
||||
// Note that this cannot be parallelized in a simple way, because we need mainloop to not delete nodes under it while processing.
|
||||
// If parallelization is implemented, it needs to wait for the tasks to complete. (Like in the original pr.)
|
||||
// Also the RenderingServer has locks that need the main thread to be active, so it can deadlock.
|
||||
|
||||
// TODO implement ThreadPool like max processing per frame support
|
||||
|
||||
if (_3d_parse_jobs.size() > 0) {
|
||||
while (_3d_parse_jobs.size() > 0) {
|
||||
Ref<NavigationGeneratorTask3D> navigation_generator_task = _3d_parse_jobs[0];
|
||||
|
||||
_3d_parse_jobs.remove(0);
|
||||
|
||||
if (navigation_generator_task.is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ref<NavigationMesh> navigation_polygon = navigation_generator_task->navigation_mesh;
|
||||
Ref<NavigationMeshSourceGeometryData3D> source_geometry_data = navigation_generator_task->source_geometry_data;
|
||||
ObjectID parse_root_object_id = navigation_generator_task->parse_root_object_id;
|
||||
|
||||
if (navigation_polygon.is_null() || parse_root_object_id == ObjectID()) {
|
||||
navigation_generator_task->status = NavigationGeneratorTask3D::TaskStatus::PARSING_FAILED;
|
||||
navigation_generator_task->call_callback();
|
||||
continue;
|
||||
}
|
||||
Object *parse_root_obj = ObjectDB::get_instance(parse_root_object_id);
|
||||
if (parse_root_obj == nullptr) {
|
||||
navigation_generator_task->status = NavigationGeneratorTask3D::TaskStatus::PARSING_FAILED;
|
||||
navigation_generator_task->call_callback();
|
||||
return;
|
||||
}
|
||||
Node *parse_root_node = Object::cast_to<Node>(parse_root_obj);
|
||||
if (parse_root_node == nullptr) {
|
||||
navigation_generator_task->status = NavigationGeneratorTask3D::TaskStatus::PARSING_FAILED;
|
||||
navigation_generator_task->call_callback();
|
||||
return;
|
||||
}
|
||||
|
||||
_static_parse_3d_source_geometry_data(navigation_polygon, parse_root_node, source_geometry_data, navigation_generator_task->geometry_parsers);
|
||||
|
||||
navigation_generator_task->status = NavigationGeneratorTask3D::TaskStatus::PARSING_FINISHED;
|
||||
|
||||
// Submit resulting class To threadpool
|
||||
navigation_generator_task->set_complete(false);
|
||||
if (_use_thread_pool) {
|
||||
ThreadPool::get_singleton()->add_job(navigation_generator_task);
|
||||
} else {
|
||||
navigation_generator_task->execute();
|
||||
}
|
||||
_3d_running_jobs.push_back(navigation_generator_task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_process_3d_bake_cleanup_tasks() {
|
||||
for (uint32_t i = 0; i < _3d_running_jobs.size(); ++i) {
|
||||
Ref<NavigationGeneratorTask3D> &e = _3d_running_jobs[i];
|
||||
|
||||
if (e->get_complete()) {
|
||||
_3d_running_jobs.remove_unordered(i);
|
||||
--i;
|
||||
|
||||
int indx = _baking_navigation_polygons.find(e->navigation_mesh);
|
||||
_baking_navigation_polygons.remove_unordered(indx);
|
||||
|
||||
e->call_callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_static_bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data) {
|
||||
if (p_navigation_mesh.is_null() || p_source_geometry_data.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
PoolRealArray vertices = p_source_geometry_data->get_vertices();
|
||||
PoolIntArray indices = p_source_geometry_data->get_indices();
|
||||
|
||||
if (vertices.size() < 3 || indices.size() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
rcHeightfield *hf = nullptr;
|
||||
rcCompactHeightfield *chf = nullptr;
|
||||
rcContourSet *cset = nullptr;
|
||||
rcPolyMesh *poly_mesh = nullptr;
|
||||
rcPolyMeshDetail *detail_mesh = nullptr;
|
||||
rcContext ctx;
|
||||
|
||||
// added to keep track of steps, no functionality rightnow
|
||||
String bake_state = "";
|
||||
|
||||
bake_state = "Setting up Configuration..."; // step #1
|
||||
|
||||
PoolRealArray::Read vertices_read = vertices.read();
|
||||
PoolIntArray::Read indices_read = indices.read();
|
||||
const float *verts = vertices_read.ptr();
|
||||
const int nverts = vertices.size() / 3;
|
||||
const int *tris = indices_read.ptr();
|
||||
const int ntris = indices.size() / 3;
|
||||
|
||||
float bmin[3], bmax[3];
|
||||
rcCalcBounds(verts, nverts, bmin, bmax);
|
||||
|
||||
rcConfig cfg;
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
|
||||
cfg.cs = p_navigation_mesh->get_cell_size();
|
||||
cfg.ch = p_navigation_mesh->get_cell_height();
|
||||
cfg.walkableSlopeAngle = p_navigation_mesh->get_agent_max_slope();
|
||||
cfg.walkableHeight = (int)Math::ceil(p_navigation_mesh->get_agent_height() / cfg.ch);
|
||||
cfg.walkableClimb = (int)Math::floor(p_navigation_mesh->get_agent_max_climb() / cfg.ch);
|
||||
cfg.walkableRadius = (int)Math::ceil(p_navigation_mesh->get_agent_radius() / cfg.cs);
|
||||
cfg.maxEdgeLen = (int)(p_navigation_mesh->get_edge_max_length() / p_navigation_mesh->get_cell_size());
|
||||
cfg.maxSimplificationError = p_navigation_mesh->get_edge_max_error();
|
||||
cfg.minRegionArea = (int)(p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size());
|
||||
cfg.mergeRegionArea = (int)(p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size());
|
||||
cfg.maxVertsPerPoly = (int)p_navigation_mesh->get_vertices_per_polygon();
|
||||
cfg.detailSampleDist = MAX(p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance(), 0.1f);
|
||||
cfg.detailSampleMaxError = p_navigation_mesh->get_cell_height() * p_navigation_mesh->get_detail_sample_max_error();
|
||||
|
||||
cfg.bmin[0] = bmin[0];
|
||||
cfg.bmin[1] = bmin[1];
|
||||
cfg.bmin[2] = bmin[2];
|
||||
cfg.bmax[0] = bmax[0];
|
||||
cfg.bmax[1] = bmax[1];
|
||||
cfg.bmax[2] = bmax[2];
|
||||
|
||||
AABB baking_aabb = p_navigation_mesh->get_filter_baking_aabb();
|
||||
if (!baking_aabb.has_no_volume()) {
|
||||
Vector3 baking_aabb_offset = p_navigation_mesh->get_filter_baking_aabb_offset();
|
||||
cfg.bmin[0] = baking_aabb.position[0] + baking_aabb_offset.x;
|
||||
cfg.bmin[1] = baking_aabb.position[1] + baking_aabb_offset.y;
|
||||
cfg.bmin[2] = baking_aabb.position[2] + baking_aabb_offset.z;
|
||||
cfg.bmax[0] = cfg.bmin[0] + baking_aabb.size[0];
|
||||
cfg.bmax[1] = cfg.bmin[1] + baking_aabb.size[1];
|
||||
cfg.bmax[2] = cfg.bmin[2] + baking_aabb.size[2];
|
||||
}
|
||||
|
||||
bake_state = "Calculating grid size..."; // step #2
|
||||
|
||||
rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
|
||||
|
||||
bake_state = "Creating heightfield..."; // step #3
|
||||
|
||||
hf = rcAllocHeightfield();
|
||||
|
||||
ERR_FAIL_COND(!hf);
|
||||
ERR_FAIL_COND(!rcCreateHeightfield(&ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch));
|
||||
|
||||
bake_state = "Marking walkable triangles..."; // step #4
|
||||
|
||||
{
|
||||
Vector<unsigned char> tri_areas;
|
||||
tri_areas.resize(ntris);
|
||||
|
||||
ERR_FAIL_COND(tri_areas.size() == 0);
|
||||
|
||||
memset(tri_areas.ptrw(), 0, ntris * sizeof(unsigned char));
|
||||
rcMarkWalkableTriangles(&ctx, cfg.walkableSlopeAngle, verts, nverts, tris, ntris, tri_areas.ptrw());
|
||||
|
||||
ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb));
|
||||
}
|
||||
|
||||
if (p_navigation_mesh->get_filter_low_hanging_obstacles()) {
|
||||
rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf);
|
||||
}
|
||||
if (p_navigation_mesh->get_filter_ledge_spans()) {
|
||||
rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf);
|
||||
}
|
||||
if (p_navigation_mesh->get_filter_walkable_low_height_spans()) {
|
||||
rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf);
|
||||
}
|
||||
|
||||
bake_state = "Constructing compact heightfield..."; // step #5
|
||||
|
||||
chf = rcAllocCompactHeightfield();
|
||||
|
||||
ERR_FAIL_COND(!chf);
|
||||
ERR_FAIL_COND(!rcBuildCompactHeightfield(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf, *chf));
|
||||
|
||||
rcFreeHeightField(hf);
|
||||
hf = nullptr;
|
||||
|
||||
bake_state = "Eroding walkable area..."; // step #6
|
||||
|
||||
ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf));
|
||||
|
||||
bake_state = "Partitioning..."; // step #7
|
||||
|
||||
if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
|
||||
ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
|
||||
ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
|
||||
} else if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
|
||||
ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
|
||||
} else {
|
||||
ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea));
|
||||
}
|
||||
|
||||
bake_state = "Creating contours..."; // step #8
|
||||
|
||||
cset = rcAllocContourSet();
|
||||
|
||||
ERR_FAIL_COND(!cset);
|
||||
ERR_FAIL_COND(!rcBuildContours(&ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset));
|
||||
|
||||
bake_state = "Creating polymesh..."; // step #9
|
||||
|
||||
poly_mesh = rcAllocPolyMesh();
|
||||
ERR_FAIL_COND(!poly_mesh);
|
||||
ERR_FAIL_COND(!rcBuildPolyMesh(&ctx, *cset, cfg.maxVertsPerPoly, *poly_mesh));
|
||||
|
||||
detail_mesh = rcAllocPolyMeshDetail();
|
||||
ERR_FAIL_COND(!detail_mesh);
|
||||
ERR_FAIL_COND(!rcBuildPolyMeshDetail(&ctx, *poly_mesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *detail_mesh));
|
||||
|
||||
rcFreeCompactHeightfield(chf);
|
||||
chf = nullptr;
|
||||
rcFreeContourSet(cset);
|
||||
cset = nullptr;
|
||||
|
||||
bake_state = "Converting to native navigation mesh..."; // step #10
|
||||
|
||||
PoolVector<Vector3> new_navigation_mesh_vertices;
|
||||
Vector<Vector<int>> new_navigation_mesh_polygons;
|
||||
|
||||
for (int i = 0; i < detail_mesh->nverts; i++) {
|
||||
const float *v = &detail_mesh->verts[i * 3];
|
||||
new_navigation_mesh_vertices.push_back(Vector3(v[0], v[1], v[2]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < detail_mesh->nmeshes; i++) {
|
||||
const unsigned int *detail_mesh_m = &detail_mesh->meshes[i * 4];
|
||||
const unsigned int detail_mesh_bverts = detail_mesh_m[0];
|
||||
const unsigned int detail_mesh_m_btris = detail_mesh_m[2];
|
||||
const unsigned int detail_mesh_ntris = detail_mesh_m[3];
|
||||
const unsigned char *detail_mesh_tris = &detail_mesh->tris[detail_mesh_m_btris * 4];
|
||||
for (unsigned int j = 0; j < detail_mesh_ntris; j++) {
|
||||
Vector<int> new_navigation_mesh_polygon;
|
||||
new_navigation_mesh_polygon.resize(3);
|
||||
// Polygon order in recast is opposite than godot's
|
||||
new_navigation_mesh_polygon.write[0] = ((int)(detail_mesh_bverts + detail_mesh_tris[j * 4 + 0]));
|
||||
new_navigation_mesh_polygon.write[1] = ((int)(detail_mesh_bverts + detail_mesh_tris[j * 4 + 2]));
|
||||
new_navigation_mesh_polygon.write[2] = ((int)(detail_mesh_bverts + detail_mesh_tris[j * 4 + 1]));
|
||||
new_navigation_mesh_polygons.push_back(new_navigation_mesh_polygon);
|
||||
}
|
||||
}
|
||||
|
||||
p_navigation_mesh->set_vertices(new_navigation_mesh_vertices);
|
||||
p_navigation_mesh->set_polygons(new_navigation_mesh_polygons);
|
||||
|
||||
bake_state = "Cleanup..."; // step #11
|
||||
|
||||
rcFreePolyMesh(poly_mesh);
|
||||
poly_mesh = nullptr;
|
||||
rcFreePolyMeshDetail(detail_mesh);
|
||||
detail_mesh = nullptr;
|
||||
|
||||
rcFreeHeightField(hf);
|
||||
hf = nullptr;
|
||||
|
||||
rcFreeCompactHeightfield(chf);
|
||||
chf = nullptr;
|
||||
|
||||
rcFreeContourSet(cset);
|
||||
cset = nullptr;
|
||||
|
||||
rcFreePolyMesh(poly_mesh);
|
||||
poly_mesh = nullptr;
|
||||
|
||||
rcFreePolyMeshDetail(detail_mesh);
|
||||
detail_mesh = nullptr;
|
||||
|
||||
bake_state = "Baking finished."; // step #12
|
||||
#endif // _3D_DISABLED
|
||||
p_navigation_mesh->commit_changes();
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::parse_and_bake_3d(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback) {
|
||||
ERR_FAIL_COND_MSG(_baking_navigation_meshes.find(p_navigation_mesh) >= 0, "NavigationMesh was already added to baking queue. Wait for current bake task to finish.");
|
||||
ERR_FAIL_COND_MSG(p_root_node == nullptr, "avigationMesh requires a valid root node.");
|
||||
|
||||
_generator_mutex.lock();
|
||||
_baking_navigation_meshes.push_back(p_navigation_mesh);
|
||||
_generator_mutex.unlock();
|
||||
|
||||
Ref<NavigationGeneratorTask3D> navigation_generator_task;
|
||||
navigation_generator_task.instance();
|
||||
navigation_generator_task->navigation_mesh = p_navigation_mesh;
|
||||
|
||||
navigation_generator_task->navigation_mesh = p_navigation_mesh;
|
||||
navigation_generator_task->parse_root_object_id = p_root_node->get_instance_id();
|
||||
navigation_generator_task->source_geometry_data = Ref<NavigationMeshSourceGeometryData3D>(memnew(NavigationMeshSourceGeometryData3D));
|
||||
navigation_generator_task->callback = p_callback;
|
||||
navigation_generator_task->status = NavigationGeneratorTask3D::TaskStatus::PARSING_REQUIRED;
|
||||
navigation_generator_task->geometry_parsers = _geometry_3d_parsers;
|
||||
|
||||
_generator_mutex.lock();
|
||||
_3d_parse_jobs.push_back(navigation_generator_task);
|
||||
_generator_mutex.unlock();
|
||||
}
|
||||
|
||||
bool PandemoniumNavigationMeshGenerator::is_navigation_mesh_baking(Ref<NavigationMesh> p_navigation_mesh) const {
|
||||
ERR_FAIL_COND_V(!p_navigation_mesh.is_valid(), false);
|
||||
return _baking_navigation_meshes.find(p_navigation_mesh) >= 0;
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::register_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser) {
|
||||
_generator_mutex.lock();
|
||||
if (_geometry_3d_parsers.find(p_geometry_parser) < 0) {
|
||||
_geometry_3d_parsers.push_back(p_geometry_parser);
|
||||
}
|
||||
_generator_mutex.unlock();
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::unregister_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser) {
|
||||
_generator_mutex.lock();
|
||||
_geometry_3d_parsers.erase(p_geometry_parser);
|
||||
_generator_mutex.unlock();
|
||||
}
|
||||
|
||||
Ref<NavigationMeshSourceGeometryData3D> PandemoniumNavigationMeshGenerator::parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback) {
|
||||
ERR_FAIL_COND_V_MSG(!p_navigation_mesh.is_valid(), Ref<NavigationMeshSourceGeometryData3D>(), "Invalid navigation mesh.");
|
||||
ERR_FAIL_COND_V_MSG(p_root_node == nullptr, Ref<NavigationMeshSourceGeometryData3D>(), "No parsing root node specified.");
|
||||
|
||||
ObjectID root_node_object_id = p_root_node->get_instance_id();
|
||||
ERR_FAIL_COND_V_MSG(root_node_object_id == ObjectID(), Ref<NavigationMeshSourceGeometryData3D>(), "No root node object invalid.");
|
||||
|
||||
Ref<NavigationMeshSourceGeometryData3D> source_geometry_data = Ref<NavigationMeshSourceGeometryData3D>(memnew(NavigationMeshSourceGeometryData3D));
|
||||
|
||||
_static_parse_3d_source_geometry_data(p_navigation_mesh, p_root_node, source_geometry_data, _geometry_3d_parsers);
|
||||
|
||||
return source_geometry_data;
|
||||
};
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Ref<FuncRef> p_callback) {
|
||||
ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh.");
|
||||
ERR_FAIL_COND_MSG(!p_source_geometry_data.is_valid(), "Invalid NavigationMeshSourceGeometryData3D.");
|
||||
ERR_FAIL_COND_MSG(!p_source_geometry_data->has_data(), "NavigationMeshSourceGeometryData3D is empty. Parse source geometry first.");
|
||||
ERR_FAIL_COND_MSG(_baking_navigation_meshes.find(p_navigation_mesh) >= 0, "NavigationMesh is already baking. Wait for current bake task to finish.");
|
||||
|
||||
_generator_mutex.lock();
|
||||
_baking_navigation_meshes.push_back(p_navigation_mesh);
|
||||
_generator_mutex.unlock();
|
||||
|
||||
_static_bake_3d_from_source_geometry_data(p_navigation_mesh, p_source_geometry_data);
|
||||
|
||||
_generator_mutex.lock();
|
||||
int64_t navigation_mesh_index = _baking_navigation_meshes.find(p_navigation_mesh);
|
||||
if (navigation_mesh_index >= 0) {
|
||||
_baking_navigation_meshes.remove_unordered(navigation_mesh_index);
|
||||
}
|
||||
_generator_mutex.unlock();
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_static_parse_3d_geometry_node(Ref<NavigationMesh> p_navigation_mesh, Node *p_node, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, bool p_recurse_children, LocalVector<Ref<NavigationGeometryParser3D>> &p_geometry_3d_parsers) {
|
||||
for (uint32_t i = 0; i < p_geometry_3d_parsers.size(); ++i) {
|
||||
Ref<NavigationGeometryParser3D> &geometry_3d_parser = p_geometry_3d_parsers[i];
|
||||
|
||||
if (geometry_3d_parser->parses_node(p_node)) {
|
||||
geometry_3d_parser->parse_node_geometry(p_navigation_mesh, p_node, p_source_geometry_data);
|
||||
};
|
||||
};
|
||||
|
||||
if (p_recurse_children) {
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
_static_parse_3d_geometry_node(p_navigation_mesh, p_node->get_child(i), p_source_geometry_data, p_recurse_children, p_geometry_3d_parsers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_static_parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, LocalVector<Ref<NavigationGeometryParser3D>> &p_geometry_3d_parsers) {
|
||||
ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh.");
|
||||
ERR_FAIL_COND_MSG(p_root_node == nullptr, "Invalid parse root node.");
|
||||
ERR_FAIL_COND_MSG(!p_source_geometry_data.is_valid(), "Invalid source geometry data.");
|
||||
|
||||
List<Node *> parse_nodes;
|
||||
|
||||
if (p_navigation_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
|
||||
parse_nodes.push_back(p_root_node);
|
||||
} else {
|
||||
p_root_node->get_tree()->get_nodes_in_group(p_navigation_mesh->get_source_group_name(), &parse_nodes);
|
||||
}
|
||||
|
||||
Transform root_node_transform = Object::cast_to<Spatial>(p_root_node)->get_global_transform().affine_inverse();
|
||||
bool recurse_children = p_navigation_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
|
||||
|
||||
p_source_geometry_data->clear();
|
||||
p_source_geometry_data->root_node_transform = root_node_transform;
|
||||
|
||||
for (List<Node *>::Element *E = parse_nodes.front(); E; E = E->next()) {
|
||||
_static_parse_3d_geometry_node(p_navigation_mesh, E->get(), p_source_geometry_data, recurse_children, p_geometry_3d_parsers);
|
||||
}
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
PandemoniumNavigationMeshGenerator::PandemoniumNavigationMeshGenerator() {
|
||||
_use_thread_pool = GLOBAL_GET("navigation/baking/thread_model/use_thread_pool");
|
||||
// Can't use threads in Editor as parsing gets stuck on RenderingServer / PhysicsServer locks.
|
||||
|
@ -79,37 +79,6 @@ public:
|
||||
static void _bind_methods();
|
||||
};
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
class NavigationGeneratorTask3D : public ThreadPoolJob {
|
||||
GDCLASS(NavigationGeneratorTask3D, ThreadPoolJob);
|
||||
|
||||
public:
|
||||
enum TaskStatus {
|
||||
PARSING_REQUIRED,
|
||||
PARSING_STARTED,
|
||||
PARSING_FINISHED,
|
||||
PARSING_FAILED,
|
||||
BAKING_STARTED,
|
||||
BAKING_FINISHED,
|
||||
BAKING_FAILED
|
||||
};
|
||||
|
||||
Ref<NavigationMesh> navigation_mesh;
|
||||
ObjectID parse_root_object_id;
|
||||
Ref<NavigationMeshSourceGeometryData3D> source_geometry_data;
|
||||
Ref<FuncRef> callback;
|
||||
NavigationGeneratorTask3D::TaskStatus status = NavigationGeneratorTask3D::TaskStatus::PARSING_REQUIRED;
|
||||
LocalVector<Ref<NavigationGeometryParser3D>> geometry_parsers;
|
||||
|
||||
void call_callback();
|
||||
|
||||
void _execute();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
};
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
// ======= TASKS END =======
|
||||
|
||||
public:
|
||||
@ -131,22 +100,6 @@ public:
|
||||
|
||||
virtual bool is_navigation_polygon_baking(Ref<NavigationPolygon> p_navigation_polygon) const;
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
virtual void register_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser);
|
||||
virtual void unregister_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser);
|
||||
|
||||
virtual Ref<NavigationMeshSourceGeometryData3D> parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
virtual void bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
|
||||
virtual void parse_and_bake_3d(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
|
||||
static void _static_parse_3d_geometry_node(Ref<NavigationMesh> p_navigation_mesh, Node *p_node, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, bool p_recurse_children, LocalVector<Ref<NavigationGeometryParser3D>> &p_geometry_3d_parsers);
|
||||
static void _static_parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, LocalVector<Ref<NavigationGeometryParser3D>> &p_geometry_3d_parsers);
|
||||
static void _static_bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data);
|
||||
|
||||
virtual bool is_navigation_mesh_baking(Ref<NavigationMesh> p_navigation_mesh) const;
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
PandemoniumNavigationMeshGenerator();
|
||||
~PandemoniumNavigationMeshGenerator();
|
||||
|
||||
@ -155,12 +108,6 @@ private:
|
||||
void _process_2d_parse_tasks();
|
||||
void _process_2d_bake_cleanup_tasks();
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
void _process_3d_tasks();
|
||||
void _process_3d_parse_tasks();
|
||||
void _process_3d_bake_cleanup_tasks();
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
private:
|
||||
Mutex _generator_mutex;
|
||||
|
||||
@ -173,14 +120,6 @@ private:
|
||||
LocalVector<Ref<NavigationPolygon>> _baking_navigation_polygons;
|
||||
LocalVector<Ref<NavigationGeneratorTask2D>> _2d_parse_jobs;
|
||||
LocalVector<Ref<NavigationGeneratorTask2D>> _2d_running_jobs;
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
LocalVector<Ref<NavigationGeometryParser3D>> _geometry_3d_parsers;
|
||||
|
||||
LocalVector<Ref<NavigationMesh>> _baking_navigation_meshes;
|
||||
LocalVector<Ref<NavigationGeneratorTask3D>> _3d_parse_jobs;
|
||||
LocalVector<Ref<NavigationGeneratorTask3D>> _3d_running_jobs;
|
||||
#endif // _3D_DISABLED
|
||||
};
|
||||
|
||||
#endif // GODOT_NAVIGATION_MESH_GENERATOR_H
|
||||
|
@ -35,11 +35,6 @@
|
||||
|
||||
#include "pandemonium_navigation_mesh_generator.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/navigation_mesh_editor_plugin.h"
|
||||
#include "editor/navigation_polygon_editor_plugin.h"
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
NavigationMeshGenerator *new_navigation_mesh_generator_server() {
|
||||
return memnew(PandemoniumNavigationMeshGenerator);
|
||||
}
|
||||
@ -49,13 +44,6 @@ void register_navigation_mesh_generator_types(ModuleRegistrationLevel p_level) {
|
||||
NavigationMeshGeneratorManager::get_singleton()->register_server("PandemoniumNavigationMeshGenerator", new_navigation_mesh_generator_server);
|
||||
NavigationMeshGeneratorManager::get_singleton()->set_default_server("PandemoniumNavigationMeshGenerator");
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (p_level == MODULE_REGISTRATION_LEVEL_EDITOR) {
|
||||
EditorPlugins::add_by_type<NavigationMeshEditorPlugin>();
|
||||
EditorPlugins::add_by_type<NavigationPolygonEditorPlugin>();
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
}
|
||||
|
||||
void unregister_navigation_mesh_generator_types(ModuleRegistrationLevel p_level) {
|
||||
|
@ -1,155 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* navigation.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "navigation.h"
|
||||
|
||||
#include "scene/3d/navigation_mesh_instance.h"
|
||||
#include "servers/navigation_server.h"
|
||||
|
||||
Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const {
|
||||
return NavigationServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize, navigation_layers);
|
||||
}
|
||||
|
||||
Vector3 Navigation::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const {
|
||||
return NavigationServer::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision);
|
||||
}
|
||||
|
||||
Vector3 Navigation::get_closest_point(const Vector3 &p_point) const {
|
||||
return NavigationServer::get_singleton()->map_get_closest_point(map, p_point);
|
||||
}
|
||||
|
||||
Vector3 Navigation::get_closest_point_normal(const Vector3 &p_point) const {
|
||||
return NavigationServer::get_singleton()->map_get_closest_point_normal(map, p_point);
|
||||
}
|
||||
|
||||
RID Navigation::get_closest_point_owner(const Vector3 &p_point) const {
|
||||
return NavigationServer::get_singleton()->map_get_closest_point_owner(map, p_point);
|
||||
}
|
||||
|
||||
void Navigation::set_up_vector(const Vector3 &p_up) {
|
||||
up = p_up;
|
||||
NavigationServer::get_singleton()->map_set_up(map, up);
|
||||
}
|
||||
|
||||
Vector3 Navigation::get_up_vector() const {
|
||||
return up;
|
||||
}
|
||||
|
||||
void Navigation::set_cell_size(float p_cell_size) {
|
||||
cell_size = p_cell_size;
|
||||
NavigationServer::get_singleton()->map_set_cell_size(map, cell_size);
|
||||
}
|
||||
|
||||
void Navigation::set_cell_height(float p_cell_height) {
|
||||
cell_height = p_cell_height;
|
||||
NavigationServer::get_singleton()->map_set_cell_height(map, cell_height);
|
||||
}
|
||||
|
||||
void Navigation::set_edge_connection_margin(float p_edge_connection_margin) {
|
||||
edge_connection_margin = p_edge_connection_margin;
|
||||
NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin);
|
||||
}
|
||||
|
||||
void Navigation::set_navigation_layers(uint32_t p_navigation_layers) {
|
||||
navigation_layers = p_navigation_layers;
|
||||
}
|
||||
|
||||
uint32_t Navigation::get_navigation_layers() const {
|
||||
return navigation_layers;
|
||||
}
|
||||
|
||||
void Navigation::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_rid"), &Navigation::get_rid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation::get_simple_path, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation::get_closest_point_to_segment, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation::get_closest_point);
|
||||
ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation::get_closest_point_normal);
|
||||
ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation::get_closest_point_owner);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation::set_up_vector);
|
||||
ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation::get_up_vector);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation::set_cell_size);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation::get_cell_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cell_height", "cell_height"), &Navigation::set_cell_height);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_height"), &Navigation::get_cell_height);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation::set_edge_connection_margin);
|
||||
ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation::get_edge_connection_margin);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &Navigation::set_navigation_layers);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &Navigation::get_navigation_layers);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size"), "set_cell_size", "get_cell_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_height"), "set_cell_height", "get_cell_height");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
|
||||
}
|
||||
|
||||
void Navigation::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_READY: {
|
||||
NavigationServer::get_singleton()->map_set_active(map, true);
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
// FIXME 3.5 with this old navigation node only
|
||||
// if the node gets deleted this exit causes annoying error prints in debug
|
||||
// It tries to deactivate a map that itself has send a free command to the server.
|
||||
//NavigationServer::get_singleton()->map_set_active(map, false);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
Navigation::Navigation() {
|
||||
map = NavigationServer::get_singleton()->map_create();
|
||||
|
||||
set_cell_size(0.25);
|
||||
set_cell_height(0.25);
|
||||
set_edge_connection_margin(0.25); // Five meters, depends a lot on the agents radius
|
||||
|
||||
up = Vector3(0, 1, 0);
|
||||
|
||||
navigation_layers = 1;
|
||||
|
||||
NavigationServer::get_singleton()->map_set_active(map, true);
|
||||
NavigationServer::get_singleton()->map_set_up(map, get_up_vector());
|
||||
NavigationServer::get_singleton()->map_set_cell_size(map, get_cell_size());
|
||||
NavigationServer::get_singleton()->map_set_cell_height(map, get_cell_height());
|
||||
NavigationServer::get_singleton()->map_set_edge_connection_margin(map, get_edge_connection_margin());
|
||||
}
|
||||
|
||||
Navigation::~Navigation() {
|
||||
NavigationServer::get_singleton()->free(map);
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
#ifndef NAVIGATION_H
|
||||
#define NAVIGATION_H
|
||||
/*************************************************************************/
|
||||
/* navigation.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class Navigation : public Spatial {
|
||||
GDCLASS(Navigation, Spatial);
|
||||
|
||||
RID map;
|
||||
|
||||
Vector3 up;
|
||||
real_t cell_size;
|
||||
real_t cell_height;
|
||||
real_t edge_connection_margin;
|
||||
|
||||
uint32_t navigation_layers;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
RID get_rid() const {
|
||||
return map;
|
||||
}
|
||||
|
||||
void set_up_vector(const Vector3 &p_up);
|
||||
Vector3 get_up_vector() const;
|
||||
|
||||
void set_cell_size(float p_cell_size);
|
||||
float get_cell_size() const {
|
||||
return cell_size;
|
||||
}
|
||||
|
||||
void set_cell_height(float p_cell_height);
|
||||
float get_cell_height() const {
|
||||
return cell_height;
|
||||
}
|
||||
|
||||
void set_navigation_layers(uint32_t p_navigation_layers);
|
||||
uint32_t get_navigation_layers() const;
|
||||
|
||||
void set_edge_connection_margin(float p_edge_connection_margin);
|
||||
float get_edge_connection_margin() const {
|
||||
return edge_connection_margin;
|
||||
}
|
||||
|
||||
Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const;
|
||||
Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const;
|
||||
Vector3 get_closest_point(const Vector3 &p_point) const;
|
||||
Vector3 get_closest_point_normal(const Vector3 &p_point) const;
|
||||
RID get_closest_point_owner(const Vector3 &p_point) const;
|
||||
|
||||
Navigation();
|
||||
~Navigation();
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_H
|
File diff suppressed because it is too large
Load Diff
@ -1,282 +0,0 @@
|
||||
#ifndef NAVIGATION_AGENT_H
|
||||
#define NAVIGATION_AGENT_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* navigation_agent.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/containers/vector.h"
|
||||
|
||||
#include "scene/main/node.h"
|
||||
#include "servers/navigation/navigation_path_query_parameters_3d.h"
|
||||
|
||||
class Spatial;
|
||||
class Navigation;
|
||||
class SpatialMaterial;
|
||||
class NavigationPathQueryParameters3D;
|
||||
class NavigationPathQueryResult3D;
|
||||
|
||||
class NavigationAgent : public Node {
|
||||
GDCLASS(NavigationAgent, Node);
|
||||
|
||||
Spatial *agent_parent;
|
||||
Navigation *navigation;
|
||||
|
||||
RID agent;
|
||||
RID map_override;
|
||||
|
||||
bool avoidance_enabled;
|
||||
bool use_3d_avoidance;
|
||||
uint32_t avoidance_layers;
|
||||
uint32_t avoidance_mask;
|
||||
real_t avoidance_priority;
|
||||
uint32_t navigation_layers;
|
||||
NavigationPathQueryParameters3D::PathfindingAlgorithm pathfinding_algorithm;
|
||||
NavigationPathQueryParameters3D::PathPostProcessing path_postprocessing;
|
||||
int path_metadata_flags;
|
||||
|
||||
real_t path_desired_distance;
|
||||
real_t target_desired_distance;
|
||||
real_t height;
|
||||
real_t radius;
|
||||
real_t path_height_offset;
|
||||
real_t neighbor_distance;
|
||||
int max_neighbors;
|
||||
real_t time_horizon_agents;
|
||||
real_t time_horizon_obstacles;
|
||||
real_t max_speed;
|
||||
real_t path_max_distance;
|
||||
|
||||
Vector3 target_position;
|
||||
bool target_position_submitted;
|
||||
|
||||
Ref<NavigationPathQueryParameters3D> navigation_query;
|
||||
Ref<NavigationPathQueryResult3D> navigation_result;
|
||||
int nav_path_index;
|
||||
|
||||
// the velocity result of the avoidance simulation step
|
||||
Vector3 safe_velocity;
|
||||
|
||||
/// The submitted target velocity, sets the "wanted" rvo agent velocity on the next update
|
||||
// this velocity is not guaranteed, the simulation will try to fulfil it if possible
|
||||
// if other agents or obstacles interfere it will be changed accordingly
|
||||
Vector3 velocity;
|
||||
|
||||
bool velocity_submitted;
|
||||
|
||||
/// The submitted forced velocity, overrides the rvo agent velocity on the next update
|
||||
// should only be used very intentionally and not every frame as it interferes with the simulation stability
|
||||
Vector3 velocity_forced;
|
||||
bool velocity_forced_submitted;
|
||||
|
||||
// 2D avoidance has no y-axis. This stores and reapplies the y-axis velocity to the agent before and after the avoidance step.
|
||||
// While not perfect it at least looks way better than agent's that clip through everything that is not a flat surface
|
||||
float stored_y_velocity;
|
||||
|
||||
bool target_reached;
|
||||
bool navigation_finished;
|
||||
// No initialized on purpose
|
||||
uint32_t update_frame_id;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool debug_enabled;
|
||||
bool debug_path_dirty;
|
||||
RID debug_path_instance;
|
||||
Ref<ArrayMesh> debug_path_mesh;
|
||||
float debug_path_custom_point_size;
|
||||
bool debug_use_custom;
|
||||
Color debug_path_custom_color;
|
||||
Ref<SpatialMaterial> debug_agent_path_line_custom_material;
|
||||
Ref<SpatialMaterial> debug_agent_path_point_custom_material;
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
NavigationAgent();
|
||||
virtual ~NavigationAgent();
|
||||
|
||||
void set_navigation(Navigation *p_nav);
|
||||
const Navigation *get_navigation() const {
|
||||
return navigation;
|
||||
}
|
||||
|
||||
void set_navigation_node(Node *p_nav);
|
||||
Node *get_navigation_node() const;
|
||||
|
||||
RID get_rid() const {
|
||||
return agent;
|
||||
}
|
||||
|
||||
void set_avoidance_enabled(bool p_enabled);
|
||||
bool get_avoidance_enabled() const;
|
||||
|
||||
void set_agent_parent(Node *p_agent_parent);
|
||||
|
||||
void set_navigation_layers(uint32_t p_navigation_layers);
|
||||
uint32_t get_navigation_layers() const;
|
||||
|
||||
void set_navigation_layer_value(int p_layer_number, bool p_value);
|
||||
bool get_navigation_layer_value(int p_layer_number) const;
|
||||
|
||||
void set_pathfinding_algorithm(const NavigationPathQueryParameters3D::PathfindingAlgorithm p_pathfinding_algorithm);
|
||||
NavigationPathQueryParameters3D::PathfindingAlgorithm get_pathfinding_algorithm() const {
|
||||
return pathfinding_algorithm;
|
||||
}
|
||||
|
||||
void set_path_postprocessing(const NavigationPathQueryParameters3D::PathPostProcessing p_path_postprocessing);
|
||||
NavigationPathQueryParameters3D::PathPostProcessing get_path_postprocessing() const {
|
||||
return path_postprocessing;
|
||||
}
|
||||
|
||||
void set_avoidance_layers(uint32_t p_layers);
|
||||
uint32_t get_avoidance_layers() const;
|
||||
|
||||
void set_avoidance_mask(uint32_t p_mask);
|
||||
uint32_t get_avoidance_mask() const;
|
||||
|
||||
void set_avoidance_layer_value(int p_layer_number, bool p_value);
|
||||
bool get_avoidance_layer_value(int p_layer_number) const;
|
||||
|
||||
void set_avoidance_mask_value(int p_mask_number, bool p_value);
|
||||
bool get_avoidance_mask_value(int p_mask_number) const;
|
||||
|
||||
void set_avoidance_priority(real_t p_priority);
|
||||
real_t get_avoidance_priority() const;
|
||||
|
||||
void set_path_metadata_flags(const int p_flags);
|
||||
int get_path_metadata_flags() const;
|
||||
|
||||
void set_navigation_map(RID p_navigation_map);
|
||||
RID get_navigation_map() const;
|
||||
|
||||
void set_path_desired_distance(real_t p_dd);
|
||||
real_t get_path_desired_distance() const {
|
||||
return path_desired_distance;
|
||||
}
|
||||
|
||||
void set_target_desired_distance(real_t p_dd);
|
||||
real_t get_target_desired_distance() const {
|
||||
return target_desired_distance;
|
||||
}
|
||||
|
||||
void set_radius(real_t p_radius);
|
||||
real_t get_radius() const {
|
||||
return radius;
|
||||
}
|
||||
|
||||
void set_height(real_t p_height);
|
||||
real_t get_height() const { return height; }
|
||||
|
||||
void set_path_height_offset(real_t p_path_height_offset);
|
||||
real_t get_path_height_offset() const { return path_height_offset; }
|
||||
|
||||
void set_use_3d_avoidance(bool p_use_3d_avoidance);
|
||||
bool get_use_3d_avoidance() const { return use_3d_avoidance; }
|
||||
|
||||
void set_neighbor_distance(real_t p_dist);
|
||||
real_t get_neighbor_distance() const {
|
||||
return neighbor_distance;
|
||||
}
|
||||
|
||||
void set_max_neighbors(int p_count);
|
||||
int get_max_neighbors() const {
|
||||
return max_neighbors;
|
||||
}
|
||||
|
||||
void set_time_horizon_agents(real_t p_time_horizon);
|
||||
real_t get_time_horizon_agents() const { return time_horizon_agents; }
|
||||
|
||||
void set_time_horizon_obstacles(real_t p_time_horizon);
|
||||
real_t get_time_horizon_obstacles() const { return time_horizon_obstacles; }
|
||||
|
||||
void set_max_speed(real_t p_max_speed);
|
||||
real_t get_max_speed() const {
|
||||
return max_speed;
|
||||
}
|
||||
|
||||
void set_path_max_distance(real_t p_pmd);
|
||||
real_t get_path_max_distance();
|
||||
|
||||
void set_target_position(Vector3 p_position);
|
||||
Vector3 get_target_position() const;
|
||||
|
||||
Vector3 get_next_position();
|
||||
|
||||
Ref<NavigationPathQueryResult3D> get_current_navigation_result() const;
|
||||
|
||||
Vector<Vector3> get_current_navigation_path() const;
|
||||
|
||||
int get_current_navigation_path_index() const {
|
||||
return nav_path_index;
|
||||
}
|
||||
|
||||
real_t distance_to_target() const;
|
||||
bool is_target_reached() const;
|
||||
bool is_target_reachable();
|
||||
bool is_navigation_finished();
|
||||
Vector3 get_final_position();
|
||||
|
||||
void set_velocity(const Vector3 p_velocity);
|
||||
Vector3 get_velocity() { return velocity; }
|
||||
|
||||
void set_velocity_forced(const Vector3 p_velocity);
|
||||
|
||||
void _avoidance_done(Vector3 p_new_velocity);
|
||||
|
||||
virtual String get_configuration_warning() const;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void set_debug_enabled(bool p_enabled);
|
||||
bool get_debug_enabled() const;
|
||||
|
||||
void set_debug_use_custom(bool p_enabled);
|
||||
bool get_debug_use_custom() const;
|
||||
|
||||
void set_debug_path_custom_color(Color p_color);
|
||||
Color get_debug_path_custom_color() const;
|
||||
|
||||
void set_debug_path_custom_point_size(float p_point_size);
|
||||
float get_debug_path_custom_point_size() const;
|
||||
#endif // DEBUG_ENABLE
|
||||
|
||||
private:
|
||||
void update_navigation();
|
||||
void _request_repath();
|
||||
void _check_distance_to_target();
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void _navigation_debug_changed();
|
||||
void _update_debug_path();
|
||||
#endif // DEBUG_ENABLED
|
||||
};
|
||||
|
||||
#endif
|
@ -1,69 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_geometry_parser_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "navigation_geometry_parser_3d.h"
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
bool NavigationGeometryParser3D::parses_node(Node *p_node) {
|
||||
if (!Object::cast_to<Spatial>(p_node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (has_method("_parses_node")) {
|
||||
return call("_parses_node", p_node);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void NavigationGeometryParser3D::parse_node_geometry(Ref<NavigationMesh> p_navigation_mesh, Node *p_node, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry) {
|
||||
parse_geometry(p_node, p_navigation_mesh, p_source_geometry);
|
||||
}
|
||||
|
||||
void NavigationGeometryParser3D::parse_geometry(Node *p_node, Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry) {
|
||||
if (has_method("_parse_geometry")) {
|
||||
call("_parse_geometry", p_node, p_navigation_mesh, p_source_geometry);
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationGeometryParser3D::_bind_methods() {
|
||||
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_parses_node", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
|
||||
BIND_VMETHOD(MethodInfo("_parse_geometry",
|
||||
PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"),
|
||||
PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"),
|
||||
PropertyInfo(Variant::OBJECT, "source_geometry", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMeshSourceGeometryData3D")));
|
||||
}
|
||||
|
||||
#endif // _3D_DISABLED
|
@ -1,53 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_geometry_parser_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NAVIGATION_GEOMETRY_PARSER_3D_H
|
||||
#define NAVIGATION_GEOMETRY_PARSER_3D_H
|
||||
|
||||
#include "core/object/reference.h"
|
||||
|
||||
class NavigationMesh;
|
||||
class NavigationMeshSourceGeometryData3D;
|
||||
class Node;
|
||||
|
||||
class NavigationGeometryParser3D : public Reference {
|
||||
GDCLASS(NavigationGeometryParser3D, Reference);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool parses_node(Node *p_node);
|
||||
virtual void parse_geometry(Node *p_node, Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry);
|
||||
|
||||
void parse_node_geometry(Ref<NavigationMesh> p_navigationmesh, Node *p_node, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry);
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_GEOMETRY_PARSER_3D_H
|
@ -1,435 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_link_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "navigation_link_3d.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "mesh_instance.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "servers/navigation_server.h"
|
||||
#include "scene/resources/material/spatial_material.h"
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void NavigationLink3D::_update_debug_mesh() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
// don't update inside Editor as node 3d gizmo takes care of this
|
||||
// as collisions and selections for Editor Viewport need to be updated
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NavigationServer::get_singleton()->get_debug_navigation_enabled()) {
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!debug_instance.is_valid()) {
|
||||
debug_instance = RenderingServer::get_singleton()->instance_create();
|
||||
}
|
||||
|
||||
if (!debug_mesh.is_valid()) {
|
||||
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
|
||||
}
|
||||
|
||||
RID nav_map = get_world_3d()->get_navigation_map();
|
||||
real_t search_radius = NavigationServer::get_singleton()->map_get_link_connection_radius(nav_map);
|
||||
Vector3 up_vector = NavigationServer::get_singleton()->map_get_up(nav_map);
|
||||
Vector3::Axis up_axis = static_cast<Vector3::Axis>(up_vector.max_axis());
|
||||
|
||||
debug_mesh->clear_surfaces();
|
||||
|
||||
Vector<Vector3> lines;
|
||||
|
||||
// Draw line between the points.
|
||||
lines.push_back(start_position);
|
||||
lines.push_back(end_position);
|
||||
|
||||
// Draw start position search radius
|
||||
for (int i = 0; i < 30; i++) {
|
||||
// Create a circle
|
||||
const float ra = Math::deg2rad((float)(i * 12));
|
||||
const float rb = Math::deg2rad((float)((i + 1) * 12));
|
||||
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
|
||||
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
|
||||
|
||||
// Draw axis-aligned circle
|
||||
switch (up_axis) {
|
||||
case Vector3::AXIS_X:
|
||||
lines.push_back(start_position + Vector3(0, a.x, a.y));
|
||||
lines.push_back(start_position + Vector3(0, b.x, b.y));
|
||||
break;
|
||||
case Vector3::AXIS_Y:
|
||||
lines.push_back(start_position + Vector3(a.x, 0, a.y));
|
||||
lines.push_back(start_position + Vector3(b.x, 0, b.y));
|
||||
break;
|
||||
case Vector3::AXIS_Z:
|
||||
lines.push_back(start_position + Vector3(a.x, a.y, 0));
|
||||
lines.push_back(start_position + Vector3(b.x, b.y, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw end position search radius
|
||||
for (int i = 0; i < 30; i++) {
|
||||
// Create a circle
|
||||
const float ra = Math::deg2rad((float)(i * 12));
|
||||
const float rb = Math::deg2rad((float)((i + 1) * 12));
|
||||
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
|
||||
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
|
||||
|
||||
// Draw axis-aligned circle
|
||||
switch (up_axis) {
|
||||
case Vector3::AXIS_X:
|
||||
lines.push_back(end_position + Vector3(0, a.x, a.y));
|
||||
lines.push_back(end_position + Vector3(0, b.x, b.y));
|
||||
break;
|
||||
case Vector3::AXIS_Y:
|
||||
lines.push_back(end_position + Vector3(a.x, 0, a.y));
|
||||
lines.push_back(end_position + Vector3(b.x, 0, b.y));
|
||||
break;
|
||||
case Vector3::AXIS_Z:
|
||||
lines.push_back(end_position + Vector3(a.x, a.y, 0));
|
||||
lines.push_back(end_position + Vector3(b.x, b.y, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Array mesh_array;
|
||||
mesh_array.resize(Mesh::ARRAY_MAX);
|
||||
mesh_array[Mesh::ARRAY_VERTEX] = lines;
|
||||
|
||||
debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_array);
|
||||
|
||||
RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
|
||||
RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
|
||||
|
||||
Ref<SpatialMaterial> link_material = NavigationServer::get_singleton()->get_debug_navigation_link_connections_material();
|
||||
Ref<SpatialMaterial> disabled_link_material = NavigationServer::get_singleton()->get_debug_navigation_link_connections_disabled_material();
|
||||
|
||||
if (enabled) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, link_material->get_rid());
|
||||
} else {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, disabled_link_material->get_rid());
|
||||
}
|
||||
|
||||
RS::get_singleton()->instance_set_transform(debug_instance, current_global_transform);
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
void NavigationLink3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink3D::set_bidirectional);
|
||||
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink3D::is_bidirectional);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink3D::set_navigation_layers);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink3D::get_navigation_layers);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink3D::set_navigation_layer_value);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink3D::get_navigation_layer_value);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_start_position", "position"), &NavigationLink3D::set_start_position);
|
||||
ClassDB::bind_method(D_METHOD("get_start_position"), &NavigationLink3D::get_start_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink3D::set_end_position);
|
||||
ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink3D::get_end_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink3D::set_global_start_position);
|
||||
ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink3D::get_global_start_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink3D::set_global_end_position);
|
||||
ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink3D::get_global_end_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink3D::set_enter_cost);
|
||||
ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink3D::get_enter_cost);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink3D::set_travel_cost);
|
||||
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink3D::get_travel_cost);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_position"), "set_start_position", "get_start_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "end_position"), "set_end_position", "get_end_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "enter_cost"), "set_enter_cost", "get_enter_cost");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "travel_cost"), "set_travel_cost", "get_travel_cost");
|
||||
}
|
||||
|
||||
void NavigationLink3D::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
if (enabled) {
|
||||
NavigationServer::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
|
||||
}
|
||||
current_global_transform = get_global_transform();
|
||||
NavigationServer::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
|
||||
NavigationServer::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_update_debug_mesh();
|
||||
#endif // DEBUG_ENABLED
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
set_physics_process_internal(true);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
set_physics_process_internal(false);
|
||||
if (is_inside_tree()) {
|
||||
Transform new_global_transform = get_global_transform();
|
||||
if (current_global_transform != new_global_transform) {
|
||||
current_global_transform = new_global_transform;
|
||||
NavigationServer::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
|
||||
NavigationServer::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_transform(debug_instance, current_global_transform);
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
NavigationServer::get_singleton()->link_set_map(link, RID());
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_scenario(debug_instance, RID());
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
NavigationLink3D::NavigationLink3D() {
|
||||
link = NavigationServer::get_singleton()->link_create();
|
||||
NavigationServer::get_singleton()->link_set_owner_id(link, get_instance_id());
|
||||
|
||||
set_notify_transform(true);
|
||||
}
|
||||
|
||||
NavigationLink3D::~NavigationLink3D() {
|
||||
ERR_FAIL_NULL(NavigationServer::get_singleton());
|
||||
NavigationServer::get_singleton()->free(link);
|
||||
link = RID();
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_NULL(RenderingServer::get_singleton());
|
||||
if (debug_instance.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(debug_instance);
|
||||
}
|
||||
if (debug_mesh.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(debug_mesh->get_rid());
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_enabled(bool p_enabled) {
|
||||
if (enabled == p_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
enabled = p_enabled;
|
||||
|
||||
NavigationServer::get_singleton()->link_set_enabled(link, enabled);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_instance.is_valid() && debug_mesh.is_valid()) {
|
||||
if (enabled) {
|
||||
Ref<SpatialMaterial> link_material = NavigationServer::get_singleton()->get_debug_navigation_link_connections_material();
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, link_material->get_rid());
|
||||
} else {
|
||||
Ref<SpatialMaterial> disabled_link_material = NavigationServer::get_singleton()->get_debug_navigation_link_connections_disabled_material();
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, disabled_link_material->get_rid());
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_bidirectional(bool p_bidirectional) {
|
||||
if (bidirectional == p_bidirectional) {
|
||||
return;
|
||||
}
|
||||
|
||||
bidirectional = p_bidirectional;
|
||||
|
||||
NavigationServer::get_singleton()->link_set_bidirectional(link, bidirectional);
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_navigation_layers(uint32_t p_navigation_layers) {
|
||||
if (navigation_layers == p_navigation_layers) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigation_layers = p_navigation_layers;
|
||||
|
||||
NavigationServer::get_singleton()->link_set_navigation_layers(link, navigation_layers);
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_navigation_layer_value(int p_layer_number, bool p_value) {
|
||||
ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
|
||||
uint32_t _navigation_layers = get_navigation_layers();
|
||||
|
||||
if (p_value) {
|
||||
_navigation_layers |= 1 << (p_layer_number - 1);
|
||||
} else {
|
||||
_navigation_layers &= ~(1 << (p_layer_number - 1));
|
||||
}
|
||||
|
||||
set_navigation_layers(_navigation_layers);
|
||||
}
|
||||
|
||||
bool NavigationLink3D::get_navigation_layer_value(int p_layer_number) const {
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
|
||||
return get_navigation_layers() & (1 << (p_layer_number - 1));
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_start_position(Vector3 p_position) {
|
||||
if (start_position.is_equal_approx(p_position)) {
|
||||
return;
|
||||
}
|
||||
|
||||
start_position = p_position;
|
||||
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NavigationServer::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_update_debug_mesh();
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
update_gizmos();
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_end_position(Vector3 p_position) {
|
||||
if (end_position.is_equal_approx(p_position)) {
|
||||
return;
|
||||
}
|
||||
|
||||
end_position = p_position;
|
||||
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NavigationServer::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_update_debug_mesh();
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
update_gizmos();
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_global_start_position(Vector3 p_position) {
|
||||
if (is_inside_tree()) {
|
||||
set_start_position(to_local(p_position));
|
||||
} else {
|
||||
set_start_position(p_position);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 NavigationLink3D::get_global_start_position() const {
|
||||
if (is_inside_tree()) {
|
||||
return to_global(start_position);
|
||||
} else {
|
||||
return start_position;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_global_end_position(Vector3 p_position) {
|
||||
if (is_inside_tree()) {
|
||||
set_end_position(to_local(p_position));
|
||||
} else {
|
||||
set_end_position(p_position);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 NavigationLink3D::get_global_end_position() const {
|
||||
if (is_inside_tree()) {
|
||||
return to_global(end_position);
|
||||
} else {
|
||||
return end_position;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_enter_cost(real_t p_enter_cost) {
|
||||
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
|
||||
if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
enter_cost = p_enter_cost;
|
||||
|
||||
NavigationServer::get_singleton()->link_set_enter_cost(link, enter_cost);
|
||||
}
|
||||
|
||||
void NavigationLink3D::set_travel_cost(real_t p_travel_cost) {
|
||||
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
|
||||
if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
travel_cost = p_travel_cost;
|
||||
|
||||
NavigationServer::get_singleton()->link_set_travel_cost(link, travel_cost);
|
||||
}
|
||||
|
||||
String NavigationLink3D::get_configuration_warning() const {
|
||||
String warnings = Node::get_configuration_warning();
|
||||
|
||||
if (start_position.is_equal_approx(end_position)) {
|
||||
warnings += RTR("NavigationLink3D start position should be different than the end position to be useful.");
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
#ifndef NAVIGATION_LINK_3D_H
|
||||
#define NAVIGATION_LINK_3D_H
|
||||
|
||||
/**************************************************************************/
|
||||
/* navigation_link_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class NavigationLink3D : public Spatial {
|
||||
GDCLASS(NavigationLink3D, Spatial);
|
||||
|
||||
bool enabled = true;
|
||||
RID link;
|
||||
bool bidirectional = true;
|
||||
uint32_t navigation_layers = 1;
|
||||
Vector3 end_position;
|
||||
Vector3 start_position;
|
||||
real_t enter_cost = 0.0;
|
||||
real_t travel_cost = 1.0;
|
||||
|
||||
Transform current_global_transform;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
RID debug_instance;
|
||||
Ref<ArrayMesh> debug_mesh;
|
||||
|
||||
void _update_debug_mesh();
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
NavigationLink3D();
|
||||
~NavigationLink3D();
|
||||
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const { return enabled; }
|
||||
|
||||
void set_bidirectional(bool p_bidirectional);
|
||||
bool is_bidirectional() const { return bidirectional; }
|
||||
|
||||
void set_navigation_layers(uint32_t p_navigation_layers);
|
||||
uint32_t get_navigation_layers() const { return navigation_layers; }
|
||||
|
||||
void set_navigation_layer_value(int p_layer_number, bool p_value);
|
||||
bool get_navigation_layer_value(int p_layer_number) const;
|
||||
|
||||
void set_start_position(Vector3 p_position);
|
||||
Vector3 get_start_position() const { return start_position; }
|
||||
|
||||
void set_end_position(Vector3 p_position);
|
||||
Vector3 get_end_position() const { return end_position; }
|
||||
|
||||
void set_global_start_position(Vector3 p_position);
|
||||
Vector3 get_global_start_position() const;
|
||||
|
||||
void set_global_end_position(Vector3 p_position);
|
||||
Vector3 get_global_end_position() const;
|
||||
|
||||
void set_enter_cost(real_t p_enter_cost);
|
||||
real_t get_enter_cost() const { return enter_cost; }
|
||||
|
||||
void set_travel_cost(real_t p_travel_cost);
|
||||
real_t get_travel_cost() const { return travel_cost; }
|
||||
|
||||
String get_configuration_warning() const;
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_LINK_3D_H
|
@ -1,760 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* navigation_mesh_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "navigation_mesh_instance.h"
|
||||
|
||||
#include "core/core_string_names.h"
|
||||
#include "core/os/os.h"
|
||||
#include "mesh_instance.h"
|
||||
#include "navigation.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "servers/navigation/navigation_mesh_generator.h"
|
||||
#include "servers/navigation_server.h"
|
||||
#include "scene/resources/material/spatial_material.h"
|
||||
|
||||
void NavigationMeshInstance::set_enabled(bool p_enabled) {
|
||||
if (enabled == p_enabled) {
|
||||
return;
|
||||
}
|
||||
enabled = p_enabled;
|
||||
|
||||
NavigationServer::get_singleton()->region_set_enabled(region, enabled);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_instance.is_valid()) {
|
||||
if (!is_enabled()) {
|
||||
if (debug_mesh.is_valid()) {
|
||||
if (debug_mesh->get_surface_count() > 0) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, NavigationServer::get_singleton()->get_debug_navigation_geometry_face_disabled_material()->get_rid());
|
||||
}
|
||||
if (debug_mesh->get_surface_count() > 1) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 1, NavigationServer::get_singleton()->get_debug_navigation_geometry_edge_disabled_material()->get_rid());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug_mesh.is_valid()) {
|
||||
if (debug_mesh->get_surface_count() > 0) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, RID());
|
||||
}
|
||||
if (debug_mesh->get_surface_count() > 1) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 1, RID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
bool NavigationMeshInstance::is_enabled() const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_use_edge_connections(bool p_enabled) {
|
||||
if (use_edge_connections == p_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
use_edge_connections = p_enabled;
|
||||
|
||||
NavigationServer::get_singleton()->region_set_use_edge_connections(region, use_edge_connections);
|
||||
}
|
||||
|
||||
bool NavigationMeshInstance::get_use_edge_connections() const {
|
||||
return use_edge_connections;
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_navigation_layers(uint32_t p_navigation_layers) {
|
||||
navigation_layers = p_navigation_layers;
|
||||
NavigationServer::get_singleton()->region_set_navigation_layers(region, navigation_layers);
|
||||
}
|
||||
|
||||
uint32_t NavigationMeshInstance::get_navigation_layers() const {
|
||||
return navigation_layers;
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_navigation_layer_value(int p_layer_number, bool p_value) {
|
||||
ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
uint32_t _navigation_layers = get_navigation_layers();
|
||||
if (p_value) {
|
||||
_navigation_layers |= 1 << (p_layer_number - 1);
|
||||
} else {
|
||||
_navigation_layers &= ~(1 << (p_layer_number - 1));
|
||||
}
|
||||
set_navigation_layers(_navigation_layers);
|
||||
}
|
||||
|
||||
bool NavigationMeshInstance::get_navigation_layer_value(int p_layer_number) const {
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
|
||||
return get_navigation_layers() & (1 << (p_layer_number - 1));
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_enter_cost(real_t p_enter_cost) {
|
||||
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
|
||||
if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
enter_cost = p_enter_cost;
|
||||
|
||||
NavigationServer::get_singleton()->region_set_enter_cost(region, p_enter_cost);
|
||||
}
|
||||
|
||||
real_t NavigationMeshInstance::get_enter_cost() const {
|
||||
return enter_cost;
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_travel_cost(real_t p_travel_cost) {
|
||||
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
|
||||
if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
travel_cost = p_travel_cost;
|
||||
NavigationServer::get_singleton()->region_set_travel_cost(region, travel_cost);
|
||||
}
|
||||
|
||||
real_t NavigationMeshInstance::get_travel_cost() const {
|
||||
return travel_cost;
|
||||
}
|
||||
|
||||
RID NavigationMeshInstance::get_region_rid() const {
|
||||
return region;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
|
||||
void NavigationMeshInstance::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
Spatial *c = this;
|
||||
while (c) {
|
||||
navigation = Object::cast_to<Navigation>(c);
|
||||
if (navigation) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = c->get_parent_spatial();
|
||||
}
|
||||
|
||||
_region_enter_navigation_map();
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
set_physics_process_internal(true);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
set_physics_process_internal(false);
|
||||
|
||||
_region_update_transform();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
_region_exit_navigation_map();
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_navigation_mesh) {
|
||||
if (navigation_mesh.is_valid()) {
|
||||
navigation_mesh->disconnect(CoreStringNames::get_singleton()->changed, this, "_navigation_mesh_changed");
|
||||
}
|
||||
|
||||
navigation_mesh = p_navigation_mesh;
|
||||
|
||||
if (navigation_mesh.is_valid()) {
|
||||
navigation_mesh->connect(CoreStringNames::get_singleton()->changed, this, "_navigation_mesh_changed");
|
||||
}
|
||||
|
||||
_navigation_mesh_changed();
|
||||
}
|
||||
|
||||
Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const {
|
||||
return navigation_mesh;
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::set_navigation_map(RID p_navigation_map) {
|
||||
if (map_override == p_navigation_map) {
|
||||
return;
|
||||
}
|
||||
|
||||
map_override = p_navigation_map;
|
||||
|
||||
NavigationServer::get_singleton()->region_set_map(region, map_override);
|
||||
}
|
||||
|
||||
RID NavigationMeshInstance::get_navigation_map() const {
|
||||
if (map_override.is_valid()) {
|
||||
return map_override;
|
||||
} else if (navigation) {
|
||||
return navigation->get_rid();
|
||||
} else if (is_inside_tree()) {
|
||||
return get_world_3d()->get_navigation_map();
|
||||
}
|
||||
return RID();
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::bake_navigation_mesh(bool p_on_thread) {
|
||||
ERR_FAIL_COND_MSG(!get_navigation_mesh().is_valid(), "Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist");
|
||||
if (baking_started) {
|
||||
WARN_PRINT("NavigationMesh baking already started. Wait for it to finish.");
|
||||
return;
|
||||
}
|
||||
baking_started = true;
|
||||
|
||||
navigation_mesh->clear();
|
||||
|
||||
if (p_on_thread && OS::get_singleton()->can_use_threads()) {
|
||||
Ref<FuncRef> f;
|
||||
f.instance();
|
||||
f->set_instance(this);
|
||||
f->set_function("_bake_finished");
|
||||
|
||||
NavigationMeshGenerator::get_singleton()->parse_and_bake_3d(navigation_mesh, this, f);
|
||||
} else {
|
||||
Ref<NavigationMeshSourceGeometryData3D> source_geometry_data = NavigationMeshGenerator::get_singleton()->parse_3d_source_geometry_data(navigation_mesh, this);
|
||||
NavigationMeshGenerator::get_singleton()->bake_3d_from_source_geometry_data(navigation_mesh, source_geometry_data);
|
||||
_bake_finished(navigation_mesh);
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::_bake_finished(Ref<NavigationMesh> p_navigation_mesh) {
|
||||
baking_started = false;
|
||||
set_navigation_mesh(p_navigation_mesh);
|
||||
emit_signal("bake_finished");
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::_navigation_mesh_changed() {
|
||||
NavigationServer::get_singleton()->region_set_navigation_mesh(region, navigation_mesh);
|
||||
|
||||
update_gizmos();
|
||||
update_configuration_warning();
|
||||
|
||||
emit_signal("navigation_mesh_changed");
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (is_inside_tree() && NavigationServer::get_singleton()->get_debug_navigation_enabled()) {
|
||||
if (navigation_mesh.is_valid()) {
|
||||
_update_debug_mesh();
|
||||
_update_debug_edge_connections_mesh();
|
||||
} else {
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
if (debug_edge_connections_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void NavigationMeshInstance::_navigation_map_changed(RID p_map) {
|
||||
if (is_inside_tree() && p_map == get_world_3d()->get_navigation_map()) {
|
||||
_update_debug_edge_connections_mesh();
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
String NavigationMeshInstance::get_configuration_warning() const {
|
||||
if (!is_visible_in_tree() || !is_inside_tree()) {
|
||||
return String();
|
||||
}
|
||||
|
||||
if (!navigation_mesh.is_valid()) {
|
||||
return TTR("A NavigationMesh resource must be set or created for this node to work.");
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationMeshInstance::set_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationMeshInstance::is_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_edge_connections", "enabled"), &NavigationMeshInstance::set_use_edge_connections);
|
||||
ClassDB::bind_method(D_METHOD("get_use_edge_connections"), &NavigationMeshInstance::get_use_edge_connections);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navigation_mesh"), &NavigationMeshInstance::set_navigation_mesh);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationMeshInstance::get_navigation_mesh);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationMeshInstance::set_navigation_map);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationMeshInstance::get_navigation_map);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationMeshInstance::set_navigation_layers);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationMeshInstance::get_navigation_layers);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationMeshInstance::set_navigation_layer_value);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationMeshInstance::get_navigation_layer_value);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationMeshInstance::set_enter_cost);
|
||||
ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationMeshInstance::get_enter_cost);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationMeshInstance::set_travel_cost);
|
||||
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationMeshInstance::get_travel_cost);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_region_rid"), &NavigationMeshInstance::get_region_rid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("bake_navigation_mesh", "on_thread"), &NavigationMeshInstance::bake_navigation_mesh, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("_bake_finished"), &NavigationMeshInstance::_bake_finished);
|
||||
ClassDB::bind_method(D_METHOD("_navigation_mesh_changed"), &NavigationMeshInstance::_navigation_mesh_changed);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ClassDB::bind_method(D_METHOD("_update_debug_mesh"), &NavigationMeshInstance::_update_debug_mesh);
|
||||
ClassDB::bind_method(D_METHOD("_update_debug_edge_connections_mesh"), &NavigationMeshInstance::_update_debug_edge_connections_mesh);
|
||||
ClassDB::bind_method(D_METHOD("_navigation_map_changed"), &NavigationMeshInstance::_navigation_map_changed);
|
||||
#endif
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_edge_connections"), "set_use_edge_connections", "get_use_edge_connections");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "enter_cost"), "set_enter_cost", "get_enter_cost");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "travel_cost"), "set_travel_cost", "get_travel_cost");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("navigation_mesh_changed"));
|
||||
ADD_SIGNAL(MethodInfo("bake_finished"));
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
//Renamed after 4.0
|
||||
bool NavigationMeshInstance::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (p_name == "navmesh") {
|
||||
set_navigation_mesh(p_value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NavigationMeshInstance::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (p_name == "navmesh") {
|
||||
r_ret = get_navigation_mesh();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
void NavigationMeshInstance::_changed_callback(Object *p_changed, const char *p_prop) {
|
||||
update_gizmos();
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
NavigationMeshInstance::NavigationMeshInstance() {
|
||||
set_notify_transform(true);
|
||||
|
||||
navigation = nullptr;
|
||||
use_edge_connections = true;
|
||||
|
||||
enter_cost = 0.0;
|
||||
travel_cost = 1.0;
|
||||
|
||||
navigation_layers = 1;
|
||||
|
||||
baking_started = false;
|
||||
|
||||
region = NavigationServer::get_singleton()->region_create();
|
||||
NavigationServer::get_singleton()->region_set_owner_id(region, get_instance_id());
|
||||
NavigationServer::get_singleton()->region_set_enter_cost(region, get_enter_cost());
|
||||
NavigationServer::get_singleton()->region_set_travel_cost(region, get_travel_cost());
|
||||
enabled = true;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
NavigationServer::get_singleton()->connect("map_changed", this, "_navigation_map_changed");
|
||||
NavigationServer::get_singleton()->connect("navigation_debug_changed", this, "_update_debug_mesh");
|
||||
NavigationServer::get_singleton()->connect("navigation_debug_changed", this, "_update_debug_edge_connections_mesh");
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
NavigationMeshInstance::~NavigationMeshInstance() {
|
||||
if (navigation_mesh.is_valid()) {
|
||||
navigation_mesh->disconnect(CoreStringNames::get_singleton()->changed, this, "_navigation_mesh_changed");
|
||||
}
|
||||
|
||||
ERR_FAIL_NULL(NavigationServer::get_singleton());
|
||||
NavigationServer::get_singleton()->free(region);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
NavigationServer::get_singleton()->disconnect("map_changed", this, "_navigation_map_changed");
|
||||
NavigationServer::get_singleton()->disconnect("navigation_debug_changed", this, "_update_debug_mesh");
|
||||
NavigationServer::get_singleton()->disconnect("navigation_debug_changed", this, "_update_debug_edge_connections_mesh");
|
||||
|
||||
ERR_FAIL_NULL(RenderingServer::get_singleton());
|
||||
|
||||
if (debug_instance.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(debug_instance);
|
||||
}
|
||||
if (debug_mesh.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(debug_mesh->get_rid());
|
||||
}
|
||||
if (debug_edge_connections_instance.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(debug_edge_connections_instance);
|
||||
}
|
||||
if (debug_edge_connections_mesh.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(debug_edge_connections_mesh->get_rid());
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::_region_enter_navigation_map() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
RID map = get_navigation_map();
|
||||
|
||||
NavigationServer::get_singleton()->region_set_map(region, map);
|
||||
}
|
||||
|
||||
current_global_transform = get_global_transform();
|
||||
NavigationServer::get_singleton()->region_set_transform(region, current_global_transform);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (NavigationServer::get_singleton()->get_debug_navigation_enabled()) {
|
||||
_update_debug_mesh();
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::_region_exit_navigation_map() {
|
||||
NavigationServer::get_singleton()->region_set_map(region, RID());
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
|
||||
if (debug_edge_connections_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
void NavigationMeshInstance::_region_update_transform() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Transform new_global_transform = get_global_transform();
|
||||
|
||||
if (current_global_transform != new_global_transform) {
|
||||
current_global_transform = new_global_transform;
|
||||
|
||||
NavigationServer::get_singleton()->region_set_transform(region, current_global_transform);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_transform(debug_instance, current_global_transform);
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void NavigationMeshInstance::_update_debug_mesh() {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
// don't update inside Editor as node 3d gizmo takes care of this
|
||||
// as collisions and selections for Editor Viewport need to be updated
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NavigationServer::get_singleton()->get_debug_navigation_enabled()) {
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!navigation_mesh.is_valid()) {
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!debug_instance.is_valid()) {
|
||||
debug_instance = RenderingServer::get_singleton()->instance_create();
|
||||
}
|
||||
|
||||
if (!debug_mesh.is_valid()) {
|
||||
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
|
||||
}
|
||||
|
||||
debug_mesh->clear_surfaces();
|
||||
|
||||
PoolVector<Vector3> vertices = navigation_mesh->get_vertices();
|
||||
if (vertices.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int polygon_count = navigation_mesh->get_polygon_count();
|
||||
if (polygon_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled_geometry_face_random_color = NavigationServer::get_singleton()->get_debug_navigation_enable_geometry_face_random_color();
|
||||
bool enabled_edge_lines = NavigationServer::get_singleton()->get_debug_navigation_enable_edge_lines();
|
||||
|
||||
int vertex_count = 0;
|
||||
int line_count = 0;
|
||||
|
||||
for (int i = 0; i < polygon_count; i++) {
|
||||
const Vector<int> &polygon = navigation_mesh->get_polygon(i);
|
||||
int polygon_size = polygon.size();
|
||||
if (polygon_size < 3) {
|
||||
continue;
|
||||
}
|
||||
line_count += polygon_size * 2;
|
||||
vertex_count += (polygon_size - 2) * 3;
|
||||
}
|
||||
|
||||
Vector<Vector3> face_vertex_array;
|
||||
face_vertex_array.resize(vertex_count);
|
||||
|
||||
Vector<Color> face_color_array;
|
||||
if (enabled_geometry_face_random_color) {
|
||||
face_color_array.resize(vertex_count);
|
||||
}
|
||||
|
||||
Vector<Vector3> line_vertex_array;
|
||||
if (enabled_edge_lines) {
|
||||
line_vertex_array.resize(line_count);
|
||||
}
|
||||
|
||||
Color debug_navigation_geometry_face_color = NavigationServer::get_singleton()->get_debug_navigation_geometry_face_color();
|
||||
|
||||
RandomPCG rand;
|
||||
Color polygon_color = debug_navigation_geometry_face_color;
|
||||
|
||||
int face_vertex_index = 0;
|
||||
int line_vertex_index = 0;
|
||||
|
||||
Vector3 *face_vertex_array_ptrw = face_vertex_array.ptrw();
|
||||
Color *face_color_array_ptrw = face_color_array.ptrw();
|
||||
Vector3 *line_vertex_array_ptrw = line_vertex_array.ptrw();
|
||||
|
||||
for (int polygon_index = 0; polygon_index < polygon_count; polygon_index++) {
|
||||
const Vector<int> &polygon_indices = navigation_mesh->get_polygon(polygon_index);
|
||||
int polygon_indices_size = polygon_indices.size();
|
||||
if (polygon_indices_size < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enabled_geometry_face_random_color) {
|
||||
// Generate the polygon color, slightly randomly modified from the settings one.
|
||||
polygon_color.set_hsv(debug_navigation_geometry_face_color.get_h() + rand.random(-1.0, 1.0) * 0.1, debug_navigation_geometry_face_color.get_s(), debug_navigation_geometry_face_color.get_v() + rand.random(-1.0, 1.0) * 0.2);
|
||||
polygon_color.a = debug_navigation_geometry_face_color.a;
|
||||
}
|
||||
|
||||
for (int polygon_indices_index = 0; polygon_indices_index < polygon_indices_size - 2; polygon_indices_index++) {
|
||||
face_vertex_array_ptrw[face_vertex_index] = vertices[polygon_indices[0]];
|
||||
face_vertex_array_ptrw[face_vertex_index + 1] = vertices[polygon_indices[polygon_indices_index + 1]];
|
||||
face_vertex_array_ptrw[face_vertex_index + 2] = vertices[polygon_indices[polygon_indices_index + 2]];
|
||||
if (enabled_geometry_face_random_color) {
|
||||
face_color_array_ptrw[face_vertex_index] = polygon_color;
|
||||
face_color_array_ptrw[face_vertex_index + 1] = polygon_color;
|
||||
face_color_array_ptrw[face_vertex_index + 2] = polygon_color;
|
||||
}
|
||||
face_vertex_index += 3;
|
||||
}
|
||||
|
||||
if (enabled_edge_lines) {
|
||||
for (int polygon_indices_index = 0; polygon_indices_index < polygon_indices_size; polygon_indices_index++) {
|
||||
line_vertex_array_ptrw[line_vertex_index] = vertices[polygon_indices[polygon_indices_index]];
|
||||
line_vertex_index += 1;
|
||||
if (polygon_indices_index + 1 == polygon_indices_size) {
|
||||
line_vertex_array_ptrw[line_vertex_index] = vertices[polygon_indices[0]];
|
||||
line_vertex_index += 1;
|
||||
} else {
|
||||
line_vertex_array_ptrw[line_vertex_index] = vertices[polygon_indices[polygon_indices_index + 1]];
|
||||
line_vertex_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<SpatialMaterial> face_material = NavigationServer::get_singleton()->get_debug_navigation_geometry_face_material();
|
||||
|
||||
Array face_mesh_array;
|
||||
face_mesh_array.resize(Mesh::ARRAY_MAX);
|
||||
face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array;
|
||||
if (enabled_geometry_face_random_color) {
|
||||
face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array;
|
||||
}
|
||||
debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array);
|
||||
debug_mesh->surface_set_material(0, face_material);
|
||||
|
||||
if (enabled_edge_lines) {
|
||||
Ref<SpatialMaterial> line_material = NavigationServer::get_singleton()->get_debug_navigation_geometry_edge_material();
|
||||
|
||||
Array line_mesh_array;
|
||||
line_mesh_array.resize(Mesh::ARRAY_MAX);
|
||||
line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array;
|
||||
debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array);
|
||||
debug_mesh->surface_set_material(1, line_material);
|
||||
}
|
||||
|
||||
RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
|
||||
if (is_inside_tree()) {
|
||||
RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
|
||||
RS::get_singleton()->instance_set_transform(debug_instance, current_global_transform);
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
|
||||
}
|
||||
if (!is_enabled()) {
|
||||
if (debug_mesh.is_valid()) {
|
||||
if (debug_mesh->get_surface_count() > 0) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, NavigationServer::get_singleton()->get_debug_navigation_geometry_face_disabled_material()->get_rid());
|
||||
}
|
||||
if (debug_mesh->get_surface_count() > 1) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 1, NavigationServer::get_singleton()->get_debug_navigation_geometry_edge_disabled_material()->get_rid());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug_mesh.is_valid()) {
|
||||
if (debug_mesh->get_surface_count() > 0) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 0, RID());
|
||||
}
|
||||
if (debug_mesh->get_surface_count() > 1) {
|
||||
RS::get_singleton()->instance_set_surface_material(debug_instance, 1, RID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void NavigationMeshInstance::_update_debug_edge_connections_mesh() {
|
||||
if (!NavigationServer::get_singleton()->get_debug_navigation_enabled()) {
|
||||
if (debug_edge_connections_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!use_edge_connections || !NavigationServer::get_singleton()->map_get_use_edge_connections(get_world_3d()->get_navigation_map())) {
|
||||
if (debug_edge_connections_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!navigation_mesh.is_valid()) {
|
||||
if (debug_edge_connections_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!debug_edge_connections_instance.is_valid()) {
|
||||
debug_edge_connections_instance = RenderingServer::get_singleton()->instance_create();
|
||||
}
|
||||
|
||||
if (!debug_edge_connections_mesh.is_valid()) {
|
||||
debug_edge_connections_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
|
||||
}
|
||||
|
||||
debug_edge_connections_mesh->clear_surfaces();
|
||||
|
||||
float edge_connection_margin = NavigationServer::get_singleton()->map_get_edge_connection_margin(get_world_3d()->get_navigation_map());
|
||||
float half_edge_connection_margin = edge_connection_margin * 0.5;
|
||||
int connections_count = NavigationServer::get_singleton()->region_get_connections_count(region);
|
||||
|
||||
if (connections_count == 0) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<Vector3> vertex_array;
|
||||
//vertex_array.resize(connections_count * 6);
|
||||
|
||||
for (int i = 0; i < connections_count; i++) {
|
||||
Vector3 connection_pathway_start = NavigationServer::get_singleton()->region_get_connection_pathway_start(region, i);
|
||||
Vector3 connection_pathway_end = NavigationServer::get_singleton()->region_get_connection_pathway_end(region, i);
|
||||
|
||||
Vector3 direction_start_end = connection_pathway_start.direction_to(connection_pathway_end);
|
||||
Vector3 direction_end_start = connection_pathway_end.direction_to(connection_pathway_start);
|
||||
|
||||
Vector3 start_right_dir = direction_start_end.cross(Vector3(0, 1, 0));
|
||||
Vector3 start_left_dir = -start_right_dir;
|
||||
|
||||
Vector3 end_right_dir = direction_end_start.cross(Vector3(0, 1, 0));
|
||||
Vector3 end_left_dir = -end_right_dir;
|
||||
|
||||
Vector3 left_start_pos = connection_pathway_start + (start_left_dir * half_edge_connection_margin);
|
||||
Vector3 right_start_pos = connection_pathway_start + (start_right_dir * half_edge_connection_margin);
|
||||
Vector3 left_end_pos = connection_pathway_end + (end_right_dir * half_edge_connection_margin);
|
||||
Vector3 right_end_pos = connection_pathway_end + (end_left_dir * half_edge_connection_margin);
|
||||
|
||||
vertex_array.push_back(right_end_pos);
|
||||
vertex_array.push_back(left_start_pos);
|
||||
vertex_array.push_back(right_start_pos);
|
||||
|
||||
vertex_array.push_back(left_end_pos);
|
||||
vertex_array.push_back(right_end_pos);
|
||||
vertex_array.push_back(right_start_pos);
|
||||
}
|
||||
|
||||
if (vertex_array.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<SpatialMaterial> edge_connections_material = NavigationServer::get_singleton()->get_debug_navigation_edge_connections_material();
|
||||
|
||||
Array mesh_array;
|
||||
mesh_array.resize(Mesh::ARRAY_MAX);
|
||||
mesh_array[Mesh::ARRAY_VERTEX] = vertex_array;
|
||||
|
||||
debug_edge_connections_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mesh_array);
|
||||
debug_edge_connections_mesh->surface_set_material(0, edge_connections_material);
|
||||
|
||||
RS::get_singleton()->instance_set_base(debug_edge_connections_instance, debug_edge_connections_mesh->get_rid());
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, is_visible_in_tree());
|
||||
if (is_inside_tree()) {
|
||||
RS::get_singleton()->instance_set_scenario(debug_edge_connections_instance, get_world_3d()->get_scenario());
|
||||
}
|
||||
|
||||
bool enable_edge_connections = NavigationServer::get_singleton()->get_debug_navigation_enable_edge_connections();
|
||||
if (!enable_edge_connections) {
|
||||
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
@ -1,127 +0,0 @@
|
||||
#ifndef NAVIGATION_MESH_INSTANCE_H
|
||||
#define NAVIGATION_MESH_INSTANCE_H
|
||||
/*************************************************************************/
|
||||
/* navigation_mesh_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/os/thread.h"
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class Mesh;
|
||||
class Navigation;
|
||||
class NavigationMesh;
|
||||
|
||||
class NavigationMeshInstance : public Spatial {
|
||||
GDCLASS(NavigationMeshInstance, Spatial);
|
||||
|
||||
bool enabled;
|
||||
bool use_edge_connections;
|
||||
|
||||
RID region;
|
||||
RID map_override;
|
||||
Ref<NavigationMesh> navigation_mesh;
|
||||
|
||||
Transform current_global_transform;
|
||||
|
||||
real_t enter_cost;
|
||||
real_t travel_cost;
|
||||
|
||||
uint32_t navigation_layers;
|
||||
|
||||
Navigation *navigation;
|
||||
|
||||
bool baking_started;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
RID debug_instance;
|
||||
RID debug_edge_connections_instance;
|
||||
Ref<ArrayMesh> debug_mesh;
|
||||
Ref<ArrayMesh> debug_edge_connections_mesh;
|
||||
|
||||
private:
|
||||
void _update_debug_mesh();
|
||||
void _update_debug_edge_connections_mesh();
|
||||
void _navigation_map_changed(RID p_map);
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
void _changed_callback(Object *p_changed, const char *p_prop);
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
public:
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
|
||||
void set_use_edge_connections(bool p_enabled);
|
||||
bool get_use_edge_connections() const;
|
||||
|
||||
void set_navigation_layers(uint32_t p_navigation_layers);
|
||||
uint32_t get_navigation_layers() const;
|
||||
|
||||
void set_navigation_layer_value(int p_layer_number, bool p_value);
|
||||
bool get_navigation_layer_value(int p_layer_number) const;
|
||||
|
||||
void set_enter_cost(real_t p_enter_cost);
|
||||
real_t get_enter_cost() const;
|
||||
|
||||
void set_travel_cost(real_t p_travel_cost);
|
||||
real_t get_travel_cost() const;
|
||||
|
||||
void set_navigation_mesh(const Ref<NavigationMesh> &p_navigation_mesh);
|
||||
Ref<NavigationMesh> get_navigation_mesh() const;
|
||||
|
||||
void set_navigation_map(RID p_navigation_map);
|
||||
RID get_navigation_map() const;
|
||||
|
||||
RID get_region_rid() const;
|
||||
|
||||
/// Bakes the navigation mesh; once done, automatically
|
||||
/// sets the new navigation mesh and emits a signal
|
||||
void bake_navigation_mesh(bool p_on_thread = true);
|
||||
void _bake_finished(Ref<NavigationMesh> p_navigation_mesh);
|
||||
void _navigation_mesh_changed();
|
||||
|
||||
String get_configuration_warning() const;
|
||||
|
||||
NavigationMeshInstance();
|
||||
~NavigationMeshInstance();
|
||||
|
||||
private:
|
||||
void _region_enter_navigation_map();
|
||||
void _region_exit_navigation_map();
|
||||
void _region_update_transform();
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_MESH_INSTANCE_H
|
@ -157,7 +157,6 @@
|
||||
#include "scene/resources/mesh/multimesh.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation_2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
#include "scene/resources/navigation_2d/navigation_polygon.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
#include "scene/resources/material/particles_material.h"
|
||||
@ -189,11 +188,6 @@
|
||||
#include "scene/3d/listener.h"
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "scene/3d/multimesh_instance.h"
|
||||
#include "scene/3d/navigation.h"
|
||||
#include "scene/3d/navigation_agent.h"
|
||||
#include "scene/3d/navigation_geometry_parser_3d.h"
|
||||
#include "scene/3d/navigation_link_3d.h"
|
||||
#include "scene/3d/navigation_mesh_instance.h"
|
||||
#include "scene/3d/occluder.h"
|
||||
#include "scene/3d/path.h"
|
||||
#include "scene/3d/portal.h"
|
||||
@ -434,9 +428,7 @@ void register_scene_types() {
|
||||
ClassDB::register_class<ReflectionProbe>();
|
||||
ClassDB::register_class<CPUParticles>();
|
||||
ClassDB::register_class<Position3D>();
|
||||
ClassDB::register_class<NavigationMeshInstance>();
|
||||
ClassDB::register_class<NavigationMesh>();
|
||||
ClassDB::register_class<Navigation>();
|
||||
ClassDB::register_class<Room>();
|
||||
ClassDB::register_class<RoomGroup>();
|
||||
ClassDB::register_class<RoomManager>();
|
||||
@ -459,12 +451,6 @@ void register_scene_types() {
|
||||
ClassDB::register_class<WorldEnvironment3D>();
|
||||
ClassDB::register_class<RemoteTransform>();
|
||||
|
||||
|
||||
ClassDB::register_class<Navigation>();
|
||||
ClassDB::register_class<NavigationMeshInstance>();
|
||||
ClassDB::register_class<NavigationAgent>();
|
||||
ClassDB::register_class<NavigationLink3D>();
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
#endif
|
||||
@ -643,11 +629,6 @@ void register_scene_types() {
|
||||
ClassDB::register_class<NavigationMeshSourceGeometryData2D>();
|
||||
ClassDB::register_class<NavigationGeometryParser2D>();
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
ClassDB::register_class<NavigationGeometryParser3D>();
|
||||
ClassDB::register_class<NavigationMeshSourceGeometryData3D>();
|
||||
#endif
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
ClassDB::register_virtual_class<SceneState>();
|
||||
|
@ -1,183 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* navigation_mesh_source_geometry_data_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "navigation_mesh_source_geometry_data_3d.h"
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::set_vertices(const PoolRealArray &p_vertices) {
|
||||
vertices = p_vertices;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::set_indices(const PoolIntArray &p_indices) {
|
||||
indices = p_indices;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::clear() {
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::_add_vertex(const Vector3 &p_vec3) {
|
||||
vertices.push_back(p_vec3.x);
|
||||
vertices.push_back(p_vec3.y);
|
||||
vertices.push_back(p_vec3.z);
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform) {
|
||||
int current_vertex_count;
|
||||
for (int i = 0; i < p_mesh->get_surface_count(); i++) {
|
||||
current_vertex_count = vertices.size() / 3;
|
||||
|
||||
if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int index_count = 0;
|
||||
if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) {
|
||||
index_count = p_mesh->surface_get_array_index_len(i);
|
||||
} else {
|
||||
index_count = p_mesh->surface_get_array_len(i);
|
||||
}
|
||||
|
||||
ERR_CONTINUE((index_count == 0 || (index_count % 3) != 0));
|
||||
|
||||
int face_count = index_count / 3;
|
||||
|
||||
Array a = p_mesh->surface_get_arrays(i);
|
||||
|
||||
Vector<Vector3> mesh_vertices = a[Mesh::ARRAY_VERTEX];
|
||||
const Vector3 *vr = mesh_vertices.ptr();
|
||||
|
||||
if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) {
|
||||
PoolIntArray mesh_indices = a[Mesh::ARRAY_INDEX];
|
||||
PoolIntArray::Read r = mesh_indices.read();
|
||||
const int *ir = r.ptr();
|
||||
|
||||
for (int j = 0; j < mesh_vertices.size(); j++) {
|
||||
_add_vertex(p_xform.xform(vr[j]));
|
||||
}
|
||||
|
||||
for (int j = 0; j < face_count; j++) {
|
||||
// CCW
|
||||
indices.push_back(current_vertex_count + (ir[j * 3 + 0]));
|
||||
indices.push_back(current_vertex_count + (ir[j * 3 + 2]));
|
||||
indices.push_back(current_vertex_count + (ir[j * 3 + 1]));
|
||||
}
|
||||
} else {
|
||||
face_count = mesh_vertices.size() / 3;
|
||||
for (int j = 0; j < face_count; j++) {
|
||||
_add_vertex(p_xform.xform(vr[j * 3 + 0]));
|
||||
_add_vertex(p_xform.xform(vr[j * 3 + 2]));
|
||||
_add_vertex(p_xform.xform(vr[j * 3 + 1]));
|
||||
|
||||
indices.push_back(current_vertex_count + (j * 3 + 0));
|
||||
indices.push_back(current_vertex_count + (j * 3 + 1));
|
||||
indices.push_back(current_vertex_count + (j * 3 + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::_add_mesh_array(const Array &p_mesh_array, const Transform &p_xform) {
|
||||
Vector<Vector3> mesh_vertices = p_mesh_array[Mesh::ARRAY_VERTEX];
|
||||
const Vector3 *vr = mesh_vertices.ptr();
|
||||
|
||||
PoolIntArray mesh_indices = p_mesh_array[Mesh::ARRAY_INDEX];
|
||||
PoolIntArray::Read r = mesh_indices.read();
|
||||
const int *ir = r.ptr();
|
||||
|
||||
const int face_count = mesh_indices.size() / 3;
|
||||
const int current_vertex_count = vertices.size() / 3;
|
||||
|
||||
for (int j = 0; j < mesh_vertices.size(); j++) {
|
||||
_add_vertex(p_xform.xform(vr[j]));
|
||||
}
|
||||
|
||||
for (int j = 0; j < face_count; j++) {
|
||||
// CCW
|
||||
indices.push_back(current_vertex_count + (ir[j * 3 + 0]));
|
||||
indices.push_back(current_vertex_count + (ir[j * 3 + 2]));
|
||||
indices.push_back(current_vertex_count + (ir[j * 3 + 1]));
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::_add_faces(const PoolVector3Array &p_faces, const Transform &p_xform) {
|
||||
int face_count = p_faces.size() / 3;
|
||||
int current_vertex_count = vertices.size() / 3;
|
||||
|
||||
for (int j = 0; j < face_count; j++) {
|
||||
_add_vertex(p_xform.xform(p_faces[j * 3 + 0]));
|
||||
_add_vertex(p_xform.xform(p_faces[j * 3 + 1]));
|
||||
_add_vertex(p_xform.xform(p_faces[j * 3 + 2]));
|
||||
|
||||
indices.push_back(current_vertex_count + (j * 3 + 0));
|
||||
indices.push_back(current_vertex_count + (j * 3 + 2));
|
||||
indices.push_back(current_vertex_count + (j * 3 + 1));
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform) {
|
||||
ERR_FAIL_COND(!p_mesh.is_valid());
|
||||
_add_mesh(p_mesh, root_node_transform * p_xform);
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::add_mesh_array(const Array &p_mesh_array, const Transform &p_xform) {
|
||||
ERR_FAIL_COND(p_mesh_array.size() != Mesh::ARRAY_MAX);
|
||||
_add_mesh_array(p_mesh_array, root_node_transform * p_xform);
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::add_faces(const PoolVector3Array &p_faces, const Transform &p_xform) {
|
||||
ERR_FAIL_COND(p_faces.size() % 3 != 0);
|
||||
_add_faces(p_faces, root_node_transform * p_xform);
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationMeshSourceGeometryData3D::set_vertices);
|
||||
ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationMeshSourceGeometryData3D::get_vertices);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_indices", "indices"), &NavigationMeshSourceGeometryData3D::set_indices);
|
||||
ClassDB::bind_method(D_METHOD("get_indices"), &NavigationMeshSourceGeometryData3D::get_indices);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("clear"), &NavigationMeshSourceGeometryData3D::clear);
|
||||
ClassDB::bind_method(D_METHOD("has_data"), &NavigationMeshSourceGeometryData3D::has_data);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "xform"), &NavigationMeshSourceGeometryData3D::add_mesh);
|
||||
ClassDB::bind_method(D_METHOD("add_mesh_array", "mesh_array", "xform"), &NavigationMeshSourceGeometryData3D::add_mesh_array);
|
||||
ClassDB::bind_method(D_METHOD("add_faces", "faces", "xform"), &NavigationMeshSourceGeometryData3D::add_faces);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "indices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_indices", "get_indices");
|
||||
}
|
||||
|
||||
NavigationMeshSourceGeometryData3D::NavigationMeshSourceGeometryData3D() {
|
||||
}
|
||||
|
||||
NavigationMeshSourceGeometryData3D::~NavigationMeshSourceGeometryData3D() {
|
||||
clear();
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
#ifndef NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_3D_H
|
||||
#define NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_3D_H
|
||||
|
||||
/**************************************************************************/
|
||||
/* navigation_mesh_source_geometry_data_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "core/object/resource.h"
|
||||
|
||||
#include "core/math/transform.h"
|
||||
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
|
||||
class NavigationMeshSourceGeometryData3D : public Resource {
|
||||
GDCLASS(NavigationMeshSourceGeometryData3D, Resource);
|
||||
|
||||
PoolRealArray vertices;
|
||||
PoolIntArray indices;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
void _add_vertex(const Vector3 &p_vec3);
|
||||
void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform);
|
||||
void _add_mesh_array(const Array &p_array, const Transform &p_xform);
|
||||
void _add_faces(const PoolVector3Array &p_faces, const Transform &p_xform);
|
||||
|
||||
public:
|
||||
// kept root node transform here on the geometry data
|
||||
// if we add this transform to all exposed functions we need to break comp on all functions later
|
||||
// when navigation_mesh changes from global transfrom to relative to navregion
|
||||
// but if it stays here we can just remove it and change the internal functions only
|
||||
Transform root_node_transform;
|
||||
|
||||
void set_vertices(const PoolRealArray &p_vertices);
|
||||
PoolRealArray get_vertices() const { return vertices; }
|
||||
|
||||
void set_indices(const PoolIntArray &p_indices);
|
||||
PoolIntArray get_indices() const { return indices; }
|
||||
|
||||
bool has_data() { return vertices.size() && indices.size(); };
|
||||
void clear();
|
||||
|
||||
void add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform);
|
||||
void add_mesh_array(const Array &p_mesh_array, const Transform &p_xform);
|
||||
void add_faces(const PoolVector3Array &p_faces, const Transform &p_xform);
|
||||
|
||||
NavigationMeshSourceGeometryData3D();
|
||||
~NavigationMeshSourceGeometryData3D();
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_3D_H
|
@ -33,15 +33,9 @@
|
||||
#include "core/config/project_settings.h"
|
||||
|
||||
#include "scene/2d/navigation_geometry_parser_2d.h"
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/3d/navigation_geometry_parser_3d.h"
|
||||
#endif // _3D_DISABLED
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation_2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
NavigationMeshGenerator *NavigationMeshGenerator::singleton = nullptr;
|
||||
|
||||
@ -54,17 +48,6 @@ void NavigationMeshGenerator::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("parse_and_bake_2d", "navigation_polygon", "root_node", "callback"), &NavigationMeshGenerator::parse_and_bake_2d, DEFVAL(Ref<FuncRef>()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_navigation_polygon_baking", "navigation_polygon"), &NavigationMeshGenerator::is_navigation_polygon_baking);
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
ClassDB::bind_method(D_METHOD("register_geometry_parser_3d", "geometry_parser"), &NavigationMeshGenerator::register_geometry_parser_3d);
|
||||
ClassDB::bind_method(D_METHOD("unregister_geometry_parser_3d", "geometry_parser"), &NavigationMeshGenerator::unregister_geometry_parser_3d);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("parse_3d_source_geometry_data", "navigation_mesh", "root_node", "callback"), &NavigationMeshGenerator::parse_3d_source_geometry_data, DEFVAL(Ref<FuncRef>()));
|
||||
ClassDB::bind_method(D_METHOD("bake_3d_from_source_geometry_data", "navigation_mesh", "source_geometry_data", "callback"), &NavigationMeshGenerator::bake_3d_from_source_geometry_data, DEFVAL(Ref<FuncRef>()));
|
||||
ClassDB::bind_method(D_METHOD("parse_and_bake_3d", "navigation_mesh", "root_node", "callback"), &NavigationMeshGenerator::parse_and_bake_3d, DEFVAL(Ref<FuncRef>()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_navigation_mesh_baking", "navigation_mesh"), &NavigationMeshGenerator::is_navigation_mesh_baking);
|
||||
#endif // _3D_DISABLED
|
||||
}
|
||||
|
||||
NavigationMeshGenerator *NavigationMeshGenerator::get_singleton() {
|
||||
|
@ -72,19 +72,6 @@ public:
|
||||
|
||||
virtual bool is_navigation_polygon_baking(Ref<NavigationPolygon> p_navigation_polygon) const = 0;
|
||||
|
||||
// 3D //////////////////////////////
|
||||
#ifndef _3D_DISABLED
|
||||
virtual void register_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser) = 0;
|
||||
virtual void unregister_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser) = 0;
|
||||
|
||||
virtual Ref<NavigationMeshSourceGeometryData3D> parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>()) = 0;
|
||||
virtual void bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Ref<FuncRef> p_callback = Ref<FuncRef>()) = 0;
|
||||
|
||||
virtual void parse_and_bake_3d(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>()) = 0;
|
||||
|
||||
virtual bool is_navigation_mesh_baking(Ref<NavigationMesh> p_navigation_mesh) const = 0;
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
virtual void init();
|
||||
virtual void finish();
|
||||
|
||||
|
@ -4,15 +4,9 @@
|
||||
#include "core/config/project_settings.h"
|
||||
|
||||
#include "scene/2d/navigation_geometry_parser_2d.h"
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/3d/navigation_geometry_parser_3d.h"
|
||||
#endif // _3D_DISABLED
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation_2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/resources/navigation/navigation_mesh_source_geometry_data_3d.h"
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
void NavigationMeshGeneratorDummy::cleanup() {}
|
||||
void NavigationMeshGeneratorDummy::process() {}
|
||||
@ -32,19 +26,3 @@ bool NavigationMeshGeneratorDummy::is_navigation_polygon_baking(Ref<NavigationPo
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3D //////////////////////////////
|
||||
#ifndef _3D_DISABLED
|
||||
void NavigationMeshGeneratorDummy::register_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser) {}
|
||||
void NavigationMeshGeneratorDummy::unregister_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser) {}
|
||||
|
||||
Ref<NavigationMeshSourceGeometryData3D> NavigationMeshGeneratorDummy::parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback) {
|
||||
return Ref<NavigationMeshSourceGeometryData3D>();
|
||||
}
|
||||
void NavigationMeshGeneratorDummy::bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Ref<FuncRef> p_callback) {}
|
||||
|
||||
void NavigationMeshGeneratorDummy::parse_and_bake_3d(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback) {}
|
||||
|
||||
bool NavigationMeshGeneratorDummy::is_navigation_mesh_baking(Ref<NavigationMesh> p_navigation_mesh) const {
|
||||
return false;
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
|
@ -61,19 +61,6 @@ public:
|
||||
virtual void parse_and_bake_2d(Ref<NavigationPolygon> p_navigation_polygon, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
|
||||
virtual bool is_navigation_polygon_baking(Ref<NavigationPolygon> p_navigation_polygon) const;
|
||||
|
||||
// 3D //////////////////////////////
|
||||
#ifndef _3D_DISABLED
|
||||
virtual void register_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser);
|
||||
virtual void unregister_geometry_parser_3d(Ref<NavigationGeometryParser3D> p_geometry_parser);
|
||||
|
||||
virtual Ref<NavigationMeshSourceGeometryData3D> parse_3d_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
virtual void bake_3d_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
|
||||
virtual void parse_and_bake_3d(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node, Ref<FuncRef> p_callback = Ref<FuncRef>());
|
||||
|
||||
virtual bool is_navigation_mesh_baking(Ref<NavigationMesh> p_navigation_mesh) const;
|
||||
#endif // _3D_DISABLED
|
||||
};
|
||||
|
||||
#endif // NAVIGATION_MESH_GENERATOR_DUMMY_H
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "core/config/project_settings.h"
|
||||
#include "navigation/navigation_path_query_parameters_3d.h"
|
||||
#include "navigation/navigation_path_query_result_3d.h"
|
||||
#include "scene/3d/navigation_mesh_instance.h"
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
Loading…
Reference in New Issue
Block a user