diff options
27 files changed, 607 insertions, 33 deletions
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index 770a5dc5b0..31d347d76c 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -28,6 +28,12 @@ Returns which index the agent is currently on in the navigation path's [PackedVector2Array]. </description> </method> + <method name="get_current_navigation_result" qualifiers="const"> + <return type="NavigationPathQueryResult2D" /> + <description> + Returns the path query result for the path the agent is currently following. + </description> + </method> <method name="get_final_location"> <return type="Vector2" /> <description> @@ -122,6 +128,9 @@ <member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="3.0"> The maximum distance the agent is allowed away from the ideal path to the final location. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path. </member> + <member name="path_metadata_flags" type="int" setter="set_path_metadata_flags" getter="get_path_metadata_flags" enum="NavigationPathQueryParameters2D.PathMetadataFlags" default="7"> + Additional information to return with the navigation path. + </member> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0"> The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_distance]). Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size. @@ -137,6 +146,17 @@ </member> </members> <signals> + <signal name="link_reached"> + <param index="0" name="details" type="Dictionary" /> + <description> + Notifies when a navigation link has been reached. + The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]: + - [code]location[/code]: The start location of the link that was reached. + - [code]type[/code]: Always [constant NavigationPathQueryResult2D.PATH_SEGMENT_TYPE_LINK]. + - [code]rid[/code]: The [RID] of the link. + - [code]owner[/code]: The object which manages the link (usually [NavigationLink2D]). + </description> + </signal> <signal name="navigation_finished"> <description> Notifies when the final location is reached. @@ -158,5 +178,16 @@ Notifies when the collision avoidance velocity is calculated. Emitted by [method set_velocity]. Only emitted when [member avoidance_enabled] is true. </description> </signal> + <signal name="waypoint_reached"> + <param index="0" name="details" type="Dictionary" /> + <description> + Notifies when a waypoint along the path has been reached. + The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]: + - [code]location[/code]: The location of the waypoint that was reached. + - [code]type[/code]: The type of navigation primitive (region or link) that contains this waypoint. + - [code]rid[/code]: The [RID] of the containing navigation primitive (region or link). + - [code]owner[/code]: The object which manages the containing navigation primitive (region or link). + </description> + </signal> </signals> </class> diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml index d9a1235bdd..c3f4809b5e 100644 --- a/doc/classes/NavigationAgent3D.xml +++ b/doc/classes/NavigationAgent3D.xml @@ -28,6 +28,12 @@ Returns which index the agent is currently on in the navigation path's [PackedVector3Array]. </description> </method> + <method name="get_current_navigation_result" qualifiers="const"> + <return type="NavigationPathQueryResult3D" /> + <description> + Returns the path query result for the path the agent is currently following. + </description> + </method> <method name="get_final_location"> <return type="Vector3" /> <description> @@ -128,6 +134,9 @@ <member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="3.0"> The maximum distance the agent is allowed away from the ideal path to the final location. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path. </member> + <member name="path_metadata_flags" type="int" setter="set_path_metadata_flags" getter="get_path_metadata_flags" enum="NavigationPathQueryParameters3D.PathMetadataFlags" default="7"> + Additional information to return with the navigation path. + </member> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_distance]). Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size. @@ -143,6 +152,17 @@ </member> </members> <signals> + <signal name="link_reached"> + <param index="0" name="details" type="Dictionary" /> + <description> + Notifies when a navigation link has been reached. + The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]: + - [code]location[/code]: The start location of the link that was reached. + - [code]type[/code]: Always [constant NavigationPathQueryResult3D.PATH_SEGMENT_TYPE_LINK]. + - [code]rid[/code]: The [RID] of the link. + - [code]owner[/code]: The object which manages the link (usually [NavigationLink3D]). + </description> + </signal> <signal name="navigation_finished"> <description> Notifies when the final location is reached. @@ -164,5 +184,16 @@ Notifies when the collision avoidance velocity is calculated. Emitted by [method set_velocity]. Only emitted when [member avoidance_enabled] is true. </description> </signal> + <signal name="waypoint_reached"> + <param index="0" name="details" type="Dictionary" /> + <description> + Notifies when a waypoint along the path has been reached. + The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]: + - [code]location[/code]: The location of the waypoint that was reached. + - [code]type[/code]: The type of navigation primitive (region or link) that contains this waypoint. + - [code]rid[/code]: The [RID] of the containing navigation primitive (region or link). + - [code]owner[/code]: The object which manages the containing navigation primitive (region or link). + </description> + </signal> </signals> </class> diff --git a/doc/classes/NavigationPathQueryParameters2D.xml b/doc/classes/NavigationPathQueryParameters2D.xml index dff58fc1bd..511b2e7a8c 100644 --- a/doc/classes/NavigationPathQueryParameters2D.xml +++ b/doc/classes/NavigationPathQueryParameters2D.xml @@ -12,6 +12,9 @@ <member name="map" type="RID" setter="set_map" getter="get_map"> The navigation [code]map[/code] [RID] used in the path query. </member> + <member name="metadata_flags" type="int" setter="set_metadata_flags" getter="get_metadata_flags" enum="NavigationPathQueryParameters2D.PathMetadataFlags" default="7"> + Additional information to include with the navigation path. + </member> <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1"> The navigation layers the query will use (as a bitmask). </member> @@ -38,5 +41,20 @@ <constant name="PATH_POSTPROCESSING_EDGECENTERED" value="1" enum="PathPostProcessing"> Centers every path position in the middle of the traveled navigation mesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center. </constant> + <constant name="PATH_METADATA_INCLUDE_NONE" value="0" enum="PathMetadataFlags" is_bitfield="true"> + Don't include any additional metadata about the returned path. + </constant> + <constant name="PATH_METADATA_INCLUDE_TYPES" value="1" enum="PathMetadataFlags" is_bitfield="true"> + Include the type of navigation primitive (region or link) that each point of the path goes through. + </constant> + <constant name="PATH_METADATA_INCLUDE_RIDS" value="2" enum="PathMetadataFlags" is_bitfield="true"> + Include the [RID]s of the regions and links that each point of the path goes through. + </constant> + <constant name="PATH_METADATA_INCLUDE_OWNERS" value="4" enum="PathMetadataFlags" is_bitfield="true"> + Include the [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through. + </constant> + <constant name="PATH_METADATA_INCLUDE_ALL" value="7" enum="PathMetadataFlags" is_bitfield="true"> + Include all available metadata about the returned path. + </constant> </constants> </class> diff --git a/doc/classes/NavigationPathQueryParameters3D.xml b/doc/classes/NavigationPathQueryParameters3D.xml index 46a35b1071..b5031f60f2 100644 --- a/doc/classes/NavigationPathQueryParameters3D.xml +++ b/doc/classes/NavigationPathQueryParameters3D.xml @@ -12,6 +12,9 @@ <member name="map" type="RID" setter="set_map" getter="get_map"> The navigation [code]map[/code] [RID] used in the path query. </member> + <member name="metadata_flags" type="int" setter="set_metadata_flags" getter="get_metadata_flags" enum="NavigationPathQueryParameters3D.PathMetadataFlags" default="7"> + Additional information to include with the navigation path. + </member> <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1"> The navigation layers the query will use (as a bitmask). </member> @@ -38,5 +41,20 @@ <constant name="PATH_POSTPROCESSING_EDGECENTERED" value="1" enum="PathPostProcessing"> Centers every path position in the middle of the traveled navigation mesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center. </constant> + <constant name="PATH_METADATA_INCLUDE_NONE" value="0" enum="PathMetadataFlags" is_bitfield="true"> + Don't include any additional metadata about the returned path. + </constant> + <constant name="PATH_METADATA_INCLUDE_TYPES" value="1" enum="PathMetadataFlags" is_bitfield="true"> + Include the type of navigation primitive (region or link) that each point of the path goes through. + </constant> + <constant name="PATH_METADATA_INCLUDE_RIDS" value="2" enum="PathMetadataFlags" is_bitfield="true"> + Include the [RID]s of the regions and links that each point of the path goes through. + </constant> + <constant name="PATH_METADATA_INCLUDE_OWNERS" value="4" enum="PathMetadataFlags" is_bitfield="true"> + Include the [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through. + </constant> + <constant name="PATH_METADATA_INCLUDE_ALL" value="7" enum="PathMetadataFlags" is_bitfield="true"> + Include all available metadata about the returned path. + </constant> </constants> </class> diff --git a/doc/classes/NavigationPathQueryResult2D.xml b/doc/classes/NavigationPathQueryResult2D.xml index 77b19b07b6..75f7cc47aa 100644 --- a/doc/classes/NavigationPathQueryResult2D.xml +++ b/doc/classes/NavigationPathQueryResult2D.xml @@ -20,5 +20,22 @@ <member name="path" type="PackedVector2Array" setter="set_path" getter="get_path" default="PackedVector2Array()"> The resulting path array from the navigation query. All path array positions are in global coordinates. Without customized query parameters this is the same path as returned by [method NavigationServer2D.map_get_path]. </member> + <member name="path_owner_ids" type="PackedInt64Array" setter="set_path_owner_ids" getter="get_path_owner_ids" default="PackedInt64Array()"> + The [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through. + </member> + <member name="path_rids" type="RID[]" setter="set_path_rids" getter="get_path_rids" default="[]"> + The [RID]s of the regions and links that each point of the path goes through. + </member> + <member name="path_types" type="PackedInt32Array" setter="set_path_types" getter="get_path_types" default="PackedInt32Array()"> + The type of navigation primitive (region or link) that each point of the path goes through. + </member> </members> + <constants> + <constant name="PATH_SEGMENT_TYPE_REGION" value="0" enum="PathSegmentType"> + This segment of the path goes through a region. + </constant> + <constant name="PATH_SEGMENT_TYPE_LINK" value="1" enum="PathSegmentType"> + This segment of the path goes through a link. + </constant> + </constants> </class> diff --git a/doc/classes/NavigationPathQueryResult3D.xml b/doc/classes/NavigationPathQueryResult3D.xml index 6c553bf36b..03d41cb230 100644 --- a/doc/classes/NavigationPathQueryResult3D.xml +++ b/doc/classes/NavigationPathQueryResult3D.xml @@ -20,5 +20,22 @@ <member name="path" type="PackedVector3Array" setter="set_path" getter="get_path" default="PackedVector3Array()"> The resulting path array from the navigation query. All path array positions are in global coordinates. Without customized query parameters this is the same path as returned by [method NavigationServer3D.map_get_path]. </member> + <member name="path_owner_ids" type="PackedInt64Array" setter="set_path_owner_ids" getter="get_path_owner_ids" default="PackedInt64Array()"> + The [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through. + </member> + <member name="path_rids" type="RID[]" setter="set_path_rids" getter="get_path_rids" default="[]"> + The [RID]s of the regions and links that each point of the path goes through. + </member> + <member name="path_types" type="PackedInt32Array" setter="set_path_types" getter="get_path_types" default="PackedInt32Array()"> + The type of navigation primitive (region or link) that each point of the path goes through. + </member> </members> + <constants> + <constant name="PATH_SEGMENT_TYPE_REGION" value="0" enum="PathSegmentType"> + This segment of the path goes through a region. + </constant> + <constant name="PATH_SEGMENT_TYPE_LINK" value="1" enum="PathSegmentType"> + This segment of the path goes through a link. + </constant> + </constants> </class> diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index c5c1912621..58a0982425 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -36,6 +36,8 @@ #include "navigation_mesh_generator.h" #endif +using namespace NavigationUtilities; + /// Creates a struct for each function and a function that once called creates /// an instance of that struct with the submitted parameters. /// Then, that struct is stored in an array; the `sync` function consume that array. @@ -228,7 +230,7 @@ Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, const NavMap *map = map_owner.get_or_null(p_map); ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>()); - return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers); + return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers, nullptr, nullptr, nullptr); } Vector3 GodotNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const { @@ -838,20 +840,34 @@ void GodotNavigationServer::process(real_t p_delta_time) { } } -NavigationUtilities::PathQueryResult GodotNavigationServer::_query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const { - NavigationUtilities::PathQueryResult r_query_result; +PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_parameters) const { + PathQueryResult r_query_result; const NavMap *map = map_owner.get_or_null(p_parameters.map); ERR_FAIL_COND_V(map == nullptr, r_query_result); // run the pathfinding - if (p_parameters.pathfinding_algorithm == NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR) { + if (p_parameters.pathfinding_algorithm == PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR) { // while postprocessing is still part of map.get_path() need to check and route it here for the correct "optimize" post-processing - if (p_parameters.path_postprocessing == NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL) { - r_query_result.path = map->get_path(p_parameters.start_position, p_parameters.target_position, true, p_parameters.navigation_layers); - } else if (p_parameters.path_postprocessing == NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED) { - r_query_result.path = map->get_path(p_parameters.start_position, p_parameters.target_position, false, p_parameters.navigation_layers); + if (p_parameters.path_postprocessing == PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL) { + r_query_result.path = map->get_path( + p_parameters.start_position, + p_parameters.target_position, + true, + p_parameters.navigation_layers, + p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_TYPES) ? &r_query_result.path_types : nullptr, + p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_RIDS) ? &r_query_result.path_rids : nullptr, + p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_OWNERS) ? &r_query_result.path_owner_ids : nullptr); + } else if (p_parameters.path_postprocessing == PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED) { + r_query_result.path = map->get_path( + p_parameters.start_position, + p_parameters.target_position, + false, + p_parameters.navigation_layers, + p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_TYPES) ? &r_query_result.path_types : nullptr, + p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_RIDS) ? &r_query_result.path_rids : nullptr, + p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_OWNERS) ? &r_query_result.path_owner_ids : nullptr); } } else { return r_query_result; diff --git a/modules/navigation/nav_base.h b/modules/navigation/nav_base.h index f5d2880d36..a3ab77301b 100644 --- a/modules/navigation/nav_base.h +++ b/modules/navigation/nav_base.h @@ -33,6 +33,7 @@ #include "nav_rid.h" #include "nav_utils.h" +#include "servers/navigation/navigation_utilities.h" class NavMap; @@ -42,8 +43,11 @@ protected: float enter_cost = 0.0; float travel_cost = 1.0; ObjectID owner_id; + NavigationUtilities::PathSegmentType type; public: + NavigationUtilities::PathSegmentType get_type() const { return type; } + void set_navigation_layers(uint32_t p_navigation_layers) { navigation_layers = p_navigation_layers; } uint32_t get_navigation_layers() const { return navigation_layers; } diff --git a/modules/navigation/nav_link.h b/modules/navigation/nav_link.h index 8f51a63951..e9c69286f9 100644 --- a/modules/navigation/nav_link.h +++ b/modules/navigation/nav_link.h @@ -43,6 +43,10 @@ class NavLink : public NavBase { bool link_dirty = true; public: + NavLink() { + type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_LINK; + } + void set_map(NavMap *p_map); NavMap *get_map() const { return map; diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 83862e1e34..8d58c9335d 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -38,6 +38,18 @@ #define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a))) +// Helper macro +#define APPEND_METADATA(poly) \ + if (r_path_types) { \ + r_path_types->push_back(poly->owner->get_type()); \ + } \ + if (r_path_rids) { \ + r_path_rids->push_back(poly->owner->get_self()); \ + } \ + if (r_path_owners) { \ + r_path_owners->push_back(poly->owner->get_owner_id()); \ + } + void NavMap::set_up(Vector3 p_up) { up = p_up; regenerate_polygons = true; @@ -71,7 +83,18 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { return p; } -Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const { +Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const { + // Clear metadata outputs. + if (r_path_types) { + r_path_types->clear(); + } + if (r_path_rids) { + r_path_rids->clear(); + } + if (r_path_owners) { + r_path_owners->clear(); + } + // Find the start poly and the end poly on this map. const gd::Polygon *begin_poly = nullptr; const gd::Polygon *end_poly = nullptr; @@ -115,6 +138,24 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p return Vector<Vector3>(); } if (begin_poly == end_poly) { + if (r_path_types) { + r_path_types->resize(2); + r_path_types->write[0] = begin_poly->owner->get_type(); + r_path_types->write[1] = end_poly->owner->get_type(); + } + + if (r_path_rids) { + r_path_rids->resize(2); + (*r_path_rids)[0] = begin_poly->owner->get_self(); + (*r_path_rids)[1] = end_poly->owner->get_self(); + } + + if (r_path_owners) { + r_path_owners->resize(2); + r_path_owners->write[0] = begin_poly->owner->get_owner_id(); + r_path_owners->write[1] = end_poly->owner->get_owner_id(); + } + Vector<Vector3> path; path.resize(2); path.write[0] = begin_point; @@ -296,6 +337,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p gd::NavigationPoly *p = apex_poly; path.push_back(end_point); + APPEND_METADATA(end_poly); while (p) { // Set left and right points of the pathway between polygons. @@ -312,7 +354,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p left_poly = p; left_portal = left; } else { - clip_path(navigation_polys, path, apex_poly, right_portal, right_poly); + clip_path(navigation_polys, path, apex_poly, right_portal, right_poly, r_path_types, r_path_rids, r_path_owners); apex_point = right_portal; p = right_poly; @@ -320,7 +362,9 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p apex_poly = p; left_portal = apex_point; right_portal = apex_point; + path.push_back(apex_point); + APPEND_METADATA(apex_poly->poly); skip = true; } } @@ -331,7 +375,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p right_poly = p; right_portal = right; } else { - clip_path(navigation_polys, path, apex_poly, left_portal, left_poly); + clip_path(navigation_polys, path, apex_poly, left_portal, left_poly, r_path_types, r_path_rids, r_path_owners); apex_point = left_portal; p = left_poly; @@ -339,7 +383,9 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p apex_poly = p; right_portal = apex_point; left_portal = apex_point; + path.push_back(apex_point); + APPEND_METADATA(apex_poly->poly); } } @@ -355,12 +401,23 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p // If the last point is not the begin point, add it to the list. if (path[path.size() - 1] != begin_point) { path.push_back(begin_point); + APPEND_METADATA(begin_poly); } path.reverse(); + if (r_path_types) { + r_path_types->reverse(); + } + if (r_path_rids) { + r_path_rids->reverse(); + } + if (r_path_owners) { + r_path_owners->reverse(); + } } else { path.push_back(end_point); + APPEND_METADATA(end_poly); // Add mid points int np_id = least_cost_id; @@ -369,18 +426,37 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p int prev = navigation_polys[np_id].back_navigation_edge; int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size(); Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5; + path.push_back(point); + APPEND_METADATA(navigation_polys[np_id].poly); } else { path.push_back(navigation_polys[np_id].entry); + APPEND_METADATA(navigation_polys[np_id].poly); } np_id = navigation_polys[np_id].back_navigation_poly_id; } path.push_back(begin_point); + APPEND_METADATA(begin_poly); + path.reverse(); + if (r_path_types) { + r_path_types->reverse(); + } + if (r_path_rids) { + r_path_rids->reverse(); + } + if (r_path_owners) { + r_path_owners->reverse(); + } } + // Ensure post conditions (path arrays MUST match in size). + CRASH_COND(r_path_types && path.size() != r_path_types->size()); + CRASH_COND(r_path_rids && path.size() != r_path_rids->size()); + CRASH_COND(r_path_owners && path.size() != r_path_owners->size()); + return path; } @@ -837,7 +913,7 @@ void NavMap::dispatch_callbacks() { } } -void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const { +void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const { Vector3 from = path[path.size() - 1]; if (from.is_equal_approx(p_to_point)) { @@ -863,6 +939,7 @@ void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) { if (!inters.is_equal_approx(p_to_point) && !inters.is_equal_approx(path[path.size() - 1])) { path.push_back(inters); + APPEND_METADATA(from_poly->poly); } } } diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index a3da9fa727..3be13133d2 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -115,7 +115,7 @@ public: gd::PointKey get_point_key(const Vector3 &p_pos) const; - Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const; + Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) 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; @@ -154,7 +154,7 @@ public: private: void compute_single_step(uint32_t index, RvoAgent **agent); - void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const; + void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const; }; #endif // NAV_MAP_H diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h index 8d2b5aa9eb..3ef3ef5748 100644 --- a/modules/navigation/nav_region.h +++ b/modules/navigation/nav_region.h @@ -48,7 +48,9 @@ class NavRegion : public NavBase { LocalVector<gd::Polygon> polygons; public: - NavRegion() {} + NavRegion() { + type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_REGION; + } void scratch_polygons() { polygons_dirty = true; diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 67c32dffb4..bf966db892 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -70,6 +70,9 @@ void NavigationAgent2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationAgent2D::set_navigation_layer_value); ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationAgent2D::get_navigation_layer_value); + ClassDB::bind_method(D_METHOD("set_path_metadata_flags", "flags"), &NavigationAgent2D::set_path_metadata_flags); + ClassDB::bind_method(D_METHOD("get_path_metadata_flags"), &NavigationAgent2D::get_path_metadata_flags); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent2D::set_navigation_map); ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent2D::get_navigation_map); @@ -79,6 +82,7 @@ void NavigationAgent2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent2D::get_next_location); ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent2D::distance_to_target); ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent2D::set_velocity); + ClassDB::bind_method(D_METHOD("get_current_navigation_result"), &NavigationAgent2D::get_current_navigation_result); ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent2D::get_current_navigation_path); ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent2D::get_current_navigation_path_index); ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent2D::is_target_reached); @@ -94,6 +98,7 @@ void NavigationAgent2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags"); ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); @@ -105,6 +110,8 @@ void NavigationAgent2D::_bind_methods() { ADD_SIGNAL(MethodInfo("path_changed")); ADD_SIGNAL(MethodInfo("target_reached")); + ADD_SIGNAL(MethodInfo("waypoint_reached", PropertyInfo(Variant::DICTIONARY, "details"))); + ADD_SIGNAL(MethodInfo("link_reached", PropertyInfo(Variant::DICTIONARY, "details"))); ADD_SIGNAL(MethodInfo("navigation_finished")); ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR2, "safe_velocity"))); } @@ -256,6 +263,14 @@ bool NavigationAgent2D::get_navigation_layer_value(int p_layer_number) const { return get_navigation_layers() & (1 << (p_layer_number - 1)); } +void NavigationAgent2D::set_path_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_path_metadata_flags) { + if (path_metadata_flags == p_path_metadata_flags) { + return; + } + + path_metadata_flags = p_path_metadata_flags; +} + void NavigationAgent2D::set_navigation_map(RID p_navigation_map) { map_override = p_navigation_map; NavigationServer2D::get_singleton()->agent_set_map(agent, map_override); @@ -333,10 +348,6 @@ Vector2 NavigationAgent2D::get_next_location() { } } -const Vector<Vector2> &NavigationAgent2D::get_current_navigation_path() const { - return navigation_result->get_path(); -} - real_t NavigationAgent2D::distance_to_target() const { ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent."); return agent_parent->get_global_position().distance_to(target_location); @@ -436,6 +447,7 @@ void NavigationAgent2D::update_navigation() { navigation_query->set_start_position(origin); navigation_query->set_target_position(target_location); navigation_query->set_navigation_layers(navigation_layers); + navigation_query->set_metadata_flags(path_metadata_flags); if (map_override.is_valid()) { navigation_query->set_map(map_override); @@ -457,8 +469,52 @@ void NavigationAgent2D::update_navigation() { if (navigation_finished == false) { // Advances to the next far away location. const Vector<Vector2> &navigation_path = navigation_result->get_path(); + const Vector<int32_t> &navigation_path_types = navigation_result->get_path_types(); + const TypedArray<RID> &navigation_path_rids = navigation_result->get_path_rids(); + const Vector<int64_t> &navigation_path_owners = navigation_result->get_path_owner_ids(); + while (origin.distance_to(navigation_path[navigation_path_index]) < path_desired_distance) { + Dictionary details; + + const Vector2 waypoint = navigation_path[navigation_path_index]; + details[SNAME("location")] = waypoint; + + int waypoint_type = -1; + if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_TYPES)) { + const NavigationPathQueryResult2D::PathSegmentType type = NavigationPathQueryResult2D::PathSegmentType(navigation_path_types[navigation_path_index]); + + details[SNAME("type")] = type; + waypoint_type = type; + } + + if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_RIDS)) { + details[SNAME("rid")] = navigation_path_rids[navigation_path_index]; + } + + if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_OWNERS)) { + const ObjectID waypoint_owner_id = ObjectID(navigation_path_owners[navigation_path_index]); + + // Get a reference to the owning object. + Object *owner = nullptr; + if (waypoint_owner_id.is_valid()) { + owner = ObjectDB::get_instance(waypoint_owner_id); + } + + details[SNAME("owner")] = owner; + } + + // Emit a signal for the waypoint + emit_signal(SNAME("waypoint_reached"), details); + + // Emit a signal if we've reached a navigation link + if (waypoint_type == NavigationPathQueryResult2D::PATH_SEGMENT_TYPE_LINK) { + emit_signal(SNAME("link_reached"), details); + } + + // Move to the next waypoint on the list navigation_path_index += 1; + + // Check to see if we've finished our route if (navigation_path_index == navigation_path.size()) { _check_distance_to_target(); navigation_path_index -= 1; diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 2c77bdc8db..747c1570f8 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -32,10 +32,10 @@ #define NAVIGATION_AGENT_2D_H #include "scene/main/node.h" +#include "servers/navigation/navigation_path_query_parameters_2d.h" +#include "servers/navigation/navigation_path_query_result_2d.h" class Node2D; -class NavigationPathQueryParameters2D; -class NavigationPathQueryResult2D; class NavigationAgent2D : public Node { GDCLASS(NavigationAgent2D, Node); @@ -48,6 +48,7 @@ class NavigationAgent2D : public Node { bool avoidance_enabled = false; uint32_t navigation_layers = 1; + BitField<NavigationPathQueryParameters2D::PathMetadataFlags> path_metadata_flags = NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_ALL; real_t path_desired_distance = 1.0; real_t target_desired_distance = 1.0; @@ -95,6 +96,11 @@ public: void set_navigation_layer_value(int p_layer_number, bool p_value); bool get_navigation_layer_value(int p_layer_number) const; + void set_path_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags); + BitField<NavigationPathQueryParameters2D::PathMetadataFlags> get_path_metadata_flags() const { + return path_metadata_flags; + } + void set_navigation_map(RID p_navigation_map); RID get_navigation_map() const; @@ -141,8 +147,12 @@ public: Vector2 get_next_location(); - const Vector<Vector2> &get_current_navigation_path() const; - + Ref<NavigationPathQueryResult2D> get_current_navigation_result() const { + return navigation_result; + } + const Vector<Vector2> &get_current_navigation_path() const { + return navigation_result->get_path(); + } int get_current_navigation_path_index() const { return navigation_path_index; } diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 08ceb946df..26dd8dfba9 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -74,6 +74,9 @@ void NavigationAgent3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationAgent3D::set_navigation_layer_value); ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationAgent3D::get_navigation_layer_value); + ClassDB::bind_method(D_METHOD("set_path_metadata_flags", "flags"), &NavigationAgent3D::set_path_metadata_flags); + ClassDB::bind_method(D_METHOD("get_path_metadata_flags"), &NavigationAgent3D::get_path_metadata_flags); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent3D::set_navigation_map); ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent3D::get_navigation_map); @@ -83,6 +86,7 @@ void NavigationAgent3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent3D::get_next_location); ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent3D::distance_to_target); ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent3D::set_velocity); + ClassDB::bind_method(D_METHOD("get_current_navigation_result"), &NavigationAgent3D::get_current_navigation_result); ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent3D::get_current_navigation_path); ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent3D::get_current_navigation_path_index); ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent3D::is_target_reached); @@ -99,6 +103,7 @@ void NavigationAgent3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags"); ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); @@ -111,6 +116,8 @@ void NavigationAgent3D::_bind_methods() { ADD_SIGNAL(MethodInfo("path_changed")); ADD_SIGNAL(MethodInfo("target_reached")); + ADD_SIGNAL(MethodInfo("waypoint_reached", PropertyInfo(Variant::DICTIONARY, "details"))); + ADD_SIGNAL(MethodInfo("link_reached", PropertyInfo(Variant::DICTIONARY, "details"))); ADD_SIGNAL(MethodInfo("navigation_finished")); ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); } @@ -263,6 +270,14 @@ bool NavigationAgent3D::get_navigation_layer_value(int p_layer_number) const { return get_navigation_layers() & (1 << (p_layer_number - 1)); } +void NavigationAgent3D::set_path_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_path_metadata_flags) { + if (path_metadata_flags == p_path_metadata_flags) { + return; + } + + path_metadata_flags = p_path_metadata_flags; +} + void NavigationAgent3D::set_navigation_map(RID p_navigation_map) { map_override = p_navigation_map; NavigationServer3D::get_singleton()->agent_set_map(agent, map_override); @@ -349,10 +364,6 @@ Vector3 NavigationAgent3D::get_next_location() { } } -const Vector<Vector3> &NavigationAgent3D::get_current_navigation_path() const { - return navigation_result->get_path(); -} - real_t NavigationAgent3D::distance_to_target() const { ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent."); return agent_parent->get_global_transform().origin.distance_to(target_location); @@ -453,6 +464,7 @@ void NavigationAgent3D::update_navigation() { navigation_query->set_start_position(origin); navigation_query->set_target_position(target_location); navigation_query->set_navigation_layers(navigation_layers); + navigation_query->set_metadata_flags(path_metadata_flags); if (map_override.is_valid()) { navigation_query->set_map(map_override); @@ -474,8 +486,52 @@ void NavigationAgent3D::update_navigation() { if (navigation_finished == false) { // Advances to the next far away location. const Vector<Vector3> &navigation_path = navigation_result->get_path(); + const Vector<int32_t> &navigation_path_types = navigation_result->get_path_types(); + const TypedArray<RID> &navigation_path_rids = navigation_result->get_path_rids(); + const Vector<int64_t> &navigation_path_owners = navigation_result->get_path_owner_ids(); + while (origin.distance_to(navigation_path[navigation_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) { + Dictionary details; + + const Vector3 waypoint = navigation_path[navigation_path_index]; + details[SNAME("location")] = waypoint; + + int waypoint_type = -1; + if (path_metadata_flags.has_flag(NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_TYPES)) { + const NavigationPathQueryResult3D::PathSegmentType type = NavigationPathQueryResult3D::PathSegmentType(navigation_path_types[navigation_path_index]); + + details[SNAME("type")] = type; + waypoint_type = type; + } + + if (path_metadata_flags.has_flag(NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_RIDS)) { + details[SNAME("rid")] = navigation_path_rids[navigation_path_index]; + } + + if (path_metadata_flags.has_flag(NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_OWNERS)) { + const ObjectID waypoint_owner_id = ObjectID(navigation_path_owners[navigation_path_index]); + + // Get a reference to the owning object. + Object *owner = nullptr; + if (waypoint_owner_id.is_valid()) { + owner = ObjectDB::get_instance(waypoint_owner_id); + } + + details[SNAME("owner")] = owner; + } + + // Emit a signal for the waypoint + emit_signal(SNAME("waypoint_reached"), details); + + // Emit a signal if we've reached a navigation link + if (waypoint_type == NavigationPathQueryResult3D::PATH_SEGMENT_TYPE_LINK) { + emit_signal(SNAME("link_reached"), details); + } + + // Move to the next waypoint on the list navigation_path_index += 1; + + // Check to see if we've finished our route if (navigation_path_index == navigation_path.size()) { _check_distance_to_target(); navigation_path_index -= 1; diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 1caa783a8b..b950367a87 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -32,10 +32,10 @@ #define NAVIGATION_AGENT_3D_H #include "scene/main/node.h" +#include "servers/navigation/navigation_path_query_parameters_3d.h" +#include "servers/navigation/navigation_path_query_result_3d.h" class Node3D; -class NavigationPathQueryParameters3D; -class NavigationPathQueryResult3D; class NavigationAgent3D : public Node { GDCLASS(NavigationAgent3D, Node); @@ -48,6 +48,7 @@ class NavigationAgent3D : public Node { bool avoidance_enabled = false; uint32_t navigation_layers = 1; + BitField<NavigationPathQueryParameters3D::PathMetadataFlags> path_metadata_flags = NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_ALL; real_t path_desired_distance = 1.0; real_t target_desired_distance = 1.0; @@ -97,6 +98,11 @@ public: void set_navigation_layer_value(int p_layer_number, bool p_value); bool get_navigation_layer_value(int p_layer_number) const; + void set_path_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_flags); + BitField<NavigationPathQueryParameters3D::PathMetadataFlags> get_path_metadata_flags() const { + return path_metadata_flags; + } + void set_navigation_map(RID p_navigation_map); RID get_navigation_map() const; @@ -153,8 +159,12 @@ public: Vector3 get_next_location(); - const Vector<Vector3> &get_current_navigation_path() const; - + Ref<NavigationPathQueryResult3D> get_current_navigation_result() const { + return navigation_result; + } + const Vector<Vector3> &get_current_navigation_path() const { + return navigation_result->get_path(); + } int get_current_navigation_path_index() const { return navigation_path_index; } diff --git a/servers/navigation/navigation_path_query_parameters_2d.cpp b/servers/navigation/navigation_path_query_parameters_2d.cpp index 574af90be1..717ada3834 100644 --- a/servers/navigation/navigation_path_query_parameters_2d.cpp +++ b/servers/navigation/navigation_path_query_parameters_2d.cpp @@ -105,11 +105,19 @@ Vector2 NavigationPathQueryParameters2D::get_target_position() const { void NavigationPathQueryParameters2D::set_navigation_layers(uint32_t p_navigation_layers) { parameters.navigation_layers = p_navigation_layers; -}; +} uint32_t NavigationPathQueryParameters2D::get_navigation_layers() const { return parameters.navigation_layers; -}; +} + +void NavigationPathQueryParameters2D::set_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags) { + parameters.metadata_flags = (int64_t)p_flags; +} + +BitField<NavigationPathQueryParameters2D::PathMetadataFlags> NavigationPathQueryParameters2D::get_metadata_flags() const { + return (int64_t)parameters.metadata_flags; +} void NavigationPathQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters2D::set_pathfinding_algorithm); @@ -130,15 +138,25 @@ void NavigationPathQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationPathQueryParameters2D::set_navigation_layers); ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationPathQueryParameters2D::get_navigation_layers); + ClassDB::bind_method(D_METHOD("set_metadata_flags", "flags"), &NavigationPathQueryParameters2D::set_metadata_flags); + ClassDB::bind_method(D_METHOD("get_metadata_flags"), &NavigationPathQueryParameters2D::get_metadata_flags); + ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_position"), "set_start_position", "get_start_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "pathfinding_algorithm", PROPERTY_HINT_ENUM, "AStar"), "set_pathfinding_algorithm", "get_pathfinding_algorithm"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_postprocessing", PROPERTY_HINT_ENUM, "Corridorfunnel,Edgecentered"), "set_path_postprocessing", "get_path_postprocessing"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_metadata_flags", "get_metadata_flags"); BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR); BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_CORRIDORFUNNEL); BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_EDGECENTERED); + + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_NONE); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_TYPES); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_RIDS); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_OWNERS); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_ALL); } diff --git a/servers/navigation/navigation_path_query_parameters_2d.h b/servers/navigation/navigation_path_query_parameters_2d.h index c0ef337a27..aeabe1f690 100644 --- a/servers/navigation/navigation_path_query_parameters_2d.h +++ b/servers/navigation/navigation_path_query_parameters_2d.h @@ -52,6 +52,14 @@ public: PATH_POSTPROCESSING_EDGECENTERED, }; + enum PathMetadataFlags { + PATH_METADATA_INCLUDE_NONE = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_NONE, + PATH_METADATA_INCLUDE_TYPES = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_TYPES, + PATH_METADATA_INCLUDE_RIDS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_RIDS, + PATH_METADATA_INCLUDE_OWNERS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_OWNERS, + PATH_METADATA_INCLUDE_ALL = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_ALL + }; + const NavigationUtilities::PathQueryParameters &get_parameters() const { return parameters; } void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm); @@ -71,9 +79,13 @@ public: void set_navigation_layers(uint32_t p_navigation_layers); uint32_t get_navigation_layers() const; + + void set_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags); + BitField<NavigationPathQueryParameters2D::PathMetadataFlags> get_metadata_flags() const; }; VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathfindingAlgorithm); VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathPostProcessing); +VARIANT_BITFIELD_CAST(NavigationPathQueryParameters2D::PathMetadataFlags); #endif // NAVIGATION_PATH_QUERY_PARAMETERS_2D_H diff --git a/servers/navigation/navigation_path_query_parameters_3d.cpp b/servers/navigation/navigation_path_query_parameters_3d.cpp index b09448e82e..180af57af5 100644 --- a/servers/navigation/navigation_path_query_parameters_3d.cpp +++ b/servers/navigation/navigation_path_query_parameters_3d.cpp @@ -111,6 +111,14 @@ uint32_t NavigationPathQueryParameters3D::get_navigation_layers() const { return parameters.navigation_layers; } +void NavigationPathQueryParameters3D::set_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_flags) { + parameters.metadata_flags = (int64_t)p_flags; +} + +BitField<NavigationPathQueryParameters3D::PathMetadataFlags> NavigationPathQueryParameters3D::get_metadata_flags() const { + return (int64_t)parameters.metadata_flags; +} + void NavigationPathQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters3D::set_pathfinding_algorithm); ClassDB::bind_method(D_METHOD("get_pathfinding_algorithm"), &NavigationPathQueryParameters3D::get_pathfinding_algorithm); @@ -130,15 +138,25 @@ void NavigationPathQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationPathQueryParameters3D::set_navigation_layers); ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationPathQueryParameters3D::get_navigation_layers); + ClassDB::bind_method(D_METHOD("set_metadata_flags", "flags"), &NavigationPathQueryParameters3D::set_metadata_flags); + ClassDB::bind_method(D_METHOD("get_metadata_flags"), &NavigationPathQueryParameters3D::get_metadata_flags); + ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_position"), "set_start_position", "get_start_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "pathfinding_algorithm", PROPERTY_HINT_ENUM, "AStar"), "set_pathfinding_algorithm", "get_pathfinding_algorithm"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_postprocessing", PROPERTY_HINT_ENUM, "Corridorfunnel,Edgecentered"), "set_path_postprocessing", "get_path_postprocessing"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_metadata_flags", "get_metadata_flags"); BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR); BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_CORRIDORFUNNEL); BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_EDGECENTERED); + + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_NONE); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_TYPES); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_RIDS); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_OWNERS); + BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_ALL); } diff --git a/servers/navigation/navigation_path_query_parameters_3d.h b/servers/navigation/navigation_path_query_parameters_3d.h index b4cf02fc79..386c83dece 100644 --- a/servers/navigation/navigation_path_query_parameters_3d.h +++ b/servers/navigation/navigation_path_query_parameters_3d.h @@ -52,6 +52,14 @@ public: PATH_POSTPROCESSING_EDGECENTERED, }; + enum PathMetadataFlags { + PATH_METADATA_INCLUDE_NONE = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_NONE, + PATH_METADATA_INCLUDE_TYPES = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_TYPES, + PATH_METADATA_INCLUDE_RIDS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_RIDS, + PATH_METADATA_INCLUDE_OWNERS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_OWNERS, + PATH_METADATA_INCLUDE_ALL = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_ALL + }; + const NavigationUtilities::PathQueryParameters &get_parameters() const { return parameters; } void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm); @@ -71,9 +79,13 @@ public: void set_navigation_layers(uint32_t p_navigation_layers); uint32_t get_navigation_layers() const; + + void set_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_flags); + BitField<NavigationPathQueryParameters3D::PathMetadataFlags> get_metadata_flags() const; }; VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathfindingAlgorithm); VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathPostProcessing); +VARIANT_BITFIELD_CAST(NavigationPathQueryParameters3D::PathMetadataFlags); #endif // NAVIGATION_PATH_QUERY_PARAMETERS_3D_H diff --git a/servers/navigation/navigation_path_query_result_2d.cpp b/servers/navigation/navigation_path_query_result_2d.cpp index 8a55451e40..e2764daa9a 100644 --- a/servers/navigation/navigation_path_query_result_2d.cpp +++ b/servers/navigation/navigation_path_query_result_2d.cpp @@ -38,15 +38,57 @@ const Vector<Vector2> &NavigationPathQueryResult2D::get_path() const { return path; } +void NavigationPathQueryResult2D::set_path_types(const Vector<int32_t> &p_path_types) { + path_types = p_path_types; +} + +const Vector<int32_t> &NavigationPathQueryResult2D::get_path_types() const { + return path_types; +} + +void NavigationPathQueryResult2D::set_path_rids(const TypedArray<RID> &p_path_rids) { + path_rids = p_path_rids; +} + +TypedArray<RID> NavigationPathQueryResult2D::get_path_rids() const { + return path_rids; +} + +void NavigationPathQueryResult2D::set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids) { + path_owner_ids = p_path_owner_ids; +} + +const Vector<int64_t> &NavigationPathQueryResult2D::get_path_owner_ids() const { + return path_owner_ids; +} + void NavigationPathQueryResult2D::reset() { path.clear(); + path_types.clear(); + path_rids.clear(); + path_owner_ids.clear(); } void NavigationPathQueryResult2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult2D::set_path); ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult2D::get_path); + ClassDB::bind_method(D_METHOD("set_path_types", "path_types"), &NavigationPathQueryResult2D::set_path_types); + ClassDB::bind_method(D_METHOD("get_path_types"), &NavigationPathQueryResult2D::get_path_types); + + ClassDB::bind_method(D_METHOD("set_path_rids", "path_rids"), &NavigationPathQueryResult2D::set_path_rids); + ClassDB::bind_method(D_METHOD("get_path_rids"), &NavigationPathQueryResult2D::get_path_rids); + + ClassDB::bind_method(D_METHOD("set_path_owner_ids", "path_owner_ids"), &NavigationPathQueryResult2D::set_path_owner_ids); + ClassDB::bind_method(D_METHOD("get_path_owner_ids"), &NavigationPathQueryResult2D::get_path_owner_ids); + ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult2D::reset); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "path"), "set_path", "get_path"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "path_types"), "set_path_types", "get_path_types"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "path_rids", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_path_rids", "get_path_rids"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT64_ARRAY, "path_owner_ids"), "set_path_owner_ids", "get_path_owner_ids"); + + BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_REGION); + BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_LINK); } diff --git a/servers/navigation/navigation_path_query_result_2d.h b/servers/navigation/navigation_path_query_result_2d.h index da251ef32d..852a9780ef 100644 --- a/servers/navigation/navigation_path_query_result_2d.h +++ b/servers/navigation/navigation_path_query_result_2d.h @@ -38,15 +38,34 @@ class NavigationPathQueryResult2D : public RefCounted { GDCLASS(NavigationPathQueryResult2D, RefCounted); Vector<Vector2> path; + Vector<int32_t> path_types; + TypedArray<RID> path_rids; + Vector<int64_t> path_owner_ids; protected: static void _bind_methods(); public: + enum PathSegmentType { + PATH_SEGMENT_TYPE_REGION = 0, + PATH_SEGMENT_TYPE_LINK = 1, + }; + void set_path(const Vector<Vector2> &p_path); const Vector<Vector2> &get_path() const; + void set_path_types(const Vector<int32_t> &p_path_types); + const Vector<int32_t> &get_path_types() const; + + void set_path_rids(const TypedArray<RID> &p_path_rids); + TypedArray<RID> get_path_rids() const; + + void set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids); + const Vector<int64_t> &get_path_owner_ids() const; + void reset(); }; +VARIANT_ENUM_CAST(NavigationPathQueryResult2D::PathSegmentType); + #endif // NAVIGATION_PATH_QUERY_RESULT_2D_H diff --git a/servers/navigation/navigation_path_query_result_3d.cpp b/servers/navigation/navigation_path_query_result_3d.cpp index 1e28352995..8218adec18 100644 --- a/servers/navigation/navigation_path_query_result_3d.cpp +++ b/servers/navigation/navigation_path_query_result_3d.cpp @@ -38,15 +38,57 @@ const Vector<Vector3> &NavigationPathQueryResult3D::get_path() const { return path; } +void NavigationPathQueryResult3D::set_path_types(const Vector<int32_t> &p_path_types) { + path_types = p_path_types; +} + +const Vector<int32_t> &NavigationPathQueryResult3D::get_path_types() const { + return path_types; +} + +void NavigationPathQueryResult3D::set_path_rids(const TypedArray<RID> &p_path_rids) { + path_rids = p_path_rids; +} + +TypedArray<RID> NavigationPathQueryResult3D::get_path_rids() const { + return path_rids; +} + +void NavigationPathQueryResult3D::set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids) { + path_owner_ids = p_path_owner_ids; +} + +const Vector<int64_t> &NavigationPathQueryResult3D::get_path_owner_ids() const { + return path_owner_ids; +} + void NavigationPathQueryResult3D::reset() { path.clear(); + path_types.clear(); + path_rids.clear(); + path_owner_ids.clear(); } void NavigationPathQueryResult3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult3D::set_path); ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult3D::get_path); + ClassDB::bind_method(D_METHOD("set_path_types", "path_types"), &NavigationPathQueryResult3D::set_path_types); + ClassDB::bind_method(D_METHOD("get_path_types"), &NavigationPathQueryResult3D::get_path_types); + + ClassDB::bind_method(D_METHOD("set_path_rids", "path_rids"), &NavigationPathQueryResult3D::set_path_rids); + ClassDB::bind_method(D_METHOD("get_path_rids"), &NavigationPathQueryResult3D::get_path_rids); + + ClassDB::bind_method(D_METHOD("set_path_owner_ids", "path_owner_ids"), &NavigationPathQueryResult3D::set_path_owner_ids); + ClassDB::bind_method(D_METHOD("get_path_owner_ids"), &NavigationPathQueryResult3D::get_path_owner_ids); + ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult3D::reset); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "path"), "set_path", "get_path"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "path_types"), "set_path_types", "get_path_types"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "path_rids", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_path_rids", "get_path_rids"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT64_ARRAY, "path_owner_ids"), "set_path_owner_ids", "get_path_owner_ids"); + + BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_REGION); + BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_LINK); } diff --git a/servers/navigation/navigation_path_query_result_3d.h b/servers/navigation/navigation_path_query_result_3d.h index fc143ac389..ce34e18dc1 100644 --- a/servers/navigation/navigation_path_query_result_3d.h +++ b/servers/navigation/navigation_path_query_result_3d.h @@ -32,21 +32,41 @@ #define NAVIGATION_PATH_QUERY_RESULT_3D_H #include "core/object/ref_counted.h" +#include "core/variant/typed_array.h" #include "servers/navigation/navigation_utilities.h" class NavigationPathQueryResult3D : public RefCounted { GDCLASS(NavigationPathQueryResult3D, RefCounted); Vector<Vector3> path; + Vector<int32_t> path_types; + TypedArray<RID> path_rids; + Vector<int64_t> path_owner_ids; protected: static void _bind_methods(); public: + enum PathSegmentType { + PATH_SEGMENT_TYPE_REGION = 0, + PATH_SEGMENT_TYPE_LINK = 1, + }; + void set_path(const Vector<Vector3> &p_path); const Vector<Vector3> &get_path() const; + void set_path_types(const Vector<int32_t> &p_path_types); + const Vector<int32_t> &get_path_types() const; + + void set_path_rids(const TypedArray<RID> &p_path_rids); + TypedArray<RID> get_path_rids() const; + + void set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids); + const Vector<int64_t> &get_path_owner_ids() const; + void reset(); }; +VARIANT_ENUM_CAST(NavigationPathQueryResult3D::PathSegmentType); + #endif // NAVIGATION_PATH_QUERY_RESULT_3D_H diff --git a/servers/navigation/navigation_utilities.h b/servers/navigation/navigation_utilities.h index e99c139528..c22a2ed952 100644 --- a/servers/navigation/navigation_utilities.h +++ b/servers/navigation/navigation_utilities.h @@ -32,6 +32,7 @@ #define NAVIGATION_UTILITIES_H #include "core/math/vector3.h" +#include "core/variant/typed_array.h" namespace NavigationUtilities { @@ -44,6 +45,19 @@ enum PathPostProcessing { PATH_POSTPROCESSING_EDGECENTERED, }; +enum PathSegmentType { + PATH_SEGMENT_TYPE_REGION = 0, + PATH_SEGMENT_TYPE_LINK +}; + +enum PathMetadataFlags { + PATH_INCLUDE_NONE = 0, + PATH_INCLUDE_TYPES = 1, + PATH_INCLUDE_RIDS = 2, + PATH_INCLUDE_OWNERS = 4, + PATH_INCLUDE_ALL = PATH_INCLUDE_TYPES | PATH_INCLUDE_RIDS | PATH_INCLUDE_OWNERS +}; + struct PathQueryParameters { PathfindingAlgorithm pathfinding_algorithm = PATHFINDING_ALGORITHM_ASTAR; PathPostProcessing path_postprocessing = PATH_POSTPROCESSING_CORRIDORFUNNEL; @@ -51,10 +65,14 @@ struct PathQueryParameters { Vector3 start_position; Vector3 target_position; uint32_t navigation_layers = 1; + BitField<PathMetadataFlags> metadata_flags = PATH_INCLUDE_ALL; }; struct PathQueryResult { Vector<Vector3> path; + Vector<int32_t> path_types; + TypedArray<RID> path_rids; + Vector<int64_t> path_owner_ids; }; } //namespace NavigationUtilities diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 1614b8e2f5..6fd5f222cf 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -427,4 +427,7 @@ void NavigationServer2D::query_path(const Ref<NavigationPathQueryParameters2D> & const NavigationUtilities::PathQueryResult _query_result = NavigationServer3D::get_singleton()->_query_path(p_query_parameters->get_parameters()); p_query_result->set_path(vector_v3_to_v2(_query_result.path)); + p_query_result->set_path_types(_query_result.path_types); + p_query_result->set_path_rids(_query_result.path_rids); + p_query_result->set_path_owner_ids(_query_result.path_owner_ids); } diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index cbefe48633..6ad07d3053 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -491,4 +491,7 @@ void NavigationServer3D::query_path(const Ref<NavigationPathQueryParameters3D> & const NavigationUtilities::PathQueryResult _query_result = _query_path(p_query_parameters->get_parameters()); p_query_result->set_path(_query_result.path); + p_query_result->set_path_types(_query_result.path_types); + p_query_result->set_path_rids(_query_result.path_rids); + p_query_result->set_path_owner_ids(_query_result.path_owner_ids); } |