From ba1344408f66592eb1bec0b91b5bcdea8385ccdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gilles=20Roudi=C3=A8re?= Date: Mon, 8 Mar 2021 20:56:33 +0100 Subject: [PATCH] Implement Navigation layers --- core/core_constants.cpp | 2 + core/object/object.h | 2 + doc/classes/@GlobalScope.xml | 32 +++-- doc/classes/NavigationRegion2D.xml | 9 ++ doc/classes/NavigationRegion3D.xml | 4 + doc/classes/NavigationServer2D.xml | 31 ++++- doc/classes/NavigationServer3D.xml | 35 ++++- doc/classes/ProjectSettings.xml | 124 ++++++++++++++++++ editor/editor_properties.cpp | 19 ++- editor/editor_properties.h | 2 + editor/property_editor.cpp | 20 ++- .../include/nativescript/godot_nativescript.h | 2 + modules/gdnavigation/gd_navigation_server.cpp | 18 ++- modules/gdnavigation/gd_navigation_server.h | 4 +- modules/gdnavigation/nav_map.cpp | 14 +- modules/gdnavigation/nav_map.h | 2 +- modules/gdnavigation/nav_region.cpp | 8 ++ modules/gdnavigation/nav_region.h | 4 + modules/gdscript/gdscript_parser.cpp | 2 + modules/gridmap/doc_classes/GridMap.xml | 3 + modules/gridmap/grid_map.cpp | 15 +++ modules/gridmap/grid_map.h | 4 + scene/2d/navigation_agent_2d.cpp | 11 +- scene/2d/navigation_agent_2d.h | 5 + scene/2d/navigation_region_2d.cpp | 12 ++ scene/2d/navigation_region_2d.h | 3 + scene/3d/navigation_region_3d.cpp | 12 ++ scene/3d/navigation_region_3d.h | 3 + scene/register_scene_types.cpp | 2 + servers/navigation_server_2d.cpp | 25 +++- servers/navigation_server_2d.h | 6 +- servers/navigation_server_3d.cpp | 4 +- servers/navigation_server_3d.h | 6 +- 33 files changed, 410 insertions(+), 35 deletions(-) diff --git a/core/core_constants.cpp b/core/core_constants.cpp index f9edff18992..a99df936387 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -521,8 +521,10 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_PHYSICS); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_NAVIGATION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_RENDER); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_PHYSICS); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_NAVIGATION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FILE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DIR); diff --git a/core/object/object.h b/core/object/object.h index 029478873d1..448a33d3bca 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -66,8 +66,10 @@ enum PropertyHint { PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_LAYERS_2D_RENDER, PROPERTY_HINT_LAYERS_2D_PHYSICS, + PROPERTY_HINT_LAYERS_2D_NAVIGATION, PROPERTY_HINT_LAYERS_3D_RENDER, PROPERTY_HINT_LAYERS_3D_PHYSICS, + PROPERTY_HINT_LAYERS_3D_NAVIGATION, PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," PROPERTY_HINT_DIR, ///< a directory path must be passed PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 380abed083c..d57d241b533 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2409,43 +2409,49 @@ Hints that an integer property is a bitmask using the optionally named 2D physics layers. - + + Hints that an integer property is a bitmask using the optionally named 2D navigation layers. + + Hints that an integer property is a bitmask using the optionally named 3D render layers. - + Hints that an integer property is a bitmask using the optionally named 3D physics layers. - + + Hints that an integer property is a bitmask using the optionally named 2D navigation layers. + + Hints that a string property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. - + Hints that a string property is a path to a directory. Editing it will show a file dialog for picking the path. - + Hints that a string property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. - + Hints that a string property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path. - + Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate. - + Hints that a string property is text with line breaks. Editing it will show a text input field where line breaks can be typed. - + Hints that a string property should have a placeholder text visible on its input field, whenever the property is empty. The hint string is the placeholder text to use. - + Hints that a color property should be edited without changing its alpha component, i.e. only R, G and B channels are edited. - + Hints that an image is compressed using lossy compression. - + Hints that an image is compressed using lossless compression. - + Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance: [codeblock] hint_string = "%s:" % [TYPE_INT] # Array of inteters. diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml index aef114e1db3..33a3f04c3de 100644 --- a/doc/classes/NavigationRegion2D.xml +++ b/doc/classes/NavigationRegion2D.xml @@ -1,8 +1,12 @@ + A region of the 2D navigation map. + A region of the navigation map. It tells the [NavigationServer2D] what can be navigated and what cannot, based on its [NavigationPolygon] resource. + Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer2D.map_set_edge_connection_margin]. + [b]Note:[/b] Overlapping two regions' polygons is not enough for connecting two regions. They must share a similar edge. @@ -10,8 +14,13 @@ + Determines if the [NavigationRegion2D] is enabled or disabled. + + + A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. + The [NavigationPolygon] resource to use. diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml index e48c326ad7c..2904ba42003 100644 --- a/doc/classes/NavigationRegion3D.xml +++ b/doc/classes/NavigationRegion3D.xml @@ -5,6 +5,7 @@ A region of the navigation map. It tells the [NavigationServer3D] what can be navigated and what cannot, based on its [NavigationMesh] resource. + Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer3D.map_set_edge_connection_margin]. @@ -21,6 +22,9 @@ Determines if the [NavigationRegion3D] is enabled or disabled. + + A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. + The [NavigationMesh] resource to use. diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 5f0b04487e9..4f34a8a4242 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -4,7 +4,12 @@ Server interface for low-level 2D navigation access - NavigationServer2D is the server responsible for all 2D navigation. It creates the agents, maps, and regions for navigation to work as expected. This keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. + NavigationServer2D is the server responsible for all 2D navigation. It handles several objects, namely maps, regions and agents. + Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world. For two regions to be connected to each other, they must share a similar edge. An edges is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. + You may assign navigation layers to regions with [method NavigationServer2D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects. + To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity. + [b]Note:[/b] the collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine. + This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. https://godotengine.org/asset-library/asset/117 @@ -207,8 +212,10 @@ + + - Returns the navigation path to reach the destination from the origin, while avoiding static obstacles. + Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path. @@ -260,6 +267,26 @@ Creates a new region. + + + + + + + Returns the region's layers. + + + + + + + + + + + Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]). + + diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 95890c4b4c3..0653c0d27d7 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -4,7 +4,12 @@ Server interface for low-level 3D navigation access - NavigationServer3D is the server responsible for all 3D navigation. It creates the agents, maps, and regions for navigation to work as expected. This keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. + NavigationServer3D is the server responsible for all 3D navigation. It handles several objects, namely maps, regions and agents. + Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world. For two regions to be connected to each other, they must share a similar edge. An edges is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. + You may assign navigation layers to regions with [method NavigationServer3D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects. + To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity. + [b]Note:[/b] the collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine. + This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. https://godotengine.org/asset-library/asset/124 @@ -219,7 +224,7 @@ - Returns the edge connection margin of the map. + Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions. @@ -233,8 +238,10 @@ + + - Returns the navigation path to reach the destination from the origin. + Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path. @@ -285,7 +292,7 @@ - Set the map edge connection margein used to weld the compatible region edges. + Set the map edge connection margin used to weld the compatible region edges. @@ -328,6 +335,26 @@ Creates a new region. + + + + + + + Returns the region's layers. + + + + + + + + + + + Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]). + + diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index f551022437e..ac63c5da795 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -758,6 +758,66 @@ Specifies the [TextServer] to use. If left empty, the default will be used. + + Optional name for the 2D navigation layer 0. If left empty, the layer will display as "Layer 0". + + + Optional name for the 2D navigation layer 1. If left empty, the layer will display as "Layer 1". + + + Optional name for the 2D navigation layer 10. If left empty, the layer will display as "Layer 10". + + + Optional name for the 2D navigation layer 11. If left empty, the layer will display as "Layer 11". + + + Optional name for the 2D navigation layer 12. If left empty, the layer will display as "Layer 12". + + + Optional name for the 2D navigation layer 13. If left empty, the layer will display as "Layer 13". + + + Optional name for the 2D navigation layer 14. If left empty, the layer will display as "Layer 14". + + + Optional name for the 2D navigation layer 15. If left empty, the layer will display as "Layer 15". + + + Optional name for the 2D navigation layer 16. If left empty, the layer will display as "Layer 16". + + + Optional name for the 2D navigation layer 17. If left empty, the layer will display as "Layer 17". + + + Optional name for the 2D navigation layer 18. If left empty, the layer will display as "Layer 18". + + + Optional name for the 2D navigation layer 19. If left empty, the layer will display as "Layer 19". + + + Optional name for the 2D navigation layer 2. If left empty, the layer will display as "Layer 2". + + + Optional name for the 2D navigation layer 3. If left empty, the layer will display as "Layer 3". + + + Optional name for the 2D navigation layer 4. If left empty, the layer will display as "Layer 4". + + + Optional name for the 2D navigation layer 5. If left empty, the layer will display as "Layer 5". + + + Optional name for the 2D navigation layer 6. If left empty, the layer will display as "Layer 6". + + + Optional name for the 2D navigation layer 7. If left empty, the layer will display as "Layer 7". + + + Optional name for the 2D navigation layer 8. If left empty, the layer will display as "Layer 8". + + + Optional name for the 2D navigation layer 9. If left empty, the layer will display as "Layer 9". + Optional name for the 2D physics layer 0. If left empty, the layer will display as "Layer 0". @@ -878,6 +938,66 @@ Optional name for the 2D render layer 9. If left empty, the layer will display as "Layer 9". + + Optional name for the 3D navigation layer 0. If left empty, the layer will display as "Layer 0". + + + Optional name for the 3D navigation layer 1. If left empty, the layer will display as "Layer 1". + + + Optional name for the 3D navigation layer 10. If left empty, the layer will display as "Layer 10". + + + Optional name for the 3D navigation layer 11. If left empty, the layer will display as "Layer 11". + + + Optional name for the 3D navigation layer 12. If left empty, the layer will display as "Layer 12". + + + Optional name for the 3D navigation layer 13. If left empty, the layer will display as "Layer 13". + + + Optional name for the 3D navigation layer 14. If left empty, the layer will display as "Layer 14". + + + Optional name for the 3D navigation layer 15. If left empty, the layer will display as "Layer 15". + + + Optional name for the 3D navigation layer 16. If left empty, the layer will display as "Layer 16". + + + Optional name for the 3D navigation layer 17. If left empty, the layer will display as "Layer 17". + + + Optional name for the 3D navigation layer 18. If left empty, the layer will display as "Layer 18". + + + Optional name for the 3D navigation layer 19. If left empty, the layer will display as "Layer 19". + + + Optional name for the 3D navigation layer 2. If left empty, the layer will display as "Layer 2". + + + Optional name for the 3D navigation layer 3. If left empty, the layer will display as "Layer 3". + + + Optional name for the 3D navigation layer 4. If left empty, the layer will display as "Layer 4". + + + Optional name for the 3D navigation layer 5. If left empty, the layer will display as "Layer 5". + + + Optional name for the 3D navigation layer 6. If left empty, the layer will display as "Layer 6". + + + Optional name for the 3D navigation layer 7. If left empty, the layer will display as "Layer 7". + + + Optional name for the 3D navigation layer 8. If left empty, the layer will display as "Layer 8". + + + Optional name for the 3D navigation layer 9. If left empty, the layer will display as "Layer 9". + Optional name for the 3D physics layer 0. If left empty, the layer will display as "Layer 0". @@ -1021,12 +1141,16 @@ + Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size]. + Default edge connection margin for 2D navigation maps. See [method NavigationServer2D.map_set_edge_connection_margin]. + Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size]. + Default edge connection margin for 3D navigation maps. See [method NavigationServer3D.map_set_edge_connection_margin]. Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection. diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 6bfc16ccd7e..dbe4aa55fae 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -716,12 +716,18 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) { case LAYER_PHYSICS_2D: basename = "layer_names/2d_physics"; break; + case LAYER_NAVIGATION_2D: + basename = "layer_names/2d_navigation"; + break; case LAYER_RENDER_3D: basename = "layer_names/3d_render"; break; case LAYER_PHYSICS_3D: basename = "layer_names/3d_physics"; break; + case LAYER_NAVIGATION_3D: + basename = "layer_names/3d_navigation"; + break; } Vector names; @@ -3300,7 +3306,12 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ editor->setup(options); add_property_editor(p_path, editor); - } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_3D_RENDER) { + } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || + p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || + p_hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || + p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || + p_hint == PROPERTY_HINT_LAYERS_3D_RENDER || + p_hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { EditorPropertyLayers::LayerType lt = EditorPropertyLayers::LAYER_RENDER_2D; switch (p_hint) { case PROPERTY_HINT_LAYERS_2D_RENDER: @@ -3309,12 +3320,18 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ case PROPERTY_HINT_LAYERS_2D_PHYSICS: lt = EditorPropertyLayers::LAYER_PHYSICS_2D; break; + case PROPERTY_HINT_LAYERS_2D_NAVIGATION: + lt = EditorPropertyLayers::LAYER_NAVIGATION_2D; + break; case PROPERTY_HINT_LAYERS_3D_RENDER: lt = EditorPropertyLayers::LAYER_RENDER_3D; break; case PROPERTY_HINT_LAYERS_3D_PHYSICS: lt = EditorPropertyLayers::LAYER_PHYSICS_3D; break; + case PROPERTY_HINT_LAYERS_3D_NAVIGATION: + lt = EditorPropertyLayers::LAYER_NAVIGATION_3D; + break; default: { } //compiler could be smarter here and realize this can't happen } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 6f097fb5df4..07a1e723190 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -239,8 +239,10 @@ public: enum LayerType { LAYER_PHYSICS_2D, LAYER_RENDER_2D, + LAYER_NAVIGATION_2D, LAYER_PHYSICS_3D, LAYER_RENDER_3D, + LAYER_NAVIGATION_3D, }; private: diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 07312e42b41..8ce71533554 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -417,7 +417,12 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: updating = false; return false; - } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) { + } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_2D_RENDER || + hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || + hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_3D_RENDER || + hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { String basename; switch (hint) { case PROPERTY_HINT_LAYERS_2D_RENDER: @@ -426,12 +431,18 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: case PROPERTY_HINT_LAYERS_2D_PHYSICS: basename = "layer_names/2d_physics"; break; + case PROPERTY_HINT_LAYERS_2D_NAVIGATION: + basename = "layer_names/2d_navigation"; + break; case PROPERTY_HINT_LAYERS_3D_RENDER: basename = "layer_names/3d_render"; break; case PROPERTY_HINT_LAYERS_3D_PHYSICS: basename = "layer_names/3d_physics"; break; + case PROPERTY_HINT_LAYERS_3D_NAVIGATION: + basename = "layer_names/3d_navigation"; + break; } checks20gc->show(); @@ -1153,7 +1164,12 @@ void CustomPropertyEditor::_action_pressed(int p_which) { emit_signal("variant_changed"); } break; case Variant::INT: { - if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) { + if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_2D_RENDER || + hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || + hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_3D_RENDER || + hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { uint32_t f = v; if (checks20[p_which]->is_pressed()) { f |= (1 << p_which); diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 73b1738b039..c97f5f0389d 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -58,8 +58,10 @@ typedef enum { GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) GODOT_PROPERTY_HINT_LAYERS_2D_RENDER, GODOT_PROPERTY_HINT_LAYERS_2D_PHYSICS, + GODOT_PROPERTY_HINT_LAYERS_2D_NAVIGATION, GODOT_PROPERTY_HINT_LAYERS_3D_RENDER, GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS, + GODOT_PROPERTY_HINT_LAYERS_3D_NAVIGATION, GODOT_PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," GODOT_PROPERTY_HINT_DIR, ///< a directory path must be passed GODOT_PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp index 4f61ad5040a..af76d9a4ccc 100644 --- a/modules/gdnavigation/gd_navigation_server.cpp +++ b/modules/gdnavigation/gd_navigation_server.cpp @@ -200,11 +200,11 @@ real_t GdNavigationServer::map_get_edge_connection_margin(RID p_map) const { return map->get_edge_connection_margin(); } -Vector GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const { +Vector GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const { const NavMap *map = map_owner.getornull(p_map); ERR_FAIL_COND_V(map == nullptr, Vector()); - return map->get_path(p_origin, p_destination, p_optimize); + return map->get_path(p_origin, p_destination, p_optimize, p_layers); } Vector3 GdNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const { @@ -273,6 +273,20 @@ COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform) { region->set_transform(p_transform); } +COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers) { + NavRegion *region = region_owner.getornull(p_region); + ERR_FAIL_COND(region == nullptr); + + region->set_layers(p_layers); +} + +uint32_t GdNavigationServer::region_get_layers(RID p_region) const { + NavRegion *region = region_owner.getornull(p_region); + ERR_FAIL_COND_V(region == nullptr, 0); + + return region->get_layers(); +} + COMMAND_2(region_set_navmesh, RID, p_region, Ref, p_nav_mesh) { NavRegion *region = region_owner.getornull(p_region); ERR_FAIL_COND(region == nullptr); diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h index 92f4ccfdd5e..8bc65eccab2 100644 --- a/modules/gdnavigation/gd_navigation_server.h +++ b/modules/gdnavigation/gd_navigation_server.h @@ -100,7 +100,7 @@ public: COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin); virtual real_t map_get_edge_connection_margin(RID p_map) const; - virtual Vector map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const; + virtual Vector map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const; virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const; virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const; @@ -109,6 +109,8 @@ public: virtual RID region_create() const; COMMAND_2(region_set_map, RID, p_region, RID, p_map); + COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers); + virtual uint32_t region_get_layers(RID p_region) const; COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform); COMMAND_2(region_set_navmesh, RID, p_region, Ref, p_nav_mesh); virtual void region_bake_navmesh(Ref r_mesh, Node *p_node) const; diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp index 2646a4cc0c5..5289975e4b6 100644 --- a/modules/gdnavigation/nav_map.cpp +++ b/modules/gdnavigation/nav_map.cpp @@ -70,7 +70,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { return p; } -Vector NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize) const { +Vector NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const { const gd::Polygon *begin_poly = nullptr; const gd::Polygon *end_poly = nullptr; Vector3 begin_point; @@ -82,6 +82,11 @@ Vector NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p for (size_t i(0); i < polygons.size(); i++) { const gd::Polygon &p = polygons[i]; + // Only consider the polygon if it in a region with compatible layers. + if ((p_layers & p.owner->get_layers()) == 0) { + continue; + } + // For each point cast a face and check the distance between the origin/destination for (size_t point_id = 2; point_id < p.points.size(); point_id++) { Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); @@ -144,6 +149,11 @@ Vector NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p for (size_t i = 0; i < navigation_polys[least_cost_id].poly->edges.size(); i++) { gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id]; + // Only consider the polygon if it in a region with compatible layers. + if ((p_layers & least_cost_poly->poly->owner->get_layers()) == 0) { + continue; + } + const gd::Edge &edge = least_cost_poly->poly->edges[i]; if (!edge.other_polygon) { continue; @@ -629,7 +639,7 @@ void NavMap::sync() { connection->get().B->edges[connection->get().B_edge].other_edge = connection->get().A_edge; } else { // The edge is already connected with another edge, skip. - ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the Navigation3D's `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); + ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the current `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); } } } diff --git a/modules/gdnavigation/nav_map.h b/modules/gdnavigation/nav_map.h index bffc1fbc1a3..6b7cfae3247 100644 --- a/modules/gdnavigation/nav_map.h +++ b/modules/gdnavigation/nav_map.h @@ -102,7 +102,7 @@ public: gd::PointKey get_point_key(const Vector3 &p_pos) const; - Vector get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize) const; + Vector get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const; Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const; Vector3 get_closest_point(const Vector3 &p_point) const; Vector3 get_closest_point_normal(const Vector3 &p_point) const; diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp index 383b0f15a65..a07995bc11c 100644 --- a/modules/gdnavigation/nav_region.cpp +++ b/modules/gdnavigation/nav_region.cpp @@ -41,6 +41,14 @@ void NavRegion::set_map(NavMap *p_map) { polygons_dirty = true; } +void NavRegion::set_layers(uint32_t p_layers) { + layers = p_layers; +} + +uint32_t NavRegion::get_layers() const { + return layers; +} + void NavRegion::set_transform(Transform p_transform) { transform = p_transform; polygons_dirty = true; diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h index 3095435359e..fff7843fde6 100644 --- a/modules/gdnavigation/nav_region.h +++ b/modules/gdnavigation/nav_region.h @@ -48,6 +48,7 @@ class NavRegion : public NavRid { NavMap *map = nullptr; Transform transform; Ref mesh; + uint32_t layers = 1; bool polygons_dirty = true; @@ -66,6 +67,9 @@ public: return map; } + void set_layers(uint32_t p_layers); + uint32_t get_layers() const; + void set_transform(Transform transform); const Transform &get_transform() const { return transform; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 08645d371ca..15cb3146ee9 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -130,8 +130,10 @@ GDScriptParser::GDScriptParser() { register_annotation(MethodInfo("@export_flags", { Variant::STRING, "names" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations, 0, true); register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); + register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); register_annotation(MethodInfo("@export_flags_3d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); + register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); // Networking. register_annotation(MethodInfo("@remote"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations); register_annotation(MethodInfo("@master"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations); diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 6af371fbe4f..25776b1f6d4 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -214,6 +214,9 @@ The physics layers this GridMap detects collisions in. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + + The navigation layers the GridMap generates its navigable regions in. + The assigned [MeshLibrary]. diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 4c99c8f133b..c1c230d1046 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -188,6 +188,15 @@ bool GridMap::is_baking_navigation() { return bake_navigation; } +void GridMap::set_navigation_layers(uint32_t p_layers) { + navigation_layers = p_layers; + _recreate_octant_data(); +} + +uint32_t GridMap::get_navigation_layers() { + return navigation_layers; +} + void GridMap::set_mesh_library(const Ref &p_mesh_library) { if (!mesh_library.is_null()) { mesh_library->unregister_owner(this); @@ -485,6 +494,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) { if (bake_navigation) { RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers); NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh); NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * mesh_library->get_item_navmesh_transform(c.item)); NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); @@ -580,6 +590,7 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) { Ref nm = mesh_library->get_item_navmesh(cell_map[F->key()].item); if (nm.is_valid()) { RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers); NavigationServer3D::get_singleton()->region_set_navmesh(region, nm); NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F->get().xform); NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); @@ -785,6 +796,9 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &GridMap::set_bake_navigation); ClassDB::bind_method(D_METHOD("is_baking_navigation"), &GridMap::is_baking_navigation); + ClassDB::bind_method(D_METHOD("set_navigation_layers", "layers"), &GridMap::set_navigation_layers); + ClassDB::bind_method(D_METHOD("get_navigation_layers"), &GridMap::get_navigation_layers); + ClassDB::bind_method(D_METHOD("set_mesh_library", "mesh_library"), &GridMap::set_mesh_library); ClassDB::bind_method(D_METHOD("get_mesh_library"), &GridMap::get_mesh_library); @@ -840,6 +854,7 @@ void GridMap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Navigation", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); BIND_CONSTANT(INVALID_CELL_ITEM); diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index c485afd58ae..4c04d492f7c 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -135,6 +135,7 @@ class GridMap : public Node3D { uint32_t collision_layer = 1; uint32_t collision_mask = 1; bool bake_navigation = false; + uint32_t navigation_layers = 1; Transform last_transform; @@ -225,6 +226,9 @@ public: void set_bake_navigation(bool p_bake_navigation); bool is_baking_navigation(); + void set_navigation_layers(uint32_t p_layers); + uint32_t get_navigation_layers(); + void set_mesh_library(const Ref &p_mesh_library); Ref get_mesh_library() const; diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 2319a1413c7..064fcc91a40 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -125,6 +125,15 @@ NavigationAgent2D::~NavigationAgent2D() { agent = RID(); // Pointless } +void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) { + navigable_layers = p_layers; + update_navigation(); +} + +uint32_t NavigationAgent2D::get_navigable_layers() const { + return navigable_layers; +} + void NavigationAgent2D::set_target_desired_distance(real_t p_dd) { target_desired_distance = p_dd; } @@ -279,7 +288,7 @@ void NavigationAgent2D::update_navigation() { } if (reload_path) { - navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true); + navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigable_layers); navigation_finished = false; nav_path_index = 0; emit_signal("path_changed"); diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 2debed65a54..153ede8cec9 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -43,6 +43,8 @@ class NavigationAgent2D : public Node { RID agent; + uint32_t navigable_layers = 1; + real_t target_desired_distance = 1.0; real_t radius; real_t neighbor_dist; @@ -76,6 +78,9 @@ public: return agent; } + void set_navigable_layers(uint32_t p_layers); + uint32_t get_navigable_layers() const; + void set_target_desired_distance(real_t p_dd); real_t get_target_desired_distance() const { return target_desired_distance; diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 779dbe4b119..794993f8926 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -377,6 +377,14 @@ bool NavigationRegion2D::is_enabled() const { return enabled; } +void NavigationRegion2D::set_layers(uint32_t p_layers) { + NavigationServer2D::get_singleton()->region_set_layers(region, p_layers); +} + +uint32_t NavigationRegion2D::get_layers() const { + return NavigationServer2D::get_singleton()->region_get_layers(region); +} + ///////////////////////////// #ifdef TOOLS_ENABLED Rect2 NavigationRegion2D::_edit_get_rect() const { @@ -501,10 +509,14 @@ void NavigationRegion2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled); + ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion2D::set_layers); + ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion2D::get_layers); + ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationRegion2D::_navpoly_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_layers", "get_layers"); } NavigationRegion2D::NavigationRegion2D() { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 25a886b4461..7b471bd555b 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -113,6 +113,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; + void set_layers(uint32_t p_layers); + uint32_t get_layers() const; + void set_navigation_polygon(const Ref &p_navpoly); Ref get_navigation_polygon() const; diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 8470a7d7253..3ca704e4b82 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -66,6 +66,14 @@ bool NavigationRegion3D::is_enabled() const { return enabled; } +void NavigationRegion3D::set_layers(uint32_t p_layers) { + NavigationServer3D::get_singleton()->region_set_layers(region, p_layers); +} + +uint32_t NavigationRegion3D::get_layers() const { + return NavigationServer3D::get_singleton()->region_get_layers(region); +} + ///////////////////////////// void NavigationRegion3D::_notification(int p_what) { @@ -193,11 +201,15 @@ void NavigationRegion3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled); + ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion3D::set_layers); + ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion3D::get_layers); + ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationRegion3D::bake_navigation_mesh); ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion3D::_bake_finished); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", 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::INT, "layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_layers", "get_layers"); ADD_SIGNAL(MethodInfo("navigation_mesh_changed")); ADD_SIGNAL(MethodInfo("bake_finished")); diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index 85bf4955717..52fa2d61596 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -55,6 +55,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; + void set_layers(uint32_t p_layers); + uint32_t get_layers() const; + void set_navigation_mesh(const Ref &p_navmesh); Ref get_navigation_mesh() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index fcd8b8b4012..fe8591e3d93 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -947,8 +947,10 @@ void register_scene_types() { for (int i = 0; i < 20; i++) { GLOBAL_DEF_BASIC(vformat("layer_names/2d_render/layer_%d", i), ""); GLOBAL_DEF_BASIC(vformat("layer_names/2d_physics/layer_%d", i), ""); + GLOBAL_DEF_BASIC(vformat("layer_names/2d_navigation/layer_%d", i), ""); GLOBAL_DEF_BASIC(vformat("layer_names/3d_render/layer_%d", i), ""); GLOBAL_DEF_BASIC(vformat("layer_names/3d_physics/layer_%d", i), ""); + GLOBAL_DEF_BASIC(vformat("layer_names/3d_navigation/layer_%d", i), ""); } bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index df348d2add1..fee74f3dbc5 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -80,6 +80,18 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr; return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \ } +#define FORWARD_5_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \ + const { \ + return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4))); \ + } + +#define FORWARD_5_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \ + const { \ + return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4)); \ + } + static RID rid_to_rid(const RID d) { return d; } @@ -92,6 +104,10 @@ static int int_to_int(const int d) { return d; } +static uint32_t uint32_to_uint32(const uint32_t d) { + return d; +} + static real_t real_to_real(const real_t d) { return d; } @@ -148,12 +164,14 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer2D::map_get_path); + ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner); ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map); + ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers); + ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform); ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly); @@ -193,14 +211,15 @@ real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid); void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real); real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid); -Vector FORWARD_4_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool); +Vector FORWARD_5_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, uint32_t, p_layers, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool, uint32_to_uint32); Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); RID FORWARD_0_C(region_create); void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid); - +void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32); +uint32_t FORWARD_1_C(region_get_layers, RID, p_region, rid_to_rid); void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3); void NavigationServer2D::region_set_navpoly(RID p_region, Ref p_nav_mesh) const { diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 7be5a74cb32..46c8f6a71d8 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -77,7 +77,7 @@ public: virtual real_t map_get_edge_connection_margin(RID p_map) const; /// Returns the navigation path to reach the destination from the origin. - virtual Vector map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize) const; + virtual Vector map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const; virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; @@ -88,6 +88,10 @@ public: /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const; + /// Set the region's layers + virtual void region_set_layers(RID p_region, uint32_t p_layers) const; + virtual uint32_t region_get_layers(RID p_region) const; + /// Set the global transformation of this region. virtual void region_set_transform(RID p_region, Transform2D p_transform) const; diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 0e5ae82b0d8..d81ce70af61 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -46,7 +46,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer3D::map_get_path); + ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false)); ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal); @@ -54,6 +54,8 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map); + ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers); + ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform); ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh); ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 3761c3871af..beed19d563f 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -88,7 +88,7 @@ public: virtual real_t map_get_edge_connection_margin(RID p_map) const = 0; /// Returns the navigation path to reach the destination from the origin. - virtual Vector map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const = 0; + virtual Vector map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0; virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0; virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0; @@ -101,6 +101,10 @@ public: /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const = 0; + /// Set the region's layers + virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0; + virtual uint32_t region_get_layers(RID p_region) const = 0; + /// Set the global transformation of this region. virtual void region_set_transform(RID p_region, Transform p_transform) const = 0;