Added node for Navigation links

This commit is contained in:
Josh Jones 2022-01-30 15:39:52 -08:00
parent 4808d01b2b
commit 3dd59013f4
34 changed files with 2563 additions and 49 deletions

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="NavigationLink2D" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Creates a link between two locations that [NavigationServer2D] can route agents through.
</brief_description>
<description>
Creates a link between two locations that [NavigationServer2D] can route agents through. Links can be used to express navigation methods that aren't just traveling along the surface of the navigation mesh, like zip-lines, teleporters, or jumping across gaps.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
<description>
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
<method name="set_navigation_layer_value">
<return type="void" />
<param index="0" name="layer_number" type="int" />
<param index="1" name="value" type="bool" />
<description>
Based on [code]value[/code], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
</methods>
<members>
<member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true">
Whether this link can be traveled in both directions or only from [member start_location] to [member end_location].
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
Whether this link is currently active. If [code]false[/code], [method NavigationServer2D.map_get_path] will ignore this link.
</member>
<member name="end_location" type="Vector2" setter="set_end_location" getter="get_end_location" default="Vector2(0, 0)">
Ending position of the link.
This position will search out the nearest polygon in the navigation mesh to attach to.
The distance the link will search is controlled by [method NavigationServer2D.map_set_link_connection_radius].
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
When pathfinding enters this link from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the link belongs to. These navigation layers will be checked when requesting a path with [method NavigationServer2D.map_get_path].
</member>
<member name="start_location" type="Vector2" setter="set_start_location" getter="get_start_location" default="Vector2(0, 0)">
Starting position of the link.
This position will search out the nearest polygon in the navigation mesh to attach to.
The distance the link will search is controlled by [method NavigationServer2D.map_set_link_connection_radius].
</member>
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
When pathfinding moves along the link the traveled distance is multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
</members>
</class>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="NavigationLink3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Creates a link between two locations that [NavigationServer3D] can route agents through.
</brief_description>
<description>
Creates a link between two locations that [NavigationServer3D] can route agents through. Links can be used to express navigation methods that aren't just traveling along the surface of the navigation mesh, like zip-lines, teleporters, or jumping across gaps.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
<description>
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
<method name="set_navigation_layer_value">
<return type="void" />
<param index="0" name="layer_number" type="int" />
<param index="1" name="value" type="bool" />
<description>
Based on [code]value[/code], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
</methods>
<members>
<member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true">
Whether this link can be traveled in both directions or only from [member start_location] to [member end_location].
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
Whether this link is currently active. If [code]false[/code], [method NavigationServer3D.map_get_path] will ignore this link.
</member>
<member name="end_location" type="Vector3" setter="set_end_location" getter="get_end_location" default="Vector3(0, 0, 0)">
Ending position of the link.
This position will search out the nearest polygon in the navigation mesh to attach to.
The distance the link will search is controlled by [method NavigationServer3D.map_set_link_connection_radius].
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
When pathfinding enters this link from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the link belongs to. These navigation layers will be checked when requesting a path with [method NavigationServer3D.map_get_path].
</member>
<member name="start_location" type="Vector3" setter="set_start_location" getter="get_start_location" default="Vector3(0, 0, 0)">
Starting position of the link.
This position will search out the nearest polygon in the navigation mesh to attach to.
The distance the link will search is controlled by [method NavigationServer3D.map_set_link_connection_radius].
</member>
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
When pathfinding moves along the link the traveled distance is multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
</members>
</class>

View File

@ -133,6 +133,117 @@
Returns all created navigation map [RID]s on the NavigationServer. This returns both 2D and 3D created navigation maps as there is technically no distinction between them. Returns all created navigation map [RID]s on the NavigationServer. This returns both 2D and 3D created navigation maps as there is technically no distinction between them.
</description> </description>
</method> </method>
<method name="link_create" qualifiers="const">
<return type="RID" />
<description>
Create a new link between two locations on a map.
</description>
</method>
<method name="link_get_end_location" qualifiers="const">
<return type="Vector2" />
<param index="0" name="link" type="RID" />
<description>
Returns the ending location of this [code]link[/code].
</description>
</method>
<method name="link_get_enter_cost" qualifiers="const">
<return type="float" />
<param index="0" name="link" type="RID" />
<description>
Returns the [code]enter_cost[/code] of this [code]link[/code].
</description>
</method>
<method name="link_get_map" qualifiers="const">
<return type="RID" />
<param index="0" name="link" type="RID" />
<description>
Returns the navigation map [RID] the requested [code]link[/code] is currently assigned to.
</description>
</method>
<method name="link_get_navigation_layers" qualifiers="const">
<return type="int" />
<param index="0" name="link" type="RID" />
<description>
Returns the navigation layers for this [code]link[/code].
</description>
</method>
<method name="link_get_start_location" qualifiers="const">
<return type="Vector2" />
<param index="0" name="link" type="RID" />
<description>
Returns the starting location of this [code]link[/code].
</description>
</method>
<method name="link_get_travel_cost" qualifiers="const">
<return type="float" />
<param index="0" name="link" type="RID" />
<description>
Returns the [code]travel_cost[/code] of this [code]link[/code].
</description>
</method>
<method name="link_is_bidirectional" qualifiers="const">
<return type="bool" />
<param index="0" name="link" type="RID" />
<description>
Returns whether this [code]link[/code] can be travelled in both directions.
</description>
</method>
<method name="link_set_bidirectional" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="bidirectional" type="bool" />
<description>
Sets whether this [code]link[/code] can be travelled in both directions.
</description>
</method>
<method name="link_set_end_location" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="location" type="Vector2" />
<description>
Sets the exit location for the [code]link[/code].
</description>
</method>
<method name="link_set_enter_cost" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="enter_cost" type="float" />
<description>
Sets the [code]enter_cost[/code] for this [code]link[/code].
</description>
</method>
<method name="link_set_map" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="map" type="RID" />
<description>
Sets the navigation map [RID] for the link.
</description>
</method>
<method name="link_set_navigation_layers" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="navigation_layers" type="int" />
<description>
Set the links's navigation layers. This allows selecting links from a path request (when using [method NavigationServer2D.map_get_path]).
</description>
</method>
<method name="link_set_start_location" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="location" type="Vector2" />
<description>
Sets the entry location for this [code]link[/code].
</description>
</method>
<method name="link_set_travel_cost" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="travel_cost" type="float" />
<description>
Sets the [code]travel_cost[/code] for this [code]link[/code].
</description>
</method>
<method name="map_create" qualifiers="const"> <method name="map_create" qualifiers="const">
<return type="RID" /> <return type="RID" />
<description> <description>
@ -186,6 +297,20 @@
Returns the edge connection margin of the map. The edge connection margin is a distance used to connect two regions. Returns the edge connection margin of the map. The edge connection margin is a distance used to connect two regions.
</description> </description>
</method> </method>
<method name="map_get_link_connection_radius" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />
<description>
Returns the link connection radius of the map. This distance is the maximum range any link will search for navigation mesh polygons to connect to.
</description>
</method>
<method name="map_get_links" qualifiers="const">
<return type="RID[]" />
<param index="0" name="map" type="RID" />
<description>
Returns all navigation link [RID]s that are currently assigned to the requested navigation [code]map[/code].
</description>
</method>
<method name="map_get_path" qualifiers="const"> <method name="map_get_path" qualifiers="const">
<return type="PackedVector2Array" /> <return type="PackedVector2Array" />
<param index="0" name="map" type="RID" /> <param index="0" name="map" type="RID" />
@ -235,6 +360,14 @@
Set the map edge connection margin used to weld the compatible region edges. Set the map edge connection margin used to weld the compatible region edges.
</description> </description>
</method> </method>
<method name="map_set_link_connection_radius" qualifiers="const">
<return type="void" />
<param index="0" name="map" type="RID" />
<param index="1" name="radius" type="float" />
<description>
Set the map's link connection radius used to connect links to navigation polygons.
</description>
</method>
<method name="region_create" qualifiers="const"> <method name="region_create" qualifiers="const">
<return type="RID" /> <return type="RID" />
<description> <description>

View File

@ -133,6 +133,117 @@
Returns all created navigation map [RID]s on the NavigationServer. This returns both 2D and 3D created navigation maps as there is technically no distinction between them. Returns all created navigation map [RID]s on the NavigationServer. This returns both 2D and 3D created navigation maps as there is technically no distinction between them.
</description> </description>
</method> </method>
<method name="link_create" qualifiers="const">
<return type="RID" />
<description>
Create a new link between two locations on a map.
</description>
</method>
<method name="link_get_end_location" qualifiers="const">
<return type="Vector3" />
<param index="0" name="link" type="RID" />
<description>
Returns the ending location of this [code]link[/code].
</description>
</method>
<method name="link_get_enter_cost" qualifiers="const">
<return type="float" />
<param index="0" name="link" type="RID" />
<description>
Returns the [code]enter_cost[/code] of this [code]link[/code].
</description>
</method>
<method name="link_get_map" qualifiers="const">
<return type="RID" />
<param index="0" name="link" type="RID" />
<description>
Returns the navigation map [RID] the requested [code]link[/code] is currently assigned to.
</description>
</method>
<method name="link_get_navigation_layers" qualifiers="const">
<return type="int" />
<param index="0" name="link" type="RID" />
<description>
Returns the navigation layers for this [code]link[/code].
</description>
</method>
<method name="link_get_start_location" qualifiers="const">
<return type="Vector3" />
<param index="0" name="link" type="RID" />
<description>
Returns the starting location of this [code]link[/code].
</description>
</method>
<method name="link_get_travel_cost" qualifiers="const">
<return type="float" />
<param index="0" name="link" type="RID" />
<description>
Returns the [code]travel_cost[/code] of this [code]link[/code].
</description>
</method>
<method name="link_is_bidirectional" qualifiers="const">
<return type="bool" />
<param index="0" name="link" type="RID" />
<description>
Returns whether this [code]link[/code] can be travelled in both directions.
</description>
</method>
<method name="link_set_bidirectional" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="bidirectional" type="bool" />
<description>
Sets whether this [code]link[/code] can be travelled in both directions.
</description>
</method>
<method name="link_set_end_location" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="location" type="Vector3" />
<description>
Sets the exit location for the [code]link[/code].
</description>
</method>
<method name="link_set_enter_cost" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="enter_cost" type="float" />
<description>
Sets the [code]enter_cost[/code] for this [code]link[/code].
</description>
</method>
<method name="link_set_map" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="map" type="RID" />
<description>
Sets the navigation map [RID] for the link.
</description>
</method>
<method name="link_set_navigation_layers" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="navigation_layers" type="int" />
<description>
Set the links's navigation layers. This allows selecting links from a path request (when using [method NavigationServer3D.map_get_path]).
</description>
</method>
<method name="link_set_start_location" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="location" type="Vector3" />
<description>
Sets the entry location for this [code]link[/code].
</description>
</method>
<method name="link_set_travel_cost" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
<param index="1" name="travel_cost" type="float" />
<description>
Sets the [code]travel_cost[/code] for this [code]link[/code].
</description>
</method>
<method name="map_create" qualifiers="const"> <method name="map_create" qualifiers="const">
<return type="RID" /> <return type="RID" />
<description> <description>
@ -204,6 +315,20 @@
Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions. Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions.
</description> </description>
</method> </method>
<method name="map_get_link_connection_radius" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />
<description>
Returns the link connection radius of the map. This distance is the maximum range any link will search for navigation mesh polygons to connect to.
</description>
</method>
<method name="map_get_links" qualifiers="const">
<return type="RID[]" />
<param index="0" name="map" type="RID" />
<description>
Returns all navigation link [RID]s that are currently assigned to the requested navigation [code]map[/code].
</description>
</method>
<method name="map_get_path" qualifiers="const"> <method name="map_get_path" qualifiers="const">
<return type="PackedVector3Array" /> <return type="PackedVector3Array" />
<param index="0" name="map" type="RID" /> <param index="0" name="map" type="RID" />
@ -260,6 +385,14 @@
Set the map edge connection margin used to weld the compatible region edges. Set the map edge connection margin used to weld the compatible region edges.
</description> </description>
</method> </method>
<method name="map_set_link_connection_radius" qualifiers="const">
<return type="void" />
<param index="0" name="map" type="RID" />
<param index="1" name="radius" type="float" />
<description>
Set the map's link connection radius used to connect links to navigation polygons.
</description>
</method>
<method name="map_set_up" qualifiers="const"> <method name="map_set_up" qualifiers="const">
<return type="void" /> <return type="void" />
<param index="0" name="map" type="RID" /> <param index="0" name="map" type="RID" />

View File

@ -497,6 +497,12 @@
<member name="debug/shapes/navigation/enable_geometry_face_random_color" type="bool" setter="" getter="" default="true"> <member name="debug/shapes/navigation/enable_geometry_face_random_color" type="bool" setter="" getter="" default="true">
If enabled, colorizes each navigation mesh polygon face with a random color when "Visible Navigation" is enabled in the Debug menu. If enabled, colorizes each navigation mesh polygon face with a random color when "Visible Navigation" is enabled in the Debug menu.
</member> </member>
<member name="debug/shapes/navigation/enable_link_connections" type="bool" setter="" getter="" default="true">
If enabled, displays navigation link connections when "Visible Navigation" is enabled in the Debug menu.
</member>
<member name="debug/shapes/navigation/enable_link_connections_xray" type="bool" setter="" getter="" default="true">
If enabled, displays navigation link connections through geometry when "Visible Navigation" is enabled in the Debug menu.
</member>
<member name="debug/shapes/navigation/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)"> <member name="debug/shapes/navigation/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)">
Color of the navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu. Color of the navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu.
</member> </member>
@ -512,6 +518,12 @@
<member name="debug/shapes/navigation/geometry_face_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 0.4)"> <member name="debug/shapes/navigation/geometry_face_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 0.4)">
Color to display disabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu. Color to display disabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu.
</member> </member>
<member name="debug/shapes/navigation/link_connection_color" type="Color" setter="" getter="" default="Color(1, 0.5, 1, 1)">
Color to use to display navigation link connections, visible when "Visible Navigation" is enabled in the Debug menu.
</member>
<member name="debug/shapes/navigation/link_connection_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 1)">
Color to use to display disabled navigation link connections, visible when "Visible Navigation" is enabled in the Debug menu.
</member>
<member name="debug/shapes/paths/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)"> <member name="debug/shapes/paths/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)">
Color of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu. Color of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu.
</member> </member>
@ -1439,12 +1451,18 @@
<member name="navigation/2d/default_edge_connection_margin" type="int" setter="" getter="" default="1"> <member name="navigation/2d/default_edge_connection_margin" type="int" setter="" getter="" default="1">
Default edge connection margin for 2D navigation maps. See [method NavigationServer2D.map_set_edge_connection_margin]. Default edge connection margin for 2D navigation maps. See [method NavigationServer2D.map_set_edge_connection_margin].
</member> </member>
<member name="navigation/2d/default_link_connection_radius" type="int" setter="" getter="" default="4">
Default link connection radius for 2D navigation maps. See [method NavigationServer2D.map_set_link_connection_radius].
</member>
<member name="navigation/3d/default_cell_size" type="float" setter="" getter="" default="0.25"> <member name="navigation/3d/default_cell_size" type="float" setter="" getter="" default="0.25">
Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size]. Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size].
</member> </member>
<member name="navigation/3d/default_edge_connection_margin" type="float" setter="" getter="" default="0.25"> <member name="navigation/3d/default_edge_connection_margin" type="float" setter="" getter="" default="0.25">
Default edge connection margin for 3D navigation maps. See [method NavigationServer3D.map_set_edge_connection_margin]. Default edge connection margin for 3D navigation maps. See [method NavigationServer3D.map_set_edge_connection_margin].
</member> </member>
<member name="navigation/3d/default_link_connection_radius" type="float" setter="" getter="" default="1.0">
Default link connection radius for 3D navigation maps. See [method NavigationServer3D.map_set_link_connection_radius].
</member>
<member name="network/limits/debugger/max_chars_per_second" type="int" setter="" getter="" default="32768"> <member name="network/limits/debugger/max_chars_per_second" type="int" setter="" getter="" default="32768">
Maximum number of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection. Maximum number of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member> </member>

View File

@ -170,6 +170,7 @@
#include "editor/plugins/mesh_instance_3d_editor_plugin.h" #include "editor/plugins/mesh_instance_3d_editor_plugin.h"
#include "editor/plugins/mesh_library_editor_plugin.h" #include "editor/plugins/mesh_library_editor_plugin.h"
#include "editor/plugins/multimesh_editor_plugin.h" #include "editor/plugins/multimesh_editor_plugin.h"
#include "editor/plugins/navigation_link_2d_editor_plugin.h"
#include "editor/plugins/navigation_polygon_editor_plugin.h" #include "editor/plugins/navigation_polygon_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/plugins/occluder_instance_3d_editor_plugin.h" #include "editor/plugins/occluder_instance_3d_editor_plugin.h"
@ -7293,6 +7294,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(GPUParticles2DEditorPlugin)); add_editor_plugin(memnew(GPUParticles2DEditorPlugin));
add_editor_plugin(memnew(LightOccluder2DEditorPlugin)); add_editor_plugin(memnew(LightOccluder2DEditorPlugin));
add_editor_plugin(memnew(Line2DEditorPlugin)); add_editor_plugin(memnew(Line2DEditorPlugin));
add_editor_plugin(memnew(NavigationLink2DEditorPlugin));
add_editor_plugin(memnew(NavigationPolygonEditorPlugin)); add_editor_plugin(memnew(NavigationPolygonEditorPlugin));
add_editor_plugin(memnew(Path2DEditorPlugin)); add_editor_plugin(memnew(Path2DEditorPlugin));
add_editor_plugin(memnew(Polygon2DEditorPlugin)); add_editor_plugin(memnew(Polygon2DEditorPlugin));

View File

@ -0,0 +1,4 @@
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m12.386 5.3097c-0.69157-0.021112-1.3071 0.36382-1.7492 0.86685-0.58 0.58-1.16 1.16-1.74 1.74 0.4588-0.28502 1.0599-0.064948 1.4771-0.037996 0.45549-0.44357 0.89024-0.91006 1.3596-1.3383 0.56256-0.44564 1.4906-0.15731 1.7028 0.52802 0.18967 0.4871-0.049221 1.0098-0.43284 1.3208-0.70048 0.68896-1.3789 1.4022-2.0935 2.0755-0.47999 0.3725-1.2044 0.226-1.5679-0.24034-0.38763-0.38194-1.0641 0.16031-0.78317 0.6241 0.6767 0.94379 2.1573 1.1282 3.0411 0.36751 0.80287-0.7704 1.5793-1.5696 2.3665-2.3564 0.79925-0.83719 0.70104-2.3112-0.19552-3.0393-0.38108-0.32877-0.8822-0.5119-1.385-0.51049zm-3.051 3.051c-0.69157-0.021106-1.3071 0.36382-1.7492 0.86685-0.67513 0.68452-1.37 1.3506-2.0319 2.0474-0.75433 0.87744-0.58087 2.3428 0.34933 3.0252 0.84748 0.68613 2.192 0.54839 2.8998-0.27341 0.63032-0.63031 1.2606-1.2606 1.8909-1.8909-0.4587 0.28554-1.0602 0.0659-1.477 0.038069-0.45445 0.44348-0.88773 0.91034-1.3564 1.3383-0.56256 0.44565-1.4906 0.15731-1.7028-0.52802-0.18967-0.4871 0.049229-1.0098 0.43284-1.3208 0.70048-0.68896 1.3789-1.4022 2.0935-2.0755 0.48-0.3725 1.2044-0.22601 1.5679 0.24036 0.38733 0.38325 1.064-0.16067 0.78313-0.6241-0.39353-0.52481-1.0429-0.84871-1.7002-0.8434z" fill="#8ea6f4" fill-opacity=".99608" stroke-linecap="round" stroke-linejoin="round" stroke-width=".013911"/>
<path d="m2 1c-0.61942-0.0066969-1.0877 0.60314-1 1.198 0.00345 3.968-0.006897 7.9364 0.00517 11.904 0.043388 0.62851 0.69346 0.98513 1.272 0.89776h2.5896c-0.77174-0.5015-1.2078-1.2613-1.3143-2.3356-0.11601-1.1701 0.63729-2.024 1.6748-3.1566 0.65335-0.71326 1.4757-1.5822 2.3587-2.3316 0.76308-0.64765 1.7509-1.679 2.9376-2.578 0.91259-0.69136 2.2893-0.74691 3.1014-0.33143 0.91184 0.46649 1.2635 1.1209 1.4067 1.3826-0.0052-2.335-0.02135-1.3526-0.03955-3.6863 5e-3 -0.64349-0.67497-1.0568-1.2694-0.96289z" fill="#8ea6f4" fill-opacity=".99608"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,4 @@
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m12.386 5.3097c-0.69157-0.021112-1.3071 0.36382-1.7492 0.86685-0.58 0.58-1.16 1.16-1.74 1.74 0.4588-0.28502 1.0599-0.064948 1.4771-0.037996 0.45549-0.44357 0.89024-0.91006 1.3596-1.3383 0.56256-0.44564 1.4906-0.15731 1.7028 0.52802 0.18967 0.4871-0.049221 1.0098-0.43284 1.3208-0.70048 0.68896-1.3789 1.4022-2.0935 2.0755-0.47999 0.3725-1.2044 0.226-1.5679-0.24034-0.38763-0.38194-1.0641 0.16031-0.78317 0.6241 0.6767 0.94379 2.1573 1.1282 3.0411 0.36751 0.80287-0.7704 1.5793-1.5696 2.3665-2.3564 0.79925-0.83719 0.70104-2.3112-0.19552-3.0393-0.38108-0.32877-0.8822-0.5119-1.385-0.51049zm-3.051 3.051c-0.69157-0.021106-1.3071 0.36382-1.7492 0.86685-0.67513 0.68452-1.37 1.3506-2.0319 2.0474-0.75433 0.87744-0.58087 2.3428 0.34933 3.0252 0.84748 0.68613 2.192 0.54839 2.8998-0.27341 0.63032-0.63031 1.2606-1.2606 1.8909-1.8909-0.4587 0.28554-1.0602 0.0659-1.477 0.038069-0.45445 0.44348-0.88773 0.91034-1.3564 1.3383-0.56256 0.44565-1.4906 0.15731-1.7028-0.52802-0.18967-0.4871 0.049229-1.0098 0.43284-1.3208 0.70048-0.68896 1.3789-1.4022 2.0935-2.0755 0.48-0.3725 1.2044-0.22601 1.5679 0.24036 0.38733 0.38325 1.064-0.16067 0.78313-0.6241-0.39353-0.52481-1.0429-0.84871-1.7002-0.8434z" fill="#fc7e7e" fill-opacity=".99608" stroke-linecap="round" stroke-linejoin="round" stroke-width=".013911"/>
<path d="m2 1c-0.61942-0.0066969-1.0877 0.60314-1 1.198 0.00345 3.968-0.006897 7.9364 0.00517 11.904 0.043388 0.62851 0.69346 0.98513 1.272 0.89776h2.5896c-0.77174-0.5015-1.2078-1.2613-1.3143-2.3356-0.11601-1.1701 0.63729-2.024 1.6748-3.1566 0.65335-0.71326 1.4757-1.5822 2.3587-2.3316 0.76308-0.64765 1.7509-1.679 2.9376-2.578 0.91259-0.69136 2.2893-0.74691 3.1014-0.33143 0.91184 0.46649 1.2635 1.1209 1.4067 1.3826-0.0052-2.335-0.02135-1.3526-0.03955-3.6863 5e-3 -0.64349-0.67497-1.0568-1.2694-0.96289z" fill="#fc7d7d" fill-opacity=".99608"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,191 @@
/*************************************************************************/
/* navigation_link_2d_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "navigation_link_2d_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "servers/navigation_server_3d.h"
void NavigationLink2DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
get_tree()->connect("node_removed", callable_mp(this, &NavigationLink2DEditor::_node_removed));
} break;
case NOTIFICATION_EXIT_TREE: {
get_tree()->disconnect("node_removed", callable_mp(this, &NavigationLink2DEditor::_node_removed));
} break;
}
}
void NavigationLink2DEditor::_node_removed(Node *p_node) {
if (p_node == node) {
node = nullptr;
}
}
bool NavigationLink2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (!node || !node->is_visible_in_tree()) {
return false;
}
real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius");
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
// Start location
if (xform.xform(node->get_start_location()).distance_to(mb->get_position()) < grab_threshold) {
start_grabbed = true;
original_start_location = node->get_start_location();
return true;
} else {
start_grabbed = false;
}
// End location
if (xform.xform(node->get_end_location()).distance_to(mb->get_position()) < grab_threshold) {
end_grabbed = true;
original_end_location = node->get_end_location();
return true;
} else {
end_grabbed = false;
}
} else {
if (start_grabbed) {
undo_redo->create_action(TTR("Set start_location"));
undo_redo->add_do_method(node, "set_start_location", node->get_start_location());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(node, "set_start_location", original_start_location);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
undo_redo->commit_action();
start_grabbed = false;
return true;
}
if (end_grabbed) {
undo_redo->create_action(TTR("Set end_location"));
undo_redo->add_do_method(node, "set_end_location", node->get_end_location());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(node, "set_end_location", original_end_location);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
undo_redo->commit_action();
end_grabbed = false;
return true;
}
}
}
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()));
point = node->get_global_transform().affine_inverse().xform(point);
if (start_grabbed) {
node->set_start_location(point);
canvas_item_editor->update_viewport();
return true;
}
if (end_grabbed) {
node->set_end_location(point);
canvas_item_editor->update_viewport();
return true;
}
}
return false;
}
void NavigationLink2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!node || !node->is_visible_in_tree()) {
return;
}
Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 global_start_location = gt.xform(node->get_start_location());
Vector2 global_end_location = gt.xform(node->get_end_location());
// Only drawing the handles here, since the debug rendering will fill in the rest.
const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
p_overlay->draw_texture(handle, global_start_location - handle->get_size() / 2);
p_overlay->draw_texture(handle, global_end_location - handle->get_size() / 2);
}
void NavigationLink2DEditor::edit(NavigationLink2D *p_node) {
if (!canvas_item_editor) {
canvas_item_editor = CanvasItemEditor::get_singleton();
}
if (p_node) {
node = p_node;
} else {
node = nullptr;
}
canvas_item_editor->update_viewport();
}
NavigationLink2DEditor::NavigationLink2DEditor() {
undo_redo = EditorNode::get_undo_redo();
}
///////////////////////
void NavigationLink2DEditorPlugin::edit(Object *p_object) {
editor->edit(Object::cast_to<NavigationLink2D>(p_object));
}
bool NavigationLink2DEditorPlugin::handles(Object *p_object) const {
return Object::cast_to<NavigationLink2D>(p_object) != nullptr;
}
void NavigationLink2DEditorPlugin::make_visible(bool p_visible) {
if (!p_visible) {
edit(nullptr);
}
}
NavigationLink2DEditorPlugin::NavigationLink2DEditorPlugin() {
editor = memnew(NavigationLink2DEditor);
EditorNode::get_singleton()->get_gui_base()->add_child(editor);
}

View File

@ -0,0 +1,83 @@
/*************************************************************************/
/* navigation_link_2d_editor_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef NAVIGATION_LINK_2D_EDITOR_PLUGIN_H
#define NAVIGATION_LINK_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/2d/navigation_link_2d.h"
class CanvasItemEditor;
class EditorUndoRedoManager;
class NavigationLink2DEditor : public Control {
GDCLASS(NavigationLink2DEditor, Control);
Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
NavigationLink2D *node;
bool start_grabbed = false;
Vector2 original_start_location;
bool end_grabbed = false;
Vector2 original_end_location;
protected:
void _notification(int p_what);
void _node_removed(Node *p_node);
public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(NavigationLink2D *p_node);
NavigationLink2DEditor();
};
class NavigationLink2DEditorPlugin : public EditorPlugin {
GDCLASS(NavigationLink2DEditorPlugin, EditorPlugin);
NavigationLink2DEditor *editor = nullptr;
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return editor->forward_canvas_gui_input(p_event); }
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { editor->forward_canvas_draw_over_viewport(p_overlay); }
virtual String get_name() const override { return "NavigationLink2D"; }
bool has_main_screen() const override { return false; }
virtual void edit(Object *p_object) override;
virtual bool handles(Object *p_object) const override;
virtual void make_visible(bool p_visible) override;
NavigationLink2DEditorPlugin();
};
#endif // NAVIGATION_LINK_2D_EDITOR_PLUGIN_H

View File

@ -54,6 +54,7 @@
#include "scene/3d/lightmap_probe.h" #include "scene/3d/lightmap_probe.h"
#include "scene/3d/marker_3d.h" #include "scene/3d/marker_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_link_3d.h"
#include "scene/3d/navigation_region_3d.h" #include "scene/3d/navigation_region_3d.h"
#include "scene/3d/occluder_instance_3d.h" #include "scene/3d/occluder_instance_3d.h"
#include "scene/3d/ray_cast_3d.h" #include "scene/3d/ray_cast_3d.h"
@ -4998,6 +4999,175 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
} }
} }
////
NavigationLink3DGizmoPlugin::NavigationLink3DGizmoPlugin() {
create_material("navigation_link_material", NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_color());
create_material("navigation_link_material_disabled", NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_disabled_color());
create_handle_material("handles");
}
bool NavigationLink3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<NavigationLink3D>(p_spatial) != nullptr;
}
String NavigationLink3DGizmoPlugin::get_gizmo_name() const {
return "NavigationLink3D";
}
int NavigationLink3DGizmoPlugin::get_priority() const {
return -1;
}
void NavigationLink3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
NavigationLink3D *link = Object::cast_to<NavigationLink3D>(p_gizmo->get_spatial_node());
RID nav_map = link->get_world_3d()->get_navigation_map();
real_t search_radius = NavigationServer3D::get_singleton()->map_get_link_connection_radius(nav_map);
Vector3 up_vector = NavigationServer3D::get_singleton()->map_get_up(nav_map);
Vector3::Axis up_axis = up_vector.max_axis_index();
Vector3 start_location = link->get_start_location();
Vector3 end_location = link->get_end_location();
Ref<Material> link_material = get_material("navigation_link_material", p_gizmo);
Ref<Material> link_material_disabled = get_material("navigation_link_material_disabled", p_gizmo);
Ref<Material> handles_material = get_material("handles");
p_gizmo->clear();
// Draw line between the points.
Vector<Vector3> lines;
lines.append(start_location);
lines.append(end_location);
// Draw start location search radius
for (int i = 0; i < 30; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 12));
const float rb = Math::deg_to_rad((float)((i + 1) * 12));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
// Draw axis-aligned circle
switch (up_axis) {
case Vector3::AXIS_X:
lines.append(start_location + Vector3(0, a.x, a.y));
lines.append(start_location + Vector3(0, b.x, b.y));
break;
case Vector3::AXIS_Y:
lines.append(start_location + Vector3(a.x, 0, a.y));
lines.append(start_location + Vector3(b.x, 0, b.y));
break;
case Vector3::AXIS_Z:
lines.append(start_location + Vector3(a.x, a.y, 0));
lines.append(start_location + Vector3(b.x, b.y, 0));
break;
}
}
// Draw end location search radius
for (int i = 0; i < 30; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 12));
const float rb = Math::deg_to_rad((float)((i + 1) * 12));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
// Draw axis-aligned circle
switch (up_axis) {
case Vector3::AXIS_X:
lines.append(end_location + Vector3(0, a.x, a.y));
lines.append(end_location + Vector3(0, b.x, b.y));
break;
case Vector3::AXIS_Y:
lines.append(end_location + Vector3(a.x, 0, a.y));
lines.append(end_location + Vector3(b.x, 0, b.y));
break;
case Vector3::AXIS_Z:
lines.append(end_location + Vector3(a.x, a.y, 0));
lines.append(end_location + Vector3(b.x, b.y, 0));
break;
}
}
p_gizmo->add_lines(lines, link->is_enabled() ? link_material : link_material_disabled);
p_gizmo->add_collision_segments(lines);
Vector<Vector3> handles;
handles.append(start_location);
handles.append(end_location);
p_gizmo->add_handles(handles, handles_material);
}
String NavigationLink3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
return p_id == 0 ? TTR("Start Location") : TTR("End Location");
}
Variant NavigationLink3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
NavigationLink3D *link = Object::cast_to<NavigationLink3D>(p_gizmo->get_spatial_node());
return p_id == 0 ? link->get_start_location() : link->get_end_location();
}
void NavigationLink3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
NavigationLink3D *link = Object::cast_to<NavigationLink3D>(p_gizmo->get_spatial_node());
Transform3D gt = link->get_global_transform();
Transform3D gi = gt.affine_inverse();
Transform3D ct = p_camera->get_global_transform();
Vector3 cam_dir = ct.basis.get_column(Vector3::AXIS_Z);
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 location = p_id == 0 ? link->get_start_location() : link->get_end_location();
Plane move_plane = Plane(cam_dir, gt.xform(location));
Vector3 intersection;
if (!move_plane.intersects_ray(ray_from, ray_dir, &intersection)) {
return;
}
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
double snap = Node3DEditor::get_singleton()->get_translate_snap();
intersection.snap(Vector3(snap, snap, snap));
}
location = gi.xform(intersection);
if (p_id == 0) {
link->set_start_location(location);
} else if (p_id == 1) {
link->set_end_location(location);
}
}
void NavigationLink3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) {
NavigationLink3D *link = Object::cast_to<NavigationLink3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
if (p_id == 0) {
link->set_start_location(p_restore);
} else {
link->set_end_location(p_restore);
}
return;
}
Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
if (p_id == 0) {
ur->create_action(TTR("Change Start Location"));
ur->add_do_method(link, "set_start_location", link->get_start_location());
ur->add_undo_method(link, "set_start_location", p_restore);
} else {
ur->create_action(TTR("Change End Location"));
ur->add_do_method(link, "set_end_location", link->get_end_location());
ur->add_undo_method(link, "set_end_location", p_restore);
}
ur->commit_action();
}
////// //////
#define BODY_A_RADIUS 0.25 #define BODY_A_RADIUS 0.25

View File

@ -631,6 +631,23 @@ public:
NavigationRegion3DGizmoPlugin(); NavigationRegion3DGizmoPlugin();
}; };
class NavigationLink3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(NavigationLink3DGizmoPlugin, EditorNode3DGizmoPlugin);
public:
bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override;
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
NavigationLink3DGizmoPlugin();
};
class JointGizmosDrawer { class JointGizmosDrawer {
public: public:
static Basis look_body(const Transform3D &p_joint_transform, const Transform3D &p_body_transform); static Basis look_body(const Transform3D &p_joint_transform, const Transform3D &p_body_transform);

View File

@ -7520,6 +7520,7 @@ void Node3DEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<CollisionObject3DGizmoPlugin>(memnew(CollisionObject3DGizmoPlugin))); add_gizmo_plugin(Ref<CollisionObject3DGizmoPlugin>(memnew(CollisionObject3DGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin))); add_gizmo_plugin(Ref<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionPolygon3DGizmoPlugin>(memnew(CollisionPolygon3DGizmoPlugin))); add_gizmo_plugin(Ref<CollisionPolygon3DGizmoPlugin>(memnew(CollisionPolygon3DGizmoPlugin)));
add_gizmo_plugin(Ref<NavigationLink3DGizmoPlugin>(memnew(NavigationLink3DGizmoPlugin)));
add_gizmo_plugin(Ref<NavigationRegion3DGizmoPlugin>(memnew(NavigationRegion3DGizmoPlugin))); add_gizmo_plugin(Ref<NavigationRegion3DGizmoPlugin>(memnew(NavigationRegion3DGizmoPlugin)));
add_gizmo_plugin(Ref<Joint3DGizmoPlugin>(memnew(Joint3DGizmoPlugin))); add_gizmo_plugin(Ref<Joint3DGizmoPlugin>(memnew(Joint3DGizmoPlugin)));
add_gizmo_plugin(Ref<PhysicalBone3DGizmoPlugin>(memnew(PhysicalBone3DGizmoPlugin))); add_gizmo_plugin(Ref<PhysicalBone3DGizmoPlugin>(memnew(PhysicalBone3DGizmoPlugin)));

View File

@ -210,6 +210,20 @@ real_t GodotNavigationServer::map_get_edge_connection_margin(RID p_map) const {
return map->get_edge_connection_margin(); return map->get_edge_connection_margin();
} }
COMMAND_2(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius) {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND(map == nullptr);
map->set_link_connection_radius(p_connection_radius);
}
real_t GodotNavigationServer::map_get_link_connection_radius(RID p_map) const {
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, 0);
return map->get_link_connection_radius();
}
Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const { Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
const NavMap *map = map_owner.get_or_null(p_map); const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>()); ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
@ -245,6 +259,20 @@ RID GodotNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3
return map->get_closest_point_owner(p_point); return map->get_closest_point_owner(p_point);
} }
TypedArray<RID> GodotNavigationServer::map_get_links(RID p_map) const {
TypedArray<RID> link_rids;
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, link_rids);
const LocalVector<NavLink *> links = map->get_links();
link_rids.resize(links.size());
for (uint32_t i = 0; i < links.size(); i++) {
link_rids[i] = links[i]->get_self();
}
return link_rids;
}
TypedArray<RID> GodotNavigationServer::map_get_regions(RID p_map) const { TypedArray<RID> GodotNavigationServer::map_get_regions(RID p_map) const {
TypedArray<RID> regions_rids; TypedArray<RID> regions_rids;
const NavMap *map = map_owner.get_or_null(p_map); const NavMap *map = map_owner.get_or_null(p_map);
@ -417,6 +445,131 @@ Vector3 GodotNavigationServer::region_get_connection_pathway_end(RID p_region, i
return region->get_connection_pathway_end(p_connection_id); return region->get_connection_pathway_end(p_connection_id);
} }
RID GodotNavigationServer::link_create() const {
GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
RID rid = link_owner.make_rid();
NavLink *link = link_owner.get_or_null(rid);
link->set_self(rid);
return rid;
}
COMMAND_2(link_set_map, RID, p_link, RID, p_map) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
if (link->get_map() != nullptr) {
if (link->get_map()->get_self() == p_map) {
return; // Pointless
}
link->get_map()->remove_link(link);
link->set_map(nullptr);
}
if (p_map.is_valid()) {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND(map == nullptr);
map->add_link(link);
link->set_map(map);
}
}
RID GodotNavigationServer::link_get_map(const RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, RID());
if (link->get_map()) {
return link->get_map()->get_self();
}
return RID();
}
COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
link->set_bidirectional(p_bidirectional);
}
bool GodotNavigationServer::link_is_bidirectional(RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, false);
return link->is_bidirectional();
}
COMMAND_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
link->set_navigation_layers(p_navigation_layers);
}
uint32_t GodotNavigationServer::link_get_navigation_layers(const RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, 0);
return link->get_navigation_layers();
}
COMMAND_2(link_set_start_location, RID, p_link, Vector3, p_location) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
link->set_start_location(p_location);
}
Vector3 GodotNavigationServer::link_get_start_location(RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, Vector3());
return link->get_start_location();
}
COMMAND_2(link_set_end_location, RID, p_link, Vector3, p_location) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
link->set_end_location(p_location);
}
Vector3 GodotNavigationServer::link_get_end_location(RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, Vector3());
return link->get_end_location();
}
COMMAND_2(link_set_enter_cost, RID, p_link, real_t, p_enter_cost) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
link->set_enter_cost(p_enter_cost);
}
real_t GodotNavigationServer::link_get_enter_cost(const RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, 0);
return link->get_enter_cost();
}
COMMAND_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost) {
NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND(link == nullptr);
link->set_travel_cost(p_travel_cost);
}
real_t GodotNavigationServer::link_get_travel_cost(const RID p_link) const {
const NavLink *link = link_owner.get_or_null(p_link);
ERR_FAIL_COND_V(link == nullptr, 0);
return link->get_travel_cost();
}
RID GodotNavigationServer::agent_create() const { RID GodotNavigationServer::agent_create() const {
GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this); GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex); MutexLock lock(mut_this->operations_mutex);
@ -549,6 +702,13 @@ COMMAND_1(free, RID, p_object) {
regions[i]->set_map(nullptr); regions[i]->set_map(nullptr);
} }
// Removes any assigned links
LocalVector<NavLink *> links = map->get_links();
for (uint32_t i = 0; i < links.size(); i++) {
map->remove_link(links[i]);
links[i]->set_map(nullptr);
}
// Remove any assigned agent // Remove any assigned agent
LocalVector<RvoAgent *> agents = map->get_agents(); LocalVector<RvoAgent *> agents = map->get_agents();
for (uint32_t i = 0; i < agents.size(); i++) { for (uint32_t i = 0; i < agents.size(); i++) {
@ -572,6 +732,17 @@ COMMAND_1(free, RID, p_object) {
region_owner.free(p_object); region_owner.free(p_object);
} else if (link_owner.owns(p_object)) {
NavLink *link = link_owner.get_or_null(p_object);
// Removes this link from the map if assigned
if (link->get_map() != nullptr) {
link->get_map()->remove_link(link);
link->set_map(nullptr);
}
link_owner.free(p_object);
} else if (agent_owner.owns(p_object)) { } else if (agent_owner.owns(p_object)) {
RvoAgent *agent = agent_owner.get_or_null(p_object); RvoAgent *agent = agent_owner.get_or_null(p_object);

View File

@ -36,6 +36,7 @@
#include "core/templates/rid_owner.h" #include "core/templates/rid_owner.h"
#include "servers/navigation_server_3d.h" #include "servers/navigation_server_3d.h"
#include "nav_link.h"
#include "nav_map.h" #include "nav_map.h"
#include "nav_region.h" #include "nav_region.h"
#include "rvo_agent.h" #include "rvo_agent.h"
@ -71,6 +72,7 @@ class GodotNavigationServer : public NavigationServer3D {
LocalVector<SetCommand *> commands; LocalVector<SetCommand *> commands;
mutable RID_Owner<NavLink> link_owner;
mutable RID_Owner<NavMap> map_owner; mutable RID_Owner<NavMap> map_owner;
mutable RID_Owner<NavRegion> region_owner; mutable RID_Owner<NavRegion> region_owner;
mutable RID_Owner<RvoAgent> agent_owner; mutable RID_Owner<RvoAgent> agent_owner;
@ -100,6 +102,9 @@ public:
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin); 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 override; virtual real_t map_get_edge_connection_margin(RID p_map) const override;
COMMAND_2(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius);
virtual real_t map_get_link_connection_radius(RID p_map) const override;
virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const override; virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const override;
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 override; 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 override;
@ -107,6 +112,7 @@ public:
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override; virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override;
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override;
virtual TypedArray<RID> map_get_links(RID p_map) const override;
virtual TypedArray<RID> map_get_regions(RID p_map) const override; virtual TypedArray<RID> map_get_regions(RID p_map) const override;
virtual TypedArray<RID> map_get_agents(RID p_map) const override; virtual TypedArray<RID> map_get_agents(RID p_map) const override;
@ -132,6 +138,22 @@ public:
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override; virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override; virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override;
virtual RID link_create() const override;
COMMAND_2(link_set_map, RID, p_link, RID, p_map);
virtual RID link_get_map(RID p_link) const override;
COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional);
virtual bool link_is_bidirectional(RID p_link) const override;
COMMAND_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers);
virtual uint32_t link_get_navigation_layers(RID p_link) const override;
COMMAND_2(link_set_start_location, RID, p_link, Vector3, p_location);
virtual Vector3 link_get_start_location(RID p_link) const override;
COMMAND_2(link_set_end_location, RID, p_link, Vector3, p_location);
virtual Vector3 link_get_end_location(RID p_link) const override;
COMMAND_2(link_set_enter_cost, RID, p_link, real_t, p_enter_cost);
virtual real_t link_get_enter_cost(RID p_link) const override;
COMMAND_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost);
virtual real_t link_get_travel_cost(RID p_link) const override;
virtual RID agent_create() const override; virtual RID agent_create() const override;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map); COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
virtual RID agent_get_map(RID p_agent) const override; virtual RID agent_get_map(RID p_agent) const override;

View File

@ -0,0 +1,56 @@
/*************************************************************************/
/* nav_base.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef NAV_BASE_H
#define NAV_BASE_H
#include "nav_rid.h"
#include "nav_utils.h"
class NavMap;
class NavBase : public NavRid {
protected:
uint32_t navigation_layers = 1;
float enter_cost = 0.0;
float travel_cost = 1.0;
public:
void set_navigation_layers(uint32_t p_navigation_layers) { navigation_layers = p_navigation_layers; }
uint32_t get_navigation_layers() const { return navigation_layers; }
void set_enter_cost(float p_enter_cost) { enter_cost = MAX(p_enter_cost, 0.0); }
float get_enter_cost() const { return enter_cost; }
void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
float get_travel_cost() const { return travel_cost; }
};
#endif // NAV_BASE_H

View File

@ -0,0 +1,60 @@
/*************************************************************************/
/* nav_link.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "nav_link.h"
#include "nav_map.h"
void NavLink::set_map(NavMap *p_map) {
map = p_map;
link_dirty = true;
}
void NavLink::set_bidirectional(bool p_bidirectional) {
bidirectional = p_bidirectional;
link_dirty = true;
}
void NavLink::set_start_location(const Vector3 p_location) {
start_location = p_location;
link_dirty = true;
}
void NavLink::set_end_location(const Vector3 p_location) {
end_location = p_location;
link_dirty = true;
}
bool NavLink::check_dirty() {
const bool was_dirty = link_dirty;
link_dirty = false;
return was_dirty;
}

View File

@ -0,0 +1,69 @@
/*************************************************************************/
/* nav_link.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef NAV_LINK_H
#define NAV_LINK_H
#include "nav_base.h"
#include "nav_utils.h"
class NavLink : public NavBase {
NavMap *map = nullptr;
bool bidirectional = true;
Vector3 start_location = Vector3();
Vector3 end_location = Vector3();
bool link_dirty = true;
public:
void set_map(NavMap *p_map);
NavMap *get_map() const {
return map;
}
void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const {
return bidirectional;
}
void set_start_location(Vector3 p_location);
Vector3 get_start_location() const {
return start_location;
}
void set_end_location(Vector3 p_location);
Vector3 get_end_location() const {
return end_location;
}
bool check_dirty();
};
#endif // NAV_LINK_H

View File

@ -31,6 +31,7 @@
#include "nav_map.h" #include "nav_map.h"
#include "core/object/worker_thread_pool.h" #include "core/object/worker_thread_pool.h"
#include "nav_link.h"
#include "nav_region.h" #include "nav_region.h"
#include "rvo_agent.h" #include "rvo_agent.h"
#include <algorithm> #include <algorithm>
@ -52,6 +53,11 @@ void NavMap::set_edge_connection_margin(float p_edge_connection_margin) {
regenerate_links = true; regenerate_links = true;
} }
void NavMap::set_link_connection_radius(float p_link_connection_radius) {
link_connection_radius = p_link_connection_radius;
regenerate_links = true;
}
gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
const int x = int(Math::floor(p_pos.x / cell_size)); const int x = int(Math::floor(p_pos.x / cell_size));
const int y = int(Math::floor(p_pos.y / cell_size)); const int y = int(Math::floor(p_pos.y / cell_size));
@ -158,17 +164,17 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
continue; continue;
} }
float region_enter_cost = 0.0; float poly_enter_cost = 0.0;
float region_travel_cost = least_cost_poly->poly->owner->get_travel_cost(); float poly_travel_cost = least_cost_poly->poly->owner->get_travel_cost();
if (prev_least_cost_poly != nullptr && !(prev_least_cost_poly->poly->owner->get_self() == least_cost_poly->poly->owner->get_self())) { if (prev_least_cost_poly != nullptr && (prev_least_cost_poly->poly->owner->get_self() != least_cost_poly->poly->owner->get_self())) {
region_enter_cost = least_cost_poly->poly->owner->get_enter_cost(); poly_enter_cost = least_cost_poly->poly->owner->get_enter_cost();
} }
prev_least_cost_poly = least_cost_poly; prev_least_cost_poly = least_cost_poly;
Vector3 pathway[2] = { connection.pathway_start, connection.pathway_end }; Vector3 pathway[2] = { connection.pathway_start, connection.pathway_end };
const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway); const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway);
const float new_distance = (least_cost_poly->entry.distance_to(new_entry) * region_travel_cost) + region_enter_cost + least_cost_poly->traveled_distance; const float new_distance = (least_cost_poly->entry.distance_to(new_entry) * poly_travel_cost) + poly_enter_cost + least_cost_poly->traveled_distance;
int64_t already_visited_polygon_index = navigation_polys.find(gd::NavigationPoly(connection.polygon)); int64_t already_visited_polygon_index = navigation_polys.find(gd::NavigationPoly(connection.polygon));
@ -360,10 +366,15 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
// Add mid points // Add mid points
int np_id = least_cost_id; int np_id = least_cost_id;
while (np_id != -1 && navigation_polys[np_id].back_navigation_poly_id != -1) { while (np_id != -1 && navigation_polys[np_id].back_navigation_poly_id != -1) {
int prev = navigation_polys[np_id].back_navigation_edge; if (navigation_polys[np_id].back_navigation_edge != -1) {
int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size(); int prev = navigation_polys[np_id].back_navigation_edge;
Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5; int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size();
path.push_back(point); 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);
} else {
path.push_back(navigation_polys[np_id].entry);
}
np_id = navigation_polys[np_id].back_navigation_poly_id; np_id = navigation_polys[np_id].back_navigation_poly_id;
} }
@ -475,6 +486,19 @@ void NavMap::remove_region(NavRegion *p_region) {
} }
} }
void NavMap::add_link(NavLink *p_link) {
links.push_back(p_link);
regenerate_links = true;
}
void NavMap::remove_link(NavLink *p_link) {
int64_t link_index = links.find(p_link);
if (link_index != -1) {
links.remove_at_unordered(link_index);
regenerate_links = true;
}
}
bool NavMap::has_agent(RvoAgent *agent) const { bool NavMap::has_agent(RvoAgent *agent) const {
return (agents.find(agent) != -1); return (agents.find(agent) != -1);
} }
@ -526,6 +550,12 @@ void NavMap::sync() {
} }
} }
for (uint32_t l = 0; l < links.size(); l++) {
if (links[l]->check_dirty()) {
regenerate_links = true;
}
}
if (regenerate_links) { if (regenerate_links) {
// Remove regions connections. // Remove regions connections.
for (uint32_t r = 0; r < regions.size(); r++) { for (uint32_t r = 0; r < regions.size(); r++) {
@ -651,7 +681,121 @@ void NavMap::sync() {
free_edge.polygon->edges[free_edge.edge].connections.push_back(new_connection); free_edge.polygon->edges[free_edge.edge].connections.push_back(new_connection);
// Add the connection to the region_connection map. // Add the connection to the region_connection map.
free_edge.polygon->owner->get_connections().push_back(new_connection); ((NavRegion *)free_edge.polygon->owner)->get_connections().push_back(new_connection);
}
}
uint32_t link_poly_idx = 0;
link_polygons.resize(links.size());
// Search for polygons within range of a nav link.
for (uint32_t l = 0; l < links.size(); l++) {
const NavLink *link = links[l];
const Vector3 start = link->get_start_location();
const Vector3 end = link->get_end_location();
gd::Polygon *closest_start_polygon = nullptr;
real_t closest_start_distance = link_connection_radius;
Vector3 closest_start_point;
gd::Polygon *closest_end_polygon = nullptr;
real_t closest_end_distance = link_connection_radius;
Vector3 closest_end_point;
// Create link to any polygons within the search radius of the start point.
for (uint32_t start_index = 0; start_index < polygons.size(); start_index++) {
gd::Polygon &start_poly = polygons[start_index];
// For each face check the distance to the start
for (uint32_t start_point_id = 2; start_point_id < start_poly.points.size(); start_point_id += 1) {
const Face3 start_face(start_poly.points[0].pos, start_poly.points[start_point_id - 1].pos, start_poly.points[start_point_id].pos);
const Vector3 start_point = start_face.get_closest_point_to(start);
const real_t start_distance = start_point.distance_to(start);
// Pick the polygon that is within our radius and is closer than anything we've seen yet.
if (start_distance <= link_connection_radius && start_distance < closest_start_distance) {
closest_start_distance = start_distance;
closest_start_point = start_point;
closest_start_polygon = &start_poly;
}
}
}
// Find any polygons within the search radius of the end point.
for (uint32_t end_index = 0; end_index < polygons.size(); end_index++) {
gd::Polygon &end_poly = polygons[end_index];
// For each face check the distance to the end
for (uint32_t end_point_id = 2; end_point_id < end_poly.points.size(); end_point_id += 1) {
const Face3 end_face(end_poly.points[0].pos, end_poly.points[end_point_id - 1].pos, end_poly.points[end_point_id].pos);
const Vector3 end_point = end_face.get_closest_point_to(end);
const real_t end_distance = end_point.distance_to(end);
// Pick the polygon that is within our radius and is closer than anything we've seen yet.
if (end_distance <= link_connection_radius && end_distance < closest_end_distance) {
closest_end_distance = end_distance;
closest_end_point = end_point;
closest_end_polygon = &end_poly;
}
}
}
// If we have both a start and end point, then create a synthetic polygon to route through.
if (closest_start_polygon && closest_end_polygon) {
gd::Polygon &new_polygon = link_polygons[link_poly_idx++];
new_polygon.owner = link;
new_polygon.edges.clear();
new_polygon.edges.resize(4);
new_polygon.points.clear();
new_polygon.points.reserve(4);
// Build a set of vertices that create a thin polygon going from the start to the end point.
new_polygon.points.push_back({ closest_start_point, get_point_key(closest_start_point) });
new_polygon.points.push_back({ closest_start_point, get_point_key(closest_start_point) });
new_polygon.points.push_back({ closest_end_point, get_point_key(closest_end_point) });
new_polygon.points.push_back({ closest_end_point, get_point_key(closest_end_point) });
Vector3 center;
for (int p = 0; p < 4; ++p) {
center += new_polygon.points[p].pos;
}
new_polygon.center = center / real_t(new_polygon.points.size());
new_polygon.clockwise = true;
// Setup connections to go forward in the link.
{
gd::Edge::Connection entry_connection;
entry_connection.polygon = &new_polygon;
entry_connection.edge = -1;
entry_connection.pathway_start = new_polygon.points[0].pos;
entry_connection.pathway_end = new_polygon.points[1].pos;
closest_start_polygon->edges[0].connections.push_back(entry_connection);
gd::Edge::Connection exit_connection;
exit_connection.polygon = closest_end_polygon;
exit_connection.edge = -1;
exit_connection.pathway_start = new_polygon.points[2].pos;
exit_connection.pathway_end = new_polygon.points[3].pos;
new_polygon.edges[2].connections.push_back(exit_connection);
}
// If the link is bi-directional, create connections from the end to the start.
if (link->is_bidirectional()) {
gd::Edge::Connection entry_connection;
entry_connection.polygon = &new_polygon;
entry_connection.edge = -1;
entry_connection.pathway_start = new_polygon.points[2].pos;
entry_connection.pathway_end = new_polygon.points[3].pos;
closest_end_polygon->edges[0].connections.push_back(entry_connection);
gd::Edge::Connection exit_connection;
exit_connection.polygon = closest_start_polygon;
exit_connection.edge = -1;
exit_connection.pathway_start = new_polygon.points[0].pos;
exit_connection.pathway_end = new_polygon.points[1].pos;
new_polygon.edges[0].connections.push_back(exit_connection);
}
} }
} }

View File

@ -40,9 +40,9 @@
#include <KdTree.h> #include <KdTree.h>
class NavLink;
class NavRegion; class NavRegion;
class RvoAgent; class RvoAgent;
class NavRegion;
class NavMap : public NavRid { class NavMap : public NavRid {
/// Map Up /// Map Up
@ -55,11 +55,19 @@ class NavMap : public NavRid {
/// This value is used to detect the near edges to connect. /// This value is used to detect the near edges to connect.
real_t edge_connection_margin = 0.25; real_t edge_connection_margin = 0.25;
/// This value is used to limit how far links search to find polygons to connect to.
real_t link_connection_radius = 1.0;
bool regenerate_polygons = true; bool regenerate_polygons = true;
bool regenerate_links = true; bool regenerate_links = true;
/// Map regions
LocalVector<NavRegion *> regions; LocalVector<NavRegion *> regions;
/// Map links
LocalVector<NavLink *> links;
LocalVector<gd::Polygon> link_polygons;
/// Map polygons /// Map polygons
LocalVector<gd::Polygon> polygons; LocalVector<gd::Polygon> polygons;
@ -100,6 +108,11 @@ public:
return edge_connection_margin; return edge_connection_margin;
} }
void set_link_connection_radius(float p_link_connection_radius);
float get_link_connection_radius() const {
return link_connection_radius;
}
gd::PointKey get_point_key(const Vector3 &p_pos) const; 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 = 1) const;
@ -115,6 +128,12 @@ public:
return regions; return regions;
} }
void add_link(NavLink *p_link);
void remove_link(NavLink *p_link);
const LocalVector<NavLink *> &get_links() const {
return links;
}
bool has_agent(RvoAgent *agent) const; bool has_agent(RvoAgent *agent) const;
void add_agent(RvoAgent *agent); void add_agent(RvoAgent *agent);
void remove_agent(RvoAgent *agent); void remove_agent(RvoAgent *agent);

View File

@ -40,14 +40,6 @@ void NavRegion::set_map(NavMap *p_map) {
} }
} }
void NavRegion::set_navigation_layers(uint32_t p_navigation_layers) {
navigation_layers = p_navigation_layers;
}
uint32_t NavRegion::get_navigation_layers() const {
return navigation_layers;
}
void NavRegion::set_transform(Transform3D p_transform) { void NavRegion::set_transform(Transform3D p_transform) {
transform = p_transform; transform = p_transform;
polygons_dirty = true; polygons_dirty = true;

View File

@ -33,21 +33,13 @@
#include "scene/resources/navigation_mesh.h" #include "scene/resources/navigation_mesh.h"
#include "nav_rid.h" #include "nav_base.h"
#include "nav_utils.h" #include "nav_utils.h"
#include <vector> class NavRegion : public NavBase {
class NavMap;
class NavRegion;
class NavRegion : public NavRid {
NavMap *map = nullptr; NavMap *map = nullptr;
Transform3D transform; Transform3D transform;
Ref<NavigationMesh> mesh; Ref<NavigationMesh> mesh;
uint32_t navigation_layers = 1;
float enter_cost = 0.0;
float travel_cost = 1.0;
Vector<gd::Edge::Connection> connections; Vector<gd::Edge::Connection> connections;
bool polygons_dirty = true; bool polygons_dirty = true;
@ -67,15 +59,6 @@ public:
return map; return map;
} }
void set_enter_cost(float p_enter_cost) { enter_cost = MAX(p_enter_cost, 0.0); }
float get_enter_cost() const { return enter_cost; }
void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
float get_travel_cost() const { return travel_cost; }
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
void set_transform(Transform3D transform); void set_transform(Transform3D transform);
const Transform3D &get_transform() const { const Transform3D &get_transform() const {
return transform; return transform;

View File

@ -35,9 +35,8 @@
#include "core/templates/hash_map.h" #include "core/templates/hash_map.h"
#include "core/templates/hashfuncs.h" #include "core/templates/hashfuncs.h"
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"
#include <vector>
class NavRegion; class NavBase;
namespace gd { namespace gd {
struct Polygon; struct Polygon;
@ -79,26 +78,33 @@ struct Point {
}; };
struct Edge { struct Edge {
/// This edge ID
int this_edge = -1;
/// The gateway in the edge, as, in some case, the whole edge might not be navigable. /// The gateway in the edge, as, in some case, the whole edge might not be navigable.
struct Connection { struct Connection {
/// Polygon that this connection leads to.
Polygon *polygon = nullptr; Polygon *polygon = nullptr;
/// Edge of the source polygon where this connection starts from.
int edge = -1; int edge = -1;
/// Point on the edge where the gateway leading to the poly starts.
Vector3 pathway_start; Vector3 pathway_start;
/// Point on the edge where the gateway leading to the poly ends.
Vector3 pathway_end; Vector3 pathway_end;
}; };
/// Connections from this edge to other polygons.
Vector<Connection> connections; Vector<Connection> connections;
}; };
struct Polygon { struct Polygon {
NavRegion *owner = nullptr; /// Navigation region or link that contains this polygon.
const NavBase *owner = nullptr;
/// The points of this `Polygon` /// The points of this `Polygon`
LocalVector<Point> points; LocalVector<Point> points;
/// Are the points clockwise ? /// Are the points clockwise?
bool clockwise; bool clockwise;
/// The edges of this `Polygon` /// The edges of this `Polygon`
@ -115,7 +121,7 @@ struct NavigationPoly {
/// Those 4 variables are used to travel the path backwards. /// Those 4 variables are used to travel the path backwards.
int back_navigation_poly_id = -1; int back_navigation_poly_id = -1;
uint32_t back_navigation_edge = UINT32_MAX; int back_navigation_edge = -1;
Vector3 back_navigation_edge_pathway_start; Vector3 back_navigation_edge_pathway_start;
Vector3 back_navigation_edge_pathway_end; Vector3 back_navigation_edge_pathway_end;

View File

@ -0,0 +1,284 @@
/*************************************************************************/
/* navigation_link_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "navigation_link_2d.h"
#include "core/math/geometry_2d.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"
void NavigationLink2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);
ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional);
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink2D::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink2D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink2D::set_navigation_layer_value);
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink2D::get_navigation_layer_value);
ClassDB::bind_method(D_METHOD("set_start_location", "location"), &NavigationLink2D::set_start_location);
ClassDB::bind_method(D_METHOD("get_start_location"), &NavigationLink2D::get_start_location);
ClassDB::bind_method(D_METHOD("set_end_location", "location"), &NavigationLink2D::set_end_location);
ClassDB::bind_method(D_METHOD("get_end_location"), &NavigationLink2D::get_end_location);
ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost);
ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost);
ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink2D::set_travel_cost);
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink2D::get_travel_cost);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_location"), "set_start_location", "get_start_location");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "end_location"), "set_end_location", "get_end_location");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}
void NavigationLink2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled) {
NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
// Update global positions for the link.
Transform2D gt = get_global_transform();
NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
}
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
// Update global positions for the link.
Transform2D gt = get_global_transform();
NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
} break;
case NOTIFICATION_EXIT_TREE: {
NavigationServer2D::get_singleton()->link_set_map(link, RID());
} break;
case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) {
Color color;
if (enabled) {
color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
} else {
color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
}
real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());
draw_line(get_start_location(), get_end_location(), color);
draw_arc(get_start_location(), radius, 0, Math_TAU, 10, color);
draw_arc(get_end_location(), radius, 0, Math_TAU, 10, color);
}
#endif // DEBUG_ENABLED
} break;
}
}
#ifdef TOOLS_ENABLED
Rect2 NavigationLink2D::_edit_get_rect() const {
real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());
Rect2 rect(get_start_location(), Size2());
rect.expand_to(get_end_location());
rect.grow_by(radius);
return rect;
}
bool NavigationLink2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
Point2 segment[2] = { get_start_location(), get_end_location() };
Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, segment);
return p_point.distance_to(closest_point) < p_tolerance;
}
#endif // TOOLS_ENABLED
void NavigationLink2D::set_enabled(bool p_enabled) {
if (enabled == p_enabled) {
return;
}
enabled = p_enabled;
if (!is_inside_tree()) {
return;
}
if (!enabled) {
NavigationServer2D::get_singleton()->link_set_map(link, RID());
} else {
NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
}
#ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
update();
}
#endif // DEBUG_ENABLED
}
void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) {
return;
}
bidirectional = p_bidirectional;
NavigationServer2D::get_singleton()->link_set_bidirectional(link, bidirectional);
}
void NavigationLink2D::set_navigation_layers(uint32_t p_navigation_layers) {
if (navigation_layers == p_navigation_layers) {
return;
}
navigation_layers = p_navigation_layers;
NavigationServer2D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
}
void NavigationLink2D::set_navigation_layer_value(int p_layer_number, bool p_value) {
ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
uint32_t _navigation_layers = get_navigation_layers();
if (p_value) {
_navigation_layers |= 1 << (p_layer_number - 1);
} else {
_navigation_layers &= ~(1 << (p_layer_number - 1));
}
set_navigation_layers(_navigation_layers);
}
bool NavigationLink2D::get_navigation_layer_value(int p_layer_number) const {
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
return get_navigation_layers() & (1 << (p_layer_number - 1));
}
void NavigationLink2D::set_start_location(Vector2 p_location) {
if (start_location.is_equal_approx(p_location)) {
return;
}
start_location = p_location;
if (!is_inside_tree()) {
return;
}
Transform2D gt = get_global_transform();
NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
update_configuration_warnings();
#ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
update();
}
#endif // DEBUG_ENABLED
}
void NavigationLink2D::set_end_location(Vector2 p_location) {
if (end_location.is_equal_approx(p_location)) {
return;
}
end_location = p_location;
if (!is_inside_tree()) {
return;
}
Transform2D gt = get_global_transform();
NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
update_configuration_warnings();
#ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
update();
}
#endif // DEBUG_ENABLED
}
void NavigationLink2D::set_enter_cost(real_t p_enter_cost) {
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
return;
}
enter_cost = p_enter_cost;
NavigationServer2D::get_singleton()->link_set_enter_cost(link, enter_cost);
}
void NavigationLink2D::set_travel_cost(real_t p_travel_cost) {
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
return;
}
travel_cost = p_travel_cost;
NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost);
}
TypedArray<String> NavigationLink2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (start_location.is_equal_approx(end_location)) {
warnings.push_back(RTR("NavigationLink2D start location should be different than the end location to be useful."));
}
return warnings;
}
NavigationLink2D::NavigationLink2D() {
link = NavigationServer2D::get_singleton()->link_create();
set_notify_transform(true);
}
NavigationLink2D::~NavigationLink2D() {
NavigationServer2D::get_singleton()->free(link);
link = RID();
}

View File

@ -0,0 +1,88 @@
/*************************************************************************/
/* navigation_link_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef NAVIGATION_LINK_2D_H
#define NAVIGATION_LINK_2D_H
#include "scene/2d/node_2d.h"
class NavigationLink2D : public Node2D {
GDCLASS(NavigationLink2D, Node2D);
bool enabled = true;
RID link = RID();
bool bidirectional = true;
uint32_t navigation_layers = 1;
Vector2 end_location = Vector2();
Vector2 start_location = Vector2();
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
protected:
static void _bind_methods();
void _notification(int p_what);
public:
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const override;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override;
#endif
void set_enabled(bool p_enabled);
bool is_enabled() const { return enabled; }
void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; }
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const { return navigation_layers; }
void set_navigation_layer_value(int p_layer_number, bool p_value);
bool get_navigation_layer_value(int p_layer_number) const;
void set_start_location(Vector2 p_location);
Vector2 get_start_location() const { return start_location; }
void set_end_location(Vector2 p_location);
Vector2 get_end_location() const { return end_location; }
void set_enter_cost(real_t p_enter_cost);
real_t get_enter_cost() const { return enter_cost; }
void set_travel_cost(real_t p_travel_cost);
real_t get_travel_cost() const { return travel_cost; }
TypedArray<String> get_configuration_warnings() const override;
NavigationLink2D();
~NavigationLink2D();
};
#endif // NAVIGATION_LINK_2D_H

View File

@ -0,0 +1,389 @@
/*************************************************************************/
/* navigation_link_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "navigation_link_3d.h"
#include "mesh_instance_3d.h"
#include "servers/navigation_server_3d.h"
#ifdef DEBUG_ENABLED
void NavigationLink3D::_update_debug_mesh() {
if (!is_inside_tree()) {
return;
}
if (Engine::get_singleton()->is_editor_hint()) {
// don't update inside Editor as node 3d gizmo takes care of this
// as collisions and selections for Editor Viewport need to be updated
return;
}
if (!NavigationServer3D::get_singleton()->get_debug_enabled()) {
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_instance, false);
}
return;
}
if (!debug_instance.is_valid()) {
debug_instance = RenderingServer::get_singleton()->instance_create();
}
if (!debug_mesh.is_valid()) {
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
}
RID nav_map = get_world_3d()->get_navigation_map();
real_t search_radius = NavigationServer3D::get_singleton()->map_get_link_connection_radius(nav_map);
Vector3 up_vector = NavigationServer3D::get_singleton()->map_get_up(nav_map);
Vector3::Axis up_axis = up_vector.max_axis_index();
debug_mesh->clear_surfaces();
Vector<Vector3> lines;
// Draw line between the points.
lines.push_back(start_location);
lines.push_back(end_location);
// Draw start location search radius
for (int i = 0; i < 30; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 12));
const float rb = Math::deg_to_rad((float)((i + 1) * 12));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
// Draw axis-aligned circle
switch (up_axis) {
case Vector3::AXIS_X:
lines.append(start_location + Vector3(0, a.x, a.y));
lines.append(start_location + Vector3(0, b.x, b.y));
break;
case Vector3::AXIS_Y:
lines.append(start_location + Vector3(a.x, 0, a.y));
lines.append(start_location + Vector3(b.x, 0, b.y));
break;
case Vector3::AXIS_Z:
lines.append(start_location + Vector3(a.x, a.y, 0));
lines.append(start_location + Vector3(b.x, b.y, 0));
break;
}
}
// Draw end location search radius
for (int i = 0; i < 30; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 12));
const float rb = Math::deg_to_rad((float)((i + 1) * 12));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
// Draw axis-aligned circle
switch (up_axis) {
case Vector3::AXIS_X:
lines.append(end_location + Vector3(0, a.x, a.y));
lines.append(end_location + Vector3(0, b.x, b.y));
break;
case Vector3::AXIS_Y:
lines.append(end_location + Vector3(a.x, 0, a.y));
lines.append(end_location + Vector3(b.x, 0, b.y));
break;
case Vector3::AXIS_Z:
lines.append(end_location + Vector3(a.x, a.y, 0));
lines.append(end_location + Vector3(b.x, b.y, 0));
break;
}
}
Array mesh_array;
mesh_array.resize(Mesh::ARRAY_MAX);
mesh_array[Mesh::ARRAY_VERTEX] = lines;
debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_array);
RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
Ref<StandardMaterial3D> link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_material();
Ref<StandardMaterial3D> disabled_link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_disabled_material();
if (enabled) {
RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, link_material->get_rid());
} else {
RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, disabled_link_material->get_rid());
}
}
#endif // DEBUG_ENABLED
void NavigationLink3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled);
ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink3D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink3D::is_bidirectional);
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink3D::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink3D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink3D::set_navigation_layer_value);
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink3D::get_navigation_layer_value);
ClassDB::bind_method(D_METHOD("set_start_location", "location"), &NavigationLink3D::set_start_location);
ClassDB::bind_method(D_METHOD("get_start_location"), &NavigationLink3D::get_start_location);
ClassDB::bind_method(D_METHOD("set_end_location", "location"), &NavigationLink3D::set_end_location);
ClassDB::bind_method(D_METHOD("get_end_location"), &NavigationLink3D::get_end_location);
ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink3D::set_enter_cost);
ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink3D::get_enter_cost);
ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink3D::set_travel_cost);
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink3D::get_travel_cost);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_location"), "set_start_location", "get_start_location");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "end_location"), "set_end_location", "get_end_location");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}
void NavigationLink3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled) {
NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
// Update global positions for the link.
Transform3D gt = get_global_transform();
NavigationServer3D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
NavigationServer3D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
}
#ifdef DEBUG_ENABLED
_update_debug_mesh();
#endif // DEBUG_ENABLED
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
// Update global positions for the link.
Transform3D gt = get_global_transform();
NavigationServer3D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
NavigationServer3D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
#ifdef DEBUG_ENABLED
if (is_inside_tree() && debug_instance.is_valid()) {
RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
}
#endif // DEBUG_ENABLED
} break;
case NOTIFICATION_EXIT_TREE: {
NavigationServer3D::get_singleton()->link_set_map(link, RID());
#ifdef DEBUG_ENABLED
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_scenario(debug_instance, RID());
RS::get_singleton()->instance_set_visible(debug_instance, false);
}
#endif // DEBUG_ENABLED
} break;
}
}
NavigationLink3D::NavigationLink3D() {
link = NavigationServer3D::get_singleton()->link_create();
set_notify_transform(true);
}
NavigationLink3D::~NavigationLink3D() {
NavigationServer3D::get_singleton()->free(link);
link = RID();
#ifdef DEBUG_ENABLED
if (debug_instance.is_valid()) {
RenderingServer::get_singleton()->free(debug_instance);
}
if (debug_mesh.is_valid()) {
RenderingServer::get_singleton()->free(debug_mesh->get_rid());
}
#endif // DEBUG_ENABLED
}
void NavigationLink3D::set_enabled(bool p_enabled) {
if (enabled == p_enabled) {
return;
}
enabled = p_enabled;
if (!is_inside_tree()) {
return;
}
if (enabled) {
NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
} else {
NavigationServer3D::get_singleton()->link_set_map(link, RID());
}
#ifdef DEBUG_ENABLED
if (debug_instance.is_valid() && debug_mesh.is_valid()) {
if (enabled) {
Ref<StandardMaterial3D> link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_material();
RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, link_material->get_rid());
} else {
Ref<StandardMaterial3D> disabled_link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_disabled_material();
RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, disabled_link_material->get_rid());
}
}
#endif // DEBUG_ENABLED
update_gizmos();
}
void NavigationLink3D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) {
return;
}
bidirectional = p_bidirectional;
NavigationServer3D::get_singleton()->link_set_bidirectional(link, bidirectional);
}
void NavigationLink3D::set_navigation_layers(uint32_t p_navigation_layers) {
if (navigation_layers == p_navigation_layers) {
return;
}
navigation_layers = p_navigation_layers;
NavigationServer3D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
}
void NavigationLink3D::set_navigation_layer_value(int p_layer_number, bool p_value) {
ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
uint32_t _navigation_layers = get_navigation_layers();
if (p_value) {
_navigation_layers |= 1 << (p_layer_number - 1);
} else {
_navigation_layers &= ~(1 << (p_layer_number - 1));
}
set_navigation_layers(_navigation_layers);
}
bool NavigationLink3D::get_navigation_layer_value(int p_layer_number) const {
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
return get_navigation_layers() & (1 << (p_layer_number - 1));
}
void NavigationLink3D::set_start_location(Vector3 p_location) {
if (start_location.is_equal_approx(p_location)) {
return;
}
start_location = p_location;
if (!is_inside_tree()) {
return;
}
Transform3D gt = get_global_transform();
NavigationServer3D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
#ifdef DEBUG_ENABLED
_update_debug_mesh();
#endif // DEBUG_ENABLED
update_gizmos();
update_configuration_warnings();
}
void NavigationLink3D::set_end_location(Vector3 p_location) {
if (end_location.is_equal_approx(p_location)) {
return;
}
end_location = p_location;
if (!is_inside_tree()) {
return;
}
Transform3D gt = get_global_transform();
NavigationServer3D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
#ifdef DEBUG_ENABLED
_update_debug_mesh();
#endif // DEBUG_ENABLED
update_gizmos();
update_configuration_warnings();
}
void NavigationLink3D::set_enter_cost(real_t p_enter_cost) {
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
return;
}
enter_cost = p_enter_cost;
NavigationServer3D::get_singleton()->link_set_enter_cost(link, enter_cost);
}
void NavigationLink3D::set_travel_cost(real_t p_travel_cost) {
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
return;
}
travel_cost = p_travel_cost;
NavigationServer3D::get_singleton()->link_set_travel_cost(link, travel_cost);
}
TypedArray<String> NavigationLink3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (start_location.is_equal_approx(end_location)) {
warnings.push_back(RTR("NavigationLink3D start location should be different than the end location to be useful."));
}
return warnings;
}

View File

@ -0,0 +1,90 @@
/*************************************************************************/
/* navigation_link_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef NAVIGATION_LINK_3D_H
#define NAVIGATION_LINK_3D_H
#include "scene/3d/node_3d.h"
class NavigationLink3D : public Node3D {
GDCLASS(NavigationLink3D, Node3D);
bool enabled = true;
RID link = RID();
bool bidirectional = true;
uint32_t navigation_layers = 1;
Vector3 end_location = Vector3();
Vector3 start_location = Vector3();
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
#ifdef DEBUG_ENABLED
RID debug_instance;
Ref<ArrayMesh> debug_mesh;
void _update_debug_mesh();
#endif // DEBUG_ENABLED
protected:
static void _bind_methods();
void _notification(int p_what);
public:
NavigationLink3D();
~NavigationLink3D();
void set_enabled(bool p_enabled);
bool is_enabled() const { return enabled; }
void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; }
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const { return navigation_layers; }
void set_navigation_layer_value(int p_layer_number, bool p_value);
bool get_navigation_layer_value(int p_layer_number) const;
void set_start_location(Vector3 p_location);
Vector3 get_start_location() const { return start_location; }
void set_end_location(Vector3 p_location);
Vector3 get_end_location() const { return end_location; }
void set_enter_cost(real_t p_enter_cost);
real_t get_enter_cost() const { return enter_cost; }
void set_travel_cost(real_t p_travel_cost);
real_t get_travel_cost() const { return travel_cost; }
TypedArray<String> get_configuration_warnings() const override;
};
#endif // NAVIGATION_LINK_3D_H

View File

@ -54,6 +54,7 @@
#include "scene/2d/mesh_instance_2d.h" #include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/multimesh_instance_2d.h" #include "scene/2d/multimesh_instance_2d.h"
#include "scene/2d/navigation_agent_2d.h" #include "scene/2d/navigation_agent_2d.h"
#include "scene/2d/navigation_link_2d.h"
#include "scene/2d/navigation_obstacle_2d.h" #include "scene/2d/navigation_obstacle_2d.h"
#include "scene/2d/parallax_background.h" #include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h" #include "scene/2d/parallax_layer.h"
@ -236,6 +237,7 @@
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h" #include "scene/3d/multimesh_instance_3d.h"
#include "scene/3d/navigation_agent_3d.h" #include "scene/3d/navigation_agent_3d.h"
#include "scene/3d/navigation_link_3d.h"
#include "scene/3d/navigation_obstacle_3d.h" #include "scene/3d/navigation_obstacle_3d.h"
#include "scene/3d/navigation_region_3d.h" #include "scene/3d/navigation_region_3d.h"
#include "scene/3d/node_3d.h" #include "scene/3d/node_3d.h"
@ -573,6 +575,7 @@ void register_scene_types() {
GDREGISTER_CLASS(NavigationRegion3D); GDREGISTER_CLASS(NavigationRegion3D);
GDREGISTER_CLASS(NavigationAgent3D); GDREGISTER_CLASS(NavigationAgent3D);
GDREGISTER_CLASS(NavigationObstacle3D); GDREGISTER_CLASS(NavigationObstacle3D);
GDREGISTER_CLASS(NavigationLink3D);
OS::get_singleton()->yield(); // may take time to init OS::get_singleton()->yield(); // may take time to init
#endif // _3D_DISABLED #endif // _3D_DISABLED
@ -922,6 +925,7 @@ void register_scene_types() {
GDREGISTER_CLASS(NavigationRegion2D); GDREGISTER_CLASS(NavigationRegion2D);
GDREGISTER_CLASS(NavigationAgent2D); GDREGISTER_CLASS(NavigationAgent2D);
GDREGISTER_CLASS(NavigationObstacle2D); GDREGISTER_CLASS(NavigationObstacle2D);
GDREGISTER_CLASS(NavigationLink2D);
OS::get_singleton()->yield(); // may take time to init OS::get_singleton()->yield(); // may take time to init

View File

@ -85,6 +85,7 @@ World2D::World2D() {
NavigationServer2D::get_singleton()->map_set_active(navigation_map, true); NavigationServer2D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 1)); NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 1));
NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 1)); NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 1));
NavigationServer2D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_DEF("navigation/2d/default_link_connection_radius", 4));
} }
World2D::~World2D() { World2D::~World2D() {

View File

@ -151,6 +151,7 @@ World3D::World3D() {
NavigationServer3D::get_singleton()->map_set_active(navigation_map, true); NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.25)); NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.25));
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 0.25)); NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 0.25));
NavigationServer3D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_DEF("navigation/3d/default_link_connection_radius", 1.0));
} }
World3D::~World3D() { World3D::~World3D() {

View File

@ -53,6 +53,12 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr;
return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0)); \ return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0)); \
} }
#define FORWARD_1_R_C(CONV_R, FUNC_NAME, T_0, D_0, CONV_0) \
NavigationServer2D::FUNC_NAME(T_0 D_0) \
const { \
return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0))); \
}
#define FORWARD_2_C(FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \ #define FORWARD_2_C(FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \
NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \ NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \
const { \ const { \
@ -190,6 +196,22 @@ Color NavigationServer2D::get_debug_navigation_geometry_face_disabled_color() co
return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color(); return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color();
} }
void NavigationServer2D::set_debug_navigation_link_connection_color(const Color &p_color) {
NavigationServer3D::get_singleton_mut()->set_debug_navigation_link_connection_color(p_color);
}
Color NavigationServer2D::get_debug_navigation_link_connection_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_color();
}
void NavigationServer2D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) {
NavigationServer3D::get_singleton_mut()->set_debug_navigation_link_connection_disabled_color(p_color);
}
Color NavigationServer2D::get_debug_navigation_link_connection_disabled_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
}
void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) { void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) {
NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(p_value); NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(p_value);
} }
@ -209,10 +231,13 @@ 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_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_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_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer2D::map_set_link_connection_radius);
ClassDB::bind_method(D_METHOD("map_get_link_connection_radius", "map"), &NavigationServer2D::map_get_link_connection_radius);
ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer2D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_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", "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("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner);
ClassDB::bind_method(D_METHOD("map_get_links", "map"), &NavigationServer2D::map_get_links);
ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions); ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions);
ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents); ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents);
@ -234,6 +259,22 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end);
ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer2D::link_create);
ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer2D::link_set_map);
ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer2D::link_get_map);
ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer2D::link_set_bidirectional);
ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer2D::link_is_bidirectional);
ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer2D::link_set_navigation_layers);
ClassDB::bind_method(D_METHOD("link_get_navigation_layers", "link"), &NavigationServer2D::link_get_navigation_layers);
ClassDB::bind_method(D_METHOD("link_set_start_location", "link", "location"), &NavigationServer2D::link_set_start_location);
ClassDB::bind_method(D_METHOD("link_get_start_location", "link"), &NavigationServer2D::link_get_start_location);
ClassDB::bind_method(D_METHOD("link_set_end_location", "link", "location"), &NavigationServer2D::link_set_end_location);
ClassDB::bind_method(D_METHOD("link_get_end_location", "link"), &NavigationServer2D::link_get_end_location);
ClassDB::bind_method(D_METHOD("link_set_enter_cost", "link", "enter_cost"), &NavigationServer2D::link_set_enter_cost);
ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer2D::link_get_enter_cost);
ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer2D::link_set_travel_cost);
ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer2D::link_get_travel_cost);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map);
@ -265,6 +306,8 @@ NavigationServer2D::~NavigationServer2D() {
TypedArray<RID> FORWARD_0_C(get_maps); TypedArray<RID> FORWARD_0_C(get_maps);
TypedArray<RID> FORWARD_1_C(map_get_links, RID, p_map, rid_to_rid);
TypedArray<RID> FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid); TypedArray<RID> FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid);
TypedArray<RID> FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid); TypedArray<RID> FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid);
@ -289,6 +332,9 @@ 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); 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); real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid);
void FORWARD_2_C(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_link_connection_radius, RID, p_map, rid_to_rid);
Vector<Vector2> 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); Vector<Vector2> 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); 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);
@ -315,6 +361,23 @@ int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int); Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int); Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
RID FORWARD_0_C(link_create);
void FORWARD_2_C(link_set_map, RID, p_link, RID, p_map, rid_to_rid, rid_to_rid);
RID FORWARD_1_C(link_get_map, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_bidirectional, RID, p_link, bool, p_bidirectional, rid_to_rid, bool_to_bool);
bool FORWARD_1_C(link_is_bidirectional, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
uint32_t FORWARD_1_C(link_get_navigation_layers, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_start_location, RID, p_link, Vector2, p_location, rid_to_rid, v2_to_v3);
Vector2 FORWARD_1_R_C(v3_to_v2, link_get_start_location, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_end_location, RID, p_link, Vector2, p_location, rid_to_rid, v2_to_v3);
Vector2 FORWARD_1_R_C(v3_to_v2, link_get_end_location, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_enter_cost, RID, p_link, real_t, p_enter_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(link_get_enter_cost, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_travel_cost, RID, p_link, real_t, p_travel_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(link_get_travel_cost, RID, p_link, rid_to_rid);
RID NavigationServer2D::agent_create() const { RID NavigationServer2D::agent_create() const {
RID agent = NavigationServer3D::get_singleton()->agent_create(); RID agent = NavigationServer3D::get_singleton()->agent_create();
NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true); NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true);

View File

@ -76,12 +76,19 @@ public:
/// Returns the edge connection margin of this map. /// Returns the edge connection margin of this map.
virtual real_t map_get_edge_connection_margin(RID p_map) const; virtual real_t map_get_edge_connection_margin(RID p_map) const;
/// Set the map link connection radius used to attach links to the nav mesh.
virtual void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) const;
/// Returns the link connection radius of this map.
virtual real_t map_get_link_connection_radius(RID p_map) const;
/// Returns the navigation path to reach the destination from the origin. /// Returns the navigation path to reach the destination from the origin.
virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const; virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) 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; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
virtual TypedArray<RID> map_get_links(RID p_map) const;
virtual TypedArray<RID> map_get_regions(RID p_map) const; virtual TypedArray<RID> map_get_regions(RID p_map) const;
virtual TypedArray<RID> map_get_agents(RID p_map) const; virtual TypedArray<RID> map_get_agents(RID p_map) const;
@ -119,6 +126,37 @@ public:
virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const; virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const; virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
/// Creates a new link between locations in the nav map.
virtual RID link_create() const;
/// Set the map of this link.
virtual void link_set_map(RID p_link, RID p_map) const;
virtual RID link_get_map(RID p_link) const;
/// Set whether this link travels in both directions.
virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) const;
virtual bool link_is_bidirectional(RID p_link) const;
/// Set the link's layers.
virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) const;
virtual uint32_t link_get_navigation_layers(RID p_link) const;
/// Set the start location of the link.
virtual void link_set_start_location(RID p_link, Vector2 p_location) const;
virtual Vector2 link_get_start_location(RID p_link) const;
/// Set the end location of the link.
virtual void link_set_end_location(RID p_link, Vector2 p_location) const;
virtual Vector2 link_get_end_location(RID p_link) const;
/// Set the enter cost of the link.
virtual void link_set_enter_cost(RID p_link, real_t p_enter_cost) const;
virtual real_t link_get_enter_cost(RID p_link) const;
/// Set the travel cost of the link.
virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const;
virtual real_t link_get_travel_cost(RID p_link) const;
/// Creates the agent. /// Creates the agent.
virtual RID agent_create() const; virtual RID agent_create() const;
@ -198,6 +236,12 @@ public:
void set_debug_navigation_geometry_face_disabled_color(const Color &p_color); void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
Color get_debug_navigation_geometry_face_disabled_color() const; Color get_debug_navigation_geometry_face_disabled_color() const;
void set_debug_navigation_link_connection_color(const Color &p_color);
Color get_debug_navigation_link_connection_color() const;
void set_debug_navigation_link_connection_disabled_color(const Color &p_color);
Color get_debug_navigation_link_connection_disabled_color() const;
void set_debug_navigation_enable_edge_connections(const bool p_value); void set_debug_navigation_enable_edge_connections(const bool p_value);
bool get_debug_navigation_enable_edge_connections() const; bool get_debug_navigation_enable_edge_connections() const;
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED

View File

@ -48,12 +48,15 @@ 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_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_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_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer3D::map_set_link_connection_radius);
ClassDB::bind_method(D_METHOD("map_get_link_connection_radius", "map"), &NavigationServer3D::map_get_link_connection_radius);
ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer3D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_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_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", "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); ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner);
ClassDB::bind_method(D_METHOD("map_get_links", "map"), &NavigationServer3D::map_get_links);
ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions); ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions);
ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents); ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents);
@ -76,6 +79,22 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end);
ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer3D::link_create);
ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer3D::link_set_map);
ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer3D::link_get_map);
ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer3D::link_set_bidirectional);
ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer3D::link_is_bidirectional);
ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer3D::link_set_navigation_layers);
ClassDB::bind_method(D_METHOD("link_get_navigation_layers", "link"), &NavigationServer3D::link_get_navigation_layers);
ClassDB::bind_method(D_METHOD("link_set_start_location", "link", "location"), &NavigationServer3D::link_set_start_location);
ClassDB::bind_method(D_METHOD("link_get_start_location", "link"), &NavigationServer3D::link_get_start_location);
ClassDB::bind_method(D_METHOD("link_set_end_location", "link", "location"), &NavigationServer3D::link_set_end_location);
ClassDB::bind_method(D_METHOD("link_get_end_location", "link"), &NavigationServer3D::link_get_end_location);
ClassDB::bind_method(D_METHOD("link_set_enter_cost", "link", "enter_cost"), &NavigationServer3D::link_set_enter_cost);
ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer3D::link_get_enter_cost);
ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer3D::link_set_travel_cost);
ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer3D::link_get_travel_cost);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map);
@ -118,11 +137,16 @@ NavigationServer3D::NavigationServer3D() {
debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4)); debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4));
debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0)); debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4)); debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4));
debug_navigation_link_connection_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_color", Color(1.0, 0.5, 1.0, 1.0));
debug_navigation_link_connection_disabled_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true); debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true);
debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true); debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true);
debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true); debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true);
debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true); debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true);
debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true); debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true);
debug_navigation_enable_link_connections = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections", true);
debug_navigation_enable_link_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections_xray", true);
if (Engine::get_singleton()->is_editor_hint()) { if (Engine::get_singleton()->is_editor_hint()) {
// enable NavigationServer3D when in Editor or else navmesh edge connections are invisible // enable NavigationServer3D when in Editor or else navmesh edge connections are invisible
@ -261,6 +285,40 @@ Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_edge_connection
return debug_navigation_edge_connections_material; return debug_navigation_edge_connections_material;
} }
Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connections_material() {
if (debug_navigation_link_connections_material.is_valid()) {
return debug_navigation_link_connections_material;
}
Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
material->set_albedo(debug_navigation_link_connection_color);
if (debug_navigation_enable_link_connections_xray) {
material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
}
material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
debug_navigation_link_connections_material = material;
return debug_navigation_link_connections_material;
}
Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connections_disabled_material() {
if (debug_navigation_link_connections_disabled_material.is_valid()) {
return debug_navigation_link_connections_disabled_material;
}
Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
material->set_albedo(debug_navigation_link_connection_disabled_color);
if (debug_navigation_enable_link_connections_xray) {
material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
}
material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
debug_navigation_link_connections_disabled_material = material;
return debug_navigation_link_connections_disabled_material;
}
void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) { void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) {
debug_navigation_edge_connection_color = p_color; debug_navigation_edge_connection_color = p_color;
if (debug_navigation_edge_connections_material.is_valid()) { if (debug_navigation_edge_connections_material.is_valid()) {
@ -316,6 +374,28 @@ Color NavigationServer3D::get_debug_navigation_geometry_face_disabled_color() co
return debug_navigation_geometry_face_disabled_color; return debug_navigation_geometry_face_disabled_color;
} }
void NavigationServer3D::set_debug_navigation_link_connection_color(const Color &p_color) {
debug_navigation_link_connection_color = p_color;
if (debug_navigation_link_connections_material.is_valid()) {
debug_navigation_link_connections_material->set_albedo(debug_navigation_link_connection_color);
}
}
Color NavigationServer3D::get_debug_navigation_link_connection_color() const {
return debug_navigation_link_connection_color;
}
void NavigationServer3D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) {
debug_navigation_link_connection_disabled_color = p_color;
if (debug_navigation_link_connections_disabled_material.is_valid()) {
debug_navigation_link_connections_disabled_material->set_albedo(debug_navigation_link_connection_disabled_color);
}
}
Color NavigationServer3D::get_debug_navigation_link_connection_disabled_color() const {
return debug_navigation_link_connection_disabled_color;
}
void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) { void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) {
debug_navigation_enable_edge_connections = p_value; debug_navigation_enable_edge_connections = p_value;
debug_dirty = true; debug_dirty = true;
@ -368,6 +448,27 @@ bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color(
return debug_navigation_enable_geometry_face_random_color; return debug_navigation_enable_geometry_face_random_color;
} }
void NavigationServer3D::set_debug_navigation_enable_link_connections(const bool p_value) {
debug_navigation_enable_link_connections = p_value;
debug_dirty = true;
call_deferred("_emit_navigation_debug_changed_signal");
}
bool NavigationServer3D::get_debug_navigation_enable_link_connections() const {
return debug_navigation_enable_link_connections;
}
void NavigationServer3D::set_debug_navigation_enable_link_connections_xray(const bool p_value) {
debug_navigation_enable_link_connections_xray = p_value;
if (debug_navigation_link_connections_material.is_valid()) {
debug_navigation_link_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_link_connections_xray);
}
}
bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() const {
return debug_navigation_enable_link_connections_xray;
}
void NavigationServer3D::set_debug_enabled(bool p_enabled) { void NavigationServer3D::set_debug_enabled(bool p_enabled) {
if (debug_enabled != p_enabled) { if (debug_enabled != p_enabled) {
debug_dirty = true; debug_dirty = true;

View File

@ -85,6 +85,12 @@ public:
/// Returns the edge connection margin of this map. /// Returns the edge connection margin of this map.
virtual real_t map_get_edge_connection_margin(RID p_map) const = 0; virtual real_t map_get_edge_connection_margin(RID p_map) const = 0;
/// Set the map link connection radius used to attach links to the nav mesh.
virtual void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) const = 0;
/// Returns the link connection radius of this map.
virtual real_t map_get_link_connection_radius(RID p_map) const = 0;
/// Returns the navigation path to reach the destination from the origin. /// Returns the navigation path to reach the destination from the origin.
virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0; virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0;
@ -93,6 +99,7 @@ public:
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0;
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0;
virtual TypedArray<RID> map_get_links(RID p_map) const = 0;
virtual TypedArray<RID> map_get_regions(RID p_map) const = 0; virtual TypedArray<RID> map_get_regions(RID p_map) const = 0;
virtual TypedArray<RID> map_get_agents(RID p_map) const = 0; virtual TypedArray<RID> map_get_agents(RID p_map) const = 0;
@ -133,6 +140,37 @@ public:
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0; virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0; virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0;
/// Creates a new link between locations in the nav map.
virtual RID link_create() const = 0;
/// Set the map of this link.
virtual void link_set_map(RID p_link, RID p_map) const = 0;
virtual RID link_get_map(RID p_link) const = 0;
/// Set whether this link travels in both directions.
virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) const = 0;
virtual bool link_is_bidirectional(RID p_link) const = 0;
/// Set the link's layers.
virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) const = 0;
virtual uint32_t link_get_navigation_layers(RID p_link) const = 0;
/// Set the start location of the link.
virtual void link_set_start_location(RID p_link, Vector3 p_location) const = 0;
virtual Vector3 link_get_start_location(RID p_link) const = 0;
/// Set the end location of the link.
virtual void link_set_end_location(RID p_link, Vector3 p_location) const = 0;
virtual Vector3 link_get_end_location(RID p_link) const = 0;
/// Set the enter cost of the link.
virtual void link_set_enter_cost(RID p_link, real_t p_enter_cost) const = 0;
virtual real_t link_get_enter_cost(RID p_link) const = 0;
/// Set the travel cost of the link.
virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const = 0;
virtual real_t link_get_travel_cost(RID p_link) const = 0;
/// Creates the agent. /// Creates the agent.
virtual RID agent_create() const = 0; virtual RID agent_create() const = 0;
@ -209,29 +247,38 @@ public:
virtual ~NavigationServer3D(); virtual ~NavigationServer3D();
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
private:
bool debug_enabled = false; bool debug_enabled = false;
bool debug_dirty = true; bool debug_dirty = true;
void _emit_navigation_debug_changed_signal(); void _emit_navigation_debug_changed_signal();
void set_debug_enabled(bool p_enabled);
bool get_debug_enabled() const;
Color debug_navigation_edge_connection_color = Color(1.0, 0.0, 1.0, 1.0); Color debug_navigation_edge_connection_color = Color(1.0, 0.0, 1.0, 1.0);
Color debug_navigation_geometry_edge_color = Color(0.5, 1.0, 1.0, 1.0); Color debug_navigation_geometry_edge_color = Color(0.5, 1.0, 1.0, 1.0);
Color debug_navigation_geometry_face_color = Color(0.5, 1.0, 1.0, 0.4); Color debug_navigation_geometry_face_color = Color(0.5, 1.0, 1.0, 0.4);
Color debug_navigation_geometry_edge_disabled_color = Color(0.5, 0.5, 0.5, 1.0); Color debug_navigation_geometry_edge_disabled_color = Color(0.5, 0.5, 0.5, 1.0);
Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4); Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4);
Color debug_navigation_link_connection_color = Color(1.0, 0.5, 1.0, 1.0);
Color debug_navigation_link_connection_disabled_color = Color(0.5, 0.5, 0.5, 1.0);
bool debug_navigation_enable_edge_connections = true; bool debug_navigation_enable_edge_connections = true;
bool debug_navigation_enable_edge_connections_xray = true; bool debug_navigation_enable_edge_connections_xray = true;
bool debug_navigation_enable_edge_lines = true; bool debug_navigation_enable_edge_lines = true;
bool debug_navigation_enable_edge_lines_xray = true; bool debug_navigation_enable_edge_lines_xray = true;
bool debug_navigation_enable_geometry_face_random_color = true; bool debug_navigation_enable_geometry_face_random_color = true;
bool debug_navigation_enable_link_connections = true;
bool debug_navigation_enable_link_connections_xray = true;
Ref<StandardMaterial3D> debug_navigation_geometry_edge_material; Ref<StandardMaterial3D> debug_navigation_geometry_edge_material;
Ref<StandardMaterial3D> debug_navigation_geometry_face_material; Ref<StandardMaterial3D> debug_navigation_geometry_face_material;
Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material; Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material;
Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_material; Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_material;
Ref<StandardMaterial3D> debug_navigation_edge_connections_material; Ref<StandardMaterial3D> debug_navigation_edge_connections_material;
Ref<StandardMaterial3D> debug_navigation_link_connections_material;
Ref<StandardMaterial3D> debug_navigation_link_connections_disabled_material;
public:
void set_debug_enabled(bool p_enabled);
bool get_debug_enabled() const;
void set_debug_navigation_edge_connection_color(const Color &p_color); void set_debug_navigation_edge_connection_color(const Color &p_color);
Color get_debug_navigation_edge_connection_color() const; Color get_debug_navigation_edge_connection_color() const;
@ -248,6 +295,12 @@ public:
void set_debug_navigation_geometry_face_disabled_color(const Color &p_color); void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
Color get_debug_navigation_geometry_face_disabled_color() const; Color get_debug_navigation_geometry_face_disabled_color() const;
void set_debug_navigation_link_connection_color(const Color &p_color);
Color get_debug_navigation_link_connection_color() const;
void set_debug_navigation_link_connection_disabled_color(const Color &p_color);
Color get_debug_navigation_link_connection_disabled_color() const;
void set_debug_navigation_enable_edge_connections(const bool p_value); void set_debug_navigation_enable_edge_connections(const bool p_value);
bool get_debug_navigation_enable_edge_connections() const; bool get_debug_navigation_enable_edge_connections() const;
@ -263,11 +316,19 @@ public:
void set_debug_navigation_enable_geometry_face_random_color(const bool p_value); void set_debug_navigation_enable_geometry_face_random_color(const bool p_value);
bool get_debug_navigation_enable_geometry_face_random_color() const; bool get_debug_navigation_enable_geometry_face_random_color() const;
void set_debug_navigation_enable_link_connections(const bool p_value);
bool get_debug_navigation_enable_link_connections() const;
void set_debug_navigation_enable_link_connections_xray(const bool p_value);
bool get_debug_navigation_enable_link_connections_xray() const;
Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material(); Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material();
Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material(); Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material();
Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material(); Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material();
Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_material(); Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_material();
Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material(); Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material();
Ref<StandardMaterial3D> get_debug_navigation_link_connections_material();
Ref<StandardMaterial3D> get_debug_navigation_link_connections_disabled_material();
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
}; };