diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/navigation_region_2d.cpp | 35 | ||||
-rw-r--r-- | scene/2d/navigation_region_2d.h | 3 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 2 | ||||
-rw-r--r-- | scene/resources/navigation_mesh_source_geometry_data_2d.cpp | 138 | ||||
-rw-r--r-- | scene/resources/navigation_mesh_source_geometry_data_2d.h | 78 | ||||
-rw-r--r-- | scene/resources/navigation_polygon.cpp | 132 | ||||
-rw-r--r-- | scene/resources/navigation_polygon.h | 51 |
7 files changed, 433 insertions, 6 deletions
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 670a2c641c..706b26bd05 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -179,10 +179,6 @@ void NavigationRegion2D::_notification(int p_what) { } void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_navigation_polygon) { - if (p_navigation_polygon == navigation_polygon) { - return; - } - if (navigation_polygon.is_valid()) { navigation_polygon->disconnect_changed(callable_mp(this, &NavigationRegion2D::_navigation_polygon_changed)); } @@ -226,6 +222,32 @@ RID NavigationRegion2D::get_navigation_map() const { return RID(); } +void NavigationRegion2D::bake_navigation_polygon(bool p_on_thread) { + ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "The SceneTree can only be parsed on the main thread. Call this function from the main thread or use call_deferred()."); + ERR_FAIL_COND_MSG(!navigation_polygon.is_valid(), "Baking the navigation polygon requires a valid `NavigationPolygon` resource."); + + Ref<NavigationMeshSourceGeometryData2D> source_geometry_data; + source_geometry_data.instantiate(); + + NavigationServer2D::get_singleton()->parse_source_geometry_data(navigation_polygon, source_geometry_data, this); + + if (p_on_thread) { + NavigationServer2D::get_singleton()->bake_from_source_geometry_data_async(navigation_polygon, source_geometry_data, callable_mp(this, &NavigationRegion2D::_bake_finished).bind(navigation_polygon)); + } else { + NavigationServer2D::get_singleton()->bake_from_source_geometry_data(navigation_polygon, source_geometry_data, callable_mp(this, &NavigationRegion2D::_bake_finished).bind(navigation_polygon)); + } +} + +void NavigationRegion2D::_bake_finished(Ref<NavigationPolygon> p_navigation_polygon) { + if (!Thread::is_main_thread()) { + call_deferred(SNAME("_bake_finished"), p_navigation_polygon); + return; + } + + set_navigation_polygon(p_navigation_polygon); + emit_signal(SNAME("bake_finished")); +} + void NavigationRegion2D::_navigation_polygon_changed() { if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) { queue_redraw(); @@ -290,6 +312,8 @@ void NavigationRegion2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationRegion2D::set_travel_cost); ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion2D::get_travel_cost); + ClassDB::bind_method(D_METHOD("bake_navigation_polygon", "on_thread"), &NavigationRegion2D::bake_navigation_polygon, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("_navigation_polygon_changed"), &NavigationRegion2D::_navigation_polygon_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_polygon", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon"); @@ -300,6 +324,9 @@ void NavigationRegion2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "constrain_avoidance"), "set_constrain_avoidance", "get_constrain_avoidance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "avoidance_layers", PROPERTY_HINT_LAYERS_AVOIDANCE), "set_avoidance_layers", "get_avoidance_layers"); + + ADD_SIGNAL(MethodInfo("navigation_polygon_changed")); + ADD_SIGNAL(MethodInfo("bake_finished")); } #ifndef DISABLE_DEPRECATED diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 0a48b10f47..36e889877a 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -114,6 +114,9 @@ public: PackedStringArray get_configuration_warnings() const override; + void bake_navigation_polygon(bool p_on_thread); + void _bake_finished(Ref<NavigationPolygon> p_navigation_polygon); + NavigationRegion2D(); ~NavigationRegion2D(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 19c4b62eaf..03085edb86 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -172,6 +172,7 @@ #include "scene/resources/mesh_texture.h" #include "scene/resources/multimesh.h" #include "scene/resources/navigation_mesh.h" +#include "scene/resources/navigation_mesh_source_geometry_data_2d.h" #include "scene/resources/navigation_mesh_source_geometry_data_3d.h" #include "scene/resources/navigation_polygon.h" #include "scene/resources/packed_scene.h" @@ -956,6 +957,7 @@ void register_scene_types() { GDREGISTER_CLASS(PathFollow2D); GDREGISTER_CLASS(NavigationMesh); + GDREGISTER_CLASS(NavigationMeshSourceGeometryData2D); GDREGISTER_CLASS(NavigationMeshSourceGeometryData3D); GDREGISTER_CLASS(NavigationPolygon); GDREGISTER_CLASS(NavigationRegion2D); diff --git a/scene/resources/navigation_mesh_source_geometry_data_2d.cpp b/scene/resources/navigation_mesh_source_geometry_data_2d.cpp new file mode 100644 index 0000000000..3dde6dbff6 --- /dev/null +++ b/scene/resources/navigation_mesh_source_geometry_data_2d.cpp @@ -0,0 +1,138 @@ +/**************************************************************************/ +/* navigation_mesh_source_geometry_data_2d.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_2d.h" + +#include "scene/resources/mesh.h" + +void NavigationMeshSourceGeometryData2D::clear() { + traversable_outlines.clear(); + obstruction_outlines.clear(); +} + +void NavigationMeshSourceGeometryData2D::_set_traversable_outlines(const Vector<Vector<Vector2>> &p_traversable_outlines) { + traversable_outlines = p_traversable_outlines; +} + +void NavigationMeshSourceGeometryData2D::_set_obstruction_outlines(const Vector<Vector<Vector2>> &p_obstruction_outlines) { + obstruction_outlines = p_obstruction_outlines; +} + +void NavigationMeshSourceGeometryData2D::_add_traversable_outline(const Vector<Vector2> &p_shape_outline) { + if (p_shape_outline.size() > 1) { + traversable_outlines.push_back(p_shape_outline); + } +} + +void NavigationMeshSourceGeometryData2D::_add_obstruction_outline(const Vector<Vector2> &p_shape_outline) { + if (p_shape_outline.size() > 1) { + obstruction_outlines.push_back(p_shape_outline); + } +} + +void NavigationMeshSourceGeometryData2D::set_traversable_outlines(const TypedArray<Vector<Vector2>> &p_traversable_outlines) { + traversable_outlines.resize(p_traversable_outlines.size()); + for (int i = 0; i < p_traversable_outlines.size(); i++) { + traversable_outlines.write[i] = p_traversable_outlines[i]; + } +} + +TypedArray<Vector<Vector2>> NavigationMeshSourceGeometryData2D::get_traversable_outlines() const { + TypedArray<Vector<Vector2>> typed_array_traversable_outlines; + typed_array_traversable_outlines.resize(traversable_outlines.size()); + for (int i = 0; i < typed_array_traversable_outlines.size(); i++) { + typed_array_traversable_outlines[i] = traversable_outlines[i]; + } + + return typed_array_traversable_outlines; +} + +void NavigationMeshSourceGeometryData2D::set_obstruction_outlines(const TypedArray<Vector<Vector2>> &p_obstruction_outlines) { + obstruction_outlines.resize(p_obstruction_outlines.size()); + for (int i = 0; i < p_obstruction_outlines.size(); i++) { + obstruction_outlines.write[i] = p_obstruction_outlines[i]; + } +} + +TypedArray<Vector<Vector2>> NavigationMeshSourceGeometryData2D::get_obstruction_outlines() const { + TypedArray<Vector<Vector2>> typed_array_obstruction_outlines; + typed_array_obstruction_outlines.resize(obstruction_outlines.size()); + for (int i = 0; i < typed_array_obstruction_outlines.size(); i++) { + typed_array_obstruction_outlines[i] = obstruction_outlines[i]; + } + + return typed_array_obstruction_outlines; +} + +void NavigationMeshSourceGeometryData2D::add_traversable_outline(const PackedVector2Array &p_shape_outline) { + if (p_shape_outline.size() > 1) { + Vector<Vector2> traversable_outline; + traversable_outline.resize(p_shape_outline.size()); + for (int i = 0; i < p_shape_outline.size(); i++) { + traversable_outline.write[i] = p_shape_outline[i]; + } + traversable_outlines.push_back(traversable_outline); + } +} + +void NavigationMeshSourceGeometryData2D::add_obstruction_outline(const PackedVector2Array &p_shape_outline) { + if (p_shape_outline.size() > 1) { + Vector<Vector2> obstruction_outline; + obstruction_outline.resize(p_shape_outline.size()); + for (int i = 0; i < p_shape_outline.size(); i++) { + obstruction_outline.write[i] = p_shape_outline[i]; + } + obstruction_outlines.push_back(obstruction_outline); + } +} + +void NavigationMeshSourceGeometryData2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("clear"), &NavigationMeshSourceGeometryData2D::clear); + ClassDB::bind_method(D_METHOD("has_data"), &NavigationMeshSourceGeometryData2D::has_data); + + ClassDB::bind_method(D_METHOD("set_traversable_outlines", "traversable_outlines"), &NavigationMeshSourceGeometryData2D::set_traversable_outlines); + ClassDB::bind_method(D_METHOD("get_traversable_outlines"), &NavigationMeshSourceGeometryData2D::get_traversable_outlines); + + ClassDB::bind_method(D_METHOD("set_obstruction_outlines", "obstruction_outlines"), &NavigationMeshSourceGeometryData2D::set_obstruction_outlines); + ClassDB::bind_method(D_METHOD("get_obstruction_outlines"), &NavigationMeshSourceGeometryData2D::get_obstruction_outlines); + + ClassDB::bind_method(D_METHOD("add_traversable_outline", "shape_outline"), &NavigationMeshSourceGeometryData2D::add_traversable_outline); + ClassDB::bind_method(D_METHOD("add_obstruction_outline", "shape_outline"), &NavigationMeshSourceGeometryData2D::add_obstruction_outline); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "traversable_outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_traversable_outlines", "get_traversable_outlines"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "obstruction_outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_obstruction_outlines", "get_obstruction_outlines"); +} + +NavigationMeshSourceGeometryData2D::NavigationMeshSourceGeometryData2D() { +} + +NavigationMeshSourceGeometryData2D::~NavigationMeshSourceGeometryData2D() { + clear(); +} diff --git a/scene/resources/navigation_mesh_source_geometry_data_2d.h b/scene/resources/navigation_mesh_source_geometry_data_2d.h new file mode 100644 index 0000000000..f26a4e9a2e --- /dev/null +++ b/scene/resources/navigation_mesh_source_geometry_data_2d.h @@ -0,0 +1,78 @@ +/**************************************************************************/ +/* navigation_mesh_source_geometry_data_2d.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_SOURCE_GEOMETRY_DATA_2D_H +#define NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_2D_H + +#include "scene/2d/node_2d.h" +#include "scene/resources/navigation_polygon.h" + +class NavigationMeshSourceGeometryData2D : public Resource { + GDCLASS(NavigationMeshSourceGeometryData2D, Resource); + + Vector<Vector<Vector2>> traversable_outlines; + Vector<Vector<Vector2>> obstruction_outlines; + +protected: + static void _bind_methods(); + +public: + void _set_traversable_outlines(const Vector<Vector<Vector2>> &p_traversable_outlines); + const Vector<Vector<Vector2>> &_get_traversable_outlines() const { return traversable_outlines; } + + void _set_obstruction_outlines(const Vector<Vector<Vector2>> &p_obstruction_outlines); + const Vector<Vector<Vector2>> &_get_obstruction_outlines() const { return obstruction_outlines; } + + void _add_traversable_outline(const Vector<Vector2> &p_shape_outline); + void _add_obstruction_outline(const Vector<Vector2> &p_shape_outline); + + // 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 navmesh changes from global transform to relative to navregion + // but if it stays here we can just remove it and change the internal functions only + Transform2D root_node_transform; + + void set_traversable_outlines(const TypedArray<Vector<Vector2>> &p_traversable_outlines); + TypedArray<Vector<Vector2>> get_traversable_outlines() const; + + void set_obstruction_outlines(const TypedArray<Vector<Vector2>> &p_obstruction_outlines); + TypedArray<Vector<Vector2>> get_obstruction_outlines() const; + + void add_traversable_outline(const PackedVector2Array &p_shape_outline); + void add_obstruction_outline(const PackedVector2Array &p_shape_outline); + + bool has_data() { return traversable_outlines.size(); }; + void clear(); + + NavigationMeshSourceGeometryData2D(); + ~NavigationMeshSourceGeometryData2D(); +}; + +#endif // NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_2D_H diff --git a/scene/resources/navigation_polygon.cpp b/scene/resources/navigation_polygon.cpp index e521bfb2e0..6c0e1343ec 100644 --- a/scene/resources/navigation_polygon.cpp +++ b/scene/resources/navigation_polygon.cpp @@ -32,6 +32,7 @@ #include "core/math/geometry_2d.h" #include "core/os/mutex.h" +#include "servers/navigation_server_2d.h" #include "thirdparty/misc/polypartition.h" @@ -229,7 +230,11 @@ void NavigationPolygon::clear_outlines() { rect_cache_dirty = true; } +#ifndef DISABLE_DEPRECATED void NavigationPolygon::make_polygons_from_outlines() { + WARN_PRINT("Function make_polygons_from_outlines() is deprecated." + "\nUse NavigationServer2D.parse_source_geometry_data() and NavigationServer2D.bake_from_source_geometry_data() instead."); + { MutexLock lock(navigation_mesh_generation); navigation_mesh.unref(); @@ -331,6 +336,7 @@ void NavigationPolygon::make_polygons_from_outlines() { emit_changed(); } +#endif // DISABLE_DEPRECATED void NavigationPolygon::set_cell_size(real_t p_cell_size) { cell_size = p_cell_size; @@ -341,6 +347,69 @@ real_t NavigationPolygon::get_cell_size() const { return cell_size; } +void NavigationPolygon::set_parsed_geometry_type(ParsedGeometryType p_geometry_type) { + ERR_FAIL_INDEX(p_geometry_type, PARSED_GEOMETRY_MAX); + parsed_geometry_type = p_geometry_type; + notify_property_list_changed(); +} + +NavigationPolygon::ParsedGeometryType NavigationPolygon::get_parsed_geometry_type() const { + return parsed_geometry_type; +} + +void NavigationPolygon::set_parsed_collision_mask(uint32_t p_mask) { + parsed_collision_mask = p_mask; +} + +uint32_t NavigationPolygon::get_parsed_collision_mask() const { + return parsed_collision_mask; +} + +void NavigationPolygon::set_parsed_collision_mask_value(int p_layer_number, bool p_value) { + ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); + ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); + uint32_t mask = get_parsed_collision_mask(); + if (p_value) { + mask |= 1 << (p_layer_number - 1); + } else { + mask &= ~(1 << (p_layer_number - 1)); + } + set_parsed_collision_mask(mask); +} + +bool NavigationPolygon::get_parsed_collision_mask_value(int p_layer_number) const { + ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); + ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); + return get_parsed_collision_mask() & (1 << (p_layer_number - 1)); +} + +void NavigationPolygon::set_source_geometry_mode(SourceGeometryMode p_geometry_mode) { + ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX); + source_geometry_mode = p_geometry_mode; + notify_property_list_changed(); +} + +NavigationPolygon::SourceGeometryMode NavigationPolygon::get_source_geometry_mode() const { + return source_geometry_mode; +} + +void NavigationPolygon::set_source_geometry_group_name(StringName p_group_name) { + source_geometry_group_name = p_group_name; +} + +StringName NavigationPolygon::get_source_geometry_group_name() const { + return source_geometry_group_name; +} + +void NavigationPolygon::set_agent_radius(real_t p_value) { + ERR_FAIL_COND(p_value < 0); + agent_radius = p_value; +} + +real_t NavigationPolygon::get_agent_radius() const { + return agent_radius; +} + void NavigationPolygon::_bind_methods() { ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices); ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices); @@ -358,7 +427,9 @@ void NavigationPolygon::_bind_methods() { ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline); ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline); ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines); +#endif // DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons); ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons); @@ -369,10 +440,69 @@ void NavigationPolygon::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationPolygon::set_cell_size); ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationPolygon::get_cell_size); + ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationPolygon::set_parsed_geometry_type); + ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationPolygon::get_parsed_geometry_type); + + ClassDB::bind_method(D_METHOD("set_parsed_collision_mask", "mask"), &NavigationPolygon::set_parsed_collision_mask); + ClassDB::bind_method(D_METHOD("get_parsed_collision_mask"), &NavigationPolygon::get_parsed_collision_mask); + + ClassDB::bind_method(D_METHOD("set_parsed_collision_mask_value", "layer_number", "value"), &NavigationPolygon::set_parsed_collision_mask_value); + ClassDB::bind_method(D_METHOD("get_parsed_collision_mask_value", "layer_number"), &NavigationPolygon::get_parsed_collision_mask_value); + + ClassDB::bind_method(D_METHOD("set_source_geometry_mode", "geometry_mode"), &NavigationPolygon::set_source_geometry_mode); + ClassDB::bind_method(D_METHOD("get_source_geometry_mode"), &NavigationPolygon::get_source_geometry_mode); + + ClassDB::bind_method(D_METHOD("set_source_geometry_group_name", "group_name"), &NavigationPolygon::set_source_geometry_group_name); + ClassDB::bind_method(D_METHOD("get_source_geometry_group_name"), &NavigationPolygon::get_source_geometry_group_name); + + ClassDB::bind_method(D_METHOD("set_agent_radius", "agent_radius"), &NavigationPolygon::set_agent_radius); + ClassDB::bind_method(D_METHOD("get_agent_radius"), &NavigationPolygon::get_agent_radius); + ClassDB::bind_method(D_METHOD("clear"), &NavigationPolygon::clear); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:px"), "set_cell_size", "get_cell_size"); + + ADD_GROUP("Geometry", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Meshes and Static Colliders"), "set_parsed_geometry_type", "get_parsed_geometry_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_parsed_collision_mask", "get_parsed_collision_mask"); + ADD_PROPERTY_DEFAULT("parsed_collision_mask", 0xFFFFFFFF); + ADD_PROPERTY(PropertyInfo(Variant::INT, "source_geometry_mode", PROPERTY_HINT_ENUM, "Root Node Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_geometry_group_name"), "set_source_geometry_group_name", "get_source_geometry_group_name"); + ADD_PROPERTY_DEFAULT("source_geometry_group_name", StringName("navigation_polygon_source_geometry_group")); + ADD_GROUP("Cells", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "1.0,50.0,1.0,or_greater,suffix:px"), "set_cell_size", "get_cell_size"); + ADD_GROUP("Agents", "agent_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:px"), "set_agent_radius", "get_agent_radius"); + + BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES); + BIND_ENUM_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS); + BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH); + BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MAX); + + BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_ROOT_NODE_CHILDREN); + BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN); + BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_EXPLICIT); + BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_MAX); +} + +void NavigationPolygon::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "parsed_collision_mask") { + if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) { + p_property.usage = PROPERTY_USAGE_NONE; + return; + } + } + + if (p_property.name == "parsed_source_group_name") { + if (source_geometry_mode == SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) { + p_property.usage = PROPERTY_USAGE_NONE; + return; + } + } +} + +NavigationPolygon::NavigationPolygon() { + navigation_mesh.instantiate(); } diff --git a/scene/resources/navigation_polygon.h b/scene/resources/navigation_polygon.h index 7926709a9e..4a6a97e2e7 100644 --- a/scene/resources/navigation_polygon.h +++ b/scene/resources/navigation_polygon.h @@ -43,6 +43,7 @@ class NavigationPolygon : public Resource { }; Vector<Polygon> polygons; Vector<Vector<Vector2>> outlines; + Vector<Vector<Vector2>> baked_outlines; mutable Rect2 item_rect; mutable bool rect_cache_dirty = true; @@ -55,6 +56,7 @@ class NavigationPolygon : public Resource { protected: static void _bind_methods(); + void _validate_property(PropertyInfo &p_property) const; void _set_polygons(const TypedArray<Vector<int32_t>> &p_array); TypedArray<Vector<int32_t>> _get_polygons() const; @@ -68,6 +70,28 @@ public: bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; #endif + enum ParsedGeometryType { + PARSED_GEOMETRY_MESH_INSTANCES = 0, + PARSED_GEOMETRY_STATIC_COLLIDERS, + PARSED_GEOMETRY_BOTH, + PARSED_GEOMETRY_MAX + }; + + enum SourceGeometryMode { + SOURCE_GEOMETRY_ROOT_NODE_CHILDREN = 0, + SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN, + SOURCE_GEOMETRY_GROUPS_EXPLICIT, + SOURCE_GEOMETRY_MAX + }; + + real_t agent_radius = 10.0f; + + ParsedGeometryType parsed_geometry_type = PARSED_GEOMETRY_BOTH; + uint32_t parsed_collision_mask = 0xFFFFFFFF; + + SourceGeometryMode source_geometry_mode = SOURCE_GEOMETRY_ROOT_NODE_CHILDREN; + StringName source_geometry_group_name = "navigation_polygon_source_group"; + void set_vertices(const Vector<Vector2> &p_vertices); Vector<Vector2> get_vertices() const; @@ -82,11 +106,33 @@ public: int get_outline_count() const; void clear_outlines(); +#ifndef DISABLE_DEPRECATED void make_polygons_from_outlines(); +#endif // DISABLE_DEPRECATED + void set_polygons(const Vector<Vector<int>> &p_polygons); + const Vector<Vector<int>> &get_polygons() const; Vector<int> get_polygon(int p_idx); void clear_polygons(); + void set_parsed_geometry_type(ParsedGeometryType p_geometry_type); + ParsedGeometryType get_parsed_geometry_type() const; + + void set_parsed_collision_mask(uint32_t p_mask); + uint32_t get_parsed_collision_mask() const; + + void set_parsed_collision_mask_value(int p_layer_number, bool p_value); + bool get_parsed_collision_mask_value(int p_layer_number) const; + + void set_source_geometry_mode(SourceGeometryMode p_geometry_mode); + SourceGeometryMode get_source_geometry_mode() const; + + void set_source_geometry_group_name(StringName p_group_name); + StringName get_source_geometry_group_name() const; + + void set_agent_radius(real_t p_value); + real_t get_agent_radius() const; + Ref<NavigationMesh> get_navigation_mesh(); void set_cell_size(real_t p_cell_size); @@ -94,8 +140,11 @@ public: void clear(); - NavigationPolygon() {} + NavigationPolygon(); ~NavigationPolygon() {} }; +VARIANT_ENUM_CAST(NavigationPolygon::ParsedGeometryType); +VARIANT_ENUM_CAST(NavigationPolygon::SourceGeometryMode); + #endif // NAVIGATION_POLYGON_H |