mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 03:18:37 +08:00
Added node for Navigation links
This commit is contained in:
parent
4808d01b2b
commit
3dd59013f4
55
doc/classes/NavigationLink2D.xml
Normal file
55
doc/classes/NavigationLink2D.xml
Normal 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>
|
55
doc/classes/NavigationLink3D.xml
Normal file
55
doc/classes/NavigationLink3D.xml
Normal 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>
|
@ -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.
|
||||
</description>
|
||||
</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">
|
||||
<return type="RID" />
|
||||
<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.
|
||||
</description>
|
||||
</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">
|
||||
<return type="PackedVector2Array" />
|
||||
<param index="0" name="map" type="RID" />
|
||||
@ -235,6 +360,14 @@
|
||||
Set the map edge connection margin used to weld the compatible region edges.
|
||||
</description>
|
||||
</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">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
|
@ -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.
|
||||
</description>
|
||||
</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">
|
||||
<return type="RID" />
|
||||
<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.
|
||||
</description>
|
||||
</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">
|
||||
<return type="PackedVector3Array" />
|
||||
<param index="0" name="map" type="RID" />
|
||||
@ -260,6 +385,14 @@
|
||||
Set the map edge connection margin used to weld the compatible region edges.
|
||||
</description>
|
||||
</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">
|
||||
<return type="void" />
|
||||
<param index="0" name="map" type="RID" />
|
||||
|
@ -497,6 +497,12 @@
|
||||
<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.
|
||||
</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)">
|
||||
Color of the navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu.
|
||||
</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)">
|
||||
Color to display disabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu.
|
||||
</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)">
|
||||
Color of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu.
|
||||
</member>
|
||||
@ -1439,12 +1451,18 @@
|
||||
<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].
|
||||
</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">
|
||||
Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size].
|
||||
</member>
|
||||
<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].
|
||||
</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">
|
||||
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>
|
||||
|
@ -170,6 +170,7 @@
|
||||
#include "editor/plugins/mesh_instance_3d_editor_plugin.h"
|
||||
#include "editor/plugins/mesh_library_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/node_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(LightOccluder2DEditorPlugin));
|
||||
add_editor_plugin(memnew(Line2DEditorPlugin));
|
||||
add_editor_plugin(memnew(NavigationLink2DEditorPlugin));
|
||||
add_editor_plugin(memnew(NavigationPolygonEditorPlugin));
|
||||
add_editor_plugin(memnew(Path2DEditorPlugin));
|
||||
add_editor_plugin(memnew(Polygon2DEditorPlugin));
|
||||
|
4
editor/icons/NavigationLink2D.svg
Normal file
4
editor/icons/NavigationLink2D.svg
Normal 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 |
4
editor/icons/NavigationLink3D.svg
Normal file
4
editor/icons/NavigationLink3D.svg
Normal 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 |
191
editor/plugins/navigation_link_2d_editor_plugin.cpp
Normal file
191
editor/plugins/navigation_link_2d_editor_plugin.cpp
Normal 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);
|
||||
}
|
83
editor/plugins/navigation_link_2d_editor_plugin.h
Normal file
83
editor/plugins/navigation_link_2d_editor_plugin.h
Normal 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
|
@ -54,6 +54,7 @@
|
||||
#include "scene/3d/lightmap_probe.h"
|
||||
#include "scene/3d/marker_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/occluder_instance_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
|
||||
|
@ -631,6 +631,23 @@ public:
|
||||
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 {
|
||||
public:
|
||||
static Basis look_body(const Transform3D &p_joint_transform, const Transform3D &p_body_transform);
|
||||
|
@ -7520,6 +7520,7 @@ void Node3DEditor::_register_all_gizmos() {
|
||||
add_gizmo_plugin(Ref<CollisionObject3DGizmoPlugin>(memnew(CollisionObject3DGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin)));
|
||||
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<Joint3DGizmoPlugin>(memnew(Joint3DGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<PhysicalBone3DGizmoPlugin>(memnew(PhysicalBone3DGizmoPlugin)));
|
||||
|
@ -210,6 +210,20 @@ real_t GodotNavigationServer::map_get_edge_connection_margin(RID p_map) const {
|
||||
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 {
|
||||
const NavMap *map = map_owner.get_or_null(p_map);
|
||||
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);
|
||||
}
|
||||
|
||||
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> regions_rids;
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
|
||||
MutexLock lock(mut_this->operations_mutex);
|
||||
@ -549,6 +702,13 @@ COMMAND_1(free, RID, p_object) {
|
||||
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
|
||||
LocalVector<RvoAgent *> agents = map->get_agents();
|
||||
for (uint32_t i = 0; i < agents.size(); i++) {
|
||||
@ -572,6 +732,17 @@ COMMAND_1(free, RID, 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)) {
|
||||
RvoAgent *agent = agent_owner.get_or_null(p_object);
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "servers/navigation_server_3d.h"
|
||||
|
||||
#include "nav_link.h"
|
||||
#include "nav_map.h"
|
||||
#include "nav_region.h"
|
||||
#include "rvo_agent.h"
|
||||
@ -71,6 +72,7 @@ class GodotNavigationServer : public NavigationServer3D {
|
||||
|
||||
LocalVector<SetCommand *> commands;
|
||||
|
||||
mutable RID_Owner<NavLink> link_owner;
|
||||
mutable RID_Owner<NavMap> map_owner;
|
||||
mutable RID_Owner<NavRegion> region_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);
|
||||
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 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 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_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_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;
|
||||
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
|
||||
virtual RID agent_get_map(RID p_agent) const override;
|
||||
|
56
modules/navigation/nav_base.h
Normal file
56
modules/navigation/nav_base.h
Normal 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
|
60
modules/navigation/nav_link.cpp
Normal file
60
modules/navigation/nav_link.cpp
Normal 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;
|
||||
}
|
69
modules/navigation/nav_link.h
Normal file
69
modules/navigation/nav_link.h
Normal 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
|
@ -31,6 +31,7 @@
|
||||
#include "nav_map.h"
|
||||
|
||||
#include "core/object/worker_thread_pool.h"
|
||||
#include "nav_link.h"
|
||||
#include "nav_region.h"
|
||||
#include "rvo_agent.h"
|
||||
#include <algorithm>
|
||||
@ -52,6 +53,11 @@ void NavMap::set_edge_connection_margin(float p_edge_connection_margin) {
|
||||
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 {
|
||||
const int x = int(Math::floor(p_pos.x / 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;
|
||||
}
|
||||
|
||||
float region_enter_cost = 0.0;
|
||||
float region_travel_cost = least_cost_poly->poly->owner->get_travel_cost();
|
||||
float poly_enter_cost = 0.0;
|
||||
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())) {
|
||||
region_enter_cost = least_cost_poly->poly->owner->get_enter_cost();
|
||||
if (prev_least_cost_poly != nullptr && (prev_least_cost_poly->poly->owner->get_self() != least_cost_poly->poly->owner->get_self())) {
|
||||
poly_enter_cost = least_cost_poly->poly->owner->get_enter_cost();
|
||||
}
|
||||
prev_least_cost_poly = least_cost_poly;
|
||||
|
||||
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 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));
|
||||
|
||||
@ -360,10 +366,15 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
|
||||
// Add mid points
|
||||
int np_id = least_cost_id;
|
||||
while (np_id != -1 && navigation_polys[np_id].back_navigation_poly_id != -1) {
|
||||
if (navigation_polys[np_id].back_navigation_edge != -1) {
|
||||
int prev = navigation_polys[np_id].back_navigation_edge;
|
||||
int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size();
|
||||
Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5;
|
||||
path.push_back(point);
|
||||
} else {
|
||||
path.push_back(navigation_polys[np_id].entry);
|
||||
}
|
||||
|
||||
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 {
|
||||
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) {
|
||||
// Remove regions connections.
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,9 +40,9 @@
|
||||
|
||||
#include <KdTree.h>
|
||||
|
||||
class NavLink;
|
||||
class NavRegion;
|
||||
class RvoAgent;
|
||||
class NavRegion;
|
||||
|
||||
class NavMap : public NavRid {
|
||||
/// Map Up
|
||||
@ -55,11 +55,19 @@ class NavMap : public NavRid {
|
||||
/// This value is used to detect the near edges to connect.
|
||||
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_links = true;
|
||||
|
||||
/// Map regions
|
||||
LocalVector<NavRegion *> regions;
|
||||
|
||||
/// Map links
|
||||
LocalVector<NavLink *> links;
|
||||
LocalVector<gd::Polygon> link_polygons;
|
||||
|
||||
/// Map polygons
|
||||
LocalVector<gd::Polygon> polygons;
|
||||
|
||||
@ -100,6 +108,11 @@ public:
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
void add_agent(RvoAgent *agent);
|
||||
void remove_agent(RvoAgent *agent);
|
||||
|
@ -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) {
|
||||
transform = p_transform;
|
||||
polygons_dirty = true;
|
||||
|
@ -33,21 +33,13 @@
|
||||
|
||||
#include "scene/resources/navigation_mesh.h"
|
||||
|
||||
#include "nav_rid.h"
|
||||
#include "nav_base.h"
|
||||
#include "nav_utils.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class NavMap;
|
||||
class NavRegion;
|
||||
|
||||
class NavRegion : public NavRid {
|
||||
class NavRegion : public NavBase {
|
||||
NavMap *map = nullptr;
|
||||
Transform3D transform;
|
||||
Ref<NavigationMesh> mesh;
|
||||
uint32_t navigation_layers = 1;
|
||||
float enter_cost = 0.0;
|
||||
float travel_cost = 1.0;
|
||||
Vector<gd::Edge::Connection> connections;
|
||||
|
||||
bool polygons_dirty = true;
|
||||
@ -67,15 +59,6 @@ public:
|
||||
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);
|
||||
const Transform3D &get_transform() const {
|
||||
return transform;
|
||||
|
@ -35,9 +35,8 @@
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/hashfuncs.h"
|
||||
#include "core/templates/local_vector.h"
|
||||
#include <vector>
|
||||
|
||||
class NavRegion;
|
||||
class NavBase;
|
||||
|
||||
namespace gd {
|
||||
struct Polygon;
|
||||
@ -79,26 +78,33 @@ struct Point {
|
||||
};
|
||||
|
||||
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.
|
||||
struct Connection {
|
||||
/// Polygon that this connection leads to.
|
||||
Polygon *polygon = nullptr;
|
||||
|
||||
/// Edge of the source polygon where this connection starts from.
|
||||
int edge = -1;
|
||||
|
||||
/// Point on the edge where the gateway leading to the poly starts.
|
||||
Vector3 pathway_start;
|
||||
|
||||
/// Point on the edge where the gateway leading to the poly ends.
|
||||
Vector3 pathway_end;
|
||||
};
|
||||
|
||||
/// Connections from this edge to other polygons.
|
||||
Vector<Connection> connections;
|
||||
};
|
||||
|
||||
struct Polygon {
|
||||
NavRegion *owner = nullptr;
|
||||
/// Navigation region or link that contains this polygon.
|
||||
const NavBase *owner = nullptr;
|
||||
|
||||
/// The points of this `Polygon`
|
||||
LocalVector<Point> points;
|
||||
|
||||
/// Are the points clockwise ?
|
||||
/// Are the points clockwise?
|
||||
bool clockwise;
|
||||
|
||||
/// The edges of this `Polygon`
|
||||
@ -115,7 +121,7 @@ struct NavigationPoly {
|
||||
|
||||
/// Those 4 variables are used to travel the path backwards.
|
||||
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_end;
|
||||
|
||||
|
284
scene/2d/navigation_link_2d.cpp
Normal file
284
scene/2d/navigation_link_2d.cpp
Normal 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();
|
||||
}
|
88
scene/2d/navigation_link_2d.h
Normal file
88
scene/2d/navigation_link_2d.h
Normal 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
|
389
scene/3d/navigation_link_3d.cpp
Normal file
389
scene/3d/navigation_link_3d.cpp
Normal 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;
|
||||
}
|
90
scene/3d/navigation_link_3d.h
Normal file
90
scene/3d/navigation_link_3d.h
Normal 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
|
@ -54,6 +54,7 @@
|
||||
#include "scene/2d/mesh_instance_2d.h"
|
||||
#include "scene/2d/multimesh_instance_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/parallax_background.h"
|
||||
#include "scene/2d/parallax_layer.h"
|
||||
@ -236,6 +237,7 @@
|
||||
#include "scene/3d/mesh_instance_3d.h"
|
||||
#include "scene/3d/multimesh_instance_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_region_3d.h"
|
||||
#include "scene/3d/node_3d.h"
|
||||
@ -573,6 +575,7 @@ void register_scene_types() {
|
||||
GDREGISTER_CLASS(NavigationRegion3D);
|
||||
GDREGISTER_CLASS(NavigationAgent3D);
|
||||
GDREGISTER_CLASS(NavigationObstacle3D);
|
||||
GDREGISTER_CLASS(NavigationLink3D);
|
||||
|
||||
OS::get_singleton()->yield(); // may take time to init
|
||||
#endif // _3D_DISABLED
|
||||
@ -922,6 +925,7 @@ void register_scene_types() {
|
||||
GDREGISTER_CLASS(NavigationRegion2D);
|
||||
GDREGISTER_CLASS(NavigationAgent2D);
|
||||
GDREGISTER_CLASS(NavigationObstacle2D);
|
||||
GDREGISTER_CLASS(NavigationLink2D);
|
||||
|
||||
OS::get_singleton()->yield(); // may take time to init
|
||||
|
||||
|
@ -85,6 +85,7 @@ World2D::World2D() {
|
||||
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_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() {
|
||||
|
@ -151,6 +151,7 @@ World3D::World3D() {
|
||||
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_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() {
|
||||
|
@ -53,6 +53,12 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr;
|
||||
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) \
|
||||
NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \
|
||||
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();
|
||||
}
|
||||
|
||||
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) {
|
||||
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_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_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_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_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_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_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_set_map", "agent", "map"), &NavigationServer2D::agent_set_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_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_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);
|
||||
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);
|
||||
|
||||
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_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 agent = NavigationServer3D::get_singleton()->agent_create();
|
||||
NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true);
|
||||
|
@ -76,12 +76,19 @@ public:
|
||||
/// Returns the edge connection margin of this map.
|
||||
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.
|
||||
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 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_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_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.
|
||||
virtual RID agent_create() const;
|
||||
|
||||
@ -198,6 +236,12 @@ public:
|
||||
void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
|
||||
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);
|
||||
bool get_debug_navigation_enable_edge_connections() const;
|
||||
#endif // DEBUG_ENABLED
|
||||
|
@ -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_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_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_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point);
|
||||
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
|
||||
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_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_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_set_map", "agent", "map"), &NavigationServer3D::agent_set_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_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_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_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_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_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()) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
debug_navigation_edge_connection_color = p_color;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
debug_navigation_enable_edge_connections = p_value;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (debug_enabled != p_enabled) {
|
||||
debug_dirty = true;
|
||||
|
@ -85,6 +85,12 @@ public:
|
||||
/// Returns the edge connection margin of this map.
|
||||
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.
|
||||
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 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_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_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.
|
||||
virtual RID agent_create() const = 0;
|
||||
|
||||
@ -209,29 +247,38 @@ public:
|
||||
virtual ~NavigationServer3D();
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
private:
|
||||
bool debug_enabled = false;
|
||||
bool debug_dirty = true;
|
||||
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_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_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_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_xray = true;
|
||||
bool debug_navigation_enable_edge_lines = true;
|
||||
bool debug_navigation_enable_edge_lines_xray = 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_face_material;
|
||||
Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material;
|
||||
Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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_edge_material();
|
||||
Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material();
|
||||
Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user